mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Support delete
This commit is contained in:
parent
803780894c
commit
64c6e4db79
6 changed files with 216 additions and 22 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package com.github.damontecres.wholphin.ui.detail
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.focusGroup
|
||||
import androidx.compose.foundation.focusable
|
||||
|
|
@ -60,8 +61,10 @@ import com.github.damontecres.wholphin.data.filter.ItemFilterBy
|
|||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.data.model.GetItemsFilter
|
||||
import com.github.damontecres.wholphin.data.model.LibraryDisplayInfo
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.FavoriteWatchManager
|
||||
import com.github.damontecres.wholphin.services.MediaManagementService
|
||||
import com.github.damontecres.wholphin.services.MediaReportService
|
||||
import com.github.damontecres.wholphin.services.MusicService
|
||||
import com.github.damontecres.wholphin.services.MusicServiceState
|
||||
|
|
@ -70,6 +73,7 @@ import com.github.damontecres.wholphin.ui.DefaultItemFields
|
|||
import com.github.damontecres.wholphin.ui.TimeFormatter
|
||||
import com.github.damontecres.wholphin.ui.cards.ItemCardImage
|
||||
import com.github.damontecres.wholphin.ui.components.BasicDialog
|
||||
import com.github.damontecres.wholphin.ui.components.ConfirmDeleteDialog
|
||||
import com.github.damontecres.wholphin.ui.components.DialogParams
|
||||
import com.github.damontecres.wholphin.ui.components.DialogPopup
|
||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||
|
|
@ -108,6 +112,7 @@ import dagger.assisted.Assisted
|
|||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
|
@ -128,16 +133,18 @@ import kotlin.time.Duration
|
|||
class PlaylistViewModel
|
||||
@AssistedInject
|
||||
constructor(
|
||||
@ApplicationContext context: Context,
|
||||
api: ApiClient,
|
||||
navigationManager: NavigationManager,
|
||||
musicService: MusicService,
|
||||
mediaManagementService: MediaManagementService,
|
||||
private val backdropService: BackdropService,
|
||||
private val serverRepository: ServerRepository,
|
||||
private val libraryDisplayInfoDao: LibraryDisplayInfoDao,
|
||||
private val favoriteWatchManager: FavoriteWatchManager,
|
||||
private val mediaReportService: MediaReportService,
|
||||
@Assisted val itemId: UUID,
|
||||
) : MusicViewModel(api, musicService, navigationManager) {
|
||||
@Assisted itemId: UUID,
|
||||
) : MusicViewModel(itemId, context, api, musicService, navigationManager, mediaManagementService) {
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(itemId: UUID): PlaylistViewModel
|
||||
|
|
@ -147,6 +154,10 @@ class PlaylistViewModel
|
|||
val musicState = musicService.state
|
||||
|
||||
init {
|
||||
init()
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
state.update { it.copy(loading = LoadingState.Loading) }
|
||||
viewModelScope.launchDefault {
|
||||
try {
|
||||
|
|
@ -347,6 +358,7 @@ data class PlaylistDetailsState(
|
|||
|
||||
@Composable
|
||||
fun PlaylistDetails(
|
||||
preferences: UserPreferences,
|
||||
destination: Destination.MediaItem,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: PlaylistViewModel =
|
||||
|
|
@ -392,7 +404,7 @@ fun PlaylistDetails(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
var showDeleteDialog by remember { mutableStateOf<BaseItem?>(null) }
|
||||
val musicMoreActions =
|
||||
MusicMoreDialogActions(
|
||||
onNavigate = { viewModel.navigationManager.navigateTo(it) },
|
||||
|
|
@ -405,6 +417,7 @@ fun PlaylistDetails(
|
|||
showPlaylistDialog.makePresent(itemId)
|
||||
},
|
||||
onClickRemoveFromQueue = {},
|
||||
onClickDelete = { showDeleteDialog = it },
|
||||
)
|
||||
val moreActions =
|
||||
MoreDialogActions(
|
||||
|
|
@ -416,7 +429,7 @@ fun PlaylistDetails(
|
|||
showPlaylistDialog.makePresent(itemId)
|
||||
},
|
||||
onSendMediaInfo = viewModel::sendMediaReport,
|
||||
onClickDelete = {},
|
||||
onClickDelete = { showDeleteDialog = it },
|
||||
)
|
||||
|
||||
PlaylistDetailsContent(
|
||||
|
|
@ -446,6 +459,7 @@ fun PlaylistDetails(
|
|||
item = item,
|
||||
index = index,
|
||||
canRemove = false,
|
||||
canDelete = viewModel.canDelete(item, preferences.appPreferences),
|
||||
)
|
||||
} else {
|
||||
buildMoreDialogItemsForHome(
|
||||
|
|
@ -455,7 +469,7 @@ fun PlaylistDetails(
|
|||
playbackPosition = item.playbackPosition,
|
||||
watched = item.played,
|
||||
favorite = item.favorite,
|
||||
canDelete = false,
|
||||
canDelete = viewModel.canDelete(item, preferences.appPreferences),
|
||||
actions = moreActions,
|
||||
)
|
||||
},
|
||||
|
|
@ -495,6 +509,16 @@ fun PlaylistDetails(
|
|||
elevation = 3.dp,
|
||||
)
|
||||
}
|
||||
showDeleteDialog?.let { item ->
|
||||
ConfirmDeleteDialog(
|
||||
itemTitle = item.title ?: "",
|
||||
onCancel = { showDeleteDialog = null },
|
||||
onConfirm = {
|
||||
viewModel.deleteItem(item)
|
||||
showDeleteDialog = null
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import androidx.compose.ui.focus.focusRequester
|
|||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
|
|
@ -46,9 +47,11 @@ import coil3.compose.AsyncImage
|
|||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.ServerRepository
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.FavoriteWatchManager
|
||||
import com.github.damontecres.wholphin.services.ImageUrlService
|
||||
import com.github.damontecres.wholphin.services.MediaManagementService
|
||||
import com.github.damontecres.wholphin.services.MediaReportService
|
||||
import com.github.damontecres.wholphin.services.MusicService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
|
|
@ -58,6 +61,7 @@ import com.github.damontecres.wholphin.ui.DefaultItemFields
|
|||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||
import com.github.damontecres.wholphin.ui.cards.BannerCardWithTitle
|
||||
import com.github.damontecres.wholphin.ui.cards.ItemRow
|
||||
import com.github.damontecres.wholphin.ui.components.ConfirmDeleteDialog
|
||||
import com.github.damontecres.wholphin.ui.components.DialogParams
|
||||
import com.github.damontecres.wholphin.ui.components.DialogPopup
|
||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||
|
|
@ -107,18 +111,19 @@ import java.util.UUID
|
|||
class AlbumViewModel
|
||||
@AssistedInject
|
||||
constructor(
|
||||
@ApplicationContext context: Context,
|
||||
api: ApiClient,
|
||||
musicService: MusicService,
|
||||
navigationManager: NavigationManager,
|
||||
@param:ApplicationContext private val context: Context,
|
||||
mediaManagementService: MediaManagementService,
|
||||
val serverRepository: ServerRepository,
|
||||
val mediaReportService: MediaReportService,
|
||||
private val favoriteWatchManager: FavoriteWatchManager,
|
||||
private val userPreferencesService: UserPreferencesService,
|
||||
private val backdropService: BackdropService,
|
||||
private val imageUrlService: ImageUrlService,
|
||||
@Assisted val itemId: UUID,
|
||||
) : MusicViewModel(api, musicService, navigationManager) {
|
||||
@Assisted itemId: UUID,
|
||||
) : MusicViewModel(itemId, context, api, musicService, navigationManager, mediaManagementService) {
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(itemId: UUID): AlbumViewModel
|
||||
|
|
@ -130,6 +135,10 @@ class AlbumViewModel
|
|||
val currentMusic = musicService.state
|
||||
|
||||
init {
|
||||
init()
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
viewModelScope.launchIO {
|
||||
try {
|
||||
val itemDeferred =
|
||||
|
|
@ -280,6 +289,7 @@ private const val SIMILAR_ROW = MUSIC_VIDEO_ROW + 1
|
|||
@Composable
|
||||
fun AlbumDetailsPage(
|
||||
itemId: UUID,
|
||||
preferences: UserPreferences,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: AlbumViewModel =
|
||||
hiltViewModel<AlbumViewModel, AlbumViewModel.Factory>(
|
||||
|
|
@ -292,9 +302,14 @@ fun AlbumDetailsPage(
|
|||
val state by viewModel.state.collectAsState()
|
||||
val currentMusic by viewModel.currentMusic.collectAsState()
|
||||
|
||||
var position by rememberPosition(0, 0)
|
||||
val focusRequesters =
|
||||
remember { List(SIMILAR_ROW + 1) { FocusRequester() } }
|
||||
val focusManager = LocalFocusManager.current
|
||||
var showPlaylistDialog by remember { mutableStateOf<Optional<UUID>>(Optional.absent()) }
|
||||
val playlistState by playlistViewModel.playlistState.observeAsState(PlaylistLoadingState.Pending)
|
||||
var moreDialog by remember { mutableStateOf<DialogParams?>(null) }
|
||||
var showDeleteDialog by remember { mutableStateOf<BaseItem?>(null) }
|
||||
val moreDialogActions =
|
||||
remember {
|
||||
MusicMoreDialogActions(
|
||||
|
|
@ -308,6 +323,7 @@ fun AlbumDetailsPage(
|
|||
showPlaylistDialog.makePresent(itemId)
|
||||
},
|
||||
onClickRemoveFromQueue = {},
|
||||
onClickDelete = { showDeleteDialog = it },
|
||||
)
|
||||
}
|
||||
when (val loading = state.loading) {
|
||||
|
|
@ -323,15 +339,13 @@ fun AlbumDetailsPage(
|
|||
|
||||
LoadingState.Success -> {
|
||||
val album = state.album!!
|
||||
var position by rememberPosition(0, 0)
|
||||
|
||||
val firstFocusRequester = remember { FocusRequester() }
|
||||
val firstBringIntoViewRequester = remember { BringIntoViewRequester() }
|
||||
val bringIntoViewRequester = remember { BringIntoViewRequester() }
|
||||
val listState = rememberLazyListState()
|
||||
val itemsBefore = 2
|
||||
val focusRequesters =
|
||||
remember { List(SIMILAR_ROW + 1) { FocusRequester() } }
|
||||
|
||||
val songFocusRequester = remember { FocusRequester() }
|
||||
LaunchedEffect(Unit) {
|
||||
if (position.row == SONG_ROW) {
|
||||
|
|
@ -399,6 +413,11 @@ fun AlbumDetailsPage(
|
|||
item = album,
|
||||
index = 0,
|
||||
canRemove = false,
|
||||
canDelete =
|
||||
viewModel.canDelete(
|
||||
album,
|
||||
preferences.appPreferences,
|
||||
),
|
||||
),
|
||||
)
|
||||
},
|
||||
|
|
@ -451,6 +470,11 @@ fun AlbumDetailsPage(
|
|||
item = song,
|
||||
index = index,
|
||||
canRemove = false,
|
||||
canDelete =
|
||||
viewModel.canDelete(
|
||||
song,
|
||||
preferences.appPreferences,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -468,6 +492,11 @@ fun AlbumDetailsPage(
|
|||
item = song,
|
||||
index = index,
|
||||
canRemove = false,
|
||||
canDelete =
|
||||
viewModel.canDelete(
|
||||
song,
|
||||
preferences.appPreferences,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -527,7 +556,24 @@ fun AlbumDetailsPage(
|
|||
viewModel.navigationManager.navigateTo(item.destination())
|
||||
},
|
||||
onLongClickItem = { index, item ->
|
||||
// TODO
|
||||
moreDialog =
|
||||
DialogParams(
|
||||
fromLongClick = true,
|
||||
title = item.name ?: "",
|
||||
items =
|
||||
buildMoreDialogForMusic(
|
||||
context = context,
|
||||
actions = moreDialogActions,
|
||||
item = item,
|
||||
index = index,
|
||||
canRemove = false,
|
||||
canDelete =
|
||||
viewModel.canDelete(
|
||||
item,
|
||||
preferences.appPreferences,
|
||||
),
|
||||
),
|
||||
)
|
||||
},
|
||||
cardContent = { index: Int, item: BaseItem?, mod: Modifier, onClick: () -> Unit, onLongClick: () -> Unit ->
|
||||
BannerCardWithTitle(
|
||||
|
|
@ -575,6 +621,17 @@ fun AlbumDetailsPage(
|
|||
elevation = 3.dp,
|
||||
)
|
||||
}
|
||||
showDeleteDialog?.let { item ->
|
||||
ConfirmDeleteDialog(
|
||||
itemTitle = item.title ?: "",
|
||||
onCancel = { showDeleteDialog = null },
|
||||
onConfirm = {
|
||||
viewModel.deleteItem(item)
|
||||
focusRequesters.getOrNull(position.row)?.tryRequestFocus()
|
||||
showDeleteDialog = null
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import androidx.compose.ui.focus.focusRequester
|
|||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
|
|
@ -44,9 +45,11 @@ import coil3.compose.AsyncImage
|
|||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.ServerRepository
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.FavoriteWatchManager
|
||||
import com.github.damontecres.wholphin.services.ImageUrlService
|
||||
import com.github.damontecres.wholphin.services.MediaManagementService
|
||||
import com.github.damontecres.wholphin.services.MediaReportService
|
||||
import com.github.damontecres.wholphin.services.MusicService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
|
|
@ -56,6 +59,7 @@ import com.github.damontecres.wholphin.ui.DefaultItemFields
|
|||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||
import com.github.damontecres.wholphin.ui.cards.BannerCardWithTitle
|
||||
import com.github.damontecres.wholphin.ui.cards.ItemRow
|
||||
import com.github.damontecres.wholphin.ui.components.ConfirmDeleteDialog
|
||||
import com.github.damontecres.wholphin.ui.components.DialogParams
|
||||
import com.github.damontecres.wholphin.ui.components.DialogPopup
|
||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||
|
|
@ -106,18 +110,19 @@ import java.util.UUID
|
|||
class ArtistViewModel
|
||||
@AssistedInject
|
||||
constructor(
|
||||
@ApplicationContext context: Context,
|
||||
api: ApiClient,
|
||||
musicService: MusicService,
|
||||
navigationManager: NavigationManager,
|
||||
@param:ApplicationContext private val context: Context,
|
||||
mediaManagementService: MediaManagementService,
|
||||
val serverRepository: ServerRepository,
|
||||
val mediaReportService: MediaReportService,
|
||||
private val favoriteWatchManager: FavoriteWatchManager,
|
||||
private val userPreferencesService: UserPreferencesService,
|
||||
private val backdropService: BackdropService,
|
||||
private val imageUrlService: ImageUrlService,
|
||||
@Assisted val itemId: UUID,
|
||||
) : MusicViewModel(api, musicService, navigationManager) {
|
||||
@Assisted itemId: UUID,
|
||||
) : MusicViewModel(itemId, context, api, musicService, navigationManager, mediaManagementService) {
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(itemId: UUID): ArtistViewModel
|
||||
|
|
@ -129,6 +134,10 @@ class ArtistViewModel
|
|||
val currentMusic = musicService.state
|
||||
|
||||
init {
|
||||
init()
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
viewModelScope.launchIO {
|
||||
try {
|
||||
val itemDeferred =
|
||||
|
|
@ -230,7 +239,7 @@ class ArtistViewModel
|
|||
}
|
||||
}
|
||||
|
||||
fun init() {
|
||||
fun refresh() {
|
||||
viewModelScope.launchDefault {
|
||||
state.value.artist?.let {
|
||||
backdropService.submit(it)
|
||||
|
|
@ -283,6 +292,7 @@ private const val SIMILAR_ROW = MUSIC_VIDEO_ROW + 1
|
|||
|
||||
@Composable
|
||||
fun ArtistDetailsPage(
|
||||
preferences: UserPreferences,
|
||||
itemId: UUID,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: ArtistViewModel =
|
||||
|
|
@ -292,13 +302,18 @@ fun ArtistDetailsPage(
|
|||
playlistViewModel: AddPlaylistViewModel = hiltViewModel(),
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val focusManager = LocalFocusManager.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val state by viewModel.state.collectAsState()
|
||||
val currentMusic by viewModel.currentMusic.collectAsState()
|
||||
var position by rememberPosition(0, 0)
|
||||
val focusRequesters =
|
||||
remember { List(SIMILAR_ROW + 1) { FocusRequester() } }
|
||||
|
||||
var showPlaylistDialog by remember { mutableStateOf<Optional<UUID>>(Optional.absent()) }
|
||||
val playlistState by playlistViewModel.playlistState.observeAsState(PlaylistLoadingState.Pending)
|
||||
var moreDialog by remember { mutableStateOf<DialogParams?>(null) }
|
||||
var showDeleteDialog by remember { mutableStateOf<BaseItem?>(null) }
|
||||
val moreDialogActions =
|
||||
remember {
|
||||
MusicMoreDialogActions(
|
||||
|
|
@ -312,6 +327,7 @@ fun ArtistDetailsPage(
|
|||
showPlaylistDialog.makePresent(itemId)
|
||||
},
|
||||
onClickRemoveFromQueue = {},
|
||||
onClickDelete = { showDeleteDialog = it },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -327,10 +343,7 @@ fun ArtistDetailsPage(
|
|||
}
|
||||
|
||||
LoadingState.Success -> {
|
||||
var position by rememberPosition(0, 0)
|
||||
val artist = state.artist!!
|
||||
val focusRequesters =
|
||||
remember { List(SIMILAR_ROW + 1) { FocusRequester() } }
|
||||
val songFocusRequester = remember { FocusRequester() }
|
||||
LaunchedEffect(Unit) {
|
||||
if (position.row == SONG_ROW) {
|
||||
|
|
@ -338,7 +351,7 @@ fun ArtistDetailsPage(
|
|||
} else {
|
||||
focusRequesters.getOrNull(position.row)?.tryRequestFocus()
|
||||
}
|
||||
viewModel.init()
|
||||
viewModel.refresh()
|
||||
}
|
||||
val bringIntoViewRequester = remember { BringIntoViewRequester() }
|
||||
Box(modifier = modifier) {
|
||||
|
|
@ -389,6 +402,11 @@ fun ArtistDetailsPage(
|
|||
item = artist,
|
||||
index = 0,
|
||||
canRemove = false,
|
||||
canDelete =
|
||||
viewModel.canDelete(
|
||||
artist,
|
||||
preferences.appPreferences,
|
||||
),
|
||||
),
|
||||
)
|
||||
},
|
||||
|
|
@ -438,6 +456,11 @@ fun ArtistDetailsPage(
|
|||
item = song,
|
||||
index = index,
|
||||
canRemove = false,
|
||||
canDelete =
|
||||
viewModel.canDelete(
|
||||
song,
|
||||
preferences.appPreferences,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -455,6 +478,11 @@ fun ArtistDetailsPage(
|
|||
item = song,
|
||||
index = index,
|
||||
canRemove = false,
|
||||
canDelete =
|
||||
viewModel.canDelete(
|
||||
song,
|
||||
preferences.appPreferences,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -482,7 +510,24 @@ fun ArtistDetailsPage(
|
|||
viewModel.navigationManager.navigateTo(album.destination())
|
||||
},
|
||||
onLongClickItem = { index, album ->
|
||||
// TODO
|
||||
moreDialog =
|
||||
DialogParams(
|
||||
fromLongClick = true,
|
||||
title = album.name ?: "",
|
||||
items =
|
||||
buildMoreDialogForMusic(
|
||||
context = context,
|
||||
actions = moreDialogActions,
|
||||
item = album,
|
||||
index = index,
|
||||
canRemove = false,
|
||||
canDelete =
|
||||
viewModel.canDelete(
|
||||
album,
|
||||
preferences.appPreferences,
|
||||
),
|
||||
),
|
||||
)
|
||||
},
|
||||
cardContent = { index: Int, album: BaseItem?, mod: Modifier, onClick: () -> Unit, onLongClick: () -> Unit ->
|
||||
BannerCardWithTitle(
|
||||
|
|
@ -534,7 +579,24 @@ fun ArtistDetailsPage(
|
|||
viewModel.navigationManager.navigateTo(item.destination())
|
||||
},
|
||||
onLongClickItem = { index, item ->
|
||||
// TODO
|
||||
moreDialog =
|
||||
DialogParams(
|
||||
fromLongClick = true,
|
||||
title = item.name ?: "",
|
||||
items =
|
||||
buildMoreDialogForMusic(
|
||||
context = context,
|
||||
actions = moreDialogActions,
|
||||
item = item,
|
||||
index = index,
|
||||
canRemove = false,
|
||||
canDelete =
|
||||
viewModel.canDelete(
|
||||
item,
|
||||
preferences.appPreferences,
|
||||
),
|
||||
),
|
||||
)
|
||||
},
|
||||
cardContent = { index: Int, item: BaseItem?, mod: Modifier, onClick: () -> Unit, onLongClick: () -> Unit ->
|
||||
BannerCardWithTitle(
|
||||
|
|
@ -582,6 +644,17 @@ fun ArtistDetailsPage(
|
|||
elevation = 3.dp,
|
||||
)
|
||||
}
|
||||
showDeleteDialog?.let { item ->
|
||||
ConfirmDeleteDialog(
|
||||
itemTitle = item.title ?: "",
|
||||
onCancel = { showDeleteDialog = null },
|
||||
onConfirm = {
|
||||
viewModel.deleteItem(item)
|
||||
focusRequesters.getOrNull(position.row)?.tryRequestFocus()
|
||||
showDeleteDialog = null
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
package com.github.damontecres.wholphin.ui.detail.music
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||
import com.github.damontecres.wholphin.services.MediaManagementService
|
||||
import com.github.damontecres.wholphin.services.MusicService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.services.deleteItem
|
||||
import com.github.damontecres.wholphin.ui.launchDefault
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
|
|
@ -17,9 +21,12 @@ import timber.log.Timber
|
|||
import java.util.UUID
|
||||
|
||||
abstract class MusicViewModel(
|
||||
internal val itemId: UUID,
|
||||
internal val context: Context,
|
||||
internal val api: ApiClient,
|
||||
internal val musicService: MusicService,
|
||||
internal val navigationManager: NavigationManager,
|
||||
internal val mediaManagementService: MediaManagementService,
|
||||
) : ViewModel() {
|
||||
fun play(
|
||||
pager: ApiRequestPager<*>,
|
||||
|
|
@ -115,4 +122,21 @@ abstract class MusicViewModel(
|
|||
navigationManager.navigateTo(Destination.NowPlaying)
|
||||
}
|
||||
}
|
||||
|
||||
fun canDelete(
|
||||
item: BaseItem,
|
||||
appPreferences: AppPreferences,
|
||||
): Boolean = mediaManagementService.canDelete(item, appPreferences)
|
||||
|
||||
fun deleteItem(item: BaseItem) {
|
||||
deleteItem(context, mediaManagementService, item) {
|
||||
if (item.id == itemId) {
|
||||
navigationManager.goBack()
|
||||
} else {
|
||||
init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract fun init()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ data class MusicMoreDialogActions(
|
|||
onNavigate.invoke(Destination.MediaItem(itemId = it, type = BaseItemKind.MUSIC_ARTIST))
|
||||
},
|
||||
val onClickRemoveFromQueue: (Int) -> Unit,
|
||||
val onClickDelete: (BaseItem) -> Unit,
|
||||
)
|
||||
|
||||
fun buildMoreDialogForMusic(
|
||||
|
|
@ -45,6 +46,7 @@ fun buildMoreDialogForMusic(
|
|||
item: BaseItem,
|
||||
index: Int,
|
||||
canRemove: Boolean,
|
||||
canDelete: Boolean,
|
||||
): List<DialogItem> =
|
||||
buildList {
|
||||
add(
|
||||
|
|
@ -91,6 +93,17 @@ fun buildMoreDialogForMusic(
|
|||
actions.onClickAddPlaylist.invoke(item.id)
|
||||
},
|
||||
)
|
||||
if (canDelete) {
|
||||
add(
|
||||
DialogItem(
|
||||
context.getString(R.string.delete),
|
||||
Icons.Default.Delete,
|
||||
iconColor = Color.Red.copy(alpha = .8f),
|
||||
) {
|
||||
actions.onClickDelete.invoke(item)
|
||||
},
|
||||
)
|
||||
}
|
||||
add(
|
||||
DialogItem(
|
||||
text = if (item.favorite) R.string.remove_favorite else R.string.add_favorite,
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ fun DestinationContent(
|
|||
BaseItemKind.PLAYLIST -> {
|
||||
LaunchedEffect(Unit) { onClearBackdrop.invoke() }
|
||||
PlaylistDetails(
|
||||
preferences = preferences,
|
||||
destination = destination,
|
||||
modifier = modifier,
|
||||
)
|
||||
|
|
@ -221,6 +222,7 @@ fun DestinationContent(
|
|||
BaseItemKind.MUSIC_ALBUM -> {
|
||||
LaunchedEffect(Unit) { onClearBackdrop.invoke() }
|
||||
AlbumDetailsPage(
|
||||
preferences = preferences,
|
||||
itemId = destination.itemId,
|
||||
modifier = modifier,
|
||||
)
|
||||
|
|
@ -229,6 +231,7 @@ fun DestinationContent(
|
|||
BaseItemKind.MUSIC_ARTIST -> {
|
||||
LaunchedEffect(Unit) { onClearBackdrop.invoke() }
|
||||
ArtistDetailsPage(
|
||||
preferences = preferences,
|
||||
itemId = destination.itemId,
|
||||
modifier = modifier,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue