feat: Add support for old theme selection

This commit is contained in:
Myzel394 2023-10-22 14:40:57 +02:00
parent 46dfee9467
commit 0fb341ffb9
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
5 changed files with 191 additions and 9 deletions

View File

@ -6,10 +6,15 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.platform.LocalContext
import androidx.core.view.WindowCompat
import androidx.datastore.dataStore
import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.db.AppSettingsSerializer
import app.myzel394.alibi.ui.Navigation
import app.myzel394.alibi.ui.SUPPORTS_DARK_MODE_NATIVELY
import app.myzel394.alibi.ui.theme.AlibiTheme
const val SETTINGS_FILE = "settings.json"
@ -25,6 +30,24 @@ class MainActivity : AppCompatActivity() {
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
val dataStore = LocalContext.current.dataStore
val settings = dataStore
.data
.collectAsState(initial = AppSettings.getDefaultInstance())
.value
LaunchedEffect(settings.theme) {
if (!SUPPORTS_DARK_MODE_NATIVELY) {
val currentValue = AppCompatDelegate.getDefaultNightMode()
if (settings.theme == AppSettings.Theme.LIGHT && currentValue != AppCompatDelegate.MODE_NIGHT_NO) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
} else if (settings.theme == AppSettings.Theme.DARK && currentValue != AppCompatDelegate.MODE_NIGHT_YES) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
}
}
AlibiTheme {
Navigation()
}

View File

