diff --git a/.phrasey/schema.toml b/.phrasey/schema.toml index 506a519a..72c9ebb5 100644 --- a/.phrasey/schema.toml +++ b/.phrasey/schema.toml @@ -746,5 +746,7 @@ name = "UseMetaphonyMetadataDecoder" name = "PlayStore" [[keys]] -name = "GaplessPlayback" +name = "GridSize" +[[keys]] +name = "GaplessPlayback" diff --git a/app/src/main/java/io/github/zyrouge/symphony/services/Settings.kt b/app/src/main/java/io/github/zyrouge/symphony/services/Settings.kt index 2c6df4b9..51177c27 100644 --- a/app/src/main/java/io/github/zyrouge/symphony/services/Settings.kt +++ b/app/src/main/java/io/github/zyrouge/symphony/services/Settings.kt @@ -147,6 +147,7 @@ class Settings(private val symphony: Symphony) { AlbumRepository.SortBy.ALBUM_NAME, ) val lastUsedAlbumsSortReverse = BooleanEntry("last_used_albums_sort_reverse", false) + val lastUsedAlbumsTileSize = FloatEntry("last_used_albums_tile_size", 200f) val lastUsedGenresSortBy = EnumEntry( "last_used_genres_sort_by", enumEntries(), diff --git a/app/src/main/java/io/github/zyrouge/symphony/ui/components/AlbumGrid.kt b/app/src/main/java/io/github/zyrouge/symphony/ui/components/AlbumGrid.kt index b4294a06..6b9f2c3c 100644 --- a/app/src/main/java/io/github/zyrouge/symphony/ui/components/AlbumGrid.kt +++ b/app/src/main/java/io/github/zyrouge/symphony/ui/components/AlbumGrid.kt @@ -3,17 +3,24 @@ package io.github.zyrouge.symphony.ui.components import androidx.compose.foundation.lazy.grid.itemsIndexed import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Album +import androidx.compose.material3.Button +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon +import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import io.github.zyrouge.symphony.services.groove.Groove import io.github.zyrouge.symphony.services.groove.repositories.AlbumRepository import io.github.zyrouge.symphony.ui.helpers.ViewContext +@OptIn(ExperimentalMaterial3Api::class) @Composable fun AlbumGrid( context: ViewContext, @@ -27,6 +34,10 @@ fun AlbumGrid( context.symphony.groove.album.sort(albumIds, sortBy, sortReverse) } } + val tileSize by context.symphony.settings.lastUsedAlbumsTileSize.flow.collectAsState() + + val sheetState = rememberModalBottomSheetState() + var showBottomSheet by remember { mutableStateOf(false) } MediaSortBarScaffold( mediaSortBar = { @@ -46,6 +57,7 @@ fun AlbumGrid( label = { Text(context.symphony.t.XAlbums((albumsCount ?: albumIds.size).toString())) }, + onShowSheet = { showBottomSheet = true }, ) }, content = { @@ -61,7 +73,7 @@ fun AlbumGrid( content = { Text(context.symphony.t.DamnThisIsSoEmpty) } ) - else -> ResponsiveGrid { + else -> ResponsiveGrid(tileSize) { itemsIndexed( sortedAlbumIds, key = { i, x -> "$i-$x" }, @@ -73,6 +85,23 @@ fun AlbumGrid( } } } + + if (showBottomSheet) { + ModalBottomSheet( + onDismissRequest = { showBottomSheet = false }, + sheetState = sheetState + ) { + ResponsiveGridSizeAdjust( + context, + tileSize, + onTileSizeChange = { + context.symphony.settings.lastUsedAlbumsTileSize.setValue( + it + ) + }, + ) + } + } } ) } diff --git a/app/src/main/java/io/github/zyrouge/symphony/ui/components/MediaSortBar.kt b/app/src/main/java/io/github/zyrouge/symphony/ui/components/MediaSortBar.kt index b865aaab..8589ceaa 100644 --- a/app/src/main/java/io/github/zyrouge/symphony/ui/components/MediaSortBar.kt +++ b/app/src/main/java/io/github/zyrouge/symphony/ui/components/MediaSortBar.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.width import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowDownward import androidx.compose.material.icons.filled.ArrowUpward +import androidx.compose.material.icons.filled.GridView import androidx.compose.material.icons.filled.Shuffle import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.DropdownMenu @@ -46,6 +47,7 @@ fun > MediaSortBar( onSortChange: (T) -> Unit, label: @Composable () -> Unit, onShufflePlay: (() -> Unit)? = null, + onShowSheet: (() -> Unit)? = null, ) { var showDropdown by remember { mutableStateOf(false) } val currentTextStyle = MaterialTheme.typography.bodySmall.run { @@ -119,6 +121,17 @@ fun > MediaSortBar( } } } + onShowSheet?.let { + IconButton( + { onShowSheet() } + ) { + Icon( + Icons.Filled.GridView, + null, + modifier = iconModifier, + ) + } + } } Row(verticalAlignment = Alignment.CenterVertically) { ProvideTextStyle(currentTextStyle) { diff --git a/app/src/main/java/io/github/zyrouge/symphony/ui/components/ResponsiveGrid.kt b/app/src/main/java/io/github/zyrouge/symphony/ui/components/ResponsiveGrid.kt index 01f11c67..11ee7d78 100644 --- a/app/src/main/java/io/github/zyrouge/symphony/ui/components/ResponsiveGrid.kt +++ b/app/src/main/java/io/github/zyrouge/symphony/ui/components/ResponsiveGrid.kt @@ -1,21 +1,33 @@ package io.github.zyrouge.symphony.ui.components import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyGridScope import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.rememberLazyGridState +import androidx.compose.material3.MenuDefaults +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.dp +import io.github.zyrouge.symphony.ui.helpers.ViewContext +import kotlin.math.max import kotlin.math.roundToInt data class ResponsiveGridData(val columnsCount: Int) @Composable -fun ResponsiveGrid(content: LazyGridScope.(ResponsiveGridData) -> Unit) { +fun ResponsiveGrid(tileSize: Float = 200f, content: LazyGridScope.(ResponsiveGridData) -> Unit) { BoxWithConstraints(modifier = Modifier.fillMaxSize()) { - val cols = (this@BoxWithConstraints.maxWidth.value / 200).roundToInt() + val cols = max((this@BoxWithConstraints.maxWidth.value / tileSize).roundToInt(), 1) val gridState = rememberLazyGridState() val responsiveGridData = ResponsiveGridData(columnsCount = cols) @@ -28,3 +40,32 @@ fun ResponsiveGrid(content: LazyGridScope.(ResponsiveGridData) -> Unit) { } } } + +@Composable +fun ResponsiveGridSizeAdjust(context: ViewContext, tileSize: Float, onTileSizeChange: (Float) -> Unit) { + Row( + modifier = Modifier.padding( + MenuDefaults.DropdownMenuItemContentPadding.run { + val horizontalPadding = + calculateLeftPadding(LayoutDirection.Ltr) + PaddingValues( + start = horizontalPadding.div(2), + end = horizontalPadding.div(2), + ) + }, + ) + ) { + Column(modifier = Modifier.padding(horizontal = 16.dp)) { + Text(context.symphony.t.GridSize) + val width = LocalConfiguration.current.screenWidthDp.toFloat() + val stops = width / 100f + androidx.compose.material3.Slider( + modifier = Modifier.fillMaxWidth(), + value = stops - (width / tileSize) + 1, + onValueChange = { onTileSizeChange(width / (stops - it + 1)) }, + valueRange = 1f..stops, + steps = (stops - 2).roundToInt(), + ) + } + } +} \ No newline at end of file diff --git a/i18n/en.toml b/i18n/en.toml index 59ced1b6..3f52c32f 100644 --- a/i18n/en.toml +++ b/i18n/en.toml @@ -249,4 +249,5 @@ High = "High" Loseless = "Loseless" UseMetaphonyMetadataDecoder = "Use Metaphony metadata decoder" PlayStore = "Play Store" +GridSize = "Grid size" GaplessPlayback = "Gapless playback"