summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/build.gradle4
-rw-r--r--app/src/main/AndroidManifest.xml3
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/common/AppsAdapter.kt3
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt4
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/entities/AppWithCounts.kt12
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt50
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt60
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt13
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFeature.kt1
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt28
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt4
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt22
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt15
-rw-r--r--app/src/main/res/layout/apptrackers_item_tracker_toggle.xml12
-rw-r--r--app/src/main/res/layout/fragment_dashboard.xml17
-rw-r--r--app/src/main/res/layout/widget.xml15
-rw-r--r--app/src/main/res/values-fr/strings.xml2
-rw-r--r--app/src/main/res/values/strings.xml6
-rw-r--r--build.gradle2
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 &amp; 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",
],
]