mirror of
https://github.com/LiveFastEatTrashRaccoon/RaccoonForLemmy.git
synced 2025-02-08 17:28:47 +01:00
enhancement: add workaround for solid status bar color (#303)
* define interface for workaround * expose opaque theme support in bar color provider * update iOS implementation or bar color provider * update Android implementation or bar color provider * restore option in advanced settings * update Gradle scripts * apply workaround in MainActivity
This commit is contained in:
parent
a49cc6258e
commit
c17f31e8ee
@ -94,9 +94,11 @@ dependencies {
|
||||
implementation(libs.voyager.tab)
|
||||
|
||||
implementation(projects.shared)
|
||||
implementation(projects.core.appearance)
|
||||
implementation(projects.core.di)
|
||||
implementation(projects.core.utils)
|
||||
implementation(projects.core.navigation)
|
||||
implementation(projects.core.persistence)
|
||||
implementation(projects.core.resources)
|
||||
|
||||
kover(projects.shared)
|
||||
|
@ -10,12 +10,19 @@ import androidx.activity.enableEdgeToEdge
|
||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.livefast.eattrash.raccoonforlemmy.MainView
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.appearance.data.toUiBarTheme
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.appearance.data.toUiTheme
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.appearance.di.getBarColorProvider
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.appearance.theme.SolidBarColorWorkaround
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.navigation.ComposeEvent
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.navigation.TabNavigationSection
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.navigation.di.getNavigationCoordinator
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.di.getAccountRepository
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.di.getSettingsRepository
|
||||
import com.livefast.eattrash.raccoonforlemmy.feature.home.ui.HomeTab
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@ -79,6 +86,11 @@ class MainActivity : ComponentActivity() {
|
||||
handleIntent(intent)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
applyWorkaroundForSolidStatusBar()
|
||||
}
|
||||
|
||||
private fun handleIntent(intent: Intent?) =
|
||||
intent?.apply {
|
||||
when (action) {
|
||||
@ -110,4 +122,20 @@ class MainActivity : ComponentActivity() {
|
||||
val navigationCoordinator = getNavigationCoordinator()
|
||||
navigationCoordinator.submitComposeEvent(event)
|
||||
}
|
||||
|
||||
private fun applyWorkaroundForSolidStatusBar() {
|
||||
val barColorProvider = getBarColorProvider()
|
||||
val settingsRepository = getSettingsRepository()
|
||||
val accountRepository = getAccountRepository()
|
||||
val settings =
|
||||
runBlocking {
|
||||
val accountId = accountRepository.getActive()?.id
|
||||
settingsRepository.getSettings(accountId)
|
||||
}
|
||||
(barColorProvider as? SolidBarColorWorkaround)?.apply(
|
||||
activity = this@MainActivity,
|
||||
theme = settings.theme.toUiTheme(),
|
||||
barTheme = settings.systemBarTheme.toUiBarTheme(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.livefast.eattrash.raccoonforlemmy.core.appearance.theme
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import android.view.WindowInsets
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@ -12,9 +13,14 @@ import androidx.core.view.WindowCompat
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.appearance.data.UiBarTheme
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.appearance.data.UiTheme
|
||||
|
||||
internal class DefaultBarColorProvider : BarColorProvider {
|
||||
override val isBarThemeSupported: Boolean
|
||||
get() = Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM
|
||||
internal class DefaultBarColorProvider :
|
||||
BarColorProvider,
|
||||
SolidBarColorWorkaround {
|
||||
override val isBarThemeSupported = true
|
||||
override val isOpaqueThemeSupported: Boolean
|
||||
get() {
|
||||
return Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun setBarColorAccordingToTheme(
|
||||
@ -25,24 +31,8 @@ internal class DefaultBarColorProvider : BarColorProvider {
|
||||
val isSystemInDarkTheme = isSystemInDarkTheme()
|
||||
LaunchedEffect(theme, barTheme) {
|
||||
(view.context as? Activity)?.window?.apply {
|
||||
val baseColor =
|
||||
when (theme) {
|
||||
UiTheme.Light -> Color.White
|
||||
UiTheme.Black, UiTheme.Dark -> Color.Black
|
||||
UiTheme.Default ->
|
||||
if (isSystemInDarkTheme) {
|
||||
Color.Black
|
||||
} else {
|
||||
Color.White
|
||||
}
|
||||
else -> Color.Black
|
||||
}
|
||||
val barColor =
|
||||
when (barTheme) {
|
||||
UiBarTheme.Opaque -> baseColor.copy(alpha = 0.25f)
|
||||
UiBarTheme.Transparent -> baseColor.copy(alpha = 0.01f)
|
||||
else -> baseColor
|
||||
}.toArgb()
|
||||
val baseColor = theme.getBaseColor(isSystemInDarkTheme)
|
||||
val barColor = barTheme.getBarColor(baseColor).toArgb()
|
||||
if (isBarThemeSupported) {
|
||||
statusBarColor = barColor
|
||||
navigationBarColor = barColor
|
||||
@ -50,7 +40,7 @@ internal class DefaultBarColorProvider : BarColorProvider {
|
||||
|
||||
WindowCompat.setDecorFitsSystemWindows(this, false)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
||||
if (isBarThemeSupported) {
|
||||
isStatusBarContrastEnforced = true
|
||||
}
|
||||
isNavigationBarContrastEnforced = true
|
||||
@ -71,4 +61,50 @@ internal class DefaultBarColorProvider : BarColorProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun apply(
|
||||
activity: Activity,
|
||||
theme: UiTheme,
|
||||
barTheme: UiBarTheme,
|
||||
) {
|
||||
if (barTheme == UiBarTheme.Transparent) {
|
||||
return
|
||||
}
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||
return
|
||||
}
|
||||
|
||||
val decorView = activity.window.decorView
|
||||
val isSystemInDarkTheme = activity.resources.configuration.isNightModeActive
|
||||
val baseColor = theme.getBaseColor(isSystemInDarkTheme)
|
||||
val barColor = barTheme.getBarColor(baseColor).toArgb()
|
||||
|
||||
decorView.setOnApplyWindowInsetsListener { view, insets ->
|
||||
val systemBarInsets = insets.getInsets(WindowInsets.Type.systemBars())
|
||||
view.setBackgroundColor(barColor)
|
||||
view.setPadding(0, systemBarInsets.top, 0, systemBarInsets.bottom)
|
||||
insets
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun UiTheme.getBaseColor(isSystemInDarkTheme: Boolean): Color =
|
||||
when (this) {
|
||||
UiTheme.Light -> Color.White
|
||||
UiTheme.Black, UiTheme.Dark -> Color.Black
|
||||
UiTheme.Default ->
|
||||
if (isSystemInDarkTheme) {
|
||||
Color.Black
|
||||
} else {
|
||||
Color.White
|
||||
}
|
||||
|
||||
else -> Color.Black
|
||||
}
|
||||
|
||||
private fun UiBarTheme.getBarColor(baseColor: Color): Color =
|
||||
when (this) {
|
||||
UiBarTheme.Opaque -> baseColor.copy(alpha = 0.25f)
|
||||
UiBarTheme.Transparent -> baseColor.copy(alpha = 0.01f)
|
||||
else -> baseColor
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
package com.livefast.eattrash.raccoonforlemmy.core.appearance.theme
|
||||
|
||||
import android.app.Activity
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.appearance.data.UiBarTheme
|
||||
import com.livefast.eattrash.raccoonforlemmy.core.appearance.data.UiTheme
|
||||
|
||||
interface SolidBarColorWorkaround {
|
||||
fun apply(
|
||||
activity: Activity,
|
||||
theme: UiTheme,
|
||||
barTheme: UiBarTheme,
|
||||
)
|
||||
}
|
@ -6,6 +6,7 @@ import com.livefast.eattrash.raccoonforlemmy.core.appearance.data.UiTheme
|
||||
|
||||
interface BarColorProvider {
|
||||
val isBarThemeSupported: Boolean
|
||||
val isOpaqueThemeSupported: Boolean
|
||||
|
||||
@Composable
|
||||
fun setBarColorAccordingToTheme(
|
||||
|
@ -11,6 +11,7 @@ import platform.UIKit.setStatusBarStyle
|
||||
|
||||
internal class DefaultBarColorProvider : BarColorProvider {
|
||||
override val isBarThemeSupported = false
|
||||
override val isOpaqueThemeSupported = false
|
||||
|
||||
@Composable
|
||||
override fun setBarColorAccordingToTheme(
|
||||
|
@ -131,6 +131,7 @@ interface AdvancedSettingsMviModel :
|
||||
val enableAlternateMarkdownRendering: Boolean = false,
|
||||
val restrictLocalUserSearch: Boolean = false,
|
||||
val isBarThemeSupported: Boolean = false,
|
||||
val isBarOpaqueThemeSupported: Boolean = false,
|
||||
val markAsReadOnInteraction: Boolean = true,
|
||||
)
|
||||
|
||||
|
@ -665,11 +665,13 @@ class AdvancedSettingsScreen : Screen {
|
||||
|
||||
if (barThemeBottomSheetOpened) {
|
||||
val values =
|
||||
listOf(
|
||||
UiBarTheme.Transparent,
|
||||
UiBarTheme.Opaque,
|
||||
UiBarTheme.Solid,
|
||||
)
|
||||
buildList {
|
||||
this += UiBarTheme.Transparent
|
||||
if (uiState.isBarOpaqueThemeSupported) {
|
||||
this += UiBarTheme.Opaque
|
||||
}
|
||||
this += UiBarTheme.Solid
|
||||
}
|
||||
CustomModalBottomSheet(
|
||||
title = LocalStrings.current.settingsBarTheme,
|
||||
items =
|
||||
|
@ -167,6 +167,7 @@ class AdvancedSettingsViewModel(
|
||||
enableAlternateMarkdownRendering = settings.enableAlternateMarkdownRendering,
|
||||
restrictLocalUserSearch = settings.restrictLocalUserSearch,
|
||||
isBarThemeSupported = barColorProvider.isBarThemeSupported,
|
||||
isBarOpaqueThemeSupported = barColorProvider.isOpaqueThemeSupported,
|
||||
markAsReadOnInteraction = settings.markAsReadOnInteraction,
|
||||
)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user