aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/foundation/e/advancedprivacy/features
diff options
context:
space:
mode:
authorGuillaume Jacquart <guillaume.jacquart@hoodbrains.com>2023-06-09 06:34:09 +0000
committerGuillaume Jacquart <guillaume.jacquart@hoodbrains.com>2023-06-09 06:34:09 +0000
commit74b9860784913c097ae59e58b0958da7744ebc2e (patch)
tree29f4f655f6ac71a0da40bc50d332db3c2c75f634 /app/src/main/java/foundation/e/advancedprivacy/features
parent045261f84c1ac5ba4c8ed0f3dabd4ea53a1155c9 (diff)
downloadadvanced-privacy-74b9860784913c097ae59e58b0958da7744ebc2e.tar.gz
1227: use navigation graph component, avoid view (fragments) duplications
Diffstat (limited to 'app/src/main/java/foundation/e/advancedprivacy/features')
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt69
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardViewModel.kt25
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyFragment.kt3
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt3
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt32
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt11
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/trackers/apptrackers/AppTrackersFragment.kt26
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,