mirror of
https://github.com/f-droid/fdroidclient.git
synced 2026-06-02 13:00:01 -04:00
Add a dedicated screen showing all categories
This commit is contained in:
@@ -16,6 +16,8 @@ import androidx.navigation3.runtime.NavEntry
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import androidx.navigation3.runtime.entryProvider
|
||||
import org.fdroid.ui.apps.myAppsEntry
|
||||
import org.fdroid.ui.categories.Categories
|
||||
import org.fdroid.ui.categories.CategoriesViewModel
|
||||
import org.fdroid.ui.details.NoAppSelected
|
||||
import org.fdroid.ui.details.appDetailsEntry
|
||||
import org.fdroid.ui.discover.discoverEntry
|
||||
@@ -78,6 +80,14 @@ fun Main(onListeningForIntent: () -> Unit = {}) {
|
||||
onSearchCleared = viewModel::onSearchCleared,
|
||||
)
|
||||
}
|
||||
entry(NavigationKey.Categories) {
|
||||
val viewModel = hiltViewModel<CategoriesViewModel>()
|
||||
Categories(
|
||||
categories = viewModel.categories.collectAsStateWithLifecycle(null).value,
|
||||
onNav = { navKey -> navigator.navigate(navKey) },
|
||||
onBackClicked = { navigator.goBack() },
|
||||
)
|
||||
}
|
||||
entry(NavigationKey.Settings) {
|
||||
val viewModel = hiltViewModel<SettingsViewModel>()
|
||||
Settings(
|
||||
|
||||
94
app/src/main/kotlin/org/fdroid/ui/categories/Categories.kt
Normal file
94
app/src/main/kotlin/org/fdroid/ui/categories/Categories.kt
Normal file
@@ -0,0 +1,94 @@
|
||||
package org.fdroid.ui.categories
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement.spacedBy
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults.enterAlwaysScrollBehavior
|
||||
import androidx.compose.material3.rememberTopAppBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import org.fdroid.R
|
||||
import org.fdroid.ui.FDroidContent
|
||||
import org.fdroid.ui.utils.BackButton
|
||||
import org.fdroid.ui.utils.BigLoadingIndicator
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
fun Categories(
|
||||
categories: List<CategoryItem>?,
|
||||
onNav: (NavKey) -> Unit,
|
||||
onBackClicked: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val scrollBehavior = enterAlwaysScrollBehavior(rememberTopAppBarState())
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(R.string.main_menu__categories),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.MiddleEllipsis,
|
||||
)
|
||||
},
|
||||
navigationIcon = { BackButton(onClick = onBackClicked) },
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
},
|
||||
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
) { paddingValues ->
|
||||
val listState = rememberSaveable(saver = LazyListState.Saver) { LazyListState() }
|
||||
if (categories == null) {
|
||||
BigLoadingIndicator(modifier.padding(paddingValues))
|
||||
} else {
|
||||
LazyColumn(
|
||||
state = listState,
|
||||
contentPadding = paddingValues,
|
||||
verticalArrangement = spacedBy(8.dp),
|
||||
) {
|
||||
items(items = categories, key = { it.id }, contentType = { "C" }) { categoryItem ->
|
||||
CategoryRow(categoryItem, onNav)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@PreviewLightDark
|
||||
private fun PreviewLoading() {
|
||||
FDroidContent {
|
||||
Categories(null, {}, {})
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@PreviewLightDark
|
||||
private fun Preview() {
|
||||
FDroidContent {
|
||||
val categories =
|
||||
listOf(
|
||||
CategoryItem("App Store & Updater", "App Store & Updater"),
|
||||
CategoryItem("Browser", "Browser"),
|
||||
CategoryItem("Calendar & Agenda", "Calendar & Agenda"),
|
||||
CategoryItem("Cloud Storage & File Sync", "Cloud Storage & File Sync"),
|
||||
CategoryItem("Connectivity", "Connectivity"),
|
||||
CategoryItem("Development", "Development"),
|
||||
CategoryItem("doesn't exist", "Foo bar"),
|
||||
)
|
||||
Categories(categories, {}, {})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.fdroid.ui.categories
|
||||
|
||||
import android.app.Application
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.asFlow
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import java.text.Collator
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.fdroid.database.FDroidDatabase
|
||||
|
||||
@HiltViewModel
|
||||
class CategoriesViewModel @Inject constructor(app: Application, db: FDroidDatabase) :
|
||||
AndroidViewModel(app) {
|
||||
private val collator = Collator.getInstance(Locale.getDefault())
|
||||
private val localeList = LocaleListCompat.getDefault()
|
||||
|
||||
val categories =
|
||||
db.getRepositoryDao().getLiveCategories().asFlow().map { categories ->
|
||||
categories
|
||||
.map { category ->
|
||||
CategoryItem(id = category.id, name = category.getName(localeList) ?: "Unknown Category")
|
||||
}
|
||||
.sortedWith { c1, c2 -> collator.compare(c1.name, c2.name) }
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import org.fdroid.R
|
||||
import org.fdroid.ui.FDroidContent
|
||||
import org.fdroid.ui.navigation.NavigationKey
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@@ -29,7 +30,7 @@ fun CategoryList(
|
||||
onNav: (NavKey) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val onAllCategories = { /* TODO */ }
|
||||
val onAllCategories = { onNav(NavigationKey.Categories) }
|
||||
AnimatedVisibility(!categoryList.isNullOrEmpty()) {
|
||||
Column(modifier = modifier) {
|
||||
Row(
|
||||
|
||||
@@ -39,6 +39,8 @@ sealed interface NavigationKey : NavKey {
|
||||
|
||||
@Serializable data class AppList(val type: AppListType) : NavigationKey
|
||||
|
||||
@Serializable data object Categories : NavigationKey
|
||||
|
||||
@Serializable data object Repos : NavigationKey
|
||||
|
||||
@Serializable data class RepoDetails(val repoId: Long) : NavigationKey
|
||||
|
||||
Reference in New Issue
Block a user