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

@@ -76,6 +76,7 @@ gradle.taskGraph.whenReady {
dependencies {
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.accompanist.drawablepainter)
implementation(libs.androidx.material3)
implementation(libs.androidx.navigation.compose)

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

@@ -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,11 +332,11 @@ 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"))
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))
@@ -343,56 +344,34 @@ private fun WifiSsidPolicy() {
value = inputSsid,
label = { Text("SSID") },
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()
dpm.wifiSsidPolicy = if(selectedPolicyType == -1 || ssidList.isEmpty()) {
null
} else {
dpm.wifiSsidPolicy = if(ssidList.isEmpty()) { null }else{ WifiSsidPolicy(selectedPolicyType, ssidList.toSet()) }
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,

View File

@@ -38,7 +38,6 @@
<string name="decide_by_user">Определять пользователем</string>
<string name="unsupported">Не поддерживается</string>
<string name="developing">Разрабатываемая функция</string>
<string name="unknown_effect">Неизвестный эффект</string>
<string name="options">Опции</string>
<string name="copy_command">Копировать команду</string>
<string name="package_name">Имя пакета</string>
@@ -58,6 +57,8 @@
<string name="no">Нет</string>
<string name="previous">Предыдущий</string>
<string name="next">Следующий</string>
<string name="on">On</string> <!--TODO-->
<string name="off">Off</string> <!--TODO-->
<!--Разрешения-->
@@ -222,7 +223,6 @@
<string name="lockdown_admin_configured_network">Блокировка ети, настроенной администратором</string>
<string name="wifi_ssid_policy">Политика SSID Wi-Fi</string>
<string name="ssid_list_is">Список SSID:</string>
<string name="cannot_be_empty">Не может быть пустым</string>
<string name="already_exist">Уже существует</string>
<string name="private_dns">Частный DNS</string>
<string name="dns_provide_hostname">Укажите имя хоста</string>
@@ -330,7 +330,6 @@
<string name="ucd">Отключить управление пользователем</string>
<string name="ucd_desc">Если вы установите этот флажок, вы не сможете очистить хранилище этих приложений или принудительно остановить их.</string>
<string name="app_list_is">Список приложений:</string>
<string name="clear_list">Очистить список</string>
<string name="permission_manage">Управление разрешениями</string>
<string name="cross_profile_package">Кросс-профильный пакет</string>
<string name="cross_profile_widget">Кросс-профильный виджет</string>
@@ -469,8 +468,6 @@
<string name="logout_current_user">Выйти из текущего пользователя</string>
<string name="start_in_background">Запустить в фоновом режиме</string>
<string name="user_operation_switch">Переключиться</string>
<string name="user_operation_stop">Остановить</string>
<string name="user_operation_remove">Удалить</string>
<string name="create_user">Создать пользователя</string>
<string name="username">Имя пользователя</string>
<string name="create_user_skip_wizard">Пропустить мастер настройки</string>
@@ -478,7 +475,6 @@
<string name="create_user_enable_all_system_app">Включить все системные приложения</string>
<string name="serial_number_of_new_user_is">Серийный номер этого пользователя: %1$s</string>
<string name="affiliation_id">Идентификатор принадлежности</string>
<string name="include_empty_string">Включая пустую строку</string>
<string name="change_user_icon">Изменить значок пользователя</string>
<string name="file_picker_instead_gallery">Использовать выборщик файлов вместо галереи</string>
<string name="select_picture" tools:ignore="TypographyEllipsis">Выберите изображение...</string>
@@ -552,13 +548,13 @@
<string name="setting">Настройки</string>
<string name="show_dangerous_features">Показывать опасные функции</string>
<string name="material_you_color">Цвет Material You</string>
<string name="dynamic_color_desc">Android 12+</string>
<string name="dark_theme">Dark theme</string> <!--TODO-->
<string name="follow_system">Follow system</string> <!--TODO-->
<string name="black_theme">Black theme</string> <!--TODO-->
<string name="about">О приложении</string>
<string name="user_guide">Руководство пользователя</string>
<string name="source_code">Исходный код</string>
<string name="theme">Тема</string>
<string name="amoled_black">Черная тема</string>
<string name="blackTheme_desc">Требуется включенный темный режим</string>
<string name="security">Безопасность</string>
<string name="lock_owndroid">Заблокировать OwnDroid</string>

View File

@@ -39,7 +39,6 @@
<string name="decide_by_user">Kullanıcı Tarafından Karar Ver</string>
<string name="unsupported">Desteklenmiyor</string>
<string name="developing">Geliştirilen İşlev</string>
<string name="unknown_effect">Bilinmeyen Etki</string>
<string name="options">Seçenekler</string>
<string name="copy_command">Komutu Kopyala</string>
<string name="package_name">Paket Adı</string>
@@ -59,6 +58,8 @@
<string name="no">No</string> <!--TODO-->
<string name="previous">Previous</string> <!--TODO-->
<string name="next">Next</string> <!--TODO-->
<string name="on">On</string> <!--TODO-->
<string name="off">Off</string> <!--TODO-->
<!--Permissions-->
<string name="click_to_activate">Etkinleştirmek İçin Tıklayın</string>
@@ -223,7 +224,6 @@
<string name="lockdown_admin_configured_network">Yönetici tarafından yapılandırılmış ağı kilitle</string>
<string name="wifi_ssid_policy">WiFi SSID politikası</string>
<string name="ssid_list_is">SSID listesi:</string>
<string name="cannot_be_empty">Boş olamaz</string>
<string name="already_exist">Zaten mevcut</string>
<string name="private_dns">Özel DNS</string>
<string name="dns_provide_hostname">Ana bilgisayar adı sağlayın</string>
@@ -329,7 +329,6 @@
<string name="ucd">Kullanıcı kontrolünü devre dışı bırak</string>
<string name="ucd_desc">Bunu ayarlarsanız, bu uygulamaların depolama alanını temizleyemez veya zorla durduramazsınız. </string>
<string name="app_list_is">Uygulama listesi:</string>
<string name="clear_list">Listeyi temizle</string>
<string name="permission_manage">İzin yönetimi</string>
<string name="cross_profile_package">Profil geçişli paket</string>
<string name="cross_profile_widget">Profil geçişli widget</string>
@@ -467,8 +466,6 @@
<string name="logout_current_user">Mevcut kullanıcıyı çıkış yap</string>
<string name="start_in_background">Arka planda başlat</string>
<string name="user_operation_switch">Değiştir</string>
<string name="user_operation_stop">Durdur</string>
<string name="user_operation_remove">Kaldır</string>
<string name="create_user">Kullanıcı oluştur</string>
<string name="username">Kullanıcı adı</string>
<string name="create_user_skip_wizard">Sihirbazı atla</string>
@@ -476,7 +473,6 @@
<string name="create_user_enable_all_system_app">Tüm sistem uygulamalarını etkinleştir</string>
<string name="serial_number_of_new_user_is">Bu kullanıcının seri numarası: %1$s</string>
<string name="affiliation_id">Bağlılık ID</string>
<string name="include_empty_string">Boş string dahil et</string>
<string name="change_user_icon">Kullanıcı simgesini değiştir</string>
<string name="file_picker_instead_gallery">Galeri yerine dosya seçici kullan</string>
<string name="select_picture" tools:ignore="TypographyEllipsis">Resim seç...</string>
@@ -547,13 +543,13 @@
<string name="setting">Ayarlar</string>
<string name="show_dangerous_features">Show dangerous features</string> <!--TODO-->
<string name="material_you_color">Material You rengi</string>
<string name="dynamic_color_desc">Android 12+</string>
<string name="dark_theme">Dark theme</string> <!--TODO-->
<string name="follow_system">Follow system</string> <!--TODO-->
<string name="black_theme">Black theme</string> <!--TODO-->
<string name="about">Hakkında</string>
<string name="user_guide">Kullanıcı rehberi</string>
<string name="source_code">Kaynak kodu</string>
<string name="theme">Tema</string>
<string name="amoled_black">Siyah tema</string>
<string name="blackTheme_desc">Karanlık modun açık olmasını gerektirir</string>
<string name="security">Güvenlik</string>
<string name="lock_owndroid">OwnDroid\'u kilitle</string>

View File

@@ -38,7 +38,6 @@
<string name="decide_by_user">由用户决定</string>
<string name="unsupported">不支持</string>
<string name="developing">功能开发中</string>
<string name="unknown_effect">效果未知</string>
<string name="options">选项</string>
<string name="copy_command">复制代码</string>
<string name="unknown_status">未知状态</string>
@@ -56,6 +55,8 @@
<string name="no"></string>
<string name="previous">上一个</string>
<string name="next">下一个</string>
<string name="on">开启</string>
<string name="off">关闭</string>
<!--Permissions-->
<string name="click_to_activate">点击以激活</string>
@@ -218,7 +219,6 @@
<string name="lockdown_admin_configured_network">锁定由管理员配置的网络</string>
<string name="wifi_ssid_policy">WiFi SSID策略</string>
<string name="ssid_list_is">SSID列表</string>
<string name="cannot_be_empty">不能为空</string>
<string name="already_exist">已经存在</string>
<string name="private_dns">私人DNS</string>
<string name="dns_provide_hostname">指定主机名</string>
@@ -320,7 +320,6 @@
<string name="ucd">禁止用户控制</string>
<string name="ucd_desc">用户将无法清除这些应用的存储空间或强制停止这些应用</string>
<string name="app_list_is">应用列表:</string>
<string name="clear_list">清空列表</string>
<string name="permission_manage">权限管理</string>
<string name="cross_profile_package">跨资料应用</string>
<string name="cross_profile_widget">跨资料微件</string>
@@ -459,8 +458,6 @@
<string name="logout_current_user">登出当前用户</string>
<string name="start_in_background">在后台启动</string>
<string name="user_operation_switch">切换</string>
<string name="user_operation_stop">停止</string>
<string name="user_operation_remove">移除</string>
<string name="create_user">创建用户</string>
<string name="username">用户名</string>
<string name="create_user_skip_wizard">跳过创建用户向导</string>
@@ -468,7 +465,6 @@
<string name="create_user_enable_all_system_app">启用所有系统应用</string>
<string name="serial_number_of_new_user_is">新用户的序列号:%1$s</string>
<string name="affiliation_id">附属用户ID</string>
<string name="include_empty_string">有空字符串</string>
<string name="change_user_icon">更换用户头像</string>
<string name="file_picker_instead_gallery">使用文件选择器而不是相册</string>
<string name="select_picture" tools:ignore="TypographyEllipsis">选择图片...</string>
@@ -539,13 +535,13 @@
<string name="setting">设置</string>
<string name="show_dangerous_features">显示危险功能</string>
<string name="material_you_color">Material you 颜色</string>
<string name="dynamic_color_desc">安卓12+</string>
<string name="dark_theme">深色主题</string>
<string name="follow_system">跟随系统</string>
<string name="black_theme">黑色主题</string>
<string name="about">关于</string>
<string name="user_guide">使用教程</string>
<string name="source_code">源代码</string>
<string name="theme">主题</string>
<string name="amoled_black">纯黑夜间主题</string>
<string name="blackTheme_desc">需要打开夜间模式</string>
<string name="security">安全</string>
<string name="lock_owndroid">锁定OwnDroid</string>

View File

@@ -39,7 +39,6 @@
<string name="decide_by_user">Decide by user</string>
<string name="unsupported">Unsupported</string>
<string name="developing">Developing function</string>
<string name="unknown_effect">Unknown effect</string>
<string name="options">Options</string>
<string name="copy_command">Copy Command</string>
<string name="package_name">Package name</string>
@@ -59,6 +58,8 @@
<string name="no">No</string>
<string name="previous">Previous</string>
<string name="next">Next</string>
<string name="on">On</string>
<string name="off">Off</string>
<!--Permissions-->
<string name="click_to_activate">Click to activate</string>
@@ -227,7 +228,6 @@
<string name="lockdown_admin_configured_network">Lockdown admin configured network</string>
<string name="wifi_ssid_policy">WiFi SSID policy</string>
<string name="ssid_list_is">SSID list:</string>
<string name="cannot_be_empty">Cannot be empty</string>
<string name="already_exist">Already exist</string>
<string name="private_dns">Private DNS</string>
<string name="dns_provide_hostname">Provide hostname</string>
@@ -335,7 +335,6 @@
<string name="ucd">Disable user control</string>
<string name="ucd_desc">If you set this, you cannot clear these apps\' storage or force stop them. </string>
<string name="app_list_is">App list:</string>
<string name="clear_list">Clear list</string>
<string name="permission_manage">Permission manage</string>
<string name="cross_profile_package">Cross profile package</string>
<string name="cross_profile_widget">Cross profile widget</string>
@@ -472,8 +471,6 @@
<string name="logout_current_user">Logout current user</string>
<string name="start_in_background">Start in background</string>
<string name="user_operation_switch">Switch</string>
<string name="user_operation_stop">Stop</string>
<string name="user_operation_remove">Remove</string>
<string name="create_user">Create user</string>
<string name="username">Username</string>
<string name="create_user_skip_wizard">Skip wizard</string>
@@ -481,7 +478,6 @@
<string name="create_user_enable_all_system_app">Enable all system app</string>
<string name="serial_number_of_new_user_is">Serial number of this user: %1$s</string>
<string name="affiliation_id">Affiliation ID</string>
<string name="include_empty_string">Include empty string</string>
<string name="change_user_icon">Change user icon</string>
<string name="file_picker_instead_gallery">Use file picker instead of gallery</string>
<string name="select_picture" tools:ignore="TypographyEllipsis">Select image...</string>
@@ -552,13 +548,13 @@
<string name="setting">Settings</string>
<string name="show_dangerous_features">Show dangerous features</string>
<string name="material_you_color">Material you color</string>
<string name="dynamic_color_desc">Android 12+</string>
<string name="dark_theme">Dark theme</string>
<string name="follow_system">Follow system</string>
<string name="black_theme">Black theme</string>
<string name="about">About</string>
<string name="user_guide">User guide</string>
<string name="source_code">Source code</string>
<string name="theme">Theme</string>
<string name="amoled_black">Black theme</string>
<string name="blackTheme_desc">Require dark mode on</string>
<string name="security">Security</string>
<string name="lock_owndroid">Lock OwnDroid</string>

View File

@@ -2,20 +2,20 @@
agp = "8.7.2"
kotlin = "2.0.21"
androidx-activity-compose = "1.9.0"
navigation-compose = "2.7.7"
material3 = "1.2.1"
navigation-compose = "2.8.3"
composeBom = "2024.10.01"
accompanist-drawablepainter = "0.35.0-alpha"
shizuku = "13.1.5"
biometric = "1.2.0-alpha05"
fragment = "1.8.0-beta01"
dhizuku = "2.5.2"
hiddenApiBypass = "4.3"
serialization = "1.7.1"
serialization = "1.7.3"
[libraries]
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity-compose" }
androidx-material3 = { module = "androidx.compose.material3:material3", version.ref = "material3" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-activity-compose = { module = "androidx.activity:activity-compose" }
androidx-material3 = { module = "androidx.compose.material3:material3" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigation-compose" }
accompanist-drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version.ref = "accompanist-drawablepainter" }