fix: resolve SYSTEM theme to concrete DARK/LIGHT before crossing process boundary

Instead of passing the raw ThemeType name ("SYSTEM") to the :napplet process,
resolve it to the actual dark/light value in the main process by reading
context.resources.configuration.uiMode before the launch. The napplet process
now always receives "DARK" or "LIGHT" and sets UiModeManager.nightMode
unconditionally, making prefers-color-scheme reliable on all ThemeType choices.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0198rKcuv32DEoUPpLqsBYbx
This commit is contained in:
Claude
2026-06-25 12:53:03 +00:00
parent 85388e3c4b
commit daf6a2d022
7 changed files with 36 additions and 7 deletions
@@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.favorites
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import android.util.Log
import android.widget.Toast
@@ -29,6 +30,7 @@ import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.commons.favorites.FavoriteApp
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.ThemeType
import com.vitorpamplona.amethyst.napplet.NappletLauncher
import com.vitorpamplona.amethyst.napplet.WebUrlNetworkRegistry
import com.vitorpamplona.amethyst.napplethost.NappletBrowserActivity
@@ -77,7 +79,16 @@ object FavoriteAppLauncher {
) {
val proxyPort = Amethyst.instance.torManager.activePortOrNull.value ?: -1
val useTor = proxyPort > 0 && (preferTor || WebUrlNetworkRegistry.useTor(url))
val theme = Amethyst.instance.uiPrefs.value.theme.value.name
val themeType = Amethyst.instance.uiPrefs.value.theme.value
val theme =
when (themeType) {
ThemeType.DARK -> "DARK"
ThemeType.LIGHT -> "LIGHT"
ThemeType.SYSTEM -> {
val nightMask = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
if (nightMask == Configuration.UI_MODE_NIGHT_YES) "DARK" else "LIGHT"
}
}
val intent =
NappletBrowserActivity.intent(context, url, proxyPort, useTor, theme = theme).apply {
if (context !is Activity) addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
@@ -22,12 +22,14 @@ package com.vitorpamplona.amethyst.napplet
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.os.Bundle
import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.commons.napplet.NappletCapability
import com.vitorpamplona.amethyst.commons.napplet.NappletIdentity
import com.vitorpamplona.amethyst.commons.napplet.resolveRequiredCapabilities
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.ThemeType
import com.vitorpamplona.amethyst.napplethost.NappletHostActivity
import com.vitorpamplona.amethyst.napplethost.NappletHostContract
import com.vitorpamplona.quartz.nip01Core.core.HexKey
@@ -134,7 +136,16 @@ object NappletLauncher {
// Resolve capability labels here (the app has the resources) so the sandbox module needs none.
val capLabels = declared.map { context.getString(it.labelRes()) }
val theme = Amethyst.instance.uiPrefs.value.theme.value.name
val themeType = Amethyst.instance.uiPrefs.value.theme.value
val theme =
when (themeType) {
ThemeType.DARK -> "DARK"
ThemeType.LIGHT -> "LIGHT"
ThemeType.SYSTEM -> {
val nightMask = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
if (nightMask == Configuration.UI_MODE_NIGHT_YES) "DARK" else "LIGHT"
}
}
return Bundle().apply {
putStringArrayList(NappletHostContract.EXTRA_PATHS, ArrayList(paths.map { it.path }))
@@ -21,6 +21,7 @@
package com.vitorpamplona.amethyst.ui.screen.loggedIn.embed
import android.content.Context
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
import androidx.annotation.RequiresApi
@@ -28,6 +29,7 @@ import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.commons.favorites.FavoriteApp
import com.vitorpamplona.amethyst.commons.tor.TorType
import com.vitorpamplona.amethyst.favorites.FavoriteAppLauncher
import com.vitorpamplona.amethyst.model.ThemeType
import com.vitorpamplona.amethyst.napplet.WebUrlNetworkRegistry
import com.vitorpamplona.amethyst.napplethost.NappletHostContract
import com.vitorpamplona.amethyst.ui.screen.loggedIn.browser.EmbeddedBrowserController
@@ -57,7 +59,16 @@ object EmbeddedTabFactory {
EmbeddedTabHost.acquire(browserId(url)) {
val proxyPort = Amethyst.instance.torManager.activePortOrNull.value ?: -1
val initialUseTor = proxyPort > 0 && WebUrlNetworkRegistry.useTor(url)
val theme = Amethyst.instance.uiPrefs.value.theme.value.name
val themeType = Amethyst.instance.uiPrefs.value.theme.value
val theme =
when (themeType) {
ThemeType.DARK -> "DARK"
ThemeType.LIGHT -> "LIGHT"
ThemeType.SYSTEM -> {
val nightMask = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
if (nightMask == Configuration.UI_MODE_NIGHT_YES) "DARK" else "LIGHT"
}
}
EmbeddedBrowserController(context.applicationContext, proxyPort, initialUseTor, backgroundColor, theme).also { it.bind(url) }
} as EmbeddedBrowserController
@@ -624,7 +624,6 @@ class NappletBrowserActivity : ComponentActivity() {
when (themeType) {
"DARK" -> uiManager.nightMode = android.app.UiModeManager.MODE_NIGHT_YES
"LIGHT" -> uiManager.nightMode = android.app.UiModeManager.MODE_NIGHT_NO
else -> {} // SYSTEM: follow the device setting (process default)
}
}
@@ -143,7 +143,6 @@ class NappletBrowserService : Service() {
when (themeType) {
"DARK" -> uiManager.nightMode = android.app.UiModeManager.MODE_NIGHT_YES
"LIGHT" -> uiManager.nightMode = android.app.UiModeManager.MODE_NIGHT_NO
else -> {} // SYSTEM: follow the device setting (process default)
}
}
@@ -803,7 +803,6 @@ class NappletHostActivity : ComponentActivity() {
when (themeType) {
"DARK" -> uiManager.nightMode = android.app.UiModeManager.MODE_NIGHT_YES
"LIGHT" -> uiManager.nightMode = android.app.UiModeManager.MODE_NIGHT_NO
else -> {} // SYSTEM: follow the device setting (process default)
}
}
@@ -192,7 +192,6 @@ class NappletHostService : Service() {
when (themeType) {
"DARK" -> uiManager.nightMode = android.app.UiModeManager.MODE_NIGHT_YES
"LIGHT" -> uiManager.nightMode = android.app.UiModeManager.MODE_NIGHT_NO
else -> {} // SYSTEM: follow the device setting (process default)
}
}