Set Dark theme in Settings

Add MyViewModel to keep ThemeSettings state
Use ListItem to display SSIDs in WiFi SSID Policy
Use green color scheme as default color scheme
Add Compose BOM dependency, update dependencies
This commit is contained in:
BinTianqi
2024-11-16 12:48:01 +08:00
parent 66d7e80c8c
commit 2546a9c3c8
16 changed files with 316 additions and 259 deletions

View File

@@ -7,6 +7,7 @@ import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
@@ -64,11 +65,10 @@ class InstallAppActivity: FragmentActivity() {
apkInfoText += "${context.getString(R.string.version_code)}: ${apkInfo.versionCode}"
}
}
val vm by viewModels<MyViewModel>()
if(!vm.initialized) vm.initialize(applicationContext)
setContent {
OwnDroidTheme(
sharedPref.getBoolean("material_you", true),
sharedPref.getBoolean("black_theme", false)
) {
OwnDroidTheme(vm) {
AlertDialog(
properties = DialogProperties(dismissOnBackPress = false, dismissOnClickOutside = false),
title = {

View File

@@ -7,6 +7,7 @@ import android.os.Bundle
import android.widget.Toast
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
@@ -30,7 +31,6 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
@@ -85,7 +85,7 @@ class MainActivity : FragmentActivity() {
enableEdgeToEdge()
WindowCompat.setDecorFitsSystemWindows(window, false)
super.onCreate(savedInstanceState)
val sharedPref = applicationContext.getSharedPreferences("data", Context.MODE_PRIVATE)
val sharedPref = applicationContext.getSharedPreferences("data", MODE_PRIVATE)
if (VERSION.SDK_INT >= 28) HiddenApiBypass.setHiddenApiExemptions("")
if(sharedPref.getBoolean("auth", false)) {
showAuth.value = true
@@ -93,11 +93,11 @@ class MainActivity : FragmentActivity() {
val locale = applicationContext.resources?.configuration?.locale
zhCN = locale == Locale.SIMPLIFIED_CHINESE || locale == Locale.CHINESE || locale == Locale.CHINA
toggleInstallAppActivity()
val vm by viewModels<MyViewModel>()
if(!vm.initialized) vm.initialize(applicationContext)
setContent {
val materialYou = remember { mutableStateOf(sharedPref.getBoolean("material_you", true)) }
val blackTheme = remember { mutableStateOf(sharedPref.getBoolean("black_theme", false)) }
OwnDroidTheme(materialYou.value, blackTheme.value) {
Home(materialYou, blackTheme)
OwnDroidTheme(vm) {
Home(vm)
if(showAuth.value) {
AuthScreen(this, showAuth)
}
@@ -107,7 +107,7 @@ class MainActivity : FragmentActivity() {
override fun onResume() {
super.onResume()
val sharedPref = applicationContext.getSharedPreferences("data", Context.MODE_PRIVATE)
val sharedPref = applicationContext.getSharedPreferences("data", MODE_PRIVATE)
if(
sharedPref.getBoolean("auth", false) &&
sharedPref.getBoolean("lock_in_background", false)
@@ -128,7 +128,7 @@ class MainActivity : FragmentActivity() {
@ExperimentalMaterial3Api
@Composable
fun Home(materialYou:MutableState<Boolean>, blackTheme:MutableState<Boolean>) {
fun Home(vm: MyViewModel) {
val navCtrl = rememberNavController()
val context = LocalContext.current
val dpm = context.getDPM()
@@ -161,7 +161,7 @@ fun Home(materialYou:MutableState<Boolean>, blackTheme:MutableState<Boolean>) {
composable(route = "UserRestriction") { UserRestriction(navCtrl) }
composable(route = "UserManage") { UserManage(navCtrl) }
composable(route = "Password") { Password(navCtrl) }
composable(route = "AppSetting") { AppSetting(navCtrl, materialYou, blackTheme) }
composable(route = "AppSetting") { AppSetting(navCtrl, vm) }
composable(route = "Network") { Network(navCtrl) }
composable(route = "PackageSelector") { PackageSelector(navCtrl) }
}

View File

@@ -3,6 +3,7 @@ package com.bintianqi.owndroid
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
@@ -17,11 +18,11 @@ class ManageSpaceActivity: FragmentActivity() {
WindowCompat.setDecorFitsSystemWindows(window, false)
super.onCreate(savedInstanceState)
val sharedPref = applicationContext.getSharedPreferences("data", MODE_PRIVATE)
val materialYou = sharedPref.getBoolean("material_you", true)
val blackTheme = sharedPref.getBoolean("black_theme", false)
val protected = sharedPref.getBoolean("protect_storage", false)
val vm by viewModels<MyViewModel>()
if(!vm.initialized) vm.initialize(applicationContext)
setContent {
OwnDroidTheme(materialYou, blackTheme) {
OwnDroidTheme(vm) {
AlertDialog(
title = {
Text(stringResource(R.string.clear_storage))

View File

@@ -0,0 +1,37 @@
package com.bintianqi.owndroid
import android.content.Context
import android.os.Build
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
class MyViewModel: ViewModel() {
val theme = MutableStateFlow(ThemeSettings())
var initialized = false
fun initialize(context: Context) {
val sharedPrefs = context.getSharedPreferences("data", Context.MODE_PRIVATE)
theme.value = ThemeSettings(
materialYou = sharedPrefs.getBoolean("material_you", Build.VERSION.SDK_INT >= 31),
darkTheme = if(sharedPrefs.contains("dark_theme")) sharedPrefs.getBoolean("dark_theme", false) else null,
blackTheme = sharedPrefs.getBoolean("black_theme", false)
)
viewModelScope.launch {
theme.collect {
val editor = sharedPrefs.edit()
editor.putBoolean("material_you", it.materialYou)
if(it.darkTheme == null) editor.remove("dark_theme") else editor.putBoolean("dark_theme", it.darkTheme)
editor.putBoolean("black_theme", it.blackTheme)
editor.commit()
}
}
}
}
data class ThemeSettings(
val materialYou: Boolean = false,
val darkTheme: Boolean? = null,
val blackTheme: Boolean = false
)

View File

@@ -4,9 +4,10 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build.VERSION
import android.util.Base64
import android.widget.Toast
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
@@ -15,6 +16,8 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme.typography
@@ -22,7 +25,6 @@ import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -31,7 +33,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
@@ -44,7 +48,7 @@ import com.bintianqi.owndroid.ui.TopBar
import java.security.SecureRandom
@Composable
fun AppSetting(navCtrl:NavHostController, materialYou: MutableState<Boolean>, blackTheme: MutableState<Boolean>) {
fun AppSetting(navCtrl:NavHostController, vm: MyViewModel) {
val localNavCtrl = rememberNavController()
val backStackEntry by localNavCtrl.currentBackStackEntryAsState()
Scaffold(
@@ -62,7 +66,7 @@ fun AppSetting(navCtrl:NavHostController, materialYou: MutableState<Boolean>, bl
) {
composable(route = "Home") { Home(localNavCtrl) }
composable(route = "Options") { Options() }
composable(route = "Theme") { ThemeSettings(materialYou, blackTheme) }
composable(route = "Theme") { ThemeSettings(vm) }
composable(route = "Auth") { AuthSettings() }
composable(route = "Automation") { Automation() }
composable(route = "About") { About() }
@@ -94,27 +98,56 @@ private fun Options() {
}
@Composable
private fun ThemeSettings(materialYou:MutableState<Boolean>, blackTheme:MutableState<Boolean>) {
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(start = 20.dp, end = 16.dp)) {
private fun ThemeSettings(vm: MyViewModel) {
val theme by vm.theme.collectAsStateWithLifecycle()
var darkThemeMenu by remember { mutableStateOf(false) }
val darkThemeTextID = when(theme.darkTheme) {
true -> R.string.on
false -> R.string.off
null -> R.string.follow_system
}
Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())) {
if(VERSION.SDK_INT >= 31) {
SwitchItem(
R.string.material_you_color, stringResource(R.string.dynamic_color_desc), null,
{ sharedPref.getBoolean("material_you",true) },
{
sharedPref.edit().putBoolean("material_you", it).apply()
materialYou.value = it
}, padding = false
R.string.material_you_color, "", null,
theme.materialYou,
{ vm.theme.value = theme.copy(materialYou = it) }
)
}
if(isSystemInDarkTheme()) {
Box {
SubPageItem(R.string.dark_theme, stringResource(darkThemeTextID)) { darkThemeMenu = true }
DropdownMenu(
expanded = darkThemeMenu, onDismissRequest = { darkThemeMenu = false },
offset = DpOffset(x = 30.dp, y = 0.dp)
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.follow_system)) },
onClick = {
vm.theme.value = theme.copy(darkTheme = null)
darkThemeMenu = false
}
)
DropdownMenuItem(
text = { Text(stringResource(R.string.on)) },
onClick = {
vm.theme.value = theme.copy(darkTheme = true)
darkThemeMenu = false
}
)
DropdownMenuItem(
text = { Text(stringResource(R.string.off)) },
onClick = {
vm.theme.value = theme.copy(darkTheme = false)
darkThemeMenu = false
}
)
}
}
AnimatedVisibility(theme.darkTheme == true || (theme.darkTheme == null && isSystemInDarkTheme())) {
SwitchItem(
R.string.amoled_black, stringResource(R.string.blackTheme_desc), null,
{ sharedPref.getBoolean("black_theme",false) },
{
sharedPref.edit().putBoolean("black_theme", it).apply()
blackTheme.value = it
}, padding = false
R.string.black_theme, "", null,
theme.blackTheme,
{ vm.theme.value = theme.copy(blackTheme = it) }
)
}
}

View File

@@ -68,7 +68,7 @@ fun registerActivityResult(context: ComponentActivity){
activityResult.data.let {
if(it == null){
Toast.makeText(context.applicationContext, R.string.file_not_exist, Toast.LENGTH_SHORT).show()
}else{
} else {
fileUriFlow.value = it.data
}
}
@@ -76,7 +76,7 @@ fun registerActivityResult(context: ComponentActivity){
createManagedProfile = context.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {}
addDeviceAdmin = context.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
val dpm = context.applicationContext.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
if(dpm.isAdminActive(ComponentName(context.applicationContext, Receiver::class.java))){
if(dpm.isAdminActive(ComponentName(context.applicationContext, Receiver::class.java))) {
backToHomeStateFlow.value = true
}
}

View File

@@ -111,6 +111,7 @@ import com.bintianqi.owndroid.formatFileSize
import com.bintianqi.owndroid.selectedPackage
import com.bintianqi.owndroid.ui.Animations
import com.bintianqi.owndroid.ui.CheckBoxItem
import com.bintianqi.owndroid.ui.ListItem
import com.bintianqi.owndroid.ui.RadioButtonItem
import com.bintianqi.owndroid.ui.SubPageItem
import com.bintianqi.owndroid.ui.SwitchItem
@@ -307,7 +308,7 @@ private fun WifiSsidPolicy() {
val policy = dpm.wifiSsidPolicy
ssidList.clear()
selectedPolicyType = policy?.policyType ?: -1
(policy?.ssids ?: mutableSetOf()).forEach { ssidList.add(it) }
ssidList.addAll(policy?.ssids ?: mutableSetOf())
}
LaunchedEffect(Unit) { refreshPolicy() }
Spacer(Modifier.padding(vertical = 10.dp))
@@ -331,68 +332,46 @@ private fun WifiSsidPolicy() {
AnimatedVisibility(selectedPolicyType != -1) {
var inputSsid by remember { mutableStateOf("") }
Column {
Column {
Spacer(Modifier.padding(vertical = 5.dp))
Text(stringResource(R.string.ssid_list_is))
SelectionContainer(modifier = Modifier.animateContentSize().horizontalScroll(rememberScrollState())) {
Text(if(ssidList.isEmpty()) stringResource(R.string.none) else ssidList.joinToString(separator = "\n"))
Text(stringResource(R.string.ssid_list_is))
if(ssidList.isEmpty()) Text(stringResource(R.string.none))
Column(modifier = Modifier.animateContentSize()) {
for(i in ssidList) {
ListItem(i.bytes.decodeToString()) { ssidList -= i }
}
}
Spacer(Modifier.padding(vertical = 5.dp))
OutlinedTextField(
value = inputSsid,
label = { Text("SSID") },
onValueChange = {inputSsid = it },
onValueChange = { inputSsid = it },
trailingIcon = {
IconButton(
onClick = {
ssidList += WifiSsid.fromBytes(inputSsid.encodeToByteArray())
inputSsid = ""
},
enabled = inputSsid != ""
) {
Icon(imageVector = Icons.Default.Add, contentDescription = stringResource(R.string.add))
}
},
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
modifier = Modifier.fillMaxWidth()
)
Spacer(Modifier.padding(vertical = 5.dp))
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Button(
onClick = {
if(inputSsid == "") {
Toast.makeText(context, R.string.cannot_be_empty, Toast.LENGTH_SHORT).show()
} else if (WifiSsid.fromBytes(inputSsid.toByteArray()) in ssidList) {
Toast.makeText(context, R.string.already_exist, Toast.LENGTH_SHORT).show()
} else {
ssidList.add(WifiSsid.fromBytes(inputSsid.toByteArray()))
}
},
modifier = Modifier.fillMaxWidth(0.49F)
) {
Text(stringResource(R.string.add))
}
Button(
onClick = {
if(inputSsid == "") {
Toast.makeText(context, R.string.cannot_be_empty, Toast.LENGTH_SHORT).show()
} else if (WifiSsid.fromBytes(inputSsid.toByteArray()) in ssidList) {
ssidList.remove(WifiSsid.fromBytes(inputSsid.toByteArray()))
} else {
Toast.makeText(context, R.string.not_exist, Toast.LENGTH_SHORT).show()
}
},
modifier = Modifier.fillMaxWidth(0.96F)
) {
Text(stringResource(R.string.remove))
}
}
Spacer(Modifier.padding(vertical = 10.dp))
}
}
Button(
onClick = {
focusMgr.clearFocus()
if(selectedPolicyType == -1) {
dpm.wifiSsidPolicy = null
refreshPolicy()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
}else{
dpm.wifiSsidPolicy = if(ssidList.isEmpty()) { null }else{ WifiSsidPolicy(selectedPolicyType, ssidList.toSet()) }
refreshPolicy()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
dpm.wifiSsidPolicy = if(selectedPolicyType == -1 || ssidList.isEmpty()) {
null
} else {
WifiSsidPolicy(selectedPolicyType, ssidList.toSet())
}
refreshPolicy()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
},
modifier = Modifier.fillMaxWidth()
) {

View File

@@ -278,7 +278,7 @@ private fun UserOperation() {
},
modifier = Modifier.fillMaxWidth()
) {
Text(stringResource(R.string.user_operation_stop))
Text(stringResource(R.string.stop))
}
}
Button(
@@ -293,7 +293,7 @@ private fun UserOperation() {
},
modifier = Modifier.fillMaxWidth()
) {
Text(stringResource(R.string.user_operation_remove))
Text(stringResource(R.string.delete))
}
Spacer(Modifier.padding(vertical = 30.dp))
}

View File

@@ -2,62 +2,75 @@ package com.bintianqi.owndroid.ui.theme
import androidx.compose.ui.graphics.Color
val md_theme_light_primary = Color(0xFF006A65)
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
val md_theme_light_primaryContainer = Color(0xFF70F7EE)
val md_theme_light_onPrimaryContainer = Color(0xFF00201E)
val md_theme_light_secondary = Color(0xFF4A6361)
val md_theme_light_onSecondary = Color(0xFFFFFFFF)
val md_theme_light_secondaryContainer = Color(0xFFCCE8E5)
val md_theme_light_onSecondaryContainer = Color(0xFF051F1E)
val md_theme_light_tertiary = Color(0xFF48607B)
val md_theme_light_onTertiary = Color(0xFFFFFFFF)
val md_theme_light_tertiaryContainer = Color(0xFFD0E4FF)
val md_theme_light_onTertiaryContainer = Color(0xFF001D34)
val md_theme_light_error = Color(0xFFBA1A1A)
val md_theme_light_errorContainer = Color(0xFFFFDAD6)
val md_theme_light_onError = Color(0xFFFFFFFF)
val md_theme_light_onErrorContainer = Color(0xFF410002)
val md_theme_light_background = Color(0xFFFAFDFB)
val md_theme_light_onBackground = Color(0xFF191C1C)
val md_theme_light_surface = Color(0xFFFAFDFB)
val md_theme_light_onSurface = Color(0xFF191C1C)
val md_theme_light_surfaceVariant = Color(0xFFDAE5E3)
val md_theme_light_onSurfaceVariant = Color(0xFF3F4947)
val md_theme_light_outline = Color(0xFF6F7978)
val md_theme_light_inverseOnSurface = Color(0xFFEFF1F0)
val md_theme_light_inverseSurface = Color(0xFF2D3130)
val md_theme_light_inversePrimary = Color(0xFF4FDAD1)
val md_theme_light_surfaceTint = Color(0xFF006A65)
val md_theme_light_outlineVariant = Color(0xFFBEC9C7)
val md_theme_light_scrim = Color(0xFF000000)
val primaryLight = Color(0xFF4C662B)
val onPrimaryLight = Color(0xFFFFFFFF)
val primaryContainerLight = Color(0xFFCDEDA3)
val onPrimaryContainerLight = Color(0xFF102000)
val secondaryLight = Color(0xFF586249)
val onSecondaryLight = Color(0xFFFFFFFF)
val secondaryContainerLight = Color(0xFFDCE7C8)
val onSecondaryContainerLight = Color(0xFF151E0B)
val tertiaryLight = Color(0xFF386663)
val onTertiaryLight = Color(0xFFFFFFFF)
val tertiaryContainerLight = Color(0xFFBCECE7)
val onTertiaryContainerLight = Color(0xFF00201E)
val errorLight = Color(0xFFBA1A1A)
val onErrorLight = Color(0xFFFFFFFF)
val errorContainerLight = Color(0xFFFFDAD6)
val onErrorContainerLight = Color(0xFF410002)
val backgroundLight = Color(0xFFF9FAEF)
val onBackgroundLight = Color(0xFF1A1C16)
val surfaceLight = Color(0xFFF9FAEF)
val onSurfaceLight = Color(0xFF1A1C16)
val surfaceVariantLight = Color(0xFFE1E4D5)
val onSurfaceVariantLight = Color(0xFF44483D)
val outlineLight = Color(0xFF75796C)
val outlineVariantLight = Color(0xFFC5C8BA)
val scrimLight = Color(0xFF000000)
val inverseSurfaceLight = Color(0xFF2F312A)
val inverseOnSurfaceLight = Color(0xFFF1F2E6)
val inversePrimaryLight = Color(0xFFB1D18A)
val surfaceDimLight = Color(0xFFDADBD0)
val surfaceBrightLight = Color(0xFFF9FAEF)
val surfaceContainerLowestLight = Color(0xFFFFFFFF)
val surfaceContainerLowLight = Color(0xFFF3F4E9)
val surfaceContainerLight = Color(0xFFEEEFE3)
val surfaceContainerHighLight = Color(0xFFE8E9DE)
val surfaceContainerHighestLight = Color(0xFFE2E3D8)
val md_theme_dark_primary = Color(0xFF4FDAD1)
val md_theme_dark_onPrimary = Color(0xFF003734)
val md_theme_dark_primaryContainer = Color(0xFF00504C)
val md_theme_dark_onPrimaryContainer = Color(0xFF70F7EE)
val md_theme_dark_secondary = Color(0xFFB0CCC9)
val md_theme_dark_onSecondary = Color(0xFF1C3533)
val md_theme_dark_secondaryContainer = Color(0xFF324B49)
val md_theme_dark_onSecondaryContainer = Color(0xFFCCE8E5)
val md_theme_dark_tertiary = Color(0xFFB0C9E7)
val md_theme_dark_onTertiary = Color(0xFF18324A)
val md_theme_dark_tertiaryContainer = Color(0xFF304962)
val md_theme_dark_onTertiaryContainer = Color(0xFFD0E4FF)
val md_theme_dark_error = Color(0xFFFFB4AB)
val md_theme_dark_errorContainer = Color(0xFF93000A)
val md_theme_dark_onError = Color(0xFF690005)
val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6)
val md_theme_dark_background = Color(0xFF000000)
val md_theme_dark_onBackground = Color(0xFFE0E3E2)
val md_theme_dark_surface = Color(0xFF191C1C)
val md_theme_dark_onSurface = Color(0xFFE0E3E2)
val md_theme_dark_surfaceVariant = Color(0xFF3F4947)
val md_theme_dark_onSurfaceVariant = Color(0xFFBEC9C7)
val md_theme_dark_outline = Color(0xFF889391)
val md_theme_dark_inverseOnSurface = Color(0xFF191C1C)
val md_theme_dark_inverseSurface = Color(0xFFE0E3E2)
val md_theme_dark_inversePrimary = Color(0xFF006A65)
val md_theme_dark_surfaceTint = Color(0xFF4FDAD1)
val md_theme_dark_outlineVariant = Color(0xFF3F4947)
val md_theme_dark_scrim = Color(0xFF000000)
val primaryDark = Color(0xFFB1D18A)
val onPrimaryDark = Color(0xFF1F3701)
val primaryContainerDark = Color(0xFF354E16)
val onPrimaryContainerDark = Color(0xFFCDEDA3)
val secondaryDark = Color(0xFFBFCBAD)
val onSecondaryDark = Color(0xFF2A331E)
val secondaryContainerDark = Color(0xFF404A33)
val onSecondaryContainerDark = Color(0xFFDCE7C8)
val tertiaryDark = Color(0xFFA0D0CB)
val onTertiaryDark = Color(0xFF003735)
val tertiaryContainerDark = Color(0xFF1F4E4B)
val onTertiaryContainerDark = Color(0xFFBCECE7)
val errorDark = Color(0xFFFFB4AB)
val onErrorDark = Color(0xFF690005)
val errorContainerDark = Color(0xFF93000A)
val onErrorContainerDark = Color(0xFFFFDAD6)
val backgroundDark = Color(0xFF12140E)
val onBackgroundDark = Color(0xFFE2E3D8)
val surfaceDark = Color(0xFF12140E)
val onSurfaceDark = Color(0xFFE2E3D8)
val surfaceVariantDark = Color(0xFF44483D)
val onSurfaceVariantDark = Color(0xFFC5C8BA)
val outlineDark = Color(0xFF8F9285)
val outlineVariantDark = Color(0xFF44483D)
val scrimDark = Color(0xFF000000)
val inverseSurfaceDark = Color(0xFFE2E3D8)
val inverseOnSurfaceDark = Color(0xFF2F312A)
val inversePrimaryDark = Color(0xFF4C662B)
val surfaceDimDark = Color(0xFF12140E)
val surfaceBrightDark = Color(0xFF383A32)
val surfaceContainerLowestDark = Color(0xFF0C0F09)
val surfaceContainerLowDark = Color(0xFF1A1C16)
val surfaceContainerDark = Color(0xFF1E201A)
val surfaceContainerHighDark = Color(0xFF282B24)
val surfaceContainerHighestDark = Color(0xFF33362E)

View File

@@ -1,102 +1,112 @@
package com.bintianqi.owndroid.ui.theme
import android.app.Activity
import android.content.Context
import android.os.Build.VERSION
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.bintianqi.owndroid.MyViewModel
private val DarkColorScheme = darkColorScheme(
primary = md_theme_dark_primary,
onPrimary = md_theme_dark_onPrimary,
primaryContainer = md_theme_dark_primaryContainer,
onPrimaryContainer = md_theme_dark_onPrimaryContainer,
secondary = md_theme_dark_secondary,
onSecondary = md_theme_dark_onSecondary,
secondaryContainer = md_theme_dark_secondaryContainer,
onSecondaryContainer = md_theme_dark_onSecondaryContainer,
tertiary = md_theme_dark_tertiary,
onTertiary = md_theme_dark_onTertiary,
tertiaryContainer = md_theme_dark_tertiaryContainer,
onTertiaryContainer = md_theme_dark_onTertiaryContainer,
error = md_theme_dark_error,
errorContainer = md_theme_dark_errorContainer,
onError = md_theme_dark_onError,
onErrorContainer = md_theme_dark_onErrorContainer,
background = md_theme_dark_background,
onBackground = md_theme_dark_onBackground,
surface = md_theme_dark_surface,
onSurface = md_theme_dark_onSurface,
surfaceVariant = md_theme_dark_surfaceVariant,
onSurfaceVariant = md_theme_dark_onSurfaceVariant,
outline = md_theme_dark_outline,
inverseOnSurface = md_theme_dark_inverseOnSurface,
inverseSurface = md_theme_dark_inverseSurface,
inversePrimary = md_theme_dark_inversePrimary,
surfaceTint = md_theme_dark_surfaceTint,
outlineVariant = md_theme_dark_outlineVariant,
scrim = md_theme_dark_scrim
private val lightScheme = lightColorScheme(
primary = primaryLight,
onPrimary = onPrimaryLight,
primaryContainer = primaryContainerLight,
onPrimaryContainer = onPrimaryContainerLight,
secondary = secondaryLight,
onSecondary = onSecondaryLight,
secondaryContainer = secondaryContainerLight,
onSecondaryContainer = onSecondaryContainerLight,
tertiary = tertiaryLight,
onTertiary = onTertiaryLight,
tertiaryContainer = tertiaryContainerLight,
onTertiaryContainer = onTertiaryContainerLight,
error = errorLight,
onError = onErrorLight,
errorContainer = errorContainerLight,
onErrorContainer = onErrorContainerLight,
background = backgroundLight,
onBackground = onBackgroundLight,
surface = surfaceLight,
onSurface = onSurfaceLight,
surfaceVariant = surfaceVariantLight,
onSurfaceVariant = onSurfaceVariantLight,
outline = outlineLight,
outlineVariant = outlineVariantLight,
scrim = scrimLight,
inverseSurface = inverseSurfaceLight,
inverseOnSurface = inverseOnSurfaceLight,
inversePrimary = inversePrimaryLight,
surfaceDim = surfaceDimLight,
surfaceBright = surfaceBrightLight,
surfaceContainerLowest = surfaceContainerLowestLight,
surfaceContainerLow = surfaceContainerLowLight,
surfaceContainer = surfaceContainerLight,
surfaceContainerHigh = surfaceContainerHighLight,
surfaceContainerHighest = surfaceContainerHighestLight,
)
private val LightColorScheme = lightColorScheme(
primary = md_theme_light_primary,
onPrimary = md_theme_light_onPrimary,
primaryContainer = md_theme_light_primaryContainer,
onPrimaryContainer = md_theme_light_onPrimaryContainer,
secondary = md_theme_light_secondary,
onSecondary = md_theme_light_onSecondary,
secondaryContainer = md_theme_light_secondaryContainer,
onSecondaryContainer = md_theme_light_onSecondaryContainer,
tertiary = md_theme_light_tertiary,
onTertiary = md_theme_light_onTertiary,
tertiaryContainer = md_theme_light_tertiaryContainer,
onTertiaryContainer = md_theme_light_onTertiaryContainer,
error = md_theme_light_error,
errorContainer = md_theme_light_errorContainer,
onError = md_theme_light_onError,
onErrorContainer = md_theme_light_onErrorContainer,
background = md_theme_light_background,
onBackground = md_theme_light_onBackground,
surface = md_theme_light_surface,
onSurface = md_theme_light_onSurface,
surfaceVariant = md_theme_light_surfaceVariant,
onSurfaceVariant = md_theme_light_onSurfaceVariant,
outline = md_theme_light_outline,
inverseOnSurface = md_theme_light_inverseOnSurface,
inverseSurface = md_theme_light_inverseSurface,
inversePrimary = md_theme_light_inversePrimary,
surfaceTint = md_theme_light_surfaceTint,
outlineVariant = md_theme_light_outlineVariant,
scrim = md_theme_light_scrim
private val darkScheme = darkColorScheme(
primary = primaryDark,
onPrimary = onPrimaryDark,
primaryContainer = primaryContainerDark,
onPrimaryContainer = onPrimaryContainerDark,
secondary = secondaryDark,
onSecondary = onSecondaryDark,
secondaryContainer = secondaryContainerDark,
onSecondaryContainer = onSecondaryContainerDark,
tertiary = tertiaryDark,
onTertiary = onTertiaryDark,
tertiaryContainer = tertiaryContainerDark,
onTertiaryContainer = onTertiaryContainerDark,
error = errorDark,
onError = onErrorDark,
errorContainer = errorContainerDark,
onErrorContainer = onErrorContainerDark,
background = backgroundDark,
onBackground = onBackgroundDark,
surface = surfaceDark,
onSurface = onSurfaceDark,
surfaceVariant = surfaceVariantDark,
onSurfaceVariant = onSurfaceVariantDark,
outline = outlineDark,
outlineVariant = outlineVariantDark,
scrim = scrimDark,
inverseSurface = inverseSurfaceDark,
inverseOnSurface = inverseOnSurfaceDark,
inversePrimary = inversePrimaryDark,
surfaceDim = surfaceDimDark,
surfaceBright = surfaceBrightDark,
surfaceContainerLowest = surfaceContainerLowestDark,
surfaceContainerLow = surfaceContainerLowDark,
surfaceContainer = surfaceContainerDark,
surfaceContainerHigh = surfaceContainerHighDark,
surfaceContainerHighest = surfaceContainerHighestDark,
)
@Composable
fun OwnDroidTheme(
materialYou: Boolean,
blackTheme: Boolean,
vm: MyViewModel,
content: @Composable () -> Unit
) {
val darkTheme = isSystemInDarkTheme()
val theme by vm.theme.collectAsStateWithLifecycle()
val darkTheme = theme.darkTheme == true || (theme.darkTheme == null && isSystemInDarkTheme())
val context = LocalContext.current
val sharedPref = context.getSharedPreferences("data", Context.MODE_PRIVATE)
if(!sharedPref.contains("dynamicColor") && VERSION.SDK_INT >= 32) {
sharedPref.edit().putBoolean("dynamicColor", true).apply()
}
var colorScheme = when {
materialYou && VERSION.SDK_INT>=31 -> {
theme.materialYou && VERSION.SDK_INT >= 31 -> {
if(darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
darkTheme -> darkScheme
else -> lightScheme
}
if(darkTheme&&blackTheme) {
if(darkTheme && theme.blackTheme) {
colorScheme = colorScheme.copy(background = Color.Black)
}
if(!darkTheme) {
@@ -108,7 +118,6 @@ fun OwnDroidTheme(
window.statusBarColor = Color.Transparent.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,