diff options
author | Guillaume Jacquart <guillaume.jacquart@hoodbrains.com> | 2023-06-09 06:34:09 +0000 |
---|---|---|
committer | Guillaume Jacquart <guillaume.jacquart@hoodbrains.com> | 2023-06-09 06:34:09 +0000 |
commit | 74b9860784913c097ae59e58b0958da7744ebc2e (patch) | |
tree | 29f4f655f6ac71a0da40bc50d332db3c2c75f634 /app/src/main/java/foundation/e/advancedprivacy/features | |
parent | 045261f84c1ac5ba4c8ed0f3dabd4ea53a1155c9 (diff) | |
download | advanced-privacy-74b9860784913c097ae59e58b0958da7744ebc2e.tar.gz |
1227: use navigation graph component, avoid view (fragments) duplications
Diffstat (limited to 'app/src/main/java/foundation/e/advancedprivacy/features')
7 files changed, 43 insertions, 126 deletions
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt index 02fd1ad..6ca9792 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt @@ -1,4 +1,5 @@ /* + * Copyright (C) 2023 MURENA SAS * Copyright (C) 2021 E FOUNDATION * * This program is free software: you can redistribute it and/or modify @@ -17,21 +18,19 @@ package foundation.e.advancedprivacy.features.dashboard -import android.content.Intent import android.os.Bundle import android.text.Html import android.text.Html.FROM_HTML_MODE_LEGACY import android.view.View import android.widget.Toast import androidx.core.content.ContextCompat.getColor -import androidx.core.os.bundleOf import androidx.core.view.isVisible -import androidx.fragment.app.commit -import androidx.fragment.app.replace import androidx.fragment.app.viewModels import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle +import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs import foundation.e.advancedprivacy.AdvancedPrivacyApplication import foundation.e.advancedprivacy.DependencyContainer import foundation.e.advancedprivacy.R @@ -44,20 +43,9 @@ import foundation.e.advancedprivacy.domain.entities.QuickPrivacyState import foundation.e.advancedprivacy.domain.entities.TrackerMode import foundation.e.advancedprivacy.features.dashboard.DashboardViewModel.Action import foundation.e.advancedprivacy.features.dashboard.DashboardViewModel.SingleEvent -import foundation.e.advancedprivacy.features.internetprivacy.InternetPrivacyFragment -import foundation.e.advancedprivacy.features.location.FakeLocationFragment -import foundation.e.advancedprivacy.features.trackers.TrackersFragment -import foundation.e.advancedprivacy.features.trackers.apptrackers.AppTrackersFragment import kotlinx.coroutines.launch class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) { - companion object { - private const val PARAM_HIGHLIGHT_INDEX = "PARAM_HIGHLIGHT_INDEX" - fun buildArgs(highlightIndex: Int): Bundle = bundleOf( - PARAM_HIGHLIGHT_INDEX to highlightIndex - ) - } - private val dependencyContainer: DependencyContainer by lazy { (this.requireActivity().application as AdvancedPrivacyApplication).dependencyContainer } @@ -73,10 +61,11 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) { private var highlightIndexOnStart: Int? = null + private val args: DashboardFragmentArgs by navArgs() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - highlightIndexOnStart = arguments?.getInt(PARAM_HIGHLIGHT_INDEX, -1) + highlightIndexOnStart = args.highlightLeaks } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -134,45 +123,6 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.singleEvents.collect { event -> when (event) { - is SingleEvent.NavigateToLocationSingleEvent -> { - requireActivity().supportFragmentManager.commit { - replace<FakeLocationFragment>(R.id.container) - setReorderingAllowed(true) - addToBackStack("dashboard") - } - } - is SingleEvent.NavigateToInternetActivityPrivacySingleEvent -> { - requireActivity().supportFragmentManager.commit { - replace<InternetPrivacyFragment>(R.id.container) - setReorderingAllowed(true) - addToBackStack("dashboard") - } - } - is SingleEvent.NavigateToPermissionsSingleEvent -> { - val intent = Intent("android.intent.action.MANAGE_PERMISSIONS") - requireActivity().startActivity(intent) - } - SingleEvent.NavigateToTrackersSingleEvent -> { - requireActivity().supportFragmentManager.commit { - replace<TrackersFragment>(R.id.container) - setReorderingAllowed(true) - addToBackStack("dashboard") - } - } - is SingleEvent.NavigateToAppDetailsEvent -> { - requireActivity().supportFragmentManager.commit { - replace<AppTrackersFragment>( - R.id.container, - args = AppTrackersFragment.buildArgs( - event.appDesc.label.toString(), - event.appDesc.packageName, - event.appDesc.uid - ) - ) - setReorderingAllowed(true) - addToBackStack("dashboard") - } - } is SingleEvent.ToastMessageSingleEvent -> Toast.makeText( requireContext(), @@ -183,6 +133,11 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) { } } } + viewLifecycleOwner.lifecycleScope.launch { + viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.navigate.collect(findNavController()::navigate) + } + } viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { @@ -191,10 +146,6 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) { } } - override fun getTitle(): String { - return getString(R.string.dashboard_title) - } - private fun render(state: DashboardState) { binding.stateLabel.text = getString( when (state.quickPrivacyState) { diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardViewModel.kt b/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardViewModel.kt index cc1263b..8259c89 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardViewModel.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardViewModel.kt @@ -1,5 +1,5 @@ /* -* Copyright (C) 2023 MURENA SAS + * Copyright (C) 2023 MURENA SAS * Copyright (C) 2021 E FOUNDATION * * This program is free software: you can redistribute it and/or modify @@ -21,10 +21,10 @@ package foundation.e.advancedprivacy.features.dashboard import androidx.annotation.StringRes import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import androidx.navigation.NavDirections import foundation.e.advancedprivacy.R import foundation.e.advancedprivacy.domain.usecases.GetQuickPrivacyStateUseCase import foundation.e.advancedprivacy.domain.usecases.TrackersStatisticsUseCase -import foundation.e.privacymodules.permissions.data.ApplicationDescription import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow @@ -51,6 +51,8 @@ class DashboardViewModel( private val _singleEvents = MutableSharedFlow<SingleEvent>() val singleEvents = _singleEvents.asSharedFlow() + private val _navigate = MutableSharedFlow<NavDirections>() + val navigate = _navigate.asSharedFlow() init { viewModelScope.launch(Dispatchers.IO) { trackersStatisticsUseCase.initAppList() } } @@ -98,13 +100,13 @@ class DashboardViewModel( is Action.ToggleIpScrambling -> getPrivacyStateUseCase.toggleIpScrambling(action.enabled) is Action.ShowFakeMyLocationAction -> - _singleEvents.emit(SingleEvent.NavigateToLocationSingleEvent) + _navigate.emit(DashboardFragmentDirections.gotoFakeLocationFragment()) is Action.ShowAppsPermissions -> - _singleEvents.emit(SingleEvent.NavigateToPermissionsSingleEvent) + _navigate.emit(DashboardFragmentDirections.gotoSettingsPermissionsActivity()) is Action.ShowInternetActivityPrivacyAction -> - _singleEvents.emit(SingleEvent.NavigateToInternetActivityPrivacySingleEvent) + _navigate.emit(DashboardFragmentDirections.gotoInternetPrivacyFragment()) is Action.ShowTrackers -> - _singleEvents.emit(SingleEvent.NavigateToTrackersSingleEvent) + _navigate.emit(DashboardFragmentDirections.gotoTrackersFragment()) is Action.ShowMostLeakedApp -> actionShowMostLeakedApp() } } @@ -127,19 +129,14 @@ class DashboardViewModel( } private suspend fun actionShowMostLeakedApp() = withContext(Dispatchers.IO) { - _singleEvents.emit( + _navigate.emit( trackersStatisticsUseCase.getMostLeakedApp()?.let { - SingleEvent.NavigateToAppDetailsEvent(appDesc = it) - } ?: SingleEvent.NavigateToTrackersSingleEvent + DashboardFragmentDirections.gotoAppTrackersFragment(appUid = it.uid) + } ?: DashboardFragmentDirections.gotoTrackersFragment() ) } sealed class SingleEvent { - object NavigateToTrackersSingleEvent : SingleEvent() - object NavigateToInternetActivityPrivacySingleEvent : SingleEvent() - object NavigateToLocationSingleEvent : SingleEvent() - object NavigateToPermissionsSingleEvent : SingleEvent() - data class NavigateToAppDetailsEvent(val appDesc: ApplicationDescription) : SingleEvent() data class ToastMessageSingleEvent( @StringRes val message: Int, val args: List<Any> = emptyList() diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyFragment.kt index 07da82a..35fc1d4 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyFragment.kt @@ -1,4 +1,5 @@ /* + * Copyright (C) 2023 MURENA SAS * Copyright (C) 2021 E FOUNDATION * * This program is free software: you can redistribute it and/or modify @@ -141,8 +142,6 @@ class InternetPrivacyFragment : NavToolbarFragment(R.layout.fragment_internet_ac } } - override fun getTitle(): String = getString(R.string.ipscrambling_title) - private fun render(state: InternetPrivacyState) { binding.radioUseHiddenIp.radiobutton.apply { isChecked = state.mode in listOf( diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt index 9934713..09409f2 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt @@ -1,4 +1,5 @@ /* + * Copyright (C) 2023 MURENA SAS * Copyright (C) 2021 E FOUNDATION * * This program is free software: you can redistribute it and/or modify @@ -100,8 +101,6 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location) Mapbox.getInstance(requireContext(), getString(R.string.mapbox_key), WellKnownTileServer.Mapbox) } - override fun getTitle(): String = getString(R.string.location_title) - private fun displayToast(message: String) { Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT) .show() diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt index 3e17334..f486114 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt @@ -1,5 +1,6 @@ /* - * Copyright (C) 2021 E FOUNDATION, 2022 MURENA SAS + * Copyright (C) 2022-2023 MURENA SAS + * Copyright (C) 2021 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 @@ -30,12 +31,11 @@ import android.view.View import android.widget.Toast import androidx.core.content.ContextCompat import androidx.core.view.isVisible -import androidx.fragment.app.commit -import androidx.fragment.app.replace import androidx.fragment.app.viewModels import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import foundation.e.advancedprivacy.AdvancedPrivacyApplication import foundation.e.advancedprivacy.DependencyContainer @@ -47,11 +47,9 @@ import foundation.e.advancedprivacy.common.setToolTipForAsterisk import foundation.e.advancedprivacy.databinding.FragmentTrackersBinding import foundation.e.advancedprivacy.databinding.TrackersItemGraphBinding import foundation.e.advancedprivacy.domain.entities.TrackersPeriodicStatistics -import foundation.e.advancedprivacy.features.trackers.apptrackers.AppTrackersFragment import kotlinx.coroutines.launch -class TrackersFragment : - NavToolbarFragment(R.layout.fragment_trackers) { +class TrackersFragment : NavToolbarFragment(R.layout.fragment_trackers) { private val dependencyContainer: DependencyContainer by lazy { (this.requireActivity().application as AdvancedPrivacyApplication).dependencyContainer @@ -134,20 +132,6 @@ class TrackersFragment : is TrackersViewModel.SingleEvent.ErrorEvent -> { displayToast(event.error) } - is TrackersViewModel.SingleEvent.OpenAppDetailsEvent -> { - requireActivity().supportFragmentManager.commit { - replace<AppTrackersFragment>( - R.id.container, - args = AppTrackersFragment.buildArgs( - event.appDesc.label.toString(), - event.appDesc.packageName, - event.appDesc.uid - ) - ) - setReorderingAllowed(true) - addToBackStack("apptrackers") - } - } is TrackersViewModel.SingleEvent.OpenUrl -> { try { startActivity(Intent(Intent.ACTION_VIEW, event.url)) @@ -166,6 +150,12 @@ class TrackersFragment : viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.navigate.collect(findNavController()::navigate) + } + } + + viewLifecycleOwner.lifecycleScope.launch { + viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.doOnStartedState() } } @@ -176,8 +166,6 @@ class TrackersFragment : .show() } - override fun getTitle() = getString(R.string.trackers_title) - private fun render(state: TrackersState) { state.dayStatistics?.let { renderGraph(it, dayGraphHolder!!, binding.graphDay) } state.monthStatistics?.let { renderGraph(it, monthGraphHolder!!, binding.graphMonth) } diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt index bcb4df8..8a5d0f0 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt @@ -1,5 +1,6 @@ /* - * Copyright (C) 2021 E FOUNDATION, 2022 MURENA SAS + * Copyright (C) 2022-2023 MURENA SAS + * Copyright (C) 2021 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 @@ -20,7 +21,7 @@ package foundation.e.advancedprivacy.features.trackers import android.net.Uri import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import foundation.e.advancedprivacy.domain.entities.AppWithCounts +import androidx.navigation.NavDirections import foundation.e.advancedprivacy.domain.usecases.TrackersStatisticsUseCase import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow @@ -48,6 +49,9 @@ class TrackersViewModel( private val _singleEvents = MutableSharedFlow<SingleEvent>() val singleEvents = _singleEvents.asSharedFlow() + private val _navigate = MutableSharedFlow<NavDirections>() + val navigate = _navigate.asSharedFlow() + suspend fun doOnStartedState() = withContext(Dispatchers.IO) { merge( trackersStatisticsUseCase.listenUpdates().map { @@ -78,13 +82,12 @@ class TrackersViewModel( private suspend fun actionClickApp(action: Action.ClickAppAction) { state.value.apps?.find { it.uid == action.appUid }?.let { - _singleEvents.emit(SingleEvent.OpenAppDetailsEvent(it)) + _navigate.emit(TrackersFragmentDirections.gotoAppTrackersFragment(appUid = it.uid)) } } sealed class SingleEvent { data class ErrorEvent(val error: String) : SingleEvent() - data class OpenAppDetailsEvent(val appDesc: AppWithCounts) : SingleEvent() data class OpenUrl(val url: Uri) : SingleEvent() } diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/apptrackers/AppTrackersFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/apptrackers/AppTrackersFragment.kt index 2bb53d6..457a02a 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/apptrackers/AppTrackersFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/apptrackers/AppTrackersFragment.kt @@ -23,7 +23,6 @@ import android.content.Intent import android.os.Bundle import android.view.View import android.widget.Toast -import androidx.core.os.bundleOf import androidx.core.view.isVisible import androidx.fragment.app.viewModels import androidx.lifecycle.Lifecycle @@ -39,19 +38,6 @@ import foundation.e.advancedprivacy.databinding.ApptrackersFragmentBinding import kotlinx.coroutines.launch class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) { - companion object { - private val PARAM_LABEL = "PARAM_LABEL" - private val PARAM_PACKAGE_NAME = "PARAM_PACKAGE_NAME" - - const val PARAM_APP_UID = "PARAM_APP_UID" - - fun buildArgs(label: String, packageName: String, appUid: Int): Bundle = bundleOf( - PARAM_LABEL to label, - PARAM_PACKAGE_NAME to packageName, - PARAM_APP_UID to appUid - ) - } - private val dependencyContainer: DependencyContainer by lazy { (this.requireActivity().application as AdvancedPrivacyApplication).dependencyContainer } @@ -63,13 +49,8 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) { private var _binding: ApptrackersFragmentBinding? = null private val binding get() = _binding!! - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - if (arguments == null || - requireArguments().getInt(PARAM_APP_UID, Int.MIN_VALUE) == Int.MIN_VALUE - ) { - activity?.supportFragmentManager?.popBackStack() - } + override fun getTitle(): CharSequence { + return "" } private fun displayToast(message: String) { @@ -77,8 +58,6 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) { .show() } - override fun getTitle(): String = requireArguments().getString(PARAM_LABEL) ?: "" - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) _binding = ApptrackersFragmentBinding.bind(view) @@ -144,6 +123,7 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) { } private fun render(state: AppTrackersState) { + setTitle(state.appDesc?.label) binding.trackersCountSummary.text = if (state.getTrackersCount() == 0) "" else getString( R.string.apptrackers_trackers_count_summary, |