summaryrefslogtreecommitdiffhomepage
path: root/android/app/src/main
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson90@gmail.com>2023-12-18 12:12:17 +0100
committerJonathan <jonathan@mullvad.net>2023-12-21 13:33:59 +0100
commit8ed53a012b6c510a0dfd92925b8b0e742fd79da3 (patch)
treec92a6f524fa9f659a0edb2bb702e466d051ddba2 /android/app/src/main
parentc70509a345b6db8caf12c880b3ee3bf4c70bf79d (diff)
downloadmullvadvpn-8ed53a012b6c510a0dfd92925b8b0e742fd79da3.tar.xz
mullvadvpn-8ed53a012b6c510a0dfd92925b8b0e742fd79da3.zip
Support new tunnel state API in the Android frontend.
Remove `get_current_location` from jni.
Diffstat (limited to 'android/app/src/main')
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/ConnectionStatusText.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt11
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ConnectUiState.kt6
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/OutOfTimeUiState.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/WelcomeUiState.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxy.kt4
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/LocationInfoCache.kt26
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCase.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModel.kt44
11 files changed, 35 insertions, 68 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/ConnectionStatusText.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/ConnectionStatusText.kt
index 742302ce91..903bb412dc 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/ConnectionStatusText.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/ConnectionStatusText.kt
@@ -18,7 +18,7 @@ import net.mullvad.talpid.tunnel.ErrorStateCause
private fun PreviewConnectionStatusText() {
AppTheme {
SpacedColumn {
- ConnectionStatusText(TunnelState.Disconnected)
+ ConnectionStatusText(TunnelState.Disconnected())
ConnectionStatusText(TunnelState.Connecting(null, null))
ConnectionStatusText(
state = TunnelState.Error(ErrorState(ErrorStateCause.Ipv6Unavailable, true))
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt
index b1de1ad809..646e89c987 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt
@@ -19,7 +19,9 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableLongStateOf
+import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -108,7 +110,6 @@ fun Connect(navigator: DestinationsNavigator) {
onSwitchLocationClick = {
navigator.navigate(SelectLocationDestination) { launchSingleTop = true }
},
- onToggleTunnelInfo = connectViewModel::toggleTunnelInfoExpansion,
onUpdateVersionClick = {
val intent =
Intent(
@@ -137,7 +138,6 @@ fun ConnectScreen(
onConnectClick: () -> Unit = {},
onCancelClick: () -> Unit = {},
onSwitchLocationClick: () -> Unit = {},
- onToggleTunnelInfo: () -> Unit = {},
onUpdateVersionClick: () -> Unit = {},
onManageAccountClick: () -> Unit = {},
onSettingsClick: () -> Unit = {},
@@ -233,12 +233,13 @@ fun ConnectScreen(
color = MaterialTheme.colorScheme.onPrimary,
modifier = Modifier.padding(horizontal = Dimens.sideMargin)
)
+ var expanded by rememberSaveable { mutableStateOf(false) }
LocationInfo(
- onToggleTunnelInfo = onToggleTunnelInfo,
+ onToggleTunnelInfo = { expanded = !expanded },
isVisible =
- uiState.tunnelRealState != TunnelState.Disconnected &&
+ uiState.tunnelRealState !is TunnelState.Disconnected &&
uiState.location?.hostname != null,
- isExpanded = uiState.isTunnelInfoExpanded,
+ isExpanded = expanded,
location = uiState.location,
inAddress = uiState.inAddress,
outAddress = uiState.outAddress,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt
index d9071be7d8..d0d0c7460d 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt
@@ -62,7 +62,7 @@ private fun PreviewOutOfTimeScreenDisconnected() {
OutOfTimeScreen(
uiState =
OutOfTimeUiState(
- tunnelState = TunnelState.Disconnected,
+ tunnelState = TunnelState.Disconnected(),
"Heroic Frog",
showSitePayment = true
),
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ConnectUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ConnectUiState.kt
index 54c1a0d7c0..dc26e24741 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ConnectUiState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ConnectUiState.kt
@@ -15,7 +15,6 @@ data class ConnectUiState(
val outAddress: String,
val showLocation: Boolean,
val inAppNotification: InAppNotification?,
- val isTunnelInfoExpanded: Boolean,
val deviceName: String?,
val daysLeftUntilExpiry: Int?,
val isPlayBuild: Boolean
@@ -25,12 +24,11 @@ data class ConnectUiState(
ConnectUiState(
location = null,
relayLocation = null,
- tunnelUiState = TunnelState.Disconnected,
- tunnelRealState = TunnelState.Disconnected,
+ tunnelUiState = TunnelState.Disconnected(),
+ tunnelRealState = TunnelState.Disconnected(),
inAddress = null,
outAddress = "",
showLocation = false,
- isTunnelInfoExpanded = false,
inAppNotification = null,
deviceName = null,
daysLeftUntilExpiry = null,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/OutOfTimeUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/OutOfTimeUiState.kt
index 54fd414f86..d72e015194 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/OutOfTimeUiState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/OutOfTimeUiState.kt
@@ -3,7 +3,7 @@ package net.mullvad.mullvadvpn.compose.state
import net.mullvad.mullvadvpn.model.TunnelState
data class OutOfTimeUiState(
- val tunnelState: TunnelState = TunnelState.Disconnected,
+ val tunnelState: TunnelState = TunnelState.Disconnected(),
val deviceName: String = "",
val showSitePayment: Boolean = false,
val billingPaymentState: PaymentState? = null,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/WelcomeUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/WelcomeUiState.kt
index e2673a0ddf..e43cf6bb98 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/WelcomeUiState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/WelcomeUiState.kt
@@ -3,7 +3,7 @@ package net.mullvad.mullvadvpn.compose.state
import net.mullvad.mullvadvpn.model.TunnelState
data class WelcomeUiState(
- val tunnelState: TunnelState = TunnelState.Disconnected,
+ val tunnelState: TunnelState = TunnelState.Disconnected(),
val accountNumber: String? = null,
val deviceName: String? = null,
val showSitePayment: Boolean = false,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxy.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxy.kt
index d51bad461d..bbc267b2fa 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxy.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxy.kt
@@ -19,8 +19,8 @@ const val ANTICIPATED_STATE_TIMEOUT_MS = 1500L
class ConnectionProxy(private val connection: Messenger, eventDispatcher: EventDispatcher) {
private var resetAnticipatedStateJob: Job? = null
- val onStateChange = EventNotifier<TunnelState>(TunnelState.Disconnected)
- val onUiStateChange = EventNotifier<TunnelState>(TunnelState.Disconnected)
+ val onStateChange = EventNotifier<TunnelState>(TunnelState.Disconnected())
+ val onUiStateChange = EventNotifier<TunnelState>(TunnelState.Disconnected())
var state by onStateChange.notifiable()
private set
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/LocationInfoCache.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/LocationInfoCache.kt
deleted file mode 100644
index 48f77d397d..0000000000
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/LocationInfoCache.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-package net.mullvad.mullvadvpn.ui.serviceconnection
-
-import kotlin.properties.Delegates.observable
-import net.mullvad.mullvadvpn.lib.ipc.Event
-import net.mullvad.mullvadvpn.lib.ipc.EventDispatcher
-import net.mullvad.mullvadvpn.model.GeoIpLocation
-
-class LocationInfoCache(eventDispatcher: EventDispatcher) {
- private var location: GeoIpLocation? by
- observable(null) { _, _, newLocation -> onNewLocation?.invoke(newLocation) }
-
- var onNewLocation by
- observable<((GeoIpLocation?) -> Unit)?>(null) { _, _, callback ->
- callback?.invoke(location)
- }
-
- init {
- eventDispatcher.registerHandler(Event.NewLocation::class) { event ->
- location = event.location
- }
- }
-
- fun onDestroy() {
- onNewLocation = null
- }
-}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt
index ca156bed66..8aabe6c9f5 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt
@@ -28,7 +28,6 @@ class ServiceConnectionContainer(
val authTokenCache = AuthTokenCache(connection, dispatcher)
val connectionProxy = ConnectionProxy(connection, dispatcher)
val deviceDataSource = ServiceConnectionDeviceDataSource(connection, dispatcher)
- val locationInfoCache = LocationInfoCache(dispatcher)
val settingsListener = SettingsListener(connection, dispatcher)
val splitTunneling = SplitTunneling(connection, dispatcher)
@@ -62,7 +61,6 @@ class ServiceConnectionContainer(
authTokenCache.onDestroy()
connectionProxy.onDestroy()
- locationInfoCache.onDestroy()
settingsListener.onDestroy()
voucherRedeemer.onDestroy()
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCase.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCase.kt
index f228bd7dbe..dec794c86c 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCase.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCase.kt
@@ -39,7 +39,7 @@ class TunnelStateNotificationUseCase(
}
is TunnelState.Error -> InAppNotification.TunnelStateError(tunnelUiState.errorState)
is TunnelState.Connected,
- TunnelState.Disconnected -> null
+ is TunnelState.Disconnected -> null
}
private fun ConnectionProxy.tunnelUiStateFlow(): Flow<TunnelState> =
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModel.kt
index 3066006083..d25f360b51 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModel.kt
@@ -5,30 +5,30 @@ import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.compose.state.ConnectUiState
+import net.mullvad.mullvadvpn.model.GeoIpLocation
import net.mullvad.mullvadvpn.model.TunnelState
import net.mullvad.mullvadvpn.repository.AccountRepository
import net.mullvad.mullvadvpn.repository.DeviceRepository
import net.mullvad.mullvadvpn.repository.InAppNotificationController
import net.mullvad.mullvadvpn.ui.serviceconnection.ConnectionProxy
-import net.mullvad.mullvadvpn.ui.serviceconnection.LocationInfoCache
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionContainer
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
@@ -71,48 +71,46 @@ class ConnectViewModel(
}
.shareIn(viewModelScope, SharingStarted.WhileSubscribed())
- private val _isTunnelInfoExpanded = MutableStateFlow(false)
-
val uiState: StateFlow<ConnectUiState> =
_shared
.flatMapLatest { serviceConnection ->
combine(
- serviceConnection.locationInfoCache.locationCallbackFlow(),
relayListUseCase.selectedRelayItem(),
inAppNotificationController.notifications,
serviceConnection.connectionProxy.tunnelUiStateFlow(),
serviceConnection.connectionProxy.tunnelRealStateFlow(),
+ serviceConnection.connectionProxy.lastKnownDisconnectedLocation(),
accountRepository.accountExpiryState,
- _isTunnelInfoExpanded,
deviceRepository.deviceState.map { it.deviceName() }
) {
- location,
relayLocation,
notifications,
tunnelUiState,
tunnelRealState,
+ lastKnownDisconnectedLocation,
accountExpiry,
- isTunnelInfoExpanded,
deviceName ->
ConnectUiState(
location =
when (tunnelRealState) {
- is TunnelState.Connected -> tunnelRealState.location
+ is TunnelState.Disconnected -> tunnelRealState.location()
+ ?: lastKnownDisconnectedLocation
is TunnelState.Connecting -> tunnelRealState.location
- else -> null
- }
- ?: location,
+ ?: relayLocation?.location?.location
+ is TunnelState.Connected -> tunnelRealState.location
+ is TunnelState.Disconnecting -> lastKnownDisconnectedLocation
+ is TunnelState.Error -> null
+ },
relayLocation = relayLocation,
tunnelUiState = tunnelUiState,
tunnelRealState = tunnelRealState,
- isTunnelInfoExpanded = isTunnelInfoExpanded,
inAddress =
when (tunnelRealState) {
is TunnelState.Connected -> tunnelRealState.endpoint.toInAddress()
is TunnelState.Connecting -> tunnelRealState.endpoint?.toInAddress()
else -> null
},
- outAddress = location?.toOutAddress() ?: "",
+ outAddress = tunnelRealState.location()?.toOutAddress() ?: "",
showLocation =
when (tunnelUiState) {
is TunnelState.Disconnected -> true
@@ -149,20 +147,18 @@ class ConnectViewModel(
}
}
- private fun LocationInfoCache.locationCallbackFlow() = callbackFlow {
- onNewLocation = { this.trySend(it) }
- awaitClose { onNewLocation = null }
- }
-
private fun ConnectionProxy.tunnelUiStateFlow(): Flow<TunnelState> =
callbackFlowFromNotifier(this.onUiStateChange)
private fun ConnectionProxy.tunnelRealStateFlow(): Flow<TunnelState> =
callbackFlowFromNotifier(this.onStateChange)
- fun toggleTunnelInfoExpansion() {
- _isTunnelInfoExpanded.value = _isTunnelInfoExpanded.value.not()
- }
+ private fun ConnectionProxy.lastKnownDisconnectedLocation(): Flow<GeoIpLocation?> =
+ tunnelRealStateFlow()
+ .filterIsInstance<TunnelState.Disconnected>()
+ .filter { it.location != null }
+ .map { it.location }
+ .onStart { emit(null) }
fun onDisconnectClick() {
serviceConnectionManager.connectionProxy()?.disconnect()