sonodrill

Sonodrill, app iOS/Android d’entraînement musical (repères, boucles, vitesse), Kotlin Multiplatform + Compose
git clone https://git.schurger.org/sonodrill.git
Log | Files | Refs

commit 2f76dfe373c5ff81e9ed0fcab5f818dab46599bf
parent d09cebe4d01159eb5288734e1c7fc31065b1940b
Author: Jean Schurger <jean@schurger.org>
Date:   Wed,  1 Apr 2026 08:46:14 -0400

Move loop toggles into transport row, remove skip ±15s buttons

Loop buttons (mark loop, full loop) now sit alongside prev/next/play
in the main transport row for quicker access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Diffstat:
McomposeApp/src/commonMain/kotlin/ubi2/sonodrill/ui/player/player_screen.kt | 79+++++++++++++++++++++++++++++++------------------------------------------------
1 file changed, 31 insertions(+), 48 deletions(-)

diff --git a/composeApp/src/commonMain/kotlin/ubi2/sonodrill/ui/player/player_screen.kt b/composeApp/src/commonMain/kotlin/ubi2/sonodrill/ui/player/player_screen.kt @@ -84,15 +84,32 @@ fun PlayerScreen(vm: PlayerViewModel, on_back: () -> Unit) { Spacer(Modifier.height(8.dp)) - // Transport controls + // Transport controls with loop buttons Row( modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp), horizontalArrangement = Arrangement.SpaceEvenly, verticalAlignment = Alignment.CenterVertically, ) { - IconButton(onClick = { vm.skip(-15_000) }) { - Icon(Icons.Default.FastRewind, "-15s", modifier = Modifier.size(24.dp)) + val mark_loop_active = loop_state.enabled && loop_state.mark_a != null && loop_state.mark_a!!.id != "_full_a" + val full_loop_active = loop_state.enabled && loop_state.mark_a?.id == "_full_a" + + // Mark loop toggle + if (mark_loop_active) { + FilledIconButton(onClick = { vm.toggle_mark_loop() }, enabled = marks.size >= 2) { + Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy((-2).dp)) { + Icon(Icons.Default.Repeat, null, modifier = Modifier.size(20.dp)) + Icon(Icons.Default.Bookmark, null, modifier = Modifier.size(12.dp)) + } + } + } else { + OutlinedIconButton(onClick = { vm.toggle_mark_loop() }, enabled = marks.size >= 2) { + Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy((-2).dp)) { + Icon(Icons.Default.Repeat, null, modifier = Modifier.size(20.dp)) + Icon(Icons.Default.Bookmark, null, modifier = Modifier.size(12.dp)) + } + } } + IconButton(onClick = { vm.prev_mark() }) { Icon(Icons.Default.SkipPrevious, "Previous mark") } @@ -109,14 +126,22 @@ fun PlayerScreen(vm: PlayerViewModel, on_back: () -> Unit) { IconButton(onClick = { vm.next_mark() }) { Icon(Icons.Default.SkipNext, "Next mark") } - IconButton(onClick = { vm.skip(15_000) }) { - Icon(Icons.Default.FastForward, "+15s", modifier = Modifier.size(24.dp)) + + // Full loop toggle + if (full_loop_active) { + FilledIconButton(onClick = { vm.toggle_full_loop() }) { + Icon(Icons.Default.Repeat, null, modifier = Modifier.size(22.dp)) + } + } else { + OutlinedIconButton(onClick = { vm.toggle_full_loop() }) { + Icon(Icons.Default.Repeat, null, modifier = Modifier.size(22.dp)) + } } } // Action buttons row Row( - Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 4.dp), + Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 4.dp).padding(bottom = 8.dp), horizontalArrangement = Arrangement.SpaceEvenly, verticalAlignment = Alignment.CenterVertically, ) { @@ -140,48 +165,6 @@ fun PlayerScreen(vm: PlayerViewModel, on_back: () -> Unit) { } } - // Loop buttons row - Row( - Modifier.fillMaxWidth().padding(horizontal = 16.dp).padding(bottom = 8.dp), - horizontalArrangement = Arrangement.SpaceEvenly, - verticalAlignment = Alignment.CenterVertically, - ) { - val mark_loop_active = loop_state.enabled && loop_state.mark_a != null && loop_state.mark_a!!.id != "_full_a" - val full_loop_active = loop_state.enabled && loop_state.mark_a?.id == "_full_a" - - if (mark_loop_active) { - FilledIconButton( - onClick = { vm.toggle_mark_loop() }, - enabled = marks.size >= 2, - ) { - Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy((-2).dp)) { - Icon(Icons.Default.Repeat, "Mark Loop", modifier = Modifier.size(22.dp)) - Icon(Icons.Default.Bookmark, null, modifier = Modifier.size(14.dp)) - } - } - } else { - OutlinedIconButton( - onClick = { vm.toggle_mark_loop() }, - enabled = marks.size >= 2, - ) { - Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy((-2).dp)) { - Icon(Icons.Default.Repeat, "Mark Loop", modifier = Modifier.size(22.dp)) - Icon(Icons.Default.Bookmark, null, modifier = Modifier.size(14.dp)) - } - } - } - - if (full_loop_active) { - FilledIconButton(onClick = { vm.toggle_full_loop() }) { - Icon(Icons.Default.Repeat, "Full Loop", modifier = Modifier.size(22.dp)) - } - } else { - OutlinedIconButton(onClick = { vm.toggle_full_loop() }) { - Icon(Icons.Default.Repeat, "Full Loop", modifier = Modifier.size(22.dp)) - } - } - } - Spacer(Modifier.height(8.dp)) } }