mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
WIP
This commit is contained in:
parent
6a1725fd3d
commit
ea243975ad
11 changed files with 234 additions and 84 deletions
|
|
@ -325,8 +325,8 @@ class MainActivity : AppCompatActivity() {
|
|||
// ?: Destination.Home(),
|
||||
// TODO undo
|
||||
?: Destination.MediaItem(
|
||||
itemId = "bbc3e562-6045-5521-dfda-7effa56e14f2".toUUID(),
|
||||
type = BaseItemKind.MUSIC_ARTIST,
|
||||
itemId = "011ef0c7ca45684f2cd9dd3b020ca5f6".toUUID(),
|
||||
type = BaseItemKind.MUSIC_ALBUM,
|
||||
),
|
||||
navigationManager = navigationManager,
|
||||
preferences = preferences,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.github.damontecres.wholphin.data.model.AudioItem
|
|||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.services.hilt.AuthOkHttpClient
|
||||
import com.github.damontecres.wholphin.ui.DefaultItemFields
|
||||
import com.github.damontecres.wholphin.ui.main.settings.MoveDirection
|
||||
import com.github.damontecres.wholphin.ui.onMain
|
||||
import com.github.damontecres.wholphin.ui.toServerString
|
||||
import com.github.damontecres.wholphin.util.BlockingList
|
||||
|
|
@ -200,6 +201,14 @@ class MusicService
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun moveQueue(
|
||||
index: Int,
|
||||
direction: MoveDirection,
|
||||
) = withContext(Dispatchers.Main) {
|
||||
player.moveMediaItem(index, if (direction == MoveDirection.UP) index - 1 else index + 1)
|
||||
updateQueueSize()
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.relocation.BringIntoViewRequester
|
||||
import androidx.compose.foundation.relocation.bringIntoViewRequester
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
|
|
@ -21,9 +22,11 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
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.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
|
|
@ -330,6 +333,9 @@ fun AlbumDetailsPage(
|
|||
item {
|
||||
Text(
|
||||
text = stringResource(R.string.songs),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
)
|
||||
}
|
||||
itemsIndexed(state.songs) { index, song ->
|
||||
|
|
@ -389,7 +395,11 @@ fun AlbumHeader(
|
|||
AsyncImage(
|
||||
model = imageUrl,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.fillMaxWidth(.25f),
|
||||
contentScale = ContentScale.FillWidth,
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth(.20f)
|
||||
.clip(RoundedCornerShape(16.dp)),
|
||||
)
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.relocation.BringIntoViewRequester
|
||||
import androidx.compose.foundation.relocation.bringIntoViewRequester
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
|
|
@ -22,9 +23,11 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
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.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
|
|
@ -58,9 +61,11 @@ import com.github.damontecres.wholphin.ui.components.GenreText
|
|||
import com.github.damontecres.wholphin.ui.components.LoadingPage
|
||||
import com.github.damontecres.wholphin.ui.components.OverviewText
|
||||
import com.github.damontecres.wholphin.ui.components.QuickDetails
|
||||
import com.github.damontecres.wholphin.ui.launchDefault
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
import com.github.damontecres.wholphin.ui.letNotEmpty
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import com.github.damontecres.wholphin.ui.toBaseItems
|
||||
import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||
|
|
@ -149,13 +154,44 @@ class ArtistViewModel
|
|||
loading = LoadingState.Success,
|
||||
)
|
||||
}
|
||||
backdropService.submit(artist)
|
||||
|
||||
viewModelScope.launchIO {
|
||||
val request =
|
||||
GetItemsRequest(
|
||||
parentId = itemId,
|
||||
fields = DefaultItemFields,
|
||||
recursive = true,
|
||||
includeItemTypes = listOf(BaseItemKind.AUDIO),
|
||||
minCommunityRating = 1.0,
|
||||
sortBy =
|
||||
listOf(
|
||||
ItemSortBy.COMMUNITY_RATING,
|
||||
),
|
||||
sortOrder = listOf(SortOrder.DESCENDING),
|
||||
limit = 10,
|
||||
)
|
||||
val topSongs =
|
||||
GetItemsRequestHandler.execute(api, request).toBaseItems(api, false)
|
||||
if (topSongs.isNotEmpty()) {
|
||||
_state.update {
|
||||
it.copy(topSongs = topSongs)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
_state.update { it.copy(loading = LoadingState.Error(ex)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun init() {
|
||||
viewModelScope.launchDefault {
|
||||
state.value.artist?.let {
|
||||
backdropService.submit(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setFavorite(
|
||||
itemId: UUID,
|
||||
favorite: Boolean,
|
||||
|
|
@ -169,14 +205,25 @@ class ArtistViewModel
|
|||
_state.update { it.copy(artist = artist) }
|
||||
}
|
||||
|
||||
fun play(
|
||||
shuffled: Boolean,
|
||||
startIndex: Int = 0,
|
||||
) {
|
||||
fun play(shuffled: Boolean) {
|
||||
viewModelScope.launchIO {
|
||||
Timber.v("Playing artist %s from %s", itemId, startIndex)
|
||||
val songs = state.value.topSongs as ApiRequestPager<*>
|
||||
musicService.setQueue(songs, startIndex, shuffled)
|
||||
Timber.v("Playing artist %s", itemId)
|
||||
val request =
|
||||
GetItemsRequest(
|
||||
parentId = itemId,
|
||||
fields = DefaultItemFields,
|
||||
recursive = true,
|
||||
includeItemTypes = listOf(BaseItemKind.AUDIO),
|
||||
sortBy =
|
||||
listOf(
|
||||
ItemSortBy.PREMIERE_DATE,
|
||||
ItemSortBy.INDEX_NUMBER,
|
||||
),
|
||||
sortOrder = listOf(SortOrder.DESCENDING, SortOrder.ASCENDING),
|
||||
)
|
||||
val pager =
|
||||
ApiRequestPager(api, request, GetItemsRequestHandler, viewModelScope).init()
|
||||
musicService.setQueue(pager, 0, shuffled)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -199,6 +246,12 @@ class ArtistViewModel
|
|||
navigationManager.navigateTo(Destination.NowPlaying)
|
||||
}
|
||||
}
|
||||
|
||||
fun playSong(song: BaseItem) {
|
||||
viewModelScope.launchDefault {
|
||||
musicService.setQueue(listOf(song), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class ArtistState(
|
||||
|
|
@ -233,7 +286,7 @@ fun ArtistDetailsPage(
|
|||
remember {
|
||||
MusicMoreDialogActions(
|
||||
onNavigate = { viewModel.navigationManager.navigateTo(it) },
|
||||
onClickPlay = { index, _ -> viewModel.play(false, index) },
|
||||
onClickPlay = { index, song -> TODO() },
|
||||
onClickAddToQueue = { index, itemId -> viewModel.addToQueue(itemId, index) },
|
||||
onClickFavorite = { itemId, favorite -> viewModel.setFavorite(itemId, favorite) },
|
||||
onClickAddPlaylist = {},
|
||||
|
|
@ -254,7 +307,10 @@ fun ArtistDetailsPage(
|
|||
LoadingState.Success -> {
|
||||
val artist = state.artist!!
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
LaunchedEffect(Unit) { focusRequester.requestFocus() }
|
||||
LaunchedEffect(Unit) {
|
||||
focusRequester.requestFocus()
|
||||
viewModel.init()
|
||||
}
|
||||
val bringIntoViewRequester = remember { BringIntoViewRequester() }
|
||||
Box(modifier = modifier) {
|
||||
LazyColumn(
|
||||
|
|
@ -284,7 +340,7 @@ fun ArtistDetailsPage(
|
|||
actions =
|
||||
remember {
|
||||
MusicButtonActions(
|
||||
onClickPlay = { viewModel.play(it, 0) },
|
||||
onClickPlay = { viewModel.play(it) },
|
||||
onClickInstantMix = viewModel::startInstantMix,
|
||||
onClickFavorite = {
|
||||
viewModel.setFavorite(
|
||||
|
|
@ -320,13 +376,16 @@ fun ArtistDetailsPage(
|
|||
if (state.topSongs.isNotEmpty()) {
|
||||
item {
|
||||
Text(
|
||||
text = stringResource(R.string.songs),
|
||||
text = stringResource(R.string.popular_songs),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
)
|
||||
}
|
||||
itemsIndexed(state.topSongs) { index, song ->
|
||||
SongListItem(
|
||||
song = song,
|
||||
onClick = { viewModel.play(false, index) },
|
||||
onClick = { song?.let { viewModel.playSong(it) } },
|
||||
onLongClick = {
|
||||
if (song != null) {
|
||||
moreDialog =
|
||||
|
|
@ -403,7 +462,11 @@ fun ArtistHeader(
|
|||
AsyncImage(
|
||||
model = imageUrl,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.fillMaxWidth(.25f),
|
||||
contentScale = ContentScale.FillWidth,
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth(.20f)
|
||||
.clip(RoundedCornerShape(16.dp)),
|
||||
)
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import androidx.compose.animation.core.tween
|
|||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
|
|
@ -15,6 +16,7 @@ import androidx.compose.foundation.layout.fillMaxHeight
|
|||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
|
|
@ -46,11 +48,13 @@ import androidx.tv.material3.Text
|
|||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.model.AudioItem
|
||||
import com.github.damontecres.wholphin.ui.ifElse
|
||||
import com.github.damontecres.wholphin.ui.main.settings.MoveDirection
|
||||
import com.github.damontecres.wholphin.ui.playback.ControllerViewState
|
||||
import com.github.damontecres.wholphin.ui.playback.PlaybackAction
|
||||
import com.github.damontecres.wholphin.ui.playback.PlaybackButtons
|
||||
import com.github.damontecres.wholphin.ui.playback.PlaybackFaButton
|
||||
import com.github.damontecres.wholphin.ui.playback.SeekBar
|
||||
import com.github.damontecres.wholphin.ui.preferences.MoveButton
|
||||
import com.github.damontecres.wholphin.ui.roundSeconds
|
||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -65,6 +69,7 @@ fun NowPlayingOverlay(
|
|||
current: AudioItem?,
|
||||
queue: List<AudioItem>,
|
||||
controllerViewState: ControllerViewState,
|
||||
onMoveQueue: (Int, MoveDirection) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
|
@ -228,23 +233,46 @@ fun NowPlayingOverlay(
|
|||
},
|
||||
) {
|
||||
itemsIndexed(queue) { index, song ->
|
||||
SongListItem(
|
||||
title = song.title,
|
||||
artist = song.artistNames,
|
||||
indexNumber = index + 1,
|
||||
runtime = song.runtime?.roundSeconds,
|
||||
showArtist = true,
|
||||
isPlaying = current?.id == song.id,
|
||||
onClick = {
|
||||
player.seekTo(index, 0L)
|
||||
},
|
||||
onLongClick = {},
|
||||
modifier =
|
||||
Modifier.ifElse(
|
||||
index == 0,
|
||||
Modifier.focusRequester(firstFocusRequester),
|
||||
),
|
||||
)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
SongListItem(
|
||||
title = song.title,
|
||||
artist = song.artistNames,
|
||||
indexNumber = index + 1,
|
||||
runtime = song.runtime?.roundSeconds,
|
||||
showArtist = true,
|
||||
isPlaying = current?.id == song.id,
|
||||
onClick = {
|
||||
player.seekTo(index, 0L)
|
||||
},
|
||||
onLongClick = {},
|
||||
modifier =
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.ifElse(
|
||||
index == 0,
|
||||
Modifier.focusRequester(firstFocusRequester),
|
||||
),
|
||||
)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.wrapContentWidth(),
|
||||
) {
|
||||
MoveButton(
|
||||
icon = R.string.fa_caret_up,
|
||||
enabled = index > 0,
|
||||
onClick = { onMoveQueue.invoke(index, MoveDirection.UP) },
|
||||
)
|
||||
MoveButton(
|
||||
icon = R.string.fa_caret_down,
|
||||
enabled = index < queue.lastIndex,
|
||||
onClick = { onMoveQueue.invoke(index, MoveDirection.DOWN) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import androidx.annotation.OptIn
|
|||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.expandHorizontally
|
||||
import androidx.compose.animation.shrinkHorizontally
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.focusable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
|
|
@ -131,7 +133,9 @@ fun NowPlayingPage(
|
|||
controllerViewState.hideControls()
|
||||
}
|
||||
AnimatedVisibility(
|
||||
controllerViewState.controlsVisible,
|
||||
visible = controllerViewState.controlsVisible,
|
||||
enter = slideInVertically { it },
|
||||
exit = slideOutVertically { it },
|
||||
modifier =
|
||||
Modifier
|
||||
.align(Alignment.BottomCenter),
|
||||
|
|
@ -142,6 +146,7 @@ fun NowPlayingPage(
|
|||
current = current,
|
||||
queue = queue,
|
||||
controllerViewState = controllerViewState,
|
||||
onMoveQueue = { index, direction -> viewModel.moveQueue(index, direction) },
|
||||
modifier =
|
||||
Modifier
|
||||
.background(AppColors.TransparentBlack50)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.github.damontecres.wholphin.services.MusicService
|
|||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.services.UserPreferencesService
|
||||
import com.github.damontecres.wholphin.ui.launchDefault
|
||||
import com.github.damontecres.wholphin.ui.main.settings.MoveDirection
|
||||
import com.github.damontecres.wholphin.ui.onMain
|
||||
import com.github.damontecres.wholphin.ui.playback.ControllerViewState
|
||||
import com.mayakapps.kache.InMemoryKache
|
||||
|
|
@ -164,4 +165,9 @@ class NowPlayingViewModel
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun moveQueue(
|
||||
index: Int,
|
||||
direction: MoveDirection,
|
||||
) = viewModelScope.launchDefault { musicService.moveQueue(index, direction) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.github.damontecres.wholphin.ui.detail.music
|
|||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
|
|
@ -22,7 +23,6 @@ import androidx.tv.material3.Text
|
|||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.ui.PreviewTvSpec
|
||||
import com.github.damontecres.wholphin.ui.enableMarquee
|
||||
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||
import com.github.damontecres.wholphin.ui.letNotEmpty
|
||||
import com.github.damontecres.wholphin.ui.roundMinutes
|
||||
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
||||
|
|
@ -98,51 +98,66 @@ fun SongListItem(
|
|||
modifier = modifier,
|
||||
) {
|
||||
val focused by interactionSource.collectIsFocusedAsState()
|
||||
ListItem(
|
||||
selected = isPlaying,
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
interactionSource = interactionSource,
|
||||
leadingContent = {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = indexNumber?.toString() ?: "",
|
||||
val leadingContent: @Composable (BoxScope.() -> Unit) = {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = indexNumber?.toString() ?: "",
|
||||
)
|
||||
if (isPlaying) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.PlayArrow,
|
||||
contentDescription = null,
|
||||
)
|
||||
if (isPlaying) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.PlayArrow,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
headlineContent = {
|
||||
Text(
|
||||
text = title ?: "",
|
||||
maxLines = 1,
|
||||
modifier = Modifier.enableMarquee(focused),
|
||||
)
|
||||
},
|
||||
supportingContent =
|
||||
if (showArtist && artist.isNotNullOrBlank()) {
|
||||
{
|
||||
Text(
|
||||
text = artist,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
val headlineContent = @Composable {
|
||||
Text(
|
||||
text = title ?: "",
|
||||
maxLines = 1,
|
||||
modifier = Modifier.enableMarquee(focused),
|
||||
)
|
||||
}
|
||||
val trailingContent = @Composable {
|
||||
Text(
|
||||
text = runtime.toString(),
|
||||
)
|
||||
}
|
||||
|
||||
if (showArtist) {
|
||||
// TODO use dense?
|
||||
ListItem(
|
||||
selected = isPlaying,
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
interactionSource = interactionSource,
|
||||
leadingContent = leadingContent,
|
||||
headlineContent = headlineContent,
|
||||
supportingContent = {
|
||||
Text(
|
||||
text = artist ?: "",
|
||||
)
|
||||
},
|
||||
trailingContent = {
|
||||
Text(
|
||||
text = runtime.toString(),
|
||||
)
|
||||
},
|
||||
scale = ListItemDefaults.scale(1f, 1f, .95f),
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
trailingContent = trailingContent,
|
||||
scale = ListItemDefaults.scale(1f, 1f, .95f),
|
||||
modifier = Modifier,
|
||||
)
|
||||
} else {
|
||||
ListItem(
|
||||
selected = isPlaying,
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
interactionSource = interactionSource,
|
||||
leadingContent = leadingContent,
|
||||
headlineContent = headlineContent,
|
||||
supportingContent = null,
|
||||
trailingContent = trailingContent,
|
||||
scale = ListItemDefaults.scale(1f, 1f, .95f),
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ import com.github.damontecres.wholphin.ui.components.BasicDialog
|
|||
import com.github.damontecres.wholphin.ui.components.Button
|
||||
import com.github.damontecres.wholphin.ui.launchDefault
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
import com.github.damontecres.wholphin.ui.main.settings.MoveDirection
|
||||
import com.github.damontecres.wholphin.ui.nav.NavDrawerItem
|
||||
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||
|
|
@ -85,11 +86,6 @@ data class NavDrawerPin(
|
|||
}
|
||||
}
|
||||
|
||||
enum class MoveDirection {
|
||||
UP,
|
||||
DOWN,
|
||||
}
|
||||
|
||||
private fun <T> List<T>.move(
|
||||
direction: MoveDirection,
|
||||
index: Int,
|
||||
|
|
@ -246,7 +242,7 @@ fun NavDrawerPreferenceListItem(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun MoveButton(
|
||||
fun MoveButton(
|
||||
@StringRes icon: Int,
|
||||
enabled: Boolean,
|
||||
onClick: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,26 @@
|
|||
package com.github.damontecres.wholphin.util
|
||||
|
||||
import java.util.function.IntFunction
|
||||
import java.util.function.Predicate
|
||||
|
||||
interface BlockingList<T> : List<T> {
|
||||
suspend fun getBlocking(index: Int): T
|
||||
|
||||
suspend fun indexOfBlocking(predicate: Predicate<T>): Int
|
||||
|
||||
companion object {
|
||||
fun <T> of(list: List<T>): BlockingList<T> = BlockingListWrapper(list)
|
||||
}
|
||||
}
|
||||
|
||||
private class BlockingListWrapper<T>(
|
||||
private val list: List<T>,
|
||||
) : BlockingList<T>,
|
||||
List<T> by list {
|
||||
override suspend fun getBlocking(index: Int): T = get(index)
|
||||
|
||||
override suspend fun indexOfBlocking(predicate: Predicate<T>): Int = indexOfFirst { predicate.test(it) }
|
||||
|
||||
@Deprecated("Deprecated")
|
||||
override fun <T> toArray(generator: IntFunction<Array<out T?>?>): Array<out T?> = super<List>.toArray(generator)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -726,5 +726,6 @@
|
|||
<string name="artist">Artist</string>
|
||||
<string name="album_artist">Album artist</string>
|
||||
<string name="album">Album</string>
|
||||
<string name="popular_songs">Popular songs</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue