Procházet zdrojové kódy

Add TextCard component

vfsfitvnm před 3 roky
rodič
revize
fd41e78625

+ 110 - 0
app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextCard.kt

@@ -0,0 +1,110 @@
+package it.vfsfitvnm.vimusic.ui.components.themed
+
+import androidx.annotation.DrawableRes
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.text.BasicText
+import androidx.compose.material.ripple.rememberRipple
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
+import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
+import it.vfsfitvnm.vimusic.utils.align
+import it.vfsfitvnm.vimusic.utils.secondary
+import it.vfsfitvnm.vimusic.utils.semiBold
+
+
+@Composable
+fun TextCard(
+    modifier: Modifier = Modifier,
+    @DrawableRes icon: Int? = null,
+    iconColor: ColorFilter? = null,
+    onClick: (() -> Unit)? = null,
+    content: @Composable TextCardScope.() -> Unit,
+) {
+    val colorPalette = LocalColorPalette.current
+
+    Column(
+        modifier = modifier
+            .padding(horizontal = 16.dp, vertical = 16.dp)
+            .clickable(
+                interactionSource = remember { MutableInteractionSource() },
+                indication = rememberRipple(bounded = true),
+                enabled = onClick != null,
+                onClick = onClick ?: {}
+            )
+            .background(colorPalette.lightBackground)
+            .padding(horizontal = 16.dp, vertical = 16.dp)
+    ) {
+        icon?.let {
+            Image(
+                painter = painterResource(icon),
+                contentDescription = null,
+                colorFilter = iconColor ?: ColorFilter.tint(colorPalette.red),
+                modifier = Modifier
+                    .padding(bottom = 16.dp)
+                    .size(24.dp)
+            )
+        }
+
+        (icon?.let { IconTextCardScopeImpl } ?: TextCardScopeImpl).content()
+    }
+}
+
+interface TextCardScope {
+    @Composable
+    fun Title(text: String)
+
+    @Composable
+    fun Text(text: String)
+}
+
+private object TextCardScopeImpl : TextCardScope {
+    @Composable
+    override fun Title(text: String) {
+        BasicText(
+            text = text,
+            style = LocalTypography.current.xxs.semiBold,
+        )
+    }
+
+    @Composable
+    override fun Text(text: String) {
+        BasicText(
+            text = text,
+            style = LocalTypography.current.xxs.secondary.align(TextAlign.Justify),
+        )
+    }
+}
+
+private object IconTextCardScopeImpl : TextCardScope {
+    @Composable
+    override fun Title(text: String) {
+        BasicText(
+            text = text,
+            style = LocalTypography.current.xxs.semiBold,
+            modifier = Modifier
+                .padding(horizontal = 16.dp)
+        )
+    }
+
+    @Composable
+    override fun Text(text: String) {
+        BasicText(
+            text = text,
+            style = LocalTypography.current.xxs.secondary,
+            modifier = Modifier
+                .padding(horizontal = 16.dp)
+        )
+    }
+}

+ 14 - 53
app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/ArtistScreen.kt

@@ -4,14 +4,12 @@ import androidx.compose.animation.ExperimentalAnimationApi
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
-import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.*
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.itemsIndexed
 import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.foundation.text.BasicText
-import androidx.compose.material.ripple.rememberRipple
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
@@ -24,7 +22,6 @@ import androidx.compose.ui.draw.shadow
 import androidx.compose.ui.graphics.ColorFilter
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.zIndex
 import coil.compose.AsyncImage
@@ -38,6 +35,7 @@ import it.vfsfitvnm.vimusic.models.DetailedSong
 import it.vfsfitvnm.vimusic.query
 import it.vfsfitvnm.vimusic.ui.components.TopAppBar
 import it.vfsfitvnm.vimusic.ui.components.themed.InHistoryMediaItemMenu
