From ee0e0fafc537ac22841c260b68caca59b304976b Mon Sep 17 00:00:00 2001 From: jacquarg Date: Sat, 26 Feb 2022 11:30:37 +0100 Subject: Rephrase country of origin #4607 --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8c2a0ba..397bd51 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -40,7 +40,7 @@ Hide IP address I am anonymous on the internet Note: when active, this setting will slow down your Internet connectivity speed (uses the Tor network). - Force a country of origin: + My internet activity must appear from: Random country Apply this setting to all selected apps: Enabled Quick Privacy to use functionalities -- cgit v1.2.1 From aaab068ecf81c862a6adcc06ba442bca82a9d938 Mon Sep 17 00:00:00 2001 From: jacquarg Date: Sun, 27 Feb 2022 11:58:56 +0100 Subject: Open exodus page on click trackers #4599 --- .../trackers/apptrackers/AppTrackersFeature.kt | 23 +++++++++++++++ .../trackers/apptrackers/AppTrackersFragment.kt | 23 +++++++++------ .../trackers/apptrackers/ToggleTrackersAdapter.kt | 33 ++++++++++++++++++---- 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt index 16cd4a0..e43e5aa 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt @@ -17,6 +17,7 @@ package foundation.e.privacycentralapp.features.trackers.apptrackers +import android.net.Uri import android.util.Log import foundation.e.flowmvi.Actor import foundation.e.flowmvi.Reducer @@ -68,12 +69,14 @@ class AppTrackersFeature( sealed class SingleEvent { data class ErrorEvent(val error: Any) : SingleEvent() object NewStatisticsAvailableSingleEvent : SingleEvent() + data class OpenUrlEvent(val url: Uri): SingleEvent() } sealed class Action { data class InitAction(val packageName: String) : Action() data class BlockAllToggleAction(val isBlocked: Boolean) : Action() data class ToggleTrackerAction(val tracker: Tracker, val isBlocked: Boolean) : Action() + data class ClickTracker(val tracker: Tracker): Action() object FetchStatistics : Action() } @@ -87,9 +90,12 @@ class AppTrackersFeature( object NewStatisticsAvailablesEffect : Effect() data class QuickPrivacyUpdatedEffect(val enabled: Boolean) : Effect() object QuickPrivacyDisabledWarningEffect : Effect() + data class OpenUrlEffect(val url: Uri): Effect() } companion object { + + private const val exodusBaseUrl = "https://reports.exodus-privacy.eu.org/fr/trackers/" fun create( initialState: State = State(), coroutineScope: CoroutineScope, @@ -179,6 +185,15 @@ class AppTrackersFeature( } ?: run { flowOf(Effect.ErrorEffect("No appDesc.")) } } else flowOf(Effect.NoEffect) } + is Action.ClickTracker -> { + flowOf(action.tracker.getExodusId()?.let { + try { + Effect.OpenUrlEffect(Uri.parse(exodusBaseUrl + it)) + } catch (e: Exception) { + Effect.ErrorEffect("Invalid Url") + } + } ?: Effect.NoEffect) + } is Action.FetchStatistics -> flowOf( state.appDesc?.uid?.let { Effect.AvailableTrackersListEffect( @@ -196,9 +211,17 @@ class AppTrackersFeature( SingleEvent.ErrorEvent(R.string.apptrackers_error_quickprivacy_disabled) is Effect.NewStatisticsAvailablesEffect -> SingleEvent.NewStatisticsAvailableSingleEvent + is Effect.OpenUrlEffect -> + SingleEvent.OpenUrlEvent(effect.url) else -> null } } ) } } + +fun Tracker.getExodusId(): String? { + return if (id.startsWith("exodus_")) { + id.substringAfter("exodus_") + } else null +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt index 440edf7..a823df3 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt @@ -17,6 +17,8 @@ package foundation.e.privacycentralapp.features.trackers.apptrackers +import android.content.ActivityNotFoundException +import android.content.Intent import android.os.Bundle import android.view.View import android.widget.Toast @@ -76,6 +78,12 @@ class AppTrackersFragment : is SingleEvent.NewStatisticsAvailableSingleEvent -> { viewModel.submitAction(Action.FetchStatistics) } + is SingleEvent.OpenUrlEvent -> + try { + startActivity(Intent(Intent.ACTION_VIEW, event.url)) + } catch (e: ActivityNotFoundException) { + displayToast("No application to see webpages") + } } } } @@ -104,14 +112,13 @@ class AppTrackersFragment : binding.trackers.apply { layoutManager = LinearLayoutManager(requireContext()) setHasFixedSize(true) - adapter = ToggleTrackersAdapter(R.layout.apptrackers_item_tracker_toggle) { tracker, isBlocked -> - viewModel.submitAction( - Action.ToggleTrackerAction( - tracker, - isBlocked - ) - ) - } + adapter = ToggleTrackersAdapter( + R.layout.apptrackers_item_tracker_toggle, + onToggleSwitch = { tracker, isBlocked -> + viewModel.submitAction(Action.ToggleTrackerAction(tracker, isBlocked)) + }, + onClickTitle = { viewModel.submitAction(Action.ClickTracker(it)) } + ) } } diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/ToggleTrackersAdapter.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/ToggleTrackersAdapter.kt index 580a60c..134ff4f 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/ToggleTrackersAdapter.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/ToggleTrackersAdapter.kt @@ -22,16 +22,23 @@ import android.view.View import android.view.ViewGroup import android.widget.Switch import android.widget.TextView +import androidx.core.content.ContextCompat import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import foundation.e.privacycentralapp.R import foundation.e.privacymodules.trackers.Tracker +import android.text.style.UnderlineSpan + +import android.text.SpannableString + + + class ToggleTrackersAdapter( private val itemsLayout: Int, - private val listener: (Tracker, Boolean) -> Unit -) : - RecyclerView.Adapter() { + private val onToggleSwitch: (Tracker, Boolean) -> Unit, + private val onClickTitle: (Tracker) -> Unit +) : RecyclerView.Adapter() { var isEnabled = true @@ -42,7 +49,17 @@ class ToggleTrackersAdapter( val toggleOverlay: View = view.findViewById(R.id.toggle_clicker) fun bind(item: Pair, isEnabled: Boolean) { - title.text = item.first.label + val text = item.first.label + if (item.first.website != null) { + title.setTextColor(ContextCompat.getColor(title.context, R.color.accent)) + val spannable = SpannableString(text) + spannable.setSpan(UnderlineSpan(), 0, spannable.length, 0) + title.text = spannable + } else { + title.setTextColor(ContextCompat.getColor(title.context, R.color.black)) + title.text = text + } + toggle.isChecked = item.second toggle.isEnabled = isEnabled toggleOverlay.isVisible = !isEnabled @@ -62,10 +79,14 @@ class ToggleTrackersAdapter( .inflate(itemsLayout, parent, false) val holder = ViewHolder(view) holder.toggle.setOnClickListener { - listener(dataSet[holder.adapterPosition].first, holder.toggle.isChecked) + onToggleSwitch(dataSet[holder.adapterPosition].first, holder.toggle.isChecked) } holder.toggleOverlay.setOnClickListener { - listener(dataSet[holder.adapterPosition].first, false) + onToggleSwitch(dataSet[holder.adapterPosition].first, false) + } + + holder.title.setOnClickListener { + onClickTitle(dataSet[holder.adapterPosition].first) } return holder -- cgit v1.2.1 From e6ba99e31da49df559da60e8d012e40813ee14f0 Mon Sep 17 00:00:00 2001 From: jacquarg Date: Sun, 27 Feb 2022 12:00:20 +0100 Subject: Add trackers summary count on apptrackers, #4597 --- .../trackers/apptrackers/AppTrackersFeature.kt | 27 ++++++++++++++-------- .../trackers/apptrackers/AppTrackersFragment.kt | 8 +++++++ .../trackers/apptrackers/ToggleTrackersAdapter.kt | 8 ++----- app/src/main/res/layout/apptrackers_fragment.xml | 7 ++++++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt index e43e5aa..b35fbca 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt @@ -64,19 +64,24 @@ class AppTrackersFeature( return null } } + + fun getTrackersCount() = trackers?.size ?: 0 + fun getBlockedTrackersCount(): Int = if (isBlockingActivated) + getTrackersCount() - (whitelist?.size ?: 0) + else 0 } sealed class SingleEvent { data class ErrorEvent(val error: Any) : SingleEvent() object NewStatisticsAvailableSingleEvent : SingleEvent() - data class OpenUrlEvent(val url: Uri): SingleEvent() + data class OpenUrlEvent(val url: Uri) : SingleEvent() } sealed class Action { data class InitAction(val packageName: String) : Action() data class BlockAllToggleAction(val isBlocked: Boolean) : Action() data class ToggleTrackerAction(val tracker: Tracker, val isBlocked: Boolean) : Action() - data class ClickTracker(val tracker: Tracker): Action() + data class ClickTracker(val tracker: Tracker) : Action() object FetchStatistics : Action() } @@ -90,7 +95,7 @@ class AppTrackersFeature( object NewStatisticsAvailablesEffect : Effect() data class QuickPrivacyUpdatedEffect(val enabled: Boolean) : Effect() object QuickPrivacyDisabledWarningEffect : Effect() - data class OpenUrlEffect(val url: Uri): Effect() + data class OpenUrlEffect(val url: Uri) : Effect() } companion object { @@ -186,13 +191,15 @@ class AppTrackersFeature( } else flowOf(Effect.NoEffect) } is Action.ClickTracker -> { - flowOf(action.tracker.getExodusId()?.let { - try { - Effect.OpenUrlEffect(Uri.parse(exodusBaseUrl + it)) - } catch (e: Exception) { - Effect.ErrorEffect("Invalid Url") - } - } ?: Effect.NoEffect) + flowOf( + action.tracker.getExodusId()?.let { + try { + Effect.OpenUrlEffect(Uri.parse(exodusBaseUrl + it)) + } catch (e: Exception) { + Effect.ErrorEffect("Invalid Url") + } + } ?: Effect.NoEffect + ) } is Action.FetchStatistics -> flowOf( state.appDesc?.uid?.let { diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt index a823df3..8e2dc3b 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt @@ -128,6 +128,14 @@ class AppTrackersFragment : } override fun render(state: State) { + + binding.trackersCountSummary.text = if (state.getTrackersCount() == 0) "" + else getString( + R.string.apptrackers_trackers_count_summary, + state.getBlockedTrackersCount(), + state.getTrackersCount() + ) + binding.blockAllToggle.isChecked = state.isBlockingActivated binding.trackersListTitle.isVisible = state.isBlockingActivated diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/ToggleTrackersAdapter.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/ToggleTrackersAdapter.kt index 134ff4f..82f2d2c 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/ToggleTrackersAdapter.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/ToggleTrackersAdapter.kt @@ -17,6 +17,8 @@ package foundation.e.privacycentralapp.features.trackers.apptrackers +import android.text.SpannableString +import android.text.style.UnderlineSpan import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -27,12 +29,6 @@ import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import foundation.e.privacycentralapp.R import foundation.e.privacymodules.trackers.Tracker -import android.text.style.UnderlineSpan - -import android.text.SpannableString - - - class ToggleTrackersAdapter( private val itemsLayout: Int, diff --git a/app/src/main/res/layout/apptrackers_fragment.xml b/app/src/main/res/layout/apptrackers_fragment.xml index 13f58e3..17d992e 100644 --- a/app/src/main/res/layout/apptrackers_fragment.xml +++ b/app/src/main/res/layout/apptrackers_fragment.xml @@ -41,6 +41,13 @@ android:layout_width="match_parent" android:orientation="vertical" > + No trackers were detected yet. If new trackers are detected they will be updated here. No trackers were detected yet. All future trackers will be blocked. Enable Quick Privacy to be able to activate/deactivate trackers. + %1$d blocked trackers out of %2$d detected trackers Quick protection enables these settings when turned on -- cgit v1.2.1 From e9e22d2fdbde4e9679337fa681d60b3fdbfeace7 Mon Sep 17 00:00:00 2001 From: jacquarg Date: Mon, 28 Feb 2022 09:30:55 +0100 Subject: Show trackers counts for each apps in tracekr screen, #4589 --- app/build.gradle | 4 +- .../e/privacycentralapp/DependencyContainer.kt | 4 +- .../e/privacycentralapp/common/AppsAdapter.kt | 17 ++++--- .../data/repositories/AppListsRepository.kt | 8 +++ .../domain/entities/AppWithCounts.kt | 50 +++++++++++++++++++ .../domain/usecases/TrackersStatisticsUseCase.kt | 23 +++++++++ .../features/trackers/TrackersFeature.kt | 57 +++++++++------------- .../features/trackers/TrackersFragment.kt | 6 ++- .../features/trackers/TrackersViewModel.kt | 12 ++--- app/src/main/res/layout/trackers_item_app.xml | 36 ++++++++++++-- app/src/main/res/values/strings.xml | 1 + build.gradle | 2 +- 12 files changed, 159 insertions(+), 61 deletions(-) create mode 100644 app/src/main/java/foundation/e/privacycentralapp/domain/entities/AppWithCounts.kt diff --git a/app/build.gradle b/app/build.gradle index b771285..3716977 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -110,8 +110,8 @@ dependencies { //googleImplementation project(":privacymodulesgoogle") // include the e specific version of the modules, just for the e flavor - implementation 'foundation.e:privacymodule.trackerfilter:0.3.0' - implementation 'foundation.e:privacymodule.api:0.5.0' + implementation 'foundation.e:privacymodule.trackerfilter:0.4.0' + implementation 'foundation.e:privacymodule.api:0.6.0' e29Implementation 'foundation.e:privacymodule.e-29:0.4.2' e30Implementation 'foundation.e:privacymodule.e-30:0.4.2' implementation 'foundation.e:privacymodule.tor:0.2.1' diff --git a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt index 76a9539..6b4035e 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt @@ -89,7 +89,7 @@ class DependencyContainer constructor(val app: Application) { private val appListUseCase = AppListUseCase(appListsRepository) private val trackersStatisticsUseCase by lazy { - TrackersStatisticsUseCase(trackTrackersPrivacyModule, appListsRepository, context.resources) + TrackersStatisticsUseCase(trackTrackersPrivacyModule, blockTrackersPrivacyModule, appListsRepository, context.resources) } private val trackersStateUseCase by lazy { @@ -119,7 +119,7 @@ class DependencyContainer constructor(val app: Application) { } val trackersViewModelFactory by lazy { - TrackersViewModelFactory(trackersStatisticsUseCase, appListUseCase) + TrackersViewModelFactory(trackersStatisticsUseCase) } val appTrackersViewModelFactory by lazy { diff --git a/app/src/main/java/foundation/e/privacycentralapp/common/AppsAdapter.kt b/app/src/main/java/foundation/e/privacycentralapp/common/AppsAdapter.kt index d66ce76..07cf125 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/common/AppsAdapter.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/common/AppsAdapter.kt @@ -24,7 +24,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import foundation.e.privacycentralapp.R -import foundation.e.privacymodules.permissions.data.ApplicationDescription +import foundation.e.privacycentralapp.domain.entities.AppWithCounts class AppsAdapter( private val itemsLayout: Int, @@ -34,15 +34,20 @@ class AppsAdapter( class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val appName: TextView = view.findViewById(R.id.title) - - fun bind(item: ApplicationDescription) { + val counts: TextView = view.findViewById(R.id.counts) + val icon: ImageView = view.findViewById(R.id.icon) + fun bind(item: AppWithCounts) { appName.text = item.label - - itemView.findViewById(R.id.icon).setImageDrawable(item.icon) + counts.text = itemView.context.getString( + R.string.trackers_app_trackers_counts, + item.blockedTrackersCount, + item.trackersCount + ) + icon.setImageDrawable(item.icon) } } - var dataSet: List = emptyList() + var dataSet: List = emptyList() set(value) { field = value notifyDataSetChanged() diff --git a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt index 4718923..958a536 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt @@ -50,6 +50,14 @@ class AppListsRepository( return appDescriptions.value.second } + fun foldForHiddenSystemApp(appUid: Int, appValueGetter: (Int) -> Int): Int { + return if (appUid == dummySystemApp.uid) { + getHiddenSystemApps().fold(0) { acc, app -> + acc + appValueGetter(app.uid) + } + } else appValueGetter(appUid) + } + private val pm get() = context.packageManager private val appDescriptions = MutableStateFlow( diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/entities/AppWithCounts.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/entities/AppWithCounts.kt new file mode 100644 index 0000000..682dfc8 --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/domain/entities/AppWithCounts.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 E FOUNDATION + * + * 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.privacycentralapp.domain.entities + +import android.graphics.drawable.Drawable +import foundation.e.privacymodules.permissions.data.ApplicationDescription + +data class AppWithCounts( + val packageName: String, + val uid: Int, + var label: CharSequence?, + var icon: Drawable?, + val isWhitelisted: Boolean = false, + val trackersCount: Int = 0, + val whiteListedTrackersCount: Int = 0 +) { + constructor( + app: ApplicationDescription, + isWhitelisted: Boolean, + trackersCount: Int, + whiteListedTrackersCount: Int + ) : + this( + packageName = app.packageName, + uid = app.uid, + label = app.label, + icon = app.icon, + isWhitelisted = isWhitelisted, + trackersCount = trackersCount, + whiteListedTrackersCount = whiteListedTrackersCount + ) + + val blockedTrackersCount get() = if (isWhitelisted) 0 + else trackersCount - whiteListedTrackersCount +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt index 9a8b12a..ad8f565 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt @@ -20,18 +20,22 @@ package foundation.e.privacycentralapp.domain.usecases import android.content.res.Resources import foundation.e.privacycentralapp.R import foundation.e.privacycentralapp.data.repositories.AppListsRepository +import foundation.e.privacycentralapp.domain.entities.AppWithCounts import foundation.e.privacycentralapp.domain.entities.TrackersPeriodicStatistics +import foundation.e.privacymodules.trackers.IBlockTrackersPrivacyModule import foundation.e.privacymodules.trackers.ITrackTrackersPrivacyModule import foundation.e.privacymodules.trackers.Tracker import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.map import java.time.ZonedDateTime import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit class TrackersStatisticsUseCase( private val trackTrackersPrivacyModule: ITrackTrackersPrivacyModule, + private val blockTrackersPrivacyModule: IBlockTrackersPrivacyModule, private val appListsRepository: AppListsRepository, private val resources: Resources ) { @@ -124,4 +128,23 @@ class TrackersStatisticsUseCase( return trackers.sortedBy { it.label.lowercase() } } + + fun getAppsWithCounts(): Flow> { + val trackersCounts = trackTrackersPrivacyModule.getTrackersCountByApp() + return appListsRepository.getVisibleApps() + .map { apps -> + apps.map { app -> + AppWithCounts( + app, + blockTrackersPrivacyModule.isWhitelisted(app.uid), + appListsRepository.foldForHiddenSystemApp(app.uid) { + trackersCounts.getOrDefault(it, 0) + }, + appListsRepository.foldForHiddenSystemApp(app.uid) { + blockTrackersPrivacyModule.getWhiteList(it).size + } + ) + } + } + } } diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFeature.kt index e2eb58d..a606e49 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFeature.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFeature.kt @@ -22,11 +22,9 @@ import foundation.e.flowmvi.Actor import foundation.e.flowmvi.Reducer import foundation.e.flowmvi.SingleEventProducer import foundation.e.flowmvi.feature.BaseFeature +import foundation.e.privacycentralapp.domain.entities.AppWithCounts import foundation.e.privacycentralapp.domain.entities.TrackersPeriodicStatistics -import foundation.e.privacycentralapp.domain.usecases.AppListUseCase import foundation.e.privacycentralapp.domain.usecases.TrackersStatisticsUseCase -import foundation.e.privacymodules.permissions.data.ApplicationDescription -import foundation.e.privacymodules.trackers.Tracker import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf @@ -52,13 +50,12 @@ class TrackersFeature( val dayStatistics: TrackersPeriodicStatistics? = null, val monthStatistics: TrackersPeriodicStatistics? = null, val yearStatistics: TrackersPeriodicStatistics? = null, - val apps: List? = null, - val trackers: List = emptyList() + val apps: List? = null, ) sealed class SingleEvent { data class ErrorEvent(val error: String) : SingleEvent() - data class OpenAppDetailsEvent(val appDesc: ApplicationDescription) : SingleEvent() + data class OpenAppDetailsEvent(val appDesc: AppWithCounts) : SingleEvent() object NewStatisticsAvailableSingleEvent : SingleEvent() } @@ -75,9 +72,9 @@ class TrackersFeature( val yearStatistics: TrackersPeriodicStatistics? = null ) : Effect() data class AvailableAppsListEffect( - val apps: List + val apps: List ) : Effect() - data class OpenAppDetailsEffect(val appDesc: ApplicationDescription) : Effect() + data class OpenAppDetailsEffect(val appDesc: AppWithCounts) : Effect() object QuickPrivacyDisabledWarningEffect : Effect() data class ErrorEffect(val message: String) : Effect() object NewStatisticsAvailablesEffect : Effect() @@ -87,8 +84,7 @@ class TrackersFeature( fun create( initialState: State = State(), coroutineScope: CoroutineScope, - trackersStatisticsUseCase: TrackersStatisticsUseCase, - appListUseCase: AppListUseCase + trackersStatisticsUseCase: TrackersStatisticsUseCase ) = TrackersFeature( initialState, coroutineScope, reducer = { state, effect -> @@ -106,7 +102,19 @@ class TrackersFeature( }, actor = { state, action -> when (action) { - Action.InitAction -> merge( + Action.InitAction -> merge( + flowOf(Effect.NewStatisticsAvailablesEffect), + trackersStatisticsUseCase.listenUpdates().map { + Effect.NewStatisticsAvailablesEffect + } + ) + + is Action.ClickAppAction -> flowOf( + state.apps?.find { it.packageName == action.packageName }?.let { + Effect.OpenAppDetailsEffect(it) + } ?: run { Effect.ErrorEffect("Can't find back app.") } + ) + is Action.FetchStatistics -> merge( flow { trackersStatisticsUseCase.getDayMonthYearStatistics() .let { (day, month, year) -> @@ -114,36 +122,15 @@ class TrackersFeature( Effect.TrackersStatisticsLoadedEffect( dayStatistics = day, monthStatistics = month, - yearStatistics = year + yearStatistics = year, ) ) } }, - appListUseCase.getAppsUsingInternet().map { apps -> - Effect.AvailableAppsListEffect(apps) - }, - trackersStatisticsUseCase.listenUpdates().map { - Effect.NewStatisticsAvailablesEffect + trackersStatisticsUseCase.getAppsWithCounts().map { + Effect.AvailableAppsListEffect(it) } ) - - is Action.ClickAppAction -> flowOf( - state.apps?.find { it.packageName == action.packageName }?.let { - Effect.OpenAppDetailsEffect(it) - } ?: run { Effect.ErrorEffect("Can't find back app.") } - ) - is Action.FetchStatistics -> flow { - trackersStatisticsUseCase.getDayMonthYearStatistics() - .let { (day, month, year) -> - emit( - Effect.TrackersStatisticsLoadedEffect( - dayStatistics = day, - monthStatistics = month, - yearStatistics = year, - ) - ) - } - } } }, singleEventProducer = { _, _, effect -> diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFragment.kt index 3b22f89..0f686b4 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFragment.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFragment.kt @@ -18,10 +18,11 @@ package foundation.e.privacycentralapp.features.trackers import android.os.Bundle +import android.util.Log import android.view.View import android.widget.Toast -import androidx.fragment.app.add import androidx.fragment.app.commit +import androidx.fragment.app.replace import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager @@ -70,7 +71,7 @@ class TrackersFragment : } is TrackersFeature.SingleEvent.OpenAppDetailsEvent -> { requireActivity().supportFragmentManager.commit { - add(R.id.container, args = AppTrackersFragment.buildArgs(event.appDesc.label.toString(), event.appDesc.packageName)) + replace(R.id.container, args = AppTrackersFragment.buildArgs(event.appDesc.label.toString(), event.appDesc.packageName)) setReorderingAllowed(true) addToBackStack("apptrackers") } @@ -113,6 +114,7 @@ class TrackersFragment : } override fun onResume() { + Log.d("TestCounts", "OnResume") super.onResume() viewModel.submitAction(TrackersFeature.Action.FetchStatistics) } diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersViewModel.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersViewModel.kt index e3a97cc..c2a1822 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersViewModel.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersViewModel.kt @@ -20,15 +20,13 @@ package foundation.e.privacycentralapp.features.trackers import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import foundation.e.privacycentralapp.common.Factory -import foundation.e.privacycentralapp.domain.usecases.AppListUseCase import foundation.e.privacycentralapp.domain.usecases.TrackersStatisticsUseCase import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.launch class TrackersViewModel( - private val trackersStatisticsUseCase: TrackersStatisticsUseCase, - private val appListUseCase: AppListUseCase + private val trackersStatisticsUseCase: TrackersStatisticsUseCase ) : ViewModel() { private val _actions = MutableSharedFlow() @@ -38,8 +36,7 @@ class TrackersViewModel( TrackersFeature.create( coroutineScope = viewModelScope, - trackersStatisticsUseCase = trackersStatisticsUseCase, - appListUseCase = appListUseCase + trackersStatisticsUseCase = trackersStatisticsUseCase ) } @@ -51,11 +48,10 @@ class TrackersViewModel( } class TrackersViewModelFactory( - private val trackersStatisticsUseCase: TrackersStatisticsUseCase, - private val appListUseCase: AppListUseCase + private val trackersStatisticsUseCase: TrackersStatisticsUseCase ) : Factory { override fun create(): TrackersViewModel { - return TrackersViewModel(trackersStatisticsUseCase, appListUseCase) + return TrackersViewModel(trackersStatisticsUseCase) } } diff --git a/app/src/main/res/layout/trackers_item_app.xml b/app/src/main/res/layout/trackers_item_app.xml index b368664..310c792 100644 --- a/app/src/main/res/layout/trackers_item_app.xml +++ b/app/src/main/res/layout/trackers_item_app.xml @@ -1,7 +1,7 @@ - + - + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 822244b..49b6c95 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -67,6 +67,7 @@ HH:mm MMM d - EEE MMM yyyy + %1$d blocked trackers out of %2$d Block trackers diff --git a/build.gradle b/build.gradle index cbd41b1..86a50bb 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { 'targetSdk' : 29, 'version' : [ 'major': 0, - 'minor': 5, + 'minor': 6, 'patch': 0, 'build': "milestone-3", ], -- cgit v1.2.1