From 66bced407ac0d1e15483278a7446e3b4077ae5f5 Mon Sep 17 00:00:00 2001 From: Fahim Masud Choudhury Date: Thu, 22 Aug 2024 17:16:11 +0600 Subject: [PATCH 1/3] chore: add a new utility class `CategoryStringFormatter` to handle category string formatting --- .../utils/CategoryStringFormatter.kt | 39 +++++++++ .../data/application/utils/CategoryUtils.kt | 9 +- .../ui/application/ApplicationFragment.kt | 14 ++-- .../category/CategoryStringFormatterTest.kt | 83 +++++++++++++++++++ 4 files changed, 136 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/foundation/e/apps/data/application/utils/CategoryStringFormatter.kt create mode 100644 app/src/test/java/foundation/e/apps/category/CategoryStringFormatterTest.kt diff --git a/app/src/main/java/foundation/e/apps/data/application/utils/CategoryStringFormatter.kt b/app/src/main/java/foundation/e/apps/data/application/utils/CategoryStringFormatter.kt new file mode 100644 index 000000000..f7b31818f --- /dev/null +++ b/app/src/main/java/foundation/e/apps/data/application/utils/CategoryStringFormatter.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 MURENA SAS + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see . + * + */ + +package foundation.e.apps.data.application.utils + +import java.util.Locale + +object CategoryStringFormatter { + fun format(input: String): String { + return when (input) { + "unknown" -> "Unknown" + else -> + input.replace("_", " ").split(" ").joinToString(" ") { word -> + if (word.lowercase() == "and") word + else { + word.replaceFirstChar { + if (it.isLowerCase()) it.titlecase(Locale.getDefault()) + else it.toString() + } // Example: books and reference -> Books and Reference + } + } + } // Capitalize each word except "and" + } +} diff --git a/app/src/main/java/foundation/e/apps/data/application/utils/CategoryUtils.kt b/app/src/main/java/foundation/e/apps/data/application/utils/CategoryUtils.kt index 5908cf289..d105b266d 100644 --- a/app/src/main/java/foundation/e/apps/data/application/utils/CategoryUtils.kt +++ b/app/src/main/java/foundation/e/apps/data/application/utils/CategoryUtils.kt @@ -1,6 +1,5 @@ /* - * Apps Quickly and easily install Android apps onto your device! - * Copyright (C) 2021 E FOUNDATION + * Copyright (C) 2021-2024 MURENA SAS * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,6 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * */ package foundation.e.apps.data.application.utils @@ -26,7 +26,7 @@ import foundation.e.apps.data.enums.AppTag object CategoryUtils { private const val CATEGORY_OPEN_GAMES_ID = "game_open_games" - private const val CATEGORY_OPEN_GAMES_TITLE = "Open games" + private const val CATEGORY_OPEN_GAMES_TITLE = "Open Games" private const val CATEGORY_TITLE_REPLACEABLE_CONJUNCTION = "&" private const val CATEGORY_TITLE_CONJUNCTION = "and" @@ -127,7 +127,8 @@ object CategoryUtils { return if (category.contentEquals(CATEGORY_OPEN_GAMES_ID)) { CATEGORY_OPEN_GAMES_TITLE } else { - categories.translations.getOrDefault(category, "") + val value = categories.translations.getOrDefault(category, "") + CategoryStringFormatter.format(value) } } diff --git a/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt b/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt index 210a4aa11..59cae3833 100644 --- a/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt @@ -55,6 +55,7 @@ import foundation.e.apps.MainActivity import foundation.e.apps.R import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.application.data.shareUri +import foundation.e.apps.data.application.utils.CategoryStringFormatter import foundation.e.apps.data.cleanapk.CleanApkRetrofit import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.ResultStatus @@ -461,13 +462,16 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { private fun updateCategoryTitle(app: Application) { binding.titleInclude.apply { var catText = app.category.ifBlank { args.category } - when { - catText.isBlank() -> categoryTitle.isVisible = false - catText == "game_open_games" -> catText = getString(R.string.games) // F-droid games - catText == "web_games" -> catText = getString(R.string.games) // PWA games + + catText = when (catText) { + "game_open_games" -> getString(R.string.games) // F-droid games + "web_games" -> getString(R.string.games) // PWA games + else -> catText } - catText = catText.replace("_", " ") + catText = CategoryStringFormatter.format(catText) + + categoryTitle.isVisible = catText.isNotBlank() categoryTitle.text = catText } } diff --git a/app/src/test/java/foundation/e/apps/category/CategoryStringFormatterTest.kt b/app/src/test/java/foundation/e/apps/category/CategoryStringFormatterTest.kt new file mode 100644 index 000000000..5c0a71b62 --- /dev/null +++ b/app/src/test/java/foundation/e/apps/category/CategoryStringFormatterTest.kt @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2024 MURENA SAS + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see . + * + */ + +package foundation.e.apps.category + +import foundation.e.apps.data.application.utils.CategoryStringFormatter +import org.junit.Assert.assertEquals +import org.junit.Test + +class CategoryStringFormatterTest { + + @Test + fun testFormatString_withUnderscores() { + val input = "health_and_fitness" + val expected = "Health and Fitness" + val result = CategoryStringFormatter.format(input) + assertEquals(expected, result) + } + + @Test + fun testFormatString_withMultipleWords() { + val input = "mental_health_and_fitness" + val expected = "Mental Health and Fitness" + val result = CategoryStringFormatter.format(input) + assertEquals(expected, result) + } + + @Test + fun testFormatString_withLeadingAndTrailingUnderscores() { + val input = "_health_and_fitness_" + val expected = "Health and Fitness" + val result = + CategoryStringFormatter.format(input.trim('_')) // Trimming underscores for testing + assertEquals(expected, result) + } + + @Test + fun testFormatString_withNoUnderscores() { + val input = "health" + val expected = "Health" + val result = CategoryStringFormatter.format(input) + assertEquals(expected, result) + } + + @Test + fun testFormatString_withOnlyAnd() { + val input = "and" + val expected = "and" + val result = CategoryStringFormatter.format(input) + assertEquals(expected, result) + } + + @Test + fun testFormatString_withEmptyString() { + val input = "" + val expected = "" + val result = CategoryStringFormatter.format(input) + assertEquals(expected, result) + } + + @Test + fun testFormatString_unknown() { + val input = "unknown" + val expected = "Unknown" + val result = CategoryStringFormatter.format(input) + assertEquals(expected, result) + } +} -- GitLab From b61f6505013ee7ef685adf2f0b8aa9b77fd1f25b Mon Sep 17 00:00:00 2001 From: Fahim Masud Choudhury Date: Thu, 22 Aug 2024 18:51:24 +0600 Subject: [PATCH 2/3] refactor: add more test cases --- .../utils/CategoryStringFormatter.kt | 2 +- .../category/CategoryStringFormatterTest.kt | 22 ++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/data/application/utils/CategoryStringFormatter.kt b/app/src/main/java/foundation/e/apps/data/application/utils/CategoryStringFormatter.kt index f7b31818f..d1d42e195 100644 --- a/app/src/main/java/foundation/e/apps/data/application/utils/CategoryStringFormatter.kt +++ b/app/src/main/java/foundation/e/apps/data/application/utils/CategoryStringFormatter.kt @@ -26,7 +26,7 @@ object CategoryStringFormatter { "unknown" -> "Unknown" else -> input.replace("_", " ").split(" ").joinToString(" ") { word -> - if (word.lowercase() == "and") word + if (word.lowercase() == "and") word.lowercase(Locale.getDefault()) else { word.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) diff --git a/app/src/test/java/foundation/e/apps/category/CategoryStringFormatterTest.kt b/app/src/test/java/foundation/e/apps/category/CategoryStringFormatterTest.kt index 5c0a71b62..f5ac42507 100644 --- a/app/src/test/java/foundation/e/apps/category/CategoryStringFormatterTest.kt +++ b/app/src/test/java/foundation/e/apps/category/CategoryStringFormatterTest.kt @@ -33,9 +33,17 @@ class CategoryStringFormatterTest { } @Test - fun testFormatString_withMultipleWords() { - val input = "mental_health_and_fitness" - val expected = "Mental Health and Fitness" + fun testFormatString_withSpaces() { + val input = "health and fitness" + val expected = "Health and Fitness" + val result = CategoryStringFormatter.format(input) + assertEquals(expected, result) + } + + @Test + fun testFormatString_withAllWordsCapitalized() { + val input = "Health And Fitness" + val expected = "Health and Fitness" val result = CategoryStringFormatter.format(input) assertEquals(expected, result) } @@ -65,6 +73,14 @@ class CategoryStringFormatterTest { assertEquals(expected, result) } + @Test + fun testFormatString_withOnlyCapitalizedAnd() { + val input = "And" + val expected = "and" + val result = CategoryStringFormatter.format(input) + assertEquals(expected, result) + } + @Test fun testFormatString_withEmptyString() { val input = "" -- GitLab From 4b9c73e9b7d56e2f577248bf87cdf4c5b01f480b Mon Sep 17 00:00:00 2001 From: Fahim Masud Choudhury Date: Thu, 22 Aug 2024 19:00:47 +0600 Subject: [PATCH 3/3] refactor: extract F-Droid and PWA games categories into constants --- .../ui/application/ApplicationFragment.kt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt b/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt index 59cae3833..9034b313a 100644 --- a/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/application/ApplicationFragment.kt @@ -149,6 +149,8 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { private const val PRIVACY_GUIDELINE_URL = "https://doc.e.foundation/privacy_score" private const val REQUEST_EXODUS_REPORT_URL = "https://reports.exodus-privacy.eu.org/en/analysis/submit#" + private const val CATEGORY_GAMES_F_DROID = "game_open_games" + private const val CATEGORY_GAMES_PWA = "web_games" } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -461,18 +463,17 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { private fun updateCategoryTitle(app: Application) { binding.titleInclude.apply { - var catText = app.category.ifBlank { args.category } + var categoryText = app.category.ifBlank { args.category } - catText = when (catText) { - "game_open_games" -> getString(R.string.games) // F-droid games - "web_games" -> getString(R.string.games) // PWA games - else -> catText + categoryText = when (categoryText) { + CATEGORY_GAMES_F_DROID, CATEGORY_GAMES_PWA -> getString(R.string.games) + else -> CategoryStringFormatter.format(categoryText) } - catText = CategoryStringFormatter.format(catText) - - categoryTitle.isVisible = catText.isNotBlank() - categoryTitle.text = catText + this.categoryTitle.apply { + isVisible = categoryText.isNotBlank() + text = categoryText + } } } -- GitLab