Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ android {
buildConfig = true
compose = true
resValues = true
viewBinding = true
}
lint {
// The translations are always going to lag behind new strings being
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
Expand Down Expand Up @@ -61,8 +62,9 @@ fun RecordRuleEditorScreen(
val resources = LocalResources.current

val rule by viewModel.initOrGetExisting(initialRule).collectAsStateWithLifecycle()
val latestOnRuleUpdate by rememberUpdatedState(onRuleUpdate)
LaunchedEffect(rule) {
onRuleUpdate(rule)
latestOnRuleUpdate(rule)
}

val contactInfo by viewModel.contactInfo.collectAsStateWithLifecycle()
Expand Down
32 changes: 18 additions & 14 deletions app/src/main/java/com/chiller3/bcr/settings/FileRetentionDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.InputTransformation
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.text.input.then
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalResources
import androidx.compose.ui.res.stringResource
Expand All @@ -41,15 +41,14 @@ fun FileRetentionDialog(
) {
val resources = LocalResources.current

var input by rememberSaveable(retention) {
mutableStateOf(
when (retention) {
is DaysRetention -> retention.days.toString()
NoRetention -> ""
}
)
val initialText = remember {
when (retention) {
is DaysRetention -> retention.days.toString()
NoRetention -> ""
}
}
val retention = tryParseInput(input)
val input = rememberTextFieldState(initialText = initialText)
val retention = tryParseInput(input.text.toString())
val supportingText = remember(retention) {
when (retention) {
is RetentionParse.Value -> retention.retention.toFormattedString(resources)
Expand All @@ -64,12 +63,17 @@ fun FileRetentionDialog(
Text(text = stringResource(R.string.file_retention_dialog_message))

OutlinedTextField(
state = input,
modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
value = input,
onValueChange = { if (it.isDigitsOnly()) input = it },
isError = retention is RetentionParse.Error,
supportingText = { Text(text = supportingText) },
inputTransformation = InputTransformation.then {
if (!asCharSequence().isDigitsOnly()) {
revertAllChanges()
}
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
lineLimits = TextFieldLineLimits.SingleLine,
)
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,21 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.OutputTransformation
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalResources
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.LinkAnnotation
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.DialogProperties
import com.chiller3.bcr.BuildConfig
Expand All @@ -48,17 +45,9 @@ fun FilenameTemplateDialog(
onReset: () -> Unit,
) {
val syntaxColors = templateSyntaxColors()
// This intentionally does not key off anything. We don't want to reset the text box state, only
// rehighlight the template if needed.
var input by rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(TextFieldValue(syntaxColors.annotated(template.toString())))
}
val template = tryParseInput(input.text, syntaxColors)

LaunchedEffect(syntaxColors) {
val orig = input
input = orig.copy(annotatedString = syntaxColors.annotated(orig.text))
}
val initialText = remember { template.toString() }
val input = rememberTextFieldState(initialText = initialText)
val template = tryParseInput(input.text.toString(), syntaxColors)

AlertDialog(
title = { Text(text = stringResource(R.string.filename_template_dialog_title)) },
Expand All @@ -67,17 +56,26 @@ fun FilenameTemplateDialog(
Text(text = buildMessage(syntaxColors))

OutlinedTextField(
state = input,
modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
value = input,
onValueChange = {
input = it.copy(annotatedString = syntaxColors.annotated(it.text))
},
isError = template is TemplateParse.Error,
supportingText = {
if (template is TemplateParse.Error) {
Text(text = template.message)
}
},
outputTransformation = OutputTransformation {
// This can't use an AnnotatedString directly.
// https://issuetracker.google.com/issues/389978748
val annotated = syntaxColors.annotated(originalText.toString())

for (style in annotated.spanStyles) {
addStyle(style.item, style.start, style.end)
}
for (style in annotated.paragraphStyles) {
addStyle(style.item, style.start, style.end)
}
},
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.None,
autoCorrectEnabled = false,
Expand Down
22 changes: 13 additions & 9 deletions app/src/main/java/com/chiller3/bcr/settings/FormatParamDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.InputTransformation
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.text.input.then
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalResources
import androidx.compose.ui.res.stringResource
Expand Down Expand Up @@ -61,8 +61,8 @@ fun FormatParamDialog(
}
}

var input by rememberSaveable { mutableStateOf("") }
val value = tryParseInput(paramInfo, multiplier, input)
val input = rememberTextFieldState()
val value = tryParseInput(paramInfo, multiplier, input.text.toString())
val settings = formatParamTextFieldSettings(paramInfo, multiplier)

AlertDialog(
Expand All @@ -77,9 +77,8 @@ fun FormatParamDialog(
Text(text = message)

OutlinedTextField(
state = input,
modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
value = input,
onValueChange = { if (it.isDigitsOnly()) input = it },
textStyle = LocalTextStyle.current.copy(textAlign = settings.textAlign),
prefix = {
if (settings.prefix != null) {
Expand All @@ -91,7 +90,13 @@ fun FormatParamDialog(
Text(text = settings.suffix)
}
},
inputTransformation = InputTransformation.then {
if (!asCharSequence().isDigitsOnly()) {
revertAllChanges()
}
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
lineLimits = TextFieldLineLimits.SingleLine,
)
}
},
Expand All @@ -116,7 +121,6 @@ fun FormatParamDialog(
)
}

@Composable
private fun tryParseInput(paramInfo: RangedParamInfo, multiplier: UInt, input: String): UInt? {
if (input.isNotEmpty()) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.InputTransformation
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.text.input.then
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalResources
import androidx.compose.ui.res.stringResource
Expand All @@ -46,8 +46,8 @@ fun FormatSampleRateDialog(
throw IllegalStateException("Selected format is not configurable")
}

var input by rememberSaveable { mutableStateOf("") }
val value = tryParseInput(sampleRateInfo, input)
val input = rememberTextFieldState()
val value = tryParseInput(sampleRateInfo, input.text.toString())
val settings = formatSampleRateTextFieldSettings()

AlertDialog(
Expand All @@ -57,9 +57,8 @@ fun FormatSampleRateDialog(
Text(text = sampleRateMessage(sampleRateInfo))

OutlinedTextField(
state = input,
modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
value = input,
onValueChange = { if (it.isDigitsOnly()) input = it },
textStyle = LocalTextStyle.current.copy(textAlign = settings.textAlign),
prefix = {
if (settings.prefix != null) {
Expand All @@ -71,7 +70,13 @@ fun FormatSampleRateDialog(
Text(text = settings.suffix)
}
},
inputTransformation = InputTransformation.then {
if (!asCharSequence().isDigitsOnly()) {
revertAllChanges()
}
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
lineLimits = TextFieldLineLimits.SingleLine,
)
}
},
Expand Down Expand Up @@ -115,7 +120,6 @@ private fun sampleRateMessage(sampleRateInfo: RangedSampleRateInfo) = buildAnnot
}
}

@Composable
private fun tryParseInput(sampleRateInfo: SampleRateInfo, input: String): UInt? {
if (input.isNotEmpty()) {
try {
Expand Down
22 changes: 13 additions & 9 deletions app/src/main/java/com/chiller3/bcr/settings/MinDurationDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.InputTransformation
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.text.input.then
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
Expand All @@ -35,8 +35,8 @@ fun MinDurationDialog(
onSelect: (Int) -> Unit,
onDismiss: () -> Unit,
) {
var input by rememberSaveable(minDuration) { mutableStateOf(minDuration.toString()) }
val minDuration = tryParseInput(input)
val input = rememberTextFieldState(initialText = minDuration.toString())
val minDuration = tryParseInput(input.text.toString())
val supportingText = minDuration?.let {
pluralStringResource(R.plurals.min_duration_dialog_seconds, it, it)
}
Expand All @@ -48,11 +48,16 @@ fun MinDurationDialog(
Text(text = stringResource(R.string.min_duration_dialog_message))

OutlinedTextField(
state = input,
modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
value = input,
onValueChange = { if (it.isDigitsOnly()) input = it },
supportingText = { supportingText?.let { Text(text = it) } },
inputTransformation = InputTransformation.then {
if (!asCharSequence().isDigitsOnly()) {
revertAllChanges()
}
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
lineLimits = TextFieldLineLimits.SingleLine,
)
}
},
Expand All @@ -77,7 +82,6 @@ fun MinDurationDialog(
)
}

@Composable
private fun tryParseInput(input: String): Int? {
if (input.isEmpty()) {
return 0
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/chiller3/bcr/ui/Screen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ fun AppScreen(
},
containerColor = PreferenceDefaults.containerColor,
) { contentPadding ->
val outerPadding = contentPadding.copy(bottom = 0.dp)
val innerPadding = contentPadding.copy(start = 0.dp, top = 0.dp, end = 0.dp)
val outerPadding = contentPadding.copy(start = 0.dp, end = 0.dp, bottom = 0.dp)
val innerPadding = contentPadding.copy(top = 0.dp)

Box(modifier = Modifier.padding(outerPadding)) {
content(AppScreenParams(
Expand Down