diff options
16 files changed, 676 insertions, 141 deletions
diff --git a/app/build.gradle b/app/build.gradle index bbbb70b..dbbfa47 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -112,8 +112,8 @@ dependencies { //googleImplementation project(":privacymodulesgoogle") // include the e specific version of the modules, just for the e flavor - implementation 'foundation.e:privacymodule.trackerfilter:0.5.1' - implementation 'foundation.e:privacymodule.api:0.6.0' + implementation 'foundation.e:privacymodule.trackerfilter:0.6.0' + implementation 'foundation.e:privacymodule.api:1.0.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/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 +) diff --git a/app/src/main/res/drawable/ic_legend_blocked.xml b/app/src/main/res/drawable/ic_legend_blocked.xml new file mode 100644 index 0000000..15f8c56 --- /dev/null +++ b/app/src/main/res/drawable/ic_legend_blocked.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ 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 <https://www.gnu.org/licenses/>. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> + <solid android:color="@color/accent"/> + <size android:width="12dp" android:height="12dp" /> +</shape>
\ No newline at end of file diff --git a/app/src/main/res/drawable/ic_legend_leaked.xml b/app/src/main/res/drawable/ic_legend_leaked.xml new file mode 100644 index 0000000..a96501f --- /dev/null +++ b/app/src/main/res/drawable/ic_legend_leaked.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ 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 <https://www.gnu.org/licenses/>. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> + <solid android:color="@color/red_off"/> + <size android:width="12dp" android:height="12dp" /> +</shape>
\ No newline at end of file diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_dashboard.xml index 53ec617..ff64733 100644 --- a/app/src/main/res/layout/fragment_dashboard.xml +++ b/app/src/main/res/layout/fragment_dashboard.xml @@ -188,6 +188,55 @@ android:text="@string/dashboard_state_ipaddress_off" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@+id/graph" /> + + <View + android:id="@+id/graph_legend_blocked_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:padding="1dp" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toBottomOf="@+id/graph_legend" + android:layout_marginTop="8dp" + android:layout_marginStart="16dp" + android:background="@drawable/ic_legend_blocked" + /> + <TextView + android:id="@+id/graph_legend_blocked" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + tools:text="0 Trackers" + android:layout_marginStart="8dp" + android:textSize="12sp" + app:layout_constraintLeft_toRightOf="@+id/graph_legend_blocked_icon" + app:layout_constraintBottom_toBottomOf="@+id/graph_legend_blocked_icon" + android:layout_marginTop="8dp" + android:text="@string/graph_legend_blocked" + /> + + <View + android:id="@+id/graph_legend_allowed_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:padding="1dp" + app:layout_constraintLeft_toRightOf="@+id/graph_legend_blocked" + app:layout_constraintBottom_toBottomOf="@+id/graph_legend_blocked_icon" + android:layout_marginTop="8dp" + android:layout_marginStart="32dp" + android:background="@drawable/ic_legend_leaked" + /> + <TextView + android:id="@+id/graph_legend_allowed" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + tools:text="0 Trackers" + android:layout_marginStart="8dp" + android:textSize="12sp" + app:layout_constraintLeft_toRightOf="@+id/graph_legend_allowed_icon" + app:layout_constraintBottom_toBottomOf="@+id/graph_legend_blocked_icon" + android:layout_marginTop="8dp" + android:text="@string/graph_legend_allowed" + /> + <TextView android:id="@+id/graph_empty" android:layout_width="match_parent" diff --git a/app/src/main/res/layout/trackers_item_graph.xml b/app/src/main/res/layout/trackers_item_graph.xml index 5cc2d98..933b96c 100644 --- a/app/src/main/res/layout/trackers_item_graph.xml +++ b/app/src/main/res/layout/trackers_item_graph.xml @@ -55,6 +55,55 @@ android:layout_width="match_parent" app:layout_constraintTop_toBottomOf="@+id/graph_period_label" /> + + <View + android:id="@+id/graph_legend_blocked_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:padding="1dp" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toBottomOf="@+id/graph" + android:layout_marginTop="8dp" + android:layout_marginStart="16dp" + android:background="@drawable/ic_legend_blocked" + /> + <TextView + android:id="@+id/graph_legend_blocked" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + tools:text="0 Trackers" + android:layout_marginStart="8dp" + android:textSize="12sp" + app:layout_constraintLeft_toRightOf="@+id/graph_legend_blocked_icon" + app:layout_constraintBottom_toBottomOf="@+id/graph_legend_blocked_icon" + android:layout_marginTop="8dp" + android:text="@string/graph_legend_blocked" + /> + + <View + android:id="@+id/graph_legend_allowed_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:padding="1dp" + app:layout_constraintLeft_toRightOf="@+id/graph_legend_blocked" + app:layout_constraintBottom_toBottomOf="@+id/graph_legend_blocked_icon" + android:layout_marginTop="8dp" + android:layout_marginStart="32dp" + android:background="@drawable/ic_legend_leaked" + /> + <TextView + android:id="@+id/graph_legend_allowed" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + tools:text="0 Trackers" + android:layout_marginStart="8dp" + android:textSize="12sp" + app:layout_constraintLeft_toRightOf="@+id/graph_legend_allowed_icon" + app:layout_constraintBottom_toBottomOf="@+id/graph_legend_blocked_icon" + android:layout_marginTop="8dp" + android:text="@string/graph_legend_allowed" + /> + <TextView android:id="@+id/graph_empty" android:layout_width="match_parent" diff --git a/app/src/main/res/layout/widget.xml b/app/src/main/res/layout/widget.xml index dc3ac16..ae5bfe7 100644 --- a/app/src/main/res/layout/widget.xml +++ b/app/src/main/res/layout/widget.xml @@ -178,205 +178,471 @@ android:layout_marginHorizontal="24dp" android:layout_height="26dp" > - <ImageView - android:id="@+id/widget_graph_bar_0" + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_1" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_0" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_0" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_2" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_1" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_1" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_3" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_2" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_2" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_4" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_3" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_3" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_5" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_4" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_4" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_6" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_5" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_5" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_7" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_6" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_6" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_8" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_7" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_7" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_9" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_8" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_8" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_10" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_9" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_9" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_11" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_10" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_10" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_12" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_11" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_11" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_13" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_12" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_12" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_14" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_13" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_13" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_15" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_14" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_14" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_16" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_15" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_15" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_17" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_16" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_16" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_18" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_17" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_17" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_19" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_18" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_18" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_20" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_19" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_19" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_21" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_20" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_20" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_22" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_21" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_21" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" android:layout_marginRight="1.5dp" - /> - <ImageView - android:id="@+id/widget_graph_bar_23" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_22" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_22" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> + <FrameLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" - android:src="@color/accent" - /> - </LinearLayout> + android:layout_marginRight="1.5dp" + > + <ImageView + android:id="@+id/widget_leaked_graph_bar_23" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/red_off" + /> + <ImageView + android:id="@+id/widget_graph_bar_23" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:src="@color/accent" + /> + </FrameLayout> -<!-- <com.github.mikephil.charting.charts.BarChart--> -<!-- android:id="@+id/graph"--> -<!-- android:layout_height="144dp"--> -<!-- android:layout_width="match_parent"--> -<!-- android:layout_marginHorizontal="24dp"--> -<!-- />--> + </LinearLayout> <TextView android:id="@+id/graph_legend" @@ -387,9 +653,57 @@ android:textColor="@color/on_primary_high_emphasis" android:layout_marginTop="16dp" android:layout_marginHorizontal="24dp" - android:layout_marginBottom="24dp" /> + <LinearLayout + android:id="@+id/graph_legend_values" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_marginTop="16dp" + android:layout_marginHorizontal="24dp" + android:layout_marginBottom="24dp" + > + + <ImageView + android:id="@+id/graph_legend_blocked_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:padding="1dp" + android:src="@drawable/ic_legend_blocked" + /> + <TextView + android:id="@+id/graph_legend_blocked" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + tools:text="0 Trackers" + android:textColor="@color/on_primary_medium_emphasis" + android:layout_marginStart="8dp" + android:textSize="12sp" + android:text="@string/graph_legend_blocked" + /> + + <ImageView + android:id="@+id/graph_legend_allowed_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:padding="1dp" + android:layout_marginStart="32dp" + android:src="@drawable/ic_legend_leaked" + /> + + <TextView + android:id="@+id/graph_legend_allowed" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + tools:text="0 Trackers" + android:textColor="@color/on_primary_medium_emphasis" + android:layout_marginStart="8dp" + android:textSize="12sp" + android:text="@string/graph_legend_allowed" + /> + </LinearLayout> + <TextView android:id="@+id/graph_empty" android:layout_width="match_parent" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ce7709c..88bd473 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -4,6 +4,8 @@ <!-- Commons --> <string name="dummy_system_app_label">System</string> <string name="graph_empty_message">Congratulations! No trackers are profiling you.</string> + <string name="graph_legend_blocked">Blocked leaks</string> + <string name="graph_legend_allowed">Allowed leaks</string> <!-- Dashboard --> <string name="dashboard_title">@string/app_name</string> diff --git a/build.gradle b/build.gradle index 5ff250d..c7815e7 100644 --- a/build.gradle +++ b/build.gradle @@ -8,10 +8,10 @@ buildscript { 'minSdk' : 26, 'targetSdk' : 29, 'version' : [ - 'major': 0, - 'minor': 6, + 'major': 1, + 'minor': 0, 'patch': 0, - 'build': "milestone-3", + 'build': "milestone-5", ], ] |