diff options
| author | Albin <albin@mullvad.net> | 2023-11-27 17:23:12 +0100 |
|---|---|---|
| committer | Albin <albin@mullvad.net> | 2023-11-27 17:23:12 +0100 |
| commit | 3b093e0ee4afd159412d9921d8707478874d2392 (patch) | |
| tree | cf499ed6dc34f582cb70181f8ee84c58389370b0 /android/app/src/main | |
| parent | 851b1343afa7dfd93547e7836d90e6eb73330d3a (diff) | |
| parent | 836a7937974141aa4ad55750556e5d607c956665 (diff) | |
| download | mullvadvpn-3b093e0ee4afd159412d9921d8707478874d2392.tar.xz mullvadvpn-3b093e0ee4afd159412d9921d8707478874d2392.zip | |
Merge branch 'fix-clipboard-copypaste-bug-on-voucherredeemdialog-when-it-droid-402'
Diffstat (limited to 'android/app/src/main')
6 files changed, 39 insertions, 51 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt index c5b619a9cd..1c48a8a64a 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt @@ -14,6 +14,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource @@ -29,7 +30,8 @@ import net.mullvad.mullvadvpn.compose.button.VariantButton import net.mullvad.mullvadvpn.compose.component.MullvadCircularProgressIndicatorSmall import net.mullvad.mullvadvpn.compose.state.VoucherDialogState import net.mullvad.mullvadvpn.compose.state.VoucherDialogUiState -import net.mullvad.mullvadvpn.compose.textfield.GroupedTextField +import net.mullvad.mullvadvpn.compose.test.VOUCHER_INPUT_TEST_TAG +import net.mullvad.mullvadvpn.compose.textfield.CustomTextField import net.mullvad.mullvadvpn.compose.util.MAX_VOUCHER_LENGTH import net.mullvad.mullvadvpn.compose.util.vouchersVisualTransformation import net.mullvad.mullvadvpn.constant.VOUCHER_LENGTH @@ -217,23 +219,21 @@ private fun EnterVoucherBody( onVoucherInputChange: (String) -> Unit = {}, onRedeem: (voucherCode: String) -> Unit ) { - GroupedTextField( + CustomTextField( value = uiState.voucherInput, onSubmit = { input -> if (uiState.voucherInput.length == VOUCHER_LENGTH) { onRedeem(input) } }, - onValueChanged = { input -> onVoucherInputChange(input.uppercase()) }, + onValueChanged = { input -> onVoucherInputChange(input) }, isValidValue = uiState.voucherInput.isEmpty() || uiState.voucherInput.length == MAX_VOUCHER_LENGTH, keyboardType = KeyboardType.Password, placeholderText = stringResource(id = R.string.voucher_hint), visualTransformation = vouchersVisualTransformation(), - maxCharLength = VOUCHER_LENGTH, isDigitsOnlyAllowed = false, - isEnabled = true, - validateRegex = "^[A-Za-z0-9]*$".toRegex() + modifier = Modifier.testTag(VOUCHER_INPUT_TEST_TAG) ) Spacer(modifier = Modifier.height(Dimens.smallPadding)) Row( diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/test/ComposeTestTagConstants.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/test/ComposeTestTagConstants.kt index 01d434a117..e3cb4faa5b 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/test/ComposeTestTagConstants.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/test/ComposeTestTagConstants.kt @@ -31,3 +31,6 @@ const val PLAY_PAYMENT_INFO_ICON_TEST_TAG = "play_payment_info_icon_test_tag" const val LOGIN_TITLE_TEST_TAG = "login_title_test_tag" const val LOGIN_INPUT_TEST_TAG = "login_input_test_tag" + +// VoucherDialog +const val VOUCHER_INPUT_TEST_TAG = "voucher_input_test_tag" diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/textfield/GroupedTextField.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/textfield/GroupedTextField.kt deleted file mode 100644 index 5bc0a8ff86..0000000000 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/textfield/GroupedTextField.kt +++ /dev/null @@ -1,36 +0,0 @@ -package net.mullvad.mullvadvpn.compose.textfield - -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.input.VisualTransformation - -@Composable -fun GroupedTextField( - value: String, - keyboardType: KeyboardType, - modifier: Modifier = Modifier, - onValueChanged: (String) -> Unit, - onSubmit: (String) -> Unit, - isEnabled: Boolean = true, - visualTransformation: VisualTransformation, - placeholderText: String = "", - maxCharLength: Int = Int.MAX_VALUE, - isValidValue: Boolean, - isDigitsOnlyAllowed: Boolean, - validateRegex: Regex, -) { - CustomTextField( - value = value, - keyboardType = keyboardType, - onValueChanged = { if (validateRegex.matches(it)) onValueChanged(it) }, - onSubmit = onSubmit, - isDigitsOnlyAllowed = isDigitsOnlyAllowed, - modifier = modifier, - isEnabled = isEnabled, - visualTransformation = visualTransformation, - placeholderText = placeholderText, - maxCharLength = maxCharLength, - isValidValue = isValidValue, - ) -} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt index 3232d20cbd..31ac1befdc 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt @@ -19,3 +19,6 @@ fun ServiceConnectionManager.settingsListener() = fun ServiceConnectionManager.splitTunneling() = this.connectionState.value.readyContainer()?.splitTunneling + +fun ServiceConnectionManager.voucherRedeemer() = + this.connectionState.value.readyContainer()?.voucherRedeemer diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/util/VoucherRegexHelper.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/util/VoucherRegexHelper.kt new file mode 100644 index 0000000000..48cb85f879 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/util/VoucherRegexHelper.kt @@ -0,0 +1,13 @@ +package net.mullvad.mullvadvpn.util + +private const val VALID_VOUCHER_CHARACTER_REGEX_PATTERN = "^[A-Za-z0-9- \r\n]*$" +private const val IGNORED_VOUCHER_CHARACTER_REGEX_PATTERN = """[- \n\r]""" + +object VoucherRegexHelper { + fun validate(input: String): Boolean { + return VALID_VOUCHER_CHARACTER_REGEX_PATTERN.toRegex().matches(input) + } + + fun trim(input: String): String = + input.replace(Regex(IGNORED_VOUCHER_CHARACTER_REGEX_PATTERN), "") +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModel.kt index 07c56ff954..802245bb1d 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModel.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModel.kt @@ -15,25 +15,25 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.state.LoginUiState import net.mullvad.mullvadvpn.compose.state.VoucherDialogState import net.mullvad.mullvadvpn.compose.state.VoucherDialogUiState +import net.mullvad.mullvadvpn.constant.VOUCHER_LENGTH import net.mullvad.mullvadvpn.model.VoucherSubmissionError import net.mullvad.mullvadvpn.model.VoucherSubmissionResult import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionContainer import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState -import net.mullvad.mullvadvpn.ui.serviceconnection.VoucherRedeemer +import net.mullvad.mullvadvpn.ui.serviceconnection.voucherRedeemer +import net.mullvad.mullvadvpn.util.VoucherRegexHelper class VoucherDialogViewModel( - serviceConnectionManager: ServiceConnectionManager, + private val serviceConnectionManager: ServiceConnectionManager, private val resources: Resources ) : ViewModel() { private val vmState = MutableStateFlow<VoucherDialogState>(VoucherDialogState.Default) - private val voucherInput = MutableStateFlow(LoginUiState.INITIAL.accountNumberInput) + private val voucherInput = MutableStateFlow("") - private lateinit var voucherRedeemer: VoucherRedeemer private val _shared: SharedFlow<ServiceConnectionContainer> = serviceConnectionManager.connectionState .flatMapLatest { state -> @@ -47,8 +47,7 @@ class VoucherDialogViewModel( var uiState = _shared - .flatMapLatest { serviceConnection -> - voucherRedeemer = serviceConnection.voucherRedeemer + .flatMapLatest { combine(vmState, voucherInput) { state, input -> VoucherDialogUiState(voucherInput = input, voucherViewModelState = state) } @@ -58,7 +57,7 @@ class VoucherDialogViewModel( fun onRedeem(voucherCode: String) { vmState.update { VoucherDialogState.Verifying } viewModelScope.launch { - when (val result = voucherRedeemer.submit(voucherCode)) { + when (val result = serviceConnectionManager.voucherRedeemer()?.submit(voucherCode)) { is VoucherSubmissionResult.Ok -> handleAddedTime(result.submission.timeAdded) is VoucherSubmissionResult.Error -> setError(result.error) else -> { @@ -69,7 +68,13 @@ class VoucherDialogViewModel( } fun onVoucherInputChange(voucherString: String) { - voucherInput.value = voucherString + if (VoucherRegexHelper.validate(voucherString)) { + val trimmedVoucher = VoucherRegexHelper.trim(voucherString) + voucherInput.value = + trimmedVoucher + .substring(0, Integer.min(VOUCHER_LENGTH, trimmedVoucher.length)) + .uppercase() + } } private fun handleAddedTime(timeAdded: Long) { |
