diff options
| author | saber safavi <saber.safavi@codic.se> | 2023-11-17 13:52:05 +0100 |
|---|---|---|
| committer | saber safavi <saber.safavi@codic.se> | 2023-11-27 16:26:28 +0100 |
| commit | 2430bd0f34f0352ffc31ee8598b9fd38a250aa84 (patch) | |
| tree | 6884fa4e9912676393efcc121ce83393021037f2 /android | |
| parent | 851b1343afa7dfd93547e7836d90e6eb73330d3a (diff) | |
| download | mullvadvpn-2430bd0f34f0352ffc31ee8598b9fd38a250aa84.tar.xz mullvadvpn-2430bd0f34f0352ffc31ee8598b9fd38a250aa84.zip | |
Fix Voucher dialog copy/paste issue
Diffstat (limited to 'android')
5 files changed, 33 insertions, 50 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..29d4807b42 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 @@ -29,7 +29,7 @@ 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.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 +217,20 @@ 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() + isDigitsOnlyAllowed = false ) Spacer(modifier = Modifier.height(Dimens.smallPadding)) Row( 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..a3bf687f42 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 @@ -18,22 +18,23 @@ 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 lateinit var voucherRedeemer: VoucherRedeemer private val _shared: SharedFlow<ServiceConnectionContainer> = serviceConnectionManager.connectionState .flatMapLatest { state -> @@ -47,8 +48,7 @@ class VoucherDialogViewModel( var uiState = _shared - .flatMapLatest { serviceConnection -> - voucherRedeemer = serviceConnection.voucherRedeemer + .flatMapLatest { combine(vmState, voucherInput) { state, input -> VoucherDialogUiState(voucherInput = input, voucherViewModelState = state) } @@ -58,7 +58,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 +69,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) { |
