mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Fixes for stopping now playing
This commit is contained in:
parent
c443ddb6c4
commit
3359c8ac32
5 changed files with 71 additions and 29 deletions
|
|
@ -96,7 +96,13 @@ class MusicService
|
||||||
}
|
}
|
||||||
mediaSession?.release()
|
mediaSession?.release()
|
||||||
mediaSession = null
|
mediaSession = null
|
||||||
onMain { player.stop() }
|
onMain {
|
||||||
|
player.stop()
|
||||||
|
player.setMediaItems(emptyList())
|
||||||
|
}
|
||||||
|
_state.update {
|
||||||
|
MusicServiceState.EMPTY
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,7 +242,6 @@ class MusicService
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun moveQueue(
|
suspend fun moveQueue(
|
||||||
|
|
@ -256,7 +261,10 @@ class MusicService
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun playIndex(index: Int) {
|
suspend fun playIndex(index: Int) {
|
||||||
onMain { player.seekTo(index, 0L) }
|
onMain {
|
||||||
|
player.seekTo(index, 0L)
|
||||||
|
player.play()
|
||||||
|
}
|
||||||
// MusicPlayerListener will update state
|
// MusicPlayerListener will update state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,15 +293,21 @@ data class MusicServiceState(
|
||||||
val queueSize: Int,
|
val queueSize: Int,
|
||||||
val currentIndex: Int,
|
val currentIndex: Int,
|
||||||
val currentItemId: UUID?,
|
val currentItemId: UUID?,
|
||||||
val isPlaying: Boolean,
|
val status: NowPlayingStatus,
|
||||||
val currentItemTitle: String?,
|
val currentItemTitle: String?,
|
||||||
val loadingState: LoadingState = LoadingState.Pending,
|
val loadingState: LoadingState = LoadingState.Pending,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
val EMPTY = MusicServiceState(0L, 0, 0, null, false, null)
|
val EMPTY = MusicServiceState(0L, 0, 0, null, NowPlayingStatus.IDLE, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class NowPlayingStatus {
|
||||||
|
PLAYING,
|
||||||
|
PAUSED,
|
||||||
|
IDLE,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listens to [Player] events and updates the [StateFlow]
|
* Listens to [Player] events and updates the [StateFlow]
|
||||||
*/
|
*/
|
||||||
|
|
@ -307,7 +321,7 @@ private class MusicPlayerListener(
|
||||||
it.copy(
|
it.copy(
|
||||||
queueSize = player.mediaItemCount,
|
queueSize = player.mediaItemCount,
|
||||||
currentIndex = player.currentMediaItemIndex,
|
currentIndex = player.currentMediaItemIndex,
|
||||||
isPlaying = player.isPlaying,
|
status = if (player.isPlaying) NowPlayingStatus.PLAYING else NowPlayingStatus.IDLE,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -316,7 +330,7 @@ private class MusicPlayerListener(
|
||||||
Timber.v("MusicPlayerListener onIsPlayingChanged")
|
Timber.v("MusicPlayerListener onIsPlayingChanged")
|
||||||
state.update {
|
state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
isPlaying = isPlaying,
|
status = if (isPlaying) NowPlayingStatus.PLAYING else NowPlayingStatus.PAUSED,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import timber.log.Timber
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
import kotlin.time.Duration.Companion.minutes
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class NavDrawerService
|
class NavDrawerService
|
||||||
|
|
@ -80,22 +81,33 @@ class NavDrawerService
|
||||||
coroutineScope.launchDefault {
|
coroutineScope.launchDefault {
|
||||||
musicService.state.collectLatest { music ->
|
musicService.state.collectLatest { music ->
|
||||||
Timber.v("MusicService updated")
|
Timber.v("MusicService updated")
|
||||||
if (music.isPlaying) {
|
when (music.status) {
|
||||||
_state.update {
|
NowPlayingStatus.PLAYING -> {
|
||||||
it.copy(
|
_state.update {
|
||||||
nowPlayingEnabled = true,
|
it.copy(
|
||||||
nowPlayingTitle = music.currentItemTitle,
|
nowPlayingEnabled = true,
|
||||||
)
|
nowPlayingTitle = music.currentItemTitle,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Don't immediately remove the now playing
|
NowPlayingStatus.IDLE -> {
|
||||||
// TODO need better now playing state to distinguish between paused & stopped
|
_state.update {
|
||||||
delay(30_000)
|
it.copy(
|
||||||
_state.update {
|
nowPlayingEnabled = false,
|
||||||
it.copy(
|
nowPlayingTitle = null,
|
||||||
nowPlayingEnabled = false,
|
)
|
||||||
nowPlayingTitle = null,
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
|
NowPlayingStatus.PAUSED -> {
|
||||||
|
delay(2.minutes)
|
||||||
|
_state.update {
|
||||||
|
it.copy(
|
||||||
|
nowPlayingEnabled = false,
|
||||||
|
nowPlayingTitle = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.github.damontecres.wholphin.ui.detail.music
|
||||||
import androidx.annotation.OptIn
|
import androidx.annotation.OptIn
|
||||||
import androidx.compose.foundation.BorderStroke
|
import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.focusGroup
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
|
@ -70,7 +71,7 @@ fun NowPlayingButtons(
|
||||||
|
|
||||||
val onControllerInteraction = remember { { controllerViewState.pulseControls() } }
|
val onControllerInteraction = remember { { controllerViewState.pulseControls() } }
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier,
|
modifier = modifier.focusGroup(),
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(buttonSpacing),
|
horizontalArrangement = Arrangement.spacedBy(buttonSpacing),
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,9 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
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.FocusDirection
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
|
import androidx.compose.ui.focus.focusProperties
|
||||||
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.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
|
@ -151,6 +153,10 @@ fun NowPlayingOverlay(
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.onFocusChanged {
|
.onFocusChanged {
|
||||||
queueHasFocus = it.hasFocus
|
queueHasFocus = it.hasFocus
|
||||||
|
}.focusProperties {
|
||||||
|
onExit = {
|
||||||
|
if (requestedFocusDirection == FocusDirection.Up) focusRequester.requestFocus()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
itemsIndexed(queue, key = { _, song -> song.key }) { index, song ->
|
itemsIndexed(queue, key = { _, song -> song.key }) { index, song ->
|
||||||
|
|
@ -162,7 +168,10 @@ fun NowPlayingOverlay(
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.colorScheme.surface.copy(alpha = .75f),
|
color = MaterialTheme.colorScheme.surface.copy(alpha = .75f),
|
||||||
shape = RoundedCornerShape(8.dp),
|
shape = RoundedCornerShape(8.dp),
|
||||||
).animateItem(),
|
).onFocusChanged {
|
||||||
|
if (it.hasFocus) showButtons = index < 3
|
||||||
|
controllerViewState.pulseControls()
|
||||||
|
}.animateItem(),
|
||||||
) {
|
) {
|
||||||
SongListItem(
|
SongListItem(
|
||||||
title = song.title,
|
title = song.title,
|
||||||
|
|
@ -176,10 +185,7 @@ fun NowPlayingOverlay(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.onFocusChanged {
|
.ifElse(
|
||||||
if (it.isFocused) showButtons = index < 3
|
|
||||||
controllerViewState.pulseControls()
|
|
||||||
}.ifElse(
|
|
||||||
index == 0,
|
index == 0,
|
||||||
Modifier.focusRequester(firstFocusRequester),
|
Modifier.focusRequester(firstFocusRequester),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ import com.github.damontecres.wholphin.data.model.JellyfinUser
|
||||||
import com.github.damontecres.wholphin.preferences.AppThemeColors
|
import com.github.damontecres.wholphin.preferences.AppThemeColors
|
||||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||||
import com.github.damontecres.wholphin.services.BackdropService
|
import com.github.damontecres.wholphin.services.BackdropService
|
||||||
|
import com.github.damontecres.wholphin.services.MusicService
|
||||||
import com.github.damontecres.wholphin.services.NavDrawerService
|
import com.github.damontecres.wholphin.services.NavDrawerService
|
||||||
import com.github.damontecres.wholphin.services.NavigationManager
|
import com.github.damontecres.wholphin.services.NavigationManager
|
||||||
import com.github.damontecres.wholphin.services.SetupDestination
|
import com.github.damontecres.wholphin.services.SetupDestination
|
||||||
|
|
@ -108,6 +109,7 @@ class NavDrawerViewModel
|
||||||
val navigationManager: NavigationManager,
|
val navigationManager: NavigationManager,
|
||||||
val setupNavigationManager: SetupNavigationManager,
|
val setupNavigationManager: SetupNavigationManager,
|
||||||
val backdropService: BackdropService,
|
val backdropService: BackdropService,
|
||||||
|
private val musicService: MusicService,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val state = navDrawerService.state
|
val state = navDrawerService.state
|
||||||
|
|
||||||
|
|
@ -204,6 +206,13 @@ class NavDrawerViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun navigateToSetup(userList: SetupDestination) {
|
||||||
|
viewModelScope.launchDefault {
|
||||||
|
musicService.stop()
|
||||||
|
setupNavigationManager.navigateTo(userList)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface NavDrawerItem {
|
sealed interface NavDrawerItem {
|
||||||
|
|
@ -334,7 +343,7 @@ fun NavDrawer(
|
||||||
drawerOpen = isOpen,
|
drawerOpen = isOpen,
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setupNavigationManager.navigateTo(
|
viewModel.navigateToSetup(
|
||||||
SetupDestination.UserList(server),
|
SetupDestination.UserList(server),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue