Add IconButton composable

This commit is contained in:
vfsfitvnm 2022-10-04 14:31:59 +02:00
parent 185c5ec726
commit 7fe9c1dee8
7 changed files with 299 additions and 366 deletions

View file

@ -23,17 +23,12 @@ fun HeaderIconButton(
modifier: Modifier = Modifier,
enabled: Boolean = true
) {
Image(
painter = painterResource(icon),
contentDescription = null,
colorFilter = ColorFilter.tint(color),
IconButton(
icon = icon,
color = color,
onClick = onClick,
enabled = enabled,
modifier = modifier
.clickable(
indication = rememberRipple(bounded = false),
interactionSource = remember { MutableInteractionSource() },
enabled = enabled,
onClick = onClick
)
.padding(all = 4.dp)
.size(18.dp)
)
@ -51,12 +46,13 @@ fun IconButton(
painter = painterResource(icon),
contentDescription = null,
colorFilter = ColorFilter.tint(color),
modifier = modifier
modifier = Modifier
.clickable(
indication = rememberRipple(bounded = false),
interactionSource = remember { MutableInteractionSource() },
enabled = enabled,
onClick = onClick
)
.then(modifier)
)
}

View file

@ -3,7 +3,6 @@ package it.vfsfitvnm.vimusic.ui.screens.album
import android.content.Intent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.BoxWithConstraints
@ -21,9 +20,7 @@ import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import com.valentinilk.shimmer.shimmer
@ -39,6 +36,7 @@ import it.vfsfitvnm.vimusic.savers.InnertubePlaylistOrAlbumPageSaver
import it.vfsfitvnm.vimusic.savers.innertubeItemsPageSaver
import it.vfsfitvnm.vimusic.savers.nullableSaver
import it.vfsfitvnm.vimusic.ui.components.themed.Header
import it.vfsfitvnm.vimusic.ui.components.themed.HeaderIconButton
import it.vfsfitvnm.vimusic.ui.components.themed.HeaderPlaceholder
import it.vfsfitvnm.vimusic.ui.components.themed.Scaffold
import it.vfsfitvnm.vimusic.ui.items.AlbumItem
@ -143,49 +141,39 @@ fun AlbumScreen(browseId: String) {
.weight(1f)
)
Image(
painter = painterResource(
if (album?.bookmarkedAt == null) {
R.drawable.bookmark_outline
} else {
R.drawable.bookmark
}
),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.accent),
modifier = Modifier
.clickable {
val bookmarkedAt =
if (album?.bookmarkedAt == null) System.currentTimeMillis() else null
HeaderIconButton(
icon = if (album?.bookmarkedAt == null) {
R.drawable.bookmark_outline
} else {
R.drawable.bookmark
},
color = colorPalette.accent,
onClick = {
val bookmarkedAt =
if (album?.bookmarkedAt == null) System.currentTimeMillis() else null
query {
album
?.copy(bookmarkedAt = bookmarkedAt)
?.let(Database::update)
}
query {
album
?.copy(bookmarkedAt = bookmarkedAt)
?.let(Database::update)
}
.padding(all = 4.dp)
.size(18.dp)
}
)
Image(
painter = painterResource(R.drawable.share_social),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable {
album?.shareUrl?.let { url ->
val sendIntent = Intent().apply {
action = Intent.ACTION_SEND
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, url)
}
context.startActivity(Intent.createChooser(sendIntent, null))
HeaderIconButton(
icon = R.drawable.share_social,
color = colorPalette.text,
onClick = {
album?.shareUrl?.let { url ->
val sendIntent = Intent().apply {
action = Intent.ACTION_SEND
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, url)
}
context.startActivity(Intent.createChooser(sendIntent, null))
}
.padding(all = 4.dp)
.size(18.dp)
}
)
}
}

View file

@ -3,7 +3,6 @@ package it.vfsfitvnm.vimusic.ui.screens.artist
import android.content.Intent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
@ -21,9 +20,7 @@ import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import com.valentinilk.shimmer.shimmer
@ -40,6 +37,7 @@ import it.vfsfitvnm.vimusic.savers.InnertubeSongsPageSaver
import it.vfsfitvnm.vimusic.savers.nullableSaver
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
import it.vfsfitvnm.vimusic.ui.components.themed.Header
import it.vfsfitvnm.vimusic.ui.components.themed.HeaderIconButton
import it.vfsfitvnm.vimusic.ui.components.themed.HeaderPlaceholder
import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu
import it.vfsfitvnm.vimusic.ui.components.themed.Scaffold
@ -96,7 +94,11 @@ fun ArtistScreen(browseId: String) {
stateSaver = nullableSaver(InnertubeArtistPageSaver),
tabIndex < 4
) {
if (value != null || (tabIndex == 4 && withContext(Dispatchers.IO) { Database.artistTimestamp(browseId) } != null)) return@produceSaveableState
if (value != null || (tabIndex == 4 && withContext(Dispatchers.IO) {
Database.artistTimestamp(
browseId
)
} != null)) return@produceSaveableState
withContext(Dispatchers.IO) {
Innertube.artistPage(BrowseBody(browseId = browseId))
@ -154,35 +156,33 @@ fun ArtistScreen(browseId: String) {
}
}
val headerContent: @Composable (textButton: (@Composable () -> Unit)?) -> Unit = { textButton ->
if (artist?.timestamp == null) {
HeaderPlaceholder(
modifier = Modifier
.shimmer()
)
} else {
val context = LocalContext.current
Header(title = artist?.name ?: "Unknown") {
textButton?.invoke()
Spacer(
val headerContent: @Composable (textButton: (@Composable () -> Unit)?) -> Unit =
{ textButton ->
if (artist?.timestamp == null) {
HeaderPlaceholder(
modifier = Modifier
.weight(1f)
.shimmer()
)
} else {
val (colorPalette) = LocalAppearance.current
val context = LocalContext.current
Image(
painter = painterResource(
if (artist?.bookmarkedAt == null) {
Header(title = artist?.name ?: "Unknown") {
textButton?.invoke()
Spacer(
modifier = Modifier
.weight(1f)
)
HeaderIconButton(
icon = if (artist?.bookmarkedAt == null) {
R.drawable.bookmark_outline
} else {
R.drawable.bookmark
}
),
contentDescription = null,
colorFilter = ColorFilter.tint(LocalAppearance.current.colorPalette.accent),
modifier = Modifier
.clickable {
},
color = colorPalette.accent,
onClick = {
val bookmarkedAt =
if (artist?.bookmarkedAt == null) System.currentTimeMillis() else null
@ -192,16 +192,12 @@ fun ArtistScreen(browseId: String) {
?.let(Database::update)
}
}
.padding(all = 4.dp)
.size(18.dp)
)
)
Image(
painter = painterResource(R.drawable.share_social),
contentDescription = null,
colorFilter = ColorFilter.tint(LocalAppearance.current.colorPalette.text),
modifier = Modifier
.clickable {
HeaderIconButton(
icon = R.drawable.share_social,
color = colorPalette.text,
onClick = {
val sendIntent = Intent().apply {
action = Intent.ACTION_SEND
type = "text/plain"
@ -211,19 +207,12 @@ fun ArtistScreen(browseId: String) {
)
}
context.startActivity(
Intent.createChooser(
sendIntent,
null
)
)
context.startActivity(Intent.createChooser(sendIntent, null))
}
.padding(all = 4.dp)
.size(18.dp)
)
)
}
}
}
}
Scaffold(
topIconButtonId = R.drawable.chevron_back,
@ -256,36 +245,36 @@ fun ArtistScreen(browseId: String) {
val thumbnailSizeDp = Dimensions.thumbnails.song
val thumbnailSizePx = thumbnailSizeDp.px
ItemsPage(
stateSaver = InnertubeSongsPageSaver,
headerContent = headerContent,
itemsPageProvider = youtubeArtist?.let {({ continuation ->
continuation?.let {
Innertube.itemsPage(
body = ContinuationBody(continuation = continuation),
fromMusicResponsiveListItemRenderer = Innertube.SongItem::from,
)
} ?: youtubeArtist
?.songsEndpoint
?.takeIf { it.browseId != null }
?.let { endpoint ->
itemsPageProvider = youtubeArtist?.let {
({ continuation ->
continuation?.let {
Innertube.itemsPage(
body = BrowseBody(
browseId = endpoint.browseId!!,
params = endpoint.params,
),
body = ContinuationBody(continuation = continuation),
fromMusicResponsiveListItemRenderer = Innertube.SongItem::from,
)
}
?: Result.success(
Innertube.ItemsPage(
items = youtubeArtist?.songs,
continuation = null
} ?: youtubeArtist
?.songsEndpoint
?.takeIf { it.browseId != null }
?.let { endpoint ->
Innertube.itemsPage(
body = BrowseBody(
browseId = endpoint.browseId!!,
params = endpoint.params,
),
fromMusicResponsiveListItemRenderer = Innertube.SongItem::from,
)
}
?: Result.success(
Innertube.ItemsPage(
items = youtubeArtist?.songs,
continuation = null
)
)
)
})},
})
},
itemContent = { song ->
SongItem(
song = song,
@ -320,31 +309,33 @@ fun ArtistScreen(browseId: String) {
stateSaver = InnertubeAlbumsPageSaver,
headerContent = headerContent,
emptyItemsText = "This artist didn't release any album",
itemsPageProvider = youtubeArtist?.let {({ continuation ->
continuation?.let {
Innertube.itemsPage(
body = ContinuationBody(continuation = continuation),
fromMusicTwoRowItemRenderer = Innertube.AlbumItem::from,
)
} ?: youtubeArtist
?.albumsEndpoint
?.takeIf { it.browseId != null }
?.let { endpoint ->
itemsPageProvider = youtubeArtist?.let {
({ continuation ->
continuation?.let {
Innertube.itemsPage(
body = BrowseBody(
browseId = endpoint.browseId!!,
params = endpoint.params,
),
body = ContinuationBody(continuation = continuation),
fromMusicTwoRowItemRenderer = Innertube.AlbumItem::from,
)
}
?: Result.success(
Innertube.ItemsPage(
items = youtubeArtist?.albums,
continuation = null
} ?: youtubeArtist
?.albumsEndpoint
?.takeIf { it.browseId != null }
?.let { endpoint ->
Innertube.itemsPage(
body = BrowseBody(
browseId = endpoint.browseId!!,
params = endpoint.params,
),
fromMusicTwoRowItemRenderer = Innertube.AlbumItem::from,
)
}
?: Result.success(
Innertube.ItemsPage(
items = youtubeArtist?.albums,
continuation = null
)
)
)
})},
})
},
itemContent = { album ->
AlbumItem(
album = album,
@ -368,31 +359,33 @@ fun ArtistScreen(browseId: String) {
stateSaver = InnertubeAlbumsPageSaver,
headerContent = headerContent,
emptyItemsText = "This artist didn't release any single",
itemsPageProvider = youtubeArtist?.let {({ continuation ->
continuation?.let {
Innertube.itemsPage(
body = ContinuationBody(continuation = continuation),
fromMusicTwoRowItemRenderer = Innertube.AlbumItem::from,
)
} ?: youtubeArtist
?.singlesEndpoint
?.takeIf { it.browseId != null }
?.let { endpoint ->
itemsPageProvider = youtubeArtist?.let {
({ continuation ->
continuation?.let {
Innertube.itemsPage(
body = BrowseBody(
browseId = endpoint.browseId!!,
params = endpoint.params,
),
body = ContinuationBody(continuation = continuation),
fromMusicTwoRowItemRenderer = Innertube.AlbumItem::from,
)
}
?: Result.success(
Innertube.ItemsPage(
items = youtubeArtist?.singles,
continuation = null
} ?: youtubeArtist
?.singlesEndpoint
?.takeIf { it.browseId != null }
?.let { endpoint ->
Innertube.itemsPage(
body = BrowseBody(
browseId = endpoint.browseId!!,
params = endpoint.params,
),
fromMusicTwoRowItemRenderer = Innertube.AlbumItem::from,
)
}
?: Result.success(
Innertube.ItemsPage(
items = youtubeArtist?.singles,
continuation = null
)
)
)
})},
})
},
itemContent = { album ->
AlbumItem(
album = album,

View file

@ -40,6 +40,7 @@ import it.vfsfitvnm.vimusic.transaction
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
import it.vfsfitvnm.vimusic.ui.components.themed.ConfirmationDialog
import it.vfsfitvnm.vimusic.ui.components.themed.Header
import it.vfsfitvnm.vimusic.ui.components.themed.HeaderIconButton
import it.vfsfitvnm.vimusic.ui.components.themed.InPlaylistMediaItemMenu
import it.vfsfitvnm.vimusic.ui.components.themed.PrimaryButton
import it.vfsfitvnm.vimusic.ui.components.themed.SecondaryTextButton
@ -164,59 +165,46 @@ fun LocalPlaylistSongs(
)
playlistWithSongs?.playlist?.browseId?.let { browseId ->
Image(
painter = painterResource(R.drawable.sync),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable {
transaction {
runBlocking(Dispatchers.IO) {
withContext(Dispatchers.IO) {
Innertube.playlistPage(BrowseBody(browseId = browseId))?.completed()
}
}?.getOrNull()?.let { remotePlaylist ->
Database.clearPlaylist(playlistId)
remotePlaylist.
songsPage
?.items
?.map(Innertube.SongItem::asMediaItem)
?.onEach(Database::insert)
?.mapIndexed { position, mediaItem ->
SongPlaylistMap(
songId = mediaItem.mediaId,
playlistId = playlistId,
position = position
)
}?.let(Database::insertSongPlaylistMaps)
HeaderIconButton(
icon = R.drawable.sync,
color = colorPalette.text,
onClick = {
transaction {
runBlocking(Dispatchers.IO) {
withContext(Dispatchers.IO) {
Innertube.playlistPage(BrowseBody(browseId = browseId))?.completed()
}
}?.getOrNull()?.let { remotePlaylist ->
Database.clearPlaylist(playlistId)
remotePlaylist.
songsPage
?.items
?.map(Innertube.SongItem::asMediaItem)
?.onEach(Database::insert)
?.mapIndexed { position, mediaItem ->
SongPlaylistMap(
songId = mediaItem.mediaId,
playlistId = playlistId,
position = position
)
}?.let(Database::insertSongPlaylistMaps)
}
}
.padding(all = 4.dp)
.size(18.dp)
}
)
}
Image(
painter = painterResource(R.drawable.pencil),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable { isRenaming = true }
.padding(all = 4.dp)
.size(18.dp)
HeaderIconButton(
icon = R.drawable.pencil,
color = colorPalette.text,
onClick = { isRenaming = true }
)
Image(
painter = painterResource(R.drawable.trash),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable { isDeleting = true }
.padding(all = 4.dp)
.size(18.dp)
HeaderIconButton(
icon = R.drawable.trash,
color = colorPalette.text,
onClick = { isDeleting = true }
)
}
}

View file

@ -52,6 +52,7 @@ import it.vfsfitvnm.vimusic.ui.components.BottomSheet
import it.vfsfitvnm.vimusic.ui.components.BottomSheetState
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
import it.vfsfitvnm.vimusic.ui.components.MusicBars
import it.vfsfitvnm.vimusic.ui.components.themed.IconButton
import it.vfsfitvnm.vimusic.ui.components.themed.QueuedMediaItemMenu
import it.vfsfitvnm.vimusic.ui.items.SongItem
import it.vfsfitvnm.vimusic.ui.items.SongItemPlaceholder
@ -227,7 +228,10 @@ fun PlayerBottomSheet(
}
)
.animateItemPlacement(reorderingState = reorderingState)
.draggedItem(reorderingState = reorderingState, index = window.firstPeriodIndex)
.draggedItem(
reorderingState = reorderingState,
index = window.firstPeriodIndex
)
)
}
@ -257,14 +261,13 @@ fun PlayerBottomSheet(
.height(64.dp + bottomPadding)
.background(colorPalette.background2)
.fillMaxWidth()
.padding(horizontal = 8.dp)
.padding(horizontal = 12.dp)
.padding(bottom = bottomPadding)
) {
BasicText(
text = "${windows.size} songs",
style = typography.xxs.medium,
modifier = Modifier
.padding(start = 4.dp)
.background(color = colorPalette.background1, shape = RoundedCornerShape(16.dp))
.align(Alignment.CenterStart)
.padding(all = 8.dp)
@ -279,22 +282,20 @@ fun PlayerBottomSheet(
.size(18.dp)
)
Image(
painter = painterResource(R.drawable.shuffle),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.padding(end = 2.dp)
.clickable {
reorderingState.coroutineScope.launch {
reorderingState.lazyListState.smoothScrollToTop()
}.invokeOnCompletion {
binder.player.shuffleQueue()
}
IconButton(
icon = R.drawable.shuffle,
color = colorPalette.text,
onClick = {
reorderingState.coroutineScope.launch {
reorderingState.lazyListState.smoothScrollToTop()
}.invokeOnCompletion {
binder.player.shuffleQueue()
}
.align(Alignment.CenterEnd)
.padding(all = 8.dp)
},
modifier = Modifier
.padding(horizontal = 4.dp, vertical = 8.dp)
.size(20.dp)
.align(Alignment.CenterEnd)
)
}
}

View file

@ -8,9 +8,7 @@ import androidx.activity.compose.LocalActivityResultRegistryOwner
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@ -40,12 +38,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.media3.common.Player
@ -58,6 +54,7 @@ import it.vfsfitvnm.vimusic.ui.components.BottomSheetState
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
import it.vfsfitvnm.vimusic.ui.components.rememberBottomSheetState
import it.vfsfitvnm.vimusic.ui.components.themed.BaseMediaItemMenu
import it.vfsfitvnm.vimusic.ui.components.themed.IconButton
import it.vfsfitvnm.vimusic.ui.styling.Dimensions
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.ui.styling.collapsedPlayerProgressBar
@ -178,44 +175,32 @@ fun PlayerView(
modifier = Modifier
.height(Dimensions.collapsedPlayer)
) {
Box(
modifier = Modifier
.clickable {
if (shouldBePlaying) {
binder.player.pause()
} else {
if (binder.player.playbackState == Player.STATE_IDLE) {
binder.player.prepare()
}
binder.player.play()
IconButton(
icon = if (shouldBePlaying) R.drawable.pause else R.drawable.play,
color = colorPalette.text,
onClick = {
if (shouldBePlaying) {
binder.player.pause()
} else {
if (binder.player.playbackState == Player.STATE_IDLE) {
binder.player.prepare()
}
binder.player.play()
}
.padding(horizontal = 4.dp, vertical = 8.dp)
) {
Image(
painter = painterResource(if (shouldBePlaying) R.drawable.pause else R.drawable.play),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.align(Alignment.Center)
.size(20.dp)
)
}
Box(
},
modifier = Modifier
.clickable(onClick = binder.player::seekToNext)
.padding(horizontal = 4.dp, vertical = 8.dp)
) {
Image(
painter = painterResource(R.drawable.play_skip_forward),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.align(Alignment.Center)
.size(20.dp)
)
}
.size(20.dp)
)
IconButton(
icon = R.drawable.play_skip_forward,
color = colorPalette.text,
onClick = binder.player::seekToNext,
modifier = Modifier
.padding(horizontal = 4.dp, vertical = 8.dp)
.size(20.dp)
)
}
Spacer(
@ -335,65 +320,60 @@ fun PlayerView(
.padding(horizontal = 8.dp)
.fillMaxHeight()
) {
Image(
painter = painterResource(R.drawable.ellipsis_horizontal),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable {
menuState.display {
val resultRegistryOwner =
LocalActivityResultRegistryOwner.current
IconButton(
icon = R.drawable.ellipsis_horizontal,
color = colorPalette.text,
onClick = {
menuState.display {
val resultRegistryOwner =
LocalActivityResultRegistryOwner.current
BaseMediaItemMenu(
mediaItem = mediaItem,
onStartRadio = {
binder.stopRadio()
binder.player.seamlessPlay(mediaItem)
binder.setupRadio(
NavigationEndpoint.Endpoint.Watch(videoId = mediaItem.mediaId)
)
},
onGoToEqualizer = {
val intent =
Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL).apply {
putExtra(
AudioEffect.EXTRA_AUDIO_SESSION,
binder.player.audioSessionId
)
putExtra(
AudioEffect.EXTRA_PACKAGE_NAME,
context.packageName
)
putExtra(
AudioEffect.EXTRA_CONTENT_TYPE,
AudioEffect.CONTENT_TYPE_MUSIC
)
}
if (intent.resolveActivity(context.packageManager) != null) {
val contract =
ActivityResultContracts.StartActivityForResult()
resultRegistryOwner?.activityResultRegistry
?.register("", contract) {}
?.launch(intent)
} else {
Toast
.makeText(
context,
"No equalizer app found!",
Toast.LENGTH_SHORT
)
.show()
BaseMediaItemMenu(
mediaItem = mediaItem,
onStartRadio = {
binder.stopRadio()
binder.player.seamlessPlay(mediaItem)
binder.setupRadio(
NavigationEndpoint.Endpoint.Watch(videoId = mediaItem.mediaId)
)
},
onGoToEqualizer = {
val intent =
Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL).apply {
putExtra(
AudioEffect.EXTRA_AUDIO_SESSION,
binder.player.audioSessionId
)
putExtra(
AudioEffect.EXTRA_PACKAGE_NAME,
context.packageName
)
putExtra(
AudioEffect.EXTRA_CONTENT_TYPE,
AudioEffect.CONTENT_TYPE_MUSIC
)
}
},
onSetSleepTimer = {},
onDismiss = menuState::hide
)
}
if (intent.resolveActivity(context.packageManager) != null) {
val contract =
ActivityResultContracts.StartActivityForResult()
resultRegistryOwner?.activityResultRegistry
?.register("", contract) {}
?.launch(intent)
} else {
Toast
.makeText(context, "No equalizer app found!", Toast.LENGTH_SHORT)
.show()
}
},
onSetSleepTimer = {},
onDismiss = menuState::hide
)
}
.padding(all = 8.dp)
},
modifier = Modifier
.padding(horizontal = 4.dp, vertical = 8.dp)
.size(20.dp)
)

View file

@ -3,9 +3,7 @@ package it.vfsfitvnm.vimusic.ui.screens.playlist
import android.content.Intent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@ -28,9 +26,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import com.valentinilk.shimmer.shimmer
@ -45,6 +41,7 @@ import it.vfsfitvnm.vimusic.savers.resultSaver
import it.vfsfitvnm.vimusic.transaction
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
import it.vfsfitvnm.vimusic.ui.components.themed.Header
import it.vfsfitvnm.vimusic.ui.components.themed.HeaderIconButton
import it.vfsfitvnm.vimusic.ui.components.themed.HeaderPlaceholder
import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu
import it.vfsfitvnm.vimusic.ui.components.themed.PrimaryButton
@ -137,57 +134,47 @@ fun PlaylistSongList(
.weight(1f)
)
Image(
painter = painterResource(
if (isImported == true) R.drawable.bookmark else R.drawable.bookmark_outline
),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.accent),
modifier = Modifier
.clickable(enabled = isImported == false) {
transaction {
val playlistId =
Database.insert(
Playlist(
name = playlist.title ?: "Unknown",
browseId = browseId
)
HeaderIconButton(
icon = if (isImported == true) R.drawable.bookmark else R.drawable.bookmark_outline,
color = colorPalette.accent,
onClick = {
transaction {
val playlistId =
Database.insert(
Playlist(
name = playlist.title ?: "Unknown",
browseId = browseId
)
)
playlist.songsPage?.items
?.map(Innertube.SongItem::asMediaItem)
?.onEach(Database::insert)
?.mapIndexed { index, mediaItem ->
SongPlaylistMap(
songId = mediaItem.mediaId,
playlistId = playlistId,
position = index
)
}?.let(Database::insertSongPlaylistMaps)
}
playlist.songsPage?.items
?.map(Innertube.SongItem::asMediaItem)
?.onEach(Database::insert)
?.mapIndexed { index, mediaItem ->
SongPlaylistMap(
songId = mediaItem.mediaId,
playlistId = playlistId,
position = index
)
}?.let(Database::insertSongPlaylistMaps)
}
.padding(all = 4.dp)
.size(18.dp)
}
)
Image(
painter = painterResource(R.drawable.share_social),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable {
(playlist.url ?: "https://music.youtube.com/playlist?list=${browseId.removePrefix("VL")}").let { url ->
val sendIntent = Intent().apply {
action = Intent.ACTION_SEND
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, url)
}
context.startActivity(Intent.createChooser(sendIntent, null))
HeaderIconButton(
icon = R.drawable.share_social,
color = colorPalette.text,
onClick = {
(playlist.url ?: "https://music.youtube.com/playlist?list=${browseId.removePrefix("VL")}").let { url ->
val sendIntent = Intent().apply {
action = Intent.ACTION_SEND
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, url)
}
context.startActivity(Intent.createChooser(sendIntent, null))
}
.padding(all = 4.dp)
.size(18.dp)
}
)
}