Loading app/src/androidTest/java/foundation/e/apps/ui/compose/components/SearchResultsContentTest.kt +7 −5 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import foundation.e.apps.ui.compose.state.InstallButtonAction import foundation.e.apps.ui.compose.state.InstallButtonState import foundation.e.apps.ui.compose.theme.AppTheme import foundation.e.apps.ui.search.v2.SearchTabType import foundation.e.apps.ui.utils.AppUserRatingFormatter @RunWith(AndroidJUnit4::class) class SearchResultsContentTest { Loading Loading @@ -136,8 +137,9 @@ class SearchResultsContentTest { fun applicationMapping_setsAuthorRatingAndPrimaryAction() { val notAvailable = composeRule.activity.getString(R.string.not_available) val openLabel = composeRule.activity.getString(R.string.open) val expectedRating = "4" val hiddenRating = "4.9" val locale = composeRule.activity.resources.configuration.locales[0] val expectedRating = AppUserRatingFormatter.format(4.4, locale) val hiddenRating = AppUserRatingFormatter.format(4.9, locale) renderSearchResults( tabs = listOf(SearchTabType.OPEN_SOURCE), Loading @@ -149,7 +151,7 @@ class SearchResultsContentTest { author = "", package_name = "com.example.rated", source = Source.PLAY_STORE, ratings = Ratings(usageQualityScore = 4.0), ratings = Ratings(usageQualityScore = 4.4), status = Status.INSTALLED, ), Application( Loading Loading @@ -180,10 +182,10 @@ class SearchResultsContentTest { ) composeRule.onNodeWithText("com.example.rated").assertIsDisplayed() composeRule.onNodeWithText(expectedRating).assertIsDisplayed() composeRule.onNodeWithText(expectedRating ?: "").assertIsDisplayed() composeRule.onNodeWithText(openLabel).assertIsDisplayed() composeRule.onNodeWithText(notAvailable).assertIsDisplayed() composeRule.onAllNodesWithText(hiddenRating).assertCountEquals(0) composeRule.onAllNodesWithText(hiddenRating ?: "").assertCountEquals(0) } @Test Loading app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt +4 −5 Original line number Diff line number Diff line Loading @@ -358,13 +358,14 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { private fun updateAppRating(it: Application) { binding.ratingsInclude.apply { val formattedRating = AppUserRatingFormatter.format(it.ratings.usageQualityScore) val locale = resources.configuration.locales[0] val formattedRating = AppUserRatingFormatter.format(it.ratings.usageQualityScore, locale) if (formattedRating != null) { appRating.text = getString(R.string.rating_out_of, formattedRating) appRating.setCompoundDrawablesWithIntrinsicBounds( ContextCompat.getDrawable(requireContext(), R.drawable.ic_star_blank), null, getRatingDrawable(formattedRating), getRatingDrawable(it.ratings.usageQualityScore), null ) appRating.compoundDrawablePadding = DRAWABLE_PADDING Loading Loading @@ -1076,9 +1077,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { return applyDotAccent(dotColor) } private fun getRatingDrawable(reviewRating: String): Drawable? { val rating = reviewRating.toDouble() private fun getRatingDrawable(rating: Double): Drawable? { var dotColor = ContextCompat.getColor(requireContext(), R.color.colorGreen) if (rating <= LOW_REVIEW_THRESHOLD) { dotColor = ContextCompat.getColor(requireContext(), R.color.colorRed) Loading app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt +2 −1 Original line number Diff line number Diff line Loading @@ -212,7 +212,8 @@ class ApplicationListRVAdapter( appRating.isVisible = false return } val formattedRating = AppUserRatingFormatter.format(searchApp.ratings.usageQualityScore) val locale = root.context.resources.configuration.locales[0] val formattedRating = AppUserRatingFormatter.format(searchApp.ratings.usageQualityScore, locale) appRating.text = formattedRating ?: root.context.getString(R.string.not_available) } Loading app/src/main/java/foundation/e/apps/ui/compose/components/SearchResultsContent.kt +3 −1 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp Loading Loading @@ -553,9 +554,10 @@ private fun Application.toSearchResultUiState(buttonState: InstallButtonState): ) } val locale = LocalConfiguration.current.locales[0] val ratingText = when { source == Source.OPEN_SOURCE || source == Source.PWA || isSystemApp -> "" else -> AppUserRatingFormatter.format(ratings.usageQualityScore) else -> AppUserRatingFormatter.format(ratings.usageQualityScore, locale) ?: stringResource(R.string.not_available) } Loading app/src/main/java/foundation/e/apps/ui/utils/AppUserRatingFormatter.kt +9 −6 Original line number Diff line number Diff line Loading @@ -17,19 +17,22 @@ package foundation.e.apps.ui.utils import java.text.NumberFormat import java.util.Locale object AppUserRatingFormatter { private const val MIN_VALID_RATING = 0.1 fun format(rating: Double?): String? { fun format(rating: Double?, locale: Locale): String? { if (rating == null || rating < MIN_VALID_RATING) { return null } return if (rating % 1 == 0.0) { rating.toInt().toString() } else { rating.toString() } return NumberFormat.getNumberInstance(locale).apply { minimumFractionDigits = 0 maximumFractionDigits = 1 isGroupingUsed = false }.format(rating) } } Loading
app/src/androidTest/java/foundation/e/apps/ui/compose/components/SearchResultsContentTest.kt +7 −5 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import foundation.e.apps.ui.compose.state.InstallButtonAction import foundation.e.apps.ui.compose.state.InstallButtonState import foundation.e.apps.ui.compose.theme.AppTheme import foundation.e.apps.ui.search.v2.SearchTabType import foundation.e.apps.ui.utils.AppUserRatingFormatter @RunWith(AndroidJUnit4::class) class SearchResultsContentTest { Loading Loading @@ -136,8 +137,9 @@ class SearchResultsContentTest { fun applicationMapping_setsAuthorRatingAndPrimaryAction() { val notAvailable = composeRule.activity.getString(R.string.not_available) val openLabel = composeRule.activity.getString(R.string.open) val expectedRating = "4" val hiddenRating = "4.9" val locale = composeRule.activity.resources.configuration.locales[0] val expectedRating = AppUserRatingFormatter.format(4.4, locale) val hiddenRating = AppUserRatingFormatter.format(4.9, locale) renderSearchResults( tabs = listOf(SearchTabType.OPEN_SOURCE), Loading @@ -149,7 +151,7 @@ class SearchResultsContentTest { author = "", package_name = "com.example.rated", source = Source.PLAY_STORE, ratings = Ratings(usageQualityScore = 4.0), ratings = Ratings(usageQualityScore = 4.4), status = Status.INSTALLED, ), Application( Loading Loading @@ -180,10 +182,10 @@ class SearchResultsContentTest { ) composeRule.onNodeWithText("com.example.rated").assertIsDisplayed() composeRule.onNodeWithText(expectedRating).assertIsDisplayed() composeRule.onNodeWithText(expectedRating ?: "").assertIsDisplayed() composeRule.onNodeWithText(openLabel).assertIsDisplayed() composeRule.onNodeWithText(notAvailable).assertIsDisplayed() composeRule.onAllNodesWithText(hiddenRating).assertCountEquals(0) composeRule.onAllNodesWithText(hiddenRating ?: "").assertCountEquals(0) } @Test Loading
app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt +4 −5 Original line number Diff line number Diff line Loading @@ -358,13 +358,14 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { private fun updateAppRating(it: Application) { binding.ratingsInclude.apply { val formattedRating = AppUserRatingFormatter.format(it.ratings.usageQualityScore) val locale = resources.configuration.locales[0] val formattedRating = AppUserRatingFormatter.format(it.ratings.usageQualityScore, locale) if (formattedRating != null) { appRating.text = getString(R.string.rating_out_of, formattedRating) appRating.setCompoundDrawablesWithIntrinsicBounds( ContextCompat.getDrawable(requireContext(), R.drawable.ic_star_blank), null, getRatingDrawable(formattedRating), getRatingDrawable(it.ratings.usageQualityScore), null ) appRating.compoundDrawablePadding = DRAWABLE_PADDING Loading Loading @@ -1076,9 +1077,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { return applyDotAccent(dotColor) } private fun getRatingDrawable(reviewRating: String): Drawable? { val rating = reviewRating.toDouble() private fun getRatingDrawable(rating: Double): Drawable? { var dotColor = ContextCompat.getColor(requireContext(), R.color.colorGreen) if (rating <= LOW_REVIEW_THRESHOLD) { dotColor = ContextCompat.getColor(requireContext(), R.color.colorRed) Loading
app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt +2 −1 Original line number Diff line number Diff line Loading @@ -212,7 +212,8 @@ class ApplicationListRVAdapter( appRating.isVisible = false return } val formattedRating = AppUserRatingFormatter.format(searchApp.ratings.usageQualityScore) val locale = root.context.resources.configuration.locales[0] val formattedRating = AppUserRatingFormatter.format(searchApp.ratings.usageQualityScore, locale) appRating.text = formattedRating ?: root.context.getString(R.string.not_available) } Loading
app/src/main/java/foundation/e/apps/ui/compose/components/SearchResultsContent.kt +3 −1 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp Loading Loading @@ -553,9 +554,10 @@ private fun Application.toSearchResultUiState(buttonState: InstallButtonState): ) } val locale = LocalConfiguration.current.locales[0] val ratingText = when { source == Source.OPEN_SOURCE || source == Source.PWA || isSystemApp -> "" else -> AppUserRatingFormatter.format(ratings.usageQualityScore) else -> AppUserRatingFormatter.format(ratings.usageQualityScore, locale) ?: stringResource(R.string.not_available) } Loading
app/src/main/java/foundation/e/apps/ui/utils/AppUserRatingFormatter.kt +9 −6 Original line number Diff line number Diff line Loading @@ -17,19 +17,22 @@ package foundation.e.apps.ui.utils import java.text.NumberFormat import java.util.Locale object AppUserRatingFormatter { private const val MIN_VALID_RATING = 0.1 fun format(rating: Double?): String? { fun format(rating: Double?, locale: Locale): String? { if (rating == null || rating < MIN_VALID_RATING) { return null } return if (rating % 1 == 0.0) { rating.toInt().toString() } else { rating.toString() } return NumberFormat.getNumberInstance(locale).apply { minimumFractionDigits = 0 maximumFractionDigits = 1 isGroupingUsed = false }.format(rating) } }