|
|
|
@@ -18,23 +18,35 @@ import androidx.compose.foundation.layout.Column
|
|
|
|
import androidx.compose.foundation.layout.ColumnScope
|
|
|
|
import androidx.compose.foundation.layout.ColumnScope
|
|
|
|
import androidx.compose.foundation.layout.Row
|
|
|
|
import androidx.compose.foundation.layout.Row
|
|
|
|
import androidx.compose.foundation.layout.Spacer
|
|
|
|
import androidx.compose.foundation.layout.Spacer
|
|
|
|
|
|
|
|
import androidx.compose.foundation.layout.WindowInsets
|
|
|
|
import androidx.compose.foundation.layout.fillMaxHeight
|
|
|
|
import androidx.compose.foundation.layout.fillMaxHeight
|
|
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
|
import androidx.compose.foundation.layout.height
|
|
|
|
import androidx.compose.foundation.layout.height
|
|
|
|
|
|
|
|
import androidx.compose.foundation.layout.navigationBars
|
|
|
|
import androidx.compose.foundation.layout.padding
|
|
|
|
import androidx.compose.foundation.layout.padding
|
|
|
|
import androidx.compose.foundation.layout.safeDrawingPadding
|
|
|
|
import androidx.compose.foundation.layout.safeDrawingPadding
|
|
|
|
import androidx.compose.foundation.layout.windowInsetsBottomHeight
|
|
|
|
import androidx.compose.foundation.layout.size
|
|
|
|
|
|
|
|
import androidx.compose.foundation.layout.statusBars
|
|
|
|
|
|
|
|
import androidx.compose.foundation.layout.windowInsetsPadding
|
|
|
|
import androidx.compose.foundation.rememberScrollState
|
|
|
|
import androidx.compose.foundation.rememberScrollState
|
|
|
|
import androidx.compose.foundation.verticalScroll
|
|
|
|
import androidx.compose.foundation.verticalScroll
|
|
|
|
import androidx.compose.foundation.lazy.LazyColumn
|
|
|
|
import androidx.compose.foundation.lazy.LazyColumn
|
|
|
|
import androidx.compose.foundation.lazy.items
|
|
|
|
import androidx.compose.foundation.lazy.items
|
|
|
|
|
|
|
|
import androidx.compose.material.icons.Icons
|
|
|
|
|
|
|
|
import androidx.compose.material.icons.filled.Add
|
|
|
|
|
|
|
|
import androidx.compose.material.icons.filled.Delete
|
|
|
|
|
|
|
|
import androidx.compose.material.icons.filled.PlayArrow
|
|
|
|
|
|
|
|
import androidx.compose.material.icons.filled.Settings
|
|
|
|
|
|
|
|
import androidx.compose.material3.AlertDialog
|
|
|
|
import androidx.compose.material3.Button
|
|
|
|
import androidx.compose.material3.Button
|
|
|
|
import androidx.compose.material3.Card
|
|
|
|
import androidx.compose.material3.Card
|
|
|
|
import androidx.compose.material3.CardDefaults
|
|
|
|
import androidx.compose.material3.CardDefaults
|
|
|
|
import androidx.compose.material3.Checkbox
|
|
|
|
import androidx.compose.material3.Checkbox
|
|
|
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
|
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
|
|
import androidx.compose.material3.HorizontalDivider
|
|
|
|
import androidx.compose.material3.HorizontalDivider
|
|
|
|
|
|
|
|
import androidx.compose.material3.Icon
|
|
|
|
|
|
|
|
import androidx.compose.material3.IconButton
|
|
|
|
import androidx.compose.material3.MaterialTheme
|
|
|
|
import androidx.compose.material3.MaterialTheme
|
|
|
|
import androidx.compose.material3.LinearProgressIndicator
|
|
|
|
import androidx.compose.material3.LinearProgressIndicator
|
|
|
|
import androidx.compose.material3.OutlinedButton
|
|
|
|
import androidx.compose.material3.OutlinedButton
|
|
|
|
@@ -87,11 +99,13 @@ import com.mindmachine.mvp.session.SplitFlashFrame
|
|
|
|
import com.mindmachine.mvp.session.SplitFlashSequencer
|
|
|
|
import com.mindmachine.mvp.session.SplitFlashSequencer
|
|
|
|
import com.mindmachine.mvp.session.flashIntervalMsToSeconds
|
|
|
|
import com.mindmachine.mvp.session.flashIntervalMsToSeconds
|
|
|
|
import com.mindmachine.mvp.session.flashIntervalSecondsToMs
|
|
|
|
import com.mindmachine.mvp.session.flashIntervalSecondsToMs
|
|
|
|
|
|
|
|
import com.mindmachine.mvp.session.formatDuration
|
|
|
|
import com.mindmachine.mvp.session.sessionProgressFraction
|
|
|
|
import com.mindmachine.mvp.session.sessionProgressFraction
|
|
|
|
import com.mindmachine.mvp.session.shouldShowActiveControlsByDefault
|
|
|
|
import com.mindmachine.mvp.session.shouldShowActiveControlsByDefault
|
|
|
|
import com.mindmachine.mvp.session.shouldUseImmersiveFullscreen
|
|
|
|
import com.mindmachine.mvp.session.shouldUseImmersiveFullscreen
|
|
|
|
import kotlinx.coroutines.delay
|
|
|
|
import kotlinx.coroutines.delay
|
|
|
|
import kotlin.math.roundToInt
|
|
|
|
import kotlin.math.roundToInt
|
|
|
|
|
|
|
|
import java.util.Locale
|
|
|
|
|
|
|
|
|
|
|
|
private val MindMachineColors = darkColorScheme(
|
|
|
|
private val MindMachineColors = darkColorScheme(
|
|
|
|
primary = Color(0xFF8AB4FF),
|
|
|
|
primary = Color(0xFF8AB4FF),
|
|
|
|
@@ -177,17 +191,30 @@ fun App(vm: MainViewModel = viewModel()) {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
composable("home") {
|
|
|
|
composable("home") {
|
|
|
|
Column(Modifier.fillMaxSize()) {
|
|
|
|
var confirmDeleteProgramId by remember { mutableStateOf<String?>(null) }
|
|
|
|
|
|
|
|
var confirmDeleteProgramName by remember { mutableStateOf("") }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Column(
|
|
|
|
|
|
|
|
Modifier
|
|
|
|
|
|
|
|
.fillMaxSize()
|
|
|
|
|
|
|
|
.safeDrawingPadding()
|
|
|
|
|
|
|
|
) {
|
|
|
|
TopAppBar(title = { Text("MindMachine") }, actions = {
|
|
|
|
TopAppBar(title = { Text("MindMachine") }, actions = {
|
|
|
|
TextButton(onClick = {
|
|
|
|
IconButton(
|
|
|
|
vm.createNewProgramDraft()
|
|
|
|
onClick = {
|
|
|
|
nav.navigate("setup")
|
|
|
|
vm.createNewProgramDraft()
|
|
|
|
}) { Text("Add") }
|
|
|
|
nav.navigate("setup")
|
|
|
|
TextButton(onClick = { nav.navigate("settings") }) { Text("Settings") }
|
|
|
|
}
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
Icon(Icons.Filled.Add, contentDescription = "Add")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
IconButton(onClick = { nav.navigate("settings") }) {
|
|
|
|
|
|
|
|
Icon(Icons.Filled.Settings, contentDescription = "Settings")
|
|
|
|
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
LazyColumn(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
|
|
|
LazyColumn(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
|
|
|
item {
|
|
|
|
item {
|
|
|
|
TextButton(onClick = { nav.navigate("holder") }) { Text("Holder Guidance") }
|
|
|
|
TextButton(onClick = { nav.navigate("holder") }) { Text("User Guidance/Disclaimer") }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
items(ui.presets) { p ->
|
|
|
|
items(ui.presets) { p ->
|
|
|
|
Card(
|
|
|
|
Card(
|
|
|
|
@@ -208,14 +235,66 @@ fun App(vm: MainViewModel = viewModel()) {
|
|
|
|
Column(Modifier.weight(1f)) {
|
|
|
|
Column(Modifier.weight(1f)) {
|
|
|
|
Text(p.name, style = MaterialTheme.typography.titleMedium)
|
|
|
|
Text(p.name, style = MaterialTheme.typography.titleMedium)
|
|
|
|
Text(p.description)
|
|
|
|
Text(p.description)
|
|
|
|
Text("${p.defaultDurationSec / 60} min • ${p.visualPatternType} • binaural ${p.binauralDifferenceHz}")
|
|
|
|
Text("${formatDuration(p.defaultDurationSec)} • ${p.visualPatternType} • binaural ${formatMaxTwoDecimals(p.binauralDifferenceHz)}")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Row(
|
|
|
|
|
|
|
|
verticalAlignment = Alignment.CenterVertically,
|
|
|
|
|
|
|
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
Icon(
|
|
|
|
|
|
|
|
imageVector = Icons.Filled.PlayArrow,
|
|
|
|
|
|
|
|
contentDescription = null,
|
|
|
|
|
|
|
|
tint = Color(0xFF4CAF50),
|
|
|
|
|
|
|
|
modifier = Modifier.size(30.dp)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
Box(
|
|
|
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
|
|
|
.size(24.dp)
|
|
|
|
|
|
|
|
.clickable {
|
|
|
|
|
|
|
|
confirmDeleteProgramId = p.id
|
|
|
|
|
|
|
|
confirmDeleteProgramName = p.name
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
contentAlignment = Alignment.Center
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
Icon(
|
|
|
|
|
|
|
|
imageVector = Icons.Filled.Delete,
|
|
|
|
|
|
|
|
contentDescription = "Delete ${p.name}",
|
|
|
|
|
|
|
|
tint = Color(0xFFFF5252),
|
|
|
|
|
|
|
|
modifier = Modifier.fillMaxSize()
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TextButton(onClick = { vm.deleteProgram(p.id) }) { Text("Delete") }
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (confirmDeleteProgramId != null) {
|
|
|
|
|
|
|
|
AlertDialog(
|
|
|
|
|
|
|
|
onDismissRequest = {
|
|
|
|
|
|
|
|
confirmDeleteProgramId = null
|
|
|
|
|
|
|
|
confirmDeleteProgramName = ""
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
title = { Text("Delete program?") },
|
|
|
|
|
|
|
|
text = { Text("Delete \"$confirmDeleteProgramName\"?") },
|
|
|
|
|
|
|
|
confirmButton = {
|
|
|
|
|
|
|
|
TextButton(onClick = {
|
|
|
|
|
|
|
|
confirmDeleteProgramId?.let(vm::deleteProgram)
|
|
|
|
|
|
|
|
confirmDeleteProgramId = null
|
|
|
|
|
|
|
|
confirmDeleteProgramName = ""
|
|
|
|
|
|
|
|
}) {
|
|
|
|
|
|
|
|
Text("Delete", color = Color(0xFFFF5252))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
dismissButton = {
|
|
|
|
|
|
|
|
TextButton(onClick = {
|
|
|
|
|
|
|
|
confirmDeleteProgramId = null
|
|
|
|
|
|
|
|
confirmDeleteProgramName = ""
|
|
|
|
|
|
|
|
}) { Text("Cancel") }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
composable("setup") {
|
|
|
|
composable("setup") {
|
|
|
|
SetupScreen(
|
|
|
|
SetupScreen(
|
|
|
|
@@ -226,7 +305,6 @@ fun App(vm: MainViewModel = viewModel()) {
|
|
|
|
nav.navigate("active")
|
|
|
|
nav.navigate("active")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
onHolder = { nav.navigate("holder") },
|
|
|
|
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
composable("active") {
|
|
|
|
composable("active") {
|
|
|
|
@@ -262,7 +340,11 @@ fun App(vm: MainViewModel = viewModel()) {
|
|
|
|
@Composable
|
|
|
|
@Composable
|
|
|
|
fun SimpleScreen(title: String, subtitle: String, actions: @Composable ColumnScope.() -> Unit) {
|
|
|
|
fun SimpleScreen(title: String, subtitle: String, actions: @Composable ColumnScope.() -> Unit) {
|
|
|
|
Column(
|
|
|
|
Column(
|
|
|
|
modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background).padding(16.dp),
|
|
|
|
modifier = Modifier
|
|
|
|
|
|
|
|
.fillMaxSize()
|
|
|
|
|
|
|
|
.background(MaterialTheme.colorScheme.background)
|
|
|
|
|
|
|
|
.safeDrawingPadding()
|
|
|
|
|
|
|
|
.padding(16.dp),
|
|
|
|
verticalArrangement = Arrangement.spacedBy(12.dp),
|
|
|
|
verticalArrangement = Arrangement.spacedBy(12.dp),
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
Text(title, style = MaterialTheme.typography.headlineMedium, color = MaterialTheme.colorScheme.onBackground)
|
|
|
|
Text(title, style = MaterialTheme.typography.headlineMedium, color = MaterialTheme.colorScheme.onBackground)
|
|
|
|
@@ -274,7 +356,13 @@ fun SimpleScreen(title: String, subtitle: String, actions: @Composable ColumnSco
|
|
|
|
@Composable
|
|
|
|
@Composable
|
|
|
|
fun SafetyScreen(onAck: () -> Unit, onHolder: () -> Unit) {
|
|
|
|
fun SafetyScreen(onAck: () -> Unit, onHolder: () -> Unit) {
|
|
|
|
var checked by remember { mutableStateOf(false) }
|
|
|
|
var checked by remember { mutableStateOf(false) }
|
|
|
|
Column(Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background).padding(16.dp)) {
|
|
|
|
Column(
|
|
|
|
|
|
|
|
Modifier
|
|
|
|
|
|
|
|
.fillMaxSize()
|
|
|
|
|
|
|
|
.background(MaterialTheme.colorScheme.background)
|
|
|
|
|
|
|
|
.safeDrawingPadding()
|
|
|
|
|
|
|
|
.padding(16.dp)
|
|
|
|
|
|
|
|
) {
|
|
|
|
Text("Read before using MindMachine", style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onBackground)
|
|
|
|
Text("Read before using MindMachine", style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onBackground)
|
|
|
|
Spacer(Modifier.height(12.dp))
|
|
|
|
Spacer(Modifier.height(12.dp))
|
|
|
|
Text(
|
|
|
|
Text(
|
|
|
|
@@ -294,15 +382,15 @@ fun SafetyScreen(onAck: () -> Unit, onHolder: () -> Unit) {
|
|
|
|
fun SetupScreen(
|
|
|
|
fun SetupScreen(
|
|
|
|
vm: MainViewModel,
|
|
|
|
vm: MainViewModel,
|
|
|
|
onStart: () -> Unit,
|
|
|
|
onStart: () -> Unit,
|
|
|
|
onHolder: () -> Unit,
|
|
|
|
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
val ui by vm.ui.collectAsStateWithLifecycle()
|
|
|
|
val ui by vm.ui.collectAsStateWithLifecycle()
|
|
|
|
val scrollState = rememberScrollState()
|
|
|
|
val scrollState = rememberScrollState()
|
|
|
|
val containerModifier = Modifier
|
|
|
|
val containerModifier = Modifier
|
|
|
|
.fillMaxSize()
|
|
|
|
.fillMaxSize()
|
|
|
|
.background(MaterialTheme.colorScheme.background)
|
|
|
|
.background(MaterialTheme.colorScheme.background)
|
|
|
|
|
|
|
|
.windowInsetsPadding(WindowInsets.statusBars)
|
|
|
|
|
|
|
|
.windowInsetsPadding(WindowInsets.navigationBars)
|
|
|
|
.then(if (setupScreenUsesScrollableContainer()) Modifier.verticalScroll(scrollState) else Modifier)
|
|
|
|
.then(if (setupScreenUsesScrollableContainer()) Modifier.verticalScroll(scrollState) else Modifier)
|
|
|
|
.safeDrawingPadding()
|
|
|
|
|
|
|
|
.padding(horizontal = 16.dp, vertical = 12.dp)
|
|
|
|
.padding(horizontal = 16.dp, vertical = 12.dp)
|
|
|
|
|
|
|
|
|
|
|
|
var programName by remember(ui.selectedPreset.id) { mutableStateOf(ui.selectedPreset.name) }
|
|
|
|
var programName by remember(ui.selectedPreset.id) { mutableStateOf(ui.selectedPreset.name) }
|
|
|
|
@@ -342,7 +430,6 @@ fun SetupScreen(
|
|
|
|
onCurveGranularityChanged = vm::setCurveGranularitySec,
|
|
|
|
onCurveGranularityChanged = vm::setCurveGranularitySec,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
TextButton(onClick = onHolder) { Text("Holder Guidance") }
|
|
|
|
|
|
|
|
Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) {
|
|
|
|
Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) {
|
|
|
|
if (hasUnsavedChanges) {
|
|
|
|
if (hasUnsavedChanges) {
|
|
|
|
OutlinedButton(onClick = { vm.saveCurrentProgram(programName) }, modifier = Modifier.weight(1f).height(52.dp)) {
|
|
|
|
OutlinedButton(onClick = { vm.saveCurrentProgram(programName) }, modifier = Modifier.weight(1f).height(52.dp)) {
|
|
|
|
@@ -360,6 +447,9 @@ fun SetupScreen(
|
|
|
|
internal fun setupScreenFlashIntervalLabel(flashIntervalMs: Int): String =
|
|
|
|
internal fun setupScreenFlashIntervalLabel(flashIntervalMs: Int): String =
|
|
|
|
"Flash interval: ${"%.2f".format(flashIntervalMsToSeconds(flashIntervalMs))} s"
|
|
|
|
"Flash interval: ${"%.2f".format(flashIntervalMsToSeconds(flashIntervalMs))} s"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
internal fun formatMaxTwoDecimals(value: Float): String =
|
|
|
|
|
|
|
|
String.format(Locale.US, "%.2f", value).trimEnd('0').trimEnd('.')
|
|
|
|
|
|
|
|
|
|
|
|
internal fun setupScreenHasUnsavedChanges(
|
|
|
|
internal fun setupScreenHasUnsavedChanges(
|
|
|
|
hasUnsavedTimelineChanges: Boolean,
|
|
|
|
hasUnsavedTimelineChanges: Boolean,
|
|
|
|
editedProgramName: String,
|
|
|
|
editedProgramName: String,
|
|
|
|
@@ -436,6 +526,7 @@ fun ActiveSessionScreen(vm: MainViewModel, onFinish: () -> Unit, onBackToSetup:
|
|
|
|
modifier = Modifier
|
|
|
|
modifier = Modifier
|
|
|
|
.fillMaxSize()
|
|
|
|
.fillMaxSize()
|
|
|
|
.background(Color.Black)
|
|
|
|
.background(Color.Black)
|
|
|
|
|
|
|
|
.then(if (immersiveFullscreen) Modifier else Modifier.safeDrawingPadding())
|
|
|
|
.pointerInput(immersiveFullscreen) {
|
|
|
|
.pointerInput(immersiveFullscreen) {
|
|
|
|
detectTapGestures {
|
|
|
|
detectTapGestures {
|
|
|
|
brightnessOverlayVisible = true
|
|
|
|
brightnessOverlayVisible = true
|
|
|
|
@@ -636,8 +727,14 @@ private fun rememberSplitFlashFrame(
|
|
|
|
@Composable
|
|
|
|
@Composable
|
|
|
|
fun SettingsScreen(vm: MainViewModel) {
|
|
|
|
fun SettingsScreen(vm: MainViewModel) {
|
|
|
|
val ui by vm.ui.collectAsStateWithLifecycle()
|
|
|
|
val ui by vm.ui.collectAsStateWithLifecycle()
|
|
|
|
|
|
|
|
val scrollState = rememberScrollState()
|
|
|
|
Column(
|
|
|
|
Column(
|
|
|
|
Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background).padding(16.dp),
|
|
|
|
Modifier
|
|
|
|
|
|
|
|
.fillMaxSize()
|
|
|
|
|
|
|
|
.background(MaterialTheme.colorScheme.background)
|
|
|
|
|
|
|
|
.safeDrawingPadding()
|
|
|
|
|
|
|
|
.verticalScroll(scrollState)
|
|
|
|
|
|
|
|
.padding(16.dp),
|
|
|
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
|
|
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
Text("Settings", style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onBackground)
|
|
|
|
Text("Settings", style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onBackground)
|
|
|
|
@@ -671,7 +768,11 @@ fun SettingsScreen(vm: MainViewModel) {
|
|
|
|
@Composable
|
|
|
|
@Composable
|
|
|
|
fun HolderScreen() {
|
|
|
|
fun HolderScreen() {
|
|
|
|
Column(
|
|
|
|
Column(
|
|
|
|
Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background).padding(16.dp),
|
|
|
|
Modifier
|
|
|
|
|
|
|
|
.fillMaxSize()
|
|
|
|
|
|
|
|
.background(MaterialTheme.colorScheme.background)
|
|
|
|
|
|
|
|
.safeDrawingPadding()
|
|
|
|
|
|
|
|
.padding(16.dp),
|
|
|
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
|
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
Text("Holder Guidance", style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onBackground)
|
|
|
|
Text("Holder Guidance", style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onBackground)
|
|
|
|
|