Add OtherScreen in settings

This commit is contained in:
vfsfitvnm 2022-06-10 21:14:34 +02:00
parent 2c4e3b772b
commit 13357d10d7
7 changed files with 284 additions and 8 deletions

View file

@ -5,6 +5,7 @@ import android.content.Context
import coil.ImageLoader
import coil.ImageLoaderFactory
import coil.disk.DiskCache
import it.vfsfitvnm.vimusic.utils.preferences
class MainApplication : Application(), ImageLoaderFactory {
@ -14,7 +15,7 @@ class MainApplication : Application(), ImageLoaderFactory {
}
override fun newImageLoader(): ImageLoader {
return defaultCoilImageLoader(1024 * 1024 * 1024)
return defaultCoilImageLoader(preferences.coilDiskCacheMaxSizeBytes)
}
}

View file

@ -14,6 +14,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import it.vfsfitvnm.route.*
import it.vfsfitvnm.vimusic.R
@ -22,6 +23,7 @@ import it.vfsfitvnm.vimusic.ui.components.themed.EnumValueSelectorDialog
import it.vfsfitvnm.vimusic.ui.screens.settings.*
import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
import it.vfsfitvnm.vimusic.utils.disabled
import it.vfsfitvnm.vimusic.utils.medium
import it.vfsfitvnm.vimusic.utils.secondary
import it.vfsfitvnm.vimusic.utils.semiBold
@ -33,6 +35,7 @@ fun SettingsScreen() {
val artistRoute = rememberArtistRoute()
val appearanceRoute = rememberAppearanceRoute()
val backupAndRestoreRoute = rememberBackupAndRestoreRoute()
val otherRoute = rememberOtherRoute()
val aboutRoute = rememberAboutRoute()
val scrollState = rememberScrollState()
@ -41,9 +44,9 @@ fun SettingsScreen() {
listenToGlobalEmitter = true,
transitionSpec = {
when (targetState.route) {
appearanceRoute, backupAndRestoreRoute, aboutRoute -> leftSlide
appearanceRoute, backupAndRestoreRoute, otherRoute, aboutRoute -> leftSlide
else -> when (initialState.route) {
appearanceRoute, backupAndRestoreRoute, aboutRoute -> rightSlide
appearanceRoute, backupAndRestoreRoute, otherRoute, aboutRoute -> rightSlide
else -> fastFade
}
}
@ -69,6 +72,10 @@ fun SettingsScreen() {
BackupAndRestoreScreen()
}
otherRoute {
OtherScreen()
}
aboutRoute {
AboutScreen()
}
@ -178,6 +185,14 @@ fun SettingsScreen() {
route = backupAndRestoreRoute
)
Entry(
color = colorPalette.magenta,
icon = R.drawable.shapes,
title = "Other",
description = "Advanced options",
route = otherRoute
)
Entry(
color = colorPalette.green,
icon = R.drawable.information,
@ -216,25 +231,92 @@ inline fun <reified T: Enum<T>>EnumValueSelectorEntry(
)
}
Column(
SettingsEntry(
title = title,
text = valueText(selectedValue),
modifier = modifier,
onClick = {
isShowingDialog = true
}
)
}
@Composable
@NonRestartableComposable
fun SettingsEntry(
title: String,
text: String,
modifier: Modifier = Modifier,
onClick: () -> Unit
) {
BaseSettingsEntry(
title = title,
text = text,
modifier = modifier
.clickable(
indication = rememberRipple(bounded = true),
interactionSource = remember { MutableInteractionSource() },
onClick = { isShowingDialog = true }
onClick = onClick
)
)
}
@Composable
@NonRestartableComposable
fun DisabledSettingsEntry(
title: String,
text: String,
modifier: Modifier = Modifier,
) {
BaseSettingsEntry(
title = title,
text = text,
modifier = modifier,
titleTextStyle = { disabled },
textStyle = { disabled },
)
}
@Composable
fun BaseSettingsEntry(
title: String,
text: String,
modifier: Modifier = Modifier,
titleTextStyle: @Composable TextStyle.() -> TextStyle = { this },
textStyle: @Composable TextStyle.() -> TextStyle = { this },
) {
val typography = LocalTypography.current
Column(
modifier = modifier
.padding(start = 24.dp)
.padding(horizontal = 32.dp, vertical = 16.dp)
.fillMaxWidth()
) {
BasicText(
text = title,
style = typography.xs.semiBold,
style = typography.xs.semiBold.run { titleTextStyle() },
)
BasicText(
text = valueText(selectedValue),
style = typography.xs.semiBold.secondary
text = text,
style = typography.xs.semiBold.secondary.run { textStyle() }
)
}
}
@Composable
fun SettingsEntryGroupText(
title: String,
modifier: Modifier = Modifier,
) {
val typography = LocalTypography.current
BasicText(
text = title.uppercase(),
style = typography.xs.semiBold,
modifier = modifier
.padding(start = 24.dp, top = 24.dp)
.padding(horizontal = 32.dp)
)
}

View file

@ -0,0 +1,170 @@
package it.vfsfitvnm.vimusic.ui.screens.settings
import android.text.format.Formatter
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import coil.Coil
import coil.annotation.ExperimentalCoilApi
import it.vfsfitvnm.route.RouteHandler
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.ui.components.SeekBar
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.secondary
import it.vfsfitvnm.vimusic.utils.semiBold
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@OptIn(ExperimentalCoilApi::class)
@ExperimentalAnimationApi
@Composable
fun OtherScreen() {
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 context = LocalContext.current
val colorPalette = LocalColorPalette.current
val typography = LocalTypography.current
val preferences = LocalPreferences.current
var coilDiskCache by remember {
mutableStateOf(Coil.imageLoader(context).diskCache)
}
val coroutineScope = rememberCoroutineScope()
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 = "Other",
style = typography.m.semiBold
)
Spacer(
modifier = Modifier
.padding(horizontal = 16.dp, vertical = 8.dp)
.size(24.dp)
)
}
coilDiskCache?.let { diskCache ->
var diskCacheSize by remember(diskCache) {
mutableStateOf(diskCache.size)
}
var scrubbingDiskCacheMaxSize by remember {
mutableStateOf<Long?>(null)
}
SettingsEntryGroupText(
title = "IMAGE CACHE",
)
Column(
modifier = Modifier
.padding(start = 24.dp)
.padding(horizontal = 32.dp, vertical = 16.dp)
.fillMaxWidth()
) {
BasicText(
text = "Max size",
style = typography.xs.semiBold,
)
BasicText(
text = Formatter.formatShortFileSize(context, scrubbingDiskCacheMaxSize ?: preferences.coilDiskCacheMaxSizeBytes),
style = typography.xs.semiBold.secondary
)
SeekBar(
value = (scrubbingDiskCacheMaxSize ?: preferences.coilDiskCacheMaxSizeBytes).coerceIn(250L * 1024 * 1024, 2048L * 1024 * 1024),
minimumValue = 250L * 1024 * 1024,
maximumValue = 2048L * 1024 * 1024,
onDragStart = {
scrubbingDiskCacheMaxSize = it
},
onDrag = { delta ->
scrubbingDiskCacheMaxSize = scrubbingDiskCacheMaxSize?.plus(delta)?.coerceIn(250L * 1024 * 1024, 2048L * 1024 * 1024)
println("new = $scrubbingDiskCacheMaxSize")
},
onDragEnd = {
preferences.coilDiskCacheMaxSizeBytes = scrubbingDiskCacheMaxSize ?: preferences.coilDiskCacheMaxSizeBytes
scrubbingDiskCacheMaxSize = null
},
color = colorPalette.text,
backgroundColor = colorPalette.textDisabled,
shape = RoundedCornerShape(8.dp),
modifier = Modifier
.padding(top = 8.dp)
.fillMaxWidth()
)
}
DisabledSettingsEntry(
title = "Space used",
text = "${Formatter.formatShortFileSize(context, diskCacheSize)} (${diskCacheSize * 100 / preferences.coilDiskCacheMaxSizeBytes.coerceAtLeast(1)}%)",
)
SettingsEntry(
title = "Clear space",
text = "Wipe every cached image",
onClick = {
coroutineScope.launch(Dispatchers.IO) {
diskCache.clear()
diskCacheSize = diskCache.size
}
}
)
}
}
}
}
}

