From 730c2bc7566c03a9774509ab35bbbbca578ecf72 Mon Sep 17 00:00:00 2001 From: jacquarg Date: Mon, 25 Apr 2022 08:56:18 +0200 Subject: 219 highlight active trackers --- .../e/privacycentralapp/common/AppsAdapter.kt | 3 +- .../data/repositories/AppListsRepository.kt | 4 ++ .../domain/entities/AppWithCounts.kt | 12 +++-- .../domain/usecases/TrackersStatisticsUseCase.kt | 50 +++++++++++++++--- .../features/dashboard/DashboardFeature.kt | 60 +++++++++++++--------- .../features/dashboard/DashboardFragment.kt | 13 +++++ .../features/trackers/TrackersFeature.kt | 1 - .../trackers/apptrackers/AppTrackersFeature.kt | 28 ++++++---- .../trackers/apptrackers/AppTrackersFragment.kt | 4 +- .../e/privacycentralapp/main/MainActivity.kt | 22 ++++---- .../e/privacycentralapp/widget/WidgetUI.kt | 15 +++++- 11 files changed, 153 insertions(+), 59 deletions(-) (limited to 'app/src/main/java/foundation') 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 = 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 { + 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> { 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(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( - 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? = null, val whitelist: List? = null, + val leaked: Int = 0, + val blocked: Int = 0, val isQuickPrivacyEnabled: Boolean = false, - val showQuickPrivacyDisabledMessage: Boolean = false + val showQuickPrivacyDisabledMessage: Boolean = false, ) { fun getTrackersStatus(): List>? { 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) : Effect() + data class AvailableTrackersListEffect( + val trackers: List, + val blocked: Int, + val leaked: Int + ) : Effect() data class TrackersWhitelistUpdateEffect(val whitelist: List) : 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( 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(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(R.id.container) + addToBackStack("dashboard") + } else -> add(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 -- cgit v1.2.1