fix color scheme for custom tabs
This commit is contained in:
+5
-6
@@ -216,12 +216,11 @@ class EngineSettingsReplicationService
|
|||||||
settings.globalPrivacyControlEnabled,
|
settings.globalPrivacyControlEnabled,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (previous.value?.preferredColorScheme !=
|
// Note: preferredColorScheme is intentionally NOT replicated from the
|
||||||
settings.preferredColorScheme) {
|
// engine settings here. The app theme (generalSettings.themeMode) is the
|
||||||
await _service.preferredColorScheme(
|
// sole source of truth for the color scheme; see the themeMode listener
|
||||||
settings.preferredColorScheme,
|
// above. EngineSettings.preferredColorScheme is vestigial and always
|
||||||
);
|
// `system`, so replicating it would clobber the real theme (issue #436).
|
||||||
}
|
|
||||||
if (previous.value?.cookieBannerHandlingMode !=
|
if (previous.value?.cookieBannerHandlingMode !=
|
||||||
settings.cookieBannerHandlingMode) {
|
settings.cookieBannerHandlingMode) {
|
||||||
await _service.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.activity.addCallback
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.WindowCompat
|
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.ExternalAppBrowserFragment
|
||||||
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||||
import eu.weblibre.flutter_mozilla_components.PwaConstants
|
import eu.weblibre.flutter_mozilla_components.PwaConstants
|
||||||
@@ -76,6 +77,12 @@ open class ExternalAppBrowserActivity : AppCompatActivity() {
|
|||||||
get() = intent?.getStringExtra(EXTRA_WEB_APP_MANIFEST_URL)
|
get() = intent?.getStringExtra(EXTRA_WEB_APP_MANIFEST_URL)
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
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)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
onBackPressedDispatcher.addCallback(this) {
|
onBackPressedDispatcher.addCallback(this) {
|
||||||
|
|||||||
+8
@@ -8,6 +8,7 @@ package eu.weblibre.flutter_mozilla_components.api
|
|||||||
|
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ColorSchemePreference
|
||||||
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||||
import eu.weblibre.flutter_mozilla_components.R
|
import eu.weblibre.flutter_mozilla_components.R
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.AppLinksMode
|
import eu.weblibre.flutter_mozilla_components.pigeons.AppLinksMode
|
||||||
@@ -336,6 +337,13 @@ class GeckoEngineSettingsApiImpl : GeckoEngineSettingsApi {
|
|||||||
}
|
}
|
||||||
if(settings.preferredColorScheme != null) {
|
if(settings.preferredColorScheme != null) {
|
||||||
components.core.engine.settings.preferredColorScheme = components.core.engineSettings.preferredColorScheme
|
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
|
reloadSession = true
|
||||||
}
|
}
|
||||||
if(settings.cookieBannerHandlingMode != null) {
|
if(settings.cookieBannerHandlingMode != null) {
|
||||||
|
|||||||
+5
-2
@@ -11,6 +11,7 @@ import android.content.SharedPreferences
|
|||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ColorSchemePreference
|
||||||
import eu.weblibre.flutter_mozilla_components.Components
|
import eu.weblibre.flutter_mozilla_components.Components
|
||||||
import eu.weblibre.flutter_mozilla_components.interceptor.AppRequestInterceptor
|
import eu.weblibre.flutter_mozilla_components.interceptor.AppRequestInterceptor
|
||||||
import eu.weblibre.flutter_mozilla_components.services.DownloadService
|
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
|
||||||
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
|
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
|
||||||
import mozilla.components.concept.engine.fission.WebContentIsolationStrategy
|
import mozilla.components.concept.engine.fission.WebContentIsolationStrategy
|
||||||
import mozilla.components.concept.engine.mediaquery.PreferredColorScheme
|
|
||||||
import mozilla.components.concept.fetch.Client
|
import mozilla.components.concept.fetch.Client
|
||||||
import mozilla.components.feature.addons.AddonManager
|
import mozilla.components.feature.addons.AddonManager
|
||||||
import mozilla.components.feature.addons.amo.AMOAddonsProvider
|
import mozilla.components.feature.addons.amo.AMOAddonsProvider
|
||||||
@@ -122,7 +122,10 @@ class Core(
|
|||||||
//fingerprintingProtectionPrivateBrowsing
|
//fingerprintingProtectionPrivateBrowsing
|
||||||
httpsOnlyMode = Engine.HttpsOnlyMode.ENABLED,
|
httpsOnlyMode = Engine.HttpsOnlyMode.ENABLED,
|
||||||
globalPrivacyControlEnabled = true,
|
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,
|
cookieBannerHandlingMode = EngineSession.CookieBannerHandlingMode.REJECT_ALL,
|
||||||
cookieBannerHandlingModePrivateBrowsing = EngineSession.CookieBannerHandlingMode.REJECT_ALL,
|
cookieBannerHandlingModePrivateBrowsing = EngineSession.CookieBannerHandlingMode.REJECT_ALL,
|
||||||
cookieBannerHandlingGlobalRules = true,
|
cookieBannerHandlingGlobalRules = true,
|
||||||
|
|||||||
Reference in New Issue
Block a user