diff --git a/app/src/main/java/com/aurora/extensions/App.kt b/app/src/main/java/com/aurora/extensions/App.kt new file mode 100644 index 000000000..bfc69e2c7 --- /dev/null +++ b/app/src/main/java/com/aurora/extensions/App.kt @@ -0,0 +1,11 @@ +/* + * SPDX-FileCopyrightText: 2025 The Calyx Institute + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package com.aurora.extensions + +import com.aurora.Constants.PACKAGE_NAME_GMS +import com.aurora.gplayapi.data.models.App + +fun App.requiresGMS() = dependencies.dependentPackages.contains(PACKAGE_NAME_GMS) diff --git a/app/src/main/java/com/aurora/store/compose/composables/app/AppListComposable.kt b/app/src/main/java/com/aurora/store/compose/composables/app/AppListComposable.kt index 9967f8191..c5a5a745d 100644 --- a/app/src/main/java/com/aurora/store/compose/composables/app/AppListComposable.kt +++ b/app/src/main/java/com/aurora/store/compose/composables/app/AppListComposable.kt @@ -29,8 +29,8 @@ import coil3.compose.AsyncImage import coil3.compose.LocalAsyncImagePreviewHandler import coil3.request.ImageRequest import coil3.request.crossfade -import com.aurora.Constants.PACKAGE_NAME_GMS import com.aurora.extensions.bodyVerySmall +import com.aurora.extensions.requiresGMS import com.aurora.gplayapi.data.models.App import com.aurora.store.R import com.aurora.store.compose.preview.AppPreviewProvider @@ -110,7 +110,7 @@ private fun buildExtras(app: App): List { add(stringResource(R.string.details_no_ads)) } - if (app.dependencies.dependentPackages.contains(PACKAGE_NAME_GMS)) { + if (app.requiresGMS()) { add(stringResource(R.string.details_gsf_dependent)) } } diff --git a/app/src/main/java/com/aurora/store/compose/ui/details/AppDetailsScreen.kt b/app/src/main/java/com/aurora/store/compose/ui/details/AppDetailsScreen.kt index ef4a07ad6..aed0587bc 100644 --- a/app/src/main/java/com/aurora/store/compose/ui/details/AppDetailsScreen.kt +++ b/app/src/main/java/com/aurora/store/compose/ui/details/AppDetailsScreen.kt @@ -44,10 +44,10 @@ import androidx.compose.ui.tooling.preview.PreviewScreenSizes import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import coil3.compose.LocalAsyncImagePreviewHandler -import com.aurora.Constants.PACKAGE_NAME_GMS import com.aurora.Constants.SHARE_URL import com.aurora.extensions.appInfo import com.aurora.extensions.browse +import com.aurora.extensions.requiresGMS import com.aurora.extensions.share import com.aurora.extensions.toast import com.aurora.gplayapi.data.models.App @@ -348,7 +348,7 @@ private fun ScreenContentApp( } AppCompatibility( - needsGms = app.dependencies.dependentPackages.contains(PACKAGE_NAME_GMS), + needsGms = app.requiresGMS(), plexusScores = plexusScores ) diff --git a/app/src/main/java/com/aurora/store/compose/ui/search/SearchScreen.kt b/app/src/main/java/com/aurora/store/compose/ui/search/SearchScreen.kt index c45c05104..880e1a48f 100644 --- a/app/src/main/java/com/aurora/store/compose/ui/search/SearchScreen.kt +++ b/app/src/main/java/com/aurora/store/compose/ui/search/SearchScreen.kt @@ -5,14 +5,23 @@ package com.aurora.store.compose.ui.search +import androidx.annotation.StringRes +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.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.text.input.clearText import androidx.compose.foundation.text.input.rememberTextFieldState import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd import androidx.compose.material3.AppBarWithSearch +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExpandedDockedSearchBar +import androidx.compose.material3.FilterChip import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Scaffold @@ -27,8 +36,11 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester @@ -36,6 +48,7 @@ import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringArrayResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewScreenSizes @@ -57,6 +70,7 @@ import com.aurora.store.compose.composables.app.AppListComposable import com.aurora.store.compose.preview.AppPreviewProvider import com.aurora.store.compose.preview.coilPreviewProvider import com.aurora.store.compose.ui.details.AppDetailsScreen +import com.aurora.store.data.model.SearchFilter import com.aurora.store.viewmodel.search.SearchViewModel import kotlinx.coroutines.android.awaitFrame import kotlinx.coroutines.flow.collectLatest @@ -74,7 +88,8 @@ fun SearchScreen(onNavigateUp: () -> Unit, viewModel: SearchViewModel = hiltView results = results, onNavigateUp = onNavigateUp, onSearch = { query -> viewModel.search(query) }, - onFetchSuggestions = { query -> viewModel.fetchSuggestions(query) } + onFetchSuggestions = { query -> viewModel.fetchSuggestions(query) }, + onFilter = { filter -> viewModel.filterResults(filter) } ) } @@ -84,7 +99,8 @@ private fun ScreenContent( results: LazyPagingItems = flowOf(PagingData.empty()).collectAsLazyPagingItems(), onNavigateUp: () -> Unit = {}, onFetchSuggestions: (String) -> Unit = {}, - onSearch: (String) -> Unit = {} + onSearch: (String) -> Unit = {}, + onFilter: (filter: SearchFilter) -> Unit = {} ) { val textFieldState = rememberTextFieldState() val searchBarState = rememberSearchBarState() @@ -104,12 +120,6 @@ private fun ScreenContent( .collectLatest { query -> onFetchSuggestions(query) } } - fun closeDetailPane() { - coroutineScope.launch { - scaffoldNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail, null) - } - } - fun showDetailPane(packageName: String) { coroutineScope.launch { scaffoldNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail, packageName) @@ -192,18 +202,27 @@ private fun ScreenContent( } else -> { - LazyColumn( + Column( modifier = Modifier .padding(paddingValues) .fillMaxSize() .padding(vertical = dimensionResource(R.dimen.padding_medium)) ) { - items(count = results.itemCount, key = results.itemKey { it.id }) { index -> - results[index]?.let { app -> - AppListComposable( - app = app, - onClick = { showDetailPane(app.packageName) } - ) + if (textFieldState.text.isNotBlank() && results.itemCount > 0) { + FilterHeader(onFilter = onFilter) + } + + LazyColumn { + items( + count = results.itemCount, + key = results.itemKey { it.id } + ) { index -> + results[index]?.let { app -> + AppListComposable( + app = app, + onClick = { showDetailPane(app.packageName) } + ) + } } } } @@ -245,6 +264,129 @@ private fun ScreenContent( ) } +@Composable +private fun FilterHeader(onFilter: (filter: SearchFilter) -> Unit) { + var activeFilter by rememberSaveable { mutableStateOf(SearchFilter()) } + + val filters = listOf( + R.string.action_filter_rating, + R.string.app_info_downloads, + R.string.details_free, + R.string.action_filter_no_ads, + R.string.action_filter_no_gms + ) + + @Composable + fun NonExpandableFilterChip(@StringRes filter: Int, isSelected: Boolean) { + FilterChip( + onClick = { + activeFilter = when (filter) { + R.string.details_free -> activeFilter.copy(isFree = !activeFilter.isFree) + R.string.action_filter_no_ads -> activeFilter.copy(noAds = !activeFilter.noAds) + else -> activeFilter.copy(noGMS = !activeFilter.noGMS) + } + onFilter(activeFilter) + }, + label = { Text(text = stringResource(filter)) }, + selected = isSelected, + leadingIcon = { + if (isSelected) { + Icon( + painter = painterResource(R.drawable.ic_check), + contentDescription = stringResource(filter) + ) + } + }, + ) + } + + @Composable + fun ExpandableFilterChip(@StringRes filter: Int, isSelected: Boolean) { + var isExpanded by rememberSaveable { mutableStateOf(false) } + + Box { + FilterChip( + onClick = { isExpanded = !isExpanded }, + label = { Text(text = stringResource(filter)) }, + selected = isSelected, + leadingIcon = { + if (isSelected) { + Icon( + painter = painterResource(R.drawable.ic_check), + contentDescription = stringResource(filter) + ) + } + }, + trailingIcon = { + Icon( + painter = painterResource(R.drawable.ic_arrow_drop_down), + contentDescription = stringResource(filter) + ) + }, + ) + + DropdownMenu(expanded = isExpanded, onDismissRequest = { isExpanded = false }) { + val downloadLabels = stringArrayResource(R.array.filterDownloadsLabels) + val downloadValues = stringArrayResource(R.array.filterDownloadsValues) + val ratingLabels = stringArrayResource(R.array.filterRatingLabels) + val ratingValues = stringArrayResource(R.array.filterRatingValues) + + val options = when (filter) { + R.string.action_filter_rating -> ratingLabels.zip(ratingValues).toMap() + R.string.app_info_downloads -> downloadLabels.zip(downloadValues).toMap() + else -> emptyMap() + } + + options.forEach { (key, value) -> + DropdownMenuItem( + text = { Text(text = key) }, + onClick = { + activeFilter = when (filter) { + R.string.action_filter_rating -> { + activeFilter.copy(minRating = value.toFloat()) + } + + else -> activeFilter.copy(minInstalls = value.toLong()) + } + onFilter(activeFilter) + isExpanded = false + } + ) + } + } + } + } + + LazyRow( + modifier = Modifier.padding(horizontal = dimensionResource(R.dimen.padding_medium)), + horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.margin_normal)) + ) { + items(items = filters, key = { item -> item }) { filter -> + val isSelected = when (filter) { + R.string.action_filter_rating -> activeFilter.minRating > 0.0 + R.string.app_info_downloads -> activeFilter.minInstalls > 0 + R.string.details_free -> activeFilter.isFree + R.string.action_filter_no_ads -> activeFilter.noAds + R.string.action_filter_no_gms -> activeFilter.noGMS + else -> false + } + + when (filter) { + R.string.details_free, + R.string.action_filter_no_ads, + R.string.action_filter_no_gms -> { + NonExpandableFilterChip(filter = filter, isSelected = isSelected) + } + + R.string.action_filter_rating, + R.string.app_info_downloads -> { + ExpandableFilterChip(filter = filter, isSelected = isSelected) + } + } + } + } +} + @PreviewScreenSizes @Composable private fun SearchScreenPreview(@PreviewParameter(AppPreviewProvider::class) app: App) { diff --git a/app/src/main/java/com/aurora/store/data/model/Filter.kt b/app/src/main/java/com/aurora/store/data/model/Filter.kt deleted file mode 100644 index f5e621e1d..000000000 --- a/app/src/main/java/com/aurora/store/data/model/Filter.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Aurora Store - * Copyright (C) 2021, Rahul Kumar Patel - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * - */ - -package com.aurora.store.data.model - -import kotlinx.serialization.Serializable - -@Serializable -data class Filter( - val appsWithAds: Boolean = true, - val appsWithIAP: Boolean = true, - val paidApps: Boolean = true, - val gsfDependentApps: Boolean = true, - val rating: Float = 0.0f, - val downloads: Int = 0 -) diff --git a/app/src/main/java/com/aurora/store/data/model/SearchFilter.kt b/app/src/main/java/com/aurora/store/data/model/SearchFilter.kt new file mode 100644 index 000000000..ac1b144e7 --- /dev/null +++ b/app/src/main/java/com/aurora/store/data/model/SearchFilter.kt @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2025 The Calyx Institute + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package com.aurora.store.data.model + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize +import kotlinx.serialization.Serializable + +/** + * Filter for list with search results + */ +@Parcelize +@Serializable +data class SearchFilter( + val noAds: Boolean = false, + val isFree: Boolean = false, + val noGMS: Boolean = false, + val minRating: Float = 0F, + val minInstalls: Long = 0 +) : Parcelable diff --git a/app/src/main/java/com/aurora/store/data/providers/FilterProvider.kt b/app/src/main/java/com/aurora/store/data/providers/FilterProvider.kt deleted file mode 100644 index f459dae54..000000000 --- a/app/src/main/java/com/aurora/store/data/providers/FilterProvider.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Aurora Store - * Copyright (C) 2021, Rahul Kumar Patel - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * - */ - -package com.aurora.store.data.providers - -import android.content.Context -import com.aurora.store.data.model.Filter -import com.aurora.store.util.Preferences -import com.aurora.store.util.remove -import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.serialization.json.Json -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class FilterProvider @Inject constructor( - private val json: Json, - @ApplicationContext private val context: Context -) { - - companion object { - const val PREFERENCE_FILTER = "PREFERENCE_FILTER" - } - - init { - // Clean any last saved filter - context.remove(PREFERENCE_FILTER) - } - - fun getSavedFilter(): Filter { - val rawFilter = Preferences.getString(context, PREFERENCE_FILTER) - return json.decodeFromString(rawFilter.ifEmpty { "{}" }) - } - - fun saveFilter(filter: Filter) { - Preferences.putString(context, PREFERENCE_FILTER, json.encodeToString(filter)) - } -} diff --git a/app/src/main/java/com/aurora/store/view/ui/sheets/FilterSheet.kt b/app/src/main/java/com/aurora/store/view/ui/sheets/FilterSheet.kt deleted file mode 100644 index d76a1e2c2..000000000 --- a/app/src/main/java/com/aurora/store/view/ui/sheets/FilterSheet.kt +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Aurora Store - * Copyright (C) 2021, Rahul Kumar Patel - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * - */ - -package com.aurora.store.view.ui.sheets - -import android.content.DialogInterface -import android.os.Bundle -import android.view.View -import androidx.fragment.app.viewModels -import com.aurora.store.R -import com.aurora.store.data.model.Filter -import com.aurora.store.databinding.SheetFilterBinding -import com.aurora.store.viewmodel.sheets.FilterViewModel -import com.google.android.material.chip.Chip -import dagger.hilt.android.AndroidEntryPoint - -@AndroidEntryPoint -class FilterSheet : BaseDialogSheet() { - - private val viewModel: FilterViewModel by viewModels() - - private lateinit var filter: Filter - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - filter = viewModel.filterProvider.getSavedFilter() - - attachSingleChips() - attachMultipleChips() - } - - override fun onDismiss(dialog: DialogInterface) { - super.onDismiss(dialog) - viewModel.filterProvider.saveFilter(filter) - } - - private fun attachSingleChips() { - binding.filterGfs.apply { - isChecked = filter.gsfDependentApps - setOnCheckedChangeListener { _, checked -> - isChecked = checked - filter = filter.copy(gsfDependentApps = checked) - } - } - - binding.filterPaid.apply { - isChecked = filter.paidApps - setOnCheckedChangeListener { _, checked -> - isChecked = checked - filter = filter.copy(paidApps = checked) - } - } - - binding.filterAds.apply { - isChecked = filter.appsWithAds - setOnCheckedChangeListener { _, checked -> - isChecked = checked - filter = filter.copy(appsWithAds = checked) - } - } - } - - private fun attachMultipleChips() { - val downloadLabels = resources.getStringArray(R.array.filterDownloadsLabels) - val downloadValues = resources.getStringArray(R.array.filterDownloadsValues) - val ratingLabels = resources.getStringArray(R.array.filterRatingLabels) - val ratingValues = resources.getStringArray(R.array.filterRatingValues) - - downloadLabels.forEachIndexed { index, value -> - val chip = Chip(requireContext()) - chip.id = index - chip.text = value - chip.textColors - chip.isChecked = filter.downloads == downloadValues[index].toInt() - binding.downloadChips.addView(chip) - } - - binding.downloadChips.setOnCheckedStateChangeListener { _, checkedIds -> - filter = filter.copy(downloads = downloadValues[checkedIds[0]].toInt()) - } - - ratingLabels.forEachIndexed { index, value -> - val chip = Chip(requireContext()) - chip.id = index - chip.text = value - chip.isChecked = filter.rating == ratingValues[index].toFloat() - binding.ratingChips.addView(chip) - } - - binding.ratingChips.setOnCheckedStateChangeListener { _, checkedIds -> - filter = filter.copy(rating = ratingValues[checkedIds[0]].toFloat()) - } - } -} diff --git a/app/src/main/java/com/aurora/store/viewmodel/details/AppDetailsViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/details/AppDetailsViewModel.kt index 34d057db5..15b830d7a 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/details/AppDetailsViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/details/AppDetailsViewModel.kt @@ -11,7 +11,7 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.aurora.Constants -import com.aurora.Constants.PACKAGE_NAME_GMS +import com.aurora.extensions.requiresGMS import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.Review import com.aurora.gplayapi.data.models.details.TestingProgramStatus @@ -162,9 +162,7 @@ class AppDetailsViewModel @Inject constructor( fetchDataSafetyReport(packageName) fetchSuggestions() fetchExodusPrivacyReport(packageName) - if (app.value!!.dependencies.dependentPackages.contains(PACKAGE_NAME_GMS)) { - fetchPlexusReport(packageName) - } + if (app.value!!.requiresGMS()) fetchPlexusReport(packageName) } } diff --git a/app/src/main/java/com/aurora/store/viewmodel/search/SearchViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/search/SearchViewModel.kt index 4930f0793..6ef805398 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/search/SearchViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/search/SearchViewModel.kt @@ -1,20 +1,7 @@ /* - * Aurora Store - * Copyright (C) 2021, Rahul Kumar Patel - * - * Aurora Store is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Aurora Store is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Aurora Store. If not, see . - * + * SPDX-FileCopyrightText: 2021 Rahul Kumar Patel + * SPDX-FileCopyrightText: 2025 The Calyx Institute + * SPDX-License-Identifier: GPL-3.0-or-later */ package com.aurora.store.viewmodel.search @@ -24,21 +11,27 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.paging.PagingData import androidx.paging.cachedIn +import androidx.paging.filter +import com.aurora.extensions.requiresGMS import com.aurora.gplayapi.SearchSuggestEntry import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.StreamCluster import com.aurora.gplayapi.helpers.SearchHelper import com.aurora.gplayapi.helpers.contracts.SearchContract import com.aurora.gplayapi.helpers.web.WebSearchHelper +import com.aurora.store.data.model.SearchFilter import com.aurora.store.data.paging.GenericPagingSource.Companion.createPager import com.aurora.store.data.providers.AuthProvider import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import javax.inject.Inject @@ -57,8 +50,24 @@ class SearchViewModel @Inject constructor( private val _suggestions = MutableStateFlow>(emptyList()) val suggestions = _suggestions.asStateFlow() + private val _filter = MutableStateFlow(SearchFilter()) private val _apps = MutableStateFlow>(PagingData.empty()) - val apps = _apps.asStateFlow() + val apps = combine(_filter, _apps) { filter, pagingData -> + pagingData.filter { app -> + when { + filter.noAds && app.containsAds -> false + filter.isFree && !app.isFree -> false + filter.noGMS && app.requiresGMS() -> false + app.rating.average < filter.minRating -> false + app.installs < filter.minInstalls -> false + else -> true + } + } + }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), PagingData.empty()) + + fun filterResults(filter: SearchFilter) { + _filter.value = filter + } fun search(query: String) { var nextBundleUrl: String? = null diff --git a/app/src/main/java/com/aurora/store/viewmodel/sheets/FilterViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/sheets/FilterViewModel.kt deleted file mode 100644 index 537f55048..000000000 --- a/app/src/main/java/com/aurora/store/viewmodel/sheets/FilterViewModel.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Calyx Institute - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -package com.aurora.store.viewmodel.sheets - -import androidx.lifecycle.ViewModel -import com.aurora.store.data.providers.FilterProvider -import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject - -@HiltViewModel -class FilterViewModel @Inject constructor(val filterProvider: FilterProvider) : ViewModel() diff --git a/app/src/main/res/drawable/ic_arrow_drop_down.xml b/app/src/main/res/drawable/ic_arrow_drop_down.xml new file mode 100644 index 000000000..94fa9a6e3 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_drop_down.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/app/src/main/res/layout/sheet_filter.xml b/app/src/main/res/layout/sheet_filter.xml deleted file mode 100644 index c4f5246e1..000000000 --- a/app/src/main/res/layout/sheet_filter.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 3773fad9a..7c98db554 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -134,7 +134,6 @@ 3.0 4.0 4.5 - 4.7 @@ -144,15 +143,10 @@ 3★ + 4★ + 4.5★ + - 4.7★ + 0 - 100 - 1000 - 10000 - 50000 100000 1000000 10000000 @@ -162,10 +156,6 @@ @string/action_filter_all - 100 + - 1K + - 10K + - 50K + 100K + 1M + 10M + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7a9743724..2786771a0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -534,4 +534,6 @@ Select an app for more details + No advertisements + No play services