summaryrefslogtreecommitdiffhomepage
path: root/android/lib
diff options
context:
space:
mode:
authorJonatan Rhodin <jonatan.rhodin@mullvad.net>2025-05-12 16:11:38 +0200
committerJonatan Rhodin <jonatan.rhodin@mullvad.net>2025-05-13 15:48:32 +0200
commitc0b2a8c0f1c565a0343e91e914accafe1e69f3fc (patch)
tree0c7179607e59043cc564721b5161ca5fff7af7f2 /android/lib
parentce62828a21cb65f2b0d1710b7d92b4e55a518408 (diff)
downloadmullvadvpn-c0b2a8c0f1c565a0343e91e914accafe1e69f3fc.tar.xz
mullvadvpn-c0b2a8c0f1c565a0343e91e914accafe1e69f3fc.zip
Show a specific error if selected port is not in the port range
Diffstat (limited to 'android/lib')
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ErrorStateCause.kt2
-rw-r--r--android/lib/resource/src/main/res/values/strings.xml2
-rw-r--r--android/lib/tv/src/main/kotlin/net/mullvad/mullvadvpn/lib/tv/NotificationBannerTv.kt6
-rw-r--r--android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/AnimatedNotificationBanner.kt2
-rw-r--r--android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/NotificationData.kt54
5 files changed, 59 insertions, 7 deletions
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ErrorStateCause.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ErrorStateCause.kt
index fdb7dd3a1a..cd65a7bc97 100644
--- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ErrorStateCause.kt
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ErrorStateCause.kt
@@ -30,6 +30,8 @@ sealed class ErrorStateCause {
data class OtherAlwaysOnApp(val appName: String) : ErrorStateCause()
data object OtherLegacyAlwaysOnApp : ErrorStateCause()
+
+ data class NoRelaysMatchSelectedPort(val port: Port) : ErrorStateCause()
}
sealed interface AuthFailedError {
diff --git a/android/lib/resource/src/main/res/values/strings.xml b/android/lib/resource/src/main/res/values/strings.xml
index f96fa9668b..e7405020d0 100644
--- a/android/lib/resource/src/main/res/values/strings.xml
+++ b/android/lib/resource/src/main/res/values/strings.xml
@@ -417,4 +417,6 @@
<string name="daita_multihop">%s: Multihop</string>
<string name="vpn_permission_denied_error_no_vpn_settings">VPN permission was denied</string>
<string name="vpn_settings_not_available">VPN Settings not available on device</string>
+ <string name="wireguard_port_is_not_supported">The selected %s port is not supported, please change it under</string>
+ <string name="wireguard_settings">%s settings.</string>
</resources>
diff --git a/android/lib/tv/src/main/kotlin/net/mullvad/mullvadvpn/lib/tv/NotificationBannerTv.kt b/android/lib/tv/src/main/kotlin/net/mullvad/mullvadvpn/lib/tv/NotificationBannerTv.kt
index 97d986c36a..8868938a12 100644
--- a/android/lib/tv/src/main/kotlin/net/mullvad/mullvadvpn/lib/tv/NotificationBannerTv.kt
+++ b/android/lib/tv/src/main/kotlin/net/mullvad/mullvadvpn/lib/tv/NotificationBannerTv.kt
@@ -24,7 +24,9 @@ fun PreviewNotificationBannerTv() {
onClickShowAccount = {},
onClickShowChangelog = {},
onClickDismissChangelog = {},
- ) {}
+ onClickDismissNewDevice = {},
+ onClickShowWireguardPortSettings = {},
+ )
}
}
@@ -38,6 +40,7 @@ fun NotificationBannerTv(
onClickShowChangelog: () -> Unit,
onClickDismissChangelog: () -> Unit,
onClickDismissNewDevice: () -> Unit,
+ onClickShowWireguardPortSettings: () -> Unit,
) {
AnimatedNotificationBanner(
modifier = modifier,
@@ -59,5 +62,6 @@ fun NotificationBannerTv(
onClickShowChangelog = onClickShowChangelog,
onClickDismissChangelog = onClickDismissChangelog,
onClickDismissNewDevice = onClickDismissNewDevice,
+ onClickShowWireguardPortSettings = onClickShowWireguardPortSettings,
)
}
diff --git a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/AnimatedNotificationBanner.kt b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/AnimatedNotificationBanner.kt
index 979f63920a..ba0a936109 100644
--- a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/AnimatedNotificationBanner.kt
+++ b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/AnimatedNotificationBanner.kt
@@ -44,6 +44,7 @@ fun AnimatedNotificationBanner(
onClickShowChangelog: () -> Unit,
onClickDismissChangelog: () -> Unit,
onClickDismissNewDevice: () -> Unit,
+ onClickShowWireguardPortSettings: () -> Unit,
) {
// Fix for animating to invisible state
val previous = rememberPrevious(current = notification, shouldUpdate = { _, _ -> true })
@@ -64,6 +65,7 @@ fun AnimatedNotificationBanner(
onClickShowChangelog,
onClickDismissChangelog,
onClickDismissNewDevice,
+ onClickShowWireguardPortSettings,
),
)
}
diff --git a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/NotificationData.kt b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/NotificationData.kt
index b022ca8c07..c9bfcd887d 100644
--- a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/NotificationData.kt
+++ b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/NotificationData.kt
@@ -9,10 +9,13 @@ import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.LinkAnnotation
+import androidx.compose.ui.text.LinkInteractionListener
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
+import androidx.compose.ui.text.withLink
import androidx.compose.ui.text.withStyle
import androidx.core.text.HtmlCompat
import java.net.InetAddress
@@ -75,6 +78,7 @@ fun InAppNotification.toNotificationData(
onClickShowChangelog: () -> Unit,
onClickDismissChangelog: () -> Unit,
onClickDismissNewDevice: () -> Unit,
+ onClickShowWireguardPortSettings: () -> Unit,
) =
when (this) {
is InAppNotification.NewDevice ->
@@ -113,7 +117,8 @@ fun InAppNotification.toNotificationData(
title = stringResource(id = R.string.blocking_internet),
statusLevel = StatusLevel.Error,
)
- is InAppNotification.TunnelStateError -> errorMessageBannerData(error)
+ is InAppNotification.TunnelStateError ->
+ errorMessageBannerData(error, onClickShowWireguardPortSettings)
is InAppNotification.UnsupportedVersion ->
NotificationData(
title = stringResource(id = R.string.unsupported_version),
@@ -156,10 +161,13 @@ fun InAppNotification.toNotificationData(
}
@Composable
-private fun errorMessageBannerData(error: ErrorState) =
+private fun errorMessageBannerData(
+ error: ErrorState,
+ onClickShowWireguardPortSettings: () -> Unit,
+) =
NotificationData(
title = error.title().formatWithHtml(),
- message = NotificationMessage.Text(error.message().formatWithHtml()),
+ message = NotificationMessage.Text(error.message(onClickShowWireguardPortSettings)),
statusLevel = StatusLevel.Error,
)
@@ -191,11 +199,13 @@ private fun ErrorState.title(): String {
}
@Composable
-private fun ErrorState.message(): String {
+private fun ErrorState.message(onClickShowWireguardPortSettings: () -> Unit): AnnotatedString {
val cause = this.cause
return when {
- isBlocking -> cause.errorMessageId()
- else -> stringResource(R.string.failed_to_block_internet)
+ cause is ErrorStateCause.NoRelaysMatchSelectedPort ->
+ cause.message(onClickShowWireguardPortSettings)
+ isBlocking -> cause.errorMessageId().formatWithHtml()
+ else -> stringResource(R.string.failed_to_block_internet).formatWithHtml()
}
}
@@ -220,6 +230,8 @@ private fun ErrorStateCause.errorMessageId(): String =
R.string.invalid_dns_servers,
addresses.joinToString { address -> address.addressString() },
)
+ is ErrorStateCause.NoRelaysMatchSelectedPort ->
+ stringResource(R.string.wireguard_port_is_not_supported)
}
private fun AuthFailedError.errorMessageId(): Int =
@@ -249,3 +261,33 @@ private fun InetAddress.addressString(): String {
return address
}
+
+@Composable
+private fun ErrorStateCause.NoRelaysMatchSelectedPort.message(
+ onClickShowWireguardPortSettings: () -> Unit
+) = buildAnnotatedString {
+ append(
+ stringResource(R.string.wireguard_port_is_not_supported, stringResource(R.string.wireguard))
+ )
+ append(" ")
+ withStyle(
+ SpanStyle(
+ color = MaterialTheme.colorScheme.onSurface,
+ textDecoration = TextDecoration.Underline,
+ )
+ ) {
+ withLink(
+ LinkAnnotation.Clickable(
+ tag = stringResource(R.string.wireguard),
+ linkInteractionListener =
+ object : LinkInteractionListener {
+ override fun onClick(link: LinkAnnotation) {
+ onClickShowWireguardPortSettings()
+ }
+ },
+ )
+ ) {
+ append(stringResource(R.string.wireguard_settings, stringResource(R.string.wireguard)))
+ }
+ }
+}