Pārlūkot izejas kodu

Add TextCard component

vfsfitvnm 3 gadi atpakaļ
vecāks
revīzija
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.Image
 import androidx.compose.foundation.background
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.clickable
-import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.*
 import androidx.compose.foundation.layout.*
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.itemsIndexed
 import androidx.compose.foundation.lazy.itemsIndexed
 import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.foundation.shape.CircleShape
 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.runtime.Composable
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 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.graphics.ColorFilter
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.zIndex
 import androidx.compose.ui.zIndex
 import coil.compose.AsyncImage
 import coil.compose.AsyncImage
@@ -38,6 +35,7 @@ import it.vfsfitvnm.vimusic.models.DetailedSong
 import it.vfsfitvnm.vimusic.query
 import it.vfsfitvnm.vimusic.query
 import it.vfsfitvnm.vimusic.ui.components.TopAppBar
 import it.vfsfitvnm.vimusic.ui.components.TopAppBar
 import it.vfsfitvnm.vimusic.ui.components.themed.InHistoryMediaItemMenu
 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.components.themed.TextPlaceholder
 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
@@ -154,7 +152,11 @@ fun ArtistScreen(
                                 .clickable {
                                 .clickable {
                                     query {
                                     query {
                                         runBlocking {
                                         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 ->
                 artistResult?.getOrNull()?.info?.let { description ->
                     item {
                     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,
     errorMessage: String? = null,
     onRetry: (() -> Unit)? = null
     onRetry: (() -> Unit)? = null
 ) {
 ) {
-    val typography = LocalTypography.current
     val colorPalette = LocalColorPalette.current
     val colorPalette = LocalColorPalette.current
 
 
     Box {
     Box {
@@ -353,41 +341,14 @@ private fun LoadingOrError(
         }
         }
 
 
         errorMessage?.let {
         errorMessage?.let {
-            Column(
+            TextCard(
+                icon = R.drawable.alert_circle,
+                onClick = onRetry,
                 modifier = Modifier
                 modifier = Modifier
                     .align(Alignment.Center)
                     .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.R
 import it.vfsfitvnm.vimusic.ui.components.TopAppBar
 import it.vfsfitvnm.vimusic.ui.components.TopAppBar
 import it.vfsfitvnm.vimusic.ui.components.themed.ConfirmationDialog
 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.ArtistScreen
 import it.vfsfitvnm.vimusic.ui.screens.PlaylistOrAlbumScreen
 import it.vfsfitvnm.vimusic.ui.screens.PlaylistOrAlbumScreen
 import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute
 import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute
@@ -194,7 +195,6 @@ fun BackupAndRestoreScreen() {
                         )
                         )
                     }
                     }
 
 
-
                     Column(
                     Column(
                         verticalArrangement = Arrangement.spacedBy(8.dp),
                         verticalArrangement = Arrangement.spacedBy(8.dp),
                         horizontalAlignment = Alignment.CenterHorizontally,
                         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(
                     Spacer(
                         modifier = Modifier
                         modifier = Modifier
                             .height(32.dp)
                             .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.R
 import it.vfsfitvnm.vimusic.ui.components.SeekBar
 import it.vfsfitvnm.vimusic.ui.components.SeekBar
 import it.vfsfitvnm.vimusic.ui.components.TopAppBar
 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.screens.*
 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
@@ -224,6 +225,11 @@ fun OtherSettingsScreen() {
                         text = "${Formatter.formatShortFileSize(context, diskCacheSize)} (${diskCacheSize * 100 / preferences.exoPlayerDiskCacheMaxSizeBytes.coerceAtLeast(1)}%)",
                         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.")
+                }
             }
             }
         }
         }
     }
     }