summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/build.gradle8
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt27
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/data/repositories/CityDataSource.kt46
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt23
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/entities/LocationMode.kt2
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt88
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/dummy/CityDataSource.kt66
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt4
-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.kt2
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt187
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt161
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt17
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/location/LocationApiDelegate.kt81
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt9
-rw-r--r--app/src/main/res/values/arrays.xml32
-rw-r--r--build.gradle2
17 files changed, 307 insertions, 450 deletions
diff --git a/app/build.gradle b/app/build.gradle
index bc07919..77e1113 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -95,14 +95,14 @@ dependencies {
compileOnly files('libs/e-ui-sdk-1.0.1-q.jar')
implementation files('libs/lineage-sdk.jar')
implementation files('libs/trackerfilter.aar')
-
+ //implementation project(":privacymodulesapi")
// include the google specific version of the modules, just for the google flavor
- // TODO: google version is broken for now. googleImplementation project(":privacymodulesgoogle")
+ googleImplementation project(":privacymodulesgoogle")
// include the e specific version of the modules, just for the e flavor
- eImplementation 'foundation.e:privacymodule.e-29:0.3.2'
+ eImplementation project(":privacymodulese")
- implementation 'foundation.e:privacymodule.api:0.3.2'
+ implementation 'foundation.e:privacymodule.api:0.4.1'
implementation 'foundation.e:privacymodule.tor:0.1.1'
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
diff --git a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt
index b73a79d..d8c3047 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt
@@ -22,21 +22,22 @@ import android.content.Context
import android.os.Process
import foundation.e.privacycentralapp.data.repositories.LocalStateRepository
import foundation.e.privacycentralapp.domain.usecases.AppListUseCase
+import foundation.e.privacycentralapp.domain.usecases.FakeLocationStateUseCase
import foundation.e.privacycentralapp.domain.usecases.GetQuickPrivacyStateUseCase
import foundation.e.privacycentralapp.domain.usecases.IpScramblingStateUseCase
import foundation.e.privacycentralapp.domain.usecases.TrackersStateUseCase
import foundation.e.privacycentralapp.domain.usecases.TrackersStatisticsUseCase
+import foundation.e.privacycentralapp.dummy.CityDataSource
import foundation.e.privacycentralapp.dummy.TrackTrackersPrivacyMock
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
import foundation.e.privacycentralapp.features.trackers.TrackersViewModelFactory
import foundation.e.privacycentralapp.features.trackers.apptrackers.AppTrackersViewModelFactory
import foundation.e.privacymodules.ipscrambler.IpScramblerModule
import foundation.e.privacymodules.ipscramblermodule.IIpScramblerModule
-import foundation.e.privacymodules.location.FakeLocation
-import foundation.e.privacymodules.location.IFakeLocation
+import foundation.e.privacymodules.location.FakeLocationModule
+import foundation.e.privacymodules.location.IFakeLocationModule
import foundation.e.privacymodules.permissions.PermissionsPrivacyModule
import foundation.e.privacymodules.permissions.data.ApplicationDescription
import foundation.e.trackerfilter.api.BlockTrackersPrivacyModule
@@ -54,7 +55,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 fakeLocationModule: IFakeLocationModule by lazy { FakeLocationModule(app.applicationContext) }
private val permissionsModule by lazy { PermissionsPrivacyModule(app.applicationContext) }
private val ipScramblerModule: IIpScramblerModule by lazy { IpScramblerModule(app.applicationContext) }
@@ -67,10 +68,6 @@ class DependencyContainer constructor(val app: Application) {
)
}
- private val locationApi by lazy {
- LocationApiDelegate(fakeLocationModule, permissionsModule, appDesc)
- }
-
private val blockTrackersPrivacyModule by lazy { BlockTrackersPrivacyModule.getInstance(context) }
// Repositories
@@ -85,9 +82,8 @@ class DependencyContainer constructor(val app: Application) {
private val ipScramblingStateUseCase by lazy {
IpScramblingStateUseCase(ipScramblerModule, localStateRepository, GlobalScope)
}
- private val appListUseCase by lazy {
- AppListUseCase(permissionsModule, GlobalScope)
- }
+ private val appListUseCase = AppListUseCase(permissionsModule, GlobalScope)
+
private val trackersStatisticsUseCase by lazy {
TrackersStatisticsUseCase(trackTrackersPrivacyModule)
}
@@ -96,13 +92,20 @@ class DependencyContainer constructor(val app: Application) {
TrackersStateUseCase(blockTrackersPrivacyModule, trackTrackersPrivacyModule, permissionsModule, localStateRepository, GlobalScope)
}
+ private val fakeLocationStateUseCase by lazy {
+ FakeLocationStateUseCase(
+ fakeLocationModule, permissionsModule, localStateRepository, CityDataSource, appDesc, GlobalScope)
+ }
+
// ViewModelFactories
val dashBoardViewModelFactory by lazy {
DashBoardViewModelFactory(getQuickPrivacyStateUseCase, ipScramblingStateUseCase, trackersStatisticsUseCase, trackersStateUseCase)
}
val fakeLocationViewModelFactory by lazy {
- FakeLocationViewModelFactory(locationApi)
+ FakeLocationViewModelFactory(
+ getQuickPrivacyStateUseCase = getQuickPrivacyStateUseCase,
+ fakeLocationStateUseCase = fakeLocationStateUseCase)
}
val blockerService = BlockerInterface.getInstance(context)
diff --git a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/CityDataSource.kt b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/CityDataSource.kt
new file mode 100644
index 0000000..5fab9b7
--- /dev/null
+++ b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/CityDataSource.kt
@@ -0,0 +1,46 @@
+/*
+ * 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.dummy
+
+object CityDataSource {
+ private val BARCELONA = Pair(41.3851f, 2.1734f)
+ private val BUDAPEST = Pair(47.4979f, 19.0402f)
+ private val ABU_DHABI = Pair(24.4539f, 54.3773f)
+ private val HYDERABAD = Pair(17.3850f, 78.4867f)
+ private val QUEZON_CITY = Pair(14.6760f, 121.0437f)
+ private val PARIS = Pair(48.8566f, 2.3522f)
+ private val LONDON = Pair(51.5074f, 0.1278f)
+ private val SHANGHAI = Pair(31.2304f, 121.4737f)
+ private val MADRID = Pair(40.4168f, 3.7038f)
+ private val LAHORE = Pair(31.5204f, 74.3587f)
+ private val CHICAGO = Pair(41.8781f, 87.6298f)
+
+ val citiesLocationsList = listOf(
+ BARCELONA,
+ BUDAPEST,
+ ABU_DHABI,
+ HYDERABAD,
+ QUEZON_CITY,
+ PARIS,
+ LONDON,
+ SHANGHAI,
+ MADRID,
+ LAHORE,
+ CHICAGO
+ )
+}
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 5f22c96..78cb4e4 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
@@ -26,6 +26,8 @@ class LocalStateRepository(context: Context) {
private const val SHARED_PREFS_FILE = "localState"
private const val KEY_QUICK_PRIVACY = "quickPrivacy"
private const val KEY_IP_SCRAMBLING = "ipScrambling"
+ private const val KEY_FAKE_LATITUDE = "fakeLatitude"
+ private const val KEY_FAKE_LONGITUDE = "fakeLongitude"
}
private val sharedPref = context.getSharedPreferences(SHARED_PREFS_FILE, Context.MODE_PRIVATE)
@@ -40,6 +42,27 @@ class LocalStateRepository(context: Context) {
var quickPrivacyEnabledFlow: Flow<Boolean> = quickPrivacyEnabledMutableFlow
+ var fakeLocation: Pair<Float, Float>?
+ get() = if (sharedPref.contains(KEY_FAKE_LATITUDE) && sharedPref.contains(
+ KEY_FAKE_LONGITUDE))
+ Pair(
+ sharedPref.getFloat(KEY_FAKE_LATITUDE, 0f),
+ sharedPref.getFloat(KEY_FAKE_LONGITUDE, 0f))
+ else null
+ set(value) {
+ if (value == null) {
+ sharedPref.edit()
+ .remove(KEY_FAKE_LATITUDE)
+ .remove(KEY_FAKE_LONGITUDE)
+ .commit()
+ } else {
+ sharedPref.edit()
+ .putFloat(KEY_FAKE_LATITUDE, value.first)
+ .putFloat(KEY_FAKE_LONGITUDE, value.second)
+ .commit()
+ }
+ }
+
var isIpScramblingEnabled: Boolean
get() = sharedPref.getBoolean(KEY_IP_SCRAMBLING, false)
set(value) = set(KEY_IP_SCRAMBLING, value)
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
index dbb9b0a..35a77b3 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/domain/entities/LocationMode.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/entities/LocationMode.kt
@@ -18,5 +18,5 @@
package foundation.e.privacycentralapp.domain.entities
enum class LocationMode {
- REAL_LOCATION, RANDOM_LOCATION, CUSTOM_LOCATION
+ REAL_LOCATION, RANDOM_LOCATION, SPECIFIC_LOCATION
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt
index 6d13f0e..02fdb0f 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt
@@ -17,47 +17,89 @@
package foundation.e.privacycentralapp.domain.usecases
-/*import android.app.AppOpsManager
-import android.content.Intent
-import android.util.Log
+import android.app.AppOpsManager
import foundation.e.privacycentralapp.data.repositories.LocalStateRepository
import foundation.e.privacycentralapp.domain.entities.LocationMode
-import foundation.e.privacycentralapp.features.location.LocationApiDelegate
-import foundation.e.privacymodules.location.IFakeLocation
+import foundation.e.privacycentralapp.dummy.CityDataSource
+import foundation.e.privacymodules.location.IFakeLocationModule
import foundation.e.privacymodules.permissions.PermissionsPrivacyModule
import foundation.e.privacymodules.permissions.data.AppOpModes
import foundation.e.privacymodules.permissions.data.ApplicationDescription
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
+import kotlin.random.Random
class FakeLocationStateUseCase(
- private val fakeLocationModule: IFakeLocation,
+ private val fakeLocationModule: IFakeLocationModule,
+
private val permissionsModule: PermissionsPrivacyModule,
private val localStateRepository: LocalStateRepository,
+ private val citiesRepository: CityDataSource,
private val appDesc: ApplicationDescription,
private val coroutineScope: CoroutineScope
) {
- private fun acquireLocationPermission() {
- try {
-
- permissionsModule.setAppOpMode(
- appDesc, AppOpsManager.OPSTR_COARSE_LOCATION,
- AppOpModes.ALLOWED
- )
- permissionsModule.setAppOpMode(
- appDesc, AppOpsManager.OPSTR_FINE_LOCATION,
- AppOpModes.ALLOWED
- )
- } catch (e: Exception) {
- // Log.e(TAG, "Can't start RealLocation", e)
+ init {
+ coroutineScope.launch {
+ localStateRepository.quickPrivacyEnabledFlow.collect {
+ applySettings(it, localStateRepository.fakeLocation)
+ }
}
}
- private fun applySettings(isQuickPrivacyEnabled: Boolean, fakeLocationMode: LocationMode) {
- when {
- // isQuickPrivacyEnabled ->
+ fun getLocationMode(): LocationMode = when(localStateRepository.fakeLocation) {
+ null -> LocationMode.REAL_LOCATION
+ in citiesRepository.citiesLocationsList -> LocationMode.RANDOM_LOCATION
+ else -> LocationMode.SPECIFIC_LOCATION
+ }
+
+ private fun acquireLocationPermission() {
+ permissionsModule.toggleDangerousPermission(appDesc,
+ android.Manifest.permission.ACCESS_FINE_LOCATION, true)
+
+ // permissionsModule.setAppOpMode(
+ // appDesc, AppOpsManager.OPSTR_COARSE_LOCATION,
+ // AppOpModes.ALLOWED
+ // )
+ // permissionsModule.setAppOpMode(
+ // appDesc, AppOpsManager.OPSTR_FINE_LOCATION,
+ // AppOpModes.ALLOWED
+ // )
+ }
+
+ private fun applySettings(isQuickPrivacyEnabled: Boolean, fakeLocation: Pair<Float, Float>?) {
+ if (isQuickPrivacyEnabled && fakeLocation != null) {
+ if (permissionsModule.getAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION) != AppOpModes.ALLOWED) {
+ permissionsModule.setAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION, AppOpModes.ALLOWED)
+ }
+ fakeLocationModule.startFakeLocation()
+
+ fakeLocationModule.setFakeLocation(fakeLocation.first.toDouble(), fakeLocation.second.toDouble())
+ } else {
+ fakeLocationModule.stopFakeLocation()
}
}
+ fun setSpecificLocation(latitude: Float, longitude: Float) {
+ setFakeLocation(latitude to longitude)
+ }
+
+ fun setRandomLocation() {
+ val randomIndex = Random.nextInt(citiesRepository.citiesLocationsList.size)
+ val location = citiesRepository.citiesLocationsList[randomIndex]
+
+ setFakeLocation(location)
+ }
+
+ private fun setFakeLocation(location: Pair<Float, Float>) {
+ localStateRepository.fakeLocation = location
+ applySettings(true, location)
+ }
+
+ fun stopFakeLocation() {
+ localStateRepository.fakeLocation = null
+ applySettings(true, null)
+ }
-}*/
+}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/dummy/CityDataSource.kt b/app/src/main/java/foundation/e/privacycentralapp/dummy/CityDataSource.kt
deleted file mode 100644
index 988c7f4..0000000
--- a/app/src/main/java/foundation/e/privacycentralapp/dummy/CityDataSource.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.dummy
-
-import foundation.e.privacycentralapp.domain.entities.LocationMode
-import kotlin.random.Random
-
-data class City(val name: String, val latitude: Double, val longitude: Double) {
-
- fun toRandomLocation(): Location {
- return Location(LocationMode.RANDOM_LOCATION, this.latitude, this.longitude)
- }
-}
-
-object CityDataSource {
- private val BARCELONA = Pair(41.3851, 2.1734)
- private val BUDAPEST = Pair(47.4979, 19.0402)
- private val ABU_DHABI = Pair(24.4539, 54.3773)
- private val HYDERABAD = Pair(17.3850, 78.4867)
- private val QUEZON_CITY = Pair(14.6760, 121.0437)
- private val PARIS = Pair(48.8566, 2.3522)
- private val LONDON = Pair(51.5074, 0.1278)
- private val SHANGHAI = Pair(31.2304, 121.4737)
- private val MADRID = Pair(40.4168, 3.7038)
- private val LAHORE = Pair(31.5204, 74.3587)
- private val CHICAGO = Pair(41.8781, 87.6298)
-
- // LatLong Array, the order should be the same as that of R.array.cities
- private val latLongArray = arrayOf(
- BARCELONA,
- BUDAPEST,
- ABU_DHABI,
- HYDERABAD,
- QUEZON_CITY,
- PARIS,
- LONDON,
- SHANGHAI,
- MADRID,
- LAHORE,
- CHICAGO
- )
-
- fun getRandomCity(cities: Array<String>): City {
- if (cities.size != latLongArray.size) {
- throw IllegalStateException("LatLong array must have the same number of element as in cities array.")
- }
- val randomIndex = Random.nextInt(cities.size)
- val latLong = latLongArray[randomIndex]
- return City(cities[randomIndex], latLong.first, latLong.second)
- }
-}
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 246854b..38daeab 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt
@@ -183,9 +183,9 @@ object DummyDataSource {
requireNotNull(location) { "Custom location should be null" }
_location.value = location
}
- LocationMode.CUSTOM_LOCATION -> {
+ LocationMode.SPECIFIC_LOCATION -> {
requireNotNull(location) { "Custom location should be null" }
- _location.value = location.copy(mode = LocationMode.CUSTOM_LOCATION)
+ _location.value = location.copy(mode = LocationMode.SPECIFIC_LOCATION)
}
}
return true
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 04ee5bf..ab4ba72 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/dummy/Extensions.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/dummy/Extensions.kt
@@ -24,5 +24,5 @@ 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)
LocationMode.RANDOM_LOCATION -> context.getString(R.string.random_location_mode)
- LocationMode.CUSTOM_LOCATION -> context.getString(R.string.fake_location_mode)
+ LocationMode.SPECIFIC_LOCATION -> context.getString(R.string.fake_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 5185737..39b6138 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
@@ -56,7 +56,7 @@ class DashboardFeature(
val totalGraph: Int? = null,
// val graphData
val trackersCount: Int? = null,
- val dayTrackersCount: Int? = null,
+ val activeTrackersCount: Int? = null,
val dayStatistics: List<Int>? = null
)
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 b16af28..7c6a715 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
@@ -18,17 +18,17 @@
package foundation.e.privacycentralapp.features.location
import android.util.Log
-import com.mapbox.mapboxsdk.geometry.LatLng
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.domain.usecases.FakeLocationStateUseCase
+import foundation.e.privacycentralapp.domain.usecases.GetQuickPrivacyStateUseCase
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
// Define a state machine for Fake location feature
class FakeLocationFeature(
@@ -46,7 +46,10 @@ class FakeLocationFeature(
singleEventProducer
) {
data class State(
- val location: Location
+ val isEnabled: Boolean,
+ val mode: LocationMode,
+ val specificLatitude: Float? = null,
+ val specificLongitude: Float? = null
)
sealed class SingleEvent {
@@ -57,153 +60,97 @@ class FakeLocationFeature(
}
sealed class Action {
+ object Init : Action()
// Action which is triggered everytime the location is updated.
- data class UpdateLocationAction(val latLng: LatLng) : Action()
- object UseRealLocationAction : Action()
- data class UseRandomLocationAction(
- val cities: Array<String>
- ) : Action() {
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as UseRandomLocationAction
-
- if (!cities.contentEquals(other.cities)) return false
+ //data class UpdateLocationAction(val latLng: LatLng) : Action()
- return true
- }
-
- override fun hashCode(): Int {
- return cities.contentHashCode()
- }
- }
-
- object UseSpecificLocationAction : Action()
- data class SetCustomFakeLocationAction(
- val latitude: Double,
- val longitude: Double
- ) : Action()
+ object UseRealLocationAction : Action()
+ object UseRandomLocationAction : Action()
+ data class SetSpecificLocationAction(
+ val latitude: Float,
+ val longitude: Float) : Action()
}
sealed class Effect {
- data class LocationUpdatedEffect(val latitude: Double, val longitude: Double) : Effect()
- object RealLocationSelectedEffect : Effect()
- object RandomLocationSelectedEffect : Effect()
- object SpecificLocationSelectedEffect : Effect()
- object SpecificLocationSavedEffect : Effect()
+ data class QuickPrivacyUpdatedEffect(val isEnabled: Boolean): Effect()
+ data class LocationModeUpdatedEffect(
+ val mode: LocationMode,
+ val latitude: Float? = null,
+ val longitude: Float? = null) : Effect()
data class ErrorEffect(val message: String) : Effect()
+ object QuickPrivacyDisabledWarningEffect : Effect()
}
companion object {
fun create(
initialState: State = State(
- Location(
- LocationMode.REAL_LOCATION,
- 0.0,
- 0.0
- )
+ isEnabled = false,
+ mode = LocationMode.REAL_LOCATION
),
- coroutineScope: CoroutineScope,
- locationApi: LocationApiDelegate
+ getQuickPrivacyStateUseCase: GetQuickPrivacyStateUseCase,
+ fakeLocationStateUseCase: FakeLocationStateUseCase,
+ coroutineScope: CoroutineScope
) = FakeLocationFeature(
initialState, coroutineScope,
reducer = { state, effect ->
when (effect) {
- Effect.RandomLocationSelectedEffect -> state.copy(
- location = state.location.copy(
- mode = LocationMode.RANDOM_LOCATION
- )
- )
- Effect.RealLocationSelectedEffect -> state.copy(
- location = state.location.copy(
- mode = LocationMode.REAL_LOCATION
- )
- )
- is Effect.ErrorEffect, Effect.SpecificLocationSavedEffect -> state
- is Effect.LocationUpdatedEffect -> state.copy(
- location = state.location.copy(
- latitude = effect.latitude,
- longitude = effect.longitude
- )
- )
- is Effect.SpecificLocationSelectedEffect -> state.copy(
- location = state.location.copy(
- mode = LocationMode.CUSTOM_LOCATION
- )
- )
+ is Effect.QuickPrivacyUpdatedEffect -> state.copy(isEnabled = effect.isEnabled)
+ is Effect.LocationModeUpdatedEffect -> state.copy(
+ mode = effect.mode,
+ specificLatitude = effect.latitude,
+ specificLongitude = effect.longitude)
+
+ is Effect.ErrorEffect,
+ Effect.QuickPrivacyDisabledWarningEffect -> state
}
},
- actor = { _, action ->
+ actor = { state, action ->
when (action) {
- is Action.UpdateLocationAction -> flowOf(
- Effect.LocationUpdatedEffect(
- action.latLng.latitude,
- action.latLng.longitude
- )
- )
- is Action.SetCustomFakeLocationAction -> {
- val location = Location(
- LocationMode.CUSTOM_LOCATION,
- action.latitude,
- action.longitude
- )
- locationApi.setFakeLocation(action.latitude, action.longitude)
- val success = DummyDataSource.setLocationMode(
- LocationMode.CUSTOM_LOCATION,
- location
- )
- if (success) {
- flowOf(
- Effect.SpecificLocationSavedEffect
+ is Action.Init -> merge(
+ getQuickPrivacyStateUseCase.quickPrivacyEnabledFlow.map { Effect.QuickPrivacyUpdatedEffect(it) },
+ flowOf(Effect.LocationModeUpdatedEffect(fakeLocationStateUseCase.getLocationMode())))
+
+ // is Action.UpdateLocationAction -> flowOf(
+ // Effect.LocationUpdatedEffect(
+ // action.latLng.latitude,
+ // action.latLng.longitude
+ // )
+ // )
+
+ is Action.SetSpecificLocationAction -> {
+ if (state.isEnabled) {
+ fakeLocationStateUseCase.setSpecificLocation(
+ action.latitude,
+ action.longitude
)
- } else {
flowOf(
- Effect.ErrorEffect("Couldn't select location")
+ Effect.LocationModeUpdatedEffect(
+ mode = LocationMode.SPECIFIC_LOCATION,
+ latitude = action.latitude,
+ longitude = action.longitude
+ )
)
- }
+ } else flowOf(Effect.QuickPrivacyDisabledWarningEffect)
}
is Action.UseRandomLocationAction -> {
- val randomCity = CityDataSource.getRandomCity(action.cities)
- locationApi.setFakeLocation(randomCity.latitude, randomCity.longitude)
- val success = DummyDataSource.setLocationMode(
- LocationMode.RANDOM_LOCATION,
- randomCity.toRandomLocation()
- )
- if (success) {
- flowOf(
- Effect.RandomLocationSelectedEffect
- )
- } else {
- flowOf(
- Effect.ErrorEffect("Couldn't select location")
- )
- }
+ if (state.isEnabled) {
+ fakeLocationStateUseCase.setRandomLocation()
+ flowOf(Effect.LocationModeUpdatedEffect(LocationMode.RANDOM_LOCATION))
+ } else flowOf(Effect.QuickPrivacyDisabledWarningEffect)
}
is Action.UseRealLocationAction -> {
- locationApi.startRealLocation()
- val success = DummyDataSource.setLocationMode(LocationMode.REAL_LOCATION)
- if (success) {
- flowOf(
- Effect.RealLocationSelectedEffect
- )
- } else {
- flowOf(
- Effect.ErrorEffect("Couldn't select location")
- )
- }
- }
- is Action.UseSpecificLocationAction -> {
- flowOf(Effect.SpecificLocationSelectedEffect)
+ if (state.isEnabled) {
+ fakeLocationStateUseCase.stopFakeLocation()
+ flowOf(Effect.LocationModeUpdatedEffect(LocationMode.REAL_LOCATION))
+ } else flowOf(Effect.QuickPrivacyDisabledWarningEffect)
}
}
},
singleEventProducer = { _, _, effect ->
when (effect) {
- Effect.RandomLocationSelectedEffect -> SingleEvent.RandomLocationSelectedEvent
- Effect.SpecificLocationSavedEffect -> SingleEvent.SpecificLocationSavedEvent
- Effect.RealLocationSelectedEffect -> SingleEvent.RealLocationSelectedEvent
+ Effect.QuickPrivacyDisabledWarningEffect ->
+ SingleEvent.ErrorEvent("Enabled Quick Privacy to use functionalities")
is Effect.ErrorEffect -> SingleEvent.ErrorEvent(effect.message)
else -> null
}
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 bdc405e..0f69808 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