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

Commit 1a7460b9 authored by Guillaume Jacquart's avatar Guillaume Jacquart
Browse files

Merge branch '5290_snackbar_qp_disabled' into 'main'

5290 : allow settings while main toggle off.

See merge request e/privacy-central/privacycentralapp!46
parents d0f8ec47 f9f49a98
Loading
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -78,7 +78,7 @@ class DependencyContainer(val app: Application) {

    // Usecases
    val getQuickPrivacyStateUseCase by lazy {
        GetQuickPrivacyStateUseCase(localStateRepository)
        GetQuickPrivacyStateUseCase(localStateRepository, GlobalScope)
    }
    private val ipScramblingStateUseCase by lazy {
        IpScramblingStateUseCase(
@@ -119,7 +119,7 @@ class DependencyContainer(val app: Application) {
    }

    val trackersViewModelFactory by lazy {
        TrackersViewModelFactory(trackersStatisticsUseCase)
        TrackersViewModelFactory(getQuickPrivacyStateUseCase, trackersStatisticsUseCase)
    }

    val appTrackersViewModelFactory by lazy {
+36 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 E FOUNDATION
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package foundation.e.privacycentralapp.common

import android.view.View
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar
import foundation.e.privacycentralapp.R

fun initQuickPrivacySnackbar(view: View, onDismiss: () -> Unit): Snackbar {
    val snackbar = Snackbar.make(view, R.string.quickprivacy_disabled_message, Snackbar.LENGTH_INDEFINITE)
    snackbar.setAction(R.string.close) { onDismiss() }

    snackbar.addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
        override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
            super.onDismissed(transientBottomBar, event)
            if (event == DISMISS_EVENT_SWIPE) onDismiss()
        }
    })
    return snackbar
}
+8 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
import foundation.e.privacycentralapp.domain.entities.LocationMode
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow

class LocalStateRepository(context: Context) {
    companion object {
@@ -84,6 +85,13 @@ class LocalStateRepository(context: Context) {

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

    private val _showQuickPrivacyDisabledMessage = MutableStateFlow(false)
    val showQuickPrivacyDisabledMessage: StateFlow<Boolean> = _showQuickPrivacyDisabledMessage

    fun setShowQuickPrivacyDisabledMessage(show: Boolean) {
        _showQuickPrivacyDisabledMessage.value = show
    }

    var firstBoot: Boolean
        get() = sharedPref.getBoolean(KEY_FIRST_BOOT, true)
        set(value) = set(KEY_FIRST_BOOT, value)
+31 −28
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import foundation.e.privacymodules.permissions.data.AppOpModes
import foundation.e.privacymodules.permissions.data.ApplicationDescription
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlin.random.Random
@@ -46,8 +47,8 @@ class FakeLocationStateUseCase(
    private val appContext: Context,
    private val coroutineScope: CoroutineScope
) {
    // private val _locationMode = MutableStateFlow(LocationMode.REAL_LOCATION)
    // val locationMode: StateFlow<LocationMode> = _locationMode
    private val _configuredLocationMode = MutableStateFlow<Triple<LocationMode, Float?, Float?>>(Triple(LocationMode.REAL_LOCATION, null, null))
    val configuredLocationMode: StateFlow<Triple<LocationMode, Float?, Float?>> = _configuredLocationMode

    init {
        coroutineScope.launch {
@@ -60,44 +61,23 @@ class FakeLocationStateUseCase(
    private val locationManager: LocationManager
        get() = appContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager

    fun getLocationMode(): Triple<LocationMode, Float?, Float?> {
        val fakeLocation = localStateRepository.fakeLocation
        return if (fakeLocation != null && localStateRepository.locationMode.value == LocationMode.SPECIFIC_LOCATION) {
            Triple(
                LocationMode.SPECIFIC_LOCATION,
                fakeLocation.first,
                fakeLocation.second
            )
        } else {
            Triple(localStateRepository.locationMode.value, null, null)
        }
    }

    private fun acquireLocationPermission() {
        permissionsModule.toggleDangerousPermission(
            appDesc,
            android.Manifest.permission.ACCESS_FINE_LOCATION, true
        )

        // permissionsModule.setAppOpMode(
        //     appDesc, AppOpsManager.OPSTR_COARSE_LOCATION,
        //     AppOpModes.ALLOWED
        // )
        // permissionsModule.setAppOpMode(
        //     appDesc, AppOpsManager.OPSTR_FINE_LOCATION,
        //     AppOpModes.ALLOWED
        // )
    }

    private fun applySettings(isQuickPrivacyEnabled: Boolean, fakeLocation: Pair<Float, Float>?) {
        _configuredLocationMode.value = computeLocationMode(fakeLocation)

        if (isQuickPrivacyEnabled && fakeLocation != null) {
            if (permissionsModule.getAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION) != AppOpModes.ALLOWED) {
                permissionsModule.setAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION, AppOpModes.ALLOWED)
            }
            fakeLocationModule.startFakeLocation()
            fakeLocationModule.setFakeLocation(fakeLocation.first.toDouble(), fakeLocation.second.toDouble())
            localStateRepository.locationMode.value = if (fakeLocation in citiesRepository.citiesLocationsList) LocationMode.RANDOM_LOCATION
            else LocationMode.SPECIFIC_LOCATION
            localStateRepository.locationMode.value = configuredLocationMode.value.first
        } else {
            fakeLocationModule.stopFakeLocation()
            localStateRepository.locationMode.value = LocationMode.REAL_LOCATION
@@ -105,10 +85,18 @@ class FakeLocationStateUseCase(
    }

    fun setSpecificLocation(latitude: Float, longitude: Float) {
        if (!localStateRepository.isQuickPrivacyEnabled) {
            localStateRepository.setShowQuickPrivacyDisabledMessage(true)
        }

        setFakeLocation(latitude to longitude)
    }

    fun setRandomLocation() {
        if (!localStateRepository.isQuickPrivacyEnabled) {
            localStateRepository.setShowQuickPrivacyDisabledMessage(true)
        }

        val randomIndex = Random.nextInt(citiesRepository.citiesLocationsList.size)
        val location = citiesRepository.citiesLocationsList[randomIndex]

@@ -117,12 +105,27 @@ class FakeLocationStateUseCase(

    private fun setFakeLocation(location: Pair<Float, Float>) {
        localStateRepository.fakeLocation = location
        applySettings(true, location)
        applySettings(localStateRepository.isQuickPrivacyEnabled, location)
    }

    fun stopFakeLocation() {
        if (!localStateRepository.isQuickPrivacyEnabled) {
            localStateRepository.setShowQuickPrivacyDisabledMessage(true)
        }

        localStateRepository.fakeLocation = null
        applySettings(true, null)
        applySettings(localStateRepository.isQuickPrivacyEnabled, null)
    }

    private fun computeLocationMode(fakeLocation: Pair<Float, Float>?): Triple<LocationMode, Float?, Float?> {
        return Triple(
            when {
                fakeLocation == null -> LocationMode.REAL_LOCATION
                fakeLocation in citiesRepository.citiesLocationsList -> LocationMode.RANDOM_LOCATION
                else -> LocationMode.SPECIFIC_LOCATION
            },
            fakeLocation?.first, fakeLocation?.second
        )
    }

    val currentLocation = MutableStateFlow<Location?>(null)
+22 −2
Original line number Diff line number Diff line
@@ -21,12 +21,26 @@ import foundation.e.privacycentralapp.data.repositories.LocalStateRepository
import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
import foundation.e.privacycentralapp.domain.entities.LocationMode
import foundation.e.privacycentralapp.domain.entities.QuickPrivacyState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch

class GetQuickPrivacyStateUseCase(
    private val localStateRepository: LocalStateRepository,
    private val coroutineScope: CoroutineScope
) {

    init {
        coroutineScope.launch {
            localStateRepository.quickPrivacyEnabledFlow.collect {
                if (it) resetQuickPrivacyDisabledMessage()
            }
        }
    }

class GetQuickPrivacyStateUseCase(private val localStateRepository: LocalStateRepository) {
    val quickPrivacyEnabledFlow = localStateRepository.quickPrivacyEnabledFlow
    val isQuickPrivacyEnabled get() = localStateRepository.isQuickPrivacyEnabled

    val quickPrivacyState = combine(
        localStateRepository.quickPrivacyEnabledFlow,
@@ -77,4 +91,10 @@ class GetQuickPrivacyStateUseCase(private val localStateRepository: LocalStateRe
        val newState = !localStateRepository.isQuickPrivacyEnabled
        return localStateRepository.setQuickPrivacyReturnIsFirstActivation(newState)
    }

    val showQuickPrivacyDisabledMessage: StateFlow<Boolean> = localStateRepository.showQuickPrivacyDisabledMessage

    fun resetQuickPrivacyDisabledMessage() {
        localStateRepository.setShowQuickPrivacyDisabledMessage(false)
    }
}
Loading