From 3832299463af818a087626719e1506c11d4732bd Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 18 Sep 2023 11:44:27 +0200 Subject: [PATCH] More error info in assistant --- app/src/main/assets/linphonerc_factory | 5 + .../ui/assistant/fragment/RegisterFragment.kt | 10 + .../viewmodel/AccountCreationViewModel.kt | 175 ++++++++++++++++-- .../ThirdPartySipAccountLoginViewModel.kt | 4 +- .../layout/assistant_register_fragment.xml | 13 ++ app/src/main/res/layout/toast.xml | 3 +- app/src/main/res/values/dimen.xml | 1 + app/src/main/res/values/strings.xml | 16 +- 8 files changed, 205 insertions(+), 22 deletions(-) diff --git a/app/src/main/assets/linphonerc_factory b/app/src/main/assets/linphonerc_factory index 6961f344f..85b543074 100644 --- a/app/src/main/assets/linphonerc_factory +++ b/app/src/main/assets/linphonerc_factory @@ -57,4 +57,9 @@ lime_update_threshold=86400 [alerts] alerts_enabled=1 +[assistant] +algorithm=SHA-256 +password_min_length=6 +username_regex=^[a-z0-9+_.\-]*$ + ## End of factory rc diff --git a/app/src/main/java/org/linphone/ui/assistant/fragment/RegisterFragment.kt b/app/src/main/java/org/linphone/ui/assistant/fragment/RegisterFragment.kt index c6b3b81b9..13dbd25c7 100644 --- a/app/src/main/java/org/linphone/ui/assistant/fragment/RegisterFragment.kt +++ b/app/src/main/java/org/linphone/ui/assistant/fragment/RegisterFragment.kt @@ -38,6 +38,7 @@ import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R import org.linphone.core.tools.Log import org.linphone.databinding.AssistantRegisterFragmentBinding +import org.linphone.ui.assistant.AssistantActivity import org.linphone.ui.assistant.model.ConfirmPhoneNumberDialogModel import org.linphone.ui.assistant.viewmodel.AccountCreationViewModel import org.linphone.utils.DialogUtils @@ -137,6 +138,15 @@ class RegisterFragment : Fragment() { } } + viewModel.errorHappenedEvent.observe(viewLifecycleOwner) { + it.consume { error -> + (requireActivity() as AssistantActivity).showRedToast( + error, + R.drawable.warning_circle + ) + } + } + coreContext.postOnCoreThread { val prefix = PhoneNumberUtils.getDeviceInternationalPrefix(requireContext()) if (!prefix.isNullOrEmpty()) { diff --git a/app/src/main/java/org/linphone/ui/assistant/viewmodel/AccountCreationViewModel.kt b/app/src/main/java/org/linphone/ui/assistant/viewmodel/AccountCreationViewModel.kt index ffe3d21f9..f040822cc 100644 --- a/app/src/main/java/org/linphone/ui/assistant/viewmodel/AccountCreationViewModel.kt +++ b/app/src/main/java/org/linphone/ui/assistant/viewmodel/AccountCreationViewModel.kt @@ -36,6 +36,8 @@ import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R import org.linphone.core.AccountCreator +import org.linphone.core.AccountCreator.PhoneNumberStatus +import org.linphone.core.AccountCreator.UsernameStatus import org.linphone.core.AccountCreatorListenerStub import org.linphone.core.Core import org.linphone.core.CoreListenerStub @@ -56,6 +58,8 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic val password = MutableLiveData() + val passwordError = MutableLiveData() + val phoneNumber = MutableLiveData() val phoneNumberError = MutableLiveData() @@ -81,6 +85,10 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic val goToLoginPageEvent = MutableLiveData>() + val errorHappenedEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + private var waitingForFlexiApiPushToken = false private var waitForPushJob: Job? = null @@ -113,8 +121,12 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic Log.e("$TAG An unexpected error occurred!") operationInProgress.postValue(false) createEnabled.postValue(false) - // TODO FIXME: use translated string - phoneNumberError.postValue(status.name) + + phoneNumberError.postValue( + AppUtils.getString( + R.string.assistant_account_register_invalid_phone_number_error + ) + ) } } } @@ -144,8 +156,12 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic Log.e("$TAG An unexpected error occurred!") operationInProgress.postValue(false) createEnabled.postValue(false) - // TODO FIXME: use translated string - phoneNumberError.postValue(status.name) + + phoneNumberError.postValue( + AppUtils.getString( + R.string.assistant_account_register_invalid_phone_number_error + ) + ) } } } @@ -166,7 +182,14 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic } else -> { Log.e("$TAG Account couldn't be created, an unexpected error occurred!") - // TODO: show error message to user + errorHappenedEvent.postValue( + Event( + AppUtils.getFormattedString( + R.string.assistant_account_register_server_error, + status.toInt() + ) + ) + ) } } } @@ -185,7 +208,14 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic goToLoginPageEvent.postValue(Event(true)) } else { Log.e("$TAG Account couldn't be activated, an unexpected error occurred!") - // TODO: show error message to user + errorHappenedEvent.postValue( + Event( + AppUtils.getFormattedString( + R.string.assistant_account_register_server_error, + status.toInt() + ) + ) + ) } } } @@ -282,6 +312,7 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic @UiThread fun confirmPhoneNumber() { + operationInProgress.value = true coreContext.postOnCoreThread { if (::accountCreator.isInitialized) { val prefix = internationalPrefix.value.orEmpty().trim() @@ -293,7 +324,8 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic val number = phoneNumber.value.orEmpty().trim() val status = accountCreator.setPhoneNumber(number, digitsPrefix) - if (status == AccountCreator.PhoneNumberStatus.Ok.toInt()) { + Log.i("$TAG setPhoneNumber returned $status") + if (status == PhoneNumberStatus.Ok.toInt()) { val normalizedPhoneNumber = accountCreator.phoneNumber val message = coreContext.context.getString( @@ -322,14 +354,41 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic Log.e( "$TAG Failed to set phone number [$number] and prefix [$digitsPrefix] into account creator!" ) - val error = AppUtils.getString( - R.string.assistant_account_register_invalid_phone_number_error - ) + val error = when (status) { + PhoneNumberStatus.Invalid.toInt() -> { + AppUtils.getString( + R.string.assistant_account_register_invalid_phone_number_error + ) + } + PhoneNumberStatus.InvalidCountryCode.toInt() -> { + AppUtils.getString( + R.string.assistant_account_register_invalid_phone_number_international_prefix_error + ) + } + PhoneNumberStatus.TooLong.toInt() -> { + AppUtils.getString( + R.string.assistant_account_register_invalid_phone_number_too_long_error + ) + } + PhoneNumberStatus.TooShort.toInt() -> { + AppUtils.getString( + R.string.assistant_account_register_invalid_phone_number_too_short_error + ) + } + else -> { + AppUtils.getString( + R.string.assistant_account_register_invalid_phone_number_error + ) + } + } phoneNumberError.postValue(error) + operationInProgress.postValue(false) } } else { Log.e("$TAG Account creator hasn't been initialized!") - // TODO: show error message to user + errorHappenedEvent.postValue( + Event(AppUtils.getString(R.string.assistant_account_register_unexpected_error)) + ) } } } @@ -373,7 +432,14 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic if (status != AccountCreator.Status.RequestOk) { Log.e("$TAG Can't activate account [$status]") operationInProgress.postValue(false) - // TODO: show error message to user + errorHappenedEvent.postValue( + Event( + AppUtils.getFormattedString( + R.string.assistant_account_register_server_error, + status.toInt() + ) + ) + ) } } } @@ -383,7 +449,30 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic operationInProgress.postValue(true) usernameError.postValue("") - accountCreator.username = username.value.orEmpty().trim() + val usernameStatus = accountCreator.setUsername(username.value.orEmpty().trim()) + Log.i("$TAG setUsername returned $usernameStatus") + if (usernameStatus != UsernameStatus.Ok) { + val error = when (usernameStatus) { + UsernameStatus.InvalidCharacters, UsernameStatus.Invalid -> { + AppUtils.getString( + R.string.assistant_account_register_username_invalid_characters_error + ) + } + UsernameStatus.TooShort -> { + AppUtils.getString(R.string.assistant_account_register_username_too_short_error) + } + UsernameStatus.TooLong -> { + AppUtils.getString(R.string.assistant_account_register_username_too_long_error) + } + else -> { + AppUtils.getString(R.string.assistant_account_register_username_error) + } + } + usernameError.postValue(error) + operationInProgress.postValue(false) + return + } + accountCreator.domain = corePreferences.defaultDomain val status = accountCreator.isAccountExist @@ -391,7 +480,14 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic if (status != AccountCreator.Status.RequestOk) { Log.e("$TAG Can't check if account already exists [$status]") operationInProgress.postValue(false) - // TODO: show error message to user + errorHappenedEvent.postValue( + Event( + AppUtils.getFormattedString( + R.string.assistant_account_register_server_error, + status.toInt() + ) + ) + ) } } @@ -404,7 +500,14 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic if (status != AccountCreator.Status.RequestOk) { Log.e("$TAG Can't check if phone number is already used [$status]") operationInProgress.postValue(false) - // TODO: show error message to user + errorHappenedEvent.postValue( + Event( + AppUtils.getFormattedString( + R.string.assistant_account_register_server_error, + status.toInt() + ) + ) + ) } } @@ -412,14 +515,42 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic private fun createAccount() { operationInProgress.postValue(true) - accountCreator.password = password.value.orEmpty().trim() - val status = accountCreator.createAccount() + val passwordStatus = accountCreator.setPassword(password.value.orEmpty().trim()) + Log.i("$TAG setPassword returned $passwordStatus") + if (passwordStatus != AccountCreator.PasswordStatus.Ok) { + val error = when (passwordStatus) { + AccountCreator.PasswordStatus.InvalidCharacters -> { + AppUtils.getString( + R.string.assistant_account_register_password_invalid_characters_error + ) + } + AccountCreator.PasswordStatus.TooShort -> { + AppUtils.getString(R.string.assistant_account_register_password_too_short) + } + AccountCreator.PasswordStatus.TooLong -> { + AppUtils.getString(R.string.assistant_account_register_password_too_long_error) + } + else -> { + AppUtils.getString(R.string.assistant_account_register_invalid_password_error) + } + } + passwordError.postValue(error) + operationInProgress.postValue(false) + } + val status = accountCreator.createAccount() Log.i("$TAG createAccount returned $status") if (status != AccountCreator.Status.RequestOk) { Log.e("$TAG Can't create account [$status]") operationInProgress.postValue(false) - // TODO: show error message to user + errorHappenedEvent.postValue( + Event( + AppUtils.getFormattedString( + R.string.assistant_account_register_server_error, + status.toInt() + ) + ) + ) } else { Log.i("$TAG createAccount consumed our token, setting it to null") accountCreator.token = null @@ -481,6 +612,12 @@ class AccountCreationViewModel @UiThread constructor() : ViewModel(), CountryPic private fun onFlexiApiTokenRequestError() { Log.e("$TAG Flexi API token request by push error!") operationInProgress.postValue(false) - // TODO: show error message to user + errorHappenedEvent.postValue( + Event( + AppUtils.getString( + R.string.assistant_account_register_push_notification_not_received_error + ) + ) + ) } } diff --git a/app/src/main/java/org/linphone/ui/assistant/viewmodel/ThirdPartySipAccountLoginViewModel.kt b/app/src/main/java/org/linphone/ui/assistant/viewmodel/ThirdPartySipAccountLoginViewModel.kt index 0134878a0..ac148db4d 100644 --- a/app/src/main/java/org/linphone/ui/assistant/viewmodel/ThirdPartySipAccountLoginViewModel.kt +++ b/app/src/main/java/org/linphone/ui/assistant/viewmodel/ThirdPartySipAccountLoginViewModel.kt @@ -118,10 +118,12 @@ class ThirdPartySipAccountLoginViewModel @UiThread constructor() : ViewModel() { loginEnabled.value = isLoginButtonEnabled() } + // TODO: handle formatting errors + availableTransports.add(UDP) availableTransports.add(TCP) availableTransports.add(TLS) - transport.value = UDP + transport.value = TLS } @UiThread diff --git a/app/src/main/res/layout/assistant_register_fragment.xml b/app/src/main/res/layout/assistant_register_fragment.xml index e4eae8322..01637e735 100644 --- a/app/src/main/res/layout/assistant_register_fragment.xml +++ b/app/src/main/res/layout/assistant_register_fragment.xml @@ -213,6 +213,19 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/> + + 20dp 400dp + 300dp 400dp 400dp 400dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 94d1cde2e..811ec3df7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -113,8 +113,22 @@ Interoperable Continue This account already exists + Invalid characters: capital letters and special characters are not allowed + Username is too short + Username is too long + Unexpected username error Phone number already used - Invalid phone number and/or prefix + Invalid phone number + Phone number is too long + Phone number is too short + Unexpected phone number error + Invalid characters + Password is too short + Password is too long + Unexpected password error + Failed to create account, error %i + Push notification with auth token not received in 5 seconds, please try again later + Unexpected error occurred, please try again later Manage the profile Connected