Skip to content

Commit

Permalink
Merge pull request #24 from Myzel394/add-theme-selsection
Browse files Browse the repository at this point in the history
Add theme selection
  • Loading branch information
Myzel394 authored Oct 22, 2023
2 parents 46dfee9 + c994a47 commit 3345ee6
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 9 deletions.
23 changes: 23 additions & 0 deletions app/src/main/java/app/myzel394/alibi/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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()
}
Expand Down
28 changes: 20 additions & 8 deletions app/src/main/java/app/myzel394/alibi/db/AppSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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()
}
Expand Down Expand Up @@ -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
Expand All @@ -167,18 +178,20 @@ data class AudioRecorderSettings(
MediaRecorder.OutputFormat.AAC_ADTS
}
}

MediaRecorder.AudioEncoder.OPUS -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaRecorder.OutputFormat.OGG
} else {
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"
Expand All @@ -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
Expand All @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/app/myzel394/alibi/ui/Constants.kt
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Mic
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
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(
modifier: Modifier = Modifier,
backgroundColor: Color,
primaryColor: Color,
textColor: Color,
onSelect: () -> Unit,
isSelected: Boolean = false,
) {
Box(
modifier = modifier,
contentAlignment = Alignment.Center,
) {
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
.size(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 {}
}
if (isSelected) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxSize(),
) {
Icon(
Icons.Default.CheckCircle,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier
.size(30.dp),
)
}
}
}
}

@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(
modifier = Modifier
.fillMaxWidth()
.weight(1f),
backgroundColor = Color(0xFFF0F0F0),
primaryColor = Color(0xFFAAAAAA),
textColor = Color(0xFFCCCCCC),
onSelect = {
scope.launch {
dataStore.updateData {
it.setTheme(AppSettings.Theme.LIGHT)
}
}
},
isSelected = settings.theme == AppSettings.Theme.LIGHT,
)
Preview(
modifier = Modifier
.fillMaxWidth()
.weight(1f),
backgroundColor = Color(0xFF444444),
primaryColor = Color(0xFF888888),
textColor = Color(0xFF606060),
onSelect = {
scope.launch {
dataStore.updateData {
it.setTheme(AppSettings.Theme.DARK)
}
}
},
isSelected = settings.theme == AppSettings.Theme.DARK,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -80,7 +82,7 @@ fun SettingsScreen(
},
modifier = Modifier
.nestedScroll(scrollBehavior.nestedScrollConnection)
) {padding ->
) { padding ->
Column(
modifier = Modifier
.fillMaxSize()
Expand All @@ -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,
Expand Down

0 comments on commit 3345ee6

Please sign in to comment.