Revamp SettingsScreen

This commit is contained in:
vfsfitvnm
2022-06-07 19:09:46 +02:00
parent 17b5ed36f3
commit 5c9e10bf05
5 changed files with 209 additions and 41 deletions

View File

@@ -1,25 +1,35 @@
package it.vfsfitvnm.vimusic.ui.screens package it.vfsfitvnm.vimusic.ui.screens
import androidx.annotation.DrawableRes
import androidx.compose.animation.AnimatedContentScope
import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.with
import androidx.compose.foundation.* import androidx.compose.foundation.*
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.BasicText import androidx.compose.foundation.text.BasicText
import androidx.compose.material.ripple.rememberRipple import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import it.vfsfitvnm.route.Route0
import it.vfsfitvnm.route.RouteHandler import it.vfsfitvnm.route.RouteHandler
import it.vfsfitvnm.route.fastFade
import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.components.themed.EnumValueSelectorDialog import it.vfsfitvnm.vimusic.ui.components.themed.EnumValueSelectorDialog
import it.vfsfitvnm.vimusic.ui.screens.settings.AppearanceScreen
import it.vfsfitvnm.vimusic.ui.screens.settings.BackupAndRestoreScreen
import it.vfsfitvnm.vimusic.ui.screens.settings.rememberAppearanceRoute
import it.vfsfitvnm.vimusic.ui.screens.settings.rememberBackupAndRestoreRoute
import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
import it.vfsfitvnm.vimusic.ui.styling.LocalTypography import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
import it.vfsfitvnm.vimusic.utils.LocalPreferences import it.vfsfitvnm.vimusic.utils.medium
import it.vfsfitvnm.vimusic.utils.secondary import it.vfsfitvnm.vimusic.utils.secondary
import it.vfsfitvnm.vimusic.utils.semiBold import it.vfsfitvnm.vimusic.utils.semiBold
@@ -28,10 +38,26 @@ import it.vfsfitvnm.vimusic.utils.semiBold
fun SettingsScreen() { fun SettingsScreen() {
val albumRoute = rememberPlaylistOrAlbumRoute() val albumRoute = rememberPlaylistOrAlbumRoute()
val artistRoute = rememberArtistRoute() val artistRoute = rememberArtistRoute()
val appearanceRoute = rememberAppearanceRoute()
val scrollState = rememberScrollState() val scrollState = rememberScrollState()
RouteHandler(listenToGlobalEmitter = true) { RouteHandler(
listenToGlobalEmitter = true,
transitionSpec = {
when (targetState.route) {
appearanceRoute ->
slideIntoContainer(AnimatedContentScope.SlideDirection.Left) with
slideOutOfContainer(AnimatedContentScope.SlideDirection.Left)
else -> when (initialState.route) {
appearanceRoute ->
slideIntoContainer(AnimatedContentScope.SlideDirection.Right) with
slideOutOfContainer(AnimatedContentScope.SlideDirection.Right)
else -> fastFade
}
}
}
) {
albumRoute { browseId -> albumRoute { browseId ->
PlaylistOrAlbumScreen( PlaylistOrAlbumScreen(
browseId = browseId ?: error("browseId cannot be null") browseId = browseId ?: error("browseId cannot be null")
@@ -44,17 +70,20 @@ fun SettingsScreen() {
) )
} }
appearanceRoute {
AppearanceScreen()
}
host { host {
val colorPalette = LocalColorPalette.current val colorPalette = LocalColorPalette.current
val typography = LocalTypography.current val typography = LocalTypography.current
val preferences = LocalPreferences.current
Column( Column(
modifier = Modifier modifier = Modifier
.padding(bottom = 72.dp)
.background(colorPalette.background) .background(colorPalette.background)
.fillMaxSize() .fillMaxSize()
.verticalScroll(scrollState) .verticalScroll(scrollState)
.padding(bottom = 72.dp)
) { ) {
TopAppBar( TopAppBar(
modifier = Modifier modifier = Modifier
@@ -82,43 +111,66 @@ fun SettingsScreen() {
) )
} }
Row( @Composable
verticalAlignment = Alignment.CenterVertically, fun Entry(
modifier = Modifier @DrawableRes icon: Int,
.padding(horizontal = 16.dp, vertical = 8.dp) color: Color,
.background( title: String,
color = colorPalette.lightBackground, description: String,
shape = RoundedCornerShape(8.dp) route: Route0
)
.padding(vertical = 8.dp)
.fillMaxWidth()
) { ) {
Image( Row(
painter = painterResource(R.drawable.contrast), verticalAlignment = Alignment.CenterVertically,
contentDescription = null, horizontalArrangement = Arrangement.spacedBy(16.dp),
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier modifier = Modifier
.padding(horizontal = 16.dp, vertical = 8.dp) .clickable(
.size(20.dp) indication = rememberRipple(bounded = true),
) interactionSource = remember { MutableInteractionSource() },
onClick = {
route()
}
)
.padding(horizontal = 16.dp, vertical = 12.dp)
.fillMaxWidth()
) {
Box(
modifier = Modifier
.background(color = color, shape = CircleShape)
.size(36.dp)
) {
Image(
painter = painterResource(icon),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.background),
modifier = Modifier
.align(Alignment.Center)
.size(18.dp)
)
}
BasicText( Column {
text = "Appearance", BasicText(
style = typography.m.semiBold, text = title,
modifier = Modifier style = typography.s.semiBold,
) modifier = Modifier
)
BasicText(
text = description,
style = typography.xs.secondary.medium,
maxLines = 1,
modifier = Modifier
)
}
}
} }
EnumValueSelectorEntry( Entry(
title = "Theme mode", color = colorPalette.blue,
selectedValue = preferences.colorPaletteMode, icon = R.drawable.color_palette,
onValueSelected = preferences.onColorPaletteModeChange title = "Appearance",
) description = "Change the colors and shapes of the app",
route = appearanceRoute,
EnumValueSelectorEntry(
title = "Thumbnail roundness",
selectedValue = preferences.thumbnailRoundness,
onValueSelected = preferences.onThumbnailRoundnessChange
) )
} }
} }
@@ -126,7 +178,7 @@ fun SettingsScreen() {
} }
@Composable @Composable
private inline fun <reified T: Enum<T>>EnumValueSelectorEntry( inline fun <reified T: Enum<T>>EnumValueSelectorEntry(
title: String, title: String,
selectedValue: T, selectedValue: T,
crossinline onValueSelected: (T) -> Unit, crossinline onValueSelected: (T) -> Unit,
@@ -158,7 +210,8 @@ private inline fun <reified T: Enum<T>>EnumValueSelectorEntry(
interactionSource = remember { MutableInteractionSource() }, interactionSource = remember { MutableInteractionSource() },
onClick = { isShowingDialog = true } onClick = { isShowingDialog = true }
) )
.padding(horizontal = 32.dp, vertical = 8.dp) .padding(start = 24.dp)
.padding(horizontal = 32.dp, vertical = 16.dp)
.fillMaxWidth() .fillMaxWidth()
) { ) {
BasicText( BasicText(

View File

@@ -0,0 +1,94 @@
package it.vfsfitvnm.vimusic.ui.screens.settings
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import it.vfsfitvnm.route.RouteHandler
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.screens.*
import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
import it.vfsfitvnm.vimusic.utils.LocalPreferences
import it.vfsfitvnm.vimusic.utils.semiBold
@ExperimentalAnimationApi
@Composable
fun AppearanceScreen() {
val albumRoute = rememberPlaylistOrAlbumRoute()
val artistRoute = rememberArtistRoute()
val scrollState = rememberScrollState()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
PlaylistOrAlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
host {
val colorPalette = LocalColorPalette.current
val typography = LocalTypography.current
val preferences = LocalPreferences.current
Column(
modifier = Modifier
.background(colorPalette.background)
.fillMaxSize()
.verticalScroll(scrollState)
.padding(bottom = 72.dp)
) {
TopAppBar(
modifier = Modifier
.height(52.dp)
) {
Image(
painter = painterResource(R.drawable.chevron_back),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable(onClick = pop)
.padding(horizontal = 16.dp, vertical = 8.dp)
.size(24.dp)
)
BasicText(
text = "Appearance",
style = typography.m.semiBold
)
Spacer(
modifier = Modifier
.padding(horizontal = 16.dp, vertical = 8.dp)
.size(24.dp)
)
}
EnumValueSelectorEntry(
title = "Theme mode",
selectedValue = preferences.colorPaletteMode,
onValueSelected = preferences.onColorPaletteModeChange
)
EnumValueSelectorEntry(
title = "Thumbnail roundness",
selectedValue = preferences.thumbnailRoundness,
onValueSelected = preferences.onThumbnailRoundnessChange
)
}
}
}
}

View File

@@ -0,0 +1,12 @@
package it.vfsfitvnm.vimusic.ui.screens.settings
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import it.vfsfitvnm.route.Route0
@Composable
fun rememberAppearanceRoute(): Route0 {
return remember {
Route0("AppearanceRoute")
}
}

View File

@@ -35,10 +35,10 @@ val DarkColorPalette = ColorPalette(
lightGray = Color(0xfff8f8f8), lightGray = Color(0xfff8f8f8),
gray = Color(0xFFE5E5E5), gray = Color(0xFFE5E5E5),
darkGray = Color(0xFF838383), darkGray = Color(0xFF838383),
blue = Color(0xff4046bf), blue = Color(0xff507fdd),
red = Color(0xffbf4040), red = Color(0xffbf4040),
green = Color(0xff7fbf40), green = Color(0xff7fbf40),
orange = Color(0xffe8820e), orange = Color(0xffe9a033),
primaryContainer = Color(0xff4046bf), primaryContainer = Color(0xff4046bf),
onPrimaryContainer = Color.White, onPrimaryContainer = Color.White,

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FF000000"
android:pathData="M441,336.2l-0.06,-0.05c-9.93,-9.18 -22.78,-11.34 -32.16,-12.92l-0.69,-0.12c-9.05,-1.49 -10.48,-2.5 -14.58,-6.17 -2.44,-2.17 -5.35,-5.65 -5.35,-9.94s2.91,-7.77 5.34,-9.94l30.28,-26.87c25.92,-22.91 40.2,-53.66 40.2,-86.59S449.73,119.92 423.78,97c-35.89,-31.59 -85,-49 -138.37,-49C223.72,48 162,71.37 116,112.11c-43.87,38.77 -68,90.71 -68,146.24s24.16,107.47 68,146.23c21.75,19.24 47.49,34.18 76.52,44.42a266.17,266.17 0,0 0,86.87 15h1.81c61,0 119.09,-20.57 159.39,-56.4 9.7,-8.56 15.15,-20.83 15.34,-34.56C456.14,358.87 450.56,345.09 441,336.2ZM112,208a32,32 0,1 1,32 32A32,32 0,0 1,112 208ZM152,343a32,32 0,1 1,32 -32A32,32 0,0 1,152 343ZM192,144a32,32 0,1 1,32 32A32,32 0,0 1,192 144ZM256,415a48,48 0,1 1,48 -48A48,48 0,0 1,256 415ZM328,176a32,32 0,1 1,32 -32A32,32 0,0 1,328 176Z"/>
</vector>