diff options
| author | David Göransson <david.goransson@mullvad.net> | 2025-05-07 09:30:47 +0200 |
|---|---|---|
| committer | David Göransson <david.goransson@mullvad.net> | 2025-05-07 09:30:47 +0200 |
| commit | 95bb5d4a6ecc83fb9a968fff941812231128d14f (patch) | |
| tree | 1dab3727a500e36f213635c56f2c39bcb29000b7 /android/app | |
| parent | f7aefa938f8047e8e59fd98ee0175545d585c822 (diff) | |
| parent | 7fb0b567faaff21c60009107a44840438ed67644 (diff) | |
| download | mullvadvpn-95bb5d4a6ecc83fb9a968fff941812231128d14f.tar.xz mullvadvpn-95bb5d4a6ecc83fb9a968fff941812231128d14f.zip | |
Merge branch 'update-compose-to-180-droid-1969'
Diffstat (limited to 'android/app')
5 files changed, 66 insertions, 54 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/ConnectionDetailPanel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/ConnectionDetailPanel.kt index c0a005ef40..08eec406bf 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/ConnectionDetailPanel.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/ConnectionDetailPanel.kt @@ -24,7 +24,10 @@ import net.mullvad.mullvadvpn.lib.ui.tag.LOCATION_INFO_CONNECTION_IN_TEST_TAG import net.mullvad.mullvadvpn.lib.ui.tag.LOCATION_INFO_CONNECTION_OUT_TEST_TAG @Composable -fun ConnectionDetailPanel(connectionDetails: ConnectionDetails) { +fun ConnectionDetailPanel( + connectionDetails: ConnectionDetails, + enableSelectableText: Boolean = true, +) { ConnectionInfoHeader( stringResource(R.string.connect_panel_connection_details), @@ -37,6 +40,7 @@ fun ConnectionDetailPanel(connectionDetails: ConnectionDetails) { it.outIpv4Address, it.outIpv6Address, modifier = Modifier.padding(bottom = Dimens.smallPadding), + enableSelectableText = enableSelectableText, ) } } @@ -48,6 +52,7 @@ fun ConnectionDetails( outIPV4: String?, outIPV6: String?, modifier: Modifier = Modifier, + enableSelectableText: Boolean = true, ) { ConstraintLayout(modifier = modifier.fillMaxWidth()) { val (inAddrHeader, inAddr, outAddrV4Header, outAddrV4, outAddrV6Header, outAddrV6) = @@ -131,15 +136,21 @@ fun ConnectionDetails( width = Dimension.fillToConstraints } ) { - SelectionContainer { - Text( - modifier = Modifier.testTag(LOCATION_INFO_CONNECTION_OUT_TEST_TAG), - text = outIPV4, - color = MaterialTheme.colorScheme.onPrimary, - style = MaterialTheme.typography.bodySmall, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) + val outIpV4Text = + @Composable { + Text( + modifier = Modifier.testTag(LOCATION_INFO_CONNECTION_OUT_TEST_TAG), + text = outIPV4, + color = MaterialTheme.colorScheme.onPrimary, + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + if (enableSelectableText) { + SelectionContainer(content = outIpV4Text) + } else { + outIpV4Text() } } } @@ -176,14 +187,20 @@ fun ConnectionDetails( width = Dimension.fillToConstraints } ) { - SelectionContainer { - Text( - text = outIPV6, - color = MaterialTheme.colorScheme.onPrimary, - style = MaterialTheme.typography.bodySmall, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) + val outIpV6Text = + @Composable { + Text( + text = outIPV6, + color = MaterialTheme.colorScheme.onPrimary, + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + if (enableSelectableText) { + SelectionContainer(content = outIpV6Text) + } else { + outIpV6Text() } } } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/FeatureIndicatorsPanel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/FeatureIndicatorsPanel.kt index afd13a7382..a485dbe9d9 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/FeatureIndicatorsPanel.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/FeatureIndicatorsPanel.kt @@ -1,4 +1,5 @@ @file:OptIn(ExperimentalSharedTransitionApi::class) +@file:Suppress("DEPRECATION") package net.mullvad.mullvadvpn.compose.component.connectioninfo 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 45e9bdee52..94db024b41 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 @@ -33,6 +33,7 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableLongStateOf import androidx.compose.runtime.mutableStateOf @@ -43,16 +44,14 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha -import androidx.compose.ui.focus.FocusDirection import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusProperties import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.layout -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.platform.LocalWindowInfo import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow @@ -352,26 +351,12 @@ fun ConnectScreen( if (isTv()) { Scaffold( - modifier = - Modifier.focusProperties { - enter = { focusDirection -> - // When we return to this screen from SelectLocationScreen the focus is - // sometimes put on the TV navigation drawer, which causes it expand - // (when it was previously not expanded). When returning from - // SelectLocationScreen we get a FocusDirection.Down event, so we focus - // on the switch location composable. - // When on TV and we return from account or settings we get a - // FocusDirection.Enter event, so focus remains on the navigation drawer. - if (focusDirection == FocusDirection.Down) contentFocusRequester - else FocusRequester.Default - } - }, snackbarHost = { SnackbarHost( snackbarHostState, snackbar = { snackbarData -> MullvadSnackbar(snackbarData = snackbarData) }, ) - }, + } ) { NavigationDrawerTv( daysLeftUntilExpiry = state.daysLeftUntilExpiry, @@ -382,6 +367,7 @@ fun ConnectScreen( content(it) } } + LaunchedEffect(Unit) { contentFocusRequester.requestFocus() } } else { ScaffoldWithTopBarAndDeviceName( topBarColor = state.tunnelState.topBarColor(), @@ -414,8 +400,7 @@ private fun Content( onDismissNewDeviceClick: () -> Unit, onNavigateToFeature: (FeatureIndicator) -> Unit, ) { - val configuration = LocalConfiguration.current - val screenHeight = configuration.screenHeightDp.dp + val screenHeight = LocalWindowInfo.current.containerSize.height.dp val indicatorPercentOffset = if (screenHeight < SCREEN_HEIGHT_THRESHOLD) SHORT_SCREEN_INDICATOR_BIAS else TALL_SCREEN_INDICATOR_BIAS @@ -666,7 +651,7 @@ private fun ConnectionInfo( FeatureIndicatorsPanel(featureIndicators, expanded, onToggleExpand, onNavigateToFeature) if (expanded && connectionDetails != null) { - ConnectionDetailPanel(connectionDetails) + ConnectionDetailPanel(connectionDetails, enableSelectableText = !isTv()) } } } @@ -689,7 +674,7 @@ fun TunnelState.Connected.toConnectionsDetails(): ConnectionDetails = @Composable private fun ButtonPanel( state: ConnectUiState, - focusRequester: FocusRequester, + selectButtonFocusRequester: FocusRequester, onSwitchLocationClick: () -> Unit, onDisconnectClick: () -> Unit, onReconnectClick: () -> Unit, @@ -714,12 +699,18 @@ private fun ButtonPanel( stringResource(id = R.string.switch_location) }, onSwitchLocation = onSwitchLocationClick, - reconnectClick = { handleThrottledAction(onReconnectClick) }, + reconnectClick = { + handleThrottledAction { + onReconnectClick() + selectButtonFocusRequester.requestFocus() + } + }, isReconnectButtonEnabled = state.tunnelState is TunnelState.Connected || state.tunnelState is TunnelState.Connecting, modifier = - Modifier.testTag(SELECT_LOCATION_BUTTON_TEST_TAG).focusRequester(focusRequester), + Modifier.testTag(SELECT_LOCATION_BUTTON_TEST_TAG) + .focusRequester(selectButtonFocusRequester), reconnectButtonTestTag = RECONNECT_BUTTON_TEST_TAG, ) Spacer(Modifier.height(Dimens.buttonVerticalPadding)) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreen.kt index c2c3a72c35..b41a95d64e 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreen.kt @@ -32,6 +32,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource @@ -372,7 +373,8 @@ private fun RelayLists( ) { // This is a workaround for the HorizontalPager being broken on Android TV when it contains // focusable views and you navigate with the D-pad. Remove this code once DROID-1639 is fixed. - val configuration = LocalContext.current.resources.configuration + val configuration = LocalConfiguration.current + if (configuration.navigation == Configuration.NAVIGATION_DPAD) { SelectLocationList( backgroundColor = backgroundColor, diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/Clipboard.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/Clipboard.kt index 55bc1855d3..3dbe8e7565 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/Clipboard.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/Clipboard.kt @@ -7,8 +7,7 @@ import androidx.compose.material3.SnackbarDuration import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.platform.ClipboardManager -import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.platform.LocalClipboard import androidx.compose.ui.platform.toClipEntry import kotlinx.coroutines.launch @@ -22,7 +21,7 @@ fun createCopyToClipboardHandle( isSensitive: Boolean, ): CopyToClipboardHandle { val scope = rememberCoroutineScope() - val clipboardManager: ClipboardManager = LocalClipboardManager.current + val clipboardManager = LocalClipboard.current return { textToCopy: String, toastMessage: String? -> if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU && toastMessage != null) { @@ -34,14 +33,16 @@ fun createCopyToClipboardHandle( } } - val clip = - ClipData.newPlainText("", textToCopy) - .apply { - description.extras = - PersistableBundle().apply { putBoolean(IS_SENSITIVE_FLAG, isSensitive) } - } - .toClipEntry() + scope.launch { + val clip = + ClipData.newPlainText("", textToCopy) + .apply { + description.extras = + PersistableBundle().apply { putBoolean(IS_SENSITIVE_FLAG, isSensitive) } + } + .toClipEntry() - clipboardManager.setClip(clip) + clipboardManager.setClipEntry(clip) + } } } |