@ -16,6 +16,7 @@ data class AppSettings(
val audioRecorderSettings: AudioRecorderSettings = AudioRecorderSettings(),
val hasSeenOnboarding: Boolean = false,
val showAdvancedSettings: Boolean = false,
val theme: Theme = Theme.SYSTEM,
) {
fun setShowAdvancedSettings(showAdvancedSettings: Boolean): AppSettings {
return copy(showAdvancedSettings = showAdvancedSettings)
@ -29,6 +30,16 @@ data class AppSettings(
return copy(hasSeenOnboarding = hasSeenOnboarding)
}
fun setTheme(theme: Theme): AppSettings {
return copy(theme = theme)
}
enum class Theme {
SYSTEM,
LIGHT,
DARK,
}
companion object {
fun getDefaultInstance(): AppSettings = AppSettings()
}
@ -154,7 +165,7 @@ data class AudioRecorderSettings(
else MediaRecorder.OutputFormat.THREE_GPP
}
return when(encoder) {
return when (encoder) {
MediaRecorder.AudioEncoder.AAC -> MediaRecorder.OutputFormat.AAC_ADTS
MediaRecorder.AudioEncoder.AAC_ELD -> MediaRecorder.OutputFormat.AAC_ADTS
MediaRecorder.AudioEncoder.AMR_NB -> MediaRecorder.OutputFormat.AMR_NB
@ -167,6 +178,7 @@ data class AudioRecorderSettings(
MediaRecorder.OutputFormat.AAC_ADTS
}
}
MediaRecorder.AudioEncoder.OPUS -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaRecorder.OutputFormat.OGG
@ -174,11 +186,12 @@ data class AudioRecorderSettings(
MediaRecorder.OutputFormat.AAC_ADTS
}
}
else -> MediaRecorder.OutputFormat.DEFAULT
}
}
fun getMimeType(): String = when(getOutputFormat()) {
fun getMimeType(): String = when (getOutputFormat()) {
MediaRecorder.OutputFormat.AAC_ADTS -> "audio/aac"
MediaRecorder.OutputFormat.THREE_GPP -> "audio/3gpp"
MediaRecorder.OutputFormat.MPEG_4 -> "audio/mp4"
@ -190,7 +203,7 @@ data class AudioRecorderSettings(
else -> "audio/3gpp"
}
fun getSamplingRate(): Int = samplingRate ?: when(getOutputFormat()) {
fun getSamplingRate(): Int = samplingRate ?: when (getOutputFormat()) {
MediaRecorder.OutputFormat.AAC_ADTS -> 96000
MediaRecorder.OutputFormat.THREE_GPP -> 44100
MediaRecorder.OutputFormat.MPEG_4 -> 44100
@ -202,11 +215,10 @@ data class AudioRecorderSettings(
else -> 48000
}
fun getEncoder(): Int = encoder ?:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
MediaRecorder.AudioEncoder.AAC
else
MediaRecorder.AudioEncoder.AMR_NB
fun getEncoder(): Int = encoder ?: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
MediaRecorder.AudioEncoder.AAC
else
MediaRecorder.AudioEncoder.AMR_NB
fun setIntervalDuration(duration: Long): AudioRecorderSettings {
if (duration < 10 * 1000L || duration > 60 * 60 * 1000L) {

View File

@ -1,6 +1,8 @@
package app.myzel394.alibi.ui
import android.os.Build
import androidx.compose.ui.unit.dp
val BIG_PRIMARY_BUTTON_SIZE = 64.dp
val MAX_AMPLITUDE = 20000
val SUPPORTS_DARK_MODE_NATIVELY = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q

View File

@ -0,0 +1,140 @@
package app.myzel394.alibi.ui.components.SettingsScreen.atoms
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Mic
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.navigation.navOptions
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.db.AppSettings
import kotlinx.coroutines.launch
@Composable
fun Preview(
backgroundColor: Color,
primaryColor: Color,
textColor: Color,
onSelect: () -> Unit,
) {
Column(
modifier = Modifier
.width(100.dp)
.height(200.dp)
.clip(shape = RoundedCornerShape(10.dp))
.border(width = 1.dp, color = textColor, shape = RoundedCornerShape(10.dp))
.background(backgroundColor)
.clickable { onSelect() },
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceBetween,
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.fillMaxWidth()
.padding(10.dp)
) {
Box(
modifier = Modifier
.width(30.dp)
.height(10.dp)
.clip(shape = RoundedCornerShape(10.dp))
.background(primaryColor)
)
Box(
modifier = Modifier
.width(10.dp)
.height(10.dp)
.clip(shape = RoundedCornerShape(10.dp))
.background(primaryColor)
)
}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(12.dp),
) {
Icon(
Icons.Default.Mic,
contentDescription = null,
tint = primaryColor,
)
Box(
modifier = Modifier
.width(40.dp)
.height(6.dp)
.clip(shape = RoundedCornerShape(10.dp))
.background(primaryColor)
)
Box(
modifier = Modifier
.width(75.dp)
.height(10.dp)
.clip(shape = RoundedCornerShape(10.dp))
.background(textColor)
)
}
Box {}
}
}
@Composable
fun ThemeSelector() {
val scope = rememberCoroutineScope()
val dataStore = LocalContext.current.dataStore
val settings = dataStore
.data
.collectAsState(initial = AppSettings.getDefaultInstance())
.value
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Preview(
backgroundColor = Color(0xFFF0F0F0),
primaryColor = Color(0xFFAAAAAA),
textColor = Color(0xFFCCCCCC),
onSelect = {
scope.launch {
dataStore.updateData {
it.setTheme(AppSettings.Theme.LIGHT)
}
}
}
)
Preview(
backgroundColor = Color(0xFF444444),
primaryColor = Color(0xFF888888),
textColor = Color(0xFF606060),
onSelect = {
scope.launch {
dataStore.updateData {
it.setTheme(AppSettings.Theme.DARK)
}
}
}
)
}
}

View File

@ -35,6 +35,7 @@ import androidx.navigation.NavController
import app.myzel394.alibi.R
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.ui.SUPPORTS_DARK_MODE_NATIVELY
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.BitrateTile
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.EncoderTile
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.ForceExactMaxDurationTile
@ -43,6 +44,7 @@ import app.myzel394.alibi.ui.components.SettingsScreen.atoms.IntervalDurationTil
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.MaxDurationTile
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.OutputFormatTile
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.SamplingRateTile
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.ThemeSelector
import app.myzel394.alibi.ui.components.atoms.GlobalSwitch
import app.myzel394.alibi.ui.components.atoms.MessageBox
import app.myzel394.alibi.ui.components.atoms.MessageType
@ -80,7 +82,7 @@ fun SettingsScreen(
},
modifier = Modifier
.nestedScroll(scrollBehavior.nestedScrollConnection)
) {padding ->
) { padding ->
Column(
modifier = Modifier
.fillMaxSize()
@ -107,6 +109,9 @@ fun SettingsScreen(
message = stringResource(R.string.ui_settings_hint_recordingActive_message),
)
}
if (!SUPPORTS_DARK_MODE_NATIVELY) {
ThemeSelector()
}
GlobalSwitch(
label = stringResource(R.string.ui_settings_advancedSettings_label),
checked = settings.showAdvancedSettings,