diff options
| author | Kalle Lindström <karl.lindstrom@mullvad.net> | 2026-04-22 14:01:21 +0200 |
|---|---|---|
| committer | Kalle Lindström <karl.lindstrom@mullvad.net> | 2026-04-22 14:01:21 +0200 |
| commit | 711f13f71cb83362e7ea2cbd394906509a366637 (patch) | |
| tree | 32439dbcf65ad6aa84a1695f9a982a9e02caf6db | |
| parent | 9fb40393097ba2c2619f6873cedcc479237b4d86 (diff) | |
| parent | 0ef58af29eeed5e29b7a4785eaa600196438e98e (diff) | |
| download | mullvadvpn-711f13f71cb83362e7ea2cbd394906509a366637.tar.xz mullvadvpn-711f13f71cb83362e7ea2cbd394906509a366637.zip | |
Merge branch 'add-split-app-counter-droid-1772'
14 files changed, 80 insertions, 28 deletions
diff --git a/android/lib/feature/apiaccess/impl/build.gradle.kts b/android/lib/feature/apiaccess/impl/build.gradle.kts index 3baa370158..9f59084a47 100644 --- a/android/lib/feature/apiaccess/impl/build.gradle.kts +++ b/android/lib/feature/apiaccess/impl/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { implementation(projects.lib.feature.apiaccess.api) implementation(projects.lib.navigation) implementation(projects.lib.repository) + implementation(projects.lib.ui.util) implementation(libs.koin.compose) implementation(libs.arrow) diff --git a/android/lib/feature/apiaccess/impl/src/main/java/net/mullvad/mullvadvpn/feature/apiaccess/impl/screen/edit/EditApiAccessMethodScreen.kt b/android/lib/feature/apiaccess/impl/src/main/java/net/mullvad/mullvadvpn/feature/apiaccess/impl/screen/edit/EditApiAccessMethodScreen.kt index 59888c0528..1dbec14dd8 100644 --- a/android/lib/feature/apiaccess/impl/src/main/java/net/mullvad/mullvadvpn/feature/apiaccess/impl/screen/edit/EditApiAccessMethodScreen.kt +++ b/android/lib/feature/apiaccess/impl/src/main/java/net/mullvad/mullvadvpn/feature/apiaccess/impl/screen/edit/EditApiAccessMethodScreen.kt @@ -80,6 +80,7 @@ import net.mullvad.mullvadvpn.lib.ui.theme.Dimens import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaInvisible import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaScrollbar import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaVisible +import net.mullvad.mullvadvpn.lib.ui.util.visible import org.koin.androidx.compose.koinViewModel import org.koin.core.parameter.parametersOf @@ -341,10 +342,7 @@ private fun ApiAccessMethodTypeSelection( contentDescription = null, modifier = Modifier.padding(end = Dimens.selectableCellTextMargin) - .alpha( - if (item == formData.apiAccessMethodTypes) AlphaVisible - else AlphaInvisible - ), + .visible(item == formData.apiAccessMethodTypes), ) }, ) @@ -564,7 +562,7 @@ private fun CipherSelection(cipher: Cipher, onCipherChange: (Cipher) -> Unit) { contentDescription = null, modifier = Modifier.padding(end = Dimens.selectableCellTextMargin) - .alpha(if (item == cipher) AlphaVisible else AlphaInvisible), + .visible(item == cipher), ) }, ) @@ -602,7 +600,7 @@ private fun EnableAuthentication( contentDescription = null, modifier = Modifier.padding(end = Dimens.selectableCellTextMargin) - .alpha(if (authenticationEnabled) AlphaVisible else AlphaInvisible), + .visible(authenticationEnabled), ) }, ) @@ -619,9 +617,7 @@ private fun EnableAuthentication( contentDescription = null, modifier = Modifier.padding(end = Dimens.selectableCellTextMargin) - .alpha( - if (authenticationEnabled.not()) AlphaVisible else AlphaInvisible - ), + .alpha(if (authenticationEnabled) AlphaInvisible else AlphaVisible), ) }, ) diff --git a/android/lib/feature/autoconnect/impl/build.gradle.kts b/android/lib/feature/autoconnect/impl/build.gradle.kts index 912bd3b1bd..996b14b8d2 100644 --- a/android/lib/feature/autoconnect/impl/build.gradle.kts +++ b/android/lib/feature/autoconnect/impl/build.gradle.kts @@ -10,6 +10,7 @@ android { namespace = "net.mullvad.mullvadvpn.feature.autoconnect.impl" } dependencies { implementation(projects.lib.feature.autoconnect.api) + implementation(projects.lib.ui.util) implementation(libs.koin.compose) implementation(libs.arrow) diff --git a/android/lib/feature/autoconnect/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/autoconnect/impl/AutoConnectAndLockdownModeScreen.kt b/android/lib/feature/autoconnect/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/autoconnect/impl/AutoConnectAndLockdownModeScreen.kt index a1d0ac8c5b..8c8d4761a5 100644 --- a/android/lib/feature/autoconnect/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/autoconnect/impl/AutoConnectAndLockdownModeScreen.kt +++ b/android/lib/feature/autoconnect/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/autoconnect/impl/AutoConnectAndLockdownModeScreen.kt @@ -36,7 +36,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext @@ -72,9 +71,8 @@ import net.mullvad.mullvadvpn.lib.ui.designsystem.PrimaryButton import net.mullvad.mullvadvpn.lib.ui.resource.R import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme import net.mullvad.mullvadvpn.lib.ui.theme.Dimens -import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaInvisible import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaScrollbar -import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaVisible +import net.mullvad.mullvadvpn.lib.ui.util.visible import org.koin.androidx.compose.koinViewModel @Preview("OSS|Play") @@ -268,7 +266,7 @@ private fun CarouselNavigationButton( imageVector: ImageVector, ) { IconButton( - modifier = modifier.alpha(if (isEnabled.invoke()) AlphaVisible else AlphaInvisible), + modifier = modifier.visible(isEnabled.invoke()), onClick = onClick, enabled = isEnabled.invoke(), ) { diff --git a/android/lib/feature/home/impl/build.gradle.kts b/android/lib/feature/home/impl/build.gradle.kts index 7b27e30b81..be15bee07c 100644 --- a/android/lib/feature/home/impl/build.gradle.kts +++ b/android/lib/feature/home/impl/build.gradle.kts @@ -31,6 +31,7 @@ dependencies { implementation(projects.lib.pushNotification) implementation(projects.lib.repository) implementation(projects.lib.tv) + implementation(projects.lib.ui.util) implementation(projects.lib.usecase) implementation(libs.androidx.animation) diff --git a/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectScreen.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectScreen.kt index 267b7162c9..7364e1f1a9 100644 --- a/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectScreen.kt +++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectScreen.kt @@ -129,10 +129,9 @@ import net.mullvad.mullvadvpn.lib.ui.theme.Dimens import net.mullvad.mullvadvpn.lib.ui.theme.Shapes import net.mullvad.mullvadvpn.lib.ui.theme.color.Alpha20 import net.mullvad.mullvadvpn.lib.ui.theme.color.Alpha80 -import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaInvisible import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaScrollbar -import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaVisible import net.mullvad.mullvadvpn.lib.ui.theme.color.positive +import net.mullvad.mullvadvpn.lib.ui.util.visible import org.koin.androidx.compose.koinViewModel private const val CONNECT_BUTTON_THROTTLE_MILLIS = 1000 @@ -444,7 +443,7 @@ private fun Content( ) } } - .alpha(if (state.showLoading) AlphaVisible else AlphaInvisible), + .visible(state.showLoading), ) Box( diff --git a/android/lib/feature/splittunneling/impl/build.gradle.kts b/android/lib/feature/splittunneling/impl/build.gradle.kts index 66f2072c5f..2fd10ce3f9 100644 --- a/android/lib/feature/splittunneling/impl/build.gradle.kts +++ b/android/lib/feature/splittunneling/impl/build.gradle.kts @@ -14,4 +14,5 @@ dependencies { implementation(libs.koin.compose) implementation(libs.arrow) implementation(projects.lib.feature.splittunneling.api) + implementation(projects.lib.ui.util) } diff --git a/android/lib/feature/splittunneling/impl/src/main/java/net/mullvad/mullvadvpn/feature/splittunneling/impl/SplitTunnelingScreen.kt b/android/lib/feature/splittunneling/impl/src/main/java/net/mullvad/mullvadvpn/feature/splittunneling/impl/SplitTunnelingScreen.kt index 1f992f6069..e9b81aa249 100644 --- a/android/lib/feature/splittunneling/impl/src/main/java/net/mullvad/mullvadvpn/feature/splittunneling/impl/SplitTunnelingScreen.kt +++ b/android/lib/feature/splittunneling/impl/src/main/java/net/mullvad/mullvadvpn/feature/splittunneling/impl/SplitTunnelingScreen.kt @@ -64,6 +64,7 @@ import net.mullvad.mullvadvpn.lib.ui.theme.Dimens import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaDisabled import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaScrollbar import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaVisible +import net.mullvad.mullvadvpn.lib.ui.util.visible import org.koin.androidx.compose.koinViewModel import org.koin.core.parameter.parametersOf @@ -225,10 +226,12 @@ private fun LazyListScope.appList( onResolveIcon: (PackageName) -> Drawable?, ) { if (state.excludedApps.isNotEmpty()) { - headerItem( + excludedAppsHeaderItem( key = SplitTunnelingContentKey.EXCLUDED_APPLICATIONS, textId = R.string.exclude_applications, enabled = state.enabled, + exludedAppsCount = state.excludedApps.size, + includedAppsCount = state.includedApps.size, ) appItems( apps = state.excludedApps, @@ -320,16 +323,29 @@ internal fun LazyListScope.appItems( internal fun LazyListScope.headerItem(key: String, textId: Int, enabled: Boolean) { itemWithDivider(key = key, contentType = ContentType.HEADER) { ListHeader( - modifier = - Modifier.animateItem() - .alpha( - if (enabled) { - AlphaVisible - } else { - AlphaDisabled - } - ), + modifier = Modifier.animateItem().visible(enabled), + text = stringResource(id = textId), + ) + } +} + +internal fun LazyListScope.excludedAppsHeaderItem( + key: String, + textId: Int, + enabled: Boolean, + exludedAppsCount: Int, + includedAppsCount: Int, +) { + itemWithDivider(key = key, contentType = ContentType.HEADER) { + ListHeader( + modifier = Modifier.animateItem().visible(enabled), text = stringResource(id = textId), + trailingText = + stringResource( + R.string.x_out_of_y, + exludedAppsCount, + exludedAppsCount + includedAppsCount, + ), ) } } diff --git a/android/lib/feature/splittunneling/impl/src/main/java/net/mullvad/mullvadvpn/feature/splittunneling/impl/search/SearchSplitTunnelingScreen.kt b/android/lib/feature/splittunneling/impl/src/main/java/net/mullvad/mullvadvpn/feature/splittunneling/impl/search/SearchSplitTunnelingScreen.kt index 494757f35f..4ef0597de4 100644 --- a/android/lib/feature/splittunneling/impl/src/main/java/net/mullvad/mullvadvpn/feature/splittunneling/impl/search/SearchSplitTunnelingScreen.kt +++ b/android/lib/feature/splittunneling/impl/src/main/java/net/mullvad/mullvadvpn/feature/splittunneling/impl/search/SearchSplitTunnelingScreen.kt @@ -40,6 +40,7 @@ import net.mullvad.mullvadvpn.feature.splittunneling.impl.CommonContentKey import net.mullvad.mullvadvpn.feature.splittunneling.impl.ContentType import net.mullvad.mullvadvpn.feature.splittunneling.impl.SplitTunnelingContentKey import net.mullvad.mullvadvpn.feature.splittunneling.impl.appItems +import net.mullvad.mullvadvpn.feature.splittunneling.impl.excludedAppsHeaderItem import net.mullvad.mullvadvpn.feature.splittunneling.impl.getApplicationIconOrNull import net.mullvad.mullvadvpn.feature.splittunneling.impl.headerItem import net.mullvad.mullvadvpn.lib.common.Lc @@ -158,10 +159,12 @@ private fun LazyListScope.appList( item { NoAppsMatchingSearch(state.searchTerm) } } if (state.excludedApps.isNotEmpty()) { - headerItem( + excludedAppsHeaderItem( key = SplitTunnelingContentKey.EXCLUDED_APPLICATIONS, textId = R.string.exclude_applications, enabled = true, + exludedAppsCount = state.excludedApps.size, + includedAppsCount = state.includedApps.size, ) appItems( apps = state.excludedApps, diff --git a/android/lib/ui/designsystem/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/designsystem/ListHeader.kt b/android/lib/ui/designsystem/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/designsystem/ListHeader.kt index 9f25242965..c36ff60227 100644 --- a/android/lib/ui/designsystem/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/designsystem/ListHeader.kt +++ b/android/lib/ui/designsystem/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/designsystem/ListHeader.kt @@ -3,9 +3,11 @@ package net.mullvad.mullvadvpn.lib.ui.designsystem import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Edit import androidx.compose.material3.HorizontalDivider @@ -29,6 +31,22 @@ fun ListHeader(text: String, modifier: Modifier = Modifier) { } @Composable +fun ListHeader(modifier: Modifier = Modifier, text: String, trailingText: String) { + ListHeader( + modifier = modifier, + content = { Text(text = text) }, + actions = { + Spacer(Modifier.width(Dimens.smallSpacer)) + Text( + text = trailingText, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + }, + ) +} + +@Composable fun ListHeader( content: @Composable () -> Unit, modifier: Modifier = Modifier, @@ -75,4 +93,5 @@ fun PreviewListHeader() = } }, ) + ListHeader(text = "Header", trailingText = "3 out of 200") } diff --git a/android/lib/ui/resource/src/main/res/values/strings.xml b/android/lib/ui/resource/src/main/res/values/strings.xml index 4d92f6c27b..ccafabfc04 100644 --- a/android/lib/ui/resource/src/main/res/values/strings.xml +++ b/android/lib/ui/resource/src/main/res/values/strings.xml @@ -1,4 +1,4 @@ -<resources> +<resources xmlns:tools="http://schemas.android.com/tools"> <string name="disconnecting">Disconnecting...</string> <string name="blocking">Blocking...</string> <string name="critical_error">Critical error (your attention is required)</string> @@ -132,6 +132,7 @@ <string name="custom_dns_footer">Enable to add at least one DNS server.</string> <string name="confirm_local_dns">The local DNS server will not work unless you enable \"Local Network Sharing\" under VPN settings.</string> <string name="exclude_applications">Excluded applications</string> + <string name="x_out_of_y" tools:ignore="PluralsCandidate">%1$d out of %2$d</string> <string name="all_applications">All applications</string> <string name="show_system_apps">Show system apps</string> <string name="toggle_vpn">Toggle VPN</string> diff --git a/android/lib/ui/util/build.gradle.kts b/android/lib/ui/util/build.gradle.kts index ede0822b03..48fa3b2ac9 100644 --- a/android/lib/ui/util/build.gradle.kts +++ b/android/lib/ui/util/build.gradle.kts @@ -14,4 +14,6 @@ dependencies { implementation(libs.compose.ui.tooling.preview) implementation(libs.compose.material3) implementation(libs.compose.icons.extended) + + implementation(projects.lib.ui.theme) } diff --git a/android/lib/ui/util/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/util/Modifier.kt b/android/lib/ui/util/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/util/Modifier.kt index e659e68731..2cff4ff545 100644 --- a/android/lib/ui/util/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/util/Modifier.kt +++ b/android/lib/ui/util/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/util/Modifier.kt @@ -2,6 +2,9 @@ package net.mullvad.mullvadvpn.lib.ui.util import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaInvisible +import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaVisible @Composable fun <T> Modifier.applyIfNotNull( @@ -22,3 +25,11 @@ fun Modifier.applyIf(condition: Boolean, block: @Composable Modifier.() -> Modif } else { this } + +@Composable +fun Modifier.visible(visible: Boolean): Modifier = + if (visible) { + alpha(AlphaVisible) + } else { + alpha(AlphaInvisible) + } diff --git a/desktop/packages/mullvad-vpn/locales/messages.pot b/desktop/packages/mullvad-vpn/locales/messages.pot index 8aa1a9d7ac..10e106b64d 100644 --- a/desktop/packages/mullvad-vpn/locales/messages.pot +++ b/desktop/packages/mullvad-vpn/locales/messages.pot @@ -2930,6 +2930,9 @@ msgctxt "wireguard-settings-view" msgid "Which TCP port the UDP-over-TCP obfuscation protocol should connect to on the VPN server." msgstr "" +msgid "%1$d out of %2$d" +msgstr "" + msgid "%1$s more..." msgstr "" |
