Loading app/src/main/java/foundation/e/advancedprivacy/common/BindingAdapter.kt +17 −0 Original line number Diff line number Diff line /* * 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 <https://www.gnu.org/licenses/>. */ package foundation.e.advancedprivacy.common import androidx.recyclerview.widget.RecyclerView Loading app/src/main/java/foundation/e/advancedprivacy/common/extensions/AnyExtension.kt→app/src/main/java/foundation/e/advancedprivacy/common/extensions/IntExtensions.kt +3 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 MURENA SAS * Copyright (C) 2022 E FOUNDATION * * This program is free software: you can redistribute it and/or modify Loading @@ -20,3 +21,5 @@ package foundation.e.advancedprivacy.common.extensions import android.content.Context fun Int.dpToPxF(context: Context): Float = this.toFloat() * context.resources.displayMetrics.density fun Int.dpToPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt() app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersAndAppsListsUseCase.kt +16 −8 Original line number Diff line number Diff line Loading @@ -34,12 +34,12 @@ class TrackersAndAppsListsUseCase( private val appListsRepository: AppListsRepository ) { suspend fun getAppsAndTrackersCounts(period: Period): TrackersAndAppsLists { val (countByApp, countByTracker) = getCountByEntityMaps(period) val countByEntitiesMaps = getCountByEntityMaps(period) return TrackersAndAppsLists( trackers = buildTrackerList(countByTracker), allApps = buildAllAppList(countByApp), appsWithTrackers = buildAppList(countByApp) trackers = buildTrackerList(countByEntitiesMaps.countByTrackers), allApps = buildAllAppList(countByEntitiesMaps.countByApps), appsWithTrackers = buildAppList(countByEntitiesMaps.countByApps) ) } Loading Loading @@ -73,7 +73,7 @@ class TrackersAndAppsListsUseCase( } } private suspend fun getCountByEntityMaps(period: Period): Pair<Map<ApplicationDescription, Int>, Map<Tracker, Int>> { private suspend fun getCountByEntityMaps(period: Period): CountByEntitiesMaps { val periodStart: Instant = period.getPeriodStart() val trackersAndAppsIds = statsDatabase.getDistinctTrackerAndApp(periodStart) val trackersAndApps = mapIdsToEntities(trackersAndAppsIds) Loading Loading @@ -110,15 +110,23 @@ class TrackersAndAppsListsUseCase( }.distinct() } private fun foldToCountByEntityMaps( trackersAndApps: List<Pair<Tracker, ApplicationDescription>> ): Pair<Map<ApplicationDescription, Int>, Map<Tracker, Int>> { private fun foldToCountByEntityMaps(trackersAndApps: List<Pair<Tracker, ApplicationDescription>>): CountByEntitiesMaps { return trackersAndApps.fold( mutableMapOf<ApplicationDescription, Int>() to mutableMapOf<Tracker, Int>() ) { (countByApp, countByTracker), (tracker, app) -> countByApp[app] = countByApp.getOrDefault(app, 0) + 1 countByTracker[tracker] = countByTracker.getOrDefault(tracker, 0) + 1 countByApp to countByTracker }.let { (countByApp, countByTracker) -> CountByEntitiesMaps( countByApps = countByApp, countByTrackers = countByTracker ) } } private data class CountByEntitiesMaps( val countByApps: Map<ApplicationDescription, Int>, val countByTrackers: Map<Tracker, Int> ) } app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersScreenUseCase.kt +8 −4 Original line number Diff line number Diff line Loading @@ -18,16 +18,20 @@ package foundation.e.advancedprivacy.domain.usecases import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext class TrackersScreenUseCase(private val localStateRepository: LocalStateRepository) { class TrackersScreenUseCase( private val localStateRepository: LocalStateRepository, private val backgroundDispatcher: CoroutineDispatcher = Dispatchers.IO ) { suspend fun getLastPosition(): Int = withContext(Dispatchers.IO) { suspend fun getLastPosition(): Int = withContext(backgroundDispatcher) { localStateRepository.trackersScreenLastPosition } suspend fun savePosition(currentPosition: Int) = withContext(Dispatchers.IO) { suspend fun savePosition(currentPosition: Int) = withContext(backgroundDispatcher) { localStateRepository.trackersScreenLastPosition = currentPosition } Loading @@ -39,7 +43,7 @@ class TrackersScreenUseCase(private val localStateRepository: LocalStateReposito localStateRepository.trackersScreenTabStartPosition = -1 } suspend fun preselectTab(periodPosition: Int, tabPosition: Int) = withContext(Dispatchers.IO) { suspend fun preselectTab(periodPosition: Int, tabPosition: Int) = withContext(backgroundDispatcher) { localStateRepository.trackersScreenLastPosition = periodPosition localStateRepository.trackersScreenTabStartPosition = tabPosition } Loading app/src/main/java/foundation/e/advancedprivacy/features/dashboard/ShameListsTabPagerAdapter.kt +3 −7 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ */ package foundation.e.advancedprivacy.features.dashboard import android.content.res.Resources import android.view.LayoutInflater import android.view.View import android.view.ViewGroup Loading @@ -29,6 +28,7 @@ import foundation.e.advancedprivacy.R import foundation.e.advancedprivacy.common.BigNumberFormatter import foundation.e.advancedprivacy.common.BindingListAdapter import foundation.e.advancedprivacy.common.BindingViewHolder import foundation.e.advancedprivacy.common.extensions.dpToPx import foundation.e.advancedprivacy.databinding.DashboardShameListBinding import foundation.e.advancedprivacy.databinding.TrackersItemAppBinding import foundation.e.advancedprivacy.domain.entities.AppWithCount Loading Loading @@ -85,17 +85,13 @@ class ShameListsTabPagerAdapter( addItemDecoration( MaterialDividerItemDecoration(context, LinearLayoutManager.VERTICAL).apply { dividerColor = ContextCompat.getColor(context, R.color.divider) dividerInsetStart = 16.dpToPx() dividerInsetEnd = 16.dpToPx() dividerInsetStart = 16.dpToPx(context) dividerInsetEnd = 16.dpToPx(context) } ) } } private fun Int.dpToPx(): Int { return (this * Resources.getSystem().displayMetrics.density).toInt() } class AppsListViewHolder( private val binding: DashboardShameListBinding, private val viewModel: DashboardViewModel Loading Loading
app/src/main/java/foundation/e/advancedprivacy/common/BindingAdapter.kt +17 −0 Original line number Diff line number Diff line /* * 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 <https://www.gnu.org/licenses/>. */ package foundation.e.advancedprivacy.common import androidx.recyclerview.widget.RecyclerView Loading
app/src/main/java/foundation/e/advancedprivacy/common/extensions/AnyExtension.kt→app/src/main/java/foundation/e/advancedprivacy/common/extensions/IntExtensions.kt +3 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 MURENA SAS * Copyright (C) 2022 E FOUNDATION * * This program is free software: you can redistribute it and/or modify Loading @@ -20,3 +21,5 @@ package foundation.e.advancedprivacy.common.extensions import android.content.Context fun Int.dpToPxF(context: Context): Float = this.toFloat() * context.resources.displayMetrics.density fun Int.dpToPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt()
app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersAndAppsListsUseCase.kt +16 −8 Original line number Diff line number Diff line Loading @@ -34,12 +34,12 @@ class TrackersAndAppsListsUseCase( private val appListsRepository: AppListsRepository ) { suspend fun getAppsAndTrackersCounts(period: Period): TrackersAndAppsLists { val (countByApp, countByTracker) = getCountByEntityMaps(period) val countByEntitiesMaps = getCountByEntityMaps(period) return TrackersAndAppsLists( trackers = buildTrackerList(countByTracker), allApps = buildAllAppList(countByApp), appsWithTrackers = buildAppList(countByApp) trackers = buildTrackerList(countByEntitiesMaps.countByTrackers), allApps = buildAllAppList(countByEntitiesMaps.countByApps), appsWithTrackers = buildAppList(countByEntitiesMaps.countByApps) ) } Loading Loading @@ -73,7 +73,7 @@ class TrackersAndAppsListsUseCase( } } private suspend fun getCountByEntityMaps(period: Period): Pair<Map<ApplicationDescription, Int>, Map<Tracker, Int>> { private suspend fun getCountByEntityMaps(period: Period): CountByEntitiesMaps { val periodStart: Instant = period.getPeriodStart() val trackersAndAppsIds = statsDatabase.getDistinctTrackerAndApp(periodStart) val trackersAndApps = mapIdsToEntities(trackersAndAppsIds) Loading Loading @@ -110,15 +110,23 @@ class TrackersAndAppsListsUseCase( }.distinct() } private fun foldToCountByEntityMaps( trackersAndApps: List<Pair<Tracker, ApplicationDescription>> ): Pair<Map<ApplicationDescription, Int>, Map<Tracker, Int>> { private fun foldToCountByEntityMaps(trackersAndApps: List<Pair<Tracker, ApplicationDescription>>): CountByEntitiesMaps { return trackersAndApps.fold( mutableMapOf<ApplicationDescription, Int>() to mutableMapOf<Tracker, Int>() ) { (countByApp, countByTracker), (tracker, app) -> countByApp[app] = countByApp.getOrDefault(app, 0) + 1 countByTracker[tracker] = countByTracker.getOrDefault(tracker, 0) + 1 countByApp to countByTracker }.let { (countByApp, countByTracker) -> CountByEntitiesMaps( countByApps = countByApp, countByTrackers = countByTracker ) } } private data class CountByEntitiesMaps( val countByApps: Map<ApplicationDescription, Int>, val countByTrackers: Map<Tracker, Int> ) }
app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersScreenUseCase.kt +8 −4 Original line number Diff line number Diff line Loading @@ -18,16 +18,20 @@ package foundation.e.advancedprivacy.domain.usecases import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext class TrackersScreenUseCase(private val localStateRepository: LocalStateRepository) { class TrackersScreenUseCase( private val localStateRepository: LocalStateRepository, private val backgroundDispatcher: CoroutineDispatcher = Dispatchers.IO ) { suspend fun getLastPosition(): Int = withContext(Dispatchers.IO) { suspend fun getLastPosition(): Int = withContext(backgroundDispatcher) { localStateRepository.trackersScreenLastPosition } suspend fun savePosition(currentPosition: Int) = withContext(Dispatchers.IO) { suspend fun savePosition(currentPosition: Int) = withContext(backgroundDispatcher) { localStateRepository.trackersScreenLastPosition = currentPosition } Loading @@ -39,7 +43,7 @@ class TrackersScreenUseCase(private val localStateRepository: LocalStateReposito localStateRepository.trackersScreenTabStartPosition = -1 } suspend fun preselectTab(periodPosition: Int, tabPosition: Int) = withContext(Dispatchers.IO) { suspend fun preselectTab(periodPosition: Int, tabPosition: Int) = withContext(backgroundDispatcher) { localStateRepository.trackersScreenLastPosition = periodPosition localStateRepository.trackersScreenTabStartPosition = tabPosition } Loading
app/src/main/java/foundation/e/advancedprivacy/features/dashboard/ShameListsTabPagerAdapter.kt +3 −7 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ */ package foundation.e.advancedprivacy.features.dashboard import android.content.res.Resources import android.view.LayoutInflater import android.view.View import android.view.ViewGroup Loading @@ -29,6 +28,7 @@ import foundation.e.advancedprivacy.R import foundation.e.advancedprivacy.common.BigNumberFormatter import foundation.e.advancedprivacy.common.BindingListAdapter import foundation.e.advancedprivacy.common.BindingViewHolder import foundation.e.advancedprivacy.common.extensions.dpToPx import foundation.e.advancedprivacy.databinding.DashboardShameListBinding import foundation.e.advancedprivacy.databinding.TrackersItemAppBinding import foundation.e.advancedprivacy.domain.entities.AppWithCount Loading Loading @@ -85,17 +85,13 @@ class ShameListsTabPagerAdapter( addItemDecoration( MaterialDividerItemDecoration(context, LinearLayoutManager.VERTICAL).apply { dividerColor = ContextCompat.getColor(context, R.color.divider) dividerInsetStart = 16.dpToPx() dividerInsetEnd = 16.dpToPx() dividerInsetStart = 16.dpToPx(context) dividerInsetEnd = 16.dpToPx(context) } ) } } private fun Int.dpToPx(): Int { return (this * Resources.getSystem().displayMetrics.density).toInt() } class AppsListViewHolder( private val binding: DashboardShameListBinding, private val viewModel: DashboardViewModel Loading