View file

@ -18,6 +18,13 @@ fun rememberBackupAndRestoreRoute(): Route0 {
}
}
@Composable
fun rememberOtherRoute(): Route0 {
return remember {
Route0("OtherRoute")
}
}
@Composable
fun rememberAboutRoute(): Route0 {
return remember {

View file

@ -18,6 +18,7 @@ data class ColorPalette(
val red: Color,
val green: Color,
val orange: Color,
val magenta: Color,
val primaryContainer: Color,
val onPrimaryContainer: Color,
@ -38,6 +39,7 @@ val DarkColorPalette = ColorPalette(
red = Color(0xffbf4040),
green = Color(0xff82b154),
orange = Color(0xffe9a033),
magenta = Color(0xffbb4da4),
primaryContainer = Color(0xff4046bf),
onPrimaryContainer = Color.White,
@ -64,6 +66,7 @@ val LightColorPalette = ColorPalette(
red = Color(0xffbf4040),
green = Color(0xff7fbf40),
orange = Color(0xffe8730e),
magenta = Color(0xffbb4da4),
primaryContainer = Color(0xff4046bf),
onPrimaryContainer = Color.White,

View file

@ -22,6 +22,7 @@ class Preferences(holder: SharedPreferences) : SharedPreferences by holder {
var repeatMode by preference("repeatMode", Player.REPEAT_MODE_OFF)
var homePageSongCollection by preference("homePageSongCollection", SongCollection.MostPlayed)
var thumbnailRoundness by preference("thumbnailRoundness", ThumbnailRoundness.Light)
var coilDiskCacheMaxSizeBytes by preference("coilDiskCacheMaxSizeBytes", 512L * 1024 * 1024)
}
val Context.preferences: Preferences

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FF000000"
android:pathData="M336,336H32a16,16 0,0 1,-14 -23.81l152,-272a16,16 0,0 1,27.94 0l152,272A16,16 0,0 1,336 336Z"/>
<path
android:fillColor="#FF000000"
android:pathData="M336,160a161.07,161.07 0,0 0,-32.57 3.32L377.9,296.59A48,48 0,0 1,336 368H183.33A160,160 0,1 0,336 160Z"/>
</vector>