+import it.vfsfitvnm.vimusic.ui.components.themed.TextCard
 import it.vfsfitvnm.vimusic.ui.components.themed.TextPlaceholder
 import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
 import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
@@ -154,7 +152,11 @@ fun ArtistScreen(
                                 .clickable {
                                     query {
                                         runBlocking {
-                                            Database.artist(browseId).first()?.copy(shufflePlaylistId = null)?.let(Database::update)
+                                            Database
+                                                .artist(browseId)
+                                                .first()
+                                                ?.copy(shufflePlaylistId = null)
+                                                ?.let(Database::update)
                                         }
                                     }
                                 }
@@ -292,22 +294,9 @@ fun ArtistScreen(
 
                 artistResult?.getOrNull()?.info?.let { description ->
                     item {
-                        Column(
-                            modifier = Modifier
-                                .padding(top = 32.dp)
-                                .padding(horizontal = 16.dp, vertical = 16.dp)
-                                .background(colorPalette.lightBackground)
-                                .padding(horizontal = 16.dp, vertical = 16.dp)
-                        ) {
-                            BasicText(
-                                text = "Information",
-                                style = typography.xxs.semiBold
-                            )
-
-                            BasicText(
-                                text = description,
-                                style = typography.xxs.secondary.align(TextAlign.Justify)
-                            )
+                        TextCard {
+                            Title(text = "Information")
+                            Text(text = description)
                         }
                     }
                 }
@@ -321,7 +310,6 @@ private fun LoadingOrError(
     errorMessage: String? = null,
     onRetry: (() -> Unit)? = null
 ) {
-    val typography = LocalTypography.current
     val colorPalette = LocalColorPalette.current
 
     Box {
@@ -353,41 +341,14 @@ private fun LoadingOrError(
         }
 
         errorMessage?.let {
-            Column(
+            TextCard(
+                icon = R.drawable.alert_circle,
+                onClick = onRetry,
                 modifier = Modifier
                     .align(Alignment.Center)
-                    .padding(horizontal = 16.dp, vertical = 16.dp)
-                    .clickable(
-                        interactionSource = remember { MutableInteractionSource() },
-                        indication = rememberRipple(bounded = true),
-                        enabled = onRetry != null,
-                        onClick = onRetry ?: {}
-                    )
-                    .background(colorPalette.lightBackground)
-                    .padding(horizontal = 16.dp, vertical = 16.dp)
             ) {
-                Image(
-                    painter = painterResource(R.drawable.alert_circle),
-                    contentDescription = null,
-                    colorFilter = ColorFilter.tint(colorPalette.red),
-                    modifier = Modifier
-                        .padding(bottom = 16.dp)
-                        .size(24.dp)
-                )
-
-                BasicText(
-                    text = onRetry?.let { "Tap to retry" } ?: "Error",
-                    style = typography.xxs.semiBold,
-                    modifier = Modifier
-                        .padding(horizontal = 16.dp)
-                )
-
-                BasicText(
-                    text = "An error has occurred:\n$errorMessage",
-                    style = typography.xxs.secondary,
-                    modifier = Modifier
-                        .padding(horizontal = 16.dp)
-                )
+                Title(text = onRetry?.let { "Tap to retry" } ?: "Error")
+                Text(text = "An error has occurred:\n$errorMessage")
             }
         }
     }

+ 7 - 41
app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/BackupAndRestoreScreen.kt

@@ -25,6 +25,7 @@ import it.vfsfitvnm.vimusic.*
 import it.vfsfitvnm.vimusic.R
 import it.vfsfitvnm.vimusic.ui.components.TopAppBar
 import it.vfsfitvnm.vimusic.ui.components.themed.ConfirmationDialog
+import it.vfsfitvnm.vimusic.ui.components.themed.TextCard
 import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen
 import it.vfsfitvnm.vimusic.ui.screens.PlaylistOrAlbumScreen
 import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute
@@ -194,7 +195,6 @@ fun BackupAndRestoreScreen() {
                         )
                     }
 
-
                     Column(
                         verticalArrangement = Arrangement.spacedBy(8.dp),
                         horizontalAlignment = Alignment.CenterHorizontally,
@@ -231,53 +231,19 @@ fun BackupAndRestoreScreen() {
                     }
                 }
 
-                Column(
-                    modifier = Modifier
-                        .padding(horizontal = 16.dp, vertical = 16.dp)
-                        .background(colorPalette.lightBackground)
-                        .padding(horizontal = 16.dp, vertical = 16.dp)
+                TextCard(
+                    icon = R.drawable.alert_circle,
                 ) {
-                    Image(
-                        painter = painterResource(R.drawable.alert_circle),
-                        contentDescription = null,
-                        colorFilter = ColorFilter.tint(colorPalette.red),
-                        modifier = Modifier
-                            .padding(bottom = 16.dp)
-                            .size(24.dp)
-                    )
-//
-                    BasicText(
-                        text = "Backup",
-                        style = typography.xxs.semiBold,
-                        modifier = Modifier
-                                .padding(horizontal = 16.dp)
-                    )
-
-                    BasicText(
-                        text = "The backup consists in exporting the application database to your device storage.\nThis means playlists, song history, favorites songs will exported.\nThis operation excludes personal preferences such as the theme mode and everything you can set in the Settings page.",
-                        style = typography.xxs.secondary,
-                        modifier = Modifier
-                            .padding(horizontal = 16.dp)
-                    )
+                    Title(text = "Backup")
+                    Text(text = "The backup consists in exporting the application database to your device storage.\nThis means playlists, song history, favorites songs will exported.\nThis operation excludes personal preferences such as the theme mode and everything you can set in the Settings page.")
 
                     Spacer(
                         modifier = Modifier
                             .height(32.dp)
                     )
 
-                    BasicText(
-                        text = "Restore",
-                        style = typography.xxs.semiBold,
-                        modifier = Modifier
-                            .padding(horizontal = 16.dp)
-                    )
-
-                    BasicText(
-                        text = "The restore replaces the existing application database with the selected - previously exported - one.\nThis means every currently existing data will be wiped: THE TWO DATABASES WON'T BE MERGED.\nIt is recommended to restore the database immediately after the application is installed on a new device.",
-                        style = typography.xxs.secondary,
-                        modifier = Modifier
-                            .padding(horizontal = 16.dp)
-                    )
+                    Title(text = "Restore")
+                    Text(text = "The restore replaces the existing application database with the selected - previously exported - one.\nThis means every currently existing data will be wiped: THE TWO DATABASES WON'T BE MERGED.\nIt is recommended to restore the database immediately after the application is installed on a new device.")
                 }
             }
         }

+ 6 - 0
app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/OtherSettingsScreen.kt

@@ -19,6 +19,7 @@ import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
 import it.vfsfitvnm.vimusic.R
 import it.vfsfitvnm.vimusic.ui.components.SeekBar
 import it.vfsfitvnm.vimusic.ui.components.TopAppBar
+import it.vfsfitvnm.vimusic.ui.components.themed.TextCard
 import it.vfsfitvnm.vimusic.ui.screens.*
 import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
 import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
@@ -224,6 +225,11 @@ fun OtherSettingsScreen() {
                         text = "${Formatter.formatShortFileSize(context, diskCacheSize)} (${diskCacheSize * 100 / preferences.exoPlayerDiskCacheMaxSizeBytes.coerceAtLeast(1)}%)",
                     )
                 }
+
+                TextCard(icon = R.drawable.alert_circle) {
+                    Title(text = "Cache strategy")
+                    Text(text = "The cache follows the LRU (Least Recently Used) strategy: when it runs out of space, the resources that haven't been accessed for the longest time are cleared to accommodate the new resource.")
+                }
             }
         }
     }