feat: M4c radio similarity-driven candidate pool + 80% queue refresh (closes M4) #28
@@ -30,7 +30,7 @@ import com.fabledsword.minstrel.models.TrackRef
|
|||||||
import com.fabledsword.minstrel.player.PlayerController
|
import com.fabledsword.minstrel.player.PlayerController
|
||||||
import com.fabledsword.minstrel.shared.widgets.EmptyState
|
import com.fabledsword.minstrel.shared.widgets.EmptyState
|
||||||
import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb
|
import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb
|
||||||
import com.fabledsword.minstrel.shared.widgets.track_actions.TrackActionsButton
|
import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsButton
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ import com.fabledsword.minstrel.nav.AlbumDetail
|
|||||||
import com.fabledsword.minstrel.nav.ArtistDetail
|
import com.fabledsword.minstrel.nav.ArtistDetail
|
||||||
import com.fabledsword.minstrel.shared.widgets.EmptyState
|
import com.fabledsword.minstrel.shared.widgets.EmptyState
|
||||||
import com.fabledsword.minstrel.shared.widgets.LikeButton
|
import com.fabledsword.minstrel.shared.widgets.LikeButton
|
||||||
import com.fabledsword.minstrel.shared.widgets.track_actions.TrackActionsButton
|
import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsButton
|
||||||
import com.fabledsword.minstrel.shared.widgets.track_actions.TrackActionsViewModel
|
import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsViewModel
|
||||||
import com.fabledsword.minstrel.theme.FabledSwordFlatTokens
|
import com.fabledsword.minstrel.theme.FabledSwordFlatTokens
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ import com.fabledsword.minstrel.nav.Library
|
|||||||
import com.fabledsword.minstrel.shared.widgets.EmptyState
|
import com.fabledsword.minstrel.shared.widgets.EmptyState
|
||||||
import com.fabledsword.minstrel.shared.widgets.ErrorRetry
|
import com.fabledsword.minstrel.shared.widgets.ErrorRetry
|
||||||
import com.fabledsword.minstrel.shared.widgets.MainAppBarActions
|
import com.fabledsword.minstrel.shared.widgets.MainAppBarActions
|
||||||
import com.fabledsword.minstrel.shared.widgets.track_actions.TrackActionsViewModel
|
import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsViewModel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Library tab. Five-tab TabBar (Artists / Albums / History / Liked /
|
* Library tab. Five-tab TabBar (Artists / Albums / History / Liked /
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import com.fabledsword.minstrel.player.PlayerController
|
|||||||
import com.fabledsword.minstrel.shared.widgets.EmptyState
|
import com.fabledsword.minstrel.shared.widgets.EmptyState
|
||||||
import com.fabledsword.minstrel.shared.widgets.HorizontalScrollRow
|
import com.fabledsword.minstrel.shared.widgets.HorizontalScrollRow
|
||||||
import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb
|
import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb
|
||||||
import com.fabledsword.minstrel.shared.widgets.track_actions.TrackActionsButton
|
import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsButton
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|||||||
@@ -38,6 +38,13 @@ import kotlin.coroutines.resumeWithException
|
|||||||
* the StateFlow projection means each ViewModel doesn't have to attach
|
* the StateFlow projection means each ViewModel doesn't have to attach
|
||||||
* its own Player.Listener.
|
* its own Player.Listener.
|
||||||
*/
|
*/
|
||||||
|
// PlayerController is the UI-side facade over the full Media3 surface
|
||||||
|
// (transport + queue + radio + lifecycle). All the public methods are
|
||||||
|
// legitimately part of one cohesive controller — splitting into
|
||||||
|
// "TransportController", "QueueController", etc. would scatter related
|
||||||
|
// state for no gain. Suppress the per-class function-count cap rather
|
||||||
|
// than fragment.
|
||||||
|
@Suppress("TooManyFunctions")
|
||||||
@Singleton
|
@Singleton
|
||||||
class PlayerController @Inject constructor(
|
class PlayerController @Inject constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ import com.fabledsword.minstrel.nav.AlbumDetail
|
|||||||
import com.fabledsword.minstrel.nav.ArtistDetail
|
import com.fabledsword.minstrel.nav.ArtistDetail
|
||||||
import com.fabledsword.minstrel.nav.Queue
|
import com.fabledsword.minstrel.nav.Queue
|
||||||
import com.fabledsword.minstrel.shared.widgets.EmptyState
|
import com.fabledsword.minstrel.shared.widgets.EmptyState
|
||||||
import com.fabledsword.minstrel.shared.widgets.track_actions.TrackActionsButton
|
import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsButton
|
||||||
import com.fabledsword.minstrel.shared.widgets.track_actions.TrackActionsViewModel
|
import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsViewModel
|
||||||
import com.fabledsword.minstrel.theme.FabledSwordFlatTokens
|
import com.fabledsword.minstrel.theme.FabledSwordFlatTokens
|
||||||
import com.fabledsword.minstrel.theme.LocalActionColors
|
import com.fabledsword.minstrel.theme.LocalActionColors
|
||||||
|
|
||||||
@@ -121,28 +121,36 @@ fun NowPlayingScreen(
|
|||||||
onNext = viewModel::skipToNext,
|
onNext = viewModel::skipToNext,
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(16.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
Row(
|
BottomActionsRow(navController = navController, track = track)
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
) {
|
|
||||||
ViewQueueButton(onClick = { navController.navigate(Queue) })
|
|
||||||
TrackActionsButton(
|
|
||||||
track = track,
|
|
||||||
hideQueueActions = true,
|
|
||||||
onNavigateToAlbum = { id ->
|
|
||||||
navController.popBackStack()
|
|
||||||
navController.navigate(AlbumDetail(id))
|
|
||||||
},
|
|
||||||
onNavigateToArtist = { id ->
|
|
||||||
navController.popBackStack()
|
|
||||||
navController.navigate(ArtistDetail(id))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun BottomActionsRow(
|
||||||
|
navController: NavHostController,
|
||||||
|
track: com.fabledsword.minstrel.models.TrackRef,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
ViewQueueButton(onClick = { navController.navigate(Queue) })
|
||||||
|
TrackActionsButton(
|
||||||
|
track = track,
|
||||||
|
hideQueueActions = true,
|
||||||
|
onNavigateToAlbum = { id ->
|
||||||
|
navController.popBackStack()
|
||||||
|
navController.navigate(AlbumDetail(id))
|
||||||
|
},
|
||||||
|
onNavigateToArtist = { id ->
|
||||||
|
navController.popBackStack()
|
||||||
|
navController.navigate(ArtistDetail(id))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ViewQueueButton(onClick: () -> Unit) {
|
private fun ViewQueueButton(onClick: () -> Unit) {
|
||||||
IconButton(onClick = onClick) {
|
IconButton(onClick = onClick) {
|
||||||
|
|||||||
+2
-2
@@ -67,8 +67,8 @@ import com.fabledsword.minstrel.playlists.data.PlaylistDetailRef
|
|||||||
import com.fabledsword.minstrel.playlists.data.PlaylistsRepository
|
import com.fabledsword.minstrel.playlists.data.PlaylistsRepository
|
||||||
import com.fabledsword.minstrel.shared.widgets.LikeButton
|
import com.fabledsword.minstrel.shared.widgets.LikeButton
|
||||||
import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb
|
import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb
|
||||||
import com.fabledsword.minstrel.shared.widgets.track_actions.TrackActionsButton
|
import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsButton
|
||||||
import com.fabledsword.minstrel.shared.widgets.track_actions.TrackActionsViewModel
|
import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsViewModel
|
||||||
import com.fabledsword.minstrel.theme.FabledSwordFlatTokens
|
import com.fabledsword.minstrel.theme.FabledSwordFlatTokens
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
@file:Suppress("TooManyFunctions")
|
||||||
|
// SearchScreen legitimately owns the screen-shell composable + a handful
|
||||||
|
// of small section/row helpers (ResultsPane, ResultsList, three section
|
||||||
|
// builders, two row variants, hint, loader). Splitting into a widgets/
|
||||||
|
// subdirectory for a single screen would be over-engineering.
|
||||||
|
|
||||||
package com.fabledsword.minstrel.search.ui
|
package com.fabledsword.minstrel.search.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@@ -51,8 +57,8 @@ import com.fabledsword.minstrel.models.TrackRef
|
|||||||
import com.fabledsword.minstrel.nav.AlbumDetail
|
import com.fabledsword.minstrel.nav.AlbumDetail
|
||||||
import com.fabledsword.minstrel.nav.ArtistDetail
|
import com.fabledsword.minstrel.nav.ArtistDetail
|
||||||
import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb
|
import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb
|
||||||
import com.fabledsword.minstrel.shared.widgets.track_actions.TrackActionsButton
|
import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsButton
|
||||||
import com.fabledsword.minstrel.shared.widgets.track_actions.TrackActionsViewModel
|
import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsViewModel
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.fabledsword.minstrel.shared.widgets.track_actions
|
package com.fabledsword.minstrel.shared.widgets.trackactions
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.fabledsword.minstrel.shared.widgets.track_actions
|
package com.fabledsword.minstrel.shared.widgets.trackactions
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
+17
-11
@@ -1,4 +1,4 @@
|
|||||||
package com.fabledsword.minstrel.shared.widgets.track_actions
|
package com.fabledsword.minstrel.shared.widgets.trackactions
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -93,17 +93,23 @@ fun HideTrackSheet(
|
|||||||
maxLines = 2,
|
maxLines = 2,
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(16.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
Row(
|
HideSheetButtons(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
onCancel = onDismiss,
|
||||||
horizontalArrangement = Arrangement.End,
|
onSubmit = { onSubmit(reason, notes.trim()) },
|
||||||
) {
|
)
|
||||||
TextButton(onClick = onDismiss) { Text("Cancel") }
|
|
||||||
Spacer(Modifier.padding(horizontal = 4.dp))
|
|
||||||
Button(onClick = { onSubmit(reason, notes.trim()) }) {
|
|
||||||
Text("Hide")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(8.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun HideSheetButtons(onCancel: () -> Unit, onSubmit: () -> Unit) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.End,
|
||||||
|
) {
|
||||||
|
TextButton(onClick = onCancel) { Text("Cancel") }
|
||||||
|
Spacer(Modifier.padding(horizontal = 4.dp))
|
||||||
|
Button(onClick = onSubmit) { Text("Hide") }
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.fabledsword.minstrel.shared.widgets.track_actions
|
package com.fabledsword.minstrel.shared.widgets.trackactions
|
||||||
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
+87
-48
@@ -1,4 +1,4 @@
|
|||||||
package com.fabledsword.minstrel.shared.widgets.track_actions
|
package com.fabledsword.minstrel.shared.widgets.trackactions
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@@ -63,7 +63,6 @@ fun TrackActionsSheet(
|
|||||||
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||||
val isLiked by viewModel.isLikedFlow(track.id).collectAsStateWithLifecycle(initialValue = false)
|
val isLiked by viewModel.isLikedFlow(track.id).collectAsStateWithLifecycle(initialValue = false)
|
||||||
val isHidden by viewModel.isHiddenFlow(track.id).collectAsStateWithLifecycle(initialValue = false)
|
val isHidden by viewModel.isHiddenFlow(track.id).collectAsStateWithLifecycle(initialValue = false)
|
||||||
|
|
||||||
var showAddToPlaylist by remember { mutableStateOf(false) }
|
var showAddToPlaylist by remember { mutableStateOf(false) }
|
||||||
var showHideSheet by remember { mutableStateOf(false) }
|
var showHideSheet by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
@@ -71,71 +70,111 @@ fun TrackActionsSheet(
|
|||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
sheetState = sheetState,
|
sheetState = sheetState,
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp)) {
|
TrackActionMenuItems(
|
||||||
if (!hideQueueActions) {
|
track = track,
|
||||||
MenuItem(Lucide.ListVideo, "Play next") {
|
hideQueueActions = hideQueueActions,
|
||||||
viewModel.playNext(track)
|
isLiked = isLiked,
|
||||||
onDismiss()
|
isHidden = isHidden,
|
||||||
}
|
viewModel = viewModel,
|
||||||
MenuItem(Lucide.ListMusic, "Add to queue") {
|
onDismiss = onDismiss,
|
||||||
viewModel.enqueue(track)
|
onNavigateToAlbum = onNavigateToAlbum,
|
||||||
onDismiss()
|
onNavigateToArtist = onNavigateToArtist,
|
||||||
}
|
onShowAddToPlaylist = { showAddToPlaylist = true },
|
||||||
HorizontalDivider()
|
onShowHideSheet = { showHideSheet = true },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
TrackActionSubSheets(
|
||||||
|
track = track,
|
||||||
|
showAddToPlaylist = showAddToPlaylist,
|
||||||
|
showHideSheet = showHideSheet,
|
||||||
|
viewModel = viewModel,
|
||||||
|
onDismissParent = onDismiss,
|
||||||
|
onCloseAddToPlaylist = { showAddToPlaylist = false },
|
||||||
|
onCloseHideSheet = { showHideSheet = false },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun TrackActionMenuItems(
|
||||||
|
track: TrackRef,
|
||||||
|
hideQueueActions: Boolean,
|
||||||
|
isLiked: Boolean,
|
||||||
|
isHidden: Boolean,
|
||||||
|
viewModel: TrackActionsViewModel,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
onNavigateToAlbum: (String) -> Unit,
|
||||||
|
onNavigateToArtist: (String) -> Unit,
|
||||||
|
onShowAddToPlaylist: () -> Unit,
|
||||||
|
onShowHideSheet: () -> Unit,
|
||||||
|
) {
|
||||||
|
Column(modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp)) {
|
||||||
|
if (!hideQueueActions) {
|
||||||
|
MenuItem(Lucide.ListVideo, "Play next") {
|
||||||
|
viewModel.playNext(track); onDismiss()
|
||||||
}
|
}
|
||||||
MenuItem(Lucide.Heart, if (isLiked) "Unlike" else "Like") {
|
MenuItem(Lucide.ListMusic, "Add to queue") {
|
||||||
viewModel.toggleLike(track.id, isLiked)
|
viewModel.enqueue(track); onDismiss()
|
||||||
onDismiss()
|
|
||||||
}
|
|
||||||
MenuItem(Lucide.ListPlus, "Add to playlist…") {
|
|
||||||
showAddToPlaylist = true
|
|
||||||
}
|
|
||||||
MenuItem(Lucide.Radio, "Start radio") {
|
|
||||||
viewModel.startRadio(track.id)
|
|
||||||
onDismiss()
|
|
||||||
}
|
}
|
||||||
HorizontalDivider()
|
HorizontalDivider()
|
||||||
MenuItem(Lucide.Disc3, "Go to album") {
|
}
|
||||||
onDismiss()
|
MenuItem(Lucide.Heart, if (isLiked) "Unlike" else "Like") {
|
||||||
if (track.albumId.isNotEmpty()) onNavigateToAlbum(track.albumId)
|
viewModel.toggleLike(track.id, isLiked); onDismiss()
|
||||||
}
|
}
|
||||||
MenuItem(Lucide.User, "Go to artist") {
|
MenuItem(Lucide.ListPlus, "Add to playlist…", onShowAddToPlaylist)
|
||||||
onDismiss()
|
MenuItem(Lucide.Radio, "Start radio") {
|
||||||
if (track.artistId.isNotEmpty()) onNavigateToArtist(track.artistId)
|
viewModel.startRadio(track.id); onDismiss()
|
||||||
}
|
}
|
||||||
HorizontalDivider()
|
HorizontalDivider()
|
||||||
MenuItem(
|
MenuItem(Lucide.Disc3, "Go to album") {
|
||||||
icon = if (isHidden) Lucide.Eye else Lucide.EyeOff,
|
onDismiss()
|
||||||
label = if (isHidden) "Unhide" else "Hide",
|
if (track.albumId.isNotEmpty()) onNavigateToAlbum(track.albumId)
|
||||||
) {
|
}
|
||||||
if (isHidden) {
|
MenuItem(Lucide.User, "Go to artist") {
|
||||||
viewModel.unflag(track.id)
|
onDismiss()
|
||||||
onDismiss()
|
if (track.artistId.isNotEmpty()) onNavigateToArtist(track.artistId)
|
||||||
} else {
|
}
|
||||||
showHideSheet = true
|
HorizontalDivider()
|
||||||
}
|
MenuItem(
|
||||||
|
icon = if (isHidden) Lucide.Eye else Lucide.EyeOff,
|
||||||
|
label = if (isHidden) "Unhide" else "Hide",
|
||||||
|
) {
|
||||||
|
if (isHidden) {
|
||||||
|
viewModel.unflag(track.id); onDismiss()
|
||||||
|
} else {
|
||||||
|
onShowHideSheet()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun TrackActionSubSheets(
|
||||||
|
track: TrackRef,
|
||||||
|
showAddToPlaylist: Boolean,
|
||||||
|
showHideSheet: Boolean,
|
||||||
|
viewModel: TrackActionsViewModel,
|
||||||
|
onDismissParent: () -> Unit,
|
||||||
|
onCloseAddToPlaylist: () -> Unit,
|
||||||
|
onCloseHideSheet: () -> Unit,
|
||||||
|
) {
|
||||||
if (showAddToPlaylist) {
|
if (showAddToPlaylist) {
|
||||||
AddToPlaylistSheet(
|
AddToPlaylistSheet(
|
||||||
onPick = { playlistId ->
|
onPick = { playlistId ->
|
||||||
viewModel.appendToPlaylist(playlistId, track.id)
|
viewModel.appendToPlaylist(playlistId, track.id)
|
||||||
showAddToPlaylist = false
|
onCloseAddToPlaylist()
|
||||||
onDismiss()
|
onDismissParent()
|
||||||
},
|
},
|
||||||
onDismiss = { showAddToPlaylist = false },
|
onDismiss = onCloseAddToPlaylist,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (showHideSheet) {
|
if (showHideSheet) {
|
||||||
HideTrackSheet(
|
HideTrackSheet(
|
||||||
onSubmit = { reason, notes ->
|
onSubmit = { reason, notes ->
|
||||||
viewModel.flag(track, reason, notes)
|
viewModel.flag(track, reason, notes)
|
||||||
showHideSheet = false
|
onCloseHideSheet()
|
||||||
onDismiss()
|
onDismissParent()
|
||||||
},
|
},
|
||||||
onDismiss = { showHideSheet = false },
|
onDismiss = onCloseHideSheet,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.fabledsword.minstrel.shared.widgets.track_actions
|
package com.fabledsword.minstrel.shared.widgets.trackactions
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
Reference in New Issue
Block a user