summaryrefslogtreecommitdiff
path: root/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main')
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/domain/usecases/IpScramblingStateUseCase.kt14
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt50
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFragment.kt11
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt1
-rw-r--r--app/src/main/res/layout/fragment_dashboard.xml2
5 files changed, 54 insertions, 24 deletions
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 a701eec..0d25d16 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
@@ -25,6 +25,7 @@ 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
@@ -41,6 +42,9 @@ class IpScramblingStateUseCase(
coroutineScope: CoroutineScope
) {
+ val _configuredMode = MutableStateFlow(localStateRepository.isIpScramblingEnabled)
+ val configuredMode: StateFlow<Boolean> = _configuredMode
+
val internetPrivacyMode: StateFlow<InternetPrivacyMode> = callbackFlow {
val listener = object : IIpScramblerModule.Listener {
override fun onStatusChanged(newStatus: IIpScramblerModule.Status) {
@@ -78,10 +82,14 @@ class IpScramblingStateUseCase(
}
fun toggle(hideIp: Boolean) {
- if (!localStateRepository.isQuickPrivacyEnabled) return
-
localStateRepository.isIpScramblingEnabled = hideIp
- applySettings(true, hideIp)
+ _configuredMode.value = hideIp
+
+ if (!localStateRepository.isQuickPrivacyEnabled) {
+ localStateRepository.setShowQuickPrivacyDisabledMessage(true)
+ } else {
+ applySettings(true, hideIp)
+ }
}
private fun getHiddenPackageNames(): List<String> {
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt
index eca1578..8e4318d 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/internetprivacy/InternetPrivacyFeature.kt
@@ -36,6 +36,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.debounce
+import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
@@ -63,7 +64,8 @@ class InternetPrivacyFeature(
val bypassTorApps: Collection<String>,
val selectedLocation: String,
val availableLocationIds: List<String>,
- val forceRedraw: Boolean = false
+ val forceRedraw: Boolean = false,
+ val showQuickPrivacyDisabledMessage: Boolean = false
) {
fun getApps(): List<Pair<ApplicationDescription, Boolean>> {
return availableApps.map { it to (it.packageName !in bypassTorApps) }
@@ -84,6 +86,7 @@ class InternetPrivacyFeature(
data class AndroidVpnActivityResultAction(val resultCode: Int) : Action()
data class ToggleAppIpScrambled(val packageName: String) : Action()
data class SelectLocationAction(val position: Int) : Action()
+ object CloseQuickPrivacyDisabledMessage : Action()
}
sealed class Effect {
@@ -100,6 +103,7 @@ class InternetPrivacyFeature(
data class LocationSelectedEffect(val locationId: String) : Effect()
object WarningStartingLongEffect : Effect()
data class ErrorEffect(val message: String) : Effect()
+ data class ShowQuickPrivacyDisabledMessageEffect(val show: Boolean) : Effect()
}
companion object {
@@ -131,6 +135,7 @@ class InternetPrivacyFeature(
)
is Effect.LocationSelectedEffect -> state.copy(selectedLocation = effect.locationId)
Effect.QuickPrivacyDisabledWarningEffect -> state.copy(forceRedraw = !state.forceRedraw)
+ is Effect.ShowQuickPrivacyDisabledMessageEffect -> state.copy(showQuickPrivacyDisabledMessage = effect.show)
else -> state
}
},
@@ -139,9 +144,24 @@ class InternetPrivacyFeature(
action is Action.LoadInternetModeAction -> merge(
getQuickPrivacyStateUseCase.quickPrivacyEnabledFlow
.map { Effect.QuickPrivacyUpdatedEffect(it) },
- ipScramblingStateUseCase.internetPrivacyMode
- .map { Effect.ModeUpdatedEffect(it) }
- .shareIn(scope = coroutineScope, started = SharingStarted.Lazily, replay = 0),
+ getQuickPrivacyStateUseCase.showQuickPrivacyDisabledMessage.map {
+ Effect.ShowQuickPrivacyDisabledMessageEffect(it)
+ },
+ getQuickPrivacyStateUseCase.quickPrivacyEnabledFlow.flatMapLatest { enabled ->
+ if (enabled) ipScramblingStateUseCase.internetPrivacyMode
+ .map { Effect.ModeUpdatedEffect(it) }
+ .shareIn(
+ scope = coroutineScope,
+ started = SharingStarted.Lazily,
+ replay = 0
+ )
+ else ipScramblingStateUseCase.configuredMode.map {
+ Effect.ModeUpdatedEffect(
+ if (it) InternetPrivacyMode.HIDE_IP
+ else InternetPrivacyMode.REAL_IP
+ )
+ }
+ },
appListUseCase.getAppsUsingInternet().map { apps ->
Effect.AvailableAppsListEffect(
apps,
@@ -175,24 +195,16 @@ class InternetPrivacyFeature(
InternetPrivacyMode.HIDE_IP_LOADING,
InternetPrivacyMode.REAL_IP_LOADING
) -> {
- if (getQuickPrivacyStateUseCase.isQuickPrivacyEnabled) {
- ipScramblingStateUseCase.toggle(hideIp = false)
- flowOf(Effect.ModeUpdatedEffect(InternetPrivacyMode.REAL_IP_LOADING))
- } else {
- flowOf(Effect.QuickPrivacyDisabledWarningEffect)
- }
+ ipScramblingStateUseCase.toggle(hideIp = false)
+ flowOf(Effect.ModeUpdatedEffect(InternetPrivacyMode.REAL_IP_LOADING))
}
action is Action.UseHiddenIPAction
&& state.mode in listOf(
InternetPrivacyMode.REAL_IP,
InternetPrivacyMode.REAL_IP_LOADING
) -> {
- if (getQuickPrivacyStateUseCase.isQuickPrivacyEnabled) {
- ipScramblingStateUseCase.toggle(hideIp = true)
- flowOf(Effect.ModeUpdatedEffect(InternetPrivacyMode.HIDE_IP_LOADING))
- } else {
- flowOf(Effect.QuickPrivacyDisabledWarningEffect)
- }
+ ipScramblingStateUseCase.toggle(hideIp = true)
+ flowOf(Effect.ModeUpdatedEffect(InternetPrivacyMode.HIDE_IP_LOADING))
}
action is Action.ToggleAppIpScrambled -> {
@@ -208,6 +220,10 @@ class InternetPrivacyFeature(
flowOf(Effect.NoEffect)
}
}
+ action is Action.CloseQuickPrivacyDisabledMessage -> {
+ getQuickPrivacyStateUseCase.resetQuickPrivacyDisabledMessage()
+ flowOf(Effect.NoEffect)
+ }
else -> flowOf(Effect.NoEffect)
}
},
@@ -216,8 +232,6 @@ class InternetPrivacyFeature(
effect is Effect.ErrorEffect -> SingleEvent.ErrorEvent(effect.message)
effect is Effect.WarningStartingLongEffect ->
SingleEvent.ErrorEvent(R.string.ipscrambling_warning_starting_long)
- effect is Effect.QuickPrivacyDisabledWarningEffect -> SingleEvent.ErrorEvent(error = R.string.ipscrambling_error_quickprivacy_disabled)
-
action is Action.UseHiddenIPAction
&& effect is Effect.ShowAndroidVpnDisclaimerEffect ->
SingleEvent.StartAndroidVpnActivityEvent(effect.intent)
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 f49399f..2452d33 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
@@ -26,12 +26,14 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
import foundation.e.flowmvi.MVIView
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.databinding.FragmentInternetActivityPolicyBinding
import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
import foundation.e.privacycentralapp.extensions.toText
@@ -56,6 +58,8 @@ class InternetPrivacyFragment :
private lateinit var binding: FragmentInternetActivityPolicyBinding
+ private var qpDisabledSnackbar: Snackbar? = null
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launchWhenStarted {
@@ -132,12 +136,19 @@ class InternetPrivacyFragment :
}
}
+ qpDisabledSnackbar = initQuickPrivacySnackbar(binding.root) {
+ viewModel.submitAction(InternetPrivacyFeature.Action.CloseQuickPrivacyDisabledMessage)
+ }
+
binding.executePendingBindings()
}
override fun getTitle(): String = getString(R.string.ipscrambling_title)
override fun render(state: InternetPrivacyFeature.State) {
+ if (state.showQuickPrivacyDisabledMessage) qpDisabledSnackbar?.show()
+ else qpDisabledSnackbar?.dismiss()
+
binding.radioUseHiddenIp.radiobutton.apply {
isChecked = state.mode in listOf(
InternetPrivacyMode.HIDE_IP,
diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt
index faac5a4..6ca93d3 100644
--- a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt
+++ b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFeature.kt
@@ -109,7 +109,6 @@ class FakeLocationFeature(
when (action) {
is Action.Init -> {
fakeLocationStateUseCase.startListeningLocation()
-
merge(
getQuickPrivacyStateUseCase.quickPrivacyEnabledFlow.map { Effect.QuickPrivacyUpdatedEffect(it) },
fakeLocationStateUseCase.configuredLocationMode.map { (mode, lat, lon) ->
diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_dashboard.xml
index d2cb53c..d79dea1 100644
--- a/app/src/main/res/layout/fragment_dashboard.xml
+++ b/app/src/main/res/layout/fragment_dashboard.xml
@@ -13,7 +13,6 @@
android:layout_width="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
-
<LinearLayout
android:background="@color/background"
android:gravity="center_horizontal"
@@ -200,7 +199,6 @@ android:text="@string/dashboard_state_ipaddress_off"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/graph"
/>
-
<View
android:id="@+id/graph_legend_blocked_icon"
android:layout_width="16dp"