diff --git a/composeApp/src/commonMain/composeResources/values/strings-common.xml b/composeApp/src/commonMain/composeResources/values/strings-common.xml
index 13b6f99d7..26ecd5749 100644
--- a/composeApp/src/commonMain/composeResources/values/strings-common.xml
+++ b/composeApp/src/commonMain/composeResources/values/strings-common.xml
@@ -9,6 +9,7 @@
Estimated time left:
Stopping test…
Finishing the currently pending tests, please wait…
+ Proxy in use
OONI Tests
OONI Run Links
Run finished. Tap to view results.
@@ -231,7 +232,7 @@
OONI Probe cannot run automatically without battery optimization. Do you want to try again?
- Last updated %1$s
+ Last updated %1$s
Back
refresh
Measurement
diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/di/Dependencies.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/di/Dependencies.kt
index a7fb12a22..41680a8cf 100644
--- a/composeApp/src/commonMain/kotlin/org/ooni/probe/di/Dependencies.kt
+++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/di/Dependencies.kt
@@ -57,6 +57,7 @@ import org.ooni.probe.domain.GetBootstrapTestDescriptors
import org.ooni.probe.domain.GetDefaultTestDescriptors
import org.ooni.probe.domain.GetEnginePreferences
import org.ooni.probe.domain.GetFirstRun
+import org.ooni.probe.domain.GetProxySettings
import org.ooni.probe.domain.GetResult
import org.ooni.probe.domain.GetResults
import org.ooni.probe.domain.GetSettings
@@ -238,7 +239,10 @@ class Dependencies(
}
val getCurrentTestState get() = testStateManager::observeState
private val getDefaultTestDescriptors by lazy { GetDefaultTestDescriptors() }
- private val getEnginePreferences by lazy { GetEnginePreferences(preferenceRepository) }
+ private val getProxySettings by lazy { GetProxySettings(preferenceRepository) }
+ private val getEnginePreferences by lazy {
+ GetEnginePreferences(preferencesRepository = preferenceRepository, getProxySettings = getProxySettings::invoke)
+ }
private val getFirstRun by lazy { GetFirstRun(preferenceRepository) }
private val getResults by lazy {
GetResults(
@@ -453,6 +457,7 @@ class Dependencies(
observeTestRunState = testStateManager.observeState(),
observeTestRunErrors = testStateManager.observeErrors(),
cancelTestRun = testStateManager::cancelTestRun,
+ getProxySettings = getProxySettings::invoke,
)
fun runViewModel(onBack: () -> Unit) =
diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetEnginePreferences.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetEnginePreferences.kt
index 10382902c..4781305f6 100644
--- a/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetEnginePreferences.kt
+++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetEnginePreferences.kt
@@ -11,6 +11,7 @@ import kotlin.time.Duration.Companion.seconds
class GetEnginePreferences(
private val preferencesRepository: PreferenceRepository,
+ private val getProxySettings: suspend () -> ProxySettings,
) {
suspend operator fun invoke() =
EnginePreferences(
@@ -26,11 +27,7 @@ class GetEnginePreferences(
} else {
null
},
- proxy = ProxySettings.newProxySettings(
- protocol = getValueForKey(SettingsKey.PROXY_PROTOCOL) as? String,
- hostname = getValueForKey(SettingsKey.PROXY_HOSTNAME) as? String,
- port = getValueForKey(SettingsKey.PROXY_PORT) as? String,
- ).getProxyString(),
+ proxy = getProxySettings().getProxyString(),
)
private suspend fun getEnabledCategories(): List {
diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetProxySettings.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetProxySettings.kt
new file mode 100644
index 000000000..b5fb6fb05
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetProxySettings.kt
@@ -0,0 +1,19 @@
+package org.ooni.probe.domain
+
+import kotlinx.coroutines.flow.first
+import org.ooni.probe.data.models.ProxySettings
+import org.ooni.probe.data.models.SettingsKey
+import org.ooni.probe.data.repositories.PreferenceRepository
+
+class GetProxySettings(
+ private val preferencesRepository: PreferenceRepository,
+) {
+ suspend operator fun invoke() =
+ ProxySettings.newProxySettings(
+ protocol = getValueForKey(SettingsKey.PROXY_PROTOCOL) as? String,
+ hostname = getValueForKey(SettingsKey.PROXY_HOSTNAME) as? String,
+ port = getValueForKey(SettingsKey.PROXY_PORT) as? String,
+ )
+
+ private suspend fun getValueForKey(settingsKey: SettingsKey) = preferencesRepository.getValueByKey(settingsKey).first()
+}
diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/running/RunningScreen.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/running/RunningScreen.kt
index f9f829943..d2d2bdff4 100644
--- a/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/running/RunningScreen.kt
+++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/running/RunningScreen.kt
@@ -13,6 +13,8 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
+import androidx.compose.material3.AssistChip
+import androidx.compose.material3.AssistChipDefaults
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -33,6 +35,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import ooniprobe.composeapp.generated.resources.Dashboard_Running_EstimatedTimeLeft
+import ooniprobe.composeapp.generated.resources.Dashboard_Running_ProxyInUse
import ooniprobe.composeapp.generated.resources.Dashboard_Running_Running
import ooniprobe.composeapp.generated.resources.Dashboard_Running_Stopping_Notice
import ooniprobe.composeapp.generated.resources.Dashboard_Running_Stopping_Title
@@ -40,6 +43,7 @@ import ooniprobe.composeapp.generated.resources.Notification_StopTest
import ooniprobe.composeapp.generated.resources.Res
import ooniprobe.composeapp.generated.resources.back
import ooniprobe.composeapp.generated.resources.ooni_empty_state
+import ooniprobe.composeapp.generated.resources.test_circumvention
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
import org.ooni.probe.data.models.TestRunState
@@ -80,7 +84,7 @@ fun RunningScreen(
)
when (state.testRunState) {
- is TestRunState.Running -> TestRunning(state.testRunState, onEvent)
+ is TestRunState.Running -> TestRunning(state.hasProxy, state.testRunState, onEvent)
TestRunState.Stopping -> TestStopping()
else -> Unit
}
@@ -95,6 +99,7 @@ fun RunningScreen(
@Composable
private fun TestRunning(
+ hasProxy: Boolean,
state: TestRunState.Running,
onEvent: (RunningViewModel.Event) -> Unit,
) {
@@ -120,6 +125,32 @@ private fun TestRunning(
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold,
)
+ if (hasProxy) {
+ AssistChip(
+ onClick = { },
+ label = {
+ Text(
+ text = stringResource(Res.string.Dashboard_Running_ProxyInUse),
+ style = MaterialTheme.typography.bodyLarge,
+ )
+ },
+ leadingIcon = {
+ Icon(
+ painter = painterResource(Res.drawable.test_circumvention),
+ contentDescription = null,
+ modifier = Modifier.size(AssistChipDefaults.IconSize),
+ tint = MaterialTheme.customColors.onDescriptor,
+ )
+ },
+ colors = AssistChipDefaults.assistChipColors(
+ labelColor = MaterialTheme.customColors.onDescriptor,
+ ),
+ border = AssistChipDefaults.assistChipBorder(
+ enabled = true,
+ borderColor = MaterialTheme.customColors.onDescriptor,
+ ),
+ )
+ }
}
}
diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/running/RunningViewModel.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/running/RunningViewModel.kt
index fdbd44a57..85e4441ff 100644
--- a/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/running/RunningViewModel.kt
+++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/running/RunningViewModel.kt
@@ -10,9 +10,10 @@ import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
+import org.ooni.probe.data.models.ProxySettings
import org.ooni.probe.data.models.TestRunError
import org.ooni.probe.data.models.TestRunState
-import org.ooni.probe.ui.dashboard.DashboardViewModel.Event
class RunningViewModel(
onBack: () -> Unit,
@@ -20,6 +21,7 @@ class RunningViewModel(
observeTestRunState: Flow,
observeTestRunErrors: Flow,
cancelTestRun: () -> Unit,
+ getProxySettings: suspend () -> ProxySettings,
) : ViewModel() {
private val events = MutableSharedFlow(extraBufferCapacity = 1)
@@ -27,6 +29,10 @@ class RunningViewModel(
val state = _state.asStateFlow()
init {
+ viewModelScope.launch {
+ val proxy = getProxySettings().getProxyString()
+ _state.update { it.copy(hasProxy = proxy.isNotEmpty()) }
+ }
observeTestRunState
.onEach { testRunState ->
if (testRunState is TestRunState.Idle) {
@@ -72,6 +78,7 @@ class RunningViewModel(
data class State(
val testRunState: TestRunState? = null,
val testRunErrors: List = emptyList(),
+ val hasProxy: Boolean = false,
)
sealed interface Event {