mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Dialog show/hide lyrics
This commit is contained in:
parent
59a0bee0a7
commit
18e3268638
6 changed files with 102 additions and 6 deletions
|
|
@ -68,6 +68,7 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.OkHttpClient
|
||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||
import org.jellyfin.sdk.model.serializer.toUUID
|
||||
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
|
@ -213,7 +214,12 @@ class MainActivity : AppCompatActivity() {
|
|||
) {
|
||||
val requestedDestination =
|
||||
remember(intent) {
|
||||
intent?.let(::extractDestination) ?: Destination.Home()
|
||||
intent?.let(::extractDestination) ?: // Destination.Home()
|
||||
// TODO
|
||||
Destination.MediaItem(
|
||||
itemId = "011ef0c7ca45684f2cd9dd3b020ca5f6".toUUID(),
|
||||
type = BaseItemKind.MUSIC_ALBUM,
|
||||
)
|
||||
}
|
||||
MainContent(
|
||||
backStack = setupNavigationManager.backStack,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.github.damontecres.wholphin.ui.detail.music
|
||||
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
||||
|
|
@ -10,6 +11,7 @@ import androidx.compose.foundation.layout.Column
|
|||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
|
|
@ -19,6 +21,7 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
|
|
@ -31,6 +34,7 @@ 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.Border
|
||||
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
|
|
@ -41,7 +45,9 @@ 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.PlaybackAction
|
||||
import com.github.damontecres.wholphin.ui.playback.PlaybackButton
|
||||
import com.github.damontecres.wholphin.ui.playback.PlaybackButtons
|
||||
import com.github.damontecres.wholphin.ui.playback.PlaybackDialogType
|
||||
import com.github.damontecres.wholphin.ui.playback.buttonSpacing
|
||||
import com.github.damontecres.wholphin.ui.theme.PreviewInteractionSource
|
||||
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
||||
|
|
@ -53,6 +59,7 @@ fun NowPlayingButtons(
|
|||
player: Player,
|
||||
controllerViewState: ControllerViewState,
|
||||
initialFocusRequester: FocusRequester,
|
||||
onClickMore: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val playPauseState = rememberPlayPauseButtonState(player)
|
||||
|
|
@ -60,13 +67,30 @@ fun NowPlayingButtons(
|
|||
val nextState = rememberNextButtonState(player)
|
||||
val shuffleState = rememberShuffleButtonState(player)
|
||||
val repeatState = rememberRepeatButtonState(player)
|
||||
|
||||
val onControllerInteraction = remember { { controllerViewState.pulseControls() } }
|
||||
Box(
|
||||
modifier = modifier,
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(buttonSpacing),
|
||||
modifier = Modifier.align(Alignment.CenterStart),
|
||||
) {
|
||||
PlaybackButton(
|
||||
iconRes = R.drawable.baseline_more_vert_96,
|
||||
onClick = {
|
||||
onControllerInteraction.invoke()
|
||||
onClickMore.invoke()
|
||||
},
|
||||
enabled = true,
|
||||
onControllerInteraction = onControllerInteraction,
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
PlaybackButtons(
|
||||
player = player,
|
||||
initialFocusRequester = initialFocusRequester,
|
||||
onControllerInteraction = { controllerViewState.pulseControls() },
|
||||
onControllerInteraction = onControllerInteraction,
|
||||
onPlaybackActionClick = {
|
||||
when (it) {
|
||||
PlaybackAction.Next -> {
|
||||
|
|
@ -102,7 +126,7 @@ fun NowPlayingButtons(
|
|||
onClick = {
|
||||
shuffleState.onClick()
|
||||
},
|
||||
onControllerInteraction = { controllerViewState.pulseControls() },
|
||||
onControllerInteraction = onControllerInteraction,
|
||||
)
|
||||
RepeatButton(
|
||||
repeatMode = repeatState.repeatModeState,
|
||||
|
|
@ -110,7 +134,7 @@ fun NowPlayingButtons(
|
|||
onClick = {
|
||||
repeatState.onClick()
|
||||
},
|
||||
onControllerInteraction = { controllerViewState.pulseControls() },
|
||||
onControllerInteraction = onControllerInteraction,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ fun NowPlayingOverlay(
|
|||
current: AudioItem?,
|
||||
queue: List<AudioItem>,
|
||||
controllerViewState: ControllerViewState,
|
||||
onClickMore: () -> Unit,
|
||||
onMoveQueue: (Int, MoveDirection) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
|
@ -122,6 +123,7 @@ fun NowPlayingOverlay(
|
|||
player = player,
|
||||
controllerViewState = controllerViewState,
|
||||
initialFocusRequester = focusRequester,
|
||||
onClickMore = onClickMore,
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.github.damontecres.wholphin.ui.detail.music
|
||||
|
||||
import android.view.Gravity
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
|
|
@ -21,23 +22,29 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import coil3.compose.AsyncImage
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.services.rememberQueue
|
||||
import com.github.damontecres.wholphin.ui.AppColors
|
||||
import com.github.damontecres.wholphin.ui.components.LoadingPage
|
||||
import com.github.damontecres.wholphin.ui.playback.BottomDialog
|
||||
import com.github.damontecres.wholphin.ui.playback.BottomDialogItem
|
||||
import com.github.damontecres.wholphin.ui.playback.PlaybackKeyHandler
|
||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||
import com.github.damontecres.wholphin.util.LoadingState
|
||||
|
|
@ -90,6 +97,10 @@ fun NowPlayingPage(
|
|||
)
|
||||
}
|
||||
|
||||
var showMoreDialog by remember { mutableStateOf(false) }
|
||||
var lyricsActive by remember { mutableStateOf(true) }
|
||||
var showDebugInfo by remember { mutableStateOf(true) }
|
||||
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
LaunchedEffect(Unit) { focusRequester.tryRequestFocus() }
|
||||
Box(modifier) {
|
||||
|
|
@ -106,7 +117,7 @@ fun NowPlayingPage(
|
|||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = state.lyrics != null && state.lyrics?.lyrics?.isNotEmpty() == true,
|
||||
visible = lyricsActive && state.hasLyrics,
|
||||
enter = expandHorizontally(expandFrom = Alignment.Start),
|
||||
exit = shrinkHorizontally(shrinkTowards = Alignment.Start),
|
||||
modifier = Modifier,
|
||||
|
|
@ -177,6 +188,7 @@ fun NowPlayingPage(
|
|||
queue = queue,
|
||||
controllerViewState = controllerViewState,
|
||||
onMoveQueue = { index, direction -> viewModel.moveQueue(index, direction) },
|
||||
onClickMore = { showMoreDialog = true },
|
||||
modifier =
|
||||
Modifier
|
||||
.background(AppColors.TransparentBlack50)
|
||||
|
|
@ -187,4 +199,50 @@ fun NowPlayingPage(
|
|||
LoadingPage(focusEnabled = false)
|
||||
}
|
||||
}
|
||||
if (showMoreDialog) {
|
||||
NowPlayingBottomDialog(
|
||||
showDebugInfo = showDebugInfo,
|
||||
lyricsActive = lyricsActive,
|
||||
songHasLyrics = state.hasLyrics,
|
||||
onDismissRequest = { showMoreDialog = false },
|
||||
onClickShowDebug = { showDebugInfo = !showDebugInfo },
|
||||
onClickLyrics = { lyricsActive = !lyricsActive },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NowPlayingBottomDialog(
|
||||
showDebugInfo: Boolean,
|
||||
lyricsActive: Boolean,
|
||||
songHasLyrics: Boolean,
|
||||
onDismissRequest: () -> Unit,
|
||||
onClickShowDebug: () -> Unit,
|
||||
onClickLyrics: () -> Unit,
|
||||
) {
|
||||
val choices =
|
||||
mapOf(
|
||||
BottomDialogItem(
|
||||
data = 0,
|
||||
headline = stringResource(if (showDebugInfo) R.string.hide_debug_info else R.string.show_debug_info),
|
||||
supporting = null,
|
||||
) to onClickShowDebug,
|
||||
BottomDialogItem(
|
||||
data = 0,
|
||||
headline = stringResource(if (lyricsActive) R.string.hide_lyrics else R.string.show_lyrics),
|
||||
supporting = if (songHasLyrics) stringResource(R.string.song_has_lyrics) else null,
|
||||
) to onClickLyrics,
|
||||
)
|
||||
|
||||
BottomDialog(
|
||||
choices = choices.keys.toList(),
|
||||
onDismissRequest = {
|
||||
onDismissRequest.invoke()
|
||||
},
|
||||
onSelectChoice = { _, choice ->
|
||||
choices[choice]?.invoke()
|
||||
onDismissRequest.invoke()
|
||||
},
|
||||
gravity = Gravity.START,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,4 +9,6 @@ data class NowPlayingState(
|
|||
val musicServiceState: MusicServiceState,
|
||||
val lyrics: LyricDto? = null,
|
||||
val currentLyricIndex: Int? = null,
|
||||
)
|
||||
) {
|
||||
val hasLyrics: Boolean get() = lyrics != null && lyrics.lyrics.isNotEmpty()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -733,6 +733,10 @@
|
|||
<string name="popular_songs">Popular songs</string>
|
||||
<string name="play_next">Play next</string>
|
||||
<string name="music_videos">Music videos</string>
|
||||
<string name="lyrics">Lyrics</string>
|
||||
<string name="hide_lyrics">Hide lyrics</string>
|
||||
<string name="show_lyrics">Show lyrics</string>
|
||||
<string name="song_has_lyrics">Song has lyrics</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue