dolby: Redesign dolby interface
Signed-off-by: Ghosuto <clash.raja10@gmail.com>
This commit is contained in:
committed by
pabloescobar-reborn
parent
5c91dcd7c9
commit
9bba67c6bb
@@ -18,7 +18,7 @@
|
||||
<string name="dolby_max">Max</string>
|
||||
<string name="dolby_unknown">Unknown</string>
|
||||
<string name="dolby_on_with_profile">On (%1$s)</string>
|
||||
<string name="dolby_category_settings">Settings</string>
|
||||
<string name="dolby_category_settings">Audio tuning</string>
|
||||
<string name="dolby_category_adv_settings">Advanced settings</string>
|
||||
<string name="dolby_adv_settings_footer">Choose a different profile to show advanced settings.</string>
|
||||
<string name="dolby_bass_enhancer">Bass enhancer</string>
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
|
||||
package org.lunaris.dolby.ui.components
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.gestures.detectDragGestures
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
@@ -16,29 +18,47 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Path
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import org.lunaris.dolby.domain.models.BandGain
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.pow
|
||||
|
||||
@Composable
|
||||
fun InteractiveFrequencyResponseCurve(
|
||||
bandGains: List<BandGain>,
|
||||
onBandGainChange: (index: Int, newGain: Int) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
modifier: Modifier = Modifier,
|
||||
isActive: Boolean = false
|
||||
) {
|
||||
val primaryColor = MaterialTheme.colorScheme.primary
|
||||
val surfaceColor = MaterialTheme.colorScheme.surfaceVariant
|
||||
val onSurfaceColor = MaterialTheme.colorScheme.onSurface
|
||||
val secondaryColor = MaterialTheme.colorScheme.secondary
|
||||
val primaryContainerColor = MaterialTheme.colorScheme.primaryContainer
|
||||
|
||||
val backgroundColor = if (isActive) {
|
||||
primaryContainerColor
|
||||
} else {
|
||||
surfaceColor.copy(alpha = 0.2f)
|
||||
}
|
||||
|
||||
val borderColor = if (isActive) {
|
||||
primaryColor
|
||||
} else {
|
||||
Color.Transparent
|
||||
}
|
||||
|
||||
val borderWidth = if (isActive) 2.dp else 0.dp
|
||||
|
||||
var draggedIndex by remember { mutableStateOf<Int?>(null) }
|
||||
|
||||
@@ -58,7 +78,13 @@ fun InteractiveFrequencyResponseCurve(
|
||||
Canvas(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(surfaceColor.copy(alpha = 0.2f))
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(backgroundColor)
|
||||
.border(
|
||||
width = borderWidth,
|
||||
color = borderColor,
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
)
|
||||
.pointerInput(Unit) {
|
||||
detectDragGestures(
|
||||
onDragStart = { offset ->
|
||||
@@ -111,8 +137,20 @@ fun InteractiveFrequencyResponseCurve(
|
||||
val height = size.height
|
||||
val centerY = height / 2
|
||||
|
||||
val gridColor = if (isActive) {
|
||||
surfaceColor.copy(alpha = 0.4f)
|
||||
} else {
|
||||
surfaceColor
|
||||
}
|
||||
|
||||
val gridVerticalColor = if (isActive) {
|
||||
surfaceColor.copy(alpha = 0.3f)
|
||||
} else {
|
||||
surfaceColor.copy(alpha = 0.2f)
|
||||
}
|
||||
|
||||
drawLine(
|
||||
color = surfaceColor,
|
||||
color = gridColor,
|
||||
start = Offset(0f, centerY),
|
||||
end = Offset(width, centerY),
|
||||
strokeWidth = 2f
|
||||
@@ -121,7 +159,7 @@ fun InteractiveFrequencyResponseCurve(
|
||||
for (i in 1..4) {
|
||||
val y = (height / 5) * i
|
||||
drawLine(
|
||||
color = surfaceColor.copy(alpha = 0.3f),
|
||||
color = gridColor.copy(alpha = 0.3f),
|
||||
start = Offset(0f, y),
|
||||
end = Offset(width, y),
|
||||
strokeWidth = 1f
|
||||
@@ -132,7 +170,7 @@ fun InteractiveFrequencyResponseCurve(
|
||||
bandGains.forEachIndexed { index, _ ->
|
||||
val x = index * stepX
|
||||
drawLine(
|
||||
color = surfaceColor.copy(alpha = 0.2f),
|
||||
color = gridVerticalColor,
|
||||
start = Offset(x, 0f),
|
||||
end = Offset(x, height),
|
||||
strokeWidth = 1f
|
||||
@@ -166,8 +204,8 @@ fun InteractiveFrequencyResponseCurve(
|
||||
|
||||
drawPath(
|
||||
path = path,
|
||||
color = primaryColor,
|
||||
style = Stroke(width = 4f)
|
||||
color = if (isActive) primaryColor else primaryColor.copy(alpha = 0.8f),
|
||||
style = Stroke(width = if (isActive) 5f else 4f)
|
||||
)
|
||||
|
||||
val fillPath = Path().apply {
|
||||
@@ -180,10 +218,17 @@ fun InteractiveFrequencyResponseCurve(
|
||||
drawPath(
|
||||
path = fillPath,
|
||||
brush = Brush.verticalGradient(
|
||||
colors = listOf(
|
||||
primaryColor.copy(alpha = 0.3f),
|
||||
primaryColor.copy(alpha = 0.05f)
|
||||
)
|
||||
colors = if (isActive) {
|
||||
listOf(
|
||||
primaryColor.copy(alpha = 0.4f),
|
||||
primaryColor.copy(alpha = 0.08f)
|
||||
)
|
||||
} else {
|
||||
listOf(
|
||||
primaryColor.copy(alpha = 0.3f),
|
||||
primaryColor.copy(alpha = 0.05f)
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -210,7 +255,7 @@ fun InteractiveFrequencyResponseCurve(
|
||||
)
|
||||
|
||||
drawCircle(
|
||||
color = primaryColor,
|
||||
color = if (isActive) primaryColor else primaryColor.copy(alpha = 0.8f),
|
||||
radius = pointRadius - 2f,
|
||||
center = Offset(x, y)
|
||||
)
|
||||
@@ -233,7 +278,11 @@ fun InteractiveFrequencyResponseCurve(
|
||||
"${bandGain.frequency}"
|
||||
},
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = onSurfaceColor.copy(alpha = 0.7f),
|
||||
color = if (isActive) {
|
||||
onSurfaceColor.copy(alpha = 0.8f)
|
||||
} else {
|
||||
onSurfaceColor.copy(alpha = 0.7f)
|
||||
},
|
||||
fontSize = 10.sp,
|
||||
fontWeight = FontWeight.Medium
|
||||
)
|
||||
@@ -249,7 +298,11 @@ fun InteractiveFrequencyResponseCurve(
|
||||
Text(
|
||||
text = "+15",
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = secondaryColor.copy(alpha = 0.8f),
|
||||
color = if (isActive) {
|
||||
secondaryColor
|
||||
} else {
|
||||
secondaryColor.copy(alpha = 0.8f)
|
||||
},
|
||||
fontSize = 10.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
@@ -257,14 +310,22 @@ fun InteractiveFrequencyResponseCurve(
|
||||
Text(
|
||||
text = "0",
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = secondaryColor.copy(alpha = 0.8f),
|
||||
color = if (isActive) {
|
||||
secondaryColor
|
||||
} else {
|
||||
secondaryColor.copy(alpha = 0.8f)
|
||||
},
|
||||
fontSize = 10.sp,
|
||||
fontWeight = FontWeight.SemiBold
|
||||
)
|
||||
Text(
|
||||
text = "-15",
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = secondaryColor.copy(alpha = 0.8f),
|
||||
color = if (isActive) {
|
||||
secondaryColor
|
||||
} else {
|
||||
secondaryColor.copy(alpha = 0.8f)
|
||||
},
|
||||
fontSize = 10.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
|
||||
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Copyright (C) 2024-2025 Lunaris AOSP
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.lunaris.dolby.ui.screens
|
||||
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import org.lunaris.dolby.R
|
||||
import org.lunaris.dolby.domain.models.DolbyUiState
|
||||
import org.lunaris.dolby.ui.components.*
|
||||
import org.lunaris.dolby.ui.viewmodel.DolbyViewModel
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ModernAdvancedSettingsScreen(
|
||||
viewModel: DolbyViewModel,
|
||||
navController: NavController
|
||||
) {
|
||||
val uiState by viewModel.uiState.collectAsState()
|
||||
val currentRoute by navController.currentBackStackEntryFlow.collectAsState(null)
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
stringResource(R.string.dolby_category_adv_settings),
|
||||
style = MaterialTheme.typography.headlineMedium,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
},
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = MaterialTheme.colorScheme.surface
|
||||
)
|
||||
)
|
||||
},
|
||||
bottomBar = {
|
||||
BottomNavigationBar(
|
||||
currentRoute = currentRoute?.destination?.route ?: Screen.Advanced.route,
|
||||
onNavigate = { route ->
|
||||
if (currentRoute?.destination?.route != route) {
|
||||
navController.navigate(route) {
|
||||
popUpTo(Screen.Settings.route) { saveState = true }
|
||||
launchSingleTop = true
|
||||
restoreState = true
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
when (val state = uiState) {
|
||||
is DolbyUiState.Loading -> {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
is DolbyUiState.Success -> {
|
||||
ModernAdvancedSettingsContent(
|
||||
state = state,
|
||||
viewModel = viewModel,
|
||||
modifier = Modifier.padding(paddingValues)
|
||||
)
|
||||
}
|
||||
is DolbyUiState.Error -> {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Error,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(48.dp),
|
||||
tint = MaterialTheme.colorScheme.error
|
||||
)
|
||||
Text(
|
||||
text = state.message,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.error
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ModernAdvancedSettingsContent(
|
||||
state: DolbyUiState.Success,
|
||||
viewModel: DolbyViewModel,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
if (state.settings.enabled) {
|
||||
item {
|
||||
ModernSettingsCard(
|
||||
title = stringResource(R.string.dolby_category_settings),
|
||||
icon = Icons.Default.Tune
|
||||
) {
|
||||
Column {
|
||||
ModernSettingSwitch(
|
||||
title = stringResource(R.string.dolby_bass_enhancer),
|
||||
subtitle = stringResource(R.string.dolby_bass_enhancer_summary),
|
||||
checked = state.profileSettings.bassLevel > 0,
|
||||
onCheckedChange = { enabled ->
|
||||
if (enabled && state.profileSettings.bassLevel == 0) {
|
||||
viewModel.setBassLevel(50)
|
||||
} else if (!enabled) {
|
||||
viewModel.setBassLevel(0)
|
||||
}
|
||||
},
|
||||
icon = Icons.Default.MusicNote
|
||||
)
|
||||
|
||||
AnimatedVisibility(visible = state.profileSettings.bassLevel > 0) {
|
||||
Column {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
ModernSettingSelector(
|
||||
title = stringResource(R.string.dolby_bass_curve),
|
||||
currentValue = state.profileSettings.bassCurve,
|
||||
entries = R.array.dolby_bass_curve_entries,
|
||||
values = R.array.dolby_bass_curve_values,
|
||||
onValueChange = { viewModel.setBassCurve(it) },
|
||||
icon = Icons.Default.Equalizer
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
ModernSettingSlider(
|
||||
title = stringResource(R.string.dolby_bass_level),
|
||||
value = state.profileSettings.bassLevel,
|
||||
onValueChange = { viewModel.setBassLevel(it.toInt()) },
|
||||
valueRange = 0f..100f,
|
||||
steps = 19,
|
||||
valueLabel = { "$it%" }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
Column {
|
||||
ModernSettingSwitch(
|
||||
title = stringResource(R.string.dolby_treble_enhancer),
|
||||
subtitle = stringResource(R.string.dolby_treble_enhancer_summary),
|
||||
checked = state.profileSettings.trebleLevel > 0,
|
||||
onCheckedChange = { enabled ->
|
||||
if (enabled && state.profileSettings.trebleLevel == 0) {
|
||||
viewModel.setTrebleLevel(30)
|
||||
} else if (!enabled) {
|
||||
viewModel.setTrebleLevel(0)
|
||||
}
|
||||
},
|
||||
icon = Icons.Default.GraphicEq
|
||||
)
|
||||
|
||||
AnimatedVisibility(visible = state.profileSettings.trebleLevel > 0) {
|
||||
Column {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
ModernSettingSlider(
|
||||
title = stringResource(R.string.dolby_treble_level),
|
||||
value = state.profileSettings.trebleLevel,
|
||||
onValueChange = { viewModel.setTrebleLevel(it.toInt()) },
|
||||
valueRange = 0f..100f,
|
||||
steps = 19,
|
||||
valueLabel = { "$it%" }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
ModernSettingSwitch(
|
||||
title = stringResource(R.string.dolby_volume_leveler),
|
||||
subtitle = stringResource(R.string.dolby_volume_leveler_summary),
|
||||
checked = state.settings.volumeLevelerEnabled,
|
||||
onCheckedChange = { viewModel.setVolumeLeveler(it) },
|
||||
icon = Icons.Default.BarChart
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (state.settings.currentProfile != 0) {
|
||||
item {
|
||||
ModernSettingsCard(
|
||||
title = "Surround Virtualizer",
|
||||
icon = Icons.Default.Headphones
|
||||
) {
|
||||
if (state.isOnSpeaker) {
|
||||
ModernSettingSwitch(
|
||||
title = stringResource(R.string.dolby_spk_virtualizer),
|
||||
subtitle = stringResource(R.string.dolby_spk_virtualizer_summary),
|
||||
checked = state.profileSettings.speakerVirtualizerEnabled,
|
||||
onCheckedChange = { viewModel.setSpeakerVirtualizer(it) },
|
||||
icon = Icons.Default.Speaker
|
||||
)
|
||||
} else {
|
||||
ModernSettingSwitch(
|
||||
title = stringResource(R.string.dolby_hp_virtualizer),
|
||||
subtitle = stringResource(R.string.dolby_hp_virtualizer_summary),
|
||||
checked = state.profileSettings.headphoneVirtualizerEnabled,
|
||||
onCheckedChange = { viewModel.setHeadphoneVirtualizer(it) },
|
||||
icon = Icons.Default.Headphones
|
||||
)
|
||||
|
||||
AnimatedVisibility(visible = state.profileSettings.headphoneVirtualizerEnabled) {
|
||||
Column {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
ModernSettingSlider(
|
||||
title = stringResource(R.string.dolby_hp_virtualizer_dolby_strength),
|
||||
value = state.profileSettings.stereoWideningAmount,
|
||||
onValueChange = { viewModel.setStereoWidening(it.toInt()) },
|
||||
valueRange = 4f..64f,
|
||||
steps = 59
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
ModernSettingsCard(
|
||||
title = "Dialogue Enhancement",
|
||||
icon = Icons.Default.RecordVoiceOver
|
||||
) {
|
||||
ModernSettingSwitch(
|
||||
title = stringResource(R.string.dolby_dialogue_enhancer),
|
||||
subtitle = stringResource(R.string.dolby_dialogue_enhancer_summary),
|
||||
checked = state.profileSettings.dialogueEnhancerEnabled,
|
||||
onCheckedChange = { viewModel.setDialogueEnhancer(it) },
|
||||
icon = Icons.Default.RecordVoiceOver
|
||||
)
|
||||
|
||||
AnimatedVisibility(visible = state.profileSettings.dialogueEnhancerEnabled) {
|
||||
Column {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
ModernSettingSlider(
|
||||
title = stringResource(R.string.dolby_dialogue_enhancer_dolby_strength),
|
||||
value = state.profileSettings.dialogueEnhancerAmount,
|
||||
onValueChange = { viewModel.setDialogueEnhancerAmount(it.toInt()) },
|
||||
valueRange = 1f..12f,
|
||||
steps = 10
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (state.settings.currentProfile == 0 && state.settings.enabled) {
|
||||
item {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
color = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.5f)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Info,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.dolby_adv_settings_footer),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSecondaryContainer
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!state.settings.enabled) {
|
||||
item {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
color = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.5f)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Info,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(
|
||||
text = "Enable Dolby Atmos to access advanced settings",
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSecondaryContainer
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(80.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BottomNavigationBar(
|
||||
currentRoute: String,
|
||||
onNavigate: (String) -> Unit
|
||||
) {
|
||||
NavigationBar(
|
||||
containerColor = MaterialTheme.colorScheme.surfaceContainer,
|
||||
tonalElevation = 3.dp
|
||||
) {
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
Icon(
|
||||
Icons.Default.Home,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text("Home") },
|
||||
selected = currentRoute == Screen.Settings.route,
|
||||
onClick = { onNavigate(Screen.Settings.route) }
|
||||
)
|
||||
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
AnimatedEqualizerIconDynamic(
|
||||
color = if (currentRoute == Screen.Equalizer.route) {
|
||||
MaterialTheme.colorScheme.primary
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onSurfaceVariant
|
||||
},
|
||||
size = 24.dp
|
||||
)
|
||||
},
|
||||
label = { Text("Equalizer") },
|
||||
selected = currentRoute == Screen.Equalizer.route,
|
||||
onClick = { onNavigate(Screen.Equalizer.route) }
|
||||
)
|
||||
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
Icon(
|
||||
Icons.Default.Settings,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text("Advanced") },
|
||||
selected = currentRoute == Screen.Advanced.route,
|
||||
onClick = { onNavigate(Screen.Advanced.route) }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -17,19 +17,20 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import org.lunaris.dolby.R
|
||||
import org.lunaris.dolby.domain.models.DolbyUiState
|
||||
import org.lunaris.dolby.ui.components.*
|
||||
import org.lunaris.dolby.ui.viewmodel.DolbyViewModel
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ModernDolbySettingsScreen(
|
||||
viewModel: DolbyViewModel,
|
||||
onNavigateToEqualizer: () -> Unit
|
||||
viewModel: org.lunaris.dolby.ui.viewmodel.DolbyViewModel,
|
||||
navController: NavController
|
||||
) {
|
||||
val uiState by viewModel.uiState.collectAsState()
|
||||
var showResetDialog by remember { mutableStateOf(false) }
|
||||
val currentRoute by navController.currentBackStackEntryFlow.collectAsState(null)
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
@@ -55,21 +56,20 @@ fun ModernDolbySettingsScreen(
|
||||
)
|
||||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
bottomBar = {
|
||||
if (uiState is DolbyUiState.Success) {
|
||||
val state = uiState as DolbyUiState.Success
|
||||
if (state.settings.enabled) {
|
||||
FloatingActionButton(
|
||||
onClick = onNavigateToEqualizer,
|
||||
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||
shape = MaterialTheme.shapes.large
|
||||
) {
|
||||
AnimatedEqualizerIconDynamic(
|
||||
color = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||
size = 24.dp
|
||||
)
|
||||
BottomNavigationBar(
|
||||
currentRoute = currentRoute?.destination?.route ?: Screen.Settings.route,
|
||||
onNavigate = { route ->
|
||||
if (currentRoute?.destination?.route != route) {
|
||||
navController.navigate(route) {
|
||||
popUpTo(Screen.Settings.route) { saveState = true }
|
||||
launchSingleTop = true
|
||||
restoreState = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
) { paddingValues ->
|
||||
@@ -98,7 +98,6 @@ fun ModernDolbySettingsScreen(
|
||||
ModernDolbySettingsContent(
|
||||
state = state,
|
||||
viewModel = viewModel,
|
||||
onNavigateToEqualizer = onNavigateToEqualizer,
|
||||
modifier = Modifier.padding(paddingValues)
|
||||
)
|
||||
}
|
||||
@@ -147,8 +146,7 @@ fun ModernDolbySettingsScreen(
|
||||
@Composable
|
||||
private fun ModernDolbySettingsContent(
|
||||
state: DolbyUiState.Success,
|
||||
viewModel: DolbyViewModel,
|
||||
onNavigateToEqualizer: () -> Unit,
|
||||
viewModel: org.lunaris.dolby.ui.viewmodel.DolbyViewModel,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
LazyColumn(
|
||||
@@ -178,241 +176,75 @@ private fun ModernDolbySettingsContent(
|
||||
|
||||
item {
|
||||
AnimatedVisibility(
|
||||
visible = state.settings.enabled,
|
||||
visible = state.settings.enabled && state.settings.currentProfile != 0,
|
||||
enter = fadeIn() + expandVertically(),
|
||||
exit = fadeOut() + shrinkVertically()
|
||||
) {
|
||||
ModernSettingsCard(
|
||||
title = stringResource(R.string.dolby_category_settings),
|
||||
icon = Icons.Default.Tune
|
||||
title = "Intelligent Equalizer",
|
||||
icon = Icons.Default.GraphicEq
|
||||
) {
|
||||
Surface(
|
||||
onClick = onNavigateToEqualizer,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 12.dp),
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = stringResource(R.string.dolby_preset),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Text(
|
||||
text = state.currentPresetName,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.SemiBold
|
||||
)
|
||||
}
|
||||
Icon(
|
||||
imageVector = Icons.Default.ChevronRight,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
ModernSettingSwitch(
|
||||
title = stringResource(R.string.dolby_bass_enhancer),
|
||||
subtitle = stringResource(R.string.dolby_bass_enhancer_summary),
|
||||
checked = state.profileSettings.bassLevel > 0,
|
||||
onCheckedChange = { enabled ->
|
||||
if (enabled && state.profileSettings.bassLevel == 0) {
|
||||
viewModel.setBassLevel(50)
|
||||
} else if (!enabled) {
|
||||
viewModel.setBassLevel(0)
|
||||
}
|
||||
},
|
||||
icon = Icons.Default.MusicNote
|
||||
)
|
||||
|
||||
AnimatedVisibility(visible = state.profileSettings.bassLevel > 0) {
|
||||
Column {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
ModernSettingSelector(
|
||||
title = stringResource(R.string.dolby_bass_curve),
|
||||
currentValue = state.profileSettings.bassCurve,
|
||||
entries = R.array.dolby_bass_curve_entries,
|
||||
values = R.array.dolby_bass_curve_values,
|
||||
onValueChange = { viewModel.setBassCurve(it) },
|
||||
icon = Icons.Default.Equalizer
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
ModernSettingSlider(
|
||||
title = stringResource(R.string.dolby_bass_level),
|
||||
value = state.profileSettings.bassLevel,
|
||||
onValueChange = { viewModel.setBassLevel(it.toInt()) },
|
||||
valueRange = 0f..100f,
|
||||
steps = 19,
|
||||
valueLabel = { "$it%" }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
Column {
|
||||
ModernSettingSwitch(
|
||||
title = stringResource(R.string.dolby_treble_enhancer),
|
||||
subtitle = stringResource(R.string.dolby_treble_enhancer_summary),
|
||||
checked = state.profileSettings.trebleLevel > 0,
|
||||
onCheckedChange = { enabled ->
|
||||
if (enabled && state.profileSettings.trebleLevel == 0) {
|
||||
viewModel.setTrebleLevel(30)
|
||||
} else if (!enabled) {
|
||||
viewModel.setTrebleLevel(0)
|
||||
}
|
||||
},
|
||||
icon = Icons.Default.GraphicEq
|
||||
)
|
||||
|
||||
AnimatedVisibility(visible = state.profileSettings.trebleLevel > 0) {
|
||||
Column {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
ModernSettingSlider(
|
||||
title = stringResource(R.string.dolby_treble_level),
|
||||
value = state.profileSettings.trebleLevel,
|
||||
onValueChange = { viewModel.setTrebleLevel(it.toInt()) },
|
||||
valueRange = 0f..100f,
|
||||
steps = 19,
|
||||
valueLabel = { "$it%" }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
ModernSettingSwitch(
|
||||
title = stringResource(R.string.dolby_volume_leveler),
|
||||
subtitle = stringResource(R.string.dolby_volume_leveler_summary),
|
||||
checked = state.settings.volumeLevelerEnabled,
|
||||
onCheckedChange = { viewModel.setVolumeLeveler(it) },
|
||||
icon = Icons.Default.BarChart
|
||||
ModernIeqSelector(
|
||||
currentPreset = state.profileSettings.ieqPreset,
|
||||
onPresetChange = { viewModel.setIeqPreset(it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state.settings.currentProfile != 0) {
|
||||
item {
|
||||
AnimatedVisibility(
|
||||
visible = state.settings.enabled,
|
||||
enter = fadeIn() + expandVertically(),
|
||||
exit = fadeOut() + shrinkVertically()
|
||||
) {
|
||||
ModernSettingsCard(
|
||||
title = stringResource(R.string.dolby_category_adv_settings),
|
||||
icon = Icons.Default.Settings
|
||||
) {
|
||||
ModernIeqSelector(
|
||||
currentPreset = state.profileSettings.ieqPreset,
|
||||
onPresetChange = { viewModel.setIeqPreset(it) }
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
if (state.isOnSpeaker) {
|
||||
ModernSettingSwitch(
|
||||
title = stringResource(R.string.dolby_spk_virtualizer),
|
||||
subtitle = stringResource(R.string.dolby_spk_virtualizer_summary),
|
||||
checked = state.profileSettings.speakerVirtualizerEnabled,
|
||||
onCheckedChange = { viewModel.setSpeakerVirtualizer(it) },
|
||||
icon = Icons.Default.Speaker
|
||||
)
|
||||
} else {
|
||||
ModernSettingSwitch(
|
||||
title = stringResource(R.string.dolby_hp_virtualizer),
|
||||
subtitle = stringResource(R.string.dolby_hp_virtualizer_summary),
|
||||
checked = state.profileSettings.headphoneVirtualizerEnabled,
|
||||
onCheckedChange = { viewModel.setHeadphoneVirtualizer(it) },
|
||||
icon = Icons.Default.Headphones
|
||||
)
|
||||
|
||||
AnimatedVisibility(visible = state.profileSettings.headphoneVirtualizerEnabled) {
|
||||
Column {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
ModernSettingSlider(
|
||||
title = stringResource(R.string.dolby_hp_virtualizer_dolby_strength),
|
||||
value = state.profileSettings.stereoWideningAmount,
|
||||
onValueChange = { viewModel.setStereoWidening(it.toInt()) },
|
||||
valueRange = 4f..64f,
|
||||
steps = 59
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
ModernSettingSwitch(
|
||||
title = stringResource(R.string.dolby_dialogue_enhancer),
|
||||
subtitle = stringResource(R.string.dolby_dialogue_enhancer_summary),
|
||||
checked = state.profileSettings.dialogueEnhancerEnabled,
|
||||
onCheckedChange = { viewModel.setDialogueEnhancer(it) },
|
||||
icon = Icons.Default.RecordVoiceOver
|
||||
)
|
||||
|
||||
AnimatedVisibility(visible = state.profileSettings.dialogueEnhancerEnabled) {
|
||||
Column {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
ModernSettingSlider(
|
||||
title = stringResource(R.string.dolby_dialogue_enhancer_dolby_strength),
|
||||
value = state.profileSettings.dialogueEnhancerAmount,
|
||||
onValueChange = { viewModel.setDialogueEnhancerAmount(it.toInt()) },
|
||||
valueRange = 1f..12f,
|
||||
steps = 10
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state.settings.currentProfile == 0 && state.settings.enabled) {
|
||||
item {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
color = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.5f)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Info,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.dolby_adv_settings_footer),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSecondaryContainer
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(80.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BottomNavigationBar(
|
||||
currentRoute: String,
|
||||
onNavigate: (String) -> Unit
|
||||
) {
|
||||
NavigationBar(
|
||||
containerColor = MaterialTheme.colorScheme.surfaceContainer,
|
||||
tonalElevation = 3.dp
|
||||
) {
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
Icon(
|
||||
Icons.Default.Home,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text("Home") },
|
||||
selected = currentRoute == Screen.Settings.route,
|
||||
onClick = { onNavigate(Screen.Settings.route) }
|
||||
)
|
||||
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
AnimatedEqualizerIconDynamic(
|
||||
color = if (currentRoute == Screen.Equalizer.route) {
|
||||
MaterialTheme.colorScheme.primary
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onSurfaceVariant
|
||||
},
|
||||
size = 24.dp
|
||||
)
|
||||
},
|
||||
label = { Text("Equalizer") },
|
||||
selected = currentRoute == Screen.Equalizer.route,
|
||||
onClick = { onNavigate(Screen.Equalizer.route) }
|
||||
)
|
||||
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
Icon(
|
||||
Icons.Default.Settings,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text("Advanced") },
|
||||
selected = currentRoute == Screen.Advanced.route,
|
||||
onClick = { onNavigate(Screen.Advanced.route) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ package org.lunaris.dolby.ui.screens
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
@@ -17,22 +16,25 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import org.lunaris.dolby.R
|
||||
import org.lunaris.dolby.domain.models.EqualizerUiState
|
||||
import org.lunaris.dolby.ui.components.ModernConfirmDialog
|
||||
import org.lunaris.dolby.ui.components.InteractiveFrequencyResponseCurve
|
||||
import org.lunaris.dolby.ui.components.AnimatedEqualizerIconDynamic
|
||||
import org.lunaris.dolby.ui.viewmodel.EqualizerViewModel
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ModernEqualizerScreen(
|
||||
viewModel: EqualizerViewModel,
|
||||
onNavigateBack: () -> Unit
|
||||
navController: NavController
|
||||
) {
|
||||
val uiState by viewModel.uiState.collectAsState()
|
||||
var showSaveDialog by remember { mutableStateOf(false) }
|
||||
var showDeleteDialog by remember { mutableStateOf(false) }
|
||||
var showResetDialog by remember { mutableStateOf(false) }
|
||||
val currentRoute by navController.currentBackStackEntryFlow.collectAsState(null)
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
@@ -44,11 +46,6 @@ fun ModernEqualizerScreen(
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onNavigateBack) {
|
||||
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
IconButton(onClick = { showSaveDialog = true }) {
|
||||
Icon(Icons.Default.Save, contentDescription = "Save")
|
||||
@@ -69,6 +66,20 @@ fun ModernEqualizerScreen(
|
||||
containerColor = MaterialTheme.colorScheme.surface
|
||||
)
|
||||
)
|
||||
},
|
||||
bottomBar = {
|
||||
BottomNavigationBar(
|
||||
currentRoute = currentRoute?.destination?.route ?: Screen.Equalizer.route,
|
||||
onNavigate = { route ->
|
||||
if (currentRoute?.destination?.route != route) {
|
||||
navController.navigate(route) {
|
||||
popUpTo(Screen.Settings.route) { saveState = true }
|
||||
launchSingleTop = true
|
||||
restoreState = true
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
when (val state = uiState) {
|
||||
@@ -164,6 +175,9 @@ private fun ModernEqualizerContent(
|
||||
viewModel: EqualizerViewModel,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val isFlatPreset = state.currentPreset.name == stringResource(R.string.dolby_preset_default)
|
||||
val isActive = !isFlatPreset
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
@@ -214,6 +228,7 @@ private fun ModernEqualizerContent(
|
||||
onBandGainChange = { index, newGain ->
|
||||
viewModel.setBandGain(index, newGain)
|
||||
},
|
||||
isActive = isActive,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f)
|
||||
@@ -389,3 +404,54 @@ private fun SavePresetDialog(
|
||||
shape = RoundedCornerShape(28.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BottomNavigationBar(
|
||||
currentRoute: String,
|
||||
onNavigate: (String) -> Unit
|
||||
) {
|
||||
NavigationBar(
|
||||
containerColor = MaterialTheme.colorScheme.surfaceContainer,
|
||||
tonalElevation = 3.dp
|
||||
) {
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
Icon(
|
||||
Icons.Default.Home,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text("Home") },
|
||||
selected = currentRoute == Screen.Settings.route,
|
||||
onClick = { onNavigate(Screen.Settings.route) }
|
||||
)
|
||||
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
AnimatedEqualizerIconDynamic(
|
||||
color = if (currentRoute == Screen.Equalizer.route) {
|
||||
MaterialTheme.colorScheme.primary
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onSurfaceVariant
|
||||
},
|
||||
size = 24.dp
|
||||
)
|
||||
},
|
||||
label = { Text("Equalizer") },
|
||||
selected = currentRoute == Screen.Equalizer.route,
|
||||
onClick = { onNavigate(Screen.Equalizer.route) }
|
||||
)
|
||||
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
Icon(
|
||||
Icons.Default.Settings,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text("Advanced") },
|
||||
selected = currentRoute == Screen.Advanced.route,
|
||||
onClick = { onNavigate(Screen.Advanced.route) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.lunaris.dolby.ui.viewmodel.EqualizerViewModel
|
||||
sealed class Screen(val route: String) {
|
||||
object Settings : Screen("settings")
|
||||
object Equalizer : Screen("equalizer")
|
||||
object Advanced : Screen("advanced")
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -31,18 +32,21 @@ fun DolbyNavHost(
|
||||
composable(Screen.Settings.route) {
|
||||
ModernDolbySettingsScreen(
|
||||
viewModel = dolbyViewModel,
|
||||
onNavigateToEqualizer = {
|
||||
navController.navigate(Screen.Equalizer.route)
|
||||
}
|
||||
navController = navController
|
||||
)
|
||||
}
|
||||
|
||||
composable(Screen.Equalizer.route) {
|
||||
ModernEqualizerScreen(
|
||||
viewModel = equalizerViewModel,
|
||||
onNavigateBack = {
|
||||
navController.popBackStack()
|
||||
}
|
||||
navController = navController
|
||||
)
|
||||
}
|
||||
|
||||
composable(Screen.Advanced.route) {
|
||||
ModernAdvancedSettingsScreen(
|
||||
viewModel = dolbyViewModel,
|
||||
navController = navController
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user