summaryrefslogtreecommitdiff
path: root/app/src/main/java
diff options
context:
space:
mode:
authorjacquarg <guillaume.jacquart@hoodbrains.com>2021-10-28 22:35:19 +0200
committerjacquarg <guillaume.jacquart@hoodbrains.com>2021-10-28 22:35:19 +0200
commit9035bac3ff801bb982bf54b02c0e9850d6afbc22 (patch)
tree5ffc2f5440ca70272bc9f4114d1a1794f5203152 /app/src/main/java
parentc7f46a5deb9a4b5707440ea5dd125c25584e6469 (diff)
Update dashboard UI and feature
Diffstat (limited to 'app/src/main/java')
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt16
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt7
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/entities/InternetPrivacyMode.kt22
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/entities/LocationMode.kt22
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/usecases/GetQuickPrivacyStateUseCase.kt8
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/dummy/CityDataSource.kt1
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt10
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/dummy/Extensions.kt2
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFeature.kt186
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt230
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardViewModel.kt18
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/QuickProtectionFragment.kt2
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt13
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt4
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt2
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt4
16 files changed, 344 insertions, 203 deletions
diff --git a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt
index 1ab848c..17967db 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt
@@ -20,6 +20,9 @@ package foundation.e.privacycentralapp
import android.app.Application
import android.content.Context
import android.os.Process
+import foundation.e.privacycentralapp.data.repositories.LocalStateRepository
+import foundation.e.privacycentralapp.domain.usecases.GetQuickPrivacyStateUseCase
+import foundation.e.privacycentralapp.features.dashboard.DashBoardViewModelFactory
import foundation.e.privacycentralapp.features.internetprivacy.InternetPrivacyViewModelFactory
import foundation.e.privacycentralapp.features.location.FakeLocationViewModelFactory
import foundation.e.privacycentralapp.features.location.LocationApiDelegate
@@ -40,6 +43,7 @@ class DependencyContainer constructor(val app: Application) {
val context: Context by lazy { app.applicationContext }
+ // Drivers
private val fakeLocationModule: IFakeLocation by lazy { FakeLocation(app.applicationContext) }
private val permissionsModule by lazy { PermissionsPrivacyModule(app.applicationContext) }
private val ipScramblerModule: IIpScramblerModule by lazy { IpScramblerModule(app.applicationContext) }
@@ -57,6 +61,18 @@ class DependencyContainer constructor(val app: Application) {
LocationApiDelegate(fakeLocationModule, permissionsModule, appDesc)
}
+ // Repositories
+ private val localStateRepository by lazy { LocalStateRepository(context) }
+
+ // Usecases
+ private val getQuickPrivacyStateUseCase by lazy {
+ GetQuickPrivacyStateUseCase(localStateRepository)
+ }
+
+ val dashBoardViewModelFactory by lazy {
+ DashBoardViewModelFactory(getQuickPrivacyStateUseCase)
+ }
+
val fakeLocationViewModelFactory by lazy {
FakeLocationViewModelFactory(locationApi)
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt
index 390044b..3cabae7 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt
@@ -31,10 +31,7 @@ class LocalStateRepository(context: Context) {
get() = sharedPref.getBoolean(KEY_QUICK_PRIVACY, false)
set(value) = set(KEY_QUICK_PRIVACY, value)
-
private fun set(key: String, value: Boolean) {
- sharedPref.edit().putBoolean(key, value).apply()
+ sharedPref.edit().putBoolean(key, value).commit()
}
-
-
-} \ No newline at end of file
+}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/entities/InternetPrivacyMode.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/entities/InternetPrivacyMode.kt
new file mode 100644
index 0000000..879c435
--- /dev/null
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/entities/InternetPrivacyMode.kt
@@ -0,0 +1,22 @@
+/*
+ * 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
+ * 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/>.
+ */
+
+package foundation.e.privacycentralapp.domain.entities
+
+enum class InternetPrivacyMode {
+ REAL_IP, HIDE_IP
+}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/entities/LocationMode.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/entities/LocationMode.kt
new file mode 100644
index 0000000..dbb9b0a
--- /dev/null
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/entities/LocationMode.kt
@@ -0,0 +1,22 @@
+/*
+ * 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
+ * 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/>.
+ */
+
+package foundation.e.privacycentralapp.domain.entities
+
+enum class LocationMode {
+ REAL_LOCATION, RANDOM_LOCATION, CUSTOM_LOCATION
+}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/GetQuickPrivacyStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/GetQuickPrivacyStateUseCase.kt
index 746ead4..20ac0d9 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/GetQuickPrivacyStateUseCase.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/GetQuickPrivacyStateUseCase.kt
@@ -19,6 +19,12 @@ package foundation.e.privacycentralapp.domain.usecases
import foundation.e.privacycentralapp.data.repositories.LocalStateRepository
-class GetQuickPrivacyStateUseCase(localStateRepository: LocalStateRepository) {
+class GetQuickPrivacyStateUseCase(private val localStateRepository: LocalStateRepository) {
val isQuickPrivacyEnabled = localStateRepository.isQuickPrivacyEnabled
+
+ fun toggle(): Boolean {
+ val newState = !localStateRepository.isQuickPrivacyEnabled
+ localStateRepository.isQuickPrivacyEnabled = newState
+ return newState
+ }
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/dummy/CityDataSource.kt b/app/src/main/java/foundation/e/privacycentralapp/dummy/CityDataSource.kt
index 3bb2f12..988c7f4 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/dummy/CityDataSource.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/dummy/CityDataSource.kt
@@ -17,6 +17,7 @@
package foundation.e.privacycentralapp.dummy
+import foundation.e.privacycentralapp.domain.entities.LocationMode
import kotlin.random.Random
data class City(val name: String, val latitude: Double, val longitude: Double) {
diff --git a/app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt b/app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt
index fe61354..246854b 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt
@@ -18,6 +18,8 @@
package foundation.e.privacycentralapp.dummy
import foundation.e.privacycentralapp.R
+import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
+import foundation.e.privacycentralapp.domain.entities.LocationMode
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlin.random.Random
@@ -52,14 +54,6 @@ data class Permission(
val packagesAllowed: Set<String> = emptySet()
)
-enum class LocationMode {
- REAL_LOCATION, RANDOM_LOCATION, CUSTOM_LOCATION
-}
-
-enum class InternetPrivacyMode {
- REAL_IP, HIDE_IP
-}
-
data class Location(val mode: LocationMode, val latitude: Double, val longitude: Double)
object DummyDataSource {
diff --git a/app/src/main/java/foundation/e/privacycentralapp/dummy/Extensions.kt b/app/src/main/java/foundation/e/privacycentralapp/dummy/Extensions.kt
index 133ad84..91a52ca 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/dummy/Extensions.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/dummy/Extensions.kt
@@ -19,6 +19,8 @@ package foundation.e.privacycentralapp.dummy
import android.content.Context
import foundation.e.privacycentralapp.R
+import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
+import foundation.e.privacycentralapp.domain.entities.LocationMode
fun LocationMode.mapToString(context: Context): String = when (this) {
LocationMode.REAL_LOCATION -> context.getString(R.string.real_location_mode)
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 c26fce1..a461b65 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
@@ -22,15 +22,11 @@ import foundation.e.flowmvi.Actor
import foundation.e.flowmvi.Reducer
import foundation.e.flowmvi.SingleEventProducer
import foundation.e.flowmvi.feature.BaseFeature
-import foundation.e.privacycentralapp.dummy.DummyDataSource
-import foundation.e.privacycentralapp.dummy.InternetPrivacyMode
-import foundation.e.privacycentralapp.dummy.LocationMode
-import foundation.e.privacycentralapp.dummy.TrackersDataSource
+import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
+import foundation.e.privacycentralapp.domain.entities.LocationMode
+import foundation.e.privacycentralapp.domain.usecases.GetQuickPrivacyStateUseCase
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.merge
// Define a state machine for Dashboard Feature
class DashboardFeature(
@@ -46,20 +42,23 @@ class DashboardFeature(
initialState, actor, reducer, coroutineScope, { message -> Log.d("DashboardFeature", message) },
singleEventProducer
) {
- sealed class State {
- object InitialState : State()
- object LoadingDashboardState : State()
- data class DashboardState(
- val trackersCount: Int,
- val activeTrackersCount: Int,
- val totalApps: Int,
- val permissionCount: Int,
- val appsUsingLocationPerm: Int,
- val locationMode: LocationMode,
- val internetPrivacyMode: InternetPrivacyMode
+ sealed class State() {
+ object LoadingState : State()
+ data class DisabledState(
+ val totalGraph: Int = 230,
+ // val graphData
+ val trackersCount: Int = 77,
+ val activeTrackersCount: Int = 22
+ ) : State()
+ data class EnabledState(
+ val isAllTrackersBlocked: Boolean = false,
+ val locationMode: LocationMode = LocationMode.CUSTOM_LOCATION,
+ val internetPrivacyMode: InternetPrivacyMode,
+ val totalGraph: Int = 150,
+ // val graphData
+ val trackersCount: Int = 80,
+ val activeTrackersCount: Int = 10
) : State()
-
- object QuickProtectionState : State()
}
sealed class SingleEvent {
@@ -71,9 +70,10 @@ class DashboardFeature(
}
sealed class Action {
- object ShowQuickPrivacyProtectionInfoAction : Action()
- object ObserveDashboardAction : Action()
- object ShowDashboardAction : Action()
+ object TogglePrivacyAction : Action()
+ // object ShowQuickPrivacyProtectionInfoAction : Action()
+ // object ObserveDashboardAction : Action()
+ // object ShowDashboardAction : Action()
object ShowFakeMyLocationAction : Action()
object ShowInternetActivityPrivacyAction : Action()
object ShowAppsPermissions : Action()
@@ -81,6 +81,8 @@ class DashboardFeature(
}
sealed class Effect {
+ data class UpdateStateEffect(val isEnabled: Boolean) : Effect()
+
object OpenQuickPrivacyProtectionEffect : Effect()
data class OpenDashboardEffect(
val trackersCount: Int,
@@ -98,6 +100,7 @@ class DashboardFeature(
data class UpdateLocationModeEffect(val mode: LocationMode) : Effect()
data class UpdateInternetActivityModeEffect(val mode: InternetPrivacyMode) : Effect()
data class UpdateAppsUsingLocationPermEffect(val apps: Int) : Effect()
+
object OpenFakeMyLocationEffect : Effect()
object OpenInternetActivityPrivacyEffect : Effect()
object OpenAppsPermissionsEffect : Effect()
@@ -105,14 +108,38 @@ class DashboardFeature(
}
companion object {
- fun create(initialState: State, coroutineScope: CoroutineScope): DashboardFeature =
+ fun create(
+ coroutineScope: CoroutineScope,
+ getPrivacyStateUseCase: GetQuickPrivacyStateUseCase
+ ): DashboardFeature =
DashboardFeature(
- initialState,
+ initialState = State.DisabledState(),
coroutineScope,
reducer = { state, effect ->
- when (effect) {
- Effect.OpenQuickPrivacyProtectionEffect -> State.QuickProtectionState
- is Effect.OpenDashboardEffect -> State.DashboardState(
+ if (state is State.LoadingState) state
+ else when (effect) {
+ is Effect.UpdateStateEffect -> when {
+ effect.isEnabled && state is State.EnabledState
+ || !effect.isEnabled && state is State.DisabledState -> state
+ effect.isEnabled && state is State.DisabledState -> State.EnabledState(
+ isAllTrackersBlocked = false,
+ locationMode = LocationMode.REAL_LOCATION,
+ internetPrivacyMode = InternetPrivacyMode.REAL_IP,
+ totalGraph = state.totalGraph,
+ // val graphData
+ trackersCount = state.trackersCount,
+ activeTrackersCount = state.activeTrackersCount
+ )
+ !effect.isEnabled && state is State.EnabledState -> State.DisabledState(
+ totalGraph = state.totalGraph,
+ // val graphData
+ trackersCount = state.trackersCount,
+ activeTrackersCount = state.activeTrackersCount
+ )
+ else -> state
+ }
+
+ /*is Effect.OpenDashboardEffect -> State.DashboardState(
effect.trackersCount,
effect.activeTrackersCount,
effect.totalApps,
@@ -120,46 +147,57 @@ class DashboardFeature(
effect.appsUsingLocationPerm,
effect.locationMode,
effect.internetPrivacyMode
- )
- Effect.LoadingDashboardEffect -> {
- if (state is State.InitialState) {
- State.LoadingDashboardState
- } else state
- }
- is Effect.UpdateActiveTrackersCountEffect -> {
- if (state is State.DashboardState) {
- state.copy(activeTrackersCount = effect.count)
- } else state
- }
- is Effect.UpdateTotalTrackersCountEffect -> {
- if (state is State.DashboardState) {
- state.copy(trackersCount = effect.count)
- } else state
- }
- is Effect.UpdateInternetActivityModeEffect -> {
- if (state is State.DashboardState) {
- state.copy(internetPrivacyMode = effect.mode)
- } else state
- }
- is Effect.UpdateLocationModeEffect -> {
- if (state is State.DashboardState) {
- state.copy(locationMode = effect.mode)
+ )
+ Effect.LoadingDashboardEffect -> {
+ if (state is State.InitialState) {
+ State.LoadingDashboardState
+ } else state
+ }
+ is Effect.UpdateActiveTrackersCountEffect -> {
+ if (state is State.DashboardState) {
+ state.copy(activeTrackersCount = effect.count)
+ } else state
+ }
+ is Effect.UpdateTotalTrackersCountEffect -> {
+ if (state is State.DashboardState) {
+ state.copy(trackersCount = effect.count)
+ } else state
+ }
+ is Effect.UpdateInternetActivityModeEffect -> {
+ if (state is State.DashboardState) {
+ state.copy(internetPrivacyMode = effect.mode)
+ } else state
+ }
+ is Effect.UpdateLocationModeEffect -> {
+ if (state is State.DashboardState) {
+ state.copy(locationMode = effect.mode)
+ } else state
+ }
+ is Effect.UpdateAppsUsingLocationPermEffect -> if (state is State.DashboardState) {
+ state.copy(appsUsingLocationPerm = effect.apps)
} else state
- }
- is Effect.UpdateAppsUsingLocationPermEffect -> if (state is State.DashboardState) {
- state.copy(appsUsingLocationPerm = effect.apps)
- } else state
- Effect.OpenFakeMyLocationEffect -> state
- Effect.OpenAppsPermissionsEffect -> state
- Effect.OpenInternetActivityPrivacyEffect -> state
- Effect.OpenTrackersEffect -> state
+ Effect.OpenFakeMyLocationEffect -> state
+ Effect.OpenAppsPermissionsEffect -> state
+ Effect.OpenInternetActivityPrivacyEffect -> state
+ Effect.OpenTrackersEffect -> state
+ */
+
+ else -> state
}
},
- actor = { _: State, action: Action ->
+ actor = { state: State, action: Action ->
Log.d("Feature", "action: $action")
when (action) {
- Action.ObserveDashboardAction -> merge(
+ Action.TogglePrivacyAction -> {
+ if (state != State.LoadingState) {
+ flowOf(Effect.UpdateStateEffect(getPrivacyStateUseCase.toggle()))
+ } else {
+ flowOf(Effect.UpdateStateEffect(getPrivacyStateUseCase.isQuickPrivacyEnabled))
+ }
+ }
+
+ /*Action.ObserveDashboardAction -> merge(
TrackersDataSource.trackers.map {
var activeTrackersCount: Int = 0
outer@ for (tracker in it) {
@@ -201,7 +239,7 @@ class DashboardFeature(
DummyDataSource.internetActivityMode.value
)
)
- }
+ }*/
Action.ShowFakeMyLocationAction -> flowOf(Effect.OpenFakeMyLocationEffect)
Action.ShowAppsPermissions -> flowOf(Effect.OpenAppsPermissionsEffect)
Action.ShowInternetActivityPrivacyAction -> flowOf(
@@ -212,17 +250,17 @@ class DashboardFeature(
},
singleEventProducer = { state, _, effect ->
Log.d("DashboardFeature", "$state, $effect")
- if (state is State.DashboardState && effect is Effect.OpenFakeMyLocationEffect)
- SingleEvent.NavigateToLocationSingleEvent
- else if (state is State.QuickProtectionState && effect is Effect.OpenQuickPrivacyProtectionEffect)
- SingleEvent.NavigateToQuickProtectionSingleEvent
- else if (state is State.DashboardState && effect is Effect.OpenInternetActivityPrivacyEffect)
- SingleEvent.NavigateToInternetActivityPrivacySingleEvent
- else if (state is State.DashboardState && effect is Effect.OpenAppsPermissionsEffect)
- SingleEvent.NavigateToPermissionsSingleEvent
- else if (state is State.DashboardState && effect is Effect.OpenTrackersEffect)
- SingleEvent.NavigateToTrackersSingleEvent
- else null
+ when (effect) {
+ is Effect.OpenFakeMyLocationEffect ->
+ SingleEvent.NavigateToLocationSingleEvent
+ is Effect.OpenInternetActivityPrivacyEffect ->
+ SingleEvent.NavigateToInternetActivityPrivacySingleEvent
+ is Effect.OpenAppsPermissionsEffect ->
+ SingleEvent.NavigateToPermissionsSingleEvent
+ is Effect.OpenTrackersEffect ->
+ SingleEvent.NavigateToTrackersSingleEvent
+ 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 e7ce353..3e47a18 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
@@ -17,36 +17,50 @@
package foundation.e.privacycentralapp.features.dashboard
+import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.view.View
-import android.widget.ProgressBar
-import android.widget.RelativeLayout
import android.widget.TextView
-import androidx.core.widget.NestedScrollView
+import androidx.core.content.ContextCompat.getColor
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.add
import androidx.fragment.app.commit
import androidx.lifecycle.lifecycleScope
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.ToolbarFragment
-import foundation.e.privacycentralapp.dummy.mapToString
+import foundation.e.privacycentralapp.common.NavToolbarFragment
+import foundation.e.privacycentralapp.databinding.FragmentDashboardBinding
+import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
+import foundation.e.privacycentralapp.domain.entities.LocationMode
+import foundation.e.privacycentralapp.extensions.viewModelProviderFactoryOf
+import foundation.e.privacycentralapp.features.dashboard.DashboardFeature.State.DisabledState
+import foundation.e.privacycentralapp.features.dashboard.DashboardFeature.State.EnabledState
+import foundation.e.privacycentralapp.features.dashboard.DashboardFeature.State.LoadingState
import foundation.e.privacycentralapp.features.internetprivacy.InternetPrivacyFragment
import foundation.e.privacycentralapp.features.location.FakeLocationFragment
-import foundation.e.privacycentralapp.features.permissions.PermissionsFragment
import foundation.e.privacycentralapp.features.trackers.TrackersFragment
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
class DashboardFragment :
- ToolbarFragment(R.layout.fragment_dashboard),
+ NavToolbarFragment(R.layout.fragment_dashboard),
MVIView<DashboardFeature.State, DashboardFeature.Action> {
- private val viewModel: DashboardViewModel by activityViewModels()
+ private val dependencyContainer: DependencyContainer by lazy {
+ (this.requireActivity().application as PrivacyCentralApplication).dependencyContainer
+ }
+
+ private val viewModel: DashboardViewModel by activityViewModels {
+ viewModelProviderFactoryOf { dependencyContainer.dashBoardViewModelFactory.create() }
+ }
+
+ private lateinit var binding: FragmentDashboardBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -78,11 +92,8 @@ class DashboardFragment :
}
}
is DashboardFeature.SingleEvent.NavigateToPermissionsSingleEvent -> {
- requireActivity().supportFragmentManager.commit {
- add<PermissionsFragment>(R.id.container)
- setReorderingAllowed(true)
- addToBackStack("dashboard")
- }
+ val intent = Intent("android.intent.action.MANAGE_PERMISSIONS")
+ requireActivity().startActivity(intent)
}
DashboardFeature.SingleEvent.NavigateToTrackersSingleEvent -> {
requireActivity().supportFragmentManager.commit {
@@ -94,35 +105,37 @@ class DashboardFragment :
}
}
}
- lifecycleScope.launchWhenStarted {
- viewModel.submitAction(DashboardFeature.Action.ShowDashboardAction)
- viewModel.submitAction(DashboardFeature.Action.ObserveDashboardAction)
- }
+ // lifecycleScope.launchWhenStarted {
+ // viewModel.submitAction(DashboardFeature.Action.ShowDashboardAction)
+ // viewModel.submitAction(DashboardFeature.Action.ObserveDashboardAction)
+ // }
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- addClickToMore(view.findViewById(R.id.personal_leakag_info))
- view.let {
- it.findViewById<TextView>(R.id.tap_to_enable_quick_protection).setOnClickListener {
- viewModel.submitAction(DashboardFeature.Action.ShowQuickPrivacyProtectionInfoAction)
- }
- it.findViewById<RelativeLayout>(R.id.my_location).setOnClickListener {
- viewModel.submitAction(DashboardFeature.Action.ShowFakeMyLocationAction)
- }
- it.findViewById<RelativeLayout>(R.id.internet_activity_privacy).setOnClickListener {
- viewModel.submitAction(DashboardFeature.Action.ShowInternetActivityPrivacyAction)
- }
- it.findViewById<RelativeLayout>(R.id.apps_permissions).setOnClickListener {
- viewModel.submitAction(DashboardFeature.Action.ShowAppsPermissions)
- }
- it.findViewById<RelativeLayout>(R.id.am_i_tracked).setOnClickListener {
- viewModel.submitAction(DashboardFeature.Action.ShowTrackers)
- }
+ binding = FragmentDashboardBinding.bind(view)
+
+ binding.togglePrivacyCentral.setOnClickListener {
+ viewModel.submitAction(DashboardFeature.Action.TogglePrivacyAction)
+ }
+ binding.myLocation.container.setOnClickListener {
+ viewModel.submitAction(DashboardFeature.Action.ShowFakeMyLocationAction)
+ }
+ binding.internetActivityPrivacy.container.setOnClickListener {
+ viewModel.submitAction(DashboardFeature.Action.ShowInternetActivityPrivacyAction)
+ }
+ binding.appsPermissions.container.setOnClickListener {
+ viewModel.submitAction(DashboardFeature.Action.ShowAppsPermissions)
+ }
+
+ binding.amITracked.container.setOnClickListener {
+ viewModel.submitAction(DashboardFeature.Action.ShowTrackers)
}
}
- override fun getTitle(): String = getString(R.string.privacy_dashboard)
+ override fun getTitle(): String {
+ return getString(R.string.dashboard_title)
+ }
private fun addClickToMore(textView: TextView) {
val clickToMore = SpannableString(getString(R.string.click_to_learn_more))
@@ -136,65 +149,96 @@ class DashboardFragment :
}
override fun render(state: DashboardFeature.State) {
- when (state) {
- is DashboardFeature.State.InitialState, is DashboardFeature.State.LoadingDashboardState -> {
- view?.let {
- it.findViewById<ProgressBar>(R.id.loadingSpinner).visibility = View.VISIBLE
- it.findViewById<NestedScrollView>(R.id.scrollContainer).visibility = View.GONE
- }
- }
- is DashboardFeature.State.DashboardState -> {
- view?.let { view ->
- view.findViewById<ProgressBar>(R.id.loadingSpinner).visibility = View.GONE
- view.findViewById<NestedScrollView>(R.id.scrollContainer).visibility =
- View.VISIBLE
- view.findViewById<TextView>(R.id.am_i_tracked_subtitle).text = getString(
- R.string.am_i_tracked_subtitle,
- state.trackersCount,
- state.activeTrackersCount
- )
- view.findViewById<TextView>(R.id.apps_permissions_subtitle).text = getString(
- R.string.apps_permissions_subtitle,
- state.totalApps,
- state.permissionCount
- )
- view.findViewById<TextView>(R.id.my_location_subtitle).let { textView ->
- textView.text = getString(
- R.string.my_location_subtitle,
- state.appsUsingLocationPerm,
- )
- textView.append(
- SpannableString(state.locationMode.mapToString(requireContext()))
- .also {
- it.setSpan(
- ForegroundColorSpan(Color.parseColor("#007fff")),
- 0,
- it.length,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
- )
- }
- )
- }
- view.findViewById<TextView>(R.id.internet_activity_privacy_subtitle)
- .let { textView ->
- textView.text = getString(R.string.internet_activity_privacy_subtitle)
- textView.append(
- SpannableString(state.internetPrivacyMode.mapToString(requireContext()))
- .also {
- it.setSpan(
- ForegroundColorSpan(Color.parseColor("#007fff")),
- 0,
- it.length,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
- )
- }
- )
- }
- }
- }
- DashboardFeature.State.QuickProtectionState -> {
- }
+ val enabled = state is EnabledState
+ binding.stateLabel.text = getString(
+ if (enabled) R.string.dashboard_state_label_on
+ else R.string.dashboard_state_label_off
+ )
+
+ binding.togglePrivacyCentral.setImageResource(
+ if (enabled) R.drawable.ic_quick_privacy_on
+ else R.drawable.ic_quick_privacy_off
+ )
+ binding.stateLabel.setTextColor(
+ getColor(
+ requireContext(),
+ if (enabled) R.color.green_on
+ else R.color.orange_off
+ )
+ )
+
+ val trackersEnabled = state is EnabledState &&
+ state.isAllTrackersBlocked
+ binding.stateTrackers.text = getString(
+ if (trackersEnabled) R.string.dashboard_state_trackers_on
+ else R.string.dashboard_state_trackers_off
+ )
+ binding.stateTrackers.setTextColor(
+ getColor(
+ requireContext(),
+ if (trackersEnabled) R.color.green_on
+ else R.color.black_text
+ )
+ )
+
+ val geolocEnabled = state is EnabledState && state.locationMode != LocationMode.REAL_LOCATION
+ binding.stateGeolocation.text = getString(
+ if (geolocEnabled) R.string.dashboard_state_geolocation_on
+ else R.string.dashboard_state_geolocation_off
+ )
+ binding.stateGeolocation.setTextColor(
+ getColor(
+ requireContext(),
+ if (geolocEnabled) R.color.green_on
+ else R.color.black_text
+ )
+ )
+
+ val ipAddressEnabled = state is EnabledState && state.internetPrivacyMode != InternetPrivacyMode.REAL_IP
+ binding.stateIpAddress.text = getString(
+ if (ipAddressEnabled) R.string.dashboard_state_ipaddress_on
+ else R.string.dashboard_state_ipaddress_off
+ )
+ binding.stateIpAddress.setTextColor(
+ getColor(
+ requireContext(),
+ if (ipAddressEnabled) R.color.green_on
+ else R.color.black_text
+ )
+ )
+
+ // binding.graphTotal.text = if (state == DashboardFeature.State.LoadingState) {
+ // ""
+ // } else {
+ // val value = if (state is DashboardFeature.State.EnabledState) state.totalGraph
+ // else if (state is DashboardFeature.State.DisabledState) state.totalGraph
+ // else 0 // dummy
+ // getString(R.string.dashboard_graph_total, value)
+ // }
+
+ binding.amITracked.subtitle.text = if (state == LoadingState) ""
+ else {
+ val value = if (state is EnabledState) state.activeTrackersCount
+ else if (state is DisabledState) state.activeTrackersCount
+ else 0 // dummy
+ getString(R.string.dashboard_am_i_tracked_subtitle, 77, value)
}
+
+ binding.myLocation.subtitle.text = getString(
+ if (state is EnabledState &&
+ state.locationMode != LocationMode.REAL_LOCATION
+ )
+ R.string.dashboard_location_subtitle_on
+ else R.string.dashboard_location_subtitle_off
+ )
+
+ binding.internetActivityPrivacy.subtitle.text = getString(
+ if (state is DashboardFeature.State.EnabledState &&
+ state.internetPrivacyMode != InternetPrivacyMode.REAL_IP
+ )
+ R.string.dashboard_internet_activity_privacy_subtitle_on
+ else R.string.dashboard_internet_activity_privacy_subtitle_on
+ )
}
override fun actions(): Flow<DashboardFeature.Action> = viewModel.actions
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardViewModel.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardViewModel.kt
index 3aa104e..c25f215 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardViewModel.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardViewModel.kt
@@ -19,19 +19,23 @@ package foundation.e.privacycentralapp.features.dashboard
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
+import foundation.e.privacycentralapp.common.Factory
+import foundation.e.privacycentralapp.domain.usecases.GetQuickPrivacyStateUseCase
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
-class DashboardViewModel : ViewModel() {
+class DashboardViewModel(
+ private val getPrivacyStateUseCase: GetQuickPrivacyStateUseCase
+) : ViewModel() {
private val _actions = MutableSharedFlow<DashboardFeature.Action>()
val actions = _actions.asSharedFlow()
val dashboardFeature: DashboardFeature by lazy {
DashboardFeature.create(
- DashboardFeature.State.InitialState,
- coroutineScope = viewModelScope
+ coroutineScope = viewModelScope,
+ getPrivacyStateUseCase = getPrivacyStateUseCase
)
}
@@ -41,3 +45,11 @@ class DashboardViewModel : ViewModel() {
}
}
}
+
+class DashBoardViewModelFactory(
+ private val getPrivacyStateUseCase: GetQuickPrivacyStateUseCase
+) : Factory<DashboardViewModel> {
+ override fun create(): DashboardViewModel {
+ return DashboardViewModel(getPrivacyStateUseCase)
+ }
+}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/QuickProtectionFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/QuickProtectionFragment.kt
index 727afa9..981c8da 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/QuickProtectionFragment.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/QuickProtectionFragment.kt
@@ -32,7 +32,7 @@ class QuickProtectionFragment : NavToolbarFragment(R.layout.fragment_quick_prote
override fun onAttach(context: Context) {
super.onAttach(context)
requireActivity().onBackPressedDispatcher.addCallback(this, true) {
- viewModel.submitAction(DashboardFeature.Action.ShowDashboardAction)
+ // viewModel.submitAction(DashboardFeature.Action.ShowDashboardAction)
this.isEnabled = false
requireActivity().onBackPressed()
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt
index 41ce9ad..cbe0a04 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt
@@ -239,19 +239,6 @@ class InternetPrivacyFeature(
action is Action.UseHiddenIPAction
&& effect is Effect.ShowAndroidVpnDisclaimerEffect ->
SingleEvent.StartAndroidVpnActivityEvent(effect.intent)
-
- // Action.UseRealIPAction, Action.UseHiddenIPAction -> when (effect) {
- // is Effect.ModeUpdatedEffect -> {
- // if (effect.mode == InternetPrivacyMode.REAL_IP) {
- // SingleEvent.RealIPSelectedEvent
- // } else {
- // SingleEvent.HiddenIPSelectedEvent
- // }
- // }
- // is Effect.ErrorEffect -> {
- // SingleEvent.ErrorEvent(effect.message)
- // }
- // }
else -> null
}
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt
index 22e63e3..c2be7b1 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt
@@ -35,8 +35,8 @@ 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.NavToolbarFragment
import foundation.e.privacycentralapp.common.ToggleAppsAdapter
+import foundation.e.privacycentralapp.common.ToolbarFragment
import foundation.e.privacycentralapp.extensions.viewModelProviderFactoryOf
import foundation.e.privacymodules.ipscramblermodule.IIpScramblerModule
import kotlinx.coroutines.flow.Flow
@@ -44,7 +44,7 @@ import kotlinx.coroutines.flow.collect
import java.util.Locale
class InternetPrivacyFragment :
- NavToolbarFragment(R.layout.fragment_internet_activity_policy),
+ ToolbarFragment(R.layout.fragment_internet_activity_policy),
MVIView<InternetPrivacyFeature.State, InternetPrivacyFeature.Action> {
private val dependencyContainer: DependencyContainer by lazy {
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt
index 9124f85..e9fb078 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt
@@ -23,10 +23,10 @@ import foundation.e.flowmvi.Actor
import foundation.e.flowmvi.Reducer
import foundation.e.flowmvi.SingleEventProducer
import foundation.e.flowmvi.feature.BaseFeature
+import foundation.e.privacycentralapp.domain.entities.LocationMode
import foundation.e.privacycentralapp.dummy.CityDataSource
import foundation.e.privacycentralapp.dummy.DummyDataSource
import foundation.e.privacycentralapp.dummy.Location
-import foundation.e.privacycentralapp.dummy.LocationMode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.flowOf
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt
index 7281afc..bb9bd26 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt
@@ -56,7 +56,7 @@ import foundation.e.privacycentralapp.DependencyContainer
import foundation.e.privacycentralapp.PrivacyCentralApplication
import foundation.e.privacycentralapp.R
import foundation.e.privacycentralapp.common.NavToolbarFragment
-import foundation.e.privacycentralapp.dummy.LocationMode
+import foundation.e.privacycentralapp.domain.entities.LocationMode
import foundation.e.privacycentralapp.extensions.viewModelProviderFactoryOf
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
@@ -178,7 +178,7 @@ class FakeLocationFragment :
Mapbox.getInstance(requireContext(), getString(R.string.mapbox_key))
}
- override fun getTitle(): String = getString(R.string.my_location_title)
+ override fun getTitle(): String = getString(R.string.dashboard_location_title)
private fun displayToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT)