summaryrefslogtreecommitdiffhomepage
path: root/android/app/src/main
diff options
context:
space:
mode:
authorJonatan Rhodin <jonatan.rhodin@mullvad.net>2024-08-26 10:35:29 +0200
committerAlbin <albin@mullvad.net>2024-08-26 12:44:32 +0200
commit4cefa1584d102d47110606b9797f78801103f35f (patch)
treeea679771695dc63c0d6b4a6906d90998c2eaabcd /android/app/src/main
parentec2098841f78621b31708ab6427c740f7e42ce5a (diff)
downloadmullvadvpn-4cefa1584d102d47110606b9797f78801103f35f.tar.xz
mullvadvpn-4cefa1584d102d47110606b9797f78801103f35f.zip
Add support for feature indicators for tunnel state
Diffstat (limited to 'android/app/src/main')
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt33
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/ConnectionStatusText.kt53
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/OutOfTimeScreenPreviewParameterProvider.kt29
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewData.kt70
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewParameterProvider.kt26
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt47
6 files changed, 157 insertions, 101 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt
index eda1b86690..dd8eec57d2 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt
@@ -29,16 +29,34 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.Dimension
import net.mullvad.mullvadvpn.R
+import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewParameterProvider
import net.mullvad.mullvadvpn.lib.model.TunnelState
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.lib.theme.Dimens
import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisconnectButton
@Composable
+@Preview
+private fun PreviewConnectionButton(
+ @PreviewParameter(TunnelStatePreviewParameterProvider::class) tunnelState: TunnelState
+) {
+ AppTheme {
+ ConnectionButton(
+ state = tunnelState,
+ disconnectClick = {},
+ reconnectClick = {},
+ cancelClick = {},
+ connectClick = {}
+ )
+ }
+}
+
+@Composable
fun ConnectionButton(
modifier: Modifier = Modifier,
reconnectButtonTestTag: String = "",
@@ -106,21 +124,6 @@ fun ConnectionButton(
)
}
-@Preview
-@Composable
-private fun PreviewConnectionButton() {
- AppTheme {
- ConnectionButton(
- text = "Disconnect",
- mainClick = {},
- containerColor = MaterialTheme.colorScheme.error.copy(alpha = AlphaDisconnectButton),
- contentColor = MaterialTheme.colorScheme.onError,
- reconnectClick = {},
- isReconnectButtonEnabled = true
- )
- }
-}
-
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun ConnectionButton(
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 b4d6b0d60c..0b155953e3 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
@@ -1,66 +1,29 @@
package net.mullvad.mullvadvpn.compose.component
import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Column
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
-import java.net.InetSocketAddress
+import androidx.compose.ui.tooling.preview.PreviewParameter
import net.mullvad.mullvadvpn.R
+import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewParameterProvider
import net.mullvad.mullvadvpn.lib.model.ActionAfterDisconnect
-import net.mullvad.mullvadvpn.lib.model.Endpoint
-import net.mullvad.mullvadvpn.lib.model.ErrorState
-import net.mullvad.mullvadvpn.lib.model.ErrorStateCause
-import net.mullvad.mullvadvpn.lib.model.TransportProtocol
-import net.mullvad.mullvadvpn.lib.model.TunnelEndpoint
import net.mullvad.mullvadvpn.lib.model.TunnelState
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.lib.theme.typeface.connectionStatus
@Preview
@Composable
-private fun PreviewConnectionStatusText() {
+private fun PreviewConnectionStatusText(
+ @PreviewParameter(TunnelStatePreviewParameterProvider::class) tunnelState: TunnelState
+) {
AppTheme {
- SpacedColumn(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) {
- ConnectionStatusText(TunnelState.Disconnected())
- ConnectionStatusText(TunnelState.Connecting(null, null))
- ConnectionStatusText(
- state = TunnelState.Error(ErrorState(ErrorStateCause.Ipv6Unavailable, true))
- )
- ConnectionStatusText(
- state =
- TunnelState.Connected(
- endpoint =
- TunnelEndpoint(
- endpoint =
- Endpoint(
- address = InetSocketAddress(10),
- protocol = TransportProtocol.Tcp
- ),
- quantumResistant = false,
- obfuscation = null
- ),
- location = null
- )
- )
- ConnectionStatusText(
- state =
- TunnelState.Connected(
- endpoint =
- TunnelEndpoint(
- endpoint =
- Endpoint(
- address = InetSocketAddress(10),
- protocol = TransportProtocol.Tcp
- ),
- quantumResistant = true,
- obfuscation = null
- ),
- location = null
- )
- )
+ Column(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) {
+ ConnectionStatusText(state = tunnelState)
}
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/OutOfTimeScreenPreviewParameterProvider.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/OutOfTimeScreenPreviewParameterProvider.kt
new file mode 100644
index 0000000000..efe8ac2fa5
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/OutOfTimeScreenPreviewParameterProvider.kt
@@ -0,0 +1,29 @@
+package net.mullvad.mullvadvpn.compose.preview
+
+import androidx.compose.ui.tooling.preview.PreviewParameterProvider
+import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateConnectingState
+import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateDisconnectedState
+import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateErrorState
+import net.mullvad.mullvadvpn.compose.state.OutOfTimeUiState
+
+class OutOfTimeScreenPreviewParameterProvider : PreviewParameterProvider<OutOfTimeUiState> {
+ override val values: Sequence<OutOfTimeUiState> =
+ sequenceOf(
+ OutOfTimeUiState(
+ tunnelState = generateDisconnectedState(),
+ "Heroic Frog",
+ showSitePayment = true
+ ),
+ OutOfTimeUiState(
+ tunnelState =
+ generateConnectingState(featureIndicators = 0, quantumResistant = false),
+ "Strong Rabbit",
+ showSitePayment = true
+ ),
+ OutOfTimeUiState(
+ tunnelState = generateErrorState(isBlocking = true),
+ deviceName = "Stable Horse",
+ showSitePayment = true
+ )
+ )
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewData.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewData.kt
new file mode 100644
index 0000000000..7045cc45dc
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewData.kt
@@ -0,0 +1,70 @@
+package net.mullvad.mullvadvpn.compose.preview
+
+import java.net.InetSocketAddress
+import net.mullvad.mullvadvpn.lib.model.ActionAfterDisconnect
+import net.mullvad.mullvadvpn.lib.model.Endpoint
+import net.mullvad.mullvadvpn.lib.model.ErrorState
+import net.mullvad.mullvadvpn.lib.model.ErrorStateCause
+import net.mullvad.mullvadvpn.lib.model.FeatureIndicator
+import net.mullvad.mullvadvpn.lib.model.GeoIpLocation
+import net.mullvad.mullvadvpn.lib.model.ObfuscationEndpoint
+import net.mullvad.mullvadvpn.lib.model.ObfuscationType
+import net.mullvad.mullvadvpn.lib.model.TransportProtocol
+import net.mullvad.mullvadvpn.lib.model.TunnelEndpoint
+import net.mullvad.mullvadvpn.lib.model.TunnelState
+
+object TunnelStatePreviewData {
+ fun generateDisconnectedState() = TunnelState.Disconnected()
+
+ fun generateConnectingState(featureIndicators: Int, quantumResistant: Boolean) =
+ TunnelState.Connecting(
+ endpoint = generateTunnelEndpoint(quantumResistant = quantumResistant),
+ location = generateLocation(),
+ featureIndicators = generateFeatureIndicators(featureIndicators)
+ )
+
+ fun generateConnectedState(featureIndicators: Int, quantumResistant: Boolean) =
+ TunnelState.Connected(
+ endpoint = generateTunnelEndpoint(quantumResistant = quantumResistant),
+ location = generateLocation(),
+ featureIndicators = generateFeatureIndicators(featureIndicators)
+ )
+
+ fun generateDisconnectingState(actionAfterDisconnect: ActionAfterDisconnect) =
+ TunnelState.Disconnecting(actionAfterDisconnect = actionAfterDisconnect)
+
+ fun generateErrorState(isBlocking: Boolean) =
+ TunnelState.Error(
+ errorState = ErrorState(cause = ErrorStateCause.DnsError, isBlocking = isBlocking)
+ )
+}
+
+private fun generateTunnelEndpoint(quantumResistant: Boolean): TunnelEndpoint =
+ TunnelEndpoint(
+ endpoint = generateEndpoint(TransportProtocol.Udp),
+ quantumResistant = quantumResistant,
+ obfuscation =
+ ObfuscationEndpoint(
+ endpoint = generateEndpoint(TransportProtocol.Tcp),
+ ObfuscationType.Udp2Tcp
+ )
+ )
+
+private fun generateEndpoint(transportProtocol: TransportProtocol) =
+ Endpoint(address = InetSocketAddress(DEFAULT_ENDPOINT_PORT), protocol = transportProtocol)
+
+private fun generateLocation(): GeoIpLocation =
+ GeoIpLocation(
+ ipv4 = null,
+ ipv6 = null,
+ country = "",
+ city = "",
+ hostname = "",
+ latitude = 0.0,
+ longitude = 0.0,
+ )
+
+private fun generateFeatureIndicators(size: Int): List<FeatureIndicator> =
+ FeatureIndicator.entries.subList(0, size)
+
+private const val DEFAULT_ENDPOINT_PORT = 100
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewParameterProvider.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewParameterProvider.kt
new file mode 100644
index 0000000000..9cd06ef276
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewParameterProvider.kt
@@ -0,0 +1,26 @@
+package net.mullvad.mullvadvpn.compose.preview
+
+import androidx.compose.ui.tooling.preview.PreviewParameterProvider
+import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateConnectedState
+import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateConnectingState
+import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateDisconnectedState
+import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateDisconnectingState
+import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateErrorState
+import net.mullvad.mullvadvpn.lib.model.ActionAfterDisconnect
+import net.mullvad.mullvadvpn.lib.model.TunnelState
+
+class TunnelStatePreviewParameterProvider : PreviewParameterProvider<TunnelState> {
+ override val values: Sequence<TunnelState> =
+ sequenceOf(
+ generateDisconnectedState(),
+ generateConnectingState(featureIndicators = 0, quantumResistant = false),
+ generateConnectingState(featureIndicators = 0, quantumResistant = true),
+ generateConnectedState(featureIndicators = 0, quantumResistant = false),
+ generateConnectedState(featureIndicators = 0, quantumResistant = true),
+ generateDisconnectingState(actionAfterDisconnect = ActionAfterDisconnect.Block),
+ generateDisconnectingState(actionAfterDisconnect = ActionAfterDisconnect.Nothing),
+ generateDisconnectingState(actionAfterDisconnect = ActionAfterDisconnect.Reconnect),
+ generateErrorState(isBlocking = true),
+ generateErrorState(isBlocking = false)
+ )
+}
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 7b5b4bff55..43730ff164 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
@@ -24,6 +24,7 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.compose.dropUnlessResumed
@@ -48,12 +49,12 @@ import net.mullvad.mullvadvpn.compose.component.ScaffoldWithTopBarAndDeviceName
import net.mullvad.mullvadvpn.compose.component.drawVerticalScrollbar
import net.mullvad.mullvadvpn.compose.extensions.createOpenAccountPageHook
import net.mullvad.mullvadvpn.compose.extensions.dropUnlessResumed
+import net.mullvad.mullvadvpn.compose.preview.OutOfTimeScreenPreviewParameterProvider
import net.mullvad.mullvadvpn.compose.state.OutOfTimeUiState
import net.mullvad.mullvadvpn.compose.test.OUT_OF_TIME_SCREEN_TITLE_TEST_TAG
import net.mullvad.mullvadvpn.compose.transitions.HomeTransition
import net.mullvad.mullvadvpn.compose.util.CollectSideEffectWithLifecycle
import net.mullvad.mullvadvpn.compose.util.showSnackbarImmediately
-import net.mullvad.mullvadvpn.lib.model.ErrorState
import net.mullvad.mullvadvpn.lib.model.ErrorStateCause
import net.mullvad.mullvadvpn.lib.model.TunnelState
import net.mullvad.mullvadvpn.lib.payment.model.ProductId
@@ -65,48 +66,12 @@ import org.koin.androidx.compose.koinViewModel
@Preview
@Composable
-private fun PreviewOutOfTimeScreenDisconnected() {
- AppTheme {
- OutOfTimeScreen(
- state =
- OutOfTimeUiState(
- tunnelState = TunnelState.Disconnected(),
- "Heroic Frog",
- showSitePayment = true
- ),
- )
- }
-}
-
-@Preview
-@Composable
-private fun PreviewOutOfTimeScreenConnecting() {
- AppTheme {
- OutOfTimeScreen(
- state =
- OutOfTimeUiState(
- tunnelState = TunnelState.Connecting(null, null),
- "Strong Rabbit",
- showSitePayment = true
- ),
- )
- }
-}
-
-@Preview
-@Composable
-private fun PreviewOutOfTimeScreenError() {
+private fun PreviewOutOfTimeScreen(
+ @PreviewParameter(OutOfTimeScreenPreviewParameterProvider::class) state: OutOfTimeUiState
+) {
AppTheme {
OutOfTimeScreen(
- state =
- OutOfTimeUiState(
- tunnelState =
- TunnelState.Error(
- ErrorState(cause = ErrorStateCause.IsOffline, isBlocking = true)
- ),
- deviceName = "Stable Horse",
- showSitePayment = true
- ),
+ state = state,
)
}
}