diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt index d4ffb2a6f8ec..dd3f454527b0 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt @@ -66,13 +66,11 @@ private fun PreviewAccountScreen() { AppTheme { AccountScreen( showSitePayment = true, - uiState = - AccountUiState( + uiState = AccountUiState( deviceName = "Test Name", accountNumber = "1234123412341234", accountExpiry = null, - billingPaymentState = - PaymentState.PaymentAvailable( + billingPaymentState = PaymentState.PaymentAvailable( listOf( PaymentProduct( ProductId("productId"), @@ -103,10 +101,8 @@ fun AccountScreen( onRedeemVoucherClick: () -> Unit = {}, onManageAccountClick: () -> Unit = {}, onLogoutClick: () -> Unit = {}, - onPurchaseBillingProductClick: - (productId: ProductId, activityProvider: () -> Activity) -> Unit = - { _, _ -> - }, + onPurchaseBillingProductClick: (productId: ProductId, activityProvider: () -> Activity) -> Unit = { _, _ -> + }, onClosePurchaseResultDialog: (success: Boolean) -> Unit = {}, onBackClick: () -> Unit = {}, ) { @@ -163,7 +159,9 @@ fun AccountScreen( Column( horizontalAlignment = Alignment.Start, verticalArrangement = Arrangement.spacedBy(Dimens.accountRowSpacing), - modifier = modifier.animateContentSize().padding(horizontal = Dimens.sideMargin), + modifier = modifier + .animateContentSize() + .padding(horizontal = Dimens.sideMargin), ) { DeviceNameRow(deviceName = uiState.deviceName ?: "") { showDeviceNameInfoDialog = true } @@ -238,7 +236,9 @@ private fun AccountNumberRow(accountNumber: String) { ) CopyableObfuscationView( content = accountNumber, - modifier = Modifier.heightIn(min = Dimens.accountRowMinHeight).fillMaxWidth(), + modifier = Modifier + .heightIn(min = Dimens.accountRowMinHeight) + .fillMaxWidth(), ) } } 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 91dc46af2f0d..2685a7d6b74e 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 @@ -101,6 +101,7 @@ fun ConnectScreen( is ConnectViewModel.UiSideEffect.OpenAccountManagementPageInBrowser -> { context.openAccountPageInBrowser(uiSideEffect.token) } + is ConnectViewModel.UiSideEffect.OpenOutOfTimeView -> { onOpenOutOfTimeScreen() } @@ -120,26 +121,22 @@ fun ConnectScreen( } ScaffoldWithTopBarAndDeviceName( - topBarColor = - if (uiState.tunnelUiState.isSecured()) { + topBarColor = if (uiState.tunnelUiState.isSecured()) { MaterialTheme.colorScheme.inversePrimary } else { MaterialTheme.colorScheme.error }, - statusBarColor = - if (uiState.tunnelUiState.isSecured()) { + statusBarColor = if (uiState.tunnelUiState.isSecured()) { MaterialTheme.colorScheme.inversePrimary } else { MaterialTheme.colorScheme.error }, navigationBarColor = null, - iconTintColor = - if (uiState.tunnelUiState.isSecured()) { + iconTintColor = if (uiState.tunnelUiState.isSecured()) { MaterialTheme.colorScheme.onPrimary } else { MaterialTheme.colorScheme.onError - } - .copy(alpha = AlphaTopBar), + }.copy(alpha = AlphaTopBar), onSettingsClicked = onSettingsClick, onAccountClicked = onAccountClick, deviceName = uiState.deviceName, @@ -148,8 +145,8 @@ fun ConnectScreen( Column( verticalArrangement = Arrangement.Bottom, horizontalAlignment = Alignment.Start, - modifier = - Modifier.padding(it) + modifier = Modifier + .padding(it) .background(color = MaterialTheme.colorScheme.primary) .fillMaxHeight() .drawVerticalScrollbar( @@ -167,22 +164,15 @@ fun ConnectScreen( onClickDismissNewDevice = onDismissNewDeviceClick, ) Spacer(modifier = Modifier.weight(1f)) - if ( - uiState.tunnelRealState is TunnelState.Connecting || - ( - uiState.tunnelRealState is TunnelState.Disconnecting && - uiState.tunnelRealState.actionAfterDisconnect == - ActionAfterDisconnect.Reconnect - ) - ) { + if (uiState.tunnelRealState is TunnelState.Connecting || (uiState.tunnelRealState is TunnelState.Disconnecting && uiState.tunnelRealState.actionAfterDisconnect == ActionAfterDisconnect.Reconnect)) { MullvadCircularProgressIndicatorLarge( color = MaterialTheme.colorScheme.onPrimary, - modifier = - Modifier.padding( - start = Dimens.sideMargin, - end = Dimens.sideMargin, - top = Dimens.mediumPadding, - ) + modifier = Modifier + .padding( + start = Dimens.sideMargin, + end = Dimens.sideMargin, + top = Dimens.mediumPadding, + ) .align(Alignment.CenterHorizontally) .testTag(CIRCULAR_PROGRESS_INDICATOR), ) @@ -206,28 +196,25 @@ fun ConnectScreen( ) LocationInfo( onToggleTunnelInfo = onToggleTunnelInfo, - isVisible = - uiState.tunnelRealState != TunnelState.Disconnected && - uiState.location?.hostname != null, + isVisible = uiState.tunnelRealState != TunnelState.Disconnected && uiState.location?.hostname != null, isExpanded = uiState.isTunnelInfoExpanded, location = uiState.location, inAddress = uiState.inAddress, outAddress = uiState.outAddress, - modifier = - Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .padding(horizontal = Dimens.sideMargin) .testTag(LOCATION_INFO_TEST_TAG), ) Spacer(modifier = Modifier.height(Dimens.buttonSpacing)) SwitchLocationButton( - modifier = - Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .padding(horizontal = Dimens.sideMargin) .testTag(SELECT_LOCATION_BUTTON_TEST_TAG), onClick = onSwitchLocationClick, showChevron = uiState.showLocation, - text = - if (uiState.showLocation) { + text = if (uiState.showLocation) { uiState.relayLocation?.locationName ?: "" } else { stringResource(id = R.string.switch_location) @@ -236,8 +223,8 @@ fun ConnectScreen( Spacer(modifier = Modifier.height(Dimens.buttonSpacing)) ConnectionButton( state = uiState.tunnelUiState, - modifier = - Modifier.padding(horizontal = Dimens.sideMargin) + modifier = Modifier + .padding(horizontal = Dimens.sideMargin) .testTag(CONNECT_BUTTON_TEST_TAG), disconnectClick = onDisconnectClick, reconnectClick = { handleThrottledAction(onReconnectClick) }, diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt index dd49ec929fa7..32d1b882aaac 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt @@ -48,13 +48,10 @@ import net.mullvad.mullvadvpn.util.formatDate private fun PreviewDeviceListScreen() { AppTheme { DeviceListScreen( - state = - DeviceListUiState( - deviceUiItems = - listOf( + state = DeviceListUiState( + deviceUiItems = listOf( DeviceListItemUiState( - device = - Device( + device = Device( id = "ID", name = "Name", pubkey = ByteArray(10), @@ -97,15 +94,17 @@ fun DeviceListScreen( onAccountClicked = null, ) { Column( - modifier = Modifier.fillMaxSize().padding(it), + modifier = Modifier + .fillMaxSize() + .padding(it), ) { val scrollState = rememberScrollState() Column( - modifier = - Modifier.drawVerticalScrollbar( - scrollState, - MaterialTheme.colorScheme.onBackground, - ) + modifier = Modifier + .drawVerticalScrollbar( + scrollState, + MaterialTheme.colorScheme.onBackground, + ) .verticalScroll(scrollState) .weight(1f), ) { @@ -130,27 +129,23 @@ fun DeviceListScreen( @Composable private fun ColumnScope.DeviceListHeader(state: DeviceListUiState) { Image( - painter = - painterResource( - id = - if (state.hasTooManyDevices) { + painter = painterResource( + id = if (state.hasTooManyDevices) { R.drawable.icon_fail } else { R.drawable.icon_success }, ), contentDescription = null, // No meaningful user info or action. - modifier = - Modifier.align(Alignment.CenterHorizontally) + modifier = Modifier + .align(Alignment.CenterHorizontally) .padding(top = Dimens.iconFailSuccessTopMargin) .size(Dimens.bigIconSize), ) Text( - text = - stringResource( - id = - if (state.hasTooManyDevices) { + text = stringResource( + id = if (state.hasTooManyDevices) { R.string.max_devices_warning_title } else { R.string.max_devices_resolved_title @@ -158,8 +153,7 @@ private fun ColumnScope.DeviceListHeader(state: DeviceListUiState) { ), style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onBackground, - modifier = - Modifier.padding( + modifier = Modifier.padding( start = Dimens.sideMargin, end = Dimens.sideMargin, top = Dimens.screenVerticalMargin, @@ -167,10 +161,8 @@ private fun ColumnScope.DeviceListHeader(state: DeviceListUiState) { ) Text( - text = - stringResource( - id = - if (state.hasTooManyDevices) { + text = stringResource( + id = if (state.hasTooManyDevices) { R.string.max_devices_warning_description } else { R.string.max_devices_resolved_description @@ -178,8 +170,8 @@ private fun ColumnScope.DeviceListHeader(state: DeviceListUiState) { ), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onBackground, - modifier = - Modifier.wrapContentHeight() + modifier = Modifier + .wrapContentHeight() .animateContentSize() .padding( top = Dimens.smallPadding, @@ -207,15 +199,11 @@ private fun DeviceListItem( ) Text( modifier = Modifier.fillMaxWidth(), - text = - deviceUiState.device.created.parseAsDateTime()?.let { creationDate -> + text = deviceUiState.device.created.parseAsDateTime()?.let { creationDate -> stringResource(id = R.string.created_x, creationDate.formatDate()) - } - ?: "", + } ?: "", style = MaterialTheme.typography.listItemSubText, - color = - MaterialTheme.colorScheme.onPrimary - .copy(alpha = AlphaDescription) + color = MaterialTheme.colorScheme.onPrimary.copy(alpha = AlphaDescription) .compositeOver(MaterialTheme.colorScheme.primary), ) } @@ -245,8 +233,7 @@ private fun DeviceListButtonPanel( onBackClick: () -> Unit, ) { Column( - modifier = - Modifier.padding( + modifier = Modifier.padding( start = Dimens.sideMargin, end = Dimens.sideMargin, top = Dimens.spacingAboveButton, diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt index 4d4e2d957f96..b14e1dcd4df8 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt @@ -40,12 +40,11 @@ fun DeviceRevokedScreen( onSettingsClicked: () -> Unit = {}, onGoToLoginClicked: () -> Unit = {}, ) { - val topColor = - if (state == DeviceRevokedUiState.SECURED) { - MaterialTheme.colorScheme.inversePrimary - } else { - MaterialTheme.colorScheme.error - } + val topColor = if (state == DeviceRevokedUiState.SECURED) { + MaterialTheme.colorScheme.inversePrimary + } else { + MaterialTheme.colorScheme.error + } ScaffoldWithTopBar( topBarColor = topColor, @@ -55,8 +54,8 @@ fun DeviceRevokedScreen( onAccountClicked = null, ) { ConstraintLayout( - modifier = - Modifier.fillMaxHeight() + modifier = Modifier + .fillMaxHeight() .fillMaxWidth() .padding(it) .background(color = MaterialTheme.colorScheme.background), @@ -66,19 +65,18 @@ fun DeviceRevokedScreen( Image( painter = painterResource(id = R.drawable.icon_fail), contentDescription = null, // No meaningful user info or action. - modifier = - Modifier.constrainAs(icon) { - top.linkTo(parent.top, margin = 30.dp) - start.linkTo(parent.start) - end.linkTo(parent.end) - } + modifier = Modifier + .constrainAs(icon) { + top.linkTo(parent.top, margin = 30.dp) + start.linkTo(parent.start) + end.linkTo(parent.end) + } .padding(horizontal = 12.dp) .size(Dimens.bigIconSize), ) Column( - modifier = - Modifier.constrainAs(body) { + modifier = Modifier.constrainAs(body) { top.linkTo(icon.bottom, margin = 22.dp) start.linkTo(parent.start, margin = 22.dp) end.linkTo(parent.end, margin = 22.dp) @@ -110,8 +108,7 @@ fun DeviceRevokedScreen( } Column( - modifier = - Modifier.constrainAs(actionButtons) { + modifier = Modifier.constrainAs(actionButtons) { bottom.linkTo(parent.bottom, margin = 22.dp) start.linkTo(parent.start, margin = 22.dp) end.linkTo(parent.end, margin = 22.dp) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoadingScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoadingScreen.kt index adb19766d308..cca1ee74eb7d 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoadingScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoadingScreen.kt @@ -45,8 +45,8 @@ fun LoadingScreen(onSettingsCogClicked: () -> Unit = {}) { content = { Box( contentAlignment = Alignment.Center, - modifier = - Modifier.background(backgroundColor) + modifier = Modifier + .background(backgroundColor) .padding(it) .padding(bottom = it.calculateTopPadding()) .fillMaxSize(), @@ -64,14 +64,14 @@ fun LoadingScreen(onSettingsCogClicked: () -> Unit = {}) { painter = painterResource(id = R.drawable.logo_text), contentDescription = "", alpha = 0.6f, - modifier = Modifier.padding(top = 12.dp).height(18.dp), + modifier = Modifier + .padding(top = 12.dp) + .height(18.dp), ) Text( text = stringResource(id = R.string.connecting_to_daemon), fontSize = 13.sp, - color = - MaterialTheme.colorScheme.onPrimary - .copy(alpha = AlphaDescription) + color = MaterialTheme.colorScheme.onPrimary.copy(alpha = AlphaDescription) .compositeOver(backgroundColor), modifier = Modifier.padding(top = 12.dp), ) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt index 7e98f1bb2c70..55aeebde8b78 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt @@ -120,8 +120,8 @@ fun LoginScreen( ) { val scrollState = rememberScrollState() Column( - modifier = - Modifier.padding(it) + modifier = Modifier + .padding(it) .fillMaxSize() .background(MaterialTheme.colorScheme.primary) .verticalScroll(scrollState), @@ -129,8 +129,8 @@ fun LoginScreen( Spacer(modifier = Modifier.weight(1f)) LoginIcon( uiState.loginState, - modifier = - Modifier.align(Alignment.CenterHorizontally) + modifier = Modifier + .align(Alignment.CenterHorizontally) .padding(bottom = Dimens.largePadding), ) LoginContent(uiState, onAccountNumberChange, onLoginClick, onDeleteHistoryClick) @@ -148,13 +148,17 @@ private fun LoginContent( onLoginClick: (String) -> Unit, onDeleteHistoryClick: () -> Unit, ) { - Column(modifier = Modifier.fillMaxWidth().padding(horizontal = Dimens.sideMargin)) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = Dimens.sideMargin) + ) { Text( text = uiState.loginState.title(), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary, - modifier = - Modifier.testTag(LOGIN_TITLE_TEST_TAG) + modifier = Modifier + .testTag(LOGIN_TITLE_TEST_TAG) .fillMaxWidth() .padding(bottom = Dimens.smallPadding), ) @@ -167,8 +171,7 @@ private fun LoginContent( modifier = Modifier.padding(bottom = Dimens.smallPadding), text = uiState.loginState.supportingText() ?: "", style = MaterialTheme.typography.labelMedium, - color = - if (uiState.loginState.isError()) { + color = if (uiState.loginState.isError()) { MaterialTheme.colorScheme.error } else { MaterialTheme.colorScheme.onPrimary @@ -178,7 +181,8 @@ private fun LoginContent( TextField( modifier = // Fix for DPad navigation - Modifier.onFocusChanged { tfFocusState = it } + Modifier + .onFocusChanged { tfFocusState = it } .focusProperties { left = FocusRequester.Cancel right = FocusRequester.Cancel @@ -199,10 +203,8 @@ private fun LoginContent( color = Color.Unspecified, ) }, - keyboardActions = - KeyboardActions(onDone = { onLoginClick(uiState.accountNumberInput) }), - keyboardOptions = - KeyboardOptions( + keyboardActions = KeyboardActions(onDone = { onLoginClick(uiState.accountNumberInput) }), + keyboardOptions = KeyboardOptions( imeAction = if (uiState.loginButtonEnabled) ImeAction.Done else ImeAction.None, keyboardType = KeyboardType.NumberPassword, ), @@ -248,57 +250,54 @@ private fun LoginContent( private fun LoginIcon(loginState: LoginState, modifier: Modifier = Modifier) { Box(contentAlignment = Alignment.Center, modifier = modifier.size(Dimens.bigIconSize)) { when (loginState) { - is Idle -> - if (loginState.loginError != null) { - Image( - painter = painterResource(id = R.drawable.icon_fail), - contentDescription = stringResource(id = R.string.login_fail_title), - contentScale = ContentScale.Inside, - ) - } else { - // If view is Idle, we display empty box to keep the same size as other states - } - is Loading -> MullvadCircularProgressIndicatorLarge() - Success -> + is Idle -> if (loginState.loginError != null) { Image( - painter = painterResource(id = R.drawable.icon_success), - contentDescription = stringResource(id = R.string.logged_in_title), + painter = painterResource(id = R.drawable.icon_fail), + contentDescription = stringResource(id = R.string.login_fail_title), + contentScale = ContentScale.Inside, ) + } else { + // If view is Idle, we display empty box to keep the same size as other states + } + + is Loading -> MullvadCircularProgressIndicatorLarge() + Success -> Image( + painter = painterResource(id = R.drawable.icon_success), + contentDescription = stringResource(id = R.string.logged_in_title), + ) } } } @Composable -private fun LoginState.title(): String = - stringResource( - id = - when (this) { - is Idle -> - when (this.loginError) { - is LoginError -> R.string.login_fail_title - null -> R.string.login_title - } - is Loading -> R.string.logging_in_title - Success -> R.string.logged_in_title - }, - ) +private fun LoginState.title(): String = stringResource( + id = when (this) { + is Idle -> when (this.loginError) { + is LoginError -> R.string.login_fail_title + null -> R.string.login_title + } + + is Loading -> R.string.logging_in_title + Success -> R.string.logged_in_title + }, +) @Composable private fun LoginState.supportingText(): String? { - val res = - when (this) { - is Idle -> { - when (loginError) { - LoginError.InvalidCredentials -> R.string.login_fail_description - LoginError.UnableToCreateAccount -> R.string.failed_to_create_account - is LoginError.Unknown -> R.string.error_occurred - null -> return null - } + val res = when (this) { + is Idle -> { + when (loginError) { + LoginError.InvalidCredentials -> R.string.login_fail_description + LoginError.UnableToCreateAccount -> R.string.failed_to_create_account + is LoginError.Unknown -> R.string.error_occurred + null -> return null } - is Loading.CreatingAccount -> R.string.creating_new_account - is Loading.LoggingIn -> R.string.logging_in_description - Success -> R.string.logged_in_description } + + is Loading.CreatingAccount -> R.string.creating_new_account + is Loading.LoggingIn -> R.string.logging_in_description + Success -> R.string.logged_in_description + } return stringResource(id = res) } @@ -310,8 +309,7 @@ private fun AccountDropDownItem( onDeleteClick: () -> Unit, ) { Row( - modifier = - modifier + modifier = modifier .clip( MaterialTheme.shapes.medium.copy( topStart = CornerSize(0f), @@ -323,8 +321,8 @@ private fun AccountDropDownItem( verticalAlignment = Alignment.CenterVertically, ) { Box( - modifier = - Modifier.clickable(onClick = onClick) + modifier = Modifier + .clickable(onClick = onClick) .fillMaxHeight() .weight(1f) .padding(horizontal = Dimens.mediumPadding, vertical = Dimens.smallPadding), @@ -346,7 +344,8 @@ private fun AccountDropDownItem( @Composable private fun CreateAccountPanel(onCreateAccountClick: () -> Unit, isEnabled: Boolean) { Column( - Modifier.fillMaxWidth() + Modifier + .fillMaxWidth() .background(MaterialTheme.colorScheme.background) .padding(horizontal = Dimens.sideMargin, vertical = Dimens.screenVerticalMargin), ) { 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 bb9045242902..d0449cea5711 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 @@ -69,8 +69,10 @@ private fun PreviewOutOfTimeScreenConnecting() { AppTheme { OutOfTimeScreen( showSitePayment = true, - uiState = - OutOfTimeUiState(tunnelState = TunnelState.Connecting(null, null), "Strong Rabbit"), + uiState = OutOfTimeUiState( + tunnelState = TunnelState.Connecting(null, null), + "Strong Rabbit" + ), uiSideEffect = MutableSharedFlow().asSharedFlow(), ) } @@ -82,10 +84,8 @@ private fun PreviewOutOfTimeScreenError() { AppTheme { OutOfTimeScreen( showSitePayment = true, - uiState = - OutOfTimeUiState( - tunnelState = - TunnelState.Error( + uiState = OutOfTimeUiState( + tunnelState = TunnelState.Error( ErrorState(cause = ErrorStateCause.IsOffline, isBlocking = true), ), deviceName = "Stable Horse", @@ -115,8 +115,8 @@ fun OutOfTimeScreen( LaunchedEffect(key1 = Unit) { uiSideEffect.collect { uiSideEffect -> when (uiSideEffect) { - is OutOfTimeViewModel.UiSideEffect.OpenAccountView -> - openAccountPage(uiSideEffect.token) + is OutOfTimeViewModel.UiSideEffect.OpenAccountView -> openAccountPage(uiSideEffect.token) + OutOfTimeViewModel.UiSideEffect.OpenConnectScreen -> openConnectScreen() } } @@ -137,34 +137,30 @@ fun OutOfTimeScreen( val scrollState = rememberScrollState() ScaffoldWithTopBarAndDeviceName( - topBarColor = - if (uiState.tunnelState.isSecured()) { + topBarColor = if (uiState.tunnelState.isSecured()) { MaterialTheme.colorScheme.inversePrimary } else { MaterialTheme.colorScheme.error }, - statusBarColor = - if (uiState.tunnelState.isSecured()) { + statusBarColor = if (uiState.tunnelState.isSecured()) { MaterialTheme.colorScheme.inversePrimary } else { MaterialTheme.colorScheme.error }, navigationBarColor = MaterialTheme.colorScheme.background, - iconTintColor = - if (uiState.tunnelState.isSecured()) { + iconTintColor = if (uiState.tunnelState.isSecured()) { MaterialTheme.colorScheme.onPrimary } else { MaterialTheme.colorScheme.onError - } - .copy(alpha = AlphaTopBar), + }.copy(alpha = AlphaTopBar), onSettingsClicked = onSettingsClick, onAccountClicked = onAccountClick, deviceName = uiState.deviceName, timeLeft = null, ) { Column( - modifier = - Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() .padding(it) .verticalScroll(scrollState) .drawVerticalScrollbar( @@ -176,8 +172,8 @@ fun OutOfTimeScreen( Image( painter = painterResource(id = R.drawable.icon_fail), contentDescription = null, - modifier = - Modifier.align(Alignment.CenterHorizontally) + modifier = Modifier + .align(Alignment.CenterHorizontally) .padding(vertical = Dimens.screenVerticalMargin) .size(Dimens.bigIconSize), ) @@ -188,8 +184,7 @@ fun OutOfTimeScreen( modifier = Modifier.padding(horizontal = Dimens.sideMargin), ) Text( - text = - buildString { + text = buildString { append(stringResource(R.string.account_credit_has_expired)) if (showSitePayment) { append(" ") @@ -198,21 +193,23 @@ fun OutOfTimeScreen( }, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onPrimary, - modifier = - Modifier.padding( + modifier = Modifier.padding( top = Dimens.mediumPadding, start = Dimens.sideMargin, end = Dimens.sideMargin, ), ) - Spacer(modifier = Modifier.weight(1f).defaultMinSize(minHeight = Dimens.verticalSpace)) + Spacer( + modifier = Modifier + .weight(1f) + .defaultMinSize(minHeight = Dimens.verticalSpace) + ) // Button area if (uiState.tunnelState.showDisconnectButton()) { NegativeButton( onClick = onDisconnectClick, text = stringResource(id = R.string.disconnect), - modifier = - Modifier.padding( + modifier = Modifier.padding( start = Dimens.sideMargin, end = Dimens.sideMargin, bottom = Dimens.buttonSpacing, @@ -226,12 +223,12 @@ fun OutOfTimeScreen( onPurchaseBillingProductClick(productId) { context as Activity } }, onInfoClick = { showVerificationPendingDialog = true }, - modifier = - Modifier.padding( - start = Dimens.sideMargin, - end = Dimens.sideMargin, - bottom = Dimens.buttonSpacing, - ) + modifier = Modifier + .padding( + start = Dimens.sideMargin, + end = Dimens.sideMargin, + bottom = Dimens.buttonSpacing, + ) .align(Alignment.CenterHorizontally), ) } @@ -239,8 +236,7 @@ fun OutOfTimeScreen( SitePaymentButton( onClick = onSitePaymentClick, isEnabled = uiState.tunnelState.enableSitePaymentButton(), - modifier = - Modifier.padding( + modifier = Modifier.padding( start = Dimens.sideMargin, end = Dimens.sideMargin, bottom = Dimens.buttonSpacing, @@ -249,8 +245,7 @@ fun OutOfTimeScreen( } RedeemVoucherButton( onClick = onRedeemVoucherClick, - modifier = - Modifier.padding( + modifier = Modifier.padding( start = Dimens.sideMargin, end = Dimens.sideMargin, bottom = Dimens.screenVerticalMargin, @@ -261,18 +256,19 @@ fun OutOfTimeScreen( } } -private fun TunnelState.showDisconnectButton(): Boolean = - when (this) { - is TunnelState.Disconnected -> false - is TunnelState.Connecting, - is TunnelState.Connected, - -> true - is TunnelState.Disconnecting -> { - this.actionAfterDisconnect != ActionAfterDisconnect.Nothing - } - is TunnelState.Error -> this.errorState.isBlocking +private fun TunnelState.showDisconnectButton(): Boolean = when (this) { + is TunnelState.Disconnected -> false + is TunnelState.Connecting, + is TunnelState.Connected, + -> true + + is TunnelState.Disconnecting -> { + this.actionAfterDisconnect != ActionAfterDisconnect.Nothing } + is TunnelState.Error -> this.errorState.isBlocking +} + private fun TunnelState.enableSitePaymentButton(): Boolean = this is TunnelState.Disconnected private fun TunnelState.enableRedeemButton(): Boolean = diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt index d477364e06b2..bb4115535848 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt @@ -59,8 +59,8 @@ fun PrivacyDisclaimerScreen( onSettingsClicked = null, ) { ConstraintLayout( - modifier = - Modifier.fillMaxHeight() + modifier = Modifier + .fillMaxHeight() .fillMaxWidth() .padding(it) .background(color = MaterialTheme.colorScheme.background), @@ -70,15 +70,15 @@ fun PrivacyDisclaimerScreen( val scrollState = rememberScrollState() Column( - modifier = - Modifier.constrainAs(body) { - top.linkTo(parent.top) - start.linkTo(parent.start) - end.linkTo(parent.end) - bottom.linkTo(actionButtons.top) - width = Dimension.fillToConstraints - height = Dimension.fillToConstraints - } + modifier = Modifier + .constrainAs(body) { + top.linkTo(parent.top) + start.linkTo(parent.start) + end.linkTo(parent.end) + bottom.linkTo(actionButtons.top) + width = Dimension.fillToConstraints + height = Dimension.fillToConstraints + } .drawVerticalScrollbar( state = scrollState, color = MaterialTheme.colorScheme.onPrimary.copy(alpha = AlphaScrollbar), @@ -113,8 +113,7 @@ fun PrivacyDisclaimerScreen( ClickableText( text = AnnotatedString(stringResource(id = R.string.privacy_policy_label)), onClick = { onPrivacyPolicyLinkClicked() }, - style = - TextStyle( + style = TextStyle( fontSize = 12.sp, color = Color.White, textDecoration = TextDecoration.Underline, @@ -124,8 +123,8 @@ fun PrivacyDisclaimerScreen( Image( painter = painterResource(id = R.drawable.icon_extlink), contentDescription = null, - modifier = - Modifier.align(Alignment.CenterVertically) + modifier = Modifier + .align(Alignment.CenterVertically) .padding(start = 2.dp, top = 2.dp) .width(10.dp) .height(10.dp), @@ -134,8 +133,7 @@ fun PrivacyDisclaimerScreen( } Column( - modifier = - Modifier.constrainAs(actionButtons) { + modifier = Modifier.constrainAs(actionButtons) { top.linkTo(body.bottom, margin = sideMargin) start.linkTo(parent.start, margin = sideMargin) end.linkTo(parent.end, margin = sideMargin) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt index a1424f342a7d..601263e3b864 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ReportProblemScreen.kt @@ -75,8 +75,7 @@ private fun PreviewReportProblemSuccessScreen() { private fun PreviewReportProblemErrorScreen() { AppTheme { ReportProblemScreen( - uiState = - ReportProblemUiState( + uiState = ReportProblemUiState( false, SendingReportUiState.Error(SendProblemReportResult.Error.CollectLog), ), @@ -111,19 +110,18 @@ fun ReportProblemScreen( // Show sending states if (uiState.sendingState != null) { Column( - modifier = - modifier.padding( + modifier = modifier.padding( vertical = Dimens.mediumPadding, horizontal = Dimens.sideMargin, ), ) { when (uiState.sendingState) { SendingReportUiState.Sending -> SendingContent() - is SendingReportUiState.Error -> - ErrorContent( - { onSendReport(uiState.email, uiState.description) }, - onClearSendResult, - ) + is SendingReportUiState.Error -> ErrorContent( + { onSendReport(uiState.email, uiState.description) }, + onClearSendResult, + ) + is SendingReportUiState.Success -> SentContent(uiState.sendingState) } return@ScaffoldWithMediumTopBar @@ -131,8 +129,7 @@ fun ReportProblemScreen( } Column( - modifier = - modifier + modifier = modifier .padding( start = Dimens.sideMargin, end = Dimens.sideMargin, @@ -154,7 +151,9 @@ fun ReportProblemScreen( ) TextField( - modifier = Modifier.fillMaxWidth().weight(1f), + modifier = Modifier + .fillMaxWidth() + .weight(1f), value = uiState.description, onValueChange = updateDescription, placeholder = { Text(stringResource(R.string.user_message_hint)) }, @@ -196,7 +195,9 @@ private fun ColumnScope.SentContent(sendingState: SendingReportUiState.Success) Icon( painter = painterResource(id = R.drawable.icon_success), contentDescription = stringResource(id = R.string.sent), - modifier = Modifier.align(Alignment.CenterHorizontally).size(Dimens.dialogIconHeight), + modifier = Modifier + .align(Alignment.CenterHorizontally) + .size(Dimens.dialogIconHeight), tint = Color.Unspecified, ) @@ -207,8 +208,7 @@ private fun ColumnScope.SentContent(sendingState: SendingReportUiState.Success) color = MaterialTheme.colorScheme.onBackground, ) Text( - text = - buildAnnotatedString { + text = buildAnnotatedString { withStyle(SpanStyle(color = MaterialTheme.colorScheme.surface)) { append(stringResource(id = R.string.sent_thanks)) } @@ -224,17 +224,16 @@ private fun ColumnScope.SentContent(sendingState: SendingReportUiState.Success) Spacer(modifier = Modifier.height(Dimens.smallPadding)) sendingState.email?.let { val emailTemplate = stringResource(R.string.sent_contact) - val annotatedEmailString = - remember(it) { - val emailStart = emailTemplate.indexOf('%') + val annotatedEmailString = remember(it) { + val emailStart = emailTemplate.indexOf('%') - buildAnnotatedString { - append(emailTemplate.substring(0, emailStart)) - withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { - append(sendingState.email) - } + buildAnnotatedString { + append(emailTemplate.substring(0, emailStart)) + withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { + append(sendingState.email) } } + } Text( text = annotatedEmailString, @@ -250,7 +249,9 @@ private fun ColumnScope.ErrorContent(retry: () -> Unit, onDismiss: () -> Unit) { Icon( painter = painterResource(id = R.drawable.icon_fail), contentDescription = stringResource(id = R.string.failed_to_send), - modifier = Modifier.size(Dimens.dialogIconHeight).align(Alignment.CenterHorizontally), + modifier = Modifier + .size(Dimens.dialogIconHeight) + .align(Alignment.CenterHorizontally), tint = Color.Unspecified, ) Spacer(modifier = Modifier.height(Dimens.problemReportIconToTitlePadding)) @@ -267,8 +268,8 @@ private fun ColumnScope.ErrorContent(retry: () -> Unit, onDismiss: () -> Unit) { ) Spacer(modifier = Modifier.weight(1f)) PrimaryButton( - modifier = - Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .padding(top = Dimens.mediumPadding, bottom = Dimens.buttonSpacing), onClick = onDismiss, text = stringResource(id = R.string.edit_message), diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreen.kt index bb158cb67aa7..9d802b611056 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreen.kt @@ -58,11 +58,10 @@ import net.mullvad.mullvadvpn.relaylist.RelayItem @Preview @Composable private fun PreviewSelectLocationScreen() { - val state = - SelectLocationUiState.ShowData( - countries = listOf(RelayCountry("Country 1", "Code 1", false, emptyList())), - selectedRelay = null, - ) + val state = SelectLocationUiState.ShowData( + countries = listOf(RelayCountry("Country 1", "Code 1", false, emptyList())), + selectedRelay = null, + ) AppTheme { SelectLocationScreen( uiState = state, @@ -91,20 +90,25 @@ fun SelectLocationScreen( } val (backFocus, listFocus, searchBarFocus) = remember { FocusRequester.createRefs() } - Column(modifier = Modifier.background(backgroundColor).fillMaxWidth().fillMaxHeight()) { + Column( + modifier = Modifier + .background(backgroundColor) + .fillMaxWidth() + .fillMaxHeight() + ) { Row( - modifier = - Modifier.padding( - horizontal = Dimens.selectLocationTitlePadding, - vertical = Dimens.selectLocationTitlePadding, - ) + modifier = Modifier + .padding( + horizontal = Dimens.selectLocationTitlePadding, + vertical = Dimens.selectLocationTitlePadding, + ) .fillMaxWidth(), ) { Image( painter = painterResource(id = R.drawable.icon_back), contentDescription = null, - modifier = - Modifier.focusRequester(backFocus) + modifier = Modifier + .focusRequester(backFocus) .focusProperties { next = listFocus } .focusProperties { down = listFocus @@ -116,8 +120,8 @@ fun SelectLocationScreen( ) Text( text = stringResource(id = R.string.select_location), - modifier = - Modifier.align(Alignment.CenterVertically) + modifier = Modifier + .align(Alignment.CenterVertically) .weight(weight = 1f) .padding(end = Dimens.titleIconSize), textAlign = TextAlign.Center, @@ -126,8 +130,8 @@ fun SelectLocationScreen( ) } SearchTextField( - modifier = - Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .focusRequester(searchBarFocus) .focusProperties { next = backFocus } .height(Dimens.searchFieldHeight) @@ -138,8 +142,8 @@ fun SelectLocationScreen( Spacer(modifier = Modifier.height(height = Dimens.verticalSpace)) val lazyListState = rememberLazyListState() LazyColumn( - modifier = - Modifier.focusRequester(listFocus) + modifier = Modifier + .focusRequester(listFocus) .fillMaxSize() .drawVerticalScrollbar( lazyListState, @@ -156,6 +160,7 @@ fun SelectLocationScreen( ) } } + is SelectLocationUiState.ShowData -> { items( count = uiState.countries.size, @@ -171,20 +176,18 @@ fun SelectLocationScreen( ) } } + is SelectLocationUiState.NoSearchResultFound -> { item(contentType = ContentType.EMPTY_TEXT) { - val firstRow = - HtmlCompat.fromHtml( - textResource( - id = R.string.select_location_empty_text_first_row, - uiState.searchTerm, - ), - HtmlCompat.FROM_HTML_MODE_COMPACT, - ) - .toAnnotatedString(boldFontWeight = FontWeight.ExtraBold) + val firstRow = HtmlCompat.fromHtml( + textResource( + id = R.string.select_location_empty_text_first_row, + uiState.searchTerm, + ), + HtmlCompat.FROM_HTML_MODE_COMPACT, + ).toAnnotatedString(boldFontWeight = FontWeight.ExtraBold) Text( - text = - buildAnnotatedString { + text = buildAnnotatedString { append(firstRow) appendLine() append( diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt index 8af6f9a916db..3da9967d8b78 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt @@ -41,8 +41,7 @@ import net.mullvad.mullvadvpn.util.appendHideNavOnPlayBuild private fun PreviewSettings() { AppTheme { SettingsScreen( - uiState = - SettingsUiState( + uiState = SettingsUiState( appVersion = "2222.22", isLoggedIn = true, isUpdateAvailable = true, @@ -76,7 +75,9 @@ fun SettingsScreen( navigationIcon = { NavigateBackDownIconButton(onBackClick) }, ) { modifier, lazyListState -> LazyColumn( - modifier = modifier.testTag(LAZY_LIST_TEST_TAG).animateContentSize(), + modifier = modifier + .testTag(LAZY_LIST_TEST_TAG) + .animateContentSize(), state = lazyListState, ) { item { Spacer(modifier = Modifier.height(Dimens.cellLabelVerticalPadding)) } @@ -103,19 +104,16 @@ fun SettingsScreen( onClick = { context.openLink( Uri.parse( - context.resources - .getString(R.string.download_url) + context.resources.getString(R.string.download_url) .appendHideNavOnPlayBuild(), ), ) }, - bodyView = - @Composable { + bodyView = @Composable { if (IS_PLAY_BUILD.not()) { NavigationCellBody( content = uiState.appVersion, - contentBodyDescription = - stringResource(id = R.string.app_version), + contentBodyDescription = stringResource(id = R.string.app_version), isExternalLink = true, ) } else { @@ -136,8 +134,8 @@ fun SettingsScreen( text = stringResource(id = R.string.update_available_footer), style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSecondary, - modifier = - Modifier.background(MaterialTheme.colorScheme.secondary) + modifier = Modifier + .background(MaterialTheme.colorScheme.secondary) .padding( start = Dimens.cellStartPadding, top = Dimens.cellTopPadding, @@ -179,8 +177,7 @@ fun SettingsScreen( onClick = { context.openLink( Uri.parse( - context.resources - .getString(R.string.privacy_policy_url) + context.resources.getString(R.string.privacy_policy_url) .appendHideNavOnPlayBuild(), ), ) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt index 630a5e2e736d..d2df549415a0 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt @@ -40,10 +40,8 @@ import net.mullvad.mullvadvpn.lib.theme.Dimens private fun PreviewSplitTunnelingScreen() { AppTheme { SplitTunnelingScreen( - uiState = - SplitTunnelingUiState.ShowAppList( - excludedApps = - listOf( + uiState = SplitTunnelingUiState.ShowAppList( + excludedApps = listOf( AppData( packageName = "my.package.a", name = "TitleA", @@ -55,8 +53,7 @@ private fun PreviewSplitTunnelingScreen() { iconRes = R.drawable.icon_chevron, ), ), - includedApps = - listOf( + includedApps = listOf( AppData( packageName = "my.package.c", name = "TitleC", @@ -96,8 +93,7 @@ fun SplitTunnelingScreen( Text( style = MaterialTheme.typography.labelMedium, text = stringResource(id = R.string.split_tunneling_description), - modifier = - Modifier.padding( + modifier = Modifier.padding( start = Dimens.mediumPadding, end = Dimens.mediumPadding, bottom = Dimens.mediumPadding, @@ -111,6 +107,7 @@ fun SplitTunnelingScreen( MullvadCircularProgressIndicatorLarge() } } + is SplitTunnelingUiState.ShowAppList -> { if (uiState.excludedApps.isNotEmpty()) { itemWithDivider( @@ -138,7 +135,9 @@ fun SplitTunnelingScreen( title = listItem.name, packageName = listItem.packageName, isSelected = true, - modifier = Modifier.animateItemPlacement().fillMaxWidth(), + modifier = Modifier + .animateItemPlacement() + .fillMaxWidth(), onResolveIcon = onResolveIcon, ) { // Move focus down unless the clicked item was the last in this @@ -154,8 +153,9 @@ fun SplitTunnelingScreen( } item(key = CommonContentKey.SPACER, contentType = ContentType.SPACER) { Spacer( - modifier = - Modifier.animateItemPlacement().height(Dimens.mediumPadding), + modifier = Modifier + .animateItemPlacement() + .height(Dimens.mediumPadding), ) } } @@ -197,7 +197,9 @@ fun SplitTunnelingScreen( title = listItem.name, packageName = listItem.packageName, isSelected = false, - modifier = Modifier.animateItemPlacement().fillMaxWidth(), + modifier = Modifier + .animateItemPlacement() + .fillMaxWidth(), onResolveIcon = onResolveIcon, ) { // Move focus down unless the clicked item was the last in this diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ViewLogsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ViewLogsScreen.kt index 1488860e709a..5d3ab2f19585 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ViewLogsScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ViewLogsScreen.kt @@ -92,8 +92,8 @@ fun ViewLogsScreen( }, ) { Card( - modifier = - Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() .padding(it) .padding( start = Dimens.sideMargin, @@ -103,19 +103,20 @@ fun ViewLogsScreen( ) { if (uiState.isLoading) { MullvadCircularProgressIndicatorMedium( - modifier = - Modifier.padding(Dimens.mediumPadding).align(Alignment.CenterHorizontally), + modifier = Modifier + .padding(Dimens.mediumPadding) + .align(Alignment.CenterHorizontally), color = MaterialTheme.colorScheme.primary, ) } else { val state = rememberLazyListState() LazyColumn( state = state, - modifier = - Modifier.drawVerticalScrollbar( - state, - MaterialTheme.colorScheme.primary.copy(alpha = AlphaScrollbar), - ) + modifier = Modifier + .drawVerticalScrollbar( + state, + MaterialTheme.colorScheme.primary.copy(alpha = AlphaScrollbar), + ) .padding(horizontal = Dimens.smallPadding), ) { items(uiState.allLines) { diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt index 28deee743d9d..dd3fb2fb9614 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt @@ -87,8 +87,7 @@ import net.mullvad.mullvadvpn.viewmodel.CustomDnsItem private fun PreviewVpnSettings() { AppTheme { VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( + uiState = VpnSettingsUiState.createDefault( isAutoConnectEnabled = true, mtu = "1337", isCustomDnsEnabled = true, @@ -185,6 +184,7 @@ fun VpnSettingsScreen( onDismiss = { onCancelMtuDialogClick() }, ) } + is VpnSettingsDialog.Dns -> { DnsDialog( stagedDns = dialog.stagedDns, @@ -195,27 +195,35 @@ fun VpnSettingsScreen( onDismiss = { onCancelDnsDialogClick() }, ) } + is VpnSettingsDialog.LocalNetworkSharingInfo -> { LocalNetworkSharingInfoDialog(onDismissInfoClick) } + is VpnSettingsDialog.ContentBlockersInfo -> { ContentBlockersInfoDialog(onDismissInfoClick) } + is VpnSettingsDialog.CustomDnsInfo -> { CustomDnsInfoDialog(onDismissInfoClick) } + is VpnSettingsDialog.MalwareInfo -> { MalwareInfoDialog(onDismissInfoClick) } + is VpnSettingsDialog.ObfuscationInfo -> { ObfuscationInfoDialog(onDismissInfoClick) } + is VpnSettingsDialog.QuantumResistanceInfo -> { QuantumResistanceInfoDialog(onDismissInfoClick) } + is VpnSettingsDialog.WireguardPortInfo -> { WireguardPortInfoDialog(dialog.availablePortRanges, onDismissInfoClick) } + is VpnSettingsDialog.CustomPort -> { CustomPortDialog( customPort = savedCustomPort.value.toDisplayCustomPort(), @@ -241,10 +249,7 @@ fun VpnSettingsScreen( val topPadding = 6.dp LaunchedEffect(uiState.selectedWireguardPort) { - if ( - uiState.selectedWireguardPort.isCustom() && - uiState.selectedWireguardPort != savedCustomPort.value - ) { + if (uiState.selectedWireguardPort.isCustom() && uiState.selectedWireguardPort != savedCustomPort.value) { savedCustomPort.value = uiState.selectedWireguardPort } } @@ -269,7 +274,9 @@ fun VpnSettingsScreen( navigationIcon = { NavigateBackIconButton(onBackClick) }, ) { modifier, lazyListState -> LazyColumn( - modifier = modifier.testTag(LAZY_LIST_TEST_TAG).animateContentSize(), + modifier = modifier + .testTag(LAZY_LIST_TEST_TAG) + .animateContentSize(), state = lazyListState, ) { item { @@ -373,7 +380,8 @@ fun VpnSettingsScreen( if (uiState.isCustomDnsEnabled) { item { ContentBlockersDisableModeCellSubtitle( - Modifier.background(MaterialTheme.colorScheme.secondary) + Modifier + .background(MaterialTheme.colorScheme.secondary) .padding( start = Dimens.cellStartPadding, top = topPadding, @@ -399,8 +407,7 @@ fun VpnSettingsScreen( itemsIndexed(uiState.customDnsItems) { index, item -> DnsCell( address = item.address, - isUnreachableLocalDnsWarningVisible = - item.isLocal && uiState.isAllowLanEnabled.not(), + isUnreachableLocalDnsWarningVisible = item.isLocal && uiState.isAllowLanEnabled.not(), onClick = { onDnsClick(index) }, modifier = Modifier.animateItemPlacement(), ) @@ -426,8 +433,8 @@ fun VpnSettingsScreen( item { CustomDnsCellSubtitle( isCellClickable = uiState.contentBlockersOptions.isAnyBlockerEnabled().not(), - modifier = - Modifier.background(MaterialTheme.colorScheme.secondary) + modifier = Modifier + .background(MaterialTheme.colorScheme.secondary) .padding( start = Dimens.cellStartPadding, top = topPadding, @@ -468,8 +475,7 @@ fun VpnSettingsScreen( CustomPortCell( title = stringResource(id = R.string.wireguard_custon_port_title), isSelected = uiState.selectedWireguardPort.isCustom(), - port = - if (uiState.selectedWireguardPort.isCustom()) { + port = if (uiState.selectedWireguardPort.isCustom()) { uiState.selectedWireguardPort.toDisplayCustomPort() } else { savedCustomPort.value.toDisplayCustomPort() diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreen.kt index 4a19d84e0b57..47df5cab523a 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreen.kt @@ -64,14 +64,11 @@ private fun PreviewWelcomeScreen() { AppTheme { WelcomeScreen( showSitePayment = true, - uiState = - WelcomeUiState( + uiState = WelcomeUiState( accountNumber = "4444555566667777", deviceName = "Happy Mole", - billingPaymentState = - PaymentState.PaymentAvailable( - products = - listOf( + billingPaymentState = PaymentState.PaymentAvailable( + products = listOf( PaymentProduct(ProductId("product"), ProductPrice("$44"), null), ), ), @@ -105,8 +102,10 @@ fun WelcomeScreen( LaunchedEffect(Unit) { uiSideEffect.collect { uiSideEffect -> when (uiSideEffect) { - is WelcomeViewModel.UiSideEffect.OpenAccountView -> - context.openAccountPageInBrowser(uiSideEffect.token) + is WelcomeViewModel.UiSideEffect.OpenAccountView -> context.openAccountPageInBrowser( + uiSideEffect.token + ) + WelcomeViewModel.UiSideEffect.OpenConnectScreen -> openConnectScreen() } } @@ -129,33 +128,29 @@ fun WelcomeScreen( val snackbarHostState = remember { SnackbarHostState() } ScaffoldWithTopBar( - topBarColor = - if (uiState.tunnelState.isSecured()) { + topBarColor = if (uiState.tunnelState.isSecured()) { MaterialTheme.colorScheme.inversePrimary } else { MaterialTheme.colorScheme.error }, - statusBarColor = - if (uiState.tunnelState.isSecured()) { + statusBarColor = if (uiState.tunnelState.isSecured()) { MaterialTheme.colorScheme.inversePrimary } else { MaterialTheme.colorScheme.error }, navigationBarColor = MaterialTheme.colorScheme.background, - iconTintColor = - if (uiState.tunnelState.isSecured()) { + iconTintColor = if (uiState.tunnelState.isSecured()) { MaterialTheme.colorScheme.onPrimary } else { MaterialTheme.colorScheme.onError - } - .copy(alpha = AlphaTopBar), + }.copy(alpha = AlphaTopBar), onSettingsClicked = onSettingsClick, onAccountClicked = onAccountClick, snackbarHostState = snackbarHostState, ) { Column( - modifier = - Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() .padding(it) .verticalScroll(scrollState) .drawVerticalScrollbar( @@ -191,8 +186,8 @@ private fun WelcomeInfo( Column { Text( text = stringResource(id = R.string.congrats), - modifier = - Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .padding( top = Dimens.screenVerticalMargin, start = Dimens.sideMargin, @@ -205,8 +200,8 @@ private fun WelcomeInfo( ) Text( text = stringResource(id = R.string.here_is_your_account_number), - modifier = - Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .padding( horizontal = Dimens.sideMargin, vertical = Dimens.smallPadding, @@ -220,16 +215,14 @@ private fun WelcomeInfo( DeviceNameRow(deviceName = uiState.deviceName) Text( - text = - buildString { + text = buildString { append(stringResource(id = R.string.pay_to_start_using)) if (showSitePayment) { append(" ") append(stringResource(id = R.string.add_time_to_account)) } }, - modifier = - Modifier.padding( + modifier = Modifier.padding( top = Dimens.smallPadding, bottom = Dimens.verticalSpace, start = Dimens.sideMargin, @@ -252,14 +245,16 @@ private fun AccountNumberRow(snackbarHostState: SnackbarHostState, uiState: Welc Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, - modifier = - Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .clickable(onClick = onCopyToClipboard) .padding(horizontal = Dimens.sideMargin), ) { Text( text = uiState.accountNumber?.groupWithSpaces() ?: "", - modifier = Modifier.weight(1f).padding(vertical = Dimens.smallPadding), + modifier = Modifier + .weight(1f) + .padding(vertical = Dimens.smallPadding), style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onPrimary, ) @@ -276,8 +271,7 @@ fun DeviceNameRow(deviceName: String?) { ) { Text( modifier = Modifier.weight(1f, fill = false), - text = - buildString { + text = buildString { append(stringResource(id = R.string.device_name)) append(": ") append(deviceName) @@ -316,8 +310,8 @@ private fun PaymentPanel( ) { val context = LocalContext.current Column( - modifier = - Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .padding(top = Dimens.mediumPadding) .background(color = MaterialTheme.colorScheme.background), ) { @@ -329,12 +323,12 @@ private fun PaymentPanel( onPurchaseBillingProductClick(productId) { context as Activity } }, onInfoClick = onPaymentInfoClick, - modifier = - Modifier.padding( - start = Dimens.sideMargin, - end = Dimens.sideMargin, - bottom = Dimens.buttonSpacing, - ) + modifier = Modifier + .padding( + start = Dimens.sideMargin, + end = Dimens.sideMargin, + bottom = Dimens.buttonSpacing, + ) .align(Alignment.CenterHorizontally), ) } @@ -342,8 +336,7 @@ private fun PaymentPanel( SitePaymentButton( onClick = onSitePaymentClick, isEnabled = true, - modifier = - Modifier.padding( + modifier = Modifier.padding( start = Dimens.sideMargin, end = Dimens.sideMargin, bottom = Dimens.buttonSpacing, @@ -353,8 +346,7 @@ private fun PaymentPanel( RedeemVoucherButton( onClick = onRedeemVoucherClick, isEnabled = true, - modifier = - Modifier.padding( + modifier = Modifier.padding( start = Dimens.sideMargin, end = Dimens.sideMargin, bottom = Dimens.screenVerticalMargin, diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/MullvadProblemReport.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/MullvadProblemReport.kt index 607dff9d1636..467e6d8cd0b5 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/MullvadProblemReport.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/MullvadProblemReport.kt @@ -19,7 +19,10 @@ sealed interface SendProblemReportResult { } } -data class UserReport(val email: String?, val description: String) +data class UserReport( + val email: String?, + val description: String, +) class MullvadProblemReport(context: Context, val dispatcher: CoroutineDispatcher = Dispatchers.IO) {