Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for feature indicators for tunnel state #6677

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.RegisterExtension

@Suppress("LargeClass")
class ConnectScreenTest {
@OptIn(ExperimentalTestApi::class)
@JvmField
Expand Down Expand Up @@ -78,7 +79,7 @@ class ConnectScreenTest {
ConnectUiState(
location = null,
selectedRelayItemTitle = null,
tunnelState = TunnelState.Connecting(null, null),
tunnelState = TunnelState.Connecting(null, null, emptyList()),
inAddress = null,
outAddress = "",
showLocation = false,
Expand Down Expand Up @@ -112,7 +113,11 @@ class ConnectScreenTest {
location = null,
selectedRelayItemTitle = null,
tunnelState =
TunnelState.Connecting(endpoint = mockTunnelEndpoint, null),
TunnelState.Connecting(
endpoint = mockTunnelEndpoint,
null,
emptyList()
),
inAddress = null,
outAddress = "",
showLocation = false,
Expand Down Expand Up @@ -144,7 +149,8 @@ class ConnectScreenTest {
ConnectUiState(
location = null,
selectedRelayItemTitle = null,
tunnelState = TunnelState.Connected(mockTunnelEndpoint, null),
tunnelState =
TunnelState.Connected(mockTunnelEndpoint, null, emptyList()),
inAddress = null,
outAddress = "",
showLocation = false,
Expand Down Expand Up @@ -175,7 +181,8 @@ class ConnectScreenTest {
ConnectUiState(
location = null,
selectedRelayItemTitle = null,
tunnelState = TunnelState.Connected(mockTunnelEndpoint, null),
tunnelState =
TunnelState.Connected(mockTunnelEndpoint, null, emptyList()),
inAddress = null,
outAddress = "",
showLocation = false,
Expand Down Expand Up @@ -437,7 +444,8 @@ class ConnectScreenTest {
ConnectUiState(
location = null,
selectedRelayItemTitle = null,
tunnelState = TunnelState.Connected(mockTunnelEndpoint, null),
tunnelState =
TunnelState.Connected(mockTunnelEndpoint, null, emptyList()),
inAddress = null,
outAddress = "",
showLocation = false,
Expand Down Expand Up @@ -470,7 +478,8 @@ class ConnectScreenTest {
ConnectUiState(
location = null,
selectedRelayItemTitle = null,
tunnelState = TunnelState.Connected(mockTunnelEndpoint, null),
tunnelState =
TunnelState.Connected(mockTunnelEndpoint, null, emptyList()),
inAddress = null,
outAddress = "",
showLocation = false,
Expand Down Expand Up @@ -534,7 +543,7 @@ class ConnectScreenTest {
ConnectUiState(
location = null,
selectedRelayItemTitle = null,
tunnelState = TunnelState.Connecting(null, null),
tunnelState = TunnelState.Connecting(null, null, emptyList()),
inAddress = null,
outAddress = "",
showLocation = false,
Expand Down Expand Up @@ -574,7 +583,8 @@ class ConnectScreenTest {
ConnectUiState(
location = mockLocation,
selectedRelayItemTitle = null,
tunnelState = TunnelState.Connected(mockTunnelEndpoint, null),
tunnelState =
TunnelState.Connected(mockTunnelEndpoint, null, emptyList()),
inAddress = mockInAddress,
outAddress = mockOutAddress,
showLocation = false,
Expand Down Expand Up @@ -608,7 +618,7 @@ class ConnectScreenTest {
ConnectUiState(
location = null,
selectedRelayItemTitle = null,
tunnelState = TunnelState.Connecting(null, null),
tunnelState = TunnelState.Connecting(null, null, emptyList()),
inAddress = null,
outAddress = "",
showLocation = false,
Expand Down Expand Up @@ -640,7 +650,7 @@ class ConnectScreenTest {
ConnectUiState(
location = null,
selectedRelayItemTitle = null,
tunnelState = TunnelState.Connecting(null, null),
tunnelState = TunnelState.Connecting(null, null, emptyList()),
inAddress = null,
outAddress = "",
showLocation = false,
Expand Down Expand Up @@ -671,7 +681,7 @@ class ConnectScreenTest {
ConnectUiState(
location = null,
selectedRelayItemTitle = null,
tunnelState = TunnelState.Connecting(null, null),
tunnelState = TunnelState.Connecting(null, null, emptyList()),
inAddress = null,
outAddress = "",
showLocation = false,
Expand Down Expand Up @@ -704,7 +714,7 @@ class ConnectScreenTest {
ConnectUiState(
location = null,
selectedRelayItemTitle = null,
tunnelState = TunnelState.Connecting(null, null),
tunnelState = TunnelState.Connecting(null, null, emptyList()),
inAddress = null,
outAddress = "",
showLocation = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class OutOfTimeScreenTest {
OutOfTimeScreen(
state =
OutOfTimeUiState(
tunnelState = TunnelState.Connecting(null, null),
tunnelState = TunnelState.Connecting(null, null, emptyList()),
deviceName = "",
showSitePayment = true
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,33 @@ 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,
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
)
)
}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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)
)
}
Loading
Loading