mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Better shuffle & repeat buttons
This commit is contained in:
parent
ff0417b7e7
commit
5a4528541a
1 changed files with 198 additions and 21 deletions
|
|
@ -1,14 +1,29 @@
|
||||||
package com.github.damontecres.wholphin.ui.detail.music
|
package com.github.damontecres.wholphin.ui.detail.music
|
||||||
|
|
||||||
import androidx.annotation.OptIn
|
import androidx.annotation.OptIn
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.offset
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.focus.onFocusChanged
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.ui.compose.state.rememberNextButtonState
|
import androidx.media3.ui.compose.state.rememberNextButtonState
|
||||||
|
|
@ -16,13 +31,20 @@ import androidx.media3.ui.compose.state.rememberPlayPauseButtonState
|
||||||
import androidx.media3.ui.compose.state.rememberPreviousButtonState
|
import androidx.media3.ui.compose.state.rememberPreviousButtonState
|
||||||
import androidx.media3.ui.compose.state.rememberRepeatButtonState
|
import androidx.media3.ui.compose.state.rememberRepeatButtonState
|
||||||
import androidx.media3.ui.compose.state.rememberShuffleButtonState
|
import androidx.media3.ui.compose.state.rememberShuffleButtonState
|
||||||
|
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||||
import androidx.tv.material3.MaterialTheme
|
import androidx.tv.material3.MaterialTheme
|
||||||
|
import androidx.tv.material3.Text
|
||||||
import com.github.damontecres.wholphin.R
|
import com.github.damontecres.wholphin.R
|
||||||
|
import com.github.damontecres.wholphin.ui.AppColors
|
||||||
|
import com.github.damontecres.wholphin.ui.FontAwesome
|
||||||
|
import com.github.damontecres.wholphin.ui.PreviewTvSpec
|
||||||
|
import com.github.damontecres.wholphin.ui.components.Button
|
||||||
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.PlaybackAction
|
||||||
import com.github.damontecres.wholphin.ui.playback.PlaybackButtons
|
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 com.github.damontecres.wholphin.ui.playback.buttonSpacing
|
||||||
|
import com.github.damontecres.wholphin.ui.theme.PreviewInteractionSource
|
||||||
|
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
@OptIn(UnstableApi::class)
|
@OptIn(UnstableApi::class)
|
||||||
|
|
@ -74,35 +96,190 @@ fun NowPlayingButtons(
|
||||||
horizontalArrangement = Arrangement.spacedBy(buttonSpacing),
|
horizontalArrangement = Arrangement.spacedBy(buttonSpacing),
|
||||||
modifier = Modifier.align(Alignment.CenterEnd),
|
modifier = Modifier.align(Alignment.CenterEnd),
|
||||||
) {
|
) {
|
||||||
PlaybackFaButton(
|
ShuffleButton(
|
||||||
iconRes = R.string.fa_shuffle,
|
active = shuffleState.shuffleOn,
|
||||||
|
enabled = shuffleState.isEnabled,
|
||||||
onClick = {
|
onClick = {
|
||||||
shuffleState.onClick()
|
shuffleState.onClick()
|
||||||
},
|
},
|
||||||
onControllerInteraction = { controllerViewState.pulseControls() },
|
onControllerInteraction = { controllerViewState.pulseControls() },
|
||||||
textColor =
|
|
||||||
if (shuffleState.shuffleOn) {
|
|
||||||
MaterialTheme.colorScheme.secondary
|
|
||||||
} else {
|
|
||||||
Color.Unspecified
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
PlaybackFaButton(
|
RepeatButton(
|
||||||
iconRes = R.string.fa_repeat,
|
repeatMode = repeatState.repeatModeState,
|
||||||
|
enabled = repeatState.isEnabled,
|
||||||
onClick = {
|
onClick = {
|
||||||
repeatState.onClick()
|
repeatState.onClick()
|
||||||
},
|
},
|
||||||
onControllerInteraction = { controllerViewState.pulseControls() },
|
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
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ShuffleButton(
|
||||||
|
active: Boolean,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
onControllerInteraction: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||||
|
) {
|
||||||
|
val selectedColor = MaterialTheme.colorScheme.border
|
||||||
|
val focused by interactionSource.collectIsFocusedAsState()
|
||||||
|
Button(
|
||||||
|
enabled = enabled,
|
||||||
|
onClick = onClick,
|
||||||
|
// shape = ButtonDefaults.shape(CircleShape),
|
||||||
|
colors =
|
||||||
|
ClickableSurfaceDefaults.colors(
|
||||||
|
containerColor = AppColors.TransparentBlack25,
|
||||||
|
focusedContainerColor = selectedColor,
|
||||||
|
),
|
||||||
|
contentPadding = PaddingValues(4.dp),
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
modifier =
|
||||||
|
modifier
|
||||||
|
.size(36.dp, 36.dp)
|
||||||
|
.onFocusChanged { onControllerInteraction.invoke() },
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.fa_shuffle),
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontFamily = FontAwesome,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
color =
|
||||||
|
when {
|
||||||
|
focused && active -> MaterialTheme.colorScheme.onSurface
|
||||||
|
focused && !active -> MaterialTheme.colorScheme.surface
|
||||||
|
!focused && active -> MaterialTheme.colorScheme.onSurface
|
||||||
|
else -> MaterialTheme.colorScheme.onSurface.copy(alpha = .5f)
|
||||||
|
},
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.CenterVertically),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RepeatButton(
|
||||||
|
repeatMode: Int,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
onControllerInteraction: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||||
|
) {
|
||||||
|
val selectedColor = MaterialTheme.colorScheme.border
|
||||||
|
val focused by interactionSource.collectIsFocusedAsState()
|
||||||
|
Button(
|
||||||
|
enabled = enabled,
|
||||||
|
onClick = onClick,
|
||||||
|
// shape = ButtonDefaults.shape(CircleShape),
|
||||||
|
colors =
|
||||||
|
ClickableSurfaceDefaults.colors(
|
||||||
|
containerColor = AppColors.TransparentBlack25,
|
||||||
|
focusedContainerColor = selectedColor,
|
||||||
|
),
|
||||||
|
contentPadding = PaddingValues(4.dp),
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
modifier =
|
||||||
|
modifier
|
||||||
|
.size(36.dp, 36.dp)
|
||||||
|
.onFocusChanged { onControllerInteraction.invoke() },
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.CenterVertically),
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.fa_repeat),
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontFamily = FontAwesome,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
color =
|
||||||
|
if (focused) {
|
||||||
|
when (repeatMode) {
|
||||||
|
Player.REPEAT_MODE_ALL -> MaterialTheme.colorScheme.onSurface
|
||||||
|
Player.REPEAT_MODE_ONE -> MaterialTheme.colorScheme.onSurface
|
||||||
|
else -> MaterialTheme.colorScheme.surface
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
when (repeatMode) {
|
||||||
|
Player.REPEAT_MODE_ALL -> MaterialTheme.colorScheme.onSurface
|
||||||
|
Player.REPEAT_MODE_ONE -> MaterialTheme.colorScheme.onSurface
|
||||||
|
else -> MaterialTheme.colorScheme.onSurface.copy(alpha = .5f)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.Center),
|
||||||
|
)
|
||||||
|
if (repeatMode == Player.REPEAT_MODE_ONE) {
|
||||||
|
Text(
|
||||||
|
text = "1",
|
||||||
|
fontSize = 10.sp,
|
||||||
|
color = MaterialTheme.colorScheme.surface,
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.offset(x = 4.dp)
|
||||||
|
.background(
|
||||||
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
|
shape = RoundedCornerShape(1.dp),
|
||||||
|
).align(Alignment.BottomStart),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreviewTvSpec
|
||||||
|
@Composable
|
||||||
|
fun ShuffleButtonPreview() {
|
||||||
|
val source = remember { PreviewInteractionSource() }
|
||||||
|
WholphinTheme {
|
||||||
|
Column {
|
||||||
|
Row {
|
||||||
|
RepeatButton(
|
||||||
|
repeatMode = Player.REPEAT_MODE_OFF,
|
||||||
|
onClick = {},
|
||||||
|
onControllerInteraction = {},
|
||||||
|
)
|
||||||
|
RepeatButton(
|
||||||
|
repeatMode = Player.REPEAT_MODE_ALL,
|
||||||
|
onClick = {},
|
||||||
|
onControllerInteraction = {},
|
||||||
|
)
|
||||||
|
RepeatButton(
|
||||||
|
repeatMode = Player.REPEAT_MODE_ONE,
|
||||||
|
onClick = {},
|
||||||
|
onControllerInteraction = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Row {
|
||||||
|
RepeatButton(
|
||||||
|
repeatMode = Player.REPEAT_MODE_OFF,
|
||||||
|
onClick = {},
|
||||||
|
onControllerInteraction = {},
|
||||||
|
interactionSource = source,
|
||||||
|
)
|
||||||
|
RepeatButton(
|
||||||
|
repeatMode = Player.REPEAT_MODE_ALL,
|
||||||
|
onClick = {},
|
||||||
|
onControllerInteraction = {},
|
||||||
|
interactionSource = source,
|
||||||
|
)
|
||||||
|
RepeatButton(
|
||||||
|
repeatMode = Player.REPEAT_MODE_ONE,
|
||||||
|
onClick = {},
|
||||||
|
onControllerInteraction = {},
|
||||||
|
interactionSource = source,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue