Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 21c36aa3 authored by Guillaume Jacquart's avatar Guillaume Jacquart
Browse files

Merge branch '5561-inform_vpn_always_on_already_running' into 'main'

5561: alert user that alwaysOn 3rd party VPN is running.

See merge request !94
parents 61361723 2f349590
Loading
Loading
Loading
Loading
Loading
+18 −4
Original line number Diff line number Diff line
@@ -20,9 +20,12 @@ package foundation.e.privacycentralapp.data.repositories
import android.content.Context
import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
import foundation.e.privacycentralapp.domain.entities.LocationMode
import kotlinx.coroutines.flow.Flow
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 {
@@ -48,6 +51,13 @@ class LocalStateRepository(context: Context) {
        return isFirstActivation
    }

    private val _otherVpnRunning = MutableSharedFlow<Boolean>()
    suspend fun emitOtherVpnRunning() {
        _otherVpnRunning.emit(true)
    }

    val otherVpnRunning: SharedFlow<Boolean> = _otherVpnRunning

    var quickPrivacyEnabledFlow: StateFlow<Boolean> = quickPrivacyEnabledMutableFlow

    val areAllTrackersBlocked: MutableStateFlow<Boolean> = MutableStateFlow(false)
@@ -79,9 +89,13 @@ class LocalStateRepository(context: Context) {

    val locationMode: MutableStateFlow<LocationMode> = MutableStateFlow(LocationMode.REAL_LOCATION)

    var isIpScramblingEnabled: Boolean
        get() = sharedPref.getBoolean(KEY_IP_SCRAMBLING, true)
        set(value) = set(KEY_IP_SCRAMBLING, value)
    private val _ipScramblingSetting = MutableStateFlow(sharedPref.getBoolean(KEY_IP_SCRAMBLING, true))
    val ipScramblingSetting = _ipScramblingSetting.asStateFlow()

    fun setIpScramblingSetting(enabled: Boolean) {
        set(KEY_IP_SCRAMBLING, enabled)
        _ipScramblingSetting.update { enabled }
    }

    val internetPrivacyMode: MutableStateFlow<InternetPrivacyMode> = MutableStateFlow(InternetPrivacyMode.REAL_IP)

+4 −2
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@

package foundation.e.privacycentralapp.domain.usecases

import android.util.Log
import foundation.e.privacycentralapp.data.repositories.LocalStateRepository
import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
import foundation.e.privacycentralapp.domain.entities.LocationMode
@@ -25,8 +24,8 @@ import foundation.e.privacycentralapp.domain.entities.QuickPrivacyState
import foundation.e.privacycentralapp.domain.entities.TrackerMode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch

@@ -106,4 +105,7 @@ class GetQuickPrivacyStateUseCase(
    fun resetQuickPrivacyDisabledMessage() {
        localStateRepository.setShowQuickPrivacyDisabledMessage(false)
    }

    val otherVpnRunning: SharedFlow<Boolean> = localStateRepository.otherVpnRunning

}
+15 −9
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import foundation.e.privacymodules.permissions.IPermissionsPrivacyModule
import foundation.e.privacymodules.permissions.data.ApplicationDescription
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.callbackFlow
@@ -38,11 +37,10 @@ class IpScramblingStateUseCase(
    private val appDesc: ApplicationDescription,
    private val localStateRepository: LocalStateRepository,
    private val appListsRepository: AppListsRepository,
    coroutineScope: CoroutineScope
    private val coroutineScope: CoroutineScope
) {

    val _configuredMode = MutableStateFlow(localStateRepository.isIpScramblingEnabled)
    val configuredMode: StateFlow<Boolean> = _configuredMode
    val configuredMode: StateFlow<Boolean> = localStateRepository.ipScramblingSetting

    val internetPrivacyMode: StateFlow<InternetPrivacyMode> = callbackFlow {
        val listener = object : IIpScramblerModule.Listener {
@@ -71,7 +69,7 @@ class IpScramblingStateUseCase(
    init {
        coroutineScope.launch {
            localStateRepository.quickPrivacyEnabledFlow.collect {
                applySettings(it, localStateRepository.isIpScramblingEnabled)
                applySettings(it, localStateRepository.ipScramblingSetting.value)
            }
        }

@@ -81,8 +79,7 @@ class IpScramblingStateUseCase(
    }

    fun toggle(hideIp: Boolean) {
        localStateRepository.isIpScramblingEnabled = hideIp
        _configuredMode.value = hideIp
        localStateRepository.setIpScramblingSetting(enabled = hideIp)

        if (!localStateRepository.isQuickPrivacyEnabled) {
            localStateRepository.setShowQuickPrivacyDisabledMessage(true)
@@ -132,12 +129,21 @@ class IpScramblingStateUseCase(
        when {
            isQuickPrivacyEnabled && isIpScramblingEnabled -> when (localStateRepository.internetPrivacyMode.value) {
                InternetPrivacyMode.REAL_IP, InternetPrivacyMode.REAL_IP_LOADING -> {
                    val intent = ipScramblerModule.prepareAndroidVpn()
                    var intent = ipScramblerModule.prepareAndroidVpn()
                    if (intent != null) {
                        permissionsPrivacyModule.setVpnPackageAuthorization(appDesc.packageName)
                        intent = ipScramblerModule.prepareAndroidVpn()
                    }

                    if (intent != null) {
                        coroutineScope.launch {
                            localStateRepository.emitOtherVpnRunning()
                        }
                        localStateRepository.setIpScramblingSetting(enabled = false)
                    } else {
                        ipScramblerModule.start(enableNotification = false)
                    }
                }
                else -> {}
            }
            else -> when (localStateRepository.internetPrivacyMode.value) {
+5 −0
Original line number Diff line number Diff line
@@ -74,6 +74,11 @@ class DashboardViewModel(
            },
            getPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map {
                _state.update { s -> s.copy(showQuickPrivacyDisabledMessage = it) }
            },
            getPrivacyStateUseCase.otherVpnRunning.map {
                _singleEvents.emit(SingleEvent.ToastMessageSingleEvent(
                    R.string.ipscrambling_error_always_on_vpn_already_running
                ))
            }
        ).collect {}
    }
+10 −2
Original line number Diff line number Diff line
@@ -105,6 +105,14 @@ class InternetPrivacyViewModel(
                    )
                }
        }

        launch {
            getQuickPrivacyStateUseCase.otherVpnRunning.collect {
                _singleEvents.emit(SingleEvent.ErrorEvent(R.string.ipscrambling_error_always_on_vpn_already_running))
                _state.update { it.copy(forceRedraw = !it.forceRedraw)}

            }
        }
    }

    fun submitAction(action: Action) = viewModelScope.launch {
@@ -126,12 +134,12 @@ class InternetPrivacyViewModel(
        ipScramblingStateUseCase.toggle(hideIp = true)
    }

    suspend private fun actionToggleAppIpScrambled(action: Action.ToggleAppIpScrambled) = withContext(Dispatchers.IO) {
    private suspend fun actionToggleAppIpScrambled(action: Action.ToggleAppIpScrambled) = withContext(Dispatchers.IO) {
        ipScramblingStateUseCase.toggleBypassTor(action.packageName)
        _state.update { it.copy(bypassTorApps = ipScramblingStateUseCase.bypassTorApps) }
    }

    suspend private fun actionSelectLocation(action: Action.SelectLocationAction) = withContext(Dispatchers.IO) {
    private suspend fun actionSelectLocation(action: Action.SelectLocationAction) = withContext(Dispatchers.IO) {
        val locationId = _state.value.availableLocationIds[action.position]
        if (locationId != ipScramblerModule.exitCountry) {
            ipScramblerModule.exitCountry = locationId
Loading