mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 07:29:14 +01:00
fix overscroll stretch, pad the album hero, push the gradient fade down
This commit is contained in:
@@ -3,7 +3,10 @@ package com.subtracks.ui.components
|
|||||||
import androidx.compose.animation.core.Animatable
|
import androidx.compose.animation.core.Animatable
|
||||||
import androidx.compose.animation.core.Spring
|
import androidx.compose.animation.core.Spring
|
||||||
import androidx.compose.animation.core.spring
|
import androidx.compose.animation.core.spring
|
||||||
|
import androidx.compose.foundation.LocalOverscrollFactory
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -17,10 +20,13 @@ import androidx.compose.ui.unit.Velocity
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
private const val MAX_STRETCH_FRACTION = 0.35f
|
private const val MAX_STRETCH_FRACTION = 0.30f
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Modifier.stretchOverscroll(): Modifier {
|
fun StretchOverscroll(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
content: @Composable () -> Unit,
|
||||||
|
) {
|
||||||
val overscroll = remember { Animatable(0f) }
|
val overscroll = remember { Animatable(0f) }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
@@ -58,13 +64,16 @@ fun Modifier.stretchOverscroll(): Modifier {
|
|||||||
consumed: Velocity,
|
consumed: Velocity,
|
||||||
available: Velocity,
|
available: Velocity,
|
||||||
): Velocity {
|
): Velocity {
|
||||||
overscroll.animateTo(0f, spring(stiffness = Spring.StiffnessMediumLow))
|
overscroll.animateTo(0f, spring(stiffness = Spring.StiffnessMedium))
|
||||||
return available
|
return available
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this
|
CompositionLocalProvider(LocalOverscrollFactory provides null) {
|
||||||
|
Box(
|
||||||
|
modifier =
|
||||||
|
modifier
|
||||||
.nestedScroll(connection)
|
.nestedScroll(connection)
|
||||||
.graphicsLayer {
|
.graphicsLayer {
|
||||||
val raw = overscroll.value
|
val raw = overscroll.value
|
||||||
@@ -79,5 +88,9 @@ fun Modifier.stretchOverscroll(): Modifier {
|
|||||||
translationY = resisted
|
translationY = resisted
|
||||||
transformOrigin = TransformOrigin(0.5f, if (resisted > 0f) 0f else 1f)
|
transformOrigin = TransformOrigin(0.5f, if (resisted > 0f) 0f else 1f)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
content()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ import androidx.compose.ui.layout.positionInParent
|
|||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
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.IntOffset
|
import androidx.compose.ui.unit.IntOffset
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
@@ -71,7 +72,7 @@ import com.subtracks.data.model.QueueKind
|
|||||||
import com.subtracks.data.model.Song
|
import com.subtracks.data.model.Song
|
||||||
import com.subtracks.playback.PlaybackController
|
import com.subtracks.playback.PlaybackController
|
||||||
import com.subtracks.ui.components.CoverArt
|
import com.subtracks.ui.components.CoverArt
|
||||||
import com.subtracks.ui.components.stretchOverscroll
|
import com.subtracks.ui.components.StretchOverscroll
|
||||||
import com.subtracks.ui.theme.ArtworkColors
|
import com.subtracks.ui.theme.ArtworkColors
|
||||||
import com.subtracks.ui.theme.ArtworkTheme
|
import com.subtracks.ui.theme.ArtworkTheme
|
||||||
import com.subtracks.ui.theme.HeroGradient
|
import com.subtracks.ui.theme.HeroGradient
|
||||||
@@ -82,7 +83,7 @@ import org.koin.core.parameter.parametersOf
|
|||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
private const val DOT = "\u00B7"
|
private const val DOT = "\u00B7"
|
||||||
private const val GRADIENT_SCREENS = 1.5f
|
private const val GRADIENT_SCREENS = 2.0f
|
||||||
private const val FADE_DISTANCE_DP = 64
|
private const val FADE_DISTANCE_DP = 64
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -129,6 +130,7 @@ fun AlbumDetailScreen(
|
|||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val statusBarTop = WindowInsets.statusBars.getTop(density)
|
val statusBarTop = WindowInsets.statusBars.getTop(density)
|
||||||
val navBarBottom = WindowInsets.navigationBars.getBottom(density)
|
val navBarBottom = WindowInsets.navigationBars.getBottom(density)
|
||||||
|
val statusBarDp = with(density) { statusBarTop.toDp() }
|
||||||
val barHeightPx = statusBarTop + with(density) { TopAppBarDefaults.TopAppBarExpandedHeight.toPx() }
|
val barHeightPx = statusBarTop + with(density) { TopAppBarDefaults.TopAppBarExpandedHeight.toPx() }
|
||||||
val fadeDistancePx = with(density) { FADE_DISTANCE_DP.dp.toPx() }
|
val fadeDistancePx = with(density) { FADE_DISTANCE_DP.dp.toPx() }
|
||||||
|
|
||||||
@@ -167,13 +169,14 @@ fun AlbumDetailScreen(
|
|||||||
.alpha(gradientAlpha),
|
.alpha(gradientAlpha),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
StretchOverscroll(modifier = Modifier.fillMaxSize()) {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
state = listState,
|
state = listState,
|
||||||
contentPadding =
|
contentPadding =
|
||||||
PaddingValues(
|
PaddingValues(
|
||||||
bottom = 16.dp + with(density) { navBarBottom.toDp() },
|
bottom = 16.dp + with(density) { navBarBottom.toDp() },
|
||||||
),
|
),
|
||||||
modifier = Modifier.fillMaxSize().stretchOverscroll(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
AlbumHeader(
|
AlbumHeader(
|
||||||
@@ -184,6 +187,7 @@ fun AlbumDetailScreen(
|
|||||||
onShuffle = onShuffle,
|
onShuffle = onShuffle,
|
||||||
onDownload = onDownload,
|
onDownload = onDownload,
|
||||||
onMore = onMore,
|
onMore = onMore,
|
||||||
|
topInset = statusBarDp,
|
||||||
titleModifier = Modifier.onGloballyPositioned { titleTopPx = it.positionInParent().y },
|
titleModifier = Modifier.onGloballyPositioned { titleTopPx = it.positionInParent().y },
|
||||||
modifier = Modifier.onSizeChanged { headerHeightPx = it.height.toFloat() },
|
modifier = Modifier.onSizeChanged { headerHeightPx = it.height.toFloat() },
|
||||||
)
|
)
|
||||||
@@ -199,12 +203,13 @@ fun AlbumDetailScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
Modifier
|
Modifier
|
||||||
.align(Alignment.TopStart)
|
.align(Alignment.TopStart)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(with(density) { (barHeightPx + 24.dp.toPx()).toDp() })
|
.height(statusBarDp + 8.dp)
|
||||||
.background(
|
.background(
|
||||||
Brush.verticalGradient(
|
Brush.verticalGradient(
|
||||||
listOf(Color.Black.copy(alpha = 0.8f), Color.Transparent),
|
listOf(Color.Black.copy(alpha = 0.8f), Color.Transparent),
|
||||||
@@ -216,6 +221,7 @@ fun AlbumDetailScreen(
|
|||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
text = album?.name.orEmpty(),
|
text = album?.name.orEmpty(),
|
||||||
|
style = MaterialTheme.typography.headlineLarge,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
modifier = Modifier.alpha(barFraction),
|
modifier = Modifier.alpha(barFraction),
|
||||||
@@ -250,6 +256,7 @@ private fun AlbumHeader(
|
|||||||
onShuffle: () -> Unit,
|
onShuffle: () -> Unit,
|
||||||
onDownload: () -> Unit,
|
onDownload: () -> Unit,
|
||||||
onMore: () -> Unit,
|
onMore: () -> Unit,
|
||||||
|
topInset: Dp,
|
||||||
titleModifier: Modifier = Modifier,
|
titleModifier: Modifier = Modifier,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
@@ -257,7 +264,7 @@ private fun AlbumHeader(
|
|||||||
modifier =
|
modifier =
|
||||||
modifier
|
modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 24.dp, end = 24.dp, top = 8.dp, bottom = 16.dp),
|
.padding(start = 24.dp, end = 24.dp, top = topInset + 8.dp, bottom = 16.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
CoverArt(
|
CoverArt(
|
||||||
@@ -268,7 +275,7 @@ private fun AlbumHeader(
|
|||||||
Spacer(Modifier.height(20.dp))
|
Spacer(Modifier.height(20.dp))
|
||||||
Text(
|
Text(
|
||||||
text = album?.name.orEmpty(),
|
text = album?.name.orEmpty(),
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
style = MaterialTheme.typography.headlineLarge,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
maxLines = 2,
|
maxLines = 2,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import com.subtracks.data.model.CoverArtRef
|
|||||||
import com.subtracks.ui.components.CoverArt
|
import com.subtracks.ui.components.CoverArt
|
||||||
import com.subtracks.ui.components.EmptyState
|
import com.subtracks.ui.components.EmptyState
|
||||||
import com.subtracks.ui.components.LoadingState
|
import com.subtracks.ui.components.LoadingState
|
||||||
import com.subtracks.ui.components.stretchOverscroll
|
import com.subtracks.ui.components.StretchOverscroll
|
||||||
|
|
||||||
const val ALBUM_COVER_TAG = "album-cover"
|
const val ALBUM_COVER_TAG = "album-cover"
|
||||||
|
|
||||||
@@ -45,12 +45,13 @@ fun AlbumsContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
|
StretchOverscroll(modifier = modifier.fillMaxSize()) {
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(3),
|
columns = GridCells.Fixed(3),
|
||||||
contentPadding = PaddingValues(start = 8.dp, top = 8.dp, end = 8.dp, bottom = bottomInset + 8.dp),
|
contentPadding = PaddingValues(start = 8.dp, top = 8.dp, end = 8.dp, bottom = bottomInset + 8.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
modifier = modifier.fillMaxSize().stretchOverscroll(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
) {
|
) {
|
||||||
items(count = items.itemCount, key = items.itemKey { it.id }) { index ->
|
items(count = items.itemCount, key = items.itemKey { it.id }) { index ->
|
||||||
val album = items[index]
|
val album = items[index]
|
||||||
@@ -71,4 +72,5 @@ fun AlbumsContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ import com.subtracks.data.model.Album
|
|||||||
import com.subtracks.data.model.Artist
|
import com.subtracks.data.model.Artist
|
||||||
import com.subtracks.data.model.CoverArtRef
|
import com.subtracks.data.model.CoverArtRef
|
||||||
import com.subtracks.ui.components.CoverArt
|
import com.subtracks.ui.components.CoverArt
|
||||||
import com.subtracks.ui.components.stretchOverscroll
|
import com.subtracks.ui.components.StretchOverscroll
|
||||||
import org.koin.compose.viewmodel.koinViewModel
|
import org.koin.compose.viewmodel.koinViewModel
|
||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
@@ -123,13 +123,14 @@ fun ArtistDetailScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
Box(modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)) {
|
Box(modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)) {
|
||||||
|
StretchOverscroll(modifier = Modifier.fillMaxSize()) {
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
state = listState,
|
state = listState,
|
||||||
columns = GridCells.Fixed(2),
|
columns = GridCells.Fixed(2),
|
||||||
contentPadding = PaddingValues(bottom = 16.dp + navBarBottom),
|
contentPadding = PaddingValues(bottom = 16.dp + navBarBottom),
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
modifier = Modifier.fillMaxSize().stretchOverscroll(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
) {
|
) {
|
||||||
item(span = { GridItemSpan(maxLineSpan) }) {
|
item(span = { GridItemSpan(maxLineSpan) }) {
|
||||||
Box(Modifier.fillMaxWidth().padding(bottom = 12.dp)) {
|
Box(Modifier.fillMaxWidth().padding(bottom = 12.dp)) {
|
||||||
@@ -178,6 +179,7 @@ fun ArtistDetailScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier =
|
modifier =
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import com.subtracks.data.model.CoverArtRef
|
|||||||
import com.subtracks.ui.components.CoverArt
|
import com.subtracks.ui.components.CoverArt
|
||||||
import com.subtracks.ui.components.EmptyState
|
import com.subtracks.ui.components.EmptyState
|
||||||
import com.subtracks.ui.components.LoadingState
|
import com.subtracks.ui.components.LoadingState
|
||||||
import com.subtracks.ui.components.stretchOverscroll
|
import com.subtracks.ui.components.StretchOverscroll
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ArtistsContent(
|
fun ArtistsContent(
|
||||||
@@ -44,8 +44,9 @@ fun ArtistsContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
|
StretchOverscroll(modifier = modifier.fillMaxSize()) {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = modifier.fillMaxSize().stretchOverscroll(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentPadding = PaddingValues(bottom = bottomInset),
|
contentPadding = PaddingValues(bottom = bottomInset),
|
||||||
) {
|
) {
|
||||||
items(count = items.itemCount, key = items.itemKey { it.id }) { index ->
|
items(count = items.itemCount, key = items.itemKey { it.id }) { index ->
|
||||||
@@ -81,4 +82,5 @@ fun ArtistsContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import com.subtracks.data.model.QueueKind
|
|||||||
import com.subtracks.data.model.SongListItem
|
import com.subtracks.data.model.SongListItem
|
||||||
import com.subtracks.playback.PlaybackController
|
import com.subtracks.playback.PlaybackController
|
||||||
import com.subtracks.ui.components.CoverArt
|
import com.subtracks.ui.components.CoverArt
|
||||||
import com.subtracks.ui.components.stretchOverscroll
|
import com.subtracks.ui.components.StretchOverscroll
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
import org.koin.compose.viewmodel.koinViewModel
|
import org.koin.compose.viewmodel.koinViewModel
|
||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
@@ -84,7 +84,8 @@ fun PlaylistDetailScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { padding ->
|
) { padding ->
|
||||||
LazyColumn(Modifier.padding(padding).fillMaxSize().stretchOverscroll()) {
|
StretchOverscroll(modifier = Modifier.padding(padding).fillMaxSize()) {
|
||||||
|
LazyColumn(Modifier.fillMaxSize()) {
|
||||||
item {
|
item {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth().padding(16.dp),
|
modifier = Modifier.fillMaxWidth().padding(16.dp),
|
||||||
@@ -120,4 +121,5 @@ fun PlaylistDetailScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import com.subtracks.data.model.Playlist
|
|||||||
import com.subtracks.ui.components.CoverArt
|
import com.subtracks.ui.components.CoverArt
|
||||||
import com.subtracks.ui.components.EmptyState
|
import com.subtracks.ui.components.EmptyState
|
||||||
import com.subtracks.ui.components.LoadingState
|
import com.subtracks.ui.components.LoadingState
|
||||||
import com.subtracks.ui.components.stretchOverscroll
|
import com.subtracks.ui.components.StretchOverscroll
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PlaylistsContent(
|
fun PlaylistsContent(
|
||||||
@@ -44,8 +44,9 @@ fun PlaylistsContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
|
StretchOverscroll(modifier = modifier.fillMaxSize()) {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = modifier.fillMaxSize().stretchOverscroll(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentPadding = PaddingValues(bottom = bottomInset),
|
contentPadding = PaddingValues(bottom = bottomInset),
|
||||||
) {
|
) {
|
||||||
items(count = items.itemCount, key = items.itemKey { it.id }) { index ->
|
items(count = items.itemCount, key = items.itemKey { it.id }) { index ->
|
||||||
@@ -81,4 +82,5 @@ fun PlaylistsContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import com.subtracks.data.model.SongListItem
|
|||||||
import com.subtracks.ui.components.CoverArt
|
import com.subtracks.ui.components.CoverArt
|
||||||
import com.subtracks.ui.components.EmptyState
|
import com.subtracks.ui.components.EmptyState
|
||||||
import com.subtracks.ui.components.LoadingState
|
import com.subtracks.ui.components.LoadingState
|
||||||
import com.subtracks.ui.components.stretchOverscroll
|
import com.subtracks.ui.components.StretchOverscroll
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SongsContent(
|
fun SongsContent(
|
||||||
@@ -53,8 +53,9 @@ fun SongsContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
|
StretchOverscroll(modifier = modifier.fillMaxSize()) {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = modifier.fillMaxSize().stretchOverscroll(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentPadding = PaddingValues(bottom = bottomInset),
|
contentPadding = PaddingValues(bottom = bottomInset),
|
||||||
) {
|
) {
|
||||||
items(count = items.itemCount, key = items.itemKey { it.song.id }) { index ->
|
items(count = items.itemCount, key = items.itemKey { it.song.id }) { index ->
|
||||||
@@ -72,6 +73,7 @@ fun SongsContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ import com.subtracks.data.repo.SourceRepository
|
|||||||
import com.subtracks.playback.PlaybackController
|
import com.subtracks.playback.PlaybackController
|
||||||
import com.subtracks.ui.components.EmptyState
|
import com.subtracks.ui.components.EmptyState
|
||||||
import com.subtracks.ui.components.LoadingState
|
import com.subtracks.ui.components.LoadingState
|
||||||
import com.subtracks.ui.components.stretchOverscroll
|
import com.subtracks.ui.components.StretchOverscroll
|
||||||
import com.subtracks.ui.library.SongRow
|
import com.subtracks.ui.library.SongRow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -339,9 +339,10 @@ fun QueueScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
|
StretchOverscroll(modifier = Modifier.padding(padding).fillMaxSize()) {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
state = listState,
|
state = listState,
|
||||||
modifier = Modifier.padding(padding).fillMaxSize().stretchOverscroll(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentPadding = PaddingValues(bottom = 16.dp),
|
contentPadding = PaddingValues(bottom = 16.dp),
|
||||||
) {
|
) {
|
||||||
items(count = rows.size, key = { rows[it].id }) { index ->
|
items(count = rows.size, key = { rows[it].id }) { index ->
|
||||||
@@ -394,6 +395,7 @@ fun QueueScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun dropTarget(
|
internal fun dropTarget(
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import androidx.compose.ui.text.input.KeyboardType
|
|||||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.subtracks.ui.components.stretchOverscroll
|
|
||||||
import org.koin.compose.viewmodel.koinViewModel
|
import org.koin.compose.viewmodel.koinViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -106,7 +105,6 @@ fun AddSourceScreen(
|
|||||||
Modifier
|
Modifier
|
||||||
.padding(padding)
|
.padding(padding)
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.stretchOverscroll()
|
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.subtracks.data.model.Source
|
import com.subtracks.data.model.Source
|
||||||
import com.subtracks.ui.components.stretchOverscroll
|
import com.subtracks.ui.components.StretchOverscroll
|
||||||
import org.koin.compose.viewmodel.koinViewModel
|
import org.koin.compose.viewmodel.koinViewModel
|
||||||
|
|
||||||
private val bitrateOptions = listOf(0, 24, 32, 64, 96, 128, 192, 256, 320)
|
private val bitrateOptions = listOf(0, 24, 32, 64, 96, 128, 192, 256, 320)
|
||||||
@@ -102,7 +102,8 @@ fun SettingsScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { padding ->
|
) { padding ->
|
||||||
LazyColumn(Modifier.padding(padding).fillMaxSize().stretchOverscroll()) {
|
StretchOverscroll(modifier = Modifier.padding(padding).fillMaxSize()) {
|
||||||
|
LazyColumn(Modifier.fillMaxSize()) {
|
||||||
item { SectionHeader("Servers") }
|
item { SectionHeader("Servers") }
|
||||||
items(sources.size, key = { sources[it].id }) { index ->
|
items(sources.size, key = { sources[it].id }) { index ->
|
||||||
val source = sources[index]
|
val source = sources[index]
|
||||||
@@ -156,6 +157,7 @@ fun SettingsScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
when (dialog) {
|
when (dialog) {
|
||||||
SettingsDialog.Bitrate -> {
|
SettingsDialog.Bitrate -> {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
private const val SEED_ART_SIZE_PX = 128
|
private const val SEED_ART_SIZE_PX = 128
|
||||||
private const val GRADIENT_FADE_START = 0.8f / 1.5f
|
private const val GRADIENT_FADE_START = 1.3f / 2.0f
|
||||||
|
|
||||||
data class ArtworkColors(
|
data class ArtworkColors(
|
||||||
val scheme: ColorScheme,
|
val scheme: ColorScheme,
|
||||||
@@ -84,7 +84,7 @@ fun artworkColorsFromSeed(seed: Int): ArtworkColors {
|
|||||||
scheme = scheme,
|
scheme = scheme,
|
||||||
gradientHigh = tone(hue, (s * 0.8f).coerceAtMost(0.60f), 0.30f),
|
gradientHigh = tone(hue, (s * 0.8f).coerceAtMost(0.60f), 0.30f),
|
||||||
gradientLow = tone(hue, s * 0.25f, 0.04f),
|
gradientLow = tone(hue, s * 0.25f, 0.04f),
|
||||||
accents = listOf(tone(hue, s, 0.70f), tone(hue, s * 0.85f, 0.38f)),
|
accents = listOf(tone(hue, s, 0.78f), tone(hue, s * 0.9f, 0.20f)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user