diff options
author | jacquarg <guillaume.jacquart@hoodbrains.com> | 2022-04-05 18:53:40 +0200 |
---|---|---|
committer | jacquarg <guillaume.jacquart@hoodbrains.com> | 2022-04-05 18:53:58 +0200 |
commit | bdf9198bb069f2ab9619cb4d3a85f5c2cbf9f0cd (patch) | |
tree | a1c5a0410e9392d01647301b56e9549fc934fff5 /app/src/main/java/foundation/e/privacycentralapp | |
parent | 250da848583f1fbd2d6658339fc758d22c67e938 (diff) |
5217 - Display blocked trackers, 5216 : add leaks in tooltips
Diffstat (limited to 'app/src/main/java/foundation/e/privacycentralapp')
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 +) |