Loading app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt +1 −1 Original line number Diff line number Diff line Loading @@ -119,7 +119,7 @@ class DependencyContainer(val app: Application) { } val trackersViewModelFactory by lazy { TrackersViewModelFactory(trackersStatisticsUseCase) TrackersViewModelFactory(getQuickPrivacyStateUseCase, trackersStatisticsUseCase) } val appTrackersViewModelFactory by lazy { Loading app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt +7 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,10 @@ class TrackersStateUseCase( } fun toggleAppWhitelist(appUid: Int, isWhitelisted: Boolean) { if (!localStateRepository.isQuickPrivacyEnabled) { localStateRepository.setShowQuickPrivacyDisabledMessage(true) } if (appUid == appListsRepository.dummySystemApp.uid) { appListsRepository.getHiddenSystemApps().forEach { blockTrackersPrivacyModule.setWhiteListed(it.uid, isWhitelisted) Loading @@ -89,6 +93,9 @@ class TrackersStateUseCase( } fun blockTracker(appUid: Int, tracker: Tracker, isBlocked: Boolean) { if (!localStateRepository.isQuickPrivacyEnabled) { localStateRepository.setShowQuickPrivacyDisabledMessage(true) } if (appUid == appListsRepository.dummySystemApp.uid) { appListsRepository.getHiddenSystemApps().forEach { blockTrackersPrivacyModule.setWhiteListed(tracker, it.uid, !isBlocked) Loading app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt +13 −3 Original line number Diff line number Diff line Loading @@ -57,7 +57,8 @@ class DashboardFeature( val trackersCount: Int? = null, val allowedTrackersCount: Int? = null, val dayStatistics: List<Pair<Int, Int>>? = null, val dayLabels: List<String>? = null val dayLabels: List<String>? = null, val showQuickPrivacyDisabledMessage: Boolean = false ) sealed class SingleEvent { Loading @@ -77,6 +78,7 @@ class DashboardFeature( object ShowAppsPermissions : Action() object ShowTrackers : Action() object FetchStatistics : Action() object CloseQuickPrivacyDisabledMessage : Action() } sealed class Effect { Loading @@ -99,6 +101,7 @@ class DashboardFeature( object NewStatisticsAvailablesEffect : Effect() object FirstIPTrackerActivationEffect : Effect() data class LocationHiddenUpdatedEffect(val isLocationHidden: Boolean) : Effect() data class ShowQuickPrivacyDisabledMessageEffect(val show: Boolean) : Effect() } companion object { Loading Loading @@ -129,7 +132,7 @@ class DashboardFeature( isLocationHidden = effect.isLocationHidden ) is Effect.UpdateLocationModeEffect -> state.copy(locationMode = effect.mode) is Effect.ShowQuickPrivacyDisabledMessageEffect -> state.copy(showQuickPrivacyDisabledMessage = effect.show) else -> state } }, Loading Loading @@ -161,7 +164,10 @@ class DashboardFeature( }, getPrivacyStateUseCase.locationMode.map { Effect.UpdateLocationModeEffect(it) } }, getPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map { Effect.ShowQuickPrivacyDisabledMessageEffect(it) }, ) Action.ShowFakeMyLocationAction -> flowOf(Effect.OpenFakeMyLocationEffect) Action.ShowAppsPermissions -> flowOf(Effect.OpenAppsPermissionsEffect) Loading @@ -183,6 +189,10 @@ class DashboardFeature( ) } } is Action.CloseQuickPrivacyDisabledMessage -> { getPrivacyStateUseCase.resetQuickPrivacyDisabledMessage() flowOf(Effect.NoEffect) } } }, singleEventProducer = { _, _, effect -> Loading app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt +17 −4 Original line number Diff line number Diff line Loading @@ -26,15 +26,17 @@ import android.widget.Toast import androidx.core.content.ContextCompat.getColor import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.fragment.app.add import androidx.fragment.app.commit import androidx.fragment.app.replace import androidx.lifecycle.lifecycleScope import com.google.android.material.snackbar.Snackbar import foundation.e.flowmvi.MVIView import foundation.e.privacycentralapp.DependencyContainer import foundation.e.privacycentralapp.PrivacyCentralApplication import foundation.e.privacycentralapp.R import foundation.e.privacycentralapp.common.GraphHolder import foundation.e.privacycentralapp.common.NavToolbarFragment import foundation.e.privacycentralapp.common.initQuickPrivacySnackbar import foundation.e.privacycentralapp.databinding.FragmentDashboardBinding import foundation.e.privacycentralapp.domain.entities.LocationMode import foundation.e.privacycentralapp.domain.entities.QuickPrivacyState Loading Loading @@ -65,6 +67,8 @@ class DashboardFragment : private lateinit var graphHolder: GraphHolder private lateinit var binding: FragmentDashboardBinding private var qpDisabledSnackbar: Snackbar? = null private var updateUIJob: Job? = null override fun onCreate(savedInstanceState: Bundle?) { Loading @@ -79,14 +83,14 @@ class DashboardFragment : when (event) { is DashboardFeature.SingleEvent.NavigateToLocationSingleEvent -> { requireActivity().supportFragmentManager.commit { add<FakeLocationFragment>(R.id.container) replace<FakeLocationFragment>(R.id.container) setReorderingAllowed(true) addToBackStack("dashboard") } } is DashboardFeature.SingleEvent.NavigateToInternetActivityPrivacySingleEvent -> { requireActivity().supportFragmentManager.commit { add<InternetPrivacyFragment>(R.id.container) replace<InternetPrivacyFragment>(R.id.container) setReorderingAllowed(true) addToBackStack("dashboard") } Loading @@ -97,7 +101,7 @@ class DashboardFragment : } DashboardFeature.SingleEvent.NavigateToTrackersSingleEvent -> { requireActivity().supportFragmentManager.commit { add<TrackersFragment>(R.id.container) replace<TrackersFragment>(R.id.container) setReorderingAllowed(true) addToBackStack("dashboard") } Loading Loading @@ -138,6 +142,10 @@ class DashboardFragment : binding.amITracked.container.setOnClickListener { viewModel.submitAction(DashboardFeature.Action.ShowTrackers) } qpDisabledSnackbar = initQuickPrivacySnackbar(binding.root) { viewModel.submitAction(DashboardFeature.Action.CloseQuickPrivacyDisabledMessage) } } override fun onResume() { Loading @@ -149,6 +157,8 @@ class DashboardFragment : } } render(viewModel.dashboardFeature.state.value) viewModel.submitAction(DashboardFeature.Action.FetchStatistics) } Loading @@ -162,6 +172,9 @@ class DashboardFragment : } override fun render(state: State) { if (state.showQuickPrivacyDisabledMessage) qpDisabledSnackbar?.show() else qpDisabledSnackbar?.dismiss() binding.stateLabel.text = getString( when (state.quickPrivacyState) { QuickPrivacyState.DISABLED -> R.string.dashboard_state_title_off Loading app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFeature.kt +15 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import foundation.e.flowmvi.SingleEventProducer import foundation.e.flowmvi.feature.BaseFeature import foundation.e.privacycentralapp.domain.entities.AppWithCounts import foundation.e.privacycentralapp.domain.entities.TrackersPeriodicStatistics import foundation.e.privacycentralapp.domain.usecases.GetQuickPrivacyStateUseCase import foundation.e.privacycentralapp.domain.usecases.TrackersStatisticsUseCase import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.flow Loading Loading @@ -51,6 +52,7 @@ class TrackersFeature( val monthStatistics: TrackersPeriodicStatistics? = null, val yearStatistics: TrackersPeriodicStatistics? = null, val apps: List<AppWithCounts>? = null, val showQuickPrivacyDisabledMessage: Boolean = false ) sealed class SingleEvent { Loading @@ -63,9 +65,11 @@ class TrackersFeature( object InitAction : Action() data class ClickAppAction(val packageName: String) : Action() object FetchStatistics : Action() object CloseQuickPrivacyDisabledMessage : Action() } sealed class Effect { object NoEffect : Effect() data class TrackersStatisticsLoadedEffect( val dayStatistics: TrackersPeriodicStatistics? = null, val monthStatistics: TrackersPeriodicStatistics? = null, Loading @@ -75,14 +79,15 @@ class TrackersFeature( val apps: List<AppWithCounts> ) : Effect() data class OpenAppDetailsEffect(val appDesc: AppWithCounts) : Effect() object QuickPrivacyDisabledWarningEffect : Effect() data class ErrorEffect(val message: String) : Effect() object NewStatisticsAvailablesEffect : Effect() data class ShowQuickPrivacyDisabledMessageEffect(val show: Boolean) : Effect() } companion object { fun create( initialState: State = State(), getQuickPrivacyStateUseCase: GetQuickPrivacyStateUseCase, coroutineScope: CoroutineScope, trackersStatisticsUseCase: TrackersStatisticsUseCase ) = TrackersFeature( Loading @@ -97,6 +102,7 @@ class TrackersFeature( is Effect.AvailableAppsListEffect -> state.copy(apps = effect.apps) is Effect.ErrorEffect -> state is Effect.ShowQuickPrivacyDisabledMessageEffect -> state.copy(showQuickPrivacyDisabledMessage = effect.show) else -> state } }, Loading @@ -106,7 +112,10 @@ class TrackersFeature( flowOf(Effect.NewStatisticsAvailablesEffect), trackersStatisticsUseCase.listenUpdates().map { Effect.NewStatisticsAvailablesEffect } }, getQuickPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map { Effect.ShowQuickPrivacyDisabledMessageEffect(it) }, ) is Action.ClickAppAction -> flowOf( Loading @@ -131,13 +140,16 @@ class TrackersFeature( Effect.AvailableAppsListEffect(it) } ) is Action.CloseQuickPrivacyDisabledMessage -> { getQuickPrivacyStateUseCase.resetQuickPrivacyDisabledMessage() flowOf(Effect.NoEffect) } } }, singleEventProducer = { _, _, effect -> when (effect) { is Effect.ErrorEffect -> SingleEvent.ErrorEvent(effect.message) is Effect.OpenAppDetailsEffect -> SingleEvent.OpenAppDetailsEvent(effect.appDesc) is Effect.QuickPrivacyDisabledWarningEffect -> SingleEvent.ErrorEvent("Enabled Quick Privacy to use functionalities") is Effect.NewStatisticsAvailablesEffect -> SingleEvent.NewStatisticsAvailableSingleEvent else -> null } Loading Loading
app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt +1 −1 Original line number Diff line number Diff line Loading @@ -119,7 +119,7 @@ class DependencyContainer(val app: Application) { } val trackersViewModelFactory by lazy { TrackersViewModelFactory(trackersStatisticsUseCase) TrackersViewModelFactory(getQuickPrivacyStateUseCase, trackersStatisticsUseCase) } val appTrackersViewModelFactory by lazy { Loading
app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt +7 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,10 @@ class TrackersStateUseCase( } fun toggleAppWhitelist(appUid: Int, isWhitelisted: Boolean) { if (!localStateRepository.isQuickPrivacyEnabled) { localStateRepository.setShowQuickPrivacyDisabledMessage(true) } if (appUid == appListsRepository.dummySystemApp.uid) { appListsRepository.getHiddenSystemApps().forEach { blockTrackersPrivacyModule.setWhiteListed(it.uid, isWhitelisted) Loading @@ -89,6 +93,9 @@ class TrackersStateUseCase( } fun blockTracker(appUid: Int, tracker: Tracker, isBlocked: Boolean) { if (!localStateRepository.isQuickPrivacyEnabled) { localStateRepository.setShowQuickPrivacyDisabledMessage(true) } if (appUid == appListsRepository.dummySystemApp.uid) { appListsRepository.getHiddenSystemApps().forEach { blockTrackersPrivacyModule.setWhiteListed(tracker, it.uid, !isBlocked) Loading
app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt +13 −3 Original line number Diff line number Diff line Loading @@ -57,7 +57,8 @@ class DashboardFeature( val trackersCount: Int? = null, val allowedTrackersCount: Int? = null, val dayStatistics: List<Pair<Int, Int>>? = null, val dayLabels: List<String>? = null val dayLabels: List<String>? = null, val showQuickPrivacyDisabledMessage: Boolean = false ) sealed class SingleEvent { Loading @@ -77,6 +78,7 @@ class DashboardFeature( object ShowAppsPermissions : Action() object ShowTrackers : Action() object FetchStatistics : Action() object CloseQuickPrivacyDisabledMessage : Action() } sealed class Effect { Loading @@ -99,6 +101,7 @@ class DashboardFeature( object NewStatisticsAvailablesEffect : Effect() object FirstIPTrackerActivationEffect : Effect() data class LocationHiddenUpdatedEffect(val isLocationHidden: Boolean) : Effect() data class ShowQuickPrivacyDisabledMessageEffect(val show: Boolean) : Effect() } companion object { Loading Loading @@ -129,7 +132,7 @@ class DashboardFeature( isLocationHidden = effect.isLocationHidden ) is Effect.UpdateLocationModeEffect -> state.copy(locationMode = effect.mode) is Effect.ShowQuickPrivacyDisabledMessageEffect -> state.copy(showQuickPrivacyDisabledMessage = effect.show) else -> state } }, Loading Loading @@ -161,7 +164,10 @@ class DashboardFeature( }, getPrivacyStateUseCase.locationMode.map { Effect.UpdateLocationModeEffect(it) } }, getPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map { Effect.ShowQuickPrivacyDisabledMessageEffect(it) }, ) Action.ShowFakeMyLocationAction -> flowOf(Effect.OpenFakeMyLocationEffect) Action.ShowAppsPermissions -> flowOf(Effect.OpenAppsPermissionsEffect) Loading @@ -183,6 +189,10 @@ class DashboardFeature( ) } } is Action.CloseQuickPrivacyDisabledMessage -> { getPrivacyStateUseCase.resetQuickPrivacyDisabledMessage() flowOf(Effect.NoEffect) } } }, singleEventProducer = { _, _, effect -> Loading
app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt +17 −4 Original line number Diff line number Diff line Loading @@ -26,15 +26,17 @@ import android.widget.Toast import androidx.core.content.ContextCompat.getColor import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.fragment.app.add import androidx.fragment.app.commit import androidx.fragment.app.replace import androidx.lifecycle.lifecycleScope import com.google.android.material.snackbar.Snackbar import foundation.e.flowmvi.MVIView import foundation.e.privacycentralapp.DependencyContainer import foundation.e.privacycentralapp.PrivacyCentralApplication import foundation.e.privacycentralapp.R import foundation.e.privacycentralapp.common.GraphHolder import foundation.e.privacycentralapp.common.NavToolbarFragment import foundation.e.privacycentralapp.common.initQuickPrivacySnackbar import foundation.e.privacycentralapp.databinding.FragmentDashboardBinding import foundation.e.privacycentralapp.domain.entities.LocationMode import foundation.e.privacycentralapp.domain.entities.QuickPrivacyState Loading Loading @@ -65,6 +67,8 @@ class DashboardFragment : private lateinit var graphHolder: GraphHolder private lateinit var binding: FragmentDashboardBinding private var qpDisabledSnackbar: Snackbar? = null private var updateUIJob: Job? = null override fun onCreate(savedInstanceState: Bundle?) { Loading @@ -79,14 +83,14 @@ class DashboardFragment : when (event) { is DashboardFeature.SingleEvent.NavigateToLocationSingleEvent -> { requireActivity().supportFragmentManager.commit { add<FakeLocationFragment>(R.id.container) replace<FakeLocationFragment>(R.id.container) setReorderingAllowed(true) addToBackStack("dashboard") } } is DashboardFeature.SingleEvent.NavigateToInternetActivityPrivacySingleEvent -> { requireActivity().supportFragmentManager.commit { add<InternetPrivacyFragment>(R.id.container) replace<InternetPrivacyFragment>(R.id.container) setReorderingAllowed(true) addToBackStack("dashboard") } Loading @@ -97,7 +101,7 @@ class DashboardFragment : } DashboardFeature.SingleEvent.NavigateToTrackersSingleEvent -> { requireActivity().supportFragmentManager.commit { add<TrackersFragment>(R.id.container) replace<TrackersFragment>(R.id.container) setReorderingAllowed(true) addToBackStack("dashboard") } Loading Loading @@ -138,6 +142,10 @@ class DashboardFragment : binding.amITracked.container.setOnClickListener { viewModel.submitAction(DashboardFeature.Action.ShowTrackers) } qpDisabledSnackbar = initQuickPrivacySnackbar(binding.root) { viewModel.submitAction(DashboardFeature.Action.CloseQuickPrivacyDisabledMessage) } } override fun onResume() { Loading @@ -149,6 +157,8 @@ class DashboardFragment : } } render(viewModel.dashboardFeature.state.value) viewModel.submitAction(DashboardFeature.Action.FetchStatistics) } Loading @@ -162,6 +172,9 @@ class DashboardFragment : } override fun render(state: State) { if (state.showQuickPrivacyDisabledMessage) qpDisabledSnackbar?.show() else qpDisabledSnackbar?.dismiss() binding.stateLabel.text = getString( when (state.quickPrivacyState) { QuickPrivacyState.DISABLED -> R.string.dashboard_state_title_off Loading
app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFeature.kt +15 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import foundation.e.flowmvi.SingleEventProducer import foundation.e.flowmvi.feature.BaseFeature import foundation.e.privacycentralapp.domain.entities.AppWithCounts import foundation.e.privacycentralapp.domain.entities.TrackersPeriodicStatistics import foundation.e.privacycentralapp.domain.usecases.GetQuickPrivacyStateUseCase import foundation.e.privacycentralapp.domain.usecases.TrackersStatisticsUseCase import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.flow Loading Loading @@ -51,6 +52,7 @@ class TrackersFeature( val monthStatistics: TrackersPeriodicStatistics? = null, val yearStatistics: TrackersPeriodicStatistics? = null, val apps: List<AppWithCounts>? = null, val showQuickPrivacyDisabledMessage: Boolean = false ) sealed class SingleEvent { Loading @@ -63,9 +65,11 @@ class TrackersFeature( object InitAction : Action() data class ClickAppAction(val packageName: String) : Action() object FetchStatistics : Action() object CloseQuickPrivacyDisabledMessage : Action() } sealed class Effect { object NoEffect : Effect() data class TrackersStatisticsLoadedEffect( val dayStatistics: TrackersPeriodicStatistics? = null, val monthStatistics: TrackersPeriodicStatistics? = null, Loading @@ -75,14 +79,15 @@ class TrackersFeature( val apps: List<AppWithCounts> ) : Effect() data class OpenAppDetailsEffect(val appDesc: AppWithCounts) : Effect() object QuickPrivacyDisabledWarningEffect : Effect() data class ErrorEffect(val message: String) : Effect() object NewStatisticsAvailablesEffect : Effect() data class ShowQuickPrivacyDisabledMessageEffect(val show: Boolean) : Effect() } companion object { fun create( initialState: State = State(), getQuickPrivacyStateUseCase: GetQuickPrivacyStateUseCase, coroutineScope: CoroutineScope, trackersStatisticsUseCase: TrackersStatisticsUseCase ) = TrackersFeature( Loading @@ -97,6 +102,7 @@ class TrackersFeature( is Effect.AvailableAppsListEffect -> state.copy(apps = effect.apps) is Effect.ErrorEffect -> state is Effect.ShowQuickPrivacyDisabledMessageEffect -> state.copy(showQuickPrivacyDisabledMessage = effect.show) else -> state } }, Loading @@ -106,7 +112,10 @@ class TrackersFeature( flowOf(Effect.NewStatisticsAvailablesEffect), trackersStatisticsUseCase.listenUpdates().map { Effect.NewStatisticsAvailablesEffect } }, getQuickPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map { Effect.ShowQuickPrivacyDisabledMessageEffect(it) }, ) is Action.ClickAppAction -> flowOf( Loading @@ -131,13 +140,16 @@ class TrackersFeature( Effect.AvailableAppsListEffect(it) } ) is Action.CloseQuickPrivacyDisabledMessage -> { getQuickPrivacyStateUseCase.resetQuickPrivacyDisabledMessage() flowOf(Effect.NoEffect) } } }, singleEventProducer = { _, _, effect -> when (effect) { is Effect.ErrorEffect -> SingleEvent.ErrorEvent(effect.message) is Effect.OpenAppDetailsEffect -> SingleEvent.OpenAppDetailsEvent(effect.appDesc) is Effect.QuickPrivacyDisabledWarningEffect -> SingleEvent.ErrorEvent("Enabled Quick Privacy to use functionalities") is Effect.NewStatisticsAvailablesEffect -> SingleEvent.NewStatisticsAvailableSingleEvent else -> null } Loading