summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorsaber safavi <saber.safavi@codic.se>2023-11-17 13:52:05 +0100
committersaber safavi <saber.safavi@codic.se>2023-11-27 16:26:28 +0100
commit2430bd0f34f0352ffc31ee8598b9fd38a250aa84 (patch)
tree6884fa4e9912676393efcc121ce83393021037f2 /android
parent851b1343afa7dfd93547e7836d90e6eb73330d3a (diff)
downloadmullvadvpn-2430bd0f34f0352ffc31ee8598b9fd38a250aa84.tar.xz
mullvadvpn-2430bd0f34f0352ffc31ee8598b9fd38a250aa84.zip
Fix Voucher dialog copy/paste issue
Diffstat (limited to 'android')
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RedeemVoucherDialog.kt11
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/textfield/GroupedTextField.kt36
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/util/VoucherRegexHelper.kt13
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModel.kt20
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) {