mirror of
https://github.com/f-droid/fdroidclient.git
synced 2026-04-23 16:29:28 -04:00
Merge branch 'ux-feedback--chip-flow-row' into 'master'
Consistent chip layout throughout. See merge request fdroid/fdroidclient!1628
This commit is contained in:
@@ -2,7 +2,6 @@ package org.fdroid.ui.categories
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
@@ -23,8 +22,6 @@ import androidx.compose.ui.unit.dp
|
||||
import org.fdroid.R
|
||||
import org.fdroid.ui.FDroidContent
|
||||
|
||||
private val chipHeight = 36.dp
|
||||
|
||||
@Composable
|
||||
fun CategoryChip(
|
||||
categoryItem: CategoryItem,
|
||||
@@ -53,7 +50,7 @@ fun CategoryChip(
|
||||
)
|
||||
},
|
||||
selected = selected,
|
||||
modifier = modifier.padding(horizontal = 4.dp).height(chipHeight)
|
||||
modifier = modifier.height(chipHeight)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -80,7 +77,7 @@ fun CategoryChip(
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
},
|
||||
modifier = modifier.padding(horizontal = 4.dp).height(chipHeight)
|
||||
modifier = modifier.height(chipHeight)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -88,7 +85,10 @@ fun CategoryChip(
|
||||
@Composable
|
||||
fun CategoryCardPreview() {
|
||||
FDroidContent {
|
||||
Column {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier.padding(8.dp)
|
||||
) {
|
||||
CategoryChip(
|
||||
CategoryItem("VPN & Proxy", "VPN & Proxy"),
|
||||
selected = true,
|
||||
@@ -106,34 +106,3 @@ fun CategoryCardPreview() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* More similar to how multiple category chips are shown in the main category list.
|
||||
* Used to show spacing between items, specifically with regards to how Android specifies
|
||||
* a minimum height for interactive elements. This leads to the conclusion that if we make
|
||||
* the chips too short, we get an artificially large vertical gap. Hence why we set
|
||||
* the height explicitly on category chips to make them align with this minimum height.
|
||||
*/
|
||||
@Preview
|
||||
@Composable
|
||||
fun CategoryCardFlowRowPreview() {
|
||||
val categories = listOf(
|
||||
CategoryItem("Cloud Storage & File Sync", "Cloud Storage & File Sync"),
|
||||
CategoryItem("Connectivity", "Connectivity"),
|
||||
CategoryItem("Development", "Development"),
|
||||
CategoryItem("doesn't exist", "Foo bar"),
|
||||
)
|
||||
|
||||
FDroidContent {
|
||||
FlowRow(
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier
|
||||
.padding(24.dp, 8.dp, 4.dp, 20.dp)
|
||||
) {
|
||||
categories.map { category ->
|
||||
CategoryChip(category, onClick = {})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package org.fdroid.ui.categories
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -48,11 +46,9 @@ fun CategoryList(
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp, 2.dp),
|
||||
)
|
||||
FlowRow(
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
ChipFlowRow(
|
||||
modifier = Modifier
|
||||
.padding(24.dp, 8.dp, 4.dp, 20.dp)
|
||||
.padding(start = 16.dp, bottom = 12.dp)
|
||||
) {
|
||||
categories.forEach { category ->
|
||||
CategoryChip(
|
||||
|
||||
78
app/src/main/kotlin/org/fdroid/ui/categories/ChipFlowRow.kt
Normal file
78
app/src/main/kotlin/org/fdroid/ui/categories/ChipFlowRow.kt
Normal file
@@ -0,0 +1,78 @@
|
||||
package org.fdroid.ui.categories
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.FlowRowScope
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.fdroid.ui.FDroidContent
|
||||
|
||||
val chipHeight = 36.dp
|
||||
|
||||
/**
|
||||
* When presenting a list of chips (e.g. categories, repositories, sort criteria),
|
||||
* use this to ensure appropriate spacing between elements. Make sure to set the
|
||||
* height of your chips to [chipHeight] so that all chips match.
|
||||
*/
|
||||
@Composable
|
||||
fun ChipFlowRow(
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable FlowRowScope.() -> Unit,
|
||||
) {
|
||||
FlowRow(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier.padding(8.dp),
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ChipFlowRowFewItemsPreview() {
|
||||
val categories = listOf(
|
||||
CategoryItem("News", "News"),
|
||||
CategoryItem("Note", "Note"),
|
||||
CategoryItem("doesn't exist", "Oops"),
|
||||
)
|
||||
|
||||
FDroidContent {
|
||||
ChipFlowRow {
|
||||
categories.map { category ->
|
||||
CategoryChip(category, {})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ChipFlowRowManyItemsPreview() {
|
||||
val categories = listOf(
|
||||
CategoryItem("Cloud Storage & File Sync", "Cloud Storage & File Sync"),
|
||||
CategoryItem("Connectivity", "Connectivity"),
|
||||
CategoryItem("Development", "Development"),
|
||||
CategoryItem("doesn't exist", "Foo bar"),
|
||||
CategoryItem("Online Media Player", "Online Media Player"),
|
||||
CategoryItem("Pass Wallet", "Pass Wallet"),
|
||||
CategoryItem("Password & 2FA", "Password & 2FA"),
|
||||
CategoryItem("Phone & SMS", "Phone & SMS"),
|
||||
CategoryItem("Podcast", "Podcast"),
|
||||
CategoryItem("Public Transport", "Public Transport"),
|
||||
CategoryItem("Reading", "Reading"),
|
||||
CategoryItem("Recipe Manager", "Recipe Manager"),
|
||||
CategoryItem("Religion", "Religion"),
|
||||
CategoryItem("Science & Education", "Science & Education"),
|
||||
)
|
||||
|
||||
FDroidContent {
|
||||
ChipFlowRow {
|
||||
categories.map { category ->
|
||||
CategoryChip(category, {})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package org.fdroid.ui.details
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
@@ -69,6 +68,7 @@ import org.fdroid.R
|
||||
import org.fdroid.install.InstallState
|
||||
import org.fdroid.ui.FDroidContent
|
||||
import org.fdroid.ui.categories.CategoryChip
|
||||
import org.fdroid.ui.categories.ChipFlowRow
|
||||
import org.fdroid.ui.icons.License
|
||||
import org.fdroid.ui.icons.Litecoin
|
||||
import org.fdroid.ui.lists.AppListType
|
||||
@@ -378,7 +378,7 @@ fun AppDetails(
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
initiallyExpanded = true,
|
||||
) {
|
||||
FlowRow(modifier = Modifier.padding(start = 16.dp)) {
|
||||
ChipFlowRow(modifier = Modifier.padding(start = 8.dp)) {
|
||||
item.categories.forEach { item ->
|
||||
CategoryChip(item, onClick = {
|
||||
val categoryNav = AppListType.Category(item.name, item.id)
|
||||
|
||||
@@ -2,10 +2,10 @@ package org.fdroid.ui.lists
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement.spacedBy
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
@@ -40,7 +40,9 @@ import org.fdroid.R
|
||||
import org.fdroid.database.AppListSortOrder
|
||||
import org.fdroid.ui.FDroidContent
|
||||
import org.fdroid.ui.categories.CategoryChip
|
||||
import org.fdroid.ui.categories.ChipFlowRow
|
||||
import org.fdroid.ui.categories.CategoryItem
|
||||
import org.fdroid.ui.categories.chipHeight
|
||||
import org.fdroid.ui.icons.PackageVariant
|
||||
import org.fdroid.ui.utils.AsyncShimmerImage
|
||||
import org.fdroid.ui.utils.getAppListInfo
|
||||
@@ -58,15 +60,13 @@ fun AppsFilter(
|
||||
icon = Icons.AutoMirrored.Default.Sort,
|
||||
text = stringResource(R.string.sort_title),
|
||||
)
|
||||
FlowRow(
|
||||
horizontalArrangement = spacedBy(8.dp),
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
ChipFlowRow(
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
) {
|
||||
val byNameSelected = info.model.sortBy == AppListSortOrder.NAME
|
||||
FilterChip(
|
||||
selected = byNameSelected,
|
||||
modifier = Modifier.height(chipHeight),
|
||||
leadingIcon = {
|
||||
if (byNameSelected) {
|
||||
Icon(
|
||||
@@ -87,6 +87,7 @@ fun AppsFilter(
|
||||
val byLatestSelected = info.model.sortBy == AppListSortOrder.LAST_UPDATED
|
||||
FilterChip(
|
||||
selected = byLatestSelected,
|
||||
modifier = Modifier.height(chipHeight),
|
||||
leadingIcon = {
|
||||
if (byLatestSelected) {
|
||||
Icon(
|
||||
@@ -106,6 +107,7 @@ fun AppsFilter(
|
||||
)
|
||||
FilterChip(
|
||||
selected = info.model.filterIncompatible,
|
||||
modifier = Modifier.height(chipHeight),
|
||||
leadingIcon = {
|
||||
if (info.model.filterIncompatible) {
|
||||
Icon(
|
||||
@@ -141,7 +143,7 @@ fun AppsFilter(
|
||||
icon = Icons.Default.Category,
|
||||
text = stringResource(R.string.main_menu__categories),
|
||||
)
|
||||
FlowRow(
|
||||
ChipFlowRow(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
@@ -158,14 +160,14 @@ fun AppsFilter(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info.model.repositories.isNotEmpty()) {
|
||||
HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp))
|
||||
FilterHeader(
|
||||
icon = PackageVariant,
|
||||
text = stringResource(R.string.app_details_repositories),
|
||||
)
|
||||
FlowRow(
|
||||
horizontalArrangement = spacedBy(8.dp),
|
||||
ChipFlowRow(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
@@ -174,6 +176,7 @@ fun AppsFilter(
|
||||
val selected = repo.repoId in info.model.filteredRepositoryIds
|
||||
FilterChip(
|
||||
selected = selected,
|
||||
modifier = Modifier.height(chipHeight),
|
||||
leadingIcon = {
|
||||
if (selected) {
|
||||
Icon(
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.fdroid.ui.search
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
@@ -24,6 +23,7 @@ import androidx.compose.ui.unit.dp
|
||||
import org.fdroid.R
|
||||
import org.fdroid.ui.categories.CategoryChip
|
||||
import org.fdroid.ui.categories.CategoryItem
|
||||
import org.fdroid.ui.categories.ChipFlowRow
|
||||
import org.fdroid.ui.lists.AppListItem
|
||||
import org.fdroid.ui.lists.AppListRow
|
||||
import org.fdroid.ui.lists.AppListType
|
||||
@@ -135,7 +135,7 @@ private fun CategoriesFlowRow(categories: List<CategoryItem>, onNav: (Navigation
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
modifier = Modifier.padding(8.dp)
|
||||
)
|
||||
FlowRow {
|
||||
ChipFlowRow {
|
||||
categories.forEach { item ->
|
||||
CategoryChip(categoryItem = item, onClick = {
|
||||
val type = AppListType.Category(item.name, item.id)
|
||||
|
||||
@@ -167,6 +167,9 @@ val testApp = AppDetailsItem(
|
||||
categories = listOf(
|
||||
CategoryItem("Multimedia", "Multimedia"),
|
||||
CategoryItem("Internet", "Internet"),
|
||||
CategoryItem("Cloud Storage & File Sync", "Cloud Storage & File Sync"),
|
||||
CategoryItem("Connectivity", "Connectivity"),
|
||||
CategoryItem("Development", "Development"),
|
||||
),
|
||||
antiFeatures = listOf(
|
||||
AntiFeature(
|
||||
|
||||
Reference in New Issue
Block a user