From 03d9d92af66c91b773a0156db99270ed455e4267 Mon Sep 17 00:00:00 2001 From: Zion Huang Date: Mon, 26 Aug 2024 11:30:44 +0800 Subject: [PATCH] feat: queue item menu --- .../com/zionhuang/music/ui/menu/PlayerMenu.kt | 114 +++++++++++------- .../com/zionhuang/music/ui/player/Queue.kt | 35 ++++-- 2 files changed, 98 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/com/zionhuang/music/ui/menu/PlayerMenu.kt b/app/src/main/java/com/zionhuang/music/ui/menu/PlayerMenu.kt index 0adc5ebf3..28f2723c4 100644 --- a/app/src/main/java/com/zionhuang/music/ui/menu/PlayerMenu.kt +++ b/app/src/main/java/com/zionhuang/music/ui/menu/PlayerMenu.kt @@ -64,6 +64,7 @@ import com.zionhuang.music.ui.component.DownloadGridMenu import com.zionhuang.music.ui.component.GridMenu import com.zionhuang.music.ui.component.GridMenuItem import com.zionhuang.music.ui.component.ListDialog +import java.time.LocalDateTime import kotlin.math.log2 import kotlin.math.pow import kotlin.math.round @@ -73,7 +74,8 @@ fun PlayerMenu( mediaMetadata: MediaMetadata?, navController: NavController, playerBottomSheetState: BottomSheetState, - onShowDetailsDialog: () -> Unit, + isTriggeredFromQueue: Boolean = false, + onShowDetailsDialog: () -> Unit = {}, onDismiss: () -> Unit, ) { mediaMetadata ?: return @@ -82,6 +84,7 @@ fun PlayerMenu( val playerConnection = LocalPlayerConnection.current ?: return val playerVolume = playerConnection.service.playerVolume.collectAsState() val activityResultLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { } + val librarySong by database.song(mediaMetadata.id).collectAsState(initial = null) val download by LocalDownloadUtil.current.getDownload(mediaMetadata.id).collectAsState(initial = null) @@ -150,25 +153,27 @@ fun PlayerMenu( ) } - Row( - horizontalArrangement = Arrangement.spacedBy(24.dp), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) - .padding(top = 24.dp, bottom = 6.dp) - ) { - Icon( - painter = painterResource(R.drawable.volume_up), - contentDescription = null, - modifier = Modifier.size(28.dp) - ) + if (!isTriggeredFromQueue) { + Row( + horizontalArrangement = Arrangement.spacedBy(24.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 24.dp) + .padding(top = 24.dp, bottom = 6.dp) + ) { + Icon( + painter = painterResource(R.drawable.volume_up), + contentDescription = null, + modifier = Modifier.size(28.dp) + ) - BigSeekBar( - progressProvider = playerVolume::value, - onProgressChange = { playerConnection.service.playerVolume.value = it }, - modifier = Modifier.weight(1f) - ) + BigSeekBar( + progressProvider = playerVolume::value, + onProgressChange = { playerConnection.service.playerVolume.value = it }, + modifier = Modifier.weight(1f) + ) + } } GridMenu( @@ -218,6 +223,26 @@ fun PlayerMenu( ) } ) + if (librarySong?.song?.inLibrary != null) { + GridMenuItem( + icon = R.drawable.library_add_check, + title = R.string.remove_from_library, + ) { + database.query { + inLibrary(mediaMetadata.id, null) + } + } + } else { + GridMenuItem( + icon = R.drawable.library_add, + title = R.string.add_to_library, + ) { + database.transaction { + insert(mediaMetadata) + inLibrary(mediaMetadata.id, LocalDateTime.now()) + } + } + } if (artists.isNotEmpty()) { GridMenuItem( icon = R.drawable.artist, @@ -254,32 +279,35 @@ fun PlayerMenu( context.startActivity(Intent.createChooser(intent, null)) onDismiss() } - GridMenuItem( - icon = R.drawable.info, - title = R.string.details - ) { - onShowDetailsDialog() - onDismiss() - } - GridMenuItem( - icon = R.drawable.equalizer, - title = R.string.equalizer - ) { - val intent = Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL).apply { - putExtra(AudioEffect.EXTRA_AUDIO_SESSION, playerConnection.player.audioSessionId) - putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.packageName) - putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_MUSIC) + + if (!isTriggeredFromQueue) { + GridMenuItem( + icon = R.drawable.info, + title = R.string.details + ) { + onShowDetailsDialog() + onDismiss() } - if (intent.resolveActivity(context.packageManager) != null) { - activityResultLauncher.launch(intent) + GridMenuItem( + icon = R.drawable.equalizer, + title = R.string.equalizer + ) { + val intent = Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL).apply { + putExtra(AudioEffect.EXTRA_AUDIO_SESSION, playerConnection.player.audioSessionId) + putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.packageName) + putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_MUSIC) + } + if (intent.resolveActivity(context.packageManager) != null) { + activityResultLauncher.launch(intent) + } + onDismiss() + } + GridMenuItem( + icon = R.drawable.speed, + title = R.string.tempo_and_pitch + ) { + showTempoPitchDialog = true } - onDismiss() - } - GridMenuItem( - icon = R.drawable.speed, - title = R.string.tempo_and_pitch - ) { - showTempoPitchDialog = true } } } diff --git a/app/src/main/java/com/zionhuang/music/ui/player/Queue.kt b/app/src/main/java/com/zionhuang/music/ui/player/Queue.kt index 79951816c..015b8f066 100644 --- a/app/src/main/java/com/zionhuang/music/ui/player/Queue.kt +++ b/app/src/main/java/com/zionhuang/music/ui/player/Queue.kt @@ -3,8 +3,10 @@ package com.zionhuang.music.ui.player import android.text.format.Formatter import android.widget.Toast import androidx.compose.animation.AnimatedContent +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -99,6 +101,7 @@ import java.util.Date import java.util.Locale import kotlin.math.roundToInt +@OptIn(ExperimentalFoundationApi::class) @Composable fun Queue( state: BottomSheetState, @@ -441,16 +444,32 @@ fun Queue( }, modifier = Modifier .fillMaxWidth() - .clickable { - coroutineScope.launch(Dispatchers.Main) { - if (index == currentWindowIndex) { - playerConnection.player.togglePlayPause() - } else { - playerConnection.player.seekToDefaultPosition(window.firstPeriodIndex) - playerConnection.player.playWhenReady = true + .combinedClickable( + onClick = { + coroutineScope.launch(Dispatchers.Main) { + if (index == currentWindowIndex) { + playerConnection.player.togglePlayPause() + } else { + playerConnection.player.seekToDefaultPosition(window.firstPeriodIndex) + playerConnection.player.playWhenReady = true + } + } + }, + onLongClick = { + menuState.show { + PlayerMenu( + mediaMetadata = window.mediaItem.metadata, + navController = navController, + playerBottomSheetState = playerBottomSheetState, + isTriggeredFromQueue = true, + onDismiss = { + menuState.dismiss() + state.collapseSoft() + }, + ) } } - } + ) ) }