diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/HorizontalSongCard.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/HorizontalSongCard.kt
index 9e09050..7ac2bf9 100644
--- a/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/HorizontalSongCard.kt
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/HorizontalSongCard.kt
@@ -19,6 +19,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.bobbyesp.metadator.presentation.components.image.AsyncImage
+import com.bobbyesp.metadator.presentation.components.text.ConditionedMarqueeText
import com.bobbyesp.metadator.presentation.theme.MetadatorTheme
import com.bobbyesp.ui.components.text.MarqueeText
import com.bobbyesp.utilities.Time
@@ -50,13 +51,13 @@ fun HorizontalSongCard(
.padding(vertical = 8.dp, horizontal = 6.dp)
.weight(1f)
) {
- MarqueeText(
+ ConditionedMarqueeText(
text = song.title,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Bold,
fontSize = 15.sp
)
- MarqueeText(
+ ConditionedMarqueeText(
text = song.artist,
style = MaterialTheme.typography.bodyMedium.copy(
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/VerticalSongCard.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/VerticalSongCard.kt
index 90d1276..3fef5f5 100644
--- a/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/VerticalSongCard.kt
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/VerticalSongCard.kt
@@ -16,6 +16,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.bobbyesp.metadator.presentation.components.image.AsyncImage
+import com.bobbyesp.metadator.presentation.components.text.ConditionedMarqueeText
import com.bobbyesp.metadator.presentation.theme.MetadatorTheme
import com.bobbyesp.ui.components.text.MarqueeText
import com.bobbyesp.utilities.model.Song
@@ -41,13 +42,13 @@ fun VerticalSongCard(
Column(
horizontalAlignment = Alignment.Start, modifier = Modifier.padding(8.dp)
) {
- MarqueeText(
+ ConditionedMarqueeText(
text = song.title,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Bold,
fontSize = 15.sp
)
- MarqueeText(
+ ConditionedMarqueeText(
text = song.artist,
style = MaterialTheme.typography.bodyMedium.copy(
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/compact/CompactCardSize.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/compact/CompactCardSize.kt
new file mode 100644
index 0000000..4afbd23
--- /dev/null
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/compact/CompactCardSize.kt
@@ -0,0 +1,27 @@
+package com.bobbyesp.metadator.presentation.components.cards.songs.compact
+
+import androidx.compose.foundation.shape.CornerBasedShape
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+
+enum class CompactCardSize(val value: Dp) {
+ SMALL(96.dp),
+ MEDIUM(120.dp),
+ LARGE(144.dp),
+ EXTRA_LARGE(168.dp);
+
+ companion object {
+
+ fun Int.toCompactCardSize(): CompactCardSize = CompactCardSize.entries.first { it.ordinal == this }
+
+ @Composable
+ fun CompactCardSize.toShape(): CornerBasedShape = when(this) {
+ SMALL -> MaterialTheme.shapes.small
+ MEDIUM -> MaterialTheme.shapes.medium
+ LARGE -> MaterialTheme.shapes.large
+ EXTRA_LARGE -> MaterialTheme.shapes.extraLarge
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/compact/CompactSongCard.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/compact/CompactSongCard.kt
new file mode 100644
index 0000000..47eb27b
--- /dev/null
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/compact/CompactSongCard.kt
@@ -0,0 +1,118 @@
+package com.bobbyesp.metadator.presentation.components.cards.songs.compact
+
+import android.net.Uri
+import android.util.Log
+import androidx.compose.animation.animateContentSize
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.shadow
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import com.bobbyesp.metadator.presentation.components.cards.songs.compact.CompactCardSize.Companion.toShape
+import com.bobbyesp.metadator.presentation.components.image.AsyncImage
+import com.bobbyesp.metadator.presentation.components.text.ConditionedMarqueeText
+
+@Composable
+fun CompactSongCard(
+ modifier: Modifier = Modifier,
+ name: String,
+ artists: String,
+ artworkUri: Uri? = null,
+ listIndex: Int? = null,
+ shadow: Dp? = 4.dp,
+ size: CompactCardSize = CompactCardSize.LARGE,
+ shape: Shape? = MaterialTheme.shapes.large,
+ onClick: () -> Unit
+) {
+ val cardSize by remember(size) {
+ mutableStateOf(size.value)
+ }
+
+ val formalizedShape = shape ?: size.toShape()
+
+ Box(
+ modifier = modifier
+ .shadow(
+ elevation = shadow ?: 0.dp,
+ shape = formalizedShape
+ )
+ .clip(formalizedShape)
+ .size(cardSize)
+ .clickable(onClick = onClick)
+
+ ) {
+ AsyncImage(
+ modifier = Modifier.fillMaxSize(),
+ imageModel = artworkUri,
+ )
+
+ listIndex?.let {
+ Text(
+ text = "$it.",
+ style = MaterialTheme.typography.bodySmall,
+ color = Color.White.copy(alpha = 0.8f),
+ fontWeight = FontWeight.Bold,
+ modifier = Modifier
+ .padding(8.dp)
+ .align(Alignment.TopEnd)
+ )
+ }
+ Column(
+ modifier = Modifier
+ .background(
+ brush = Brush.verticalGradient(
+ colors = listOf(
+ Color.Transparent,
+ MaterialTheme.colorScheme.scrim
+ ),
+ startY = 0f,
+ endY = 500f
+ ),
+ alpha = 0.6f
+ )
+ .fillMaxSize()
+ .padding(horizontal = 8.dp, vertical = 6.dp),
+ verticalArrangement = Arrangement.Bottom,
+ horizontalAlignment = Alignment.Start
+ ) {
+ ConditionedMarqueeText(
+ text = name,
+ style = MaterialTheme.typography.titleSmall,
+ color = Color.White,
+ overflow = TextOverflow.Ellipsis,
+ maxLines = 1
+ )
+
+ if(artists.isNotEmpty()) {
+ ConditionedMarqueeText(
+ text = artists,
+ style = MaterialTheme.typography.bodySmall,
+ color = Color.White.copy(alpha = 0.6f),
+ overflow = TextOverflow.Ellipsis,
+ maxLines = 1
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/spotify/SpotifyHorizontalSongCard.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/spotify/SpotifyHorizontalSongCard.kt
index 71c7c59..ef2da50 100644
--- a/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/spotify/SpotifyHorizontalSongCard.kt
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/components/cards/songs/spotify/SpotifyHorizontalSongCard.kt
@@ -22,6 +22,7 @@ import androidx.compose.ui.unit.dp
import com.adamratzman.spotify.models.Track
import com.bobbyesp.metadator.ext.formatArtists
import com.bobbyesp.metadator.presentation.components.image.AsyncImage
+import com.bobbyesp.metadator.presentation.components.text.ConditionedMarqueeText
import com.bobbyesp.ui.components.text.MarqueeText
@OptIn(ExperimentalFoundationApi::class)
@@ -80,12 +81,12 @@ fun SpotifyHorizontalSongCard(
.padding(8.dp)
.weight(1f)
) {
- MarqueeText(
+ ConditionedMarqueeText(
text = track.name,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Bold,
)
- MarqueeText(
+ ConditionedMarqueeText(
text = track.artists.formatArtists(),
style = MaterialTheme.typography.bodyMedium.copy(
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/components/text/ConditionedMarqueeText.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/components/text/ConditionedMarqueeText.kt
new file mode 100644
index 0000000..31e2014
--- /dev/null
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/components/text/ConditionedMarqueeText.kt
@@ -0,0 +1,93 @@
+package com.bobbyesp.metadator.presentation.components.text
+
+import androidx.compose.animation.core.Easing
+import androidx.compose.material3.LocalTextStyle
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextLayoutResult
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextDecoration
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.TextUnit
+import com.bobbyesp.ui.components.text.MarqueeText
+import com.bobbyesp.ui.components.text.MarqueeTextGradientOptions
+import com.bobbyesp.utilities.preferences.PreferencesKeys.MARQUEE_TEXT
+import com.bobbyesp.utilities.preferences.booleanState
+
+@Composable
+fun ConditionedMarqueeText(
+ text: String,
+ modifier: Modifier = Modifier,
+ textModifier: Modifier = Modifier,
+ color: Color = Color.Unspecified,
+ fontSize: TextUnit = TextUnit.Unspecified,
+ fontStyle: FontStyle? = null,
+ fontWeight: FontWeight? = null,
+ fontFamily: FontFamily? = null,
+ letterSpacing: TextUnit = TextUnit.Unspecified,
+ textDecoration: TextDecoration? = null,
+ textAlign: TextAlign? = null,
+ lineHeight: TextUnit = TextUnit.Unspecified,
+ maxLines: Int = 1,
+ overflow: TextOverflow = TextOverflow.Clip,
+ softWrap: Boolean = true,
+ onTextLayout: (TextLayoutResult) -> Unit = {},
+ style: TextStyle = LocalTextStyle.current.plus(TextStyle()),
+ sideGradient: MarqueeTextGradientOptions = MarqueeTextGradientOptions(),
+ customEasing: Easing? = null,
+ animationDuration: Float = 4000f,
+ delayBetweenAnimations: Long = 500L
+) {
+ val useMarqueeText = MARQUEE_TEXT.booleanState
+
+ if(useMarqueeText.value) {
+ MarqueeText(
+ text,
+ modifier,
+ textModifier,
+ color,
+ fontSize,
+ fontStyle,
+ fontWeight,
+ fontFamily,
+ letterSpacing,
+ textDecoration,
+ textAlign,
+ lineHeight,
+ maxLines,
+ overflow,
+ softWrap,
+ onTextLayout,
+ style,
+ sideGradient,
+ customEasing,
+ animationDuration,
+ delayBetweenAnimations
+ )
+ } else {
+ Text(
+ text = text,
+ modifier = textModifier,
+ color = color,
+ fontSize = fontSize,
+ fontStyle = fontStyle,
+ fontWeight = fontWeight,
+ fontFamily = fontFamily,
+ letterSpacing = letterSpacing,
+ textDecoration = textDecoration,
+ textAlign = textAlign,
+ lineHeight = lineHeight,
+ maxLines = maxLines,
+ overflow = overflow,
+ softWrap = softWrap,
+ onTextLayout = onTextLayout,
+ style = style
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/MediaStorePage.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/MediaStorePage.kt
index e2fef46..7cae32a 100644
--- a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/MediaStorePage.kt
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/MediaStorePage.kt
@@ -1,6 +1,7 @@
package com.bobbyesp.metadator.presentation.pages
import androidx.compose.animation.Crossfade
+import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
@@ -15,17 +16,24 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.bobbyesp.metadator.R
import com.bobbyesp.metadator.presentation.components.cards.songs.HorizontalSongCard
-import com.bobbyesp.metadator.presentation.components.cards.songs.VerticalSongCard
+import com.bobbyesp.metadator.presentation.components.cards.songs.compact.CompactCardSize
+import com.bobbyesp.metadator.presentation.components.cards.songs.compact.CompactCardSize.Companion.toCompactCardSize
+import com.bobbyesp.metadator.presentation.components.cards.songs.compact.CompactSongCard
import com.bobbyesp.metadator.presentation.components.others.status.EmptyMediaStore
import com.bobbyesp.metadator.presentation.pages.home.LayoutType
import com.bobbyesp.ui.common.pages.ErrorPage
import com.bobbyesp.ui.common.pages.LoadingPage
import com.bobbyesp.utilities.model.Song
+import com.bobbyesp.utilities.preferences.PreferencesKeys.SONG_CARD_SIZE
+import com.bobbyesp.utilities.preferences.intState
import com.bobbyesp.utilities.states.ResourceState
import my.nanihadesuka.compose.LazyColumnScrollbar
import my.nanihadesuka.compose.LazyVerticalGridScrollbar
@@ -39,10 +47,12 @@ fun MediaStorePage(
lazyGridState: LazyGridState,
lazyListState: LazyListState,
desiredLayout: LayoutType,
+ compactCardSize: CompactCardSize,
onReloadMediaStore: () -> Unit,
onItemClicked: (Song) -> Unit
) {
val songsList = songs.value
+
Box(
modifier = modifier.fillMaxSize()
) {
@@ -58,7 +68,7 @@ fun MediaStorePage(
) { onReloadMediaStore() }
is ResourceState.Success -> {
- val dataSongsList = songsList.data!!
+ val dataSongsList = songsList.data ?: throw IllegalStateException("Data is null")
if (dataSongsList.isEmpty()) {
EmptyMediaStore(
modifier = Modifier.fillMaxSize()
@@ -88,11 +98,16 @@ fun MediaStorePage(
key = { index -> dataSongsList[index].id },
contentType = { _ -> "songItem" }) { index ->
val song = dataSongsList[index]
- VerticalSongCard(
- song = song,
- modifier = Modifier.animateItem(
- fadeInSpec = null, fadeOutSpec = null
- ),
+
+ CompactSongCard(
+ modifier = Modifier
+ .animateItem(
+ fadeInSpec = null, fadeOutSpec = null
+ ),
+ size = compactCardSize,
+ name = song.title,
+ artists = song.artist,
+ artworkUri = song.artworkPath,
onClick = {
onItemClicked(song)
})
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/home/HomePage.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/home/HomePage.kt
index 9fa8fa6..e8bcc74 100644
--- a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/home/HomePage.kt
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/home/HomePage.kt
@@ -17,12 +17,11 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.automirrored.rounded.List
-import androidx.compose.material.icons.rounded.GridView
+import androidx.compose.material.icons.rounded.CropSquare
import androidx.compose.material.icons.rounded.KeyboardDoubleArrowUp
import androidx.compose.material.icons.rounded.Menu
import androidx.compose.material.icons.rounded.MoreVert
-import androidx.compose.material3.CenterAlignedTopAppBar
+import androidx.compose.material.icons.rounded.Settings
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
@@ -33,19 +32,18 @@ import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
@@ -57,15 +55,16 @@ import com.bobbyesp.metadator.ext.toParcelableSong
import com.bobbyesp.metadator.presentation.common.LocalDrawerState
import com.bobbyesp.metadator.presentation.common.LocalNavController
import com.bobbyesp.metadator.presentation.common.Route
+import com.bobbyesp.metadator.presentation.components.cards.songs.compact.CompactCardSize
import com.bobbyesp.metadator.presentation.pages.MediaStorePage
import com.bobbyesp.metadator.presentation.pages.MediaStorePageViewModel
-import com.bobbyesp.metadator.presentation.pages.home.LayoutType.entries
import com.bobbyesp.ui.components.dropdown.AnimatedDropdownMenu
import com.bobbyesp.ui.components.dropdown.DropdownItemContainer
import com.bobbyesp.ui.components.text.AutoResizableText
import com.bobbyesp.utilities.model.Song
import com.bobbyesp.utilities.preferences.Preferences
-import com.bobbyesp.utilities.preferences.PreferencesKeys.DESIRED_OVERLAY
+import com.bobbyesp.utilities.preferences.PreferencesKeys.DESIRED_LAYOUT
+import com.bobbyesp.utilities.preferences.PreferencesKeys.SONG_CARD_SIZE
import com.bobbyesp.utilities.states.ResourceState
import com.bobbyesp.utilities.ui.permission.PermissionNotGrantedDialog
import com.bobbyesp.utilities.ui.permission.PermissionRequestHandler
@@ -114,70 +113,99 @@ fun HomePage(
var desiredLayout by remember {
mutableStateOf(
Preferences.Enumerations.getValue(
- DESIRED_OVERLAY, LayoutType.Grid
+ DESIRED_LAYOUT, LayoutType.Grid
)
)
}
- val gridIsFirstItemVisible by remember { derivedStateOf { mediaStoreLazyGridState.firstVisibleItemIndex == 0 } }
- val listIsFirstItemVisible by remember { derivedStateOf { mediaStoreLazyColumnState.firstVisibleItemIndex == 0 } }
+ var desiredCardSize by remember {
+ mutableStateOf(
+ Preferences.Enumerations.getValue(
+ SONG_CARD_SIZE, CompactCardSize.LARGE
+ )
+ )
+ }
+
+ val gridIsFirstItemVisible by remember {
+ derivedStateOf {
+ mediaStoreLazyGridState.firstVisibleItemIndex == 0
+ }
+ }
+ val listIsFirstItemVisible by remember {
+ derivedStateOf {
+ mediaStoreLazyColumnState.firstVisibleItemIndex == 0
+ }
+ }
Scaffold(modifier = modifier.fillMaxSize(), topBar = {
- CenterAlignedTopAppBar(
- navigationIcon = {
- IconButton(onClick = {
- scope.launch {
- drawerState.open()
- }
- }) {
- Icon(
- imageVector = Icons.Rounded.Menu,
- contentDescription = stringResource(id = R.string.open_navigation)
- )
+ TopAppBar(navigationIcon = {
+ IconButton(onClick = {
+ scope.launch {
+ drawerState.open()
}
- }, title = {
- Column(
- horizontalAlignment = Alignment.CenterHorizontally,
- ) {
- Text(
- text = stringResource(id = R.string.app_name).uppercase(),
- fontWeight = FontWeight.SemiBold,
- fontFamily = FontFamily.Monospace,
- style = MaterialTheme.typography.titleLarge.copy(
- letterSpacing = 4.sp,
- ),
- )
- AutoResizableText(
- text = stringResource(id = R.string.app_desc).uppercase(),
- fontWeight = FontWeight.Normal,
- fontFamily = FontFamily.Monospace,
- style = MaterialTheme.typography.bodySmall.copy(
- letterSpacing = 2.sp,
- ),
- color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f)
+ }) {
+ Icon(
+ imageVector = Icons.Rounded.Menu,
+ contentDescription = stringResource(id = R.string.open_navigation)
+ )
+ }
+ }, title = {
+ Column(
+ horizontalAlignment = Alignment.Start,
+ ) {
+ Text(
+ text = stringResource(id = R.string.app_name).uppercase(),
+ fontWeight = FontWeight.SemiBold,
+ fontFamily = FontFamily.Monospace,
+ style = MaterialTheme.typography.titleLarge.copy(
+ letterSpacing = 4.sp,
+ ),
+ )
+ AutoResizableText(
+ text = stringResource(id = R.string.app_desc).uppercase(),
+ fontWeight = FontWeight.Normal,
+ fontFamily = FontFamily.Monospace,
+ style = MaterialTheme.typography.bodySmall.copy(
+ letterSpacing = 2.sp,
+ ),
+ color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f)
+ )
+ }
+ }, actions = {
+ IconButton(
+ onClick = { navController.navigate(Route.SettingsNavigator.Settings) }) {
+ Icon(
+ imageVector = Icons.Rounded.Settings, contentDescription = stringResource(
+ id = R.string.settings
)
- }
- }, actions = {
- IconButton(
- onClick = {
- moreOptionsVisible = !moreOptionsVisible
- }) {
- Icon(
- imageVector = Icons.Rounded.MoreVert, contentDescription = stringResource(
- id = R.string.open_more_options
- )
+ )
+ }
+ IconButton(
+ onClick = {
+ moreOptionsVisible = !moreOptionsVisible
+ }) {
+ Icon(
+ imageVector = Icons.Rounded.MoreVert, contentDescription = stringResource(
+ id = R.string.open_more_options
)
- }
- AnimatedDropdownMenu(
- expanded = moreOptionsVisible, onDismissRequest = {
- moreOptionsVisible = false
- }) {
- DropdownMenuContent(onLayoutChanged = {
+ )
+ }
+ AnimatedDropdownMenu(
+ expanded = moreOptionsVisible, onDismissRequest = {
+ moreOptionsVisible = false
+ }) {
+ DropdownMenuContent(
+ desiredLayout = desiredLayout,
+ desiredCardSize = desiredCardSize,
+ onLayoutChanged = {
desiredLayout = it
+ },
+ onCardSizeChanged = {
+ desiredCardSize = it
})
- }
+ }
- })
+ })
}, floatingActionButton = {
when (desiredLayout) {
LayoutType.Grid -> {
@@ -244,6 +272,7 @@ fun HomePage(
lazyGridState = mediaStoreLazyGridState,
lazyListState = mediaStoreLazyColumnState,
desiredLayout = desiredLayout,
+ compactCardSize = desiredCardSize,
onReloadMediaStore = {
onEvent(MediaStorePageViewModel.Companion.Events.ReloadMediaStore)
},
@@ -258,17 +287,13 @@ fun HomePage(
@Composable
private fun DropdownMenuContent(
- onLayoutChanged: (LayoutType) -> Unit = {}
+ desiredLayout: LayoutType,
+ desiredCardSize: CompactCardSize,
+ onLayoutChanged: (LayoutType) -> Unit = {},
+ onCardSizeChanged: (CompactCardSize) -> Unit = {}
) {
val availableLayoutType = LayoutType.entries.toImmutableList()
- var desiredOverlay by remember {
- mutableIntStateOf(
- Preferences.Enumerations.getValue(
- DESIRED_OVERLAY, LayoutType.Grid
- ).ordinal
- )
- }
Column(
modifier = Modifier.padding(horizontal = 8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
@@ -280,37 +305,61 @@ private fun DropdownMenuContent(
color = MaterialTheme.colorScheme.primary,
style = MaterialTheme.typography.labelMedium
)
- DropdownItemContainer(content = {
- SingleChoiceSegmentedButtonRow {
- availableLayoutType.forEachIndexed { index, listType ->
- SegmentedButton(
- selected = desiredOverlay == listType.ordinal,
- onClick = {
- desiredOverlay = listType.ordinal
- Preferences.Enumerations.encodeValue(
- DESIRED_OVERLAY, listType
+ DropdownItemContainer(
+ content = {
+ SingleChoiceSegmentedButtonRow {
+ availableLayoutType.forEachIndexed { index, listType ->
+ SegmentedButton(
+ selected = desiredLayout.ordinal == listType.ordinal,
+ onClick = {
+ Preferences.Enumerations.encodeValue(
+ DESIRED_LAYOUT, listType
+ )
+ onLayoutChanged(listType)
+ },
+ shape = SegmentedButtonDefaults.itemShape(
+ index = index, count = availableLayoutType.size
+ ),
+ ) {
+ Icon(
+ imageVector = listType.icon,
+ contentDescription = stringResource(id = R.string.list_type)
)
- onLayoutChanged(listType)
- },
- shape = SegmentedButtonDefaults.itemShape(
- index = index, count = availableLayoutType.size
- ),
- ) {
- Icon(
- imageVector = listType.icon,
- contentDescription = stringResource(id = R.string.list_type)
- )
+ }
}
}
- }
- })
+ })
+ Text(
+ text = stringResource(id = R.string.card_size),
+ modifier = Modifier.fillMaxWidth(),
+ color = MaterialTheme.colorScheme.primary,
+ style = MaterialTheme.typography.labelMedium
+ )
+
+ DropdownItemContainer(
+ content = {
+ SingleChoiceSegmentedButtonRow {
+ CompactCardSize.entries.forEachIndexed { index, cardSize ->
+ SegmentedButton(
+ selected = desiredCardSize.ordinal == cardSize.ordinal,
+ onClick = {
+ Preferences.Enumerations.encodeValue(
+ SONG_CARD_SIZE, cardSize
+ )
+ onCardSizeChanged(cardSize)
+ },
+ shape = SegmentedButtonDefaults.itemShape(
+ index = index, count = CompactCardSize.entries.size
+ ),
+ ) {
+ Icon(
+ imageVector = Icons.Rounded.CropSquare,
+ contentDescription = stringResource(id = R.string.card_size)
+ )
+ }
+ }
+ }
+ })
}
}
-enum class LayoutType(val icon: ImageVector) {
- Grid(icon = Icons.Rounded.GridView), List(icon = Icons.AutoMirrored.Rounded.List);
-
- companion object {
- fun Int.toListType(): LayoutType = entries.first { it.ordinal == this }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/home/LayoutType.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/home/LayoutType.kt
new file mode 100644
index 0000000..05261ea
--- /dev/null
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/home/LayoutType.kt
@@ -0,0 +1,15 @@
+package com.bobbyesp.metadator.presentation.pages.home
+
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.rounded.List
+import androidx.compose.material.icons.rounded.GridView
+import androidx.compose.ui.graphics.vector.ImageVector
+
+enum class LayoutType(val icon: ImageVector) {
+ Grid(icon = Icons.Rounded.GridView),
+ List(icon = Icons.AutoMirrored.Rounded.List);
+
+ companion object {
+ fun Int.toListType(): LayoutType = entries.first { it.ordinal == this }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/mediaplayer/player/PlayerControls.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/mediaplayer/player/PlayerControls.kt
index b68e8b1..bbe0bc0 100644
--- a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/mediaplayer/player/PlayerControls.kt
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/mediaplayer/player/PlayerControls.kt
@@ -44,6 +44,7 @@ import com.bobbyesp.metadator.R
import com.bobbyesp.metadator.presentation.components.buttons.PlayPauseAnimatedButton
import com.bobbyesp.metadator.presentation.components.others.RepeatStateIcon
import com.bobbyesp.metadator.presentation.components.others.ShuffleStateIcon
+import com.bobbyesp.metadator.presentation.components.text.ConditionedMarqueeText
import com.bobbyesp.metadator.presentation.pages.mediaplayer.MediaplayerViewModel
import com.bobbyesp.ui.components.text.MarqueeText
import com.bobbyesp.ui.components.text.MarqueeTextGradientOptions
@@ -110,7 +111,7 @@ fun PlayerControls(
text = it?.title.toString(),
style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.Medium)
)
- MarqueeText(
+ ConditionedMarqueeText(
text = it?.artist.toString(),
style = MaterialTheme.typography.bodyLarge,
customEasing = EaseInOutSine,
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/mediaplayer/player/views/MiniplayerContent.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/mediaplayer/player/views/MiniplayerContent.kt
index 4025773..f3e4012 100644
--- a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/mediaplayer/player/views/MiniplayerContent.kt
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/mediaplayer/player/views/MiniplayerContent.kt
@@ -31,6 +31,7 @@ import androidx.compose.ui.unit.sp
import androidx.media3.common.MediaMetadata
import com.bobbyesp.metadator.R
import com.bobbyesp.metadator.presentation.components.image.AsyncImage
+import com.bobbyesp.metadator.presentation.components.text.ConditionedMarqueeText
import com.bobbyesp.metadator.presentation.pages.mediaplayer.player.AnimatedTextContentTransformation
import com.bobbyesp.ui.components.button.DynamicButton
import com.bobbyesp.ui.components.text.MarqueeText
@@ -84,14 +85,14 @@ fun MiniplayerContent(
) {
transition.AnimatedContent(transitionSpec = { AnimatedTextContentTransformation }) {
Column {
- MarqueeText(
+ ConditionedMarqueeText(
text = it.title.toString(),
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Bold,
fontSize = 16.sp
)
- MarqueeText(
+ ConditionedMarqueeText(
text = it.artist.toString(),
style = MaterialTheme.typography.bodyMedium.copy(
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/settings/modules/GeneralSettingsPage.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/settings/modules/GeneralSettingsPage.kt
index 49c57e2..04935d0 100644
--- a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/settings/modules/GeneralSettingsPage.kt
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/settings/modules/GeneralSettingsPage.kt
@@ -28,7 +28,7 @@ fun GeneralSettingsPage() {
val navController = LocalNavController.current
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(
- rememberTopAppBarState(),
+ state = rememberTopAppBarState(),
canScroll = { true }
)
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/MetadataEditorPage.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/MetadataEditorPage.kt
index f74d8ab..045a6ef 100644
--- a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/MetadataEditorPage.kt
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/MetadataEditorPage.kt
@@ -175,7 +175,7 @@ fun MetadataEditorPage(
TopAppBar(
title = {
Column(modifier = Modifier.fillMaxWidth()) {
- MarqueeText(
+ Text(
text = stringResource(id = R.string.viewing_metadata),
style = MaterialTheme.typography.bodyLarge,
fontSize = 20.sp,
diff --git a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/spotify/stages/SpMetadataBsDetails.kt b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/spotify/stages/SpMetadataBsDetails.kt
index 89476fc..2cc7395 100644
--- a/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/spotify/stages/SpMetadataBsDetails.kt
+++ b/app/src/main/java/com/bobbyesp/metadator/presentation/pages/utilities/tageditor/spotify/stages/SpMetadataBsDetails.kt
@@ -43,6 +43,7 @@ import com.bobbyesp.metadator.ext.TagLib.toLocalizedName
import com.bobbyesp.metadator.ext.format
import com.bobbyesp.metadator.ext.formatArtists
import com.bobbyesp.metadator.presentation.components.image.AsyncImage
+import com.bobbyesp.metadator.presentation.components.text.ConditionedMarqueeText
import com.bobbyesp.metadator.presentation.pages.utilities.tageditor.spotify.MetadataBsVM
import com.bobbyesp.ui.components.button.BackButton
import com.bobbyesp.ui.components.others.SelectableSurface
@@ -198,7 +199,7 @@ private fun TrackInfo(
.padding(8.dp)
.weight(1f)
) {
- MarqueeText(
+ ConditionedMarqueeText(
text = track.name,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Bold,
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 130c736..a221df9 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -81,4 +81,5 @@
The lyrics retrievement process has been cancelled
The lyrics sent from the provider app were null or empty
Something unexpected occurred!
+ Card size
\ No newline at end of file
diff --git a/app/utilities/src/main/java/com/bobbyesp/utilities/preferences/Preferences.kt b/app/utilities/src/main/java/com/bobbyesp/utilities/preferences/Preferences.kt
index 2c7ebf7..bf9d8d9 100644
--- a/app/utilities/src/main/java/com/bobbyesp/utilities/preferences/Preferences.kt
+++ b/app/utilities/src/main/java/com/bobbyesp/utilities/preferences/Preferences.kt
@@ -5,6 +5,7 @@ import com.bobbyesp.utilities.preferences.PreferencesKeys.DYNAMIC_COLOR
import com.bobbyesp.utilities.preferences.PreferencesKeys.HIGH_CONTRAST
import com.bobbyesp.utilities.preferences.PreferencesKeys.MARQUEE_TEXT
import com.bobbyesp.utilities.preferences.PreferencesKeys.MMKV_PREFERENCES_NAME
+import com.bobbyesp.utilities.preferences.PreferencesKeys.SONG_CARD_SIZE
import com.bobbyesp.utilities.preferences.PreferencesKeys.THEME_COLOR
import com.bobbyesp.utilities.preferences.settings.AppMainSettings
import com.bobbyesp.utilities.theme.DarkThemePreference
@@ -23,7 +24,8 @@ private val BooleanPreferenceDefaults: Map =
private val IntPreferenceDefaults: Map =
mapOf(
- DARK_THEME_VALUE to DarkThemePreference.FOLLOW_SYSTEM
+ DARK_THEME_VALUE to DarkThemePreference.FOLLOW_SYSTEM,
+ SONG_CARD_SIZE to 2 //CompactCardSize.LARGE (com.bobbyesp.metadator.presentation.components.cards.songs.compact.CompactCardSize)
)
object Preferences {
diff --git a/app/utilities/src/main/java/com/bobbyesp/utilities/preferences/PreferencesKeys.kt b/app/utilities/src/main/java/com/bobbyesp/utilities/preferences/PreferencesKeys.kt
index be1bd64..e9d6cbb 100644
--- a/app/utilities/src/main/java/com/bobbyesp/utilities/preferences/PreferencesKeys.kt
+++ b/app/utilities/src/main/java/com/bobbyesp/utilities/preferences/PreferencesKeys.kt
@@ -2,8 +2,8 @@ package com.bobbyesp.utilities.preferences
object PreferencesKeys {
//------------GENERAL--------------
- const val DESIRED_OVERLAY = "desired_overlay"
-
+ const val DESIRED_LAYOUT = "desired_overlay"
+ const val SONG_CARD_SIZE = "song_card_size"
const val MARQUEE_TEXT = "marquee_text"
//------------THEME----------------