From b93a209be0392b967426fa5f5435786ee1809412 Mon Sep 17 00:00:00 2001 From: jacquarg Date: Wed, 13 Mar 2024 20:40:31 +0100 Subject: [PATCH 1/3] 1964: add tousand separators on leaks counts. --- .../common/BigNumberFormatter.kt | 26 +++++++++++++++++++ .../features/dashboard/DashboardFragment.kt | 7 +++-- .../apptrackers/AppTrackersFragment.kt | 10 ++++--- .../trackerdetails/TrackerDetailsFragment.kt | 9 ++++--- .../e/advancedprivacy/widget/WidgetUI.kt | 22 ++++++++++++---- build.gradle | 4 +-- 6 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/foundation/e/advancedprivacy/common/BigNumberFormatter.kt 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 00000000..a2ead00e --- /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 9cdffa45..f9576f6d 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,12 +40,14 @@ import org.koin.androidx.viewmodel.ext.android.viewModel class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) { private val viewModel: DashboardViewModel by viewModel() + private lateinit var numberFormatter: BigNumberFormatter private lateinit var binding: FragmentDashboardBinding override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = FragmentDashboardBinding.bind(view) + numberFormatter = BigNumberFormatter(requireContext()) with(binding.dataBlockedTrackers) { primaryMessage.apply { @@ -164,7 +167,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 85c53505..39325a99 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 lateinit var numberFormatter: BigNumberFormatter + private lateinit var binding: ApptrackersFragmentBinding override fun getTitle(): CharSequence { @@ -59,6 +62,7 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = ApptrackersFragmentBinding.bind(view) + numberFormatter = BigNumberFormatter(requireContext()) binding.blockAllToggle.setOnClickListener { viewModel.onToggleBlockAll(binding.blockAllToggle.isChecked) @@ -145,8 +149,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 481c8093..57c667f6 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 lateinit var numberFormatter: BigNumberFormatter private lateinit var binding: TrackerdetailsFragmentBinding @@ -57,6 +59,7 @@ class TrackerDetailsFragment : NavToolbarFragment(R.layout.trackerdetails_fragme override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = TrackerdetailsFragmentBinding.bind(view) + numberFormatter = BigNumberFormatter(requireContext()) binding.blockAllToggle.setOnClickListener { viewModel.onToggleBlockAll(binding.blockAllToggle.isChecked) @@ -136,8 +139,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 f55b178d..89707fab 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 e6aecef6..436b4c0e 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, -- GitLab From f3fb49b211969b6aa069f68884adf6702da9bfaa Mon Sep 17 00:00:00 2001 From: jacquarg Date: Fri, 15 Mar 2024 19:10:33 +0100 Subject: [PATCH 2/3] 1964: fix build after move to minSdk=30 --- app/build.gradle | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 06c484cd..67a3afa6 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" -- GitLab From c50d13f8114abf76109bae3c55d4522b9a5a9e41 Mon Sep 17 00:00:00 2001 From: jacquarg Date: Tue, 19 Mar 2024 18:32:59 +0100 Subject: [PATCH 3/3] 1964: MR fixes, switch from lateinit to lazy. --- .../e/advancedprivacy/features/dashboard/DashboardFragment.kt | 3 +-- .../features/trackers/apptrackers/AppTrackersFragment.kt | 3 +-- .../features/trackers/trackerdetails/TrackerDetailsFragment.kt | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) 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 f9576f6d..4b98d6d0 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 @@ -40,14 +40,13 @@ import org.koin.androidx.viewmodel.ext.android.viewModel class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) { private val viewModel: DashboardViewModel by viewModel() - private lateinit var numberFormatter: BigNumberFormatter + private val numberFormatter: BigNumberFormatter by lazy { BigNumberFormatter(requireContext()) } private lateinit var binding: FragmentDashboardBinding override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = FragmentDashboardBinding.bind(view) - numberFormatter = BigNumberFormatter(requireContext()) with(binding.dataBlockedTrackers) { primaryMessage.apply { 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 39325a99..adb20cea 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 @@ -46,7 +46,7 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) { private val args: AppTrackersFragmentArgs by navArgs() private val viewModel: AppTrackersViewModel by viewModel { parametersOf(args.appUid) } - private lateinit var numberFormatter: BigNumberFormatter + private val numberFormatter: BigNumberFormatter by lazy { BigNumberFormatter(requireContext()) } private lateinit var binding: ApptrackersFragmentBinding @@ -62,7 +62,6 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = ApptrackersFragmentBinding.bind(view) - numberFormatter = BigNumberFormatter(requireContext()) binding.blockAllToggle.setOnClickListener { viewModel.onToggleBlockAll(binding.blockAllToggle.isChecked) 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 57c667f6..863f93fb 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 @@ -43,7 +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 lateinit var numberFormatter: BigNumberFormatter + private val numberFormatter: BigNumberFormatter by lazy { BigNumberFormatter(requireContext()) } private lateinit var binding: TrackerdetailsFragmentBinding @@ -59,7 +59,6 @@ class TrackerDetailsFragment : NavToolbarFragment(R.layout.trackerdetails_fragme override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = TrackerdetailsFragmentBinding.bind(view) - numberFormatter = BigNumberFormatter(requireContext()) binding.blockAllToggle.setOnClickListener { viewModel.onToggleBlockAll(binding.blockAllToggle.isChecked) -- GitLab