Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Fragment
- class PhoneFragment : BaseFragment(R.layout.fragment_phone) {
- private val viewModel: PhoneViewModel by lazy { injectViewModel() }
- private val contextMenu: ContextMenuDialog by lazy { ContextMenuDialog() }
- override fun setupUI(v: View) {
- FragmentPhoneBinding.bind(v).apply {
- subtitle.startAnimation(root.context.setAnimationTextLeft())
- phoneET.apply {
- requestFocus()
- setOnFocusChangeListener { _, hasFocus ->
- if (hasFocus) {
- setupTextEditWatcher(this, false, PHONE_NUMBER_MASK, CODE_LENGTH) {
- viewModel.onSetPhoneNumber(it)
- updateEditText(it, edBackgroundInput)
- }
- }
- }
- }
- menu.setOnClickListener {
- contextMenu.show(requireActivity().supportFragmentManager, DIALOG_MENU_TAG)
- }
- loginButton.setOnClickListener {
- viewModel.sendLoginCode(phoneET.text.toString())
- }
- lifecycleScope.launch {
- launch { viewModel.progress.collect { progressBar.showProgressBar(it) } }
- launch {
- viewModel.errors.collect { ex ->
- processingServerError(ex, requireActivity()) { }
- }
- }
- launch { viewModel.watchButtonState.collect { renderButton(it, this@apply) } }
- launch {
- viewModel
- .watchPhoneNumberSending
- .filter { status -> status == PhoneStatusType.SUCCESS }
- .combine(viewModel.watchPhoneNumber) { _, p -> p }
- .combine(viewModel.watchVerificationCode) { p, c -> p to c }
- .collect { (p, c) ->
- navigateTo(
- R.id.action_phoneFragment_to_codeFragment,
- bundleOf(
- KEY_PHONE_NUMBER to p,
- KEY_VERIFICATION_CODE to c
- )
- )
- }
- }
- }
- }
- }
- override fun setupObserver() { }
- private fun updateEditText(phone: String, backgroundInput: EditText) {
- val newHint = resources
- .getString(R.string.hint_background)
- .replaceRange(0, phone.length, phone)
- backgroundInput.hint = newHint
- }
- private fun renderButton(state: ButtonState, binding: FragmentPhoneBinding) {
- binding.apply {
- if (state != ButtonState.NeutralState) showFailedInput(
- state != ButtonState.DisabledState,
- root.context,
- phoneImageFail, false,
- tvPhone,
- resources.getString(R.string.phone_number),
- resources.getString(R.string.phone_number_fail)
- )
- loginButton.isEnabled = when (state) {
- ButtonState.NeutralState -> false
- ButtonState.DisabledState -> false
- ButtonState.EnabledState -> true
- }
- }
- }
- }
- //ViewModel
- class PhoneViewModel
- @Inject
- constructor(
- private val repository: LoginRepository
- ) : ViewModel() {
- // Watchers
- val progress: Flow<Int>
- get() = _progress
- val errors: Flow<Exception>
- get() = _errors
- val watchButtonState: Flow<ButtonState>
- get() = _buttonState
- val watchPhoneNumber: Flow<String>
- get() = _phoneNumber
- val watchVerificationCode: Flow<String>
- get() = _verificationCode
- val watchPhoneNumberSending: Flow<PhoneStatusType>
- get() = _phoneNumberSending
- // Flows
- private val _progress = MutableSharedFlow<Int>()
- private val _errors = MutableSharedFlow<Exception>()
- private val _buttonState = MutableStateFlow<ButtonState>(ButtonState.NeutralState)
- private val _phoneNumber = MutableSharedFlow<String>()
- private val _verificationCode = MutableSharedFlow<String>()
- private val _phoneNumberSending = MutableSharedFlow<PhoneStatusType>()
- // Properties
- private var counter = 0
- init {
- viewModelScope.launch {
- launch {
- _phoneNumber
- .filterNotNull()
- .collect { checkPhoneNumber(it) }
- }
- launch {
- _verificationCode
- .filterNotNull()
- .distinctUntilChanged()
- .collect { _phoneNumberSending.emit(PhoneStatusType.SUCCESS) }
- }
- }
- }
- // Flow setters
- fun onSetPhoneNumber(text: String) {
- viewModelScope.launch { _phoneNumber.emit(text) }
- }
- private fun onSetVerificationCode(code: String) {
- viewModelScope.launch { _verificationCode.emit(code) }
- }
- private suspend fun checkPhoneNumber(phone: String) {
- _buttonState.emit(
- when {
- phone.isEmpty() -> ButtonState.DisabledState
- phone.length == PHONE_HINT_LENGTH && containsPhoneSymbols(phone) ->
- ButtonState.EnabledState
- else -> ButtonState.DisabledState
- }
- )
- }
- fun sendLoginCode(phone: String) {
- viewModelScope.launch {
- counter += 1
- _progress.emit(counter)
- _buttonState.emit(ButtonState.NeutralState)
- when (val r = repository.getCode(createOtpModel(phone))) {
- is Left -> _errors.emit(r.value)
- is Right -> onSetVerificationCode(r.value.data.verificationCode)
- }
- counter -= 1
- _progress.emit(counter)
- }
- }
- private fun createOtpModel(phone: String) = OtpM(
- replacePhoneSymbols(phone),
- getDeviceId()
- )
- }
- //Extensions
- fun getDeviceId(): String = deviceId ?: UUID.randomUUID().toString()
- fun containsPhoneSymbols(phone: String): Boolean =
- replacePhoneSymbols(phone).length == UIUtility.PHONE_LENGTH
- fun replacePhoneSymbols(phone: String): String = phone.replace("[^0-9]".toRegex(), "")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement