Move buttons to new composable

This commit is contained in:
Damontecres 2026-03-02 16:53:27 -05:00
parent 7044b4aa32
commit ff0417b7e7
No known key found for this signature in database
3 changed files with 115 additions and 66 deletions

View file

@ -0,0 +1,108 @@
package com.github.damontecres.wholphin.ui.detail.music
import androidx.annotation.OptIn
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.graphics.Color
import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
import androidx.media3.ui.compose.state.rememberNextButtonState
import androidx.media3.ui.compose.state.rememberPlayPauseButtonState
import androidx.media3.ui.compose.state.rememberPreviousButtonState
import androidx.media3.ui.compose.state.rememberRepeatButtonState
import androidx.media3.ui.compose.state.rememberShuffleButtonState
import androidx.tv.material3.MaterialTheme
import com.github.damontecres.wholphin.R
import com.github.damontecres.wholphin.ui.playback.ControllerViewState
import com.github.damontecres.wholphin.ui.playback.PlaybackAction
import com.github.damontecres.wholphin.ui.playback.PlaybackButtons
import com.github.damontecres.wholphin.ui.playback.PlaybackFaButton
import com.github.damontecres.wholphin.ui.playback.buttonSpacing
import kotlin.time.Duration.Companion.seconds
@OptIn(UnstableApi::class)
@Composable
fun NowPlayingButtons(
player: Player,
controllerViewState: ControllerViewState,
initialFocusRequester: FocusRequester,
modifier: Modifier = Modifier,
) {
val playPauseState = rememberPlayPauseButtonState(player)
val previousState = rememberPreviousButtonState(player)
val nextState = rememberNextButtonState(player)
val shuffleState = rememberShuffleButtonState(player)
val repeatState = rememberRepeatButtonState(player)
Box(
modifier = modifier,
) {
PlaybackButtons(
player = player,
initialFocusRequester = initialFocusRequester,
onControllerInteraction = { controllerViewState.pulseControls() },
onPlaybackActionClick = {
when (it) {
PlaybackAction.Next -> {
nextState.onClick()
}
PlaybackAction.Previous -> {
previousState.onClick()
}
is PlaybackAction.ToggleCaptions -> {
TODO()
}
else -> {}
}
},
showPlay = playPauseState.showPlay,
previousEnabled = previousState.isEnabled,
nextEnabled = nextState.isEnabled,
seekBack = 10.seconds,
skipBackOnResume = null,
seekForward = 30.seconds, // TODO
modifier = Modifier.align(Alignment.Center),
)
Row(
horizontalArrangement = Arrangement.spacedBy(buttonSpacing),
modifier = Modifier.align(Alignment.CenterEnd),
) {
PlaybackFaButton(
iconRes = R.string.fa_shuffle,
onClick = {
shuffleState.onClick()
},
onControllerInteraction = { controllerViewState.pulseControls() },
textColor =
if (shuffleState.shuffleOn) {
MaterialTheme.colorScheme.secondary
} else {
Color.Unspecified
},
)
PlaybackFaButton(
iconRes = R.string.fa_repeat,
onClick = {
repeatState.onClick()
},
onControllerInteraction = { controllerViewState.pulseControls() },
textColor =
when (repeatState.repeatModeState) {
Player.REPEAT_MODE_ALL -> MaterialTheme.colorScheme.secondary
// TODO
Player.REPEAT_MODE_ONE -> MaterialTheme.colorScheme.tertiary
else -> Color.Unspecified
},
)
}
}
}

View file

@ -33,7 +33,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.media3.common.Player import androidx.media3.common.Player
@ -50,16 +49,12 @@ import com.github.damontecres.wholphin.data.model.AudioItem
import com.github.damontecres.wholphin.ui.ifElse import com.github.damontecres.wholphin.ui.ifElse
import com.github.damontecres.wholphin.ui.main.settings.MoveDirection import com.github.damontecres.wholphin.ui.main.settings.MoveDirection
import com.github.damontecres.wholphin.ui.playback.ControllerViewState import com.github.damontecres.wholphin.ui.playback.ControllerViewState
import com.github.damontecres.wholphin.ui.playback.PlaybackAction
import com.github.damontecres.wholphin.ui.playback.PlaybackButtons
import com.github.damontecres.wholphin.ui.playback.PlaybackFaButton
import com.github.damontecres.wholphin.ui.playback.SeekBar import com.github.damontecres.wholphin.ui.playback.SeekBar
import com.github.damontecres.wholphin.ui.preferences.MoveButton import com.github.damontecres.wholphin.ui.preferences.MoveButton
import com.github.damontecres.wholphin.ui.roundSeconds import com.github.damontecres.wholphin.ui.roundSeconds
import com.github.damontecres.wholphin.ui.tryRequestFocus import com.github.damontecres.wholphin.ui.tryRequestFocus
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlin.time.Duration import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
@Composable @Composable
@ -133,69 +128,15 @@ fun NowPlayingOverlay(
Modifier Modifier
.align(Alignment.CenterHorizontally), .align(Alignment.CenterHorizontally),
) { ) {
Row( NowPlayingButtons(
player = player,
controllerViewState = controllerViewState,
initialFocusRequester = focusRequester,
modifier = modifier =
Modifier Modifier
.fillMaxWidth()
.align(Alignment.CenterHorizontally), .align(Alignment.CenterHorizontally),
) { )
PlaybackButtons(
player = player,
initialFocusRequester = focusRequester,
onControllerInteraction = { controllerViewState.pulseControls() },
onPlaybackActionClick = {
when (it) {
PlaybackAction.Next -> {
nextState.onClick()
}
PlaybackAction.Previous -> {
previousState.onClick()
}
is PlaybackAction.ToggleCaptions -> {
TODO()
}
else -> {}
}
},
showPlay = playPauseState.showPlay,
previousEnabled = previousState.isEnabled,
nextEnabled = nextState.isEnabled,
seekBack = 10.seconds,
skipBackOnResume = null,
seekForward = 30.seconds, // TODO
)
PlaybackFaButton(
iconRes = R.string.fa_shuffle,
onClick = {
shuffleState.onClick()
},
onControllerInteraction = { controllerViewState.pulseControls() },
textColor =
if (shuffleState.shuffleOn) {
MaterialTheme.colorScheme.secondary
} else {
Color.Unspecified
},
)
PlaybackFaButton(
iconRes = R.string.fa_repeat,
onClick = {
repeatState.onClick()
},
onControllerInteraction = { controllerViewState.pulseControls() },
textColor =
when (repeatState.repeatModeState) {
Player.REPEAT_MODE_ALL -> MaterialTheme.colorScheme.secondary
// TODO
Player.REPEAT_MODE_ONE -> MaterialTheme.colorScheme.tertiary
else -> Color.Unspecified
},
)
}
} }
if (queue.isEmpty()) { if (queue.isEmpty()) {
Text("No items") Text("No items")

View file

@ -290,7 +290,7 @@ fun SeekBar(
} }
} }
private val buttonSpacing = 12.dp val buttonSpacing = 12.dp
@Composable @Composable
fun LeftPlaybackButtons( fun LeftPlaybackButtons(