diff --git a/app/build.gradle b/app/build.gradle index 06c484cde3370cf1cd4f79090e5f01fde263761b..67a3afa60c239f9592ea6e52c9ba9c23663732ed 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -83,15 +83,11 @@ android { productFlavors { eos { dimension 'os' - minSdkVersion 29 - targetSdkVersion 32 signingConfig signingConfigs.eDebug } standalone { dimension 'os' applicationIdSuffix '.standalone' - minSdkVersion 26 - targetSdkVersion 31 manifestPlaceholders = [ persistent: "false", mainActivityIntentFilterCategory: "android.intent.category.LAUNCHER" diff --git a/app/src/main/java/foundation/e/advancedprivacy/common/BigNumberFormatter.kt b/app/src/main/java/foundation/e/advancedprivacy/common/BigNumberFormatter.kt new file mode 100644 index 0000000000000000000000000000000000000000..a2ead00e076a8e2f6c12c86028bea3d6cd7dbb31 --- /dev/null +++ b/app/src/main/java/foundation/e/advancedprivacy/common/BigNumberFormatter.kt @@ -0,0 +1,26 @@ +/* + * 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.advancedprivacy.common + +import android.content.Context +import android.icu.number.NumberFormatter + +class BigNumberFormatter(context: Context) { + private val formatter = NumberFormatter.withLocale(context.resources.configuration.locales[0]) + + fun format(number: Int): CharSequence = formatter.format(number) +} diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt index 9cdffa45859bf95be574e0ad52ef4b05d61db00f..4b98d6d057ddb58b1b2f40ec247e119115ae59ff 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 MURENA SAS + * Copyright (C) 2023-2024 MURENA SAS * Copyright (C) 2021 E FOUNDATION * * This program is free software: you can redistribute it and/or modify @@ -29,6 +29,7 @@ import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.navigation.fragment.findNavController import foundation.e.advancedprivacy.R +import foundation.e.advancedprivacy.common.BigNumberFormatter import foundation.e.advancedprivacy.common.NavToolbarFragment import foundation.e.advancedprivacy.databinding.FragmentDashboardBinding import foundation.e.advancedprivacy.domain.entities.FeatureState @@ -39,6 +40,7 @@ import org.koin.androidx.viewmodel.ext.android.viewModel class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) { private val viewModel: DashboardViewModel by viewModel() + private val numberFormatter: BigNumberFormatter by lazy { BigNumberFormatter(requireContext()) } private lateinit var binding: FragmentDashboardBinding @@ -164,7 +166,7 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) { } private fun render(state: DashboardState) { - binding.dataBlockedTrackers.number.text = state.blockedCallsCount.toString() + binding.dataBlockedTrackers.number.text = numberFormatter.format(state.blockedCallsCount) binding.dataApps.number.text = state.appsWithCallsCount.toString() with(binding.trackersControl) { diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/apptrackers/AppTrackersFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/apptrackers/AppTrackersFragment.kt index 85c5350552066797366ce3b08289ca49b40ef7c8..adb20ceae6734f9bcf5ee7bc34645aa760590145 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/apptrackers/AppTrackersFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/apptrackers/AppTrackersFragment.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 MURENA SAS + * Copyright (C) 2023-2024 MURENA SAS * Copyright (C) 2021 E FOUNDATION * * This program is free software: you can redistribute it and/or modify @@ -33,6 +33,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.divider.MaterialDividerItemDecoration import com.google.android.material.snackbar.Snackbar import foundation.e.advancedprivacy.R +import foundation.e.advancedprivacy.common.BigNumberFormatter import foundation.e.advancedprivacy.common.NavToolbarFragment import foundation.e.advancedprivacy.databinding.ApptrackersFragmentBinding import foundation.e.advancedprivacy.features.trackers.setupDisclaimerBlock @@ -45,6 +46,8 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) { private val args: AppTrackersFragmentArgs by navArgs() private val viewModel: AppTrackersViewModel by viewModel { parametersOf(args.appUid) } + private val numberFormatter: BigNumberFormatter by lazy { BigNumberFormatter(requireContext()) } + private lateinit var binding: ApptrackersFragmentBinding override fun getTitle(): CharSequence { @@ -145,8 +148,8 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) { binding.dataBlockedLeaks.apply { primaryMessage.setText(R.string.apptrackers_blocked_leaks_primary) - number.text = state.blocked.toString() - secondaryMessage.text = getString(R.string.apptrackers_blocked_leaks_secondary, state.leaked.toString()) + number.text = numberFormatter.format(state.blocked) + secondaryMessage.text = getString(R.string.apptrackers_blocked_leaks_secondary, numberFormatter.format(state.leaked)) } binding.blockAllToggle.isChecked = state.isBlockingActivated diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/trackerdetails/TrackerDetailsFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/trackerdetails/TrackerDetailsFragment.kt index 481c809325b9e47a55d8a3f3502613b7e0d564fa..863f93fb8413118bc4299b8b213c27332dd310b7 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/trackerdetails/TrackerDetailsFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/trackerdetails/TrackerDetailsFragment.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 MURENA SAS + * Copyright (C) 2023-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 @@ -31,6 +31,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.divider.MaterialDividerItemDecoration import com.google.android.material.snackbar.Snackbar import foundation.e.advancedprivacy.R +import foundation.e.advancedprivacy.common.BigNumberFormatter import foundation.e.advancedprivacy.common.NavToolbarFragment import foundation.e.advancedprivacy.databinding.TrackerdetailsFragmentBinding import foundation.e.advancedprivacy.features.trackers.setupDisclaimerBlock @@ -42,6 +43,7 @@ class TrackerDetailsFragment : NavToolbarFragment(R.layout.trackerdetails_fragme private val args: TrackerDetailsFragmentArgs by navArgs() private val viewModel: TrackerDetailsViewModel by viewModel { parametersOf(args.trackerId) } + private val numberFormatter: BigNumberFormatter by lazy { BigNumberFormatter(requireContext()) } private lateinit var binding: TrackerdetailsFragmentBinding @@ -136,8 +138,8 @@ class TrackerDetailsFragment : NavToolbarFragment(R.layout.trackerdetails_fragme binding.dataBlockedLeaks.apply { primaryMessage.setText(R.string.trackerdetails_blocked_leaks_primary) - number.text = state.blockedCount.toString() - secondaryMessage.text = getString(R.string.trackerdetails_blocked_leaks_secondary, state.leakedCount.toString()) + number.text = numberFormatter.format(state.blockedCount) + secondaryMessage.text = getString(R.string.trackerdetails_blocked_leaks_secondary, numberFormatter.format(state.leakedCount)) } binding.blockAllToggle.isChecked = state.isBlockAllActivated diff --git a/app/src/main/java/foundation/e/advancedprivacy/widget/WidgetUI.kt b/app/src/main/java/foundation/e/advancedprivacy/widget/WidgetUI.kt index f55b178d23dac29f3c00e82fdf6a6cc9369d87d5..89707fabab187401133e7a083ff66da7b104ef08 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/widget/WidgetUI.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/widget/WidgetUI.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 MURENA SAS + * Copyright (C) 2023-2024 MURENA SAS * Copyright (C) 2022 E FOUNDATION * * This program is free software: you can redistribute it and/or modify @@ -34,6 +34,7 @@ import androidx.annotation.StringRes import foundation.e.advancedprivacy.R import foundation.e.advancedprivacy.Widget import foundation.e.advancedprivacy.Widget.Companion.isDarkText +import foundation.e.advancedprivacy.common.BigNumberFormatter import foundation.e.advancedprivacy.domain.entities.FeatureState import foundation.e.advancedprivacy.domain.entities.TrackerMode import foundation.e.advancedprivacy.main.MainActivity @@ -60,6 +61,8 @@ fun renderAll(context: Context, state: State) { } fun render(context: Context, state: State, appWidgetManager: AppWidgetManager, widgetId: Int) { + val numberFormatter = BigNumberFormatter(context) + val views = buildLayout(context, appWidgetManager, widgetId) applyDarkText(context, isDarkText, views) @@ -76,12 +79,22 @@ fun render(context: Context, state: State, appWidgetManager: AppWidgetManager, w setTextViewText( R.id.data_blocked_trackers_secondary, - buildDataSecondarySpan(context, isDarkText, state.blockedCallsCount, R.string.widget_data_blocked_trackers_secondary) + buildDataSecondarySpan( + context, + isDarkText, + numberFormatter.format(state.blockedCallsCount).toString(), + R.string.widget_data_blocked_trackers_secondary + ) ) setTextViewText( R.id.data_apps_secondary, - buildDataSecondarySpan(context, isDarkText, state.appsWithCallsCount, R.string.widget_data_apps_secondary) + buildDataSecondarySpan( + context, + isDarkText, + state.appsWithCallsCount.toString(), + R.string.widget_data_apps_secondary + ) ) val trackersEnabled = state.trackerMode != TrackerMode.VULNERABLE @@ -198,7 +211,7 @@ private fun applyDarkText(context: Context, isDarkText: Boolean, views: RemoteVi } } -private fun buildDataSecondarySpan(context: Context, isDarkText: Boolean, count: Int, @StringRes secondaryRes: Int): CharSequence { +private fun buildDataSecondarySpan(context: Context, isDarkText: Boolean, countStr: String, @StringRes secondaryRes: Int): CharSequence { val primaryColor = context.getColor( if (isDarkText) { R.color.on_surface_medium_emphasis_light @@ -209,7 +222,6 @@ private fun buildDataSecondarySpan(context: Context, isDarkText: Boolean, count: val secondaryColor = context.getColor(if (isDarkText) R.color.on_surface_disabled_light else R.color.on_primary_medium_emphasis) - val countStr = count.toString() val secondary = context.getString(secondaryRes) val spannable = SpannableString("$countStr $secondary") diff --git a/build.gradle b/build.gradle index e6aecef6ee47e45b550d130aa0c23c7f1427afbb..436b4c0e592c7df98b310743801679060663a1bc 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 MURENA SAS + * Copyright (C) 2023-2024 MURENA SAS * Copyright (C) 2022 E FOUNDATION * * This program is free software: you can redistribute it and/or modify @@ -20,7 +20,7 @@ buildscript { ext.buildConfig = [ 'compileSdk': 34, - 'minSdk' : 26, + 'minSdk' : 30, 'targetSdk' : 33, 'version' : [ 'major': 1,