settings: make the preamp easier to set exactly

The slider alone is awkward for the two things people actually do with a
preamp: zero it, and nudge it by a known amount.

- Minus and plus buttons flank the slider, stepping one grid notch (0.5
  dB) and disabling at the ends.
- A Reset button sits under it, beside the current value, disabled when
  the value is already zero.
- Both go through the same snapping the slider does, so a button cannot
  land off the grid.
This commit is contained in:
austinried
2026-10-16 13:07:11 +00:00
parent 0b4e1d18bc
commit 31859b66b6
4 changed files with 57 additions and 7 deletions
@@ -17,6 +17,13 @@ internal val REPLAY_GAIN_PREAMP_STEPS =
// storing it.
internal fun snapReplayGainPreampDb(value: Float): Float = (value / REPLAY_GAIN_PREAMP_STEP_DB).roundToInt() * REPLAY_GAIN_PREAMP_STEP_DB
internal fun stepReplayGainPreampDb(
value: Float,
steps: Int,
): Float =
snapReplayGainPreampDb(value + steps * REPLAY_GAIN_PREAMP_STEP_DB)
.coerceIn(MIN_REPLAY_GAIN_PREAMP_DB, MAX_REPLAY_GAIN_PREAMP_DB)
internal fun replayGainModeLabel(
resources: Resources,
mode: ReplayGainMode,
@@ -28,6 +28,7 @@ import androidx.compose.material.icons.rounded.Edit
import androidx.compose.material.icons.rounded.Favorite
import androidx.compose.material.icons.rounded.Info
import androidx.compose.material.icons.rounded.Language
import androidx.compose.material.icons.rounded.Remove
import androidx.compose.material.icons.rounded.Share
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
@@ -779,13 +780,44 @@ private fun ReplayGainPreampDialog(
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.primary,
)
Slider(
value = draft,
onValueChange = { draft = snapReplayGainPreampDb(it) },
valueRange = MIN_REPLAY_GAIN_PREAMP_DB..MAX_REPLAY_GAIN_PREAMP_DB,
steps = REPLAY_GAIN_PREAMP_STEPS,
)
Text(replayGainPreampLabel(resources, draft))
Row(verticalAlignment = Alignment.CenterVertically) {
IconButton(
onClick = { draft = stepReplayGainPreampDb(draft, -1) },
enabled = draft > MIN_REPLAY_GAIN_PREAMP_DB,
) {
Icon(
Icons.Rounded.Remove,
contentDescription = stringResource(R.string.settings_replay_gain_preamp_decrease),
)
}
Slider(
value = draft,
onValueChange = { draft = snapReplayGainPreampDb(it) },
valueRange = MIN_REPLAY_GAIN_PREAMP_DB..MAX_REPLAY_GAIN_PREAMP_DB,
steps = REPLAY_GAIN_PREAMP_STEPS,
modifier = Modifier.weight(1f),
)
IconButton(
onClick = { draft = stepReplayGainPreampDb(draft, 1) },
enabled = draft < MAX_REPLAY_GAIN_PREAMP_DB,
) {
Icon(
Icons.Rounded.Add,
contentDescription = stringResource(R.string.settings_replay_gain_preamp_increase),
)
}
}
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth(),
) {
Text(replayGainPreampLabel(resources, draft))
Spacer(Modifier.weight(1f))
TextButton(
onClick = { draft = 0f },
enabled = draft != 0f,
) { Text(stringResource(R.string.settings_replay_gain_preamp_reset)) }
}
}
},
confirmButton = {