diff options
author | jacquarg <guillaume.jacquart@hoodbrains.com> | 2022-04-25 08:56:18 +0200 |
---|---|---|
committer | jacquarg <guillaume.jacquart@hoodbrains.com> | 2022-05-04 19:03:10 +0200 |
commit | 730c2bc7566c03a9774509ab35bbbbca578ecf72 (patch) | |
tree | 690e7e57530892fe5a31e12eb8f671d65d3139d2 | |
parent | fa5d60f99a07911a13c579074affd646973655b6 (diff) |
219 highlight active trackers
19 files changed, 200 insertions, 73 deletions
diff --git a/app/build.gradle b/app/build.gradle index 357a205..7749f8f 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.6.1' - implementation 'foundation.e:privacymodule.api:1.0.0' + implementation 'foundation.e:privacymodule.trackerfilter:0.7.0' + implementation 'foundation.e:privacymodule.api:1.1.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.2' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d285b6f..b288588 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -63,7 +63,8 @@ android:launchMode="singleTask"> <intent-filter> <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.INFO"/> + <category android:name="android.intent.category.LAUNCHER"/> +<!-- <category android:name="android.intent.category.INFO"/>--> </intent-filter> </activity> </application> 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 ed47cff..16b0144 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/common/AppsAdapter.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/common/AppsAdapter.kt @@ -41,7 +41,8 @@ class AppsAdapter( counts.text = itemView.context.getString( R.string.trackers_app_trackers_counts, item.blockedTrackersCount, - item.trackersCount + item.trackersCount, + item.leaks ) icon.setImageDrawable(item.icon) 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 4b19083..1f23516 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 @@ -66,6 +66,10 @@ class AppListsRepository( return appDescriptions.value.first.find { it.packageName == packageName } } + fun getApplicationDescription(appUid: Int): ApplicationDescription? { + return appDescriptions.value.first.find { it.uid == appUid } + } + fun foldForHiddenSystemApp(appUid: Int, appValueGetter: (Int) -> Int): Int { return if (appUid == dummySystemApp.uid) { getHiddenSystemApps().fold(0) { acc, app -> 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 index 682dfc8..0b76c7b 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/domain/entities/AppWithCounts.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/domain/entities/AppWithCounts.kt @@ -27,13 +27,17 @@ data class AppWithCounts( var icon: Drawable?, val isWhitelisted: Boolean = false, val trackersCount: Int = 0, - val whiteListedTrackersCount: Int = 0 + val whiteListedTrackersCount: Int = 0, + val blockedLeaks: Int = 0, + val leaks: Int = 0, ) { constructor( app: ApplicationDescription, isWhitelisted: Boolean, trackersCount: Int, - whiteListedTrackersCount: Int + whiteListedTrackersCount: Int, + blockedLeaks: Int, + leaks: Int, ) : this( packageName = app.packageName, @@ -42,7 +46,9 @@ data class AppWithCounts( icon = app.icon, isWhitelisted = isWhitelisted, trackersCount = trackersCount, - whiteListedTrackersCount = whiteListedTrackersCount + whiteListedTrackersCount = whiteListedTrackersCount, + blockedLeaks = blockedLeaks, + leaks = leaks ) val blockedTrackersCount get() = if (isWhitelisted) 0 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 6b4e098..d8eed5c 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 @@ -22,6 +22,7 @@ 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.permissions.data.ApplicationDescription import foundation.e.privacymodules.trackers.IBlockTrackersPrivacyModule import foundation.e.privacymodules.trackers.ITrackTrackersPrivacyModule import foundation.e.privacymodules.trackers.Tracker @@ -35,12 +36,14 @@ import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit class TrackersStatisticsUseCase( - // TODO private - val trackTrackersPrivacyModule: ITrackTrackersPrivacyModule, + private val trackTrackersPrivacyModule: ITrackTrackersPrivacyModule, private val blockTrackersPrivacyModule: IBlockTrackersPrivacyModule, private val appListsRepository: AppListsRepository, private val resources: Resources ) { + fun initAppList() { + appListsRepository.getVisibleApps() + } fun listenUpdates(): Flow<Unit> = callbackFlow { val listener = object : ITrackTrackersPrivacyModule.Listener { @@ -60,6 +63,12 @@ class TrackersStatisticsUseCase( ) to trackTrackersPrivacyModule.getTrackersCount() } + fun getMostLeakedApp(): ApplicationDescription? { + return appListsRepository.getApplicationDescription( + trackTrackersPrivacyModule.getPastDayMostLeakedApp() + ) + } + fun getDayTrackersCalls() = trackTrackersPrivacyModule.getPastDayTrackersCalls() fun getDayTrackersCount() = trackTrackersPrivacyModule.getPastDayTrackersCount() @@ -136,23 +145,48 @@ class TrackersStatisticsUseCase( return trackers.sortedBy { it.label.lowercase() } } + fun getCalls(appUid: Int): Pair<Int, Int> { + return if (appUid == appListsRepository.dummySystemApp.uid) { + appListsRepository.getHiddenSystemApps().map { + trackTrackersPrivacyModule.getPastDayTrackersCallsForApp(it.uid) + }.reduce { (accBlocked, accLeaked), (blocked, leaked) -> + accBlocked + blocked to accLeaked + leaked + } + } else trackTrackersPrivacyModule.getPastDayTrackersCallsForApp(appUid) + } + fun getAppsWithCounts(): Flow<List<AppWithCounts>> { val trackersCounts = trackTrackersPrivacyModule.getTrackersCountByApp() + return appListsRepository.getVisibleApps() .map { apps -> + val callsByApp = trackTrackersPrivacyModule.getPastDayTrackersCallsByApps() apps.map { app -> + val (blockedLeaks, leaks) = callsByApp.getOrDefault(app.uid, 0 to 0) AppWithCounts( - app, - !blockTrackersPrivacyModule.isBlockingEnabled() || + app = app, + isWhitelisted = !blockTrackersPrivacyModule.isBlockingEnabled() || blockTrackersPrivacyModule.isWhitelisted(app.uid), - appListsRepository.foldForHiddenSystemApp(app.uid) { + trackersCount = appListsRepository.foldForHiddenSystemApp(app.uid) { trackersCounts.getOrDefault(it, 0) }, - appListsRepository.foldForHiddenSystemApp(app.uid) { + whiteListedTrackersCount = appListsRepository.foldForHiddenSystemApp(app.uid) { blockTrackersPrivacyModule.getWhiteList(it).size - } + }, + blockedLeaks = blockedLeaks, + leaks = leaks ) - } + }.sortedWith( + Comparator { o1, o2 -> + val leaks = o2.leaks - o1.leaks + if (leaks != 0) leaks else { + val whitelisted = o2.whiteListedTrackersCount - o1.whiteListedTrackersCount + if (whitelisted != 0) whitelisted else { + o2.trackersCount - o1.trackersCount + } + } + } + ) } } diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt index 3ed3168..5192229 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt @@ -27,6 +27,7 @@ import foundation.e.privacycentralapp.domain.entities.LocationMode import foundation.e.privacycentralapp.domain.entities.QuickPrivacyState import foundation.e.privacycentralapp.domain.usecases.GetQuickPrivacyStateUseCase import foundation.e.privacycentralapp.domain.usecases.TrackersStatisticsUseCase +import foundation.e.privacymodules.permissions.data.ApplicationDescription import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf @@ -66,6 +67,7 @@ class DashboardFeature( object NavigateToInternetActivityPrivacySingleEvent : SingleEvent() object NavigateToLocationSingleEvent : SingleEvent() object NavigateToPermissionsSingleEvent : SingleEvent() + data class NavigateToAppDetailsEvent(val appDesc: ApplicationDescription) : SingleEvent() object NewStatisticsAvailableSingleEvent : SingleEvent() data class ToastMessageSingleEvent(val message: Int) : SingleEvent() } @@ -79,6 +81,7 @@ class DashboardFeature( object ShowTrackers : Action() object FetchStatistics : Action() object CloseQuickPrivacyDisabledMessage : Action() + object ShowMostLeakedApp : Action() } sealed class Effect { @@ -102,6 +105,7 @@ class DashboardFeature( object FirstIPTrackerActivationEffect : Effect() data class LocationHiddenUpdatedEffect(val isLocationHidden: Boolean) : Effect() data class ShowQuickPrivacyDisabledMessageEffect(val show: Boolean) : Effect() + data class OpenAppDetailsEffect(val appDesc: ApplicationDescription) : Effect() } companion object { @@ -146,29 +150,32 @@ class DashboardFeature( } } - Action.InitAction -> merge( - getPrivacyStateUseCase.quickPrivacyState.map { - Effect.UpdateStateEffect(it) - }, - getPrivacyStateUseCase.isIpHidden.map { - Effect.IpScramblingModeUpdatedEffect(it) - }, - trackersStatisticsUseCase.listenUpdates().map { - Effect.NewStatisticsAvailablesEffect - }, - getPrivacyStateUseCase.isTrackersDenied.map { - Effect.TrackersBlockedUpdatedEffect(it) - }, - getPrivacyStateUseCase.isLocationHidden.map { - Effect.LocationHiddenUpdatedEffect(it) - }, - getPrivacyStateUseCase.locationMode.map { - Effect.UpdateLocationModeEffect(it) - }, - getPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map { - Effect.ShowQuickPrivacyDisabledMessageEffect(it) - }, - ) + Action.InitAction -> { + trackersStatisticsUseCase.initAppList() + merge( + getPrivacyStateUseCase.quickPrivacyState.map { + Effect.UpdateStateEffect(it) + }, + getPrivacyStateUseCase.isIpHidden.map { + Effect.IpScramblingModeUpdatedEffect(it) + }, + trackersStatisticsUseCase.listenUpdates().map { + Effect.NewStatisticsAvailablesEffect + }, + getPrivacyStateUseCase.isTrackersDenied.map { + Effect.TrackersBlockedUpdatedEffect(it) + }, + getPrivacyStateUseCase.isLocationHidden.map { + Effect.LocationHiddenUpdatedEffect(it) + }, + getPrivacyStateUseCase.locationMode.map { + Effect.UpdateLocationModeEffect(it) + }, + getPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map { + Effect.ShowQuickPrivacyDisabledMessageEffect(it) + }, + ) + } Action.ShowFakeMyLocationAction -> flowOf(Effect.OpenFakeMyLocationEffect) Action.ShowAppsPermissions -> flowOf(Effect.OpenAppsPermissionsEffect) Action.ShowInternetActivityPrivacyAction -> flowOf( @@ -193,6 +200,12 @@ class DashboardFeature( getPrivacyStateUseCase.resetQuickPrivacyDisabledMessage() flowOf(Effect.NoEffect) } + is Action.ShowMostLeakedApp -> { + Log.d("mostleak", "Action.ShowMostLeakedApp") + flowOf( + trackersStatisticsUseCase.getMostLeakedApp()?.let { Effect.OpenAppDetailsEffect(appDesc = it) } ?: Effect.NoEffect + ) + } } }, singleEventProducer = { _, _, effect -> @@ -211,6 +224,7 @@ class DashboardFeature( SingleEvent.ToastMessageSingleEvent( message = R.string.dashboard_first_ipscrambling_activation ) + is Effect.OpenAppDetailsEffect -> SingleEvent.NavigateToAppDetailsEvent(effect.appDesc) else -> null } } diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt index 3f849a6..398a594 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt @@ -46,6 +46,7 @@ import foundation.e.privacycentralapp.features.dashboard.DashboardFeature.State import foundation.e.privacycentralapp.features.internetprivacy.InternetPrivacyFragment import foundation.e.privacycentralapp.features.location.FakeLocationFragment import foundation.e.privacycentralapp.features.trackers.TrackersFragment +import foundation.e.privacycentralapp.features.trackers.apptrackers.AppTrackersFragment import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow @@ -118,6 +119,13 @@ class DashboardFragment : addToBackStack("dashboard") } } + is DashboardFeature.SingleEvent.NavigateToAppDetailsEvent -> { + requireActivity().supportFragmentManager.commit { + replace<AppTrackersFragment>(R.id.container, args = AppTrackersFragment.buildArgs(event.appDesc.label.toString(), event.appDesc.packageName)) + setReorderingAllowed(true) + addToBackStack("dashboard") + } + } DashboardFeature.SingleEvent.NewStatisticsAvailableSingleEvent -> { viewModel.submitAction(DashboardFeature.Action.FetchStatistics) } @@ -138,6 +146,9 @@ class DashboardFragment : graphHolder = GraphHolder(binding.graph, requireContext()) + binding.leakingAppButton.setOnClickListener { + viewModel.submitAction(DashboardFeature.Action.ShowMostLeakedApp) + } binding.togglePrivacyCentral.setOnClickListener { viewModel.submitAction(DashboardFeature.Action.TogglePrivacyAction) } @@ -247,10 +258,12 @@ class DashboardFragment : if (state.dayStatistics?.all { it.first == 0 && it.second == 0 } == true) { binding.graph.visibility = View.INVISIBLE binding.graphLegend.isVisible = false + binding.leakingAppButton.isVisible = false binding.graphEmpty.isVisible = true } else { binding.graph.isVisible = true binding.graphLegend.isVisible = true + binding.leakingAppButton.isVisible = true binding.graphEmpty.isVisible = false state.dayStatistics?.let { graphHolder.data = it } state.dayLabels?.let { graphHolder.labels = it } 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 34ddfbe..25443e9 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 @@ -109,7 +109,6 @@ class TrackersFeature( actor = { state, action -> when (action) { Action.InitAction -> merge<Effect>( - flowOf(Effect.NewStatisticsAvailablesEffect), trackersStatisticsUseCase.listenUpdates().map { Effect.NewStatisticsAvailablesEffect }, 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 ad82337..f6d7d67 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 @@ -55,8 +55,10 @@ class AppTrackersFeature( val isBlockingActivated: Boolean = false, val trackers: List<Tracker>? = null, val whitelist: List<String>? = null, + val leaked: Int = 0, + val blocked: Int = 0, val isQuickPrivacyEnabled: Boolean = false, - val showQuickPrivacyDisabledMessage: Boolean = false + val showQuickPrivacyDisabledMessage: Boolean = false, ) { fun getTrackersStatus(): List<Pair<Tracker, Boolean>>? { if (trackers != null && whitelist != null) { @@ -92,7 +94,11 @@ class AppTrackersFeature( data class ErrorEffect(val message: Any) : Effect() data class SetAppEffect(val appDesc: ApplicationDescription) : Effect() data class AppTrackersBlockingActivatedEffect(val isBlockingActivated: Boolean) : Effect() - data class AvailableTrackersListEffect(val trackers: List<Tracker>) : Effect() + data class AvailableTrackersListEffect( + val trackers: List<Tracker>, + val blocked: Int, + val leaked: Int + ) : Effect() data class TrackersWhitelistUpdateEffect(val whitelist: List<String>) : Effect() object NewStatisticsAvailablesEffect : Effect() data class QuickPrivacyUpdatedEffect(val enabled: Boolean) : Effect() @@ -114,7 +120,11 @@ class AppTrackersFeature( reducer = { state, effect -> when (effect) { is Effect.SetAppEffect -> state.copy(appDesc = effect.appDesc) - is Effect.AvailableTrackersListEffect -> state.copy(trackers = effect.trackers) + is Effect.AvailableTrackersListEffect -> state.copy( + trackers = effect.trackers, + leaked = effect.leaked, + blocked = effect.blocked + ) is Effect.AppTrackersBlockingActivatedEffect -> state.copy(isBlockingActivated = effect.isBlockingActivated) @@ -135,7 +145,6 @@ class AppTrackersFeature( .getApplicationDescription(action.packageName)?.let { appDesc -> merge<Effect>( flow { - emit(Effect.SetAppEffect(appDesc)) emit( Effect.AppTrackersBlockingActivatedEffect( @@ -147,11 +156,6 @@ class AppTrackersFeature( trackersStateUseCase.getTrackersWhitelistIds(appDesc.uid) ) ) - emit( - Effect.AvailableTrackersListEffect( - trackers = trackersStatisticsUseCase.getTrackers(appDesc.uid) - ) - ) }, trackersStatisticsUseCase.listenUpdates().map { Effect.NewStatisticsAvailablesEffect @@ -208,8 +212,12 @@ class AppTrackersFeature( } is Action.FetchStatistics -> flowOf( state.appDesc?.uid?.let { + val (blocked, leaked) = trackersStatisticsUseCase.getCalls(it) + Effect.AvailableTrackersListEffect( - trackers = trackersStatisticsUseCase.getTrackers(it) + trackers = trackersStatisticsUseCase.getTrackers(it), + leaked = leaked, + blocked = blocked, ) } ?: Effect.ErrorEffect("No appDesc.") ) 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 7e606af..406d26c 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 @@ -143,7 +143,9 @@ class AppTrackersFragment : else getString( R.string.apptrackers_trackers_count_summary, state.getBlockedTrackersCount(), - state.getTrackersCount() + state.getTrackersCount(), + state.blocked, + state.leaked ) binding.blockAllToggle.isChecked = state.isBlockingActivated diff --git a/app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt b/app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt index 5159827..92a156a 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt @@ -27,21 +27,11 @@ import androidx.fragment.app.commit import foundation.e.privacycentralapp.PrivacyCentralApplication import foundation.e.privacycentralapp.R import foundation.e.privacycentralapp.features.dashboard.DashboardFragment +import foundation.e.privacycentralapp.features.trackers.TrackersFragment import kotlinx.coroutines.FlowPreview @FlowPreview open class MainActivity : FragmentActivity(R.layout.activity_main) { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - if (savedInstanceState == null) { - supportFragmentManager.commit { - setReorderingAllowed(true) - add<DashboardFragment>(R.id.container) - } - } - } - override fun onPostCreate(savedInstanceState: Bundle?) { super.onPostCreate(savedInstanceState) handleIntent(intent) @@ -65,6 +55,10 @@ open class MainActivity : FragmentActivity(R.layout.activity_main) { containerViewId = R.id.container, args = intent.extras ) + ACTION_VIEW_TRACKERS -> { + add<TrackersFragment>(R.id.container) + addToBackStack("dashboard") + } else -> add<DashboardFragment>(R.id.container) } } @@ -82,11 +76,17 @@ open class MainActivity : FragmentActivity(R.layout.activity_main) { companion object { private const val ACTION_HIGHLIGHT_LEAKS = "ACTION_HIGHLIGHT_LEAKS" + private const val ACTION_VIEW_TRACKERS = "ACTION_VIEW_TRACKERS" fun createHighlightLeaksIntent(context: Context, highlightIndex: Int) = Intent(context, MainActivity::class.java).apply { action = ACTION_HIGHLIGHT_LEAKS putExtras(DashboardFragment.buildArgs(highlightIndex)) } + + fun createTrackersIntent(context: Context) = + Intent(context, MainActivity::class.java).apply { + action = ACTION_VIEW_TRACKERS + } } } diff --git a/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt b/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt index 81859e6..ca93617 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt @@ -127,11 +127,23 @@ fun render( setViewVisibility(R.id.graph_legend, View.GONE) setViewVisibility(R.id.graph_empty, View.VISIBLE) setViewVisibility(R.id.graph_legend_values, View.GONE) + setViewVisibility(R.id.graph_view_trackers_btn, View.GONE) } else { setViewVisibility(R.id.graph, View.VISIBLE) setViewVisibility(R.id.graph_legend, View.VISIBLE) setViewVisibility(R.id.graph_empty, View.GONE) setViewVisibility(R.id.graph_legend_values, View.VISIBLE) + setViewVisibility(R.id.graph_view_trackers_btn, View.VISIBLE) + + val pIntent = PendingIntent.getActivity( + context, + REQUEST_CODE_TRACKERS, + MainActivity.createTrackersIntent(context), + FLAG_UPDATE_CURRENT + ) + + setOnClickPendingIntent(R.id.graph_view_trackers_btn, pIntent) + // setOnClickPendingIntent(R.id.graph_view_trackers_btn_icon, pIntent) val graphHeightPx = 26.dpToPxF(context) val maxValue = @@ -146,7 +158,7 @@ fun render( val middlePadding = graphHeightPx - blocked * ratio setViewPadding(blockedBarIds[index], 0, middlePadding.toInt(), 0, 0) - // leacked (the bar above) + // leaked (the bar above) val topPadding = graphHeightPx - (blocked + leaked) * ratio setViewPadding(leakedBarIds[index], 0, topPadding.toInt(), 0, 0) @@ -254,4 +266,5 @@ private val leakedBarIds = listOf( private const val REQUEST_CODE_DASHBOARD = 1 private const val REQUEST_CODE_TOGGLE = 2 +private const val REQUEST_CODE_TRACKERS = 3 private const val REQUEST_CODE_HIGHLIGHT = 100 diff --git a/app/src/main/res/layout/apptrackers_item_tracker_toggle.xml b/app/src/main/res/layout/apptrackers_item_tracker_toggle.xml index 0371390..db7086f 100644 --- a/app/src/main/res/layout/apptrackers_item_tracker_toggle.xml +++ b/app/src/main/res/layout/apptrackers_item_tracker_toggle.xml @@ -20,10 +20,10 @@ android:textSize="14sp" tools:text="Body sensor" /> - <Switch - android:id="@+id/toggle" - android:layout_width="wrap_content" - android:layout_height="24dp" - android:checked="true" - /> + <Switch + android:id="@+id/toggle" + android:layout_width="wrap_content" + android:layout_height="24dp" + android:checked="true" + /> </androidx.appcompat.widget.LinearLayoutCompat> diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_dashboard.xml index d79dea1..f6beca6 100644 --- a/app/src/main/res/layout/fragment_dashboard.xml +++ b/app/src/main/res/layout/fragment_dashboard.xml @@ -30,7 +30,7 @@ android:layout_height="25dp" android:layout_width="24dp" android:layout_margin="16dp" - android:src="@drawable/ic_shield_off" + android:src="@drawable/ic_shield_off_white" android:scaleType="fitCenter" /> <TextView @@ -248,6 +248,21 @@ android:text="@string/dashboard_state_ipaddress_off" /> <TextView + android:id="@+id/leaking_app_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="12sp" + android:textColor="@color/primary_text" + android:drawableEnd="@drawable/ic_chevron_right_24dp" + android:text="@string/dashboard_graph_leaking_app" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintBottom_toBottomOf="@+id/graph_legend_blocked_icon" + app:layout_constraintTop_toTopOf="@+id/graph_legend_blocked_icon" + android:gravity="center_vertical|end" + android:layout_marginRight="16dp" + /> + + <TextView android:id="@+id/graph_empty" android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/app/src/main/res/layout/widget.xml b/app/src/main/res/layout/widget.xml index e55d8a3..999a888 100644 --- a/app/src/main/res/layout/widget.xml +++ b/app/src/main/res/layout/widget.xml @@ -687,6 +687,7 @@ android:layout_marginTop="16dp" android:layout_marginHorizontal="24dp" android:layout_marginBottom="24dp" + android:gravity="center_vertical" > <ImageView @@ -726,6 +727,20 @@ android:textSize="12sp" android:text="@string/graph_legend_allowed" /> + + <TextView + android:id="@+id/graph_view_trackers_btn" + android:layout_width="0dp" + android:layout_weight="1" + android:layout_height="wrap_content" + android:textSize="12sp" + android:textAlignment="textEnd" + android:gravity="center_vertical|end" + android:textColor="@color/on_primary_high_emphasis" + android:drawableEnd="@drawable/ic_chevron_right_24dp" + android:drawableTint="@color/on_primary_high_emphasis" + android:text="@string/widget_graph_view_trackers" + /> </LinearLayout> <TextView diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 47970a1..c0a8582 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -62,7 +62,7 @@ <string name="trackers_title">Gérer les pisteurs des applications</string> <string name="trackers_count_label">%d pisteurs</string> <string name="trackers_applist_title">Gérer les pisteurs utilisés dans les applications :</string> - <string name="trackers_app_trackers_counts">%1$d pisteurs bloqués sur %2$d</string> + <string name="trackers_app_trackers_counts">%1$d pisteurs bloqués sur %2$d, </string> <string name="apptrackers_block_all_toggle">Bloquer les pisteurs</string> <string name="apptrackers_trackers_list_title">Optez pour les pisteurs que vous souhaitez activer/désactiver.</string> <string name="apptrackers_no_trackers_yet_block_off">Pour l\'instant, aucun pisteurs n\'a été détecté. Si de nouveaux pisteurs sont détectés, ils seront mis à jour ici.</string> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 489dff2..c1f15f0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -27,6 +27,7 @@ <string name="dashboard_graph_label">Personal data leakage:</string> <string name="dashboard_graph_period">Today</string> <string name="dashboard_graph_trackers_legend">%s trackers have profiled you in the last 24 hours</string> + <string name="dashboard_graph_leaking_app">View</string> <string name="dashboard_first_ipscrambling_activation">While your IP is faked, your internet speed is likely to be reduced.</string> <string name="dashboard_am_i_tracked_title">Manage apps\' trackers</string> @@ -77,7 +78,7 @@ <string name="trackers_graph_hours_period_format">HH:mm</string> <string name="trackers_graph_days_period_format">MMMM d - EEE</string> <string name="trackers_graph_months_period_format">MMMM yyyy</string> - <string name="trackers_app_trackers_counts">%1$d blocked trackers out of %2$d</string> + <string name="trackers_app_trackers_counts">%1$d blocked trackers out of %2$d, %3$d leaks</string> <!-- App Trackers --> <string name="apptrackers_block_all_toggle">Block trackers</string> @@ -85,7 +86,7 @@ <string name="apptrackers_no_trackers_yet_block_off">No trackers were detected yet. If new trackers are detected they will be updated here.</string> <string name="apptrackers_no_trackers_yet_block_on">No trackers were detected yet. All future trackers will be blocked.</string> <string name="apptrackers_error_quickprivacy_disabled">Enable Quick Privacy to be able to activate/deactivate trackers.</string> - <string name="apptrackers_trackers_count_summary">%1$d blocked trackers out of %2$d detected trackers</string> + <string name="apptrackers_trackers_count_summary">%1$d blocked trackers out of %2$d detected trackers, %3$d blocked leaks and %4$d allowed leaks.</string> <string name="apptrackers_error_no_app">App not installed.</string> <!-- --> @@ -140,6 +141,7 @@ <string name="widget_state_ipaddress_off">@string/dashboard_state_ipaddress_off</string> <string name="widget_state_ipaddress_on">@string/dashboard_state_ipaddress_on</string> <string name="widget_graph_trackers_legend">@string/dashboard_graph_trackers_legend</string> + <string name="widget_graph_view_trackers">View</string> <string name="first_notification_title">Discover Advanced Privacy</string> <string name="first_notification_summary">Tap to find out how to easily block trackers, fake your location & hide your IP address.</string> diff --git a/build.gradle b/build.gradle index c7815e7..be0a6cf 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { 'major': 1, 'minor': 0, 'patch': 0, - 'build': "milestone-5", + 'build': "RC-1", ], ] |