From a36646636f24556c8ada8edb86b72e7f7c7f778b Mon Sep 17 00:00:00 2001 From: Guillaume Jacquart Date: Fri, 4 Nov 2022 08:19:24 +0100 Subject: [PATCH 1/5] 568: individuals buttons to activate the main features --- .../privacycentralapp/DependencyContainer.kt | 2 +- .../common/QuickPrivacyDisabledSnackbar.kt | 36 --------- .../data/repositories/LocalStateRepository.kt | 75 ++++++++----------- .../domain/entities/InternetPrivacyMode.kt | 6 +- .../usecases/FakeLocationStateUseCase.kt | 35 ++++----- .../usecases/GetQuickPrivacyStateUseCase.kt | 71 +++++++----------- .../usecases/IpScramblingStateUseCase.kt | 32 +++----- .../domain/usecases/TrackersStateUseCase.kt | 9 +-- .../features/dashboard/DashboardFragment.kt | 37 +++++---- .../features/dashboard/DashboardState.kt | 4 +- .../features/dashboard/DashboardViewModel.kt | 33 ++++---- .../InternetPrivacyFragment.kt | 12 --- .../internetprivacy/InternetPrivacyState.kt | 1 - .../InternetPrivacyViewModel.kt | 19 +---- .../features/location/FakeLocationFragment.kt | 12 --- .../features/location/FakeLocationState.kt | 1 - .../location/FakeLocationViewModel.kt | 6 -- .../features/trackers/TrackersFragment.kt | 11 --- .../features/trackers/TrackersState.kt | 1 - .../features/trackers/TrackersViewModel.kt | 7 -- .../apptrackers/AppTrackersFragment.kt | 17 ++--- .../trackers/apptrackers/AppTrackersState.kt | 4 +- .../apptrackers/AppTrackersViewModel.kt | 29 +++---- .../e/privacycentralapp/main/MainActivity.kt | 6 -- .../e/privacycentralapp/widget/Widget.kt | 6 +- .../widget/WidgetCommandReceiver.kt | 13 +++- .../e/privacycentralapp/widget/WidgetUI.kt | 65 +++++++++++++--- .../main/res/layout/fragment_dashboard.xml | 25 +++++-- app/src/main/res/layout/widget.xml | 28 +++++-- app/src/main/res/values-de/strings.xml | 6 +- app/src/main/res/values-es/strings.xml | 6 +- app/src/main/res/values-fi/strings.xml | 6 +- app/src/main/res/values-fr/strings.xml | 6 +- app/src/main/res/values-it/strings.xml | 6 +- app/src/main/res/values/strings.xml | 10 +-- build.gradle | 2 +- 36 files changed, 284 insertions(+), 361 deletions(-) delete mode 100644 app/src/main/java/foundation/e/privacycentralapp/common/QuickPrivacyDisabledSnackbar.kt diff --git a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt index 670b81ee..345307c4 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 705f65d3..00000000 --- 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 . - */ - -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() { - 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 d39ee43f..2872ea95 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt @@ -31,7 +31,7 @@ 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 +41,50 @@ class LocalStateRepository(context: Context) { private val sharedPref = context.getSharedPreferences(SHARED_PREFS_FILE, Context.MODE_PRIVATE) - private val quickPrivacyEnabledMutableFlow = - MutableStateFlow(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() - suspend fun emitOtherVpnRunning(appDesc: ApplicationDescription) { - _otherVpnRunning.emit(appDesc) - } + val areAllTrackersBlocked: MutableStateFlow = MutableStateFlow(false) - val otherVpnRunning: SharedFlow = _otherVpnRunning + private val _fakeLocationEnabled = MutableStateFlow(sharedPref.getBoolean(KEY_FAKE_LOCATION, true)) - var quickPrivacyEnabledFlow: StateFlow = quickPrivacyEnabledMutableFlow + val fakeLocationEnabled = _fakeLocationEnabled.asStateFlow() - val areAllTrackersBlocked: MutableStateFlow = MutableStateFlow(false) + fun setFakeLocationEnabled(enabled: Boolean) { + set(KEY_FAKE_LOCATION, enabled) + _fakeLocationEnabled.update { enabled } + } - var fakeLocation: Pair? - 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) + var fakeLocation: Pair + get() = Pair( + // Initial default value is Quezon City + sharedPref.getFloat(KEY_FAKE_LATITUDE, 14.6760f), + sharedPref.getFloat(KEY_FAKE_LONGITUDE, 121.0437f) ) - else null 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) + .commit() } val locationMode: MutableStateFlow = 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 setIpScramblingReturnIsFirstActivation(enabled: Boolean): Boolean { + val isFirstActivation = enabled && !sharedPref.contains(KEY_IP_SCRAMBLING) + setIpScramblingSetting(enabled) + return isFirstActivation + } + fun setIpScramblingSetting(enabled: Boolean) { set(KEY_IP_SCRAMBLING, enabled) _ipScramblingSetting.update { enabled } @@ -100,12 +92,11 @@ class LocalStateRepository(context: Context) { val internetPrivacyMode: MutableStateFlow = MutableStateFlow(InternetPrivacyMode.REAL_IP) - private val _showQuickPrivacyDisabledMessage = MutableStateFlow(false) - val showQuickPrivacyDisabledMessage: StateFlow = _showQuickPrivacyDisabledMessage - - fun setShowQuickPrivacyDisabledMessage(show: Boolean) { - _showQuickPrivacyDisabledMessage.value = show + private val _otherVpnRunning = MutableSharedFlow() + suspend fun emitOtherVpnRunning(appDesc: ApplicationDescription) { + _otherVpnRunning.emit(appDesc) } + val otherVpnRunning: SharedFlow = _otherVpnRunning var firstBoot: Boolean get() = sharedPref.getBoolean(KEY_FIRST_BOOT, true) 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 534bb2f6..f849d57e 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 e9da8555..edf3c6df 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?, isSpecificLocation: Boolean = false) { - _configuredLocationMode.value = computeLocationMode(fakeLocation, isSpecificLocation) + private fun applySettings(isEnabled: Boolean, fakeLocation: Pair, 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,22 +102,23 @@ class FakeLocationStateUseCase( private fun setFakeLocation(location: Pair, 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?, isSpecificLocation: Boolean = false): Triple { + private fun computeLocationMode( + isFakeLocationEnabled: Boolean, + fakeLocation: Pair, + isSpecificLocation: Boolean = false + ): Triple { return Triple( when { - fakeLocation == null -> LocationMode.REAL_LOCATION + !isFakeLocationEnabled -> LocationMode.REAL_LOCATION fakeLocation in citiesRepository.citiesLocationsList && !isSpecificLocation -> LocationMode.RANDOM_LOCATION else -> LocationMode.SPECIFIC_LOCATION }, diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/GetQuickPrivacyStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/GetQuickPrivacyStateUseCase.kt index 46e054e6..8a382e05 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 = localStateRepository.quickPrivacyEnabledFlow - - val isQuickPrivacyEnabled: Boolean get() = localStateRepository.isQuickPrivacyEnabled - val quickPrivacyState: Flow = 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 = 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 = combine( - localStateRepository.quickPrivacyEnabledFlow, - localStateRepository.locationMode - ) { isQuickPrivacyEnabled, locationMode -> - isQuickPrivacyEnabled && locationMode != LocationMode.REAL_LOCATION + val isLocationHidden: Flow = localStateRepository.locationMode.map { locationMode -> + locationMode != LocationMode.REAL_LOCATION } val locationMode: StateFlow = localStateRepository.locationMode - val isIpHidden: Flow = combine( - localStateRepository.quickPrivacyEnabledFlow, - localStateRepository.internetPrivacyMode - ) { isQuickPrivacyEnabled, internetPrivacyMode -> - when { - !isQuickPrivacyEnabled || internetPrivacyMode == InternetPrivacyMode.REAL_IP -> false - internetPrivacyMode == InternetPrivacyMode.HIDE_IP -> true - else -> null - } - } + val ipScramblingMode: Flow = localStateRepository.internetPrivacyMode + - fun toggleReturnIsFirstActivation(): Boolean { - val newState = !localStateRepository.isQuickPrivacyEnabled - return localStateRepository.setQuickPrivacyReturnIsFirstActivation(newState) + fun toggleTrackers() { + localStateRepository.setBlockTrackers(!localStateRepository.blockTrackers.value) } - val showQuickPrivacyDisabledMessage: StateFlow = localStateRepository.showQuickPrivacyDisabledMessage + fun toggleLocation() { + localStateRepository.setFakeLocationEnabled(!localStateRepository.fakeLocationEnabled.value) + } - fun resetQuickPrivacyDisabledMessage() { - localStateRepository.setShowQuickPrivacyDisabledMessage(false) + fun toggleIpScramblingIsFirstActivation(): Boolean { + return localStateRepository.setIpScramblingReturnIsFirstActivation( + !localStateRepository.ipScramblingSetting.value + ) } val otherVpnRunning: SharedFlow = 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 cb9fcd58..405f67ab 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 @@ -43,9 +43,6 @@ class IpScramblingStateUseCase( private val appListsRepository: AppListsRepository, private val coroutineScope: CoroutineScope ) { - - val configuredMode: StateFlow = localStateRepository.ipScramblingSetting - val internetPrivacyMode: StateFlow = callbackFlow { val listener = object : IIpScramblerModule.Listener { override fun onStatusChanged(newStatus: IIpScramblerModule.Status) { @@ -67,13 +64,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) + localStateRepository.ipScramblingSetting.collect { + applySettings(it) } } @@ -84,12 +81,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 { @@ -129,15 +121,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 +152,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 17e5096b..8b371523 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 6cd259e5..e39c2ed8 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,12 @@ 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 +243,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 +292,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 +301,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 04b7ae85..937fa221 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>? = null, val dayLabels: List? = 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 d7d74c6b..fc563971 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,18 @@ class DashboardViewModel( fun submitAction(action: Action) = viewModelScope.launch { when (action) { - is Action.TogglePrivacyAction -> actionTogglePrivacy() + is Action.ToggleTrackers -> { + getPrivacyStateUseCase.toggleTrackers() + delay(200) + fetchStatistics().first() + // trackersStatisticsUseCase.getNonBlockedTrackersCount().map { + // _state.update { s -> + // s.copy(allowedTrackersCount = it) + // } + // } + } + is Action.ToggleLocation -> getPrivacyStateUseCase.toggleLocation() + is Action.ToggleIpScrambling -> actionToggleIpScrambling() is Action.ShowFakeMyLocationAction -> _singleEvents.emit(SingleEvent.NavigateToLocationSingleEvent) is Action.ShowAppsPermissions -> @@ -98,8 +107,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 +127,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 +158,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 99aa2170..afef9863 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 69911968..54b7e019 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 = emptyList(), val forceRedraw: Boolean = false, - val showQuickPrivacyDisabledMessage: Boolean = false ) { fun getApps(): List> { 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 be6cd4d2..bbd62394 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 537d0b6e..9e3f8541 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 9513f777..50d7a145 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 8db35377..1cdf9f46 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 491f6251..8adf2560 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 2437366b..a3bb80ae 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? = 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 3869c394..07828f87 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 cd4f6b27..6aeac8ee 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 d6d0858a..80884433 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>? = null, val leaked: Int = 0, val blocked: Int = 0, - val isQuickPrivacyEnabled: Boolean = false, + val isTrackersBlockingEnabled: Boolean = false, val showQuickPrivacyDisabledMessage: Boolean = false, ) { fun getTrackersStatus(): List>? { @@ -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 52ef2c43..3e874820 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,28 +67,26 @@ 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 { } } fun submitAction(action: Action) = viewModelScope.launch { - when (action) { - is Action.BlockAllToggleAction -> blockAllToggleAction(action) - is Action.ToggleTrackerAction -> toggleTrackerAction(action) - is Action.ClickTracker -> actionClickTracker(action) - is Action.CloseQuickPrivacyDisabledMessage -> - getQuickPrivacyStateUseCase.resetQuickPrivacyDisabledMessage() - } + when (action) { + is Action.BlockAllToggleAction -> blockAllToggleAction(action) + is Action.ToggleTrackerAction -> toggleTrackerAction(action) + is Action.ClickTracker -> actionClickTracker(action) + } } 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 58ac7976..a81f5b5f 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 ddfcc2e0..3abe21bc 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 831c06f9..4a103e03 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 682e5cc4..4fdbb039 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> = 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 8b8792b4..7ed581b0 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" /> - + + + + diff --git a/app/src/main/res/layout/widget.xml b/app/src/main/res/layout/widget.xml index 60cbffae..ed2d821f 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" /> - - + + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index cda8aa82..c67f7c30 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -1,12 +1,12 @@ Dein Online-Datenschutz ist nicht gewährleistet - Tracker (Verfolger): + Tracker (Verfolger) Verletzlich Abgelehnt - Standort: + Standort Verschleiert - Echte IP-Adresse: + Echte IP-Adresse Verschleiert Datenlecks (Nutzerdaten): Heute diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 9cbe21c1..213a9d7b 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1,12 +1,12 @@ - Rastreadores: + Rastreadores Vulnerable Denegado - Ubicación: + Ubicación Expuesto Falso - Direccion IP real: + Direccion IP real Expuesto Oculto Filtración de datos personales diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 0964d3f0..62adcf2f 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -90,13 +90,13 @@ Henkilötietojen vuoto: Piilotettu Paljastettu - Todellinen IP-osoite: + Todellinen IP-osoite Väärennetty Paljastettu - Sijainti: + Sijainti Estetty Haavoittuvainen - Seuraimet: + Seuraimet Sovelletaan mukautettuja yksityisyysasetuksia Yksityisyytesi verkossa on suojattu Sulje diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 628cff32..3dcf6d6a 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -2,13 +2,13 @@ Votre vie privée en ligne est protégée Votre vie privée en ligne n\'est pas protégée - Trackers : + Trackers Vulnérable Refusé - Localisation : + Localisation Exposé Faux - Adresse IP réelle : + Adresse IP réelle Exposé Fuite de données personnelles : Aujourd\'hui diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 9f8d02d3..173b156b 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -1,13 +1,13 @@ La tua privacy online non è protetta - Tracker: + Tracker Vulnerabile Negato - Posizione: + Posizione Esposta Fasulla - Indirizzo IP reale: + Indirizzo IP reale Esposto Nascosto Fuga di dati personali: diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8705ac50..0d378576 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ - Advanced Privacy + 1_ Advanced Privacy System @@ -8,21 +8,20 @@ Blocked leaks Allowed leaks Tap on the bars for more information. - Changes will only be effective when privacy protection toggle is enabled. Close @string/app_name Your online privacy is protected Your online privacy is unprotected Custom privacy settings applied - Trackers: + Trackers Vulnerable Denied Custom - Location: + Location Exposed Fake - Real IP address: + Real IP address Exposed Hidden Personal data leakage: @@ -87,6 +86,7 @@ Enable Quick Privacy to be able to activate/deactivate trackers. %1$d blocked trackers out of %2$d detected trackers, %3$d blocked leaks and %4$d allowed leaks. App not installed. + Changes will take effect when tracker blocker is on. Quick protection enables these settings when turned on - All trackers are turned off.\n- Your geolocation will be faked.\n- Your real IP address will be hidden. diff --git a/build.gradle b/build.gradle index 2abc73d2..0fe3d8fb 100644 --- a/build.gradle +++ b/build.gradle @@ -146,7 +146,7 @@ subprojects { tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { kotlinOptions { // Treat all Kotlin warnings as errors - allWarningsAsErrors = true + // TODO allWarningsAsErrors = true freeCompilerArgs += "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi" // Set JVM target to 1.8 -- GitLab From 5d69b998c90175442e53d5fa0214c259e0e9b48f Mon Sep 17 00:00:00 2001 From: Guillaume Jacquart Date: Mon, 7 Nov 2022 20:30:22 +0100 Subject: [PATCH 2/5] 568: Offer buttons to activate/deactivate individually tracker protection, fake location and fake IP address --- app/build.gradle | 2 +- .../data/repositories/LocalStateRepository.kt | 3 +-- .../domain/usecases/GetQuickPrivacyStateUseCase.kt | 5 ++--- .../domain/usecases/IpScramblingStateUseCase.kt | 3 ++- .../features/dashboard/DashboardFragment.kt | 1 - .../trackers/apptrackers/AppTrackersViewModel.kt | 10 +++++----- app/src/main/res/layout/fragment_dashboard.xml | 6 +++--- app/src/main/res/layout/widget.xml | 3 +++ app/src/main/res/values/strings.xml | 2 +- 9 files changed, 18 insertions(+), 17 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 82717d34..dd5c27bf 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-orbot-16.6.2' implementation 'foundation.e:elib:0.0.1-alpha11' 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 2872ea95..cdb47b95 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,7 +24,6 @@ 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 @@ -65,7 +64,7 @@ class LocalStateRepository(context: Context) { // Initial default value is Quezon City sharedPref.getFloat(KEY_FAKE_LATITUDE, 14.6760f), sharedPref.getFloat(KEY_FAKE_LONGITUDE, 121.0437f) - ) + ) set(value) { sharedPref.edit() 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 8a382e05..e58ab12b 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 @@ -40,8 +40,8 @@ class GetQuickPrivacyStateUseCase( ) { isBlockTrackers, isAllTrackersBlocked, locationMode, internetPrivacyMode -> when { !isBlockTrackers && - locationMode == LocationMode.REAL_LOCATION && - internetPrivacyMode == InternetPrivacyMode.REAL_IP -> QuickPrivacyState.DISABLED + locationMode == LocationMode.REAL_LOCATION && + internetPrivacyMode == InternetPrivacyMode.REAL_IP -> QuickPrivacyState.DISABLED isAllTrackersBlocked && locationMode != LocationMode.REAL_LOCATION && @@ -73,7 +73,6 @@ class GetQuickPrivacyStateUseCase( val ipScramblingMode: Flow = localStateRepository.internetPrivacyMode - fun toggleTrackers() { localStateRepository.setBlockTrackers(!localStateRepository.blockTrackers.value) } 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 405f67ab..c0b41fc7 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 @@ -68,7 +69,7 @@ class IpScramblingStateUseCase( ) init { - coroutineScope.launch { + coroutineScope.launch(Dispatchers.Main) { localStateRepository.ipScramblingSetting.collect { applySettings(it) } 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 e39c2ed8..8a0a3d4a 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 @@ -228,7 +228,6 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) { ) ) - binding.toggleIpscrambling.isChecked = state.ipScramblingMode.isChecked val isLoading = state.ipScramblingMode.isLoading 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 3e874820..1a338449 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 @@ -75,11 +75,11 @@ class AppTrackersViewModel( } fun submitAction(action: Action) = viewModelScope.launch { - when (action) { - is Action.BlockAllToggleAction -> blockAllToggleAction(action) - is Action.ToggleTrackerAction -> toggleTrackerAction(action) - is Action.ClickTracker -> actionClickTracker(action) - } + when (action) { + is Action.BlockAllToggleAction -> blockAllToggleAction(action) + is Action.ToggleTrackerAction -> toggleTrackerAction(action) + is Action.ClickTracker -> actionClickTracker(action) + } } private suspend fun blockAllToggleAction(action: Action.BlockAllToggleAction) { diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_dashboard.xml index 7ed581b0..cedf5690 100644 --- a/app/src/main/res/layout/fragment_dashboard.xml +++ b/app/src/main/res/layout/fragment_dashboard.xml @@ -63,7 +63,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" - android:paddingStart="8dp" + android:gravity="center_horizontal" > - 1_ Advanced Privacy + Advanced Privacy System -- GitLab From cf57ead4c5d7ad6895111236a15157d5cdef050d Mon Sep 17 00:00:00 2001 From: Guillaume Jacquart Date: Fri, 11 Nov 2022 14:36:20 +0100 Subject: [PATCH 3/5] MR feedbacks --- app/build.gradle | 2 +- .../domain/usecases/FakeLocationStateUseCase.kt | 8 ++++++-- .../features/dashboard/DashboardViewModel.kt | 6 +----- app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-fi/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-it/strings.xml | 1 - build.gradle | 2 +- 8 files changed, 9 insertions(+), 13 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index dd5c27bf..323a1186 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -132,7 +132,7 @@ dependencies { implementation project(':trackers') - implementation 'foundation.e:privacymodule.tor:1.6.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/domain/usecases/FakeLocationStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt index edf3c6df..65f1711e 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 @@ -119,10 +119,14 @@ class FakeLocationStateUseCase( return Triple( when { !isFakeLocationEnabled -> LocationMode.REAL_LOCATION - fakeLocation in citiesRepository.citiesLocationsList && !isSpecificLocation -> LocationMode.RANDOM_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/features/dashboard/DashboardViewModel.kt b/app/src/main/java/foundation/e/privacycentralapp/features/dashboard/DashboardViewModel.kt index fc563971..57e77908 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 @@ -89,13 +89,9 @@ class DashboardViewModel( when (action) { is Action.ToggleTrackers -> { getPrivacyStateUseCase.toggleTrackers() + // Add delay here to prevent race condition with trackers state. delay(200) fetchStatistics().first() - // trackersStatisticsUseCase.getNonBlockedTrackersCount().map { - // _state.update { s -> - // s.copy(allowedTrackersCount = it) - // } - // } } is Action.ToggleLocation -> getPrivacyStateUseCase.toggleLocation() is Action.ToggleIpScrambling -> actionToggleIpScrambling() diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index c67f7c30..ea0bacd4 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -110,7 +110,6 @@ Tippe auf die Balken für weitere Informationen. Tippe, um herauszufinden, wie Tracker einfach blockiert, dein Standort gefälscht und deine IP-Adresse verschleiert werden kann. Benutzerdefinierte Datenschutz-Einstellungen werden angewendet - Die Änderungen werden erst beim Aktivieren des Datenschutz-Schalters angewandt. Schließen Das Verschleiern deiner IP wird möglicherweise die Internetgeschwindigkeit verlangsamen. Benutzerdefinierte Datenschutz-Einstellungen werden angewandt diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 62adcf2f..b5932de4 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -100,7 +100,6 @@ Sovelletaan mukautettuja yksityisyysasetuksia Yksityisyytesi verkossa on suojattu Sulje - Muutokset tulevat voimaan vain, kun yksityisyydensuojan kytkin on käytössä. Napauta palkkeja saadaksesi lisätietoja. Sallittuja tietovuotoja Estettyjä tietovuotoja diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 3dcf6d6a..b4db80f6 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -96,7 +96,6 @@ - Tous les pisteurs sont désactivés. \n- Votre géolocalisation sera falsifiée. \n- Votre adresse IP réelle sera masquée. - Les modifications seront effectives uniquement quand la protection de la confidentialité sera activée. Votre vitesse Internet risque d\'être réduite tant que votre adresse IP est masquée. Fuites autorisées Fuites bloquées diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 173b156b..316aa4f8 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -110,7 +110,6 @@ Guarda Impostazioni della privacy personalizzate applicate Chiudi - I cambiamenti avranno efficacia solo dopo l\'abilitazione del pulsante protezione privacy. Tocca le barre per maggiori informazioni. Perdite di dati ammesse Perdite di dati bloccate diff --git a/build.gradle b/build.gradle index 0fe3d8fb..2abc73d2 100644 --- a/build.gradle +++ b/build.gradle @@ -146,7 +146,7 @@ subprojects { tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { kotlinOptions { // Treat all Kotlin warnings as errors - // TODO allWarningsAsErrors = true + allWarningsAsErrors = true freeCompilerArgs += "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi" // Set JVM target to 1.8 -- GitLab From ffcb2eb4ab8cf7327ee1ba7418cc0735e391d4b6 Mon Sep 17 00:00:00 2001 From: Guillaume Jacquart Date: Wed, 16 Nov 2022 09:02:05 +0100 Subject: [PATCH 4/5] MR feedbaks 2 --- .../data/repositories/LocalStateRepository.kt | 6 ++---- .../domain/usecases/GetQuickPrivacyStateUseCase.kt | 7 ++++--- 2 files changed, 6 insertions(+), 7 deletions(-) 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 cdb47b95..4c1c0a14 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 @@ -78,10 +78,8 @@ class LocalStateRepository(context: Context) { private val _ipScramblingSetting = MutableStateFlow(sharedPref.getBoolean(KEY_IP_SCRAMBLING, false)) val ipScramblingSetting = _ipScramblingSetting.asStateFlow() - fun setIpScramblingReturnIsFirstActivation(enabled: Boolean): Boolean { - val isFirstActivation = enabled && !sharedPref.contains(KEY_IP_SCRAMBLING) - setIpScramblingSetting(enabled) - return isFirstActivation + fun isIpScramblingFirstActivation(enabled: Boolean): Boolean { + return enabled && !sharedPref.contains(KEY_IP_SCRAMBLING) } fun setIpScramblingSetting(enabled: Boolean) { 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 e58ab12b..85410d00 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 @@ -82,9 +82,10 @@ class GetQuickPrivacyStateUseCase( } fun toggleIpScramblingIsFirstActivation(): Boolean { - return localStateRepository.setIpScramblingReturnIsFirstActivation( - !localStateRepository.ipScramblingSetting.value - ) + val enabled = !localStateRepository.ipScramblingSetting.value + val firstActivation = localStateRepository.isIpScramblingFirstActivation(enabled) + localStateRepository.setIpScramblingSetting(enabled) + return firstActivation } val otherVpnRunning: SharedFlow = localStateRepository.otherVpnRunning -- GitLab From 4c6d5ac5f0d8ab55a73b4d657b110c8bc0d8c766 Mon Sep 17 00:00:00 2001 From: Guillaume Jacquart Date: Fri, 18 Nov 2022 07:13:13 +0100 Subject: [PATCH 5/5] Feedback MR 3. --- .../data/repositories/LocalStateRepository.kt | 4 ++-- .../usecases/FakeLocationStateUseCase.kt | 8 +++----- .../usecases/IpScramblingStateUseCase.kt | 2 +- app/src/main/res/layout/widget.xml | 19 +++++++++++-------- 4 files changed, 17 insertions(+), 16 deletions(-) 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 4c1c0a14..92ee0c16 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 @@ -70,7 +70,7 @@ class LocalStateRepository(context: Context) { sharedPref.edit() .putFloat(KEY_FAKE_LATITUDE, value.first) .putFloat(KEY_FAKE_LONGITUDE, value.second) - .commit() + .apply() } val locationMode: MutableStateFlow = MutableStateFlow(LocationMode.REAL_LOCATION) @@ -100,6 +100,6 @@ class LocalStateRepository(context: Context) { 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/usecases/FakeLocationStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt index 65f1711e..2910f26a 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 @@ -114,15 +114,13 @@ class FakeLocationStateUseCase( private fun computeLocationMode( isFakeLocationEnabled: Boolean, fakeLocation: Pair, - isSpecificLocation: Boolean = false + isSpecificLocation: Boolean = false, ): Triple { return Triple( when { !isFakeLocationEnabled -> LocationMode.REAL_LOCATION - ( - fakeLocation in citiesRepository.citiesLocationsList && - !isSpecificLocation - ) -> LocationMode.RANDOM_LOCATION + (fakeLocation in citiesRepository.citiesLocationsList && !isSpecificLocation) -> + LocationMode.RANDOM_LOCATION else -> LocationMode.SPECIFIC_LOCATION }, fakeLocation.first, 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 c0b41fc7..9216233e 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 @@ -69,7 +69,7 @@ class IpScramblingStateUseCase( ) init { - coroutineScope.launch(Dispatchers.Main) { + coroutineScope.launch(Dispatchers.Default) { localStateRepository.ipScramblingSetting.collect { applySettings(it) } diff --git a/app/src/main/res/layout/widget.xml b/app/src/main/res/layout/widget.xml index 17b9be00..1e78bc75 100644 --- a/app/src/main/res/layout/widget.xml +++ b/app/src/main/res/layout/widget.xml @@ -100,11 +100,12 @@