summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGuillaume Jacquart <guillaume.jacquart@hoodbrains.com>2022-11-18 07:21:50 +0000
committerGuillaume Jacquart <guillaume.jacquart@hoodbrains.com>2022-11-18 07:21:50 +0000
commit84bdb74c79a41c90d4d374bf5eb963191de3e7b3 (patch)
tree1b81bc5228aa8c722ca8df289cd9f93c2104522f /app
parent82e1bee1454fe5f8bc6653344da76b35f1d3d8a3 (diff)
parent2ee502ad3dbfd42c09a88212f5bd179fc531e2e6 (diff)
Merge branch '568-individuals_activation_buttons' into 'main'
568: individuals buttons to activate trackers control, fake location and Hide my ip See merge request e/os/advanced-privacy!102
Diffstat (limited to 'app')
-rw-r--r--app/build.gradle2
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt2
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/common/QuickPrivacyDisabledSnackbar.kt36
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt78
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/entities/InternetPrivacyMode.kt6
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt41
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/usecases/GetQuickPrivacyStateUseCase.kt71
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt35
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt9
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardFragment.kt36
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardState.kt4
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardViewModel.kt29
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt12
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyState.kt1
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyViewModel.kt19
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt12
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationState.kt1
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt6
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFragment.kt11
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersState.kt1
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersViewModel.kt7
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt17
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersState.kt4
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersViewModel.kt19
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt6
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/widget/Widget.kt6
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/widget/WidgetCommandReceiver.kt13
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt65
-rw-r--r--app/src/main/res/layout/fragment_dashboard.xml31
-rw-r--r--app/src/main/res/layout/widget.xml50
-rw-r--r--app/src/main/res/values-de/strings.xml7
-rw-r--r--app/src/main/res/values-es/strings.xml6
-rw-r--r--app/src/main/res/values-fi/strings.xml7
-rw-r--r--app/src/main/res/values-fr/strings.xml7
-rw-r--r--app/src/main/res/values-it/strings.xml7
-rw-r--r--app/src/main/res/values/strings.xml8
36 files changed, 296 insertions, 376 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 82717d3..323a118 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -132,7 +132,7 @@ dependencies {
implementation project(':trackers')
- implementation 'foundation.e:privacymodule.tor:1.3.0-orbot-16.6.2'
+ implementation 'foundation.e:privacymodule.tor:1.6.0-dev-orbot-16.6.2'
implementation 'foundation.e:elib:0.0.1-alpha11'
diff --git a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt
index 670b81e..345307c 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt
@@ -82,7 +82,7 @@ class DependencyContainer(val app: Application) {
// Usecases
val getQuickPrivacyStateUseCase by lazy {
- GetQuickPrivacyStateUseCase(localStateRepository, GlobalScope)
+ GetQuickPrivacyStateUseCase(localStateRepository)
}
private val ipScramblingStateUseCase by lazy {
IpScramblingStateUseCase(
diff --git a/app/src/main/java/foundation/e/privacycentralapp/common/QuickPrivacyDisabledSnackbar.kt b/app/src/main/java/foundation/e/privacycentralapp/common/QuickPrivacyDisabledSnackbar.kt
deleted file mode 100644
index 705f65d..0000000
--- a/app/src/main/java/foundation/e/privacycentralapp/common/QuickPrivacyDisabledSnackbar.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2022 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.common
-
-import android.view.View
-import com.google.android.material.snackbar.BaseTransientBottomBar
-import com.google.android.material.snackbar.Snackbar
-import foundation.e.privacycentralapp.R
-
-fun initQuickPrivacySnackbar(view: View, onDismiss: () -> Unit): Snackbar {
- val snackbar = Snackbar.make(view, R.string.quickprivacy_disabled_message, Snackbar.LENGTH_INDEFINITE)
- snackbar.setAction(R.string.close) { onDismiss() }
-
- snackbar.addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
- override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
- super.onDismissed(transientBottomBar, event)
- if (event == DISMISS_EVENT_SWIPE) onDismiss()
- }
- })
- return snackbar
-}
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 d39ee43..92ee0c1 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
@@ -24,14 +24,13 @@ import foundation.e.privacymodules.permissions.data.ApplicationDescription
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
-import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
class LocalStateRepository(context: Context) {
companion object {
private const val SHARED_PREFS_FILE = "localState"
- private const val KEY_QUICK_PRIVACY = "quickPrivacy"
+ private const val KEY_BLOCK_TRACKERS = "blockTrackers"
private const val KEY_IP_SCRAMBLING = "ipScrambling"
private const val KEY_FAKE_LOCATION = "fakeLocation"
private const val KEY_FAKE_LATITUDE = "fakeLatitude"
@@ -41,58 +40,48 @@ class LocalStateRepository(context: Context) {
private val sharedPref = context.getSharedPreferences(SHARED_PREFS_FILE, Context.MODE_PRIVATE)
- private val quickPrivacyEnabledMutableFlow =
- MutableStateFlow<Boolean>(sharedPref.getBoolean(KEY_QUICK_PRIVACY, false))
- val isQuickPrivacyEnabled: Boolean get() = quickPrivacyEnabledMutableFlow.value
+ private val _blockTrackers = MutableStateFlow(sharedPref.getBoolean(KEY_BLOCK_TRACKERS, true))
+ val blockTrackers = _blockTrackers.asStateFlow()
- fun setQuickPrivacyReturnIsFirstActivation(value: Boolean): Boolean {
- val isFirstActivation = value && !sharedPref.contains(KEY_QUICK_PRIVACY)
- set(KEY_QUICK_PRIVACY, value)
- quickPrivacyEnabledMutableFlow.value = value
- return isFirstActivation
+ fun setBlockTrackers(enabled: Boolean) {
+ set(KEY_BLOCK_TRACKERS, enabled)
+ _blockTrackers.update { enabled }
}
- private val _otherVpnRunning = MutableSharedFlow<ApplicationDescription>()
- suspend fun emitOtherVpnRunning(appDesc: ApplicationDescription) {
- _otherVpnRunning.emit(appDesc)
- }
+ val areAllTrackersBlocked: MutableStateFlow<Boolean> = MutableStateFlow(false)
- val otherVpnRunning: SharedFlow<ApplicationDescription> = _otherVpnRunning
+ private val _fakeLocationEnabled = MutableStateFlow(sharedPref.getBoolean(KEY_FAKE_LOCATION, true))
- var quickPrivacyEnabledFlow: StateFlow<Boolean> = quickPrivacyEnabledMutableFlow
+ val fakeLocationEnabled = _fakeLocationEnabled.asStateFlow()
- val areAllTrackersBlocked: MutableStateFlow<Boolean> = MutableStateFlow(false)
+ fun setFakeLocationEnabled(enabled: Boolean) {
+ set(KEY_FAKE_LOCATION, enabled)
+ _fakeLocationEnabled.update { enabled }
+ }
- var fakeLocation: Pair<Float, Float>?
- get() = if (sharedPref.getBoolean(KEY_FAKE_LOCATION, true))
- Pair(
- // Initial default value is Quezon City
- sharedPref.getFloat(KEY_FAKE_LATITUDE, 14.6760f),
- sharedPref.getFloat(KEY_FAKE_LONGITUDE, 121.0437f)
- )
- else null
+ var fakeLocation: Pair<Float, Float>
+ get() = Pair(
+ // Initial default value is Quezon City
+ sharedPref.getFloat(KEY_FAKE_LATITUDE, 14.6760f),
+ sharedPref.getFloat(KEY_FAKE_LONGITUDE, 121.0437f)
+ )
set(value) {
- if (value == null) {
- sharedPref.edit()
- .putBoolean(KEY_FAKE_LOCATION, false)
- .remove(KEY_FAKE_LATITUDE)
- .remove(KEY_FAKE_LONGITUDE)
- .commit()
- } else {
- sharedPref.edit()
- .putBoolean(KEY_FAKE_LOCATION, true)
- .putFloat(KEY_FAKE_LATITUDE, value.first)
- .putFloat(KEY_FAKE_LONGITUDE, value.second)
- .commit()
- }
+ sharedPref.edit()
+ .putFloat(KEY_FAKE_LATITUDE, value.first)
+ .putFloat(KEY_FAKE_LONGITUDE, value.second)
+ .apply()
}
val locationMode: MutableStateFlow<LocationMode> = MutableStateFlow(LocationMode.REAL_LOCATION)
- private val _ipScramblingSetting = MutableStateFlow(sharedPref.getBoolean(KEY_IP_SCRAMBLING, true))
+ private val _ipScramblingSetting = MutableStateFlow(sharedPref.getBoolean(KEY_IP_SCRAMBLING, false))
val ipScramblingSetting = _ipScramblingSetting.asStateFlow()
+ fun isIpScramblingFirstActivation(enabled: Boolean): Boolean {
+ return enabled && !sharedPref.contains(KEY_IP_SCRAMBLING)
+ }
+
fun setIpScramblingSetting(enabled: Boolean) {
set(KEY_IP_SCRAMBLING, enabled)
_ipScramblingSetting.update { enabled }
@@ -100,18 +89,17 @@ class LocalStateRepository(context: Context) {
val internetPrivacyMode: MutableStateFlow<InternetPrivacyMode> = MutableStateFlow(InternetPrivacyMode.REAL_IP)
- private val _showQuickPrivacyDisabledMessage = MutableStateFlow(false)
- val showQuickPrivacyDisabledMessage: StateFlow<Boolean> = _showQuickPrivacyDisabledMessage
-
- fun setShowQuickPrivacyDisabledMessage(show: Boolean) {
- _showQuickPrivacyDisabledMessage.value = show
+ private val _otherVpnRunning = MutableSharedFlow<ApplicationDescription>()
+ suspend fun emitOtherVpnRunning(appDesc: ApplicationDescription) {
+ _otherVpnRunning.emit(appDesc)
}
+ val otherVpnRunning: SharedFlow<ApplicationDescription> = _otherVpnRunning
var firstBoot: Boolean
get() = sharedPref.getBoolean(KEY_FIRST_BOOT, true)
set(value) = set(KEY_FIRST_BOOT, value)
private fun set(key: String, value: Boolean) {
- sharedPref.edit().putBoolean(key, value).commit()
+ sharedPref.edit().putBoolean(key, value).apply()
}
}
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
index 534bb2f..f849d57 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/domain/entities/InternetPrivacyMode.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/entities/InternetPrivacyMode.kt
@@ -21,5 +21,9 @@ enum class InternetPrivacyMode {
REAL_IP,
HIDE_IP,
HIDE_IP_LOADING,
- REAL_IP_LOADING
+ REAL_IP_LOADING;
+
+ val isChecked get() = this == HIDE_IP || this == HIDE_IP_LOADING
+
+ val isLoading get() = this == HIDE_IP_LOADING || this == REAL_IP_LOADING
}
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 e9da855..2910f26 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
@@ -57,7 +57,7 @@ class FakeLocationStateUseCase(
init {
coroutineScope.launch {
- localStateRepository.quickPrivacyEnabledFlow.collect {
+ localStateRepository.fakeLocationEnabled.collect {
applySettings(it, localStateRepository.fakeLocation)
}
}
@@ -71,10 +71,10 @@ class FakeLocationStateUseCase(
permissionsModule.toggleDangerousPermission(appDesc, android.Manifest.permission.ACCESS_FINE_LOCATION, true)
}
- private fun applySettings(isQuickPrivacyEnabled: Boolean, fakeLocation: Pair<Float, Float>?, isSpecificLocation: Boolean = false) {
- _configuredLocationMode.value = computeLocationMode(fakeLocation, isSpecificLocation)
+ private fun applySettings(isEnabled: Boolean, fakeLocation: Pair<Float, Float>, isSpecificLocation: Boolean = false) {
+ _configuredLocationMode.value = computeLocationMode(isEnabled, fakeLocation, isSpecificLocation)
- if (isQuickPrivacyEnabled && fakeLocation != null && hasAcquireMockLocationPermission()) {
+ if (isEnabled && hasAcquireMockLocationPermission()) {
fakeLocationModule.startFakeLocation()
fakeLocationModule.setFakeLocation(fakeLocation.first.toDouble(), fakeLocation.second.toDouble())
localStateRepository.locationMode.value = configuredLocationMode.value.first
@@ -90,18 +90,10 @@ class FakeLocationStateUseCase(
}
fun setSpecificLocation(latitude: Float, longitude: Float) {
- if (!localStateRepository.isQuickPrivacyEnabled) {
- localStateRepository.setShowQuickPrivacyDisabledMessage(true)
- }
-
setFakeLocation(latitude to longitude, true)
}
fun setRandomLocation() {
- if (!localStateRepository.isQuickPrivacyEnabled) {
- localStateRepository.setShowQuickPrivacyDisabledMessage(true)
- }
-
val randomIndex = Random.nextInt(citiesRepository.citiesLocationsList.size)
val location = citiesRepository.citiesLocationsList[randomIndex]
@@ -110,26 +102,29 @@ class FakeLocationStateUseCase(
private fun setFakeLocation(location: Pair<Float, Float>, isSpecificLocation: Boolean = false) {
localStateRepository.fakeLocation = location
- applySettings(localStateRepository.isQuickPrivacyEnabled, location, isSpecificLocation)
+ localStateRepository.setFakeLocationEnabled(true)
+ applySettings(true, location, isSpecificLocation)
}
fun stopFakeLocation() {
- if (!localStateRepository.isQuickPrivacyEnabled) {
- localStateRepository.setShowQuickPrivacyDisabledMessage(true)
- }
-
- localStateRepository.fakeLocation = null
- applySettings(localStateRepository.isQuickPrivacyEnabled, null)
+ localStateRepository.setFakeLocationEnabled(false)
+ applySettings(false, localStateRepository.fakeLocation)
}
- private fun computeLocationMode(fakeLocation: Pair<Float, Float>?, isSpecificLocation: Boolean = false): Triple<LocationMode, Float?, Float?> {
+ private fun computeLocationMode(
+ isFakeLocationEnabled: Boolean,
+ fakeLocation: Pair<Float, Float>,
+ isSpecificLocation: Boolean = false,
+ ): Triple<LocationMode, Float?, Float?> {
return Triple(
when {
- fakeLocation == null -> LocationMode.REAL_LOCATION
- fakeLocation in citiesRepository.citiesLocationsList && !isSpecificLocation -> LocationMode.RANDOM_LOCATION
+ !isFakeLocationEnabled -> LocationMode.REAL_LOCATION
+ (fakeLocation in citiesRepository.citiesLocationsList && !isSpecificLocation) ->
+ LocationMode.RANDOM_LOCATION
else -> LocationMode.SPECIFIC_LOCATION
},
- fakeLocation?.first, fakeLocation?.second
+ fakeLocation.first,
+ fakeLocation.second
)
}
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 46e054e..85410d0 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
@@ -23,88 +23,69 @@ import foundation.e.privacycentralapp.domain.entities.LocationMode
import foundation.e.privacycentralapp.domain.entities.QuickPrivacyState
import foundation.e.privacycentralapp.domain.entities.TrackerMode
import foundation.e.privacymodules.permissions.data.ApplicationDescription
-import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.launch
+import kotlinx.coroutines.flow.map
class GetQuickPrivacyStateUseCase(
- private val localStateRepository: LocalStateRepository,
- coroutineScope: CoroutineScope
+ private val localStateRepository: LocalStateRepository
) {
-
- init {
- coroutineScope.launch {
- localStateRepository.quickPrivacyEnabledFlow.collect {
- if (it) resetQuickPrivacyDisabledMessage()
- }
- }
- }
-
- val quickPrivacyEnabledFlow: Flow<Boolean> = localStateRepository.quickPrivacyEnabledFlow
-
- val isQuickPrivacyEnabled: Boolean get() = localStateRepository.isQuickPrivacyEnabled
-
val quickPrivacyState: Flow<QuickPrivacyState> = combine(
- localStateRepository.quickPrivacyEnabledFlow,
+ localStateRepository.blockTrackers,
localStateRepository.areAllTrackersBlocked,
localStateRepository.locationMode,
localStateRepository.internetPrivacyMode
- ) { isQuickPrivacyEnabled, isAllTrackersBlocked, locationMode, internetPrivacyMode ->
+ ) { isBlockTrackers, isAllTrackersBlocked, locationMode, internetPrivacyMode ->
when {
- !isQuickPrivacyEnabled -> QuickPrivacyState.DISABLED
+ !isBlockTrackers &&
+ locationMode == LocationMode.REAL_LOCATION &&
+ internetPrivacyMode == InternetPrivacyMode.REAL_IP -> QuickPrivacyState.DISABLED
+
isAllTrackersBlocked &&
locationMode != LocationMode.REAL_LOCATION &&
internetPrivacyMode in listOf(
InternetPrivacyMode.HIDE_IP,
InternetPrivacyMode.HIDE_IP_LOADING
) -> QuickPrivacyState.FULL_ENABLED
+
else -> QuickPrivacyState.ENABLED
}
}
val trackerMode: Flow<TrackerMode> = combine(
- localStateRepository.quickPrivacyEnabledFlow,
+ localStateRepository.blockTrackers,
localStateRepository.areAllTrackersBlocked
- ) { isQuickPrivacyEnabled, isAllTrackersBlocked ->
+ ) { isBlockTrackers, isAllTrackersBlocked ->
when {
- isQuickPrivacyEnabled && isAllTrackersBlocked -> TrackerMode.DENIED
- isQuickPrivacyEnabled && !isAllTrackersBlocked -> TrackerMode.CUSTOM
+ isBlockTrackers && isAllTrackersBlocked -> TrackerMode.DENIED
+ isBlockTrackers && !isAllTrackersBlocked -> TrackerMode.CUSTOM
else -> TrackerMode.VULNERABLE
}
}
- val isLocationHidden: Flow<Boolean> = combine(
- localStateRepository.quickPrivacyEnabledFlow,
- localStateRepository.locationMode
- ) { isQuickPrivacyEnabled, locationMode ->
- isQuickPrivacyEnabled && locationMode != LocationMode.REAL_LOCATION
+ val isLocationHidden: Flow<Boolean> = localStateRepository.locationMode.map { locationMode ->
+ locationMode != LocationMode.REAL_LOCATION
}
val locationMode: StateFlow<LocationMode> = localStateRepository.locationMode
- val isIpHidden: Flow<Boolean?> = combine(
- localStateRepository.quickPrivacyEnabledFlow,
- localStateRepository.internetPrivacyMode
- ) { isQuickPrivacyEnabled, internetPrivacyMode ->
- when {
- !isQuickPrivacyEnabled || internetPrivacyMode == InternetPrivacyMode.REAL_IP -> false
- internetPrivacyMode == InternetPrivacyMode.HIDE_IP -> true
- else -> null
- }
- }
+ val ipScramblingMode: Flow<InternetPrivacyMode> = localStateRepository.internetPrivacyMode
- fun toggleReturnIsFirstActivation(): Boolean {
- val newState = !localStateRepository.isQuickPrivacyEnabled
- return localStateRepository.setQuickPrivacyReturnIsFirstActivation(newState)
+ fun toggleTrackers() {
+ localStateRepository.setBlockTrackers(!localStateRepository.blockTrackers.value)
}
- val showQuickPrivacyDisabledMessage: StateFlow<Boolean> = localStateRepository.showQuickPrivacyDisabledMessage
+ fun toggleLocation() {
+ localStateRepository.setFakeLocationEnabled(!localStateRepository.fakeLocationEnabled.value)
+ }
- fun resetQuickPrivacyDisabledMessage() {
- localStateRepository.setShowQuickPrivacyDisabledMessage(false)
+ fun toggleIpScramblingIsFirstActivation(): Boolean {
+ val enabled = !localStateRepository.ipScramblingSetting.value
+ val firstActivation = localStateRepository.isIpScramblingFirstActivation(enabled)
+ localStateRepository.setIpScramblingSetting(enabled)
+ return firstActivation
}
val otherVpnRunning: SharedFlow<ApplicationDescription> = localStateRepository.otherVpnRunning
diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt
index cb9fcd5..9216233 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt
@@ -28,6 +28,7 @@ import foundation.e.privacymodules.ipscramblermodule.IIpScramblerModule
import foundation.e.privacymodules.permissions.IPermissionsPrivacyModule
import foundation.e.privacymodules.permissions.data.ApplicationDescription
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -43,9 +44,6 @@ class IpScramblingStateUseCase(
private val appListsRepository: AppListsRepository,
private val coroutineScope: CoroutineScope
) {
-
- val configuredMode: StateFlow<Boolean> = localStateRepository.ipScramblingSetting
-
val internetPrivacyMode: StateFlow<InternetPrivacyMode> = callbackFlow {
val listener = object : IIpScramblerModule.Listener {
override fun onStatusChanged(newStatus: IIpScramblerModule.Status) {
@@ -67,13 +65,13 @@ class IpScramblingStateUseCase(
}.stateIn(
scope = coroutineScope,
started = SharingStarted.Eagerly,
- initialValue = InternetPrivacyMode.REAL_IP
+ initialValue = REAL_IP
)
init {
- coroutineScope.launch {
- localStateRepository.quickPrivacyEnabledFlow.collect {
- applySettings(it, localStateRepository.ipScramblingSetting.value)
+ coroutineScope.launch(Dispatchers.Default) {
+ localStateRepository.ipScramblingSetting.collect {
+ applySettings(it)
}
}
@@ -84,12 +82,7 @@ class IpScramblingStateUseCase(
fun toggle(hideIp: Boolean) {
localStateRepository.setIpScramblingSetting(enabled = hideIp)
-
- if (!localStateRepository.isQuickPrivacyEnabled) {
- localStateRepository.setShowQuickPrivacyDisabledMessage(true)
- } else {
- applySettings(true, hideIp)
- }
+ applySettings(hideIp)
}
private fun getHiddenPackageNames(): List<String> {
@@ -129,15 +122,13 @@ class IpScramblingStateUseCase(
ipScramblerModule.appList = rawList
}
- private fun applySettings(isQuickPrivacyEnabled: Boolean, isIpScramblingEnabled: Boolean) {
- val settingEnabled = isQuickPrivacyEnabled && isIpScramblingEnabled
+ private fun applySettings(isIpScramblingEnabled: Boolean) {
val currentMode = localStateRepository.internetPrivacyMode.value
-
when {
- settingEnabled && currentMode in setOf(REAL_IP, REAL_IP_LOADING) ->
+ isIpScramblingEnabled && currentMode in setOf(REAL_IP, REAL_IP_LOADING) ->
applyStartIpScrambling()
- !settingEnabled && currentMode in setOf(HIDE_IP, HIDE_IP_LOADING) ->
+ !isIpScramblingEnabled && currentMode in setOf(HIDE_IP, HIDE_IP_LOADING) ->
ipScramblerModule.stop()
else -> {}
@@ -162,11 +153,11 @@ class IpScramblingStateUseCase(
private fun map(status: IIpScramblerModule.Status): InternetPrivacyMode {
return when (status) {
- IIpScramblerModule.Status.OFF -> InternetPrivacyMode.REAL_IP
- IIpScramblerModule.Status.ON -> InternetPrivacyMode.HIDE_IP
- IIpScramblerModule.Status.STARTING -> InternetPrivacyMode.HIDE_IP_LOADING
+ IIpScramblerModule.Status.OFF -> REAL_IP
+ IIpScramblerModule.Status.ON -> HIDE_IP
+ IIpScramblerModule.Status.STARTING -> HIDE_IP_LOADING
IIpScramblerModule.Status.STOPPING,
- IIpScramblerModule.Status.START_DISABLED -> InternetPrivacyMode.REAL_IP_LOADING
+ IIpScramblerModule.Status.START_DISABLED -> REAL_IP_LOADING
}
}
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt
index 17e5096..8b37152 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt
@@ -38,7 +38,7 @@ class TrackersStateUseCase(
init {
trackersPrivacyModule.start(trackersRepository.trackers, enableNotification = false)
coroutineScope.launch {
- localStateRepository.quickPrivacyEnabledFlow.collect { enabled ->
+ localStateRepository.blockTrackers.collect { enabled ->
if (enabled) {
blockTrackersPrivacyModule.enableBlocking()
} else {
@@ -76,10 +76,6 @@ class TrackersStateUseCase(
}
fun toggleAppWhitelist(appUid: Int, isWhitelisted: Boolean) {
- if (!localStateRepository.isQuickPrivacyEnabled) {
- localStateRepository.setShowQuickPrivacyDisabledMessage(true)
- }
-
if (appUid == appListsRepository.dummySystemApp.uid) {
appListsRepository.getHiddenSystemApps().forEach {
blockTrackersPrivacyModule.setWhiteListed(it.uid, isWhitelisted)
@@ -90,9 +86,6 @@ class TrackersStateUseCase(
}
fun blockTracker(appUid: Int, tracker: Tracker, isBlocked: Boolean) {
- if (!localStateRepository.isQuickPrivacyEnabled) {
- localStateRepository.setShowQuickPrivacyDisabledMessage(true)
- }
if (appUid == appListsRepository.dummySystemApp.uid) {
appListsRepository.getHiddenSystemApps().forEach {
blockTrackersPrivacyModule.setWhiteListed(tracker, it.uid, !isBlocked)
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 6cd259e..8a0a3d4 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
@@ -32,14 +32,13 @@ import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
-import com.google.android.material.snackbar.Snackbar
import foundation.e.privacycentralapp.DependencyContainer
import foundation.e.privacycentralapp.PrivacyCentralApplication
import foundation.e.privacycentralapp.R
import foundation.e.privacycentralapp.common.GraphHolder
import foundation.e.privacycentralapp.common.NavToolbarFragment
-import foundation.e.privacycentralapp.common.initQuickPrivacySnackbar
import foundation.e.privacycentralapp.databinding.FragmentDashboardBinding
+import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
import foundation.e.privacycentralapp.domain.entities.LocationMode
import foundation.e.privacycentralapp.domain.entities.QuickPrivacyState
import foundation.e.privacycentralapp.domain.entities.TrackerMode
@@ -72,8 +71,6 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
private var _binding: FragmentDashboardBinding? = null
private val binding get() = _binding!!
- private var qpDisabledSnackbar: Snackbar? = null
-
private var highlightIndexOnStart: Int? = null
override fun onCreate(savedInstanceState: Bundle?) {
@@ -91,8 +88,14 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
binding.leakingAppButton.setOnClickListener {
viewModel.submitAction(Action.ShowMostLeakedApp)
}
- binding.togglePrivacyCentral.setOnClickListener {
- viewModel.submitAction(Action.TogglePrivacyAction)
+ binding.toggleTrackers.setOnClickListener {
+ viewModel.submitAction(Action.ToggleTrackers)
+ }
+ binding.toggleLocation.setOnClickListener {
+ viewModel.submitAction(Action.ToggleLocation)
+ }
+ binding.toggleIpscrambling.setOnClickListener {
+ viewModel.submitAction(Action.ToggleIpScrambling)
}
binding.myLocation.container.setOnClickListener {
viewModel.submitAction(Action.ShowFakeMyLocationAction)
@@ -108,10 +111,6 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
viewModel.submitAction(Action.ShowTrackers)
}
- qpDisabledSnackbar = initQuickPrivacySnackbar(binding.root) {
- viewModel.submitAction(Action.CloseQuickPrivacyDisabledMessage)
- }
-
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
render(viewModel.state.value)
@@ -185,9 +184,6 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
}
private fun render(state: DashboardState) {
- if (state.showQuickPrivacyDisabledMessage) qpDisabledSnackbar?.show()
- else qpDisabledSnackbar?.dismiss()
-
binding.stateLabel.text = getString(
when (state.quickPrivacyState) {
QuickPrivacyState.DISABLED -> R.string.dashboard_state_title_off
@@ -201,7 +197,7 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
else R.drawable.ic_shield_off
)
- binding.togglePrivacyCentral.isChecked = state.quickPrivacyState.isEnabled()
+ binding.toggleTrackers.isChecked = state.trackerMode != TrackerMode.VULNERABLE
binding.stateTrackers.text = getString(
when (state.trackerMode) {
@@ -218,6 +214,8 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
)
)
+ binding.toggleLocation.isChecked = state.isLocationHidden
+
binding.stateGeolocation.text = getString(
if (state.isLocationHidden) R.string.dashboard_state_geolocation_on
else R.string.dashboard_state_geolocation_off
@@ -230,10 +228,11 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
)
)
- val isLoading = state.isIpHidden == null
+ binding.toggleIpscrambling.isChecked = state.ipScramblingMode.isChecked
+ val isLoading = state.ipScramblingMode.isLoading
binding.stateIpAddress.text = getString(
- if (state.isIpHidden == true) R.string.dashboard_state_ipaddress_on
+ if (state.ipScramblingMode == InternetPrivacyMode.HIDE_IP) R.string.dashboard_state_ipaddress_on
else R.string.dashboard_state_ipaddress_off
)
@@ -243,7 +242,7 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
binding.stateIpAddress.setTextColor(
getColor(
requireContext(),
- if (state.isIpHidden == true) R.color.green_valid
+ if (state.ipScramblingMode == InternetPrivacyMode.HIDE_IP) R.color.green_valid
else R.color.red_off
)
)
@@ -292,7 +291,7 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
)
binding.internetActivityPrivacy.subTitle = getString(
- if (state.isIpHidden == true) R.string.dashboard_internet_activity_privacy_subtitle_on
+ if (state.ipScramblingMode == InternetPrivacyMode.HIDE_IP) R.string.dashboard_internet_activity_privacy_subtitle_on
else R.string.dashboard_internet_activity_privacy_subtitle_off
)
@@ -301,7 +300,6 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
override fun onDestroyView() {
super.onDestroyView()
- qpDisabledSnackbar = null
graphHolder = null
_binding = null
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardState.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardState.kt
index 04b7ae8..937fa22 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardState.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardState.kt
@@ -17,6 +17,7 @@
package foundation.e.privacycentralapp.features.dashboard
+import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
import foundation.e.privacycentralapp.domain.entities.LocationMode
import foundation.e.privacycentralapp.domain.entities.QuickPrivacyState
import foundation.e.privacycentralapp.domain.entities.TrackerMode
@@ -25,12 +26,11 @@ data class DashboardState(
val quickPrivacyState: QuickPrivacyState = QuickPrivacyState.DISABLED,
val trackerMode: TrackerMode = TrackerMode.VULNERABLE,
val isLocationHidden: Boolean = false,
- val isIpHidden: Boolean? = false,
+ val ipScramblingMode: InternetPrivacyMode = InternetPrivacyMode.REAL_IP_LOADING,
val locationMode: LocationMode = LocationMode.REAL_LOCATION,
val leakedTrackersCount: Int? = null,
val trackersCount: Int? = null,
val allowedTrackersCount: Int? = null,
val dayStatistics: List<Pair<Int, Int>>? = null,
val dayLabels: List<String>? = null,
- val showQuickPrivacyDisabledMessage: Boolean = false
)
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 d7d74c6..57e7790 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
@@ -25,6 +25,7 @@ import foundation.e.privacycentralapp.domain.usecases.GetQuickPrivacyStateUseCas
import foundation.e.privacycentralapp.domain.usecases.TrackersStatisticsUseCase
import foundation.e.privacymodules.permissions.data.ApplicationDescription
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -58,8 +59,8 @@ class DashboardViewModel(
getPrivacyStateUseCase.quickPrivacyState.map {
_state.update { s -> s.copy(quickPrivacyState = it) }
},
- getPrivacyStateUseCase.isIpHidden.map {
- _state.update { s -> s.copy(isIpHidden = it) }
+ getPrivacyStateUseCase.ipScramblingMode.map {
+ _state.update { s -> s.copy(ipScramblingMode = it) }
},
trackersStatisticsUseCase.listenUpdates().flatMapLatest {
fetchStatistics()
@@ -73,9 +74,6 @@ class DashboardViewModel(
getPrivacyStateUseCase.locationMode.map {
_state.update { s -> s.copy(locationMode = it) }
},
- getPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map {
- _state.update { s -> s.copy(showQuickPrivacyDisabledMessage = it) }
- },
getPrivacyStateUseCase.otherVpnRunning.map {
_singleEvents.emit(
SingleEvent.ToastMessageSingleEvent(
@@ -89,7 +87,14 @@ class DashboardViewModel(
fun submitAction(action: Action) = viewModelScope.launch {
when (action) {
- is Action.TogglePrivacyAction -> actionTogglePrivacy()
+ is Action.ToggleTrackers -> {
+ getPrivacyStateUseCase.toggleTrackers()
+ // Add delay here to prevent race condition with trackers state.
+ delay(200)
+ fetchStatistics().first()
+ }
+ is Action.ToggleLocation -> getPrivacyStateUseCase.toggleLocation()
+ is Action.ToggleIpScrambling -> actionToggleIpScrambling()
is Action.ShowFakeMyLocationAction ->
_singleEvents.emit(SingleEvent.NavigateToLocationSingleEvent)
is Action.ShowAppsPermissions ->
@@ -98,8 +103,6 @@ class DashboardViewModel(
_singleEvents.emit(SingleEvent.NavigateToInternetActivityPrivacySingleEvent)
is Action.ShowTrackers ->
_singleEvents.emit(SingleEvent.NavigateToTrackersSingleEvent)
- is Action.CloseQuickPrivacyDisabledMessage ->
- getPrivacyStateUseCase.resetQuickPrivacyDisabledMessage()
is Action.ShowMostLeakedApp -> actionShowMostLeakedApp()
}
}
@@ -120,9 +123,8 @@ class DashboardViewModel(
}
}
- private suspend fun actionTogglePrivacy() = withContext(Dispatchers.IO) {
- val isFirstActivation = getPrivacyStateUseCase.toggleReturnIsFirstActivation()
- fetchStatistics().first()
+ private suspend fun actionToggleIpScrambling() = withContext(Dispatchers.IO) {
+ val isFirstActivation = getPrivacyStateUseCase.toggleIpScramblingIsFirstActivation()
if (isFirstActivation) _singleEvents.emit(
SingleEvent.ToastMessageSingleEvent(
@@ -152,12 +154,13 @@ class DashboardViewModel(
}
sealed class Action {
- object TogglePrivacyAction : Action()
+ object ToggleTrackers : Action()
+ object ToggleLocation : Action()
+ object ToggleIpScrambling : Action()
object ShowFakeMyLocationAction : Action()
object ShowInternetActivityPrivacyAction : Action()
object ShowAppsPermissions : Action()
object ShowTrackers : Action()
- object CloseQuickPrivacyDisabledMessage : Action()
object ShowMostLeakedApp : Action()
}
}
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 99aa217..afef986 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
@@ -27,13 +27,11 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager
-import com.google.android.material.snackbar.Snackbar
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.initQuickPrivacySnackbar
import foundation.e.privacycentralapp.common.setToolTipForAsterisk
import foundation.e.privacycentralapp.databinding.FragmentInternetActivityPolicyBinding
import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
@@ -53,8 +51,6 @@ class InternetPrivacyFragment : NavToolbarFragment(R.layout.fragment_internet_ac
private var _binding: FragmentInternetActivityPolicyBinding? = null
private val binding get() = _binding!!
- private var qpDisabledSnackbar: Snackbar? = null
-
private fun displayToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT)
.show()
@@ -120,10 +116,6 @@ class InternetPrivacyFragment : NavToolbarFragment(R.layout.fragment_internet_ac
}
}
- qpDisabledSnackbar = initQuickPrivacySnackbar(binding.root) {
- viewModel.submitAction(InternetPrivacyViewModel.Action.CloseQuickPrivacyDisabledMessage)
- }
-
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
render(viewModel.state.value)
@@ -152,9 +144,6 @@ class InternetPrivacyFragment : NavToolbarFragment(R.layout.fragment_internet_ac
override fun getTitle(): String = getString(R.string.ipscrambling_title)
private fun render(state: InternetPrivacyState) {
- if (state.showQuickPrivacyDisabledMessage) qpDisabledSnackbar?.show()
- else qpDisabledSnackbar?.dismiss()
-
binding.radioUseHiddenIp.radiobutton.apply {
isChecked = state.mode in listOf(
InternetPrivacyMode.HIDE_IP,
@@ -207,7 +196,6 @@ class InternetPrivacyFragment : NavToolbarFragment(R.layout.fragment_internet_ac
override fun onDestroyView() {
super.onDestroyView()
- qpDisabledSnackbar = null
_binding = null
}
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyState.kt b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyState.kt
index 6991196..54b7e01 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyState.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyState.kt
@@ -27,7 +27,6 @@ data class InternetPrivacyState(
val selectedLocation: String = "",
val availableLocationIds: List<String> = emptyList(),
val forceRedraw: Boolean = false,
- val showQuickPrivacyDisabledMessage: Boolean = false
) {
fun getApps(): List<Pair<ApplicationDescription, Boolean>> {
return availableApps.map { it to (it.packageName !in bypassTorApps) }
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyViewModel.kt b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyViewModel.kt
index be6cd4d..bbd6239 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyViewModel.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyViewModel.kt
@@ -73,9 +73,6 @@ class InternetPrivacyViewModel(
suspend fun doOnStartedState() = withContext(Dispatchers.IO) {
launch {
merge(
- getQuickPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map {
- _state.update { s -> s.copy(showQuickPrivacyDisabledMessage = it) }
- },
appListUseCase.getAppsUsingInternet().map { apps ->
_state.update { s ->
s.copy(
@@ -84,17 +81,8 @@ class InternetPrivacyViewModel(
)
}
},
- if (getQuickPrivacyStateUseCase.isQuickPrivacyEnabled)
- ipScramblingStateUseCase.internetPrivacyMode.map {
- _state.update { s -> s.copy(mode = it) }
- }
- else ipScramblingStateUseCase.configuredMode.map {
- _state.update { s ->
- s.copy(
- mode = if (it) InternetPrivacyMode.HIDE_IP
- else InternetPrivacyMode.REAL_IP
- )
- }
+ ipScramblingStateUseCase.internetPrivacyMode.map {
+ _state.update { s -> s.copy(mode = it) }
}
).collect {}
}
@@ -129,8 +117,6 @@ class InternetPrivacyViewModel(
is Action.UseHiddenIPAction -> actionUseHiddenIP()
is Action.ToggleAppIpScrambled -> actionToggleAppIpScrambled(action)
is Action.SelectLocationAction -> actionSelectLocation(action)
- is Action.CloseQuickPrivacyDisabledMessage ->
- getQuickPrivacyStateUseCase.resetQuickPrivacyDisabledMessage()
}
}
@@ -167,6 +153,5 @@ class InternetPrivacyViewModel(
object UseHiddenIPAction : Action()
data class ToggleAppIpScrambled(val packageName: String) : Action()
data class SelectLocationAction(val position: Int) : Action()
- object CloseQuickPrivacyDisabledMessage : Action()
}
}
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 537d0b6..9e3f854 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
@@ -33,7 +33,6 @@ import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
-import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import com.google.android.material.textfield.TextInputLayout.END_ICON_CUSTOM
@@ -52,7 +51,6 @@ 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.initQuickPrivacySnackbar
import foundation.e.privacycentralapp.databinding.FragmentFakeLocationBinding
import foundation.e.privacycentralapp.domain.entities.LocationMode
import foundation.e.privacycentralapp.features.location.FakeLocationViewModel.Action
@@ -79,8 +77,6 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
private var mapboxMap: MapboxMap? = null
private var locationComponent: LocationComponent? = null
- private var qpDisabledSnackbar: Snackbar? = null
-
private var inputJob: Job? = null
private val locationPermissionRequest = registerForActivityResult(
@@ -147,10 +143,6 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
}
}
- qpDisabledSnackbar = initQuickPrivacySnackbar(binding.root) {
- viewModel.submitAction(Action.CloseQuickPrivacyDisabledMessage)
- }
-
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
render(viewModel.state.value)
@@ -266,9 +258,6 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
@SuppressLint("MissingPermission")
private fun render(state: FakeLocationState) {
- if (state.showQuickPrivacyDisabledMessage) qpDisabledSnackbar?.show()
- else qpDisabledSnackbar?.dismiss()
-
binding.radioUseRandomLocation.isChecked = state.mode == LocationMode.RANDOM_LOCATION
binding.radioUseSpecificLocation.isChecked = state.mode == LocationMode.SPECIFIC_LOCATION
@@ -379,7 +368,6 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
override fun onDestroyView() {
super.onDestroyView()
binding.mapView.onDestroy()
- qpDisabledSnackbar = null
mapboxMap = null
locationComponent = null
inputJob = null
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationState.kt b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationState.kt
index 9513f77..50d7a14 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationState.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationState.kt
@@ -26,5 +26,4 @@ data class FakeLocationState(
val specificLatitude: Float? = null,
val specificLongitude: Float? = null,
val forceRefresh: Boolean = false,
- val showQuickPrivacyDisabledMessage: Boolean = false
)
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt
index 8db3537..1cdf9f4 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt
@@ -66,9 +66,6 @@ class FakeLocationViewModel(
)
}
},
- getQuickPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map {
- _state.update { s -> s.copy(showQuickPrivacyDisabledMessage = it) }
- },
specificLocationInputFlow
.debounce(SET_SPECIFIC_LOCATION_DELAY).map { action ->
fakeLocationStateUseCase.setSpecificLocation(action.latitude, action.longitude)
@@ -96,8 +93,6 @@ class FakeLocationViewModel(
is Action.UseRandomLocationAction -> fakeLocationStateUseCase.setRandomLocation()
is Action.UseRealLocationAction ->
fakeLocationStateUseCase.stopFakeLocation()
- is Action.CloseQuickPrivacyDisabledMessage ->
- getQuickPrivacyStateUseCase.resetQuickPrivacyDisabledMessage()
}
}
@@ -127,6 +122,5 @@ class FakeLocationViewModel(
val latitude: Float,
val longitude: Float
) : Action()
- object CloseQuickPrivacyDisabledMessage : Action()
}
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFragment.kt
index 491f625..8adf256 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFragment.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersFragment.kt
@@ -28,14 +28,12 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager
-import com.google.android.material.snackbar.Snackbar
import foundation.e.privacycentralapp.DependencyContainer
import foundation.e.privacycentralapp.PrivacyCentralApplication
import foundation.e.privacycentralapp.R
import foundation.e.privacycentralapp.common.AppsAdapter
import foundation.e.privacycentralapp.common.GraphHolder
import foundation.e.privacycentralapp.common.NavToolbarFragment
-import foundation.e.privacycentralapp.common.initQuickPrivacySnackbar
import foundation.e.privacycentralapp.common.setToolTipForAsterisk
import foundation.e.privacycentralapp.databinding.FragmentTrackersBinding
import foundation.e.privacycentralapp.databinding.TrackersItemGraphBinding
@@ -58,7 +56,6 @@ class TrackersFragment :
private var dayGraphHolder: GraphHolder? = null
private var monthGraphHolder: GraphHolder? = null
private var yearGraphHolder: GraphHolder? = null
- private var qpDisabledSnackbar: Snackbar? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -79,10 +76,6 @@ class TrackersFragment :
}
}
- qpDisabledSnackbar = initQuickPrivacySnackbar(binding.root) {
- viewModel.submitAction(TrackersViewModel.Action.CloseQuickPrivacyDisabledMessage)
- }
-
setToolTipForAsterisk(
textView = binding.trackersAppsListTitle,
textId = R.string.trackers_applist_title,
@@ -137,9 +130,6 @@ class TrackersFragment :
override fun getTitle() = getString(R.string.trackers_title)
private fun render(state: TrackersState) {
- if (state.showQuickPrivacyDisabledMessage) qpDisabledSnackbar?.show()
- else qpDisabledSnackbar?.dismiss()
-
state.dayStatistics?.let { renderGraph(it, dayGraphHolder!!, binding.graphDay) }
state.monthStatistics?.let { renderGraph(it, monthGraphHolder!!, binding.graphMonth) }
state.yearStatistics?.let { renderGraph(it, yearGraphHolder!!, binding.graphYear) }
@@ -171,7 +161,6 @@ class TrackersFragment :
override fun onDestroyView() {
super.onDestroyView()
- qpDisabledSnackbar = null
dayGraphHolder = null
monthGraphHolder = null
yearGraphHolder = null
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersState.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersState.kt
index 2437366..a3bb80a 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersState.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersState.kt
@@ -25,5 +25,4 @@ data class TrackersState(
val monthStatistics: TrackersPeriodicStatistics? = null,
val yearStatistics: TrackersPeriodicStatistics? = null,
val apps: List<AppWithCounts>? = null,
- val showQuickPrivacyDisabledMessage: Boolean = false
)
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersViewModel.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersViewModel.kt
index 3869c39..07828f8 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersViewModel.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/TrackersViewModel.kt
@@ -46,9 +46,6 @@ class TrackersViewModel(
suspend fun doOnStartedState() = withContext(Dispatchers.IO) {
merge(
- getQuickPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map {
- _state.update { s -> s.copy(showQuickPrivacyDisabledMessage = it) }
- },
trackersStatisticsUseCase.listenUpdates().map {
trackersStatisticsUseCase.getDayMonthYearStatistics()
.let { (day, month, year) ->
@@ -70,9 +67,6 @@ class TrackersViewModel(
fun submitAction(action: Action) = viewModelScope.launch {
when (action) {
is Action.ClickAppAction -> actionClickApp(action)
- is Action.CloseQuickPrivacyDisabledMessage -> {
- getQuickPrivacyStateUseCase.resetQuickPrivacyDisabledMessage()
- }
}
}
@@ -89,6 +83,5 @@ class TrackersViewModel(
sealed class Action {
data class ClickAppAction(val packageName: String) : Action()
- object CloseQuickPrivacyDisabledMessage : Action()
}
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt
index cd4f6b2..6aeac8e 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFragment.kt
@@ -34,7 +34,6 @@ 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.initQuickPrivacySnackbar
import foundation.e.privacycentralapp.databinding.ApptrackersFragmentBinding
import kotlinx.coroutines.launch
@@ -63,8 +62,6 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) {
private var _binding: ApptrackersFragmentBinding? = null
private val binding get() = _binding!!
- private var qpDisabledSnackbar: Snackbar? = null
-
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (arguments == null ||
@@ -101,10 +98,6 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) {
)
}
- qpDisabledSnackbar = initQuickPrivacySnackbar(binding.root) {
- viewModel.submitAction(AppTrackersViewModel.Action.CloseQuickPrivacyDisabledMessage)
- }
-
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.singleEvents.collect { event ->
@@ -117,6 +110,12 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) {
} catch (e: ActivityNotFoundException) {
displayToast("No application to see webpages")
}
+ is AppTrackersViewModel.SingleEvent.ToastTrackersControlDisabled ->
+ Snackbar.make(
+ binding.root,
+ R.string.apptrackers_tracker_control_disabled_message,
+ Snackbar.LENGTH_LONG
+ ).show()
}
}
}
@@ -137,9 +136,6 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) {
}
private fun render(state: AppTrackersState) {
- if (state.showQuickPrivacyDisabledMessage) qpDisabledSnackbar?.show()
- else qpDisabledSnackbar?.dismiss()
-
binding.trackersCountSummary.text = if (state.getTrackersCount() == 0) ""
else getString(
R.string.apptrackers_trackers_count_summary,
@@ -176,7 +172,6 @@ class AppTrackersFragment : NavToolbarFragment(R.layout.apptrackers_fragment) {
override fun onDestroyView() {
super.onDestroyView()
- qpDisabledSnackbar = null
_binding = null
}
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersState.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersState.kt
index d6d0858..8088443 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersState.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersState.kt
@@ -26,7 +26,7 @@ data class AppTrackersState(
val trackersWithWhiteList: List<Pair<Tracker, Boolean>>? = null,
val leaked: Int = 0,
val blocked: Int = 0,
- val isQuickPrivacyEnabled: Boolean = false,
+ val isTrackersBlockingEnabled: Boolean = false,
val showQuickPrivacyDisabledMessage: Boolean = false,
) {
fun getTrackersStatus(): List<Pair<Tracker, Boolean>>? {
@@ -34,7 +34,7 @@ data class AppTrackersState(
}
fun getTrackersCount() = trackersWithWhiteList?.size ?: 0
- fun getBlockedTrackersCount(): Int = if (isQuickPrivacyEnabled && isBlockingActivated)
+ fun getBlockedTrackersCount(): Int = if (isTrackersBlockingEnabled && isBlockingActivated)
trackersWithWhiteList?.count { !it.second } ?: 0
else 0
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersViewModel.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersViewModel.kt
index 52ef2c4..1a33844 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersViewModel.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersViewModel.kt
@@ -21,6 +21,7 @@ import android.net.Uri
import androidx.annotation.StringRes
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
+import foundation.e.privacycentralapp.domain.entities.TrackerMode
import foundation.e.privacycentralapp.domain.usecases.GetQuickPrivacyStateUseCase
import foundation.e.privacycentralapp.domain.usecases.TrackersStateUseCase
import foundation.e.privacycentralapp.domain.usecases.TrackersStatisticsUseCase
@@ -66,11 +67,8 @@ class AppTrackersViewModel(
suspend fun doOnStartedState() = withContext(Dispatchers.IO) {
merge(
- getQuickPrivacyStateUseCase.quickPrivacyEnabledFlow.map {
- _state.update { s -> s.copy(isQuickPrivacyEnabled = it) }
- },
- getQuickPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map {
- _state.update { s -> s.copy(showQuickPrivacyDisabledMessage = it) }
+ getQuickPrivacyStateUseCase.trackerMode.map {
+ _state.update { s -> s.copy(isTrackersBlockingEnabled = it != TrackerMode.VULNERABLE) }
},
trackersStatisticsUseCase.listenUpdates().map { fetchStatistics() }
).collect { }
@@ -81,13 +79,14 @@ class AppTrackersViewModel(
is Action.BlockAllToggleAction -> blockAllToggleAction(action)
is Action.ToggleTrackerAction -> toggleTrackerAction(action)
is Action.ClickTracker -> actionClickTracker(action)
- is Action.CloseQuickPrivacyDisabledMessage ->
- getQuickPrivacyStateUseCase.resetQuickPrivacyDisabledMessage()
}
}
private suspend fun blockAllToggleAction(action: Action.BlockAllToggleAction) {
withContext(Dispatchers.IO) {
+ if (!state.value.isTrackersBlockingEnabled) {
+ _singleEvents.emit(SingleEvent.ToastTrackersControlDisabled)
+ }
trackersStateUseCase.toggleAppWhitelist(appUid, !action.isBlocked)
_state.update {
it.copy(
@@ -99,6 +98,10 @@ class AppTrackersViewModel(
private suspend fun toggleTrackerAction(action: Action.ToggleTrackerAction) {
withContext(Dispatchers.IO) {
+ if (!state.value.isTrackersBlockingEnabled) {
+ _singleEvents.emit(SingleEvent.ToastTrackersControlDisabled)
+ }
+
if (state.value.isBlockingActivated) {
trackersStateUseCase.blockTracker(appUid, action.tracker, action.isBlocked)
_state.update {
@@ -141,12 +144,12 @@ class AppTrackersViewModel(
sealed class SingleEvent {
data class ErrorEvent(@StringRes val errorResId: Int) : SingleEvent()
data class OpenUrl(val url: Uri) : SingleEvent()
+ object ToastTrackersControlDisabled : SingleEvent()
}
sealed class Action {
data class BlockAllToggleAction(val isBlocked: Boolean) : Action()
data class ToggleTrackerAction(val tracker: Tracker, val isBlocked: Boolean) : Action()
data class ClickTracker(val tracker: Tracker) : Action()
- object CloseQuickPrivacyDisabledMessage : Action()
}
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt b/app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt
index 58ac797..a81f5b5 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/main/MainActivity.kt
@@ -24,7 +24,6 @@ import android.os.Bundle
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.add
import androidx.fragment.app.commit
-import foundation.e.privacycentralapp.PrivacyCentralApplication
import foundation.e.privacycentralapp.R
import foundation.e.privacycentralapp.features.dashboard.DashboardFragment
import foundation.e.privacycentralapp.features.trackers.TrackersFragment
@@ -37,11 +36,6 @@ open class MainActivity : FragmentActivity(R.layout.activity_main) {
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
-
- (application as? PrivacyCentralApplication)
- ?.dependencyContainer?.getQuickPrivacyStateUseCase
- ?.resetQuickPrivacyDisabledMessage()
-
handleIntent(intent)
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/widget/Widget.kt b/app/src/main/java/foundation/e/privacycentralapp/widget/Widget.kt
index ddfcc2e..3abe21b 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/widget/Widget.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/widget/Widget.kt
@@ -85,14 +85,14 @@ class Widget : AppWidgetProvider() {
getPrivacyStateUseCase.quickPrivacyState,
getPrivacyStateUseCase.trackerMode,
getPrivacyStateUseCase.isLocationHidden,
- getPrivacyStateUseCase.isIpHidden,
- ) { quickPrivacyState, trackerMode, isLocationHidden, isIpHidden ->
+ getPrivacyStateUseCase.ipScramblingMode,
+ ) { quickPrivacyState, trackerMode, isLocationHidden, ipScramblingMode ->
State(
quickPrivacyState = quickPrivacyState,
trackerMode = trackerMode,
isLocationHidden = isLocationHidden,
- isIpHidden = isIpHidden
+ ipScramblingMode = ipScramblingMode
)
}.sample(50)
.combine(
diff --git a/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetCommandReceiver.kt b/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetCommandReceiver.kt
index 831c06f..4a103e0 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetCommandReceiver.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetCommandReceiver.kt
@@ -26,10 +26,13 @@ import foundation.e.privacycentralapp.R
class WidgetCommandReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
- val privacyCentralApplication = (context?.applicationContext as? PrivacyCentralApplication)
+ val getQuickPrivacyStateUseCase = (context?.applicationContext as? PrivacyCentralApplication)?.dependencyContainer?.getQuickPrivacyStateUseCase
+
when (intent?.action) {
- ACTION_TOGGLE_PRIVACY -> {
- if (privacyCentralApplication?.dependencyContainer?.getQuickPrivacyStateUseCase?.toggleReturnIsFirstActivation() == true) {
+ ACTION_TOGGLE_TRACKERS -> getQuickPrivacyStateUseCase?.toggleTrackers()
+ ACTION_TOGGLE_LOCATION -> getQuickPrivacyStateUseCase?.toggleLocation()
+ ACTION_TOGGLE_IPSCRAMBLING -> {
+ if (getQuickPrivacyStateUseCase?.toggleIpScramblingIsFirstActivation() == true) {
Toast.makeText(
context,
context.getString(R.string.dashboard_first_ipscrambling_activation),
@@ -42,6 +45,8 @@ class WidgetCommandReceiver : BroadcastReceiver() {
}
companion object {
- const val ACTION_TOGGLE_PRIVACY = "toggle_privacy"
+ const val ACTION_TOGGLE_TRACKERS = "toggle_trackers"
+ const val ACTION_TOGGLE_LOCATION = "toggle_location"
+ const val ACTION_TOGGLE_IPSCRAMBLING = "toggle_ipscrambling"
}
}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt b/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt
index 682e5cc..4fdbb03 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/widget/WidgetUI.kt
@@ -30,16 +30,19 @@ import foundation.e.privacycentralapp.R
import foundation.e.privacycentralapp.Widget
import foundation.e.privacycentralapp.Widget.Companion.isDarkText
import foundation.e.privacycentralapp.common.extensions.dpToPxF
+import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
import foundation.e.privacycentralapp.domain.entities.QuickPrivacyState
import foundation.e.privacycentralapp.domain.entities.TrackerMode
import foundation.e.privacycentralapp.main.MainActivity
-import foundation.e.privacycentralapp.widget.WidgetCommandReceiver.Companion.ACTION_TOGGLE_PRIVACY
+import foundation.e.privacycentralapp.widget.WidgetCommandReceiver.Companion.ACTION_TOGGLE_IPSCRAMBLING
+import foundation.e.privacycentralapp.widget.WidgetCommandReceiver.Companion.ACTION_TOGGLE_LOCATION
+import foundation.e.privacycentralapp.widget.WidgetCommandReceiver.Companion.ACTION_TOGGLE_TRACKERS
data class State(
val quickPrivacyState: QuickPrivacyState = QuickPrivacyState.DISABLED,
val trackerMode: TrackerMode = TrackerMode.VULNERABLE,
val isLocationHidden: Boolean = false,
- val isIpHidden: Boolean? = false,
+ val ipScramblingMode: InternetPrivacyMode = InternetPrivacyMode.REAL_IP_LOADING,
val dayStatistics: List<Pair<Int, Int>> = emptyList(),
val activeTrackersCount: Int = 0,
)
@@ -71,19 +74,21 @@ fun render(
}
)
)
+
setImageViewResource(
- R.id.toggle_privacy_central,
- if (state.quickPrivacyState.isEnabled()) R.drawable.ic_switch_enabled
- else R.drawable.ic_switch_disabled
+ R.id.toggle_trackers,
+ if (state.trackerMode == TrackerMode.VULNERABLE)
+ R.drawable.ic_switch_disabled
+ else R.drawable.ic_switch_enabled
)
setOnClickPendingIntent(
- R.id.toggle_privacy_central,
+ R.id.toggle_trackers,
PendingIntent.getBroadcast(
context,
- REQUEST_CODE_TOGGLE,
+ REQUEST_CODE_TOGGLE_TRACKERS,
Intent(context, WidgetCommandReceiver::class.java).apply {
- action = ACTION_TOGGLE_PRIVACY
+ action = ACTION_TOGGLE_TRACKERS
},
FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT
)
@@ -100,6 +105,24 @@ fun render(
)
)
+ setImageViewResource(
+ R.id.toggle_location,
+ if (state.isLocationHidden) R.drawable.ic_switch_enabled
+ else R.drawable.ic_switch_disabled
+ )
+
+ setOnClickPendingIntent(
+ R.id.toggle_location,
+ PendingIntent.getBroadcast(
+ context,
+ REQUEST_CODE_TOGGLE_LOCATION,
+ Intent(context, WidgetCommandReceiver::class.java).apply {
+ action = ACTION_TOGGLE_LOCATION
+ },
+ FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT
+ )
+ )
+
setTextViewText(
R.id.state_geolocation,
context.getString(
@@ -108,15 +131,33 @@ fun render(
)
)
+ setImageViewResource(
+ R.id.toggle_ipscrambling,
+ if (state.ipScramblingMode.isChecked) R.drawable.ic_switch_enabled
+ else R.drawable.ic_switch_disabled
+ )
+
+ setOnClickPendingIntent(
+ R.id.toggle_ipscrambling,
+ PendingIntent.getBroadcast(
+ context,
+ REQUEST_CODE_TOGGLE_IPSCRAMBLING,
+ Intent(context, WidgetCommandReceiver::class.java).apply {
+ action = ACTION_TOGGLE_IPSCRAMBLING
+ },
+ FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT
+ )
+ )
+
setTextViewText(
R.id.state_ip_address,
context.getString(
- if (state.isIpHidden == true) R.string.widget_state_ipaddress_on
+ if (state.ipScramblingMode == InternetPrivacyMode.HIDE_IP) R.string.widget_state_ipaddress_on
else R.string.widget_state_ipaddress_off
)
)
- val loading = state.isIpHidden == null
+ val loading = state.ipScramblingMode.isLoading
setViewVisibility(R.id.state_ip_address, if (loading) View.GONE else View.VISIBLE)
@@ -265,8 +306,10 @@ private val leakedBarIds = listOf(
)
private const val REQUEST_CODE_DASHBOARD = 1
-private const val REQUEST_CODE_TOGGLE = 2
private const val REQUEST_CODE_TRACKERS = 3
+private const val REQUEST_CODE_TOGGLE_TRACKERS = 4
+private const val REQUEST_CODE_TOGGLE_LOCATION = 5
+private const val REQUEST_CODE_TOGGLE_IPSCRAMBLING = 6
private const val REQUEST_CODE_HIGHLIGHT = 100
fun applyDarkText(context: Context, state: State, views: RemoteViews) {
diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_dashboard.xml
index 8b8792b..cedf569 100644
--- a/app/src/main/res/layout/fragment_dashboard.xml
+++ b/app/src/main/res/layout/fragment_dashboard.xml
@@ -42,12 +42,6 @@
android:textSize="14sp"
android:textColor="@color/secondary_text"
/>
- <Switch
- android:id="@+id/toggle_privacy_central"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_margin="16dp"
- />
</LinearLayout>
<View
android:layout_width="match_parent"
@@ -69,8 +63,9 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
- android:paddingStart="8dp"
+ android:gravity="center_horizontal"
>
+
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -89,13 +84,19 @@
android:textColor="@color/primary_text"
android:textAllCaps="true"
/>
+ <Switch
+ android:id="@+id/toggle_trackers"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_margin="12dp"
+ />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
- android:paddingStart="8dp"
+ android:gravity="center_horizontal"
>
<TextView
android:layout_width="wrap_content"
@@ -115,13 +116,19 @@
android:textColor="@color/primary_text"
android:textAllCaps="true"
/>
+ <Switch
+ android:id="@+id/toggle_location"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_margin="12dp"
+ />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
- android:paddingStart="8dp"
+ android:gravity="center_horizontal"
>
<TextView
android:layout_width="wrap_content"
@@ -148,6 +155,12 @@ android:text="@string/dashboard_state_ipaddress_off"
android:layout_height="16dp"
android:indeterminate="true"
android:visibility="visible"/>
+ <Switch
+ android:id="@+id/toggle_ipscrambling"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_margin="12dp"
+ />
</LinearLayout>
</LinearLayout>
diff --git a/app/src/main/res/layout/widget.xml b/app/src/main/res/layout/widget.xml
index 60cbffa..1e78bc7 100644
--- a/app/src/main/res/layout/widget.xml
+++ b/app/src/main/res/layout/widget.xml
@@ -72,13 +72,6 @@
android:textSize="12sp"
android:textColor="@color/on_primary_medium_emphasis"
/>
- <ImageView
- android:id="@+id/toggle_privacy_central"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_switch_disabled"
- />
-
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
@@ -92,6 +85,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
+ android:gravity="center_horizontal"
>
<TextView
android:id="@+id/trackers_label"
@@ -106,11 +100,19 @@
<TextView
android:id="@+id/state_trackers"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="18dp"
android:text="@string/dashboard_state_trackers_off"
- android:textSize="14sp"
+ android:textSize="12sp"
android:textColor="@color/on_primary_high_emphasis"
android:textAllCaps="true"
+ android:gravity="center"
+ />
+ <ImageView
+ android:id="@+id/toggle_trackers"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:src="@drawable/ic_switch_disabled"
/>
</LinearLayout>
<LinearLayout
@@ -118,6 +120,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
+ android:gravity="center_horizontal"
>
<TextView
android:id="@+id/geolocation_label"
@@ -132,11 +135,19 @@
<TextView
android:id="@+id/state_geolocation"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="18dp"
android:text="@string/dashboard_state_geolocation_off"
- android:textSize="14sp"
+ android:textSize="12sp"
android:textColor="@color/on_primary_high_emphasis"
android:textAllCaps="true"
+ android:gravity="center"
+ />
+ <ImageView
+ android:id="@+id/toggle_location"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:src="@drawable/ic_switch_disabled"
/>
</LinearLayout>
<LinearLayout
@@ -144,6 +155,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
+ android:gravity="center_horizontal"
>
<TextView
android:id="@+id/ip_address_label"
@@ -158,19 +170,27 @@
<TextView
android:id="@+id/state_ip_address"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="18dp"
android:text="@string/dashboard_state_ipaddress_off"
- android:textSize="14sp"
+ android:textSize="12sp"
android:textColor="@color/on_primary_high_emphasis"
android:textAllCaps="true"
android:visibility="gone"
+ android:gravity="center"
/>
<ProgressBar
android:id="@+id/state_ip_address_loader"
- android:layout_width="16dp"
- android:layout_height="16dp"
+ android:layout_width="18dp"
+ android:layout_height="18dp"
android:indeterminate="true"
android:visibility="visible"/>
+ <ImageView
+ android:id="@+id/toggle_ipscrambling"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:src="@drawable/ic_switch_disabled"
+ />
</LinearLayout>
</LinearLayout>
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index cda8aa8..ea0bacd 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="dashboard_state_title_off">Dein Online-Datenschutz ist nicht gewährleistet</string>
- <string name="dashboard_state_trackers_label">Tracker (Verfolger):</string>
+ <string name="dashboard_state_trackers_label">Tracker (Verfolger)</string>
<string name="dashboard_state_trackers_off">Verletzlich</string>
<string name="dashboard_state_trackers_on">Abgelehnt</string>
- <string name="dashboard_state_geolocation_label">Standort:</string>
+ <string name="dashboard_state_geolocation_label">Standort</string>
<string name="dashboard_state_geolocation_on">Verschleiert</string>
- <string name="dashboard_state_ipaddress_label">Echte IP-Adresse:</string>
+ <string name="dashboard_state_ipaddress_label">Echte IP-Adresse</string>
<string name="dashboard_state_ipaddress_on">Verschleiert</string>
<string name="dashboard_graph_label">Datenlecks (Nutzerdaten):</string>
<string name="dashboard_graph_period">Heute</string>
@@ -110,7 +110,6 @@
<string name="graph_subtitle">Tippe auf die Balken für weitere Informationen.</string>
<string name="first_notification_summary">Tippe, um herauszufinden, wie Tracker einfach blockiert, dein Standort gefälscht und deine IP-Adresse verschleiert werden kann.</string>
<string name="dashboard_state_title_custom">Benutzerdefinierte Datenschutz-Einstellungen werden angewendet</string>
- <string name="quickprivacy_disabled_message">Die Änderungen werden erst beim Aktivieren des Datenschutz-Schalters angewandt.</string>
<string name="close">Schließen</string>
<string name="dashboard_first_ipscrambling_activation">Das Verschleiern deiner IP wird möglicherweise die Internetgeschwindigkeit verlangsamen.</string>
<string name="widget_state_title_custom">Benutzerdefinierte Datenschutz-Einstellungen werden angewandt</string>
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 9cbe21c..213a9d7 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="dashboard_state_trackers_label">Rastreadores:</string>
+ <string name="dashboard_state_trackers_label">Rastreadores</string>
<string name="dashboard_state_trackers_off">Vulnerable</string>
<string name="dashboard_state_trackers_on">Denegado</string>
- <string name="dashboard_state_geolocation_label">Ubicación:</string>
+ <string name="dashboard_state_geolocation_label">Ubicación</string>
<string name="dashboard_state_geolocation_off">Expuesto</string>
<string name="dashboard_state_geolocation_on">Falso</string>
- <string name="dashboard_state_ipaddress_label">Direccion IP real:</string>
+ <string name="dashboard_state_ipaddress_label">Direccion IP real</string>
<string name="dashboard_state_ipaddress_off">Expuesto</string>
<string name="dashboard_state_ipaddress_on">Oculto</string>
<string name="dashboard_graph_label">Filtración de datos personales</string>
diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml
index 0964d3f..b5932de 100644
--- a/app/src/main/res/values-fi/strings.xml
+++ b/app/src/main/res/values-fi/strings.xml
@@ -90,17 +90,16 @@
<string name="dashboard_graph_label">Henkilötietojen vuoto:</string>
<string name="dashboard_state_ipaddress_on">Piilotettu</string>
<string name="dashboard_state_ipaddress_off">Paljastettu</string>
- <string name="dashboard_state_ipaddress_label">Todellinen IP-osoite:</string>
+ <string name="dashboard_state_ipaddress_label">Todellinen IP-osoite</string>
<string name="dashboard_state_geolocation_on">Väärennetty</string>
<string name="dashboard_state_geolocation_off">Paljastettu</string>
- <string name="dashboard_state_geolocation_label">Sijainti:</string>
+ <string name="dashboard_state_geolocation_label">Sijainti</string>
<string name="dashboard_state_trackers_on">Estetty</string>
<string name="dashboard_state_trackers_off">Haavoittuvainen</string>
- <string name="dashboard_state_trackers_label">Seuraimet:</string>
+ <string name="dashboard_state_trackers_label">Seuraimet</string>
<string name="dashboard_state_title_custom">Sovelletaan mukautettuja yksityisyysasetuksia</string>
<string name="dashboard_state_title_on">Yksityisyytesi verkossa on suojattu</string>
<string name="close">Sulje</string>
- <string name="quickprivacy_disabled_message">Muutokset tulevat voimaan vain, kun yksityisyydensuojan kytkin on käytössä.</string>
<string name="graph_subtitle">Napauta palkkeja saadaksesi lisätietoja.</string>
<string name="graph_legend_allowed">Sallittuja tietovuotoja</string>
<string name="graph_legend_blocked">Estettyjä tietovuotoja</string>
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 628cff3..b4db80f 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -2,13 +2,13 @@
<resources>
<string name="dashboard_state_title_on">Votre vie privée en ligne est protégée</string>
<string name="dashboard_state_title_off">Votre vie privée en ligne n\'est pas protégée</string>
- <string name="dashboard_state_trackers_label">Trackers :</string>
+ <string name="dashboard_state_trackers_label">Trackers</string>
<string name="dashboard_state_trackers_off">Vulnérable</string>
<string name="dashboard_state_trackers_on">Refusé</string>
- <string name="dashboard_state_geolocation_label">Localisation :</string>
+ <string name="dashboard_state_geolocation_label">Localisation</string>
<string name="dashboard_state_geolocation_off">Exposé</string>
<string name="dashboard_state_geolocation_on">Faux</string>
- <string name="dashboard_state_ipaddress_label">Adresse IP réelle :</string>
+ <string name="dashboard_state_ipaddress_label">Adresse IP réelle</string>
<string name="dashboard_state_ipaddress_off">Exposé</string>
<string name="dashboard_graph_label">Fuite de données personnelles :</string>
<string name="dashboard_graph_period">Aujourd\'hui</string>
@@ -96,7 +96,6 @@
<string name="quick_protection_settings_list">- Tous les pisteurs sont désactivés.
\n- Votre géolocalisation sera falsifiée.
\n- Votre adresse IP réelle sera masquée.</string>
- <string name="quickprivacy_disabled_message">Les modifications seront effectives uniquement quand la protection de la confidentialité sera activée.</string>
<string name="dashboard_first_ipscrambling_activation">Votre vitesse Internet risque d\'être réduite tant que votre adresse IP est masquée.</string>
<string name="graph_legend_allowed">Fuites autorisées</string>
<string name="graph_legend_blocked">Fuites bloquées</string>
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 9f8d02d..316aa4f 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="dashboard_state_title_off">La tua privacy online non è protetta</string>
- <string name="dashboard_state_trackers_label">Tracker:</string>
+ <string name="dashboard_state_trackers_label">Tracker</string>
<string name="dashboard_state_trackers_off">Vulnerabile</string>
<string name="dashboard_state_trackers_on">Negato</string>
- <string name="dashboard_state_geolocation_label">Posizione:</string>
+ <string name="dashboard_state_geolocation_label">Posizione</string>
<string name="dashboard_state_geolocation_off">Esposta</string>
<string name="dashboard_state_geolocation_on">Fasulla</string>
- <string name="dashboard_state_ipaddress_label">Indirizzo IP reale:</string>
+ <string name="dashboard_state_ipaddress_label">Indirizzo IP reale</string>
<string name="dashboard_state_ipaddress_off">Esposto</string>
<string name="dashboard_state_ipaddress_on">Nascosto</string>
<string name="dashboard_graph_label">Fuga di dati personali:</string>
@@ -110,7 +110,6 @@
<string name="dashboard_graph_leaking_app">Guarda</string>
<string name="dashboard_state_title_custom">Impostazioni della privacy personalizzate applicate</string>
<string name="close">Chiudi</string>
- <string name="quickprivacy_disabled_message">I cambiamenti avranno efficacia solo dopo l\'abilitazione del pulsante protezione privacy.</string>
<string name="graph_subtitle">Tocca le barre per maggiori informazioni.</string>
<string name="graph_legend_allowed">Perdite di dati ammesse</string>
<string name="graph_legend_blocked">Perdite di dati bloccate</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8705ac5..a4d1040 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -8,21 +8,20 @@
<string name="graph_legend_blocked">Blocked leaks</string>
<string name="graph_legend_allowed">Allowed leaks</string>
<string name="graph_subtitle">Tap on the bars for more information.</string>
- <string name="quickprivacy_disabled_message">Changes will only be effective when privacy protection toggle is enabled.</string>
<string name="close">Close</string>
<!-- Dashboard -->
<string name="dashboard_title" translatable="false">@string/app_name</string>
<string name="dashboard_state_title_on">Your online privacy is protected</string>
<string name="dashboard_state_title_off">Your online privacy is unprotected</string>
<string name="dashboard_state_title_custom">Custom privacy settings applied</string>
- <string name="dashboard_state_trackers_label">Trackers:</string>
+ <string name="dashboard_state_trackers_label">Trackers</string>
<string name="dashboard_state_trackers_off">Vulnerable</string>
<string name="dashboard_state_trackers_on">Denied</string>
<string name="dashboard_state_trackers_custom">Custom</string>
- <string name="dashboard_state_geolocation_label">Location:</string>
+ <string name="dashboard_state_geolocation_label">Location</string>
<string name="dashboard_state_geolocation_off">Exposed</string>
<string name="dashboard_state_geolocation_on">Fake</string>
- <string name="dashboard_state_ipaddress_label">Real IP address:</string>
+ <string name="dashboard_state_ipaddress_label">Real IP address</string>
<string name="dashboard_state_ipaddress_off">Exposed</string>
<string name="dashboard_state_ipaddress_on">Hidden</string>
<string name="dashboard_graph_label">Personal data leakage:</string>
@@ -87,6 +86,7 @@
<string name="apptrackers_error_quickprivacy_disabled">Enable Quick Privacy to be able to activate/deactivate trackers.</string>
<string name="apptrackers_trackers_count_summary">%1$d blocked trackers out of %2$d detected trackers, %3$d blocked leaks and %4$d allowed leaks.</string>
<string name="apptrackers_error_no_app">App not installed.</string>
+ <string name="apptrackers_tracker_control_disabled_message">Changes will take effect when tracker blocker is on.</string>
<!-- -->
<string name="quick_protection_info">Quick protection enables these settings when turned on</string>
<string name="quick_protection_settings_list"> - All trackers are turned off.\n- Your geolocation will be faked.\n- Your real IP address will be hidden.</string>