Add IconButton composable
This commit is contained in:
parent
185c5ec726
commit
7fe9c1dee8
7 changed files with 299 additions and 366 deletions
|
@ -23,17 +23,12 @@ fun HeaderIconButton(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
enabled: Boolean = true
|
enabled: Boolean = true
|
||||||
) {
|
) {
|
||||||
Image(
|
IconButton(
|
||||||
painter = painterResource(icon),
|
icon = icon,
|
||||||
contentDescription = null,
|
color = color,
|
||||||
colorFilter = ColorFilter.tint(color),
|
onClick = onClick,
|
||||||
|
enabled = enabled,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.clickable(
|
|
||||||
indication = rememberRipple(bounded = false),
|
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
|
||||||
enabled = enabled,
|
|
||||||
onClick = onClick
|
|
||||||
)
|
|
||||||
.padding(all = 4.dp)
|
.padding(all = 4.dp)
|
||||||
.size(18.dp)
|
.size(18.dp)
|
||||||
)
|
)
|
||||||
|
@ -51,12 +46,13 @@ fun IconButton(
|
||||||
painter = painterResource(icon),
|
painter = painterResource(icon),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
colorFilter = ColorFilter.tint(color),
|
colorFilter = ColorFilter.tint(color),
|
||||||
modifier = modifier
|
modifier = Modifier
|
||||||
.clickable(
|
.clickable(
|
||||||
indication = rememberRipple(bounded = false),
|
indication = rememberRipple(bounded = false),
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
onClick = onClick
|
onClick = onClick
|
||||||
)
|
)
|
||||||
|
.then(modifier)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package it.vfsfitvnm.vimusic.ui.screens.album
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
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.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.valentinilk.shimmer.shimmer
|
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.innertubeItemsPageSaver
|
||||||
import it.vfsfitvnm.vimusic.savers.nullableSaver
|
import it.vfsfitvnm.vimusic.savers.nullableSaver
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.Header
|
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.HeaderPlaceholder
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.Scaffold
|
import it.vfsfitvnm.vimusic.ui.components.themed.Scaffold
|
||||||
import it.vfsfitvnm.vimusic.ui.items.AlbumItem
|
import it.vfsfitvnm.vimusic.ui.items.AlbumItem
|
||||||
|
@ -143,49 +141,39 @@ fun AlbumScreen(browseId: String) {
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
)
|
)
|
||||||
|
|
||||||
Image(
|
HeaderIconButton(
|
||||||
painter = painterResource(
|
icon = if (album?.bookmarkedAt == null) {
|
||||||
if (album?.bookmarkedAt == null) {
|
R.drawable.bookmark_outline
|
||||||
R.drawable.bookmark_outline
|
} else {
|
||||||
} else {
|
R.drawable.bookmark
|
||||||
R.drawable.bookmark
|
},
|
||||||
}
|
color = colorPalette.accent,
|
||||||
),
|
onClick = {
|
||||||
contentDescription = null,
|
val bookmarkedAt =
|
||||||
colorFilter = ColorFilter.tint(colorPalette.accent),
|
if (album?.bookmarkedAt == null) System.currentTimeMillis() else null
|
||||||
modifier = Modifier
|
|
||||||
.clickable {
|
|
||||||
val bookmarkedAt =
|
|
||||||
if (album?.bookmarkedAt == null) System.currentTimeMillis() else null
|
|
||||||
|
|
||||||
query {
|
query {
|
||||||
album
|
album
|
||||||
?.copy(bookmarkedAt = bookmarkedAt)
|
?.copy(bookmarkedAt = bookmarkedAt)
|
||||||
?.let(Database::update)
|
?.let(Database::update)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.padding(all = 4.dp)
|
}
|
||||||
.size(18.dp)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Image(
|
HeaderIconButton(
|
||||||
painter = painterResource(R.drawable.share_social),
|
icon = R.drawable.share_social,
|
||||||
contentDescription = null,
|
color = colorPalette.text,
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
onClick = {
|
||||||
modifier = Modifier
|
album?.shareUrl?.let { url ->
|
||||||
.clickable {
|
val sendIntent = Intent().apply {
|
||||||
album?.shareUrl?.let { url ->
|
action = Intent.ACTION_SEND
|
||||||
val sendIntent = Intent().apply {
|
type = "text/plain"
|
||||||
action = Intent.ACTION_SEND
|
putExtra(Intent.EXTRA_TEXT, url)
|
||||||
type = "text/plain"
|
|
||||||
putExtra(Intent.EXTRA_TEXT, url)
|
|
||||||
}
|
|
||||||
|
|
||||||
context.startActivity(Intent.createChooser(sendIntent, null))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.startActivity(Intent.createChooser(sendIntent, null))
|
||||||
}
|
}
|
||||||
.padding(all = 4.dp)
|
}
|
||||||
.size(18.dp)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package it.vfsfitvnm.vimusic.ui.screens.artist
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
|
@ -21,9 +20,7 @@ import androidx.compose.runtime.saveable.rememberSaveableStateHolder
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.valentinilk.shimmer.shimmer
|
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.savers.nullableSaver
|
||||||
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
|
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.Header
|
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.HeaderPlaceholder
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu
|
import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.Scaffold
|
import it.vfsfitvnm.vimusic.ui.components.themed.Scaffold
|
||||||
|
@ -96,7 +94,11 @@ fun ArtistScreen(browseId: String) {
|
||||||
stateSaver = nullableSaver(InnertubeArtistPageSaver),
|
stateSaver = nullableSaver(InnertubeArtistPageSaver),
|
||||||
tabIndex < 4
|
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) {
|
withContext(Dispatchers.IO) {
|
||||||
Innertube.artistPage(BrowseBody(browseId = browseId))
|
Innertube.artistPage(BrowseBody(browseId = browseId))
|
||||||
|
@ -154,35 +156,33 @@ fun ArtistScreen(browseId: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val headerContent: @Composable (textButton: (@Composable () -> Unit)?) -> Unit = { textButton ->
|
val headerContent: @Composable (textButton: (@Composable () -> Unit)?) -> Unit =
|
||||||
if (artist?.timestamp == null) {
|
{ textButton ->
|
||||||
HeaderPlaceholder(
|
if (artist?.timestamp == null) {
|
||||||
modifier = Modifier
|
HeaderPlaceholder(
|
||||||
.shimmer()
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
val context = LocalContext.current
|
|
||||||
|
|
||||||
Header(title = artist?.name ?: "Unknown") {
|
|
||||||
textButton?.invoke()
|
|
||||||
|
|
||||||
Spacer(
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.shimmer()
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
val (colorPalette) = LocalAppearance.current
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
Image(
|
Header(title = artist?.name ?: "Unknown") {
|
||||||
painter = painterResource(
|
textButton?.invoke()
|
||||||
if (artist?.bookmarkedAt == null) {
|
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
)
|
||||||
|
|
||||||
|
HeaderIconButton(
|
||||||
|
icon = if (artist?.bookmarkedAt == null) {
|
||||||
R.drawable.bookmark_outline
|
R.drawable.bookmark_outline
|
||||||
} else {
|
} else {
|
||||||
R.drawable.bookmark
|
R.drawable.bookmark
|
||||||
}
|
},
|
||||||
),
|
color = colorPalette.accent,
|
||||||
contentDescription = null,
|
onClick = {
|
||||||
colorFilter = ColorFilter.tint(LocalAppearance.current.colorPalette.accent),
|
|
||||||
modifier = Modifier
|
|
||||||
.clickable {
|
|
||||||
val bookmarkedAt =
|
val bookmarkedAt =
|
||||||
if (artist?.bookmarkedAt == null) System.currentTimeMillis() else null
|
if (artist?.bookmarkedAt == null) System.currentTimeMillis() else null
|
||||||
|
|
||||||
|
@ -192,16 +192,12 @@ fun ArtistScreen(browseId: String) {
|
||||||
?.let(Database::update)
|
?.let(Database::update)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(all = 4.dp)
|
)
|
||||||
.size(18.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
Image(
|
HeaderIconButton(
|
||||||
painter = painterResource(R.drawable.share_social),
|
icon = R.drawable.share_social,
|
||||||
contentDescription = null,
|
color = colorPalette.text,
|
||||||
colorFilter = ColorFilter.tint(LocalAppearance.current.colorPalette.text),
|
onClick = {
|
||||||
modifier = Modifier
|
|
||||||
.clickable {
|
|
||||||
val sendIntent = Intent().apply {
|
val sendIntent = Intent().apply {
|
||||||
action = Intent.ACTION_SEND
|
action = Intent.ACTION_SEND
|
||||||
type = "text/plain"
|
type = "text/plain"
|
||||||
|
@ -211,19 +207,12 @@ fun ArtistScreen(browseId: String) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
context.startActivity(
|
context.startActivity(Intent.createChooser(sendIntent, null))
|
||||||
Intent.createChooser(
|
|
||||||
sendIntent,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
.padding(all = 4.dp)
|
)
|
||||||
.size(18.dp)
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topIconButtonId = R.drawable.chevron_back,
|
topIconButtonId = R.drawable.chevron_back,
|
||||||
|
@ -256,36 +245,36 @@ fun ArtistScreen(browseId: String) {
|
||||||
val thumbnailSizeDp = Dimensions.thumbnails.song
|
val thumbnailSizeDp = Dimensions.thumbnails.song
|
||||||
val thumbnailSizePx = thumbnailSizeDp.px
|
val thumbnailSizePx = thumbnailSizeDp.px
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ItemsPage(
|
ItemsPage(
|
||||||
stateSaver = InnertubeSongsPageSaver,
|
stateSaver = InnertubeSongsPageSaver,
|
||||||
headerContent = headerContent,
|
headerContent = headerContent,
|
||||||
itemsPageProvider = youtubeArtist?.let {({ continuation ->
|
itemsPageProvider = youtubeArtist?.let {
|
||||||
continuation?.let {
|
({ continuation ->
|
||||||
Innertube.itemsPage(
|
continuation?.let {
|
||||||
body = ContinuationBody(continuation = continuation),
|
|
||||||
fromMusicResponsiveListItemRenderer = Innertube.SongItem::from,
|
|
||||||
)
|
|
||||||
} ?: youtubeArtist
|
|
||||||
?.songsEndpoint
|
|
||||||
?.takeIf { it.browseId != null }
|
|
||||||
?.let { endpoint ->
|
|
||||||
Innertube.itemsPage(
|
Innertube.itemsPage(
|
||||||
body = BrowseBody(
|
body = ContinuationBody(continuation = continuation),
|
||||||
browseId = endpoint.browseId!!,
|
|
||||||
params = endpoint.params,
|
|
||||||
),
|
|
||||||
fromMusicResponsiveListItemRenderer = Innertube.SongItem::from,
|
fromMusicResponsiveListItemRenderer = Innertube.SongItem::from,
|
||||||
)
|
)
|
||||||
}
|
} ?: youtubeArtist
|
||||||
?: Result.success(
|
?.songsEndpoint
|
||||||
Innertube.ItemsPage(
|
?.takeIf { it.browseId != null }
|
||||||
items = youtubeArtist?.songs,
|
?.let { endpoint ->
|
||||||
continuation = null
|
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 ->
|
itemContent = { song ->
|
||||||
SongItem(
|
SongItem(
|
||||||
song = song,
|
song = song,
|
||||||
|
@ -320,31 +309,33 @@ fun ArtistScreen(browseId: String) {
|
||||||
stateSaver = InnertubeAlbumsPageSaver,
|
stateSaver = InnertubeAlbumsPageSaver,
|
||||||
headerContent = headerContent,
|
headerContent = headerContent,
|
||||||
emptyItemsText = "This artist didn't release any album",
|
emptyItemsText = "This artist didn't release any album",
|
||||||
itemsPageProvider = youtubeArtist?.let {({ continuation ->
|
itemsPageProvider = youtubeArtist?.let {
|
||||||
continuation?.let {
|
({ continuation ->
|
||||||
Innertube.itemsPage(
|
continuation?.let {
|
||||||
body = ContinuationBody(continuation = continuation),
|
|
||||||
fromMusicTwoRowItemRenderer = Innertube.AlbumItem::from,
|
|
||||||
)
|
|
||||||
} ?: youtubeArtist
|
|
||||||
?.albumsEndpoint
|
|
||||||
?.takeIf { it.browseId != null }
|
|
||||||
?.let { endpoint ->
|
|
||||||
Innertube.itemsPage(
|
Innertube.itemsPage(
|
||||||
body = BrowseBody(
|
body = ContinuationBody(continuation = continuation),
|
||||||
browseId = endpoint.browseId!!,
|
|
||||||
params = endpoint.params,
|
|
||||||
),
|
|
||||||
fromMusicTwoRowItemRenderer = Innertube.AlbumItem::from,
|
fromMusicTwoRowItemRenderer = Innertube.AlbumItem::from,
|
||||||
)
|
)
|
||||||
}
|
} ?: youtubeArtist
|
||||||
?: Result.success(
|
?.albumsEndpoint
|
||||||
Innertube.ItemsPage(
|
?.takeIf { it.browseId != null }
|
||||||
items = youtubeArtist?.albums,
|
?.let { endpoint ->
|
||||||
continuation = null
|
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 ->
|
itemContent = { album ->
|
||||||
AlbumItem(
|
AlbumItem(
|
||||||
album = album,
|
album = album,
|
||||||
|
@ -368,31 +359,33 @@ fun ArtistScreen(browseId: String) {
|
||||||
stateSaver = InnertubeAlbumsPageSaver,
|
stateSaver = InnertubeAlbumsPageSaver,
|
||||||
headerContent = headerContent,
|
headerContent = headerContent,
|
||||||
emptyItemsText = "This artist didn't release any single",
|
emptyItemsText = "This artist didn't release any single",
|
||||||
itemsPageProvider = youtubeArtist?.let {({ continuation ->
|
itemsPageProvider = youtubeArtist?.let {
|
||||||
continuation?.let {
|
({ continuation ->
|
||||||
Innertube.itemsPage(
|
continuation?.let {
|
||||||
body = ContinuationBody(continuation = continuation),
|
|
||||||
fromMusicTwoRowItemRenderer = Innertube.AlbumItem::from,
|
|
||||||
)
|
|
||||||
} ?: youtubeArtist
|
|
||||||
?.singlesEndpoint
|
|
||||||
?.takeIf { it.browseId != null }
|
|
||||||
?.let { endpoint ->
|
|
||||||
Innertube.itemsPage(
|
Innertube.itemsPage(
|
||||||
body = BrowseBody(
|
body = ContinuationBody(continuation = continuation),
|
||||||
browseId = endpoint.browseId!!,
|
|
||||||
params = endpoint.params,
|
|
||||||
),
|
|
||||||
fromMusicTwoRowItemRenderer = Innertube.AlbumItem::from,
|
fromMusicTwoRowItemRenderer = Innertube.AlbumItem::from,
|
||||||
)
|
)
|
||||||
}
|
} ?: youtubeArtist
|
||||||
?: Result.success(
|
?.singlesEndpoint
|
||||||
Innertube.ItemsPage(
|
?.takeIf { it.browseId != null }
|
||||||
items = youtubeArtist?.singles,
|
?.let { endpoint ->
|
||||||
continuation = null
|
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 ->
|
itemContent = { album ->
|
||||||
AlbumItem(
|
AlbumItem(
|
||||||
album = album,
|
album = album,
|
||||||
|
|
|
@ -40,6 +40,7 @@ import it.vfsfitvnm.vimusic.transaction
|
||||||
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
|
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.ConfirmationDialog
|
import it.vfsfitvnm.vimusic.ui.components.themed.ConfirmationDialog
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.Header
|
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.InPlaylistMediaItemMenu
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.PrimaryButton
|
import it.vfsfitvnm.vimusic.ui.components.themed.PrimaryButton
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.SecondaryTextButton
|
import it.vfsfitvnm.vimusic.ui.components.themed.SecondaryTextButton
|
||||||
|
@ -164,59 +165,46 @@ fun LocalPlaylistSongs(
|
||||||
)
|
)
|
||||||
|
|
||||||
playlistWithSongs?.playlist?.browseId?.let { browseId ->
|
playlistWithSongs?.playlist?.browseId?.let { browseId ->
|
||||||
Image(
|
HeaderIconButton(
|
||||||
painter = painterResource(R.drawable.sync),
|
icon = R.drawable.sync,
|
||||||
contentDescription = null,
|
color = colorPalette.text,
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
onClick = {
|
||||||
modifier = Modifier
|
transaction {
|
||||||
.clickable {
|
runBlocking(Dispatchers.IO) {
|
||||||
transaction {
|
withContext(Dispatchers.IO) {
|
||||||
runBlocking(Dispatchers.IO) {
|
Innertube.playlistPage(BrowseBody(browseId = browseId))?.completed()
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
}?.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(
|
HeaderIconButton(
|
||||||
painter = painterResource(R.drawable.pencil),
|
icon = R.drawable.pencil,
|
||||||
contentDescription = null,
|
color = colorPalette.text,
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
onClick = { isRenaming = true }
|
||||||
modifier = Modifier
|
|
||||||
.clickable { isRenaming = true }
|
|
||||||
.padding(all = 4.dp)
|
|
||||||
.size(18.dp)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
HeaderIconButton(
|
||||||
Image(
|
icon = R.drawable.trash,
|
||||||
painter = painterResource(R.drawable.trash),
|
color = colorPalette.text,
|
||||||
contentDescription = null,
|
onClick = { isDeleting = true }
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
|
||||||
modifier = Modifier
|
|
||||||
.clickable { isDeleting = true }
|
|
||||||
.padding(all = 4.dp)
|
|
||||||
.size(18.dp)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ import it.vfsfitvnm.vimusic.ui.components.BottomSheet
|
||||||
import it.vfsfitvnm.vimusic.ui.components.BottomSheetState
|
import it.vfsfitvnm.vimusic.ui.components.BottomSheetState
|
||||||
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
|
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
|
||||||
import it.vfsfitvnm.vimusic.ui.components.MusicBars
|
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.components.themed.QueuedMediaItemMenu
|
||||||
import it.vfsfitvnm.vimusic.ui.items.SongItem
|
import it.vfsfitvnm.vimusic.ui.items.SongItem
|
||||||
import it.vfsfitvnm.vimusic.ui.items.SongItemPlaceholder
|
import it.vfsfitvnm.vimusic.ui.items.SongItemPlaceholder
|
||||||
|
@ -227,7 +228,10 @@ fun PlayerBottomSheet(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.animateItemPlacement(reorderingState = reorderingState)
|
.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)
|
.height(64.dp + bottomPadding)
|
||||||
.background(colorPalette.background2)
|
.background(colorPalette.background2)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 8.dp)
|
.padding(horizontal = 12.dp)
|
||||||
.padding(bottom = bottomPadding)
|
.padding(bottom = bottomPadding)
|
||||||
) {
|
) {
|
||||||
BasicText(
|
BasicText(
|
||||||
text = "${windows.size} songs",
|
text = "${windows.size} songs",
|
||||||
style = typography.xxs.medium,
|
style = typography.xxs.medium,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 4.dp)
|
|
||||||
.background(color = colorPalette.background1, shape = RoundedCornerShape(16.dp))
|
.background(color = colorPalette.background1, shape = RoundedCornerShape(16.dp))
|
||||||
.align(Alignment.CenterStart)
|
.align(Alignment.CenterStart)
|
||||||
.padding(all = 8.dp)
|
.padding(all = 8.dp)
|
||||||
|
@ -279,22 +282,20 @@ fun PlayerBottomSheet(
|
||||||
.size(18.dp)
|
.size(18.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Image(
|
IconButton(
|
||||||
painter = painterResource(R.drawable.shuffle),
|
icon = R.drawable.shuffle,
|
||||||
contentDescription = null,
|
color = colorPalette.text,
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
onClick = {
|
||||||
modifier = Modifier
|
reorderingState.coroutineScope.launch {
|
||||||
.padding(end = 2.dp)
|
reorderingState.lazyListState.smoothScrollToTop()
|
||||||
.clickable {
|
}.invokeOnCompletion {
|
||||||
reorderingState.coroutineScope.launch {
|
binder.player.shuffleQueue()
|
||||||
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)
|
.size(20.dp)
|
||||||
|
.align(Alignment.CenterEnd)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,7 @@ import androidx.activity.compose.LocalActivityResultRegistryOwner
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
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.clip
|
||||||
import androidx.compose.ui.draw.drawBehind
|
import androidx.compose.ui.draw.drawBehind
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.media3.common.Player
|
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.LocalMenuState
|
||||||
import it.vfsfitvnm.vimusic.ui.components.rememberBottomSheetState
|
import it.vfsfitvnm.vimusic.ui.components.rememberBottomSheetState
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.BaseMediaItemMenu
|
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.Dimensions
|
||||||
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
|
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
|
||||||
import it.vfsfitvnm.vimusic.ui.styling.collapsedPlayerProgressBar
|
import it.vfsfitvnm.vimusic.ui.styling.collapsedPlayerProgressBar
|
||||||
|
@ -178,44 +175,32 @@ fun PlayerView(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(Dimensions.collapsedPlayer)
|
.height(Dimensions.collapsedPlayer)
|
||||||
) {
|
) {
|
||||||
Box(
|
IconButton(
|
||||||
modifier = Modifier
|
icon = if (shouldBePlaying) R.drawable.pause else R.drawable.play,
|
||||||
.clickable {
|
color = colorPalette.text,
|
||||||
if (shouldBePlaying) {
|
onClick = {
|
||||||
binder.player.pause()
|
if (shouldBePlaying) {
|
||||||
} else {
|
binder.player.pause()
|
||||||
if (binder.player.playbackState == Player.STATE_IDLE) {
|
} else {
|
||||||
binder.player.prepare()
|
if (binder.player.playbackState == Player.STATE_IDLE) {
|
||||||
}
|
binder.player.prepare()
|
||||||
binder.player.play()
|
|
||||||
}
|
}
|
||||||
|
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
|
modifier = Modifier
|
||||||
.clickable(onClick = binder.player::seekToNext)
|
|
||||||
.padding(horizontal = 4.dp, vertical = 8.dp)
|
.padding(horizontal = 4.dp, vertical = 8.dp)
|
||||||
) {
|
.size(20.dp)
|
||||||
Image(
|
)
|
||||||
painter = painterResource(R.drawable.play_skip_forward),
|
|
||||||
contentDescription = null,
|
IconButton(
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
icon = R.drawable.play_skip_forward,
|
||||||
modifier = Modifier
|
color = colorPalette.text,
|
||||||
.align(Alignment.Center)
|
onClick = binder.player::seekToNext,
|
||||||
.size(20.dp)
|
modifier = Modifier
|
||||||
)
|
.padding(horizontal = 4.dp, vertical = 8.dp)
|
||||||
}
|
.size(20.dp)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(
|
Spacer(
|
||||||
|
@ -335,65 +320,60 @@ fun PlayerView(
|
||||||
.padding(horizontal = 8.dp)
|
.padding(horizontal = 8.dp)
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
) {
|
) {
|
||||||
Image(
|
IconButton(
|
||||||
painter = painterResource(R.drawable.ellipsis_horizontal),
|
icon = R.drawable.ellipsis_horizontal,
|
||||||
contentDescription = null,
|
color = colorPalette.text,
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
onClick = {
|
||||||
modifier = Modifier
|
menuState.display {
|
||||||
.clickable {
|
val resultRegistryOwner =
|
||||||
menuState.display {
|
LocalActivityResultRegistryOwner.current
|
||||||
val resultRegistryOwner =
|
|
||||||
LocalActivityResultRegistryOwner.current
|
|
||||||
|
|
||||||
BaseMediaItemMenu(
|
BaseMediaItemMenu(
|
||||||
mediaItem = mediaItem,
|
mediaItem = mediaItem,
|
||||||
onStartRadio = {
|
onStartRadio = {
|
||||||
binder.stopRadio()
|
binder.stopRadio()
|
||||||
binder.player.seamlessPlay(mediaItem)
|
binder.player.seamlessPlay(mediaItem)
|
||||||
binder.setupRadio(
|
binder.setupRadio(
|
||||||
NavigationEndpoint.Endpoint.Watch(videoId = mediaItem.mediaId)
|
NavigationEndpoint.Endpoint.Watch(videoId = mediaItem.mediaId)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onGoToEqualizer = {
|
onGoToEqualizer = {
|
||||||
val intent =
|
val intent =
|
||||||
Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL).apply {
|
Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL).apply {
|
||||||
putExtra(
|
putExtra(
|
||||||
AudioEffect.EXTRA_AUDIO_SESSION,
|
AudioEffect.EXTRA_AUDIO_SESSION,
|
||||||
binder.player.audioSessionId
|
binder.player.audioSessionId
|
||||||
)
|
)
|
||||||
putExtra(
|
putExtra(
|
||||||
AudioEffect.EXTRA_PACKAGE_NAME,
|
AudioEffect.EXTRA_PACKAGE_NAME,
|
||||||
context.packageName
|
context.packageName
|
||||||
)
|
)
|
||||||
putExtra(
|
putExtra(
|
||||||
AudioEffect.EXTRA_CONTENT_TYPE,
|
AudioEffect.EXTRA_CONTENT_TYPE,
|
||||||
AudioEffect.CONTENT_TYPE_MUSIC
|
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()
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
onSetSleepTimer = {},
|
if (intent.resolveActivity(context.packageManager) != null) {
|
||||||
onDismiss = menuState::hide
|
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)
|
.size(20.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,7 @@ package it.vfsfitvnm.vimusic.ui.screens.playlist
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
@ -28,9 +26,7 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
import androidx.compose.ui.draw.alpha
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.valentinilk.shimmer.shimmer
|
import com.valentinilk.shimmer.shimmer
|
||||||
|
@ -45,6 +41,7 @@ import it.vfsfitvnm.vimusic.savers.resultSaver
|
||||||
import it.vfsfitvnm.vimusic.transaction
|
import it.vfsfitvnm.vimusic.transaction
|
||||||
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
|
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.Header
|
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.HeaderPlaceholder
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu
|
import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.PrimaryButton
|
import it.vfsfitvnm.vimusic.ui.components.themed.PrimaryButton
|
||||||
|
@ -137,57 +134,47 @@ fun PlaylistSongList(
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
)
|
)
|
||||||
|
|
||||||
Image(
|
HeaderIconButton(
|
||||||
painter = painterResource(
|
icon = if (isImported == true) R.drawable.bookmark else R.drawable.bookmark_outline,
|
||||||
if (isImported == true) R.drawable.bookmark else R.drawable.bookmark_outline
|
color = colorPalette.accent,
|
||||||
),
|
onClick = {
|
||||||
contentDescription = null,
|
transaction {
|
||||||
colorFilter = ColorFilter.tint(colorPalette.accent),
|
val playlistId =
|
||||||
modifier = Modifier
|
Database.insert(
|
||||||
.clickable(enabled = isImported == false) {
|
Playlist(
|
||||||
transaction {
|
name = playlist.title ?: "Unknown",
|
||||||
val playlistId =
|
browseId = browseId
|
||||||
Database.insert(
|
|
||||||
Playlist(
|
|
||||||
name = playlist.title ?: "Unknown",
|
|
||||||
browseId = browseId
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
playlist.songsPage?.items
|
playlist.songsPage?.items
|
||||||
?.map(Innertube.SongItem::asMediaItem)
|
?.map(Innertube.SongItem::asMediaItem)
|
||||||
?.onEach(Database::insert)
|
?.onEach(Database::insert)
|
||||||
?.mapIndexed { index, mediaItem ->
|
?.mapIndexed { index, mediaItem ->
|
||||||
SongPlaylistMap(
|
SongPlaylistMap(
|
||||||
songId = mediaItem.mediaId,
|
songId = mediaItem.mediaId,
|
||||||
playlistId = playlistId,
|
playlistId = playlistId,
|
||||||
position = index
|
position = index
|
||||||
)
|
)
|
||||||
}?.let(Database::insertSongPlaylistMaps)
|
}?.let(Database::insertSongPlaylistMaps)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.padding(all = 4.dp)
|
}
|
||||||
.size(18.dp)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Image(
|
HeaderIconButton(
|
||||||
painter = painterResource(R.drawable.share_social),
|
icon = R.drawable.share_social,
|
||||||
contentDescription = null,
|
color = colorPalette.text,
|
||||||
colorFilter = ColorFilter.tint(colorPalette.text),
|
onClick = {
|
||||||
modifier = Modifier
|
(playlist.url ?: "https://music.youtube.com/playlist?list=${browseId.removePrefix("VL")}").let { url ->
|
||||||
.clickable {
|
val sendIntent = Intent().apply {
|
||||||
(playlist.url ?: "https://music.youtube.com/playlist?list=${browseId.removePrefix("VL")}").let { url ->
|
action = Intent.ACTION_SEND
|
||||||
val sendIntent = Intent().apply {
|
type = "text/plain"
|
||||||
action = Intent.ACTION_SEND
|
putExtra(Intent.EXTRA_TEXT, url)
|
||||||
type = "text/plain"
|
|
||||||
putExtra(Intent.EXTRA_TEXT, url)
|
|
||||||
}
|
|
||||||
|
|
||||||
context.startActivity(Intent.createChooser(sendIntent, null))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.startActivity(Intent.createChooser(sendIntent, null))
|
||||||
}
|
}
|
||||||
.padding(all = 4.dp)
|
}
|
||||||
.size(18.dp)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue