summaryrefslogtreecommitdiff
path: root/app/src/main/java/foundation/e/privacycentralapp
diff options
context:
space:
mode:
authorRomain Hunault <romain.hunault@e.email>2022-04-05 18:23:04 +0000
committerRomain Hunault <romain.hunault@e.email>2022-04-05 18:23:04 +0000
commit752ee5975d0d1b75ef773b4d7e20ad00fac96519 (patch)
treed3abbbad472ed6a889bc3c0fa334329c01d35b4b /app/src/main/java/foundation/e/privacycentralapp
parent250da848583f1fbd2d6658339fc758d22c67e938 (diff)
parent1116394343fe8cb489f5405ab3c61b5e1ce78a50 (diff)
Merge branch '5217_blocked_trackers' into 'main'
5217 - Display blocked trackers, 5216 : add leaks in tooltips See merge request e/privacy-central/privacycentralapp!39
Diffstat (limited to 'app/src/main/java/foundation/e/privacycentralapp')
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/common/GraphHolder.kt67
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/common/NavToolbarFragment.kt1
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/entities/TrackersPeriodicStatistics.kt2
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStatisticsUseCase.kt8
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt8
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt2
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFragment.kt4
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt51
8 files changed, 111 insertions, 32 deletions
diff --git a/app/src/main/java/foundation/e/privacycentralapp/common/GraphHolder.kt b/app/src/main/java/foundation/e/privacycentralapp/common/GraphHolder.kt
index 929d838..aba3a95 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/common/GraphHolder.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/common/GraphHolder.kt
@@ -19,9 +19,14 @@ package foundation.e.privacycentralapp.common
import android.content.Context
import android.graphics.Canvas
+import android.text.Spannable
+import android.text.SpannableStringBuilder
+import android.text.style.DynamicDrawableSpan
+import android.text.style.ImageSpan
import android.view.View
import android.widget.TextView
import androidx.core.content.ContextCompat
+import androidx.core.text.toSpannable
import androidx.core.view.isVisible
import com.github.mikephil.charting.charts.BarChart
import com.github.mikephil.charting.components.MarkerView
@@ -37,7 +42,7 @@ import foundation.e.privacycentralapp.R
import foundation.e.privacycentralapp.extensions.dpToPxF
class GraphHolder(val barChart: BarChart, val context: Context, val isMarkerAbove: Boolean = true) {
- var data = emptyList<Int>()
+ var data = emptyList<Pair<Int, Int>>()
set(value) {
field = value
refreshDataSet()
@@ -80,7 +85,17 @@ class GraphHolder(val barChart: BarChart, val context: Context, val isMarkerAbov
setOnChartValueSelectedListener(object : OnChartValueSelectedListener {
override fun onValueSelected(e: Entry?, h: Highlight?) {
- h?.let { periodMarker.setLabel(labels.getOrNull(it.x.toInt())) }
+ h?.let {
+ val index = it.x.toInt()
+ if (index > 0 &&
+ index < labels.size &&
+ index < this@GraphHolder.data.size
+ ) {
+ val period = labels[index]
+ val (blocked, leaked) = this@GraphHolder.data[index]
+ periodMarker.setLabel(period, blocked, leaked)
+ }
+ }
isHighlighted = true
refreshDataSet()
}
@@ -95,18 +110,31 @@ class GraphHolder(val barChart: BarChart, val context: Context, val isMarkerAbov
private fun refreshDataSet() {
val trackersDataSet = BarDataSet(
- data.mapIndexed { index, value -> BarEntry(index.toFloat(), value.toFloat()) },
+ data.mapIndexed { index, value ->
+ BarEntry(
+ index.toFloat(),
+ floatArrayOf(value.first.toFloat(), value.second.toFloat())
+ )
+ },
""
).apply {
- color = ContextCompat.getColor(
- context,
- if (isHighlighted) R.color.blue_unselected else R.color.accent
+
+ val blockedColor = ContextCompat.getColor(context, R.color.accent)
+ val leakedColor = ContextCompat.getColor(context, R.color.red_off)
+
+ // ColorUtils.setAlphaComponent()
+ colors = listOf(
+ blockedColor,
+ // if (isHighlighted) R.color.blue_unselected else R.color.accent
+ leakedColor
)
+
setDrawValues(false)
- highLightColor = ContextCompat.getColor(
- context, R.color.accent
- )
- highLightAlpha = 255
+
+ // highLightColor = ContextCompat.getColor(
+ // context, R.color.accent
+ // )
+ // highLightAlpha = 255
}
barChart.data = BarData(trackersDataSet)
@@ -162,8 +190,23 @@ class PeriodMarkerView(context: Context, private val isMarkerAbove: Boolean = tr
}
}
- fun setLabel(label: String?) {
- findViewById<TextView>(R.id.label).text = label
+ fun setLabel(period: String, blocked: Int, leaked: Int) {
+ val span = SpannableStringBuilder(period)
+ span.append(": $blocked ")
+ span.setSpan(
+ ImageSpan(context, R.drawable.ic_legend_blocked, DynamicDrawableSpan.ALIGN_BASELINE),
+ span.length - 1,
+ span.length,
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+ span.append(" $leaked ")
+ span.setSpan(
+ ImageSpan(context, R.drawable.ic_legend_leaked, DynamicDrawableSpan.ALIGN_BASELINE),
+ span.length - 1,
+ span.length,
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+ findViewById<TextView>(R.id.label).text = span.toSpannable()
}
override fun refreshContent(e: Entry?, highlight: Highlight?) {
diff --git a/app/src/main/java/foundation/e/privacycentralapp/common/NavToolbarFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/common/NavToolbarFragment.kt
index c28c871..6955405 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/common/NavToolbarFragment.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/common/NavToolbarFragment.kt
@@ -19,7 +19,6 @@ package foundation.e.privacycentralapp.common
import androidx.annotation.LayoutRes
import com.google.android.material.appbar.MaterialToolbar
-import foundation.e.privacycentralapp.R
abstract class NavToolbarFragment(@LayoutRes contentLayoutId: Int) : ToolbarFragment(contentLayoutId) {
diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/entities/TrackersPeriodicStatistics.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/entities/TrackersPeriodicStatistics.kt
index 8a27d6d..b3a6ade 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/domain/entities/TrackersPeriodicStatistics.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/entities/TrackersPeriodicStatistics.kt
@@ -18,7 +18,7 @@
package foundation.e.privacycentralapp.domain.entities
data class TrackersPeriodicStatistics(
- val calls: List<Int>,
+ val callsBlockedNLeaked: List<Pair<Int, Int>>,
val periods: List<String>,
val trackersCount: Int
)
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 69dd0d8..4262055 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
@@ -53,7 +53,7 @@ class TrackersStatisticsUseCase(
fun getDayStatistics(): Pair<TrackersPeriodicStatistics, Int> {
return TrackersPeriodicStatistics(
- calls = trackTrackersPrivacyModule.getPastDayTrackersCalls(),
+ callsBlockedNLeaked = trackTrackersPrivacyModule.getPastDayTrackersCalls(),
periods = buildDayLabels(),
trackersCount = trackTrackersPrivacyModule.getPastDayTrackersCount()
) to trackTrackersPrivacyModule.getTrackersCount()
@@ -107,17 +107,17 @@ class TrackersStatisticsUseCase(
return with(trackTrackersPrivacyModule) {
Triple(
TrackersPeriodicStatistics(
- calls = getPastDayTrackersCalls(),
+ callsBlockedNLeaked = getPastDayTrackersCalls(),
periods = buildDayLabels(),
trackersCount = getPastDayTrackersCount()
),
TrackersPeriodicStatistics(
- calls = getPastMonthTrackersCalls(),
+ callsBlockedNLeaked = getPastMonthTrackersCalls(),
periods = buildMonthLabels(),
trackersCount = getPastMonthTrackersCount()
),
TrackersPeriodicStatistics(
- calls = getPastYearTrackersCalls(),
+ callsBlockedNLeaked = getPastYearTrackersCalls(),
periods = buildYearLabels(),
trackersCount = getPastYearTrackersCount()
)
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 87f5e42..8a4ee54 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
@@ -57,7 +57,7 @@ class DashboardFeature(
// val graphData
val trackersCount: Int? = null,
val activeTrackersCount: Int? = null,
- val dayStatistics: List<Int>? = null,
+ val dayStatistics: List<Pair<Int, Int>>? = null,
val dayLabels: List<String>? = null
)
@@ -84,7 +84,7 @@ class DashboardFeature(
data class UpdateStateEffect(val isEnabled: Boolean) : Effect()
data class IpScramblingModeUpdatedEffect(val mode: InternetPrivacyMode) : Effect()
data class TrackersStatisticsUpdatedEffect(
- val dayStatistics: List<Int>,
+ val dayStatistics: List<Pair<Int, Int>>,
val dayLabels: List<String>,
val dayTrackersCount: Int,
val trackersCount: Int
@@ -151,7 +151,7 @@ class DashboardFeature(
trackersStatisticsUseCase.getDayStatistics().let {
(dayStatistics, trackersCount) ->
Effect.TrackersStatisticsUpdatedEffect(
- dayStatistics = dayStatistics.calls,
+ dayStatistics = dayStatistics.callsBlockedNLeaked,
dayLabels = dayStatistics.periods,
dayTrackersCount = dayStatistics.trackersCount,
trackersCount = trackersCount
@@ -176,7 +176,7 @@ class DashboardFeature(
trackersStatisticsUseCase.getDayStatistics().let {
(dayStatistics, trackersCount) ->
Effect.TrackersStatisticsUpdatedEffect(
- dayStatistics = dayStatistics.calls,
+ dayStatistics = dayStatistics.callsBlockedNLeaked,
dayLabels = dayStatistics.periods,
dayTrackersCount = dayStatistics.trackersCount,
trackersCount = trackersCount
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 dec3234..51dee3d 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
@@ -217,7 +217,7 @@ class DashboardFragment :
)
)
- if (state.dayStatistics?.all { it == 0 } == true) {
+ if (state.dayStatistics?.all { it.first == 0 && it.second == 0 } == true) {
binding.graph.visibility = View.INVISIBLE
binding.graphLegend.isVisible = false
binding.graphEmpty.isVisible = true
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 c0212a5..893f4ba 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
@@ -137,13 +137,13 @@ class TrackersFragment :
graphHolder: GraphHolder,
graphBinding: TrackersItemGraphBinding
) {
- if (statistics.calls.all { it == 0 }) {
+ if (statistics.callsBlockedNLeaked.all { it.first == 0 && it.second == 0 }) {
graphBinding.graph.visibility = View.INVISIBLE
graphBinding.graphEmpty.isVisible = true
} else {
graphBinding.graph.isVisible = true
graphBinding.graphEmpty.isVisible = false
- graphHolder.data = statistics.calls
+ graphHolder.data = statistics.callsBlockedNLeaked
graphHolder.labels = statistics.periods
graphBinding.trackersCountLabel.text =
getString(R.string.trackers_count_label, statistics.trackersCount)
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 443683a..2529f6c 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt
@@ -39,7 +39,7 @@ data class State(
val isAllTrackersBlocked: Boolean = false,
val locationMode: LocationMode = LocationMode.REAL_LOCATION,
val internetPrivacyMode: InternetPrivacyMode = InternetPrivacyMode.REAL_IP,
- val dayStatistics: List<Int> = emptyList(),
+ val dayStatistics: List<Pair<Int, Int>> = emptyList(),
val activeTrackersCount: Int = 0,
) {
val isTrackersDenied get() = isQuickPrivacyEnabled && isAllTrackersBlocked
@@ -123,23 +123,33 @@ fun render(
setViewVisibility(R.id.state_ip_address_loader, if (loading) View.VISIBLE else View.GONE)
- if (state.dayStatistics.all { it == 0 }) {
+ if (state.dayStatistics.all { it.first == 0 && it.second == 0 }) {
setViewVisibility(R.id.graph, View.GONE)
setViewVisibility(R.id.graph_legend, View.GONE)
setViewVisibility(R.id.graph_empty, View.VISIBLE)
+ setViewVisibility(R.id.graph_legend_values, 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)
val graphHeightPx = 26.dpToPxF(context)
val maxValue =
- state.dayStatistics.maxOrNull().let { if (it == null || it == 0) 1 else it }
+ state.dayStatistics
+ .map { it.first + it.second }
+ .maxOrNull()
+ .let { if (it == null || it == 0) 1 else it }
val ratio = graphHeightPx / maxValue
- state.dayStatistics.zip(barIds).forEach { (value, viewId) ->
- val topPadding = graphHeightPx - value * ratio
- setViewPadding(viewId, 0, topPadding.toInt(), 0, 0)
+ state.dayStatistics.forEachIndexed { index, (blocked, leaked) ->
+ // blocked (the bar below)
+ val middlePadding = graphHeightPx - blocked * ratio
+ setViewPadding(blockedBarIds[index], 0, middlePadding.toInt(), 0, 0)
+
+ // leacked (the bar above)
+ val topPadding = graphHeightPx - (blocked + leaked) * ratio
+ setViewPadding(leakedBarIds[index], 0, topPadding.toInt(), 0, 0)
}
setTextViewText(
@@ -155,7 +165,7 @@ fun render(
appWidgetManager.updateAppWidget(ComponentName(context, Widget::class.java), views)
}
-private val barIds = listOf(
+private val blockedBarIds = listOf(
R.id.widget_graph_bar_0,
R.id.widget_graph_bar_1,
R.id.widget_graph_bar_2,
@@ -181,3 +191,30 @@ private val barIds = listOf(
R.id.widget_graph_bar_22,
R.id.widget_graph_bar_23
)
+
+private val leakedBarIds = listOf(
+ R.id.widget_leaked_graph_bar_0,
+ R.id.widget_leaked_graph_bar_1,
+ R.id.widget_leaked_graph_bar_2,
+ R.id.widget_leaked_graph_bar_3,
+ R.id.widget_leaked_graph_bar_4,
+ R.id.widget_leaked_graph_bar_5,
+ R.id.widget_leaked_graph_bar_6,
+ R.id.widget_leaked_graph_bar_7,
+ R.id.widget_leaked_graph_bar_8,
+ R.id.widget_leaked_graph_bar_9,
+ R.id.widget_leaked_graph_bar_10,
+ R.id.widget_leaked_graph_bar_11,
+ R.id.widget_leaked_graph_bar_12,
+ R.id.widget_leaked_graph_bar_13,
+ R.id.widget_leaked_graph_bar_14,
+ R.id.widget_leaked_graph_bar_15,
+ R.id.widget_leaked_graph_bar_16,
+ R.id.widget_leaked_graph_bar_17,
+ R.id.widget_leaked_graph_bar_18,
+ R.id.widget_leaked_graph_bar_19,
+ R.id.widget_leaked_graph_bar_20,
+ R.id.widget_leaked_graph_bar_21,
+ R.id.widget_leaked_graph_bar_22,
+ R.id.widget_leaked_graph_bar_23
+)