TwoFAFragment.kt
package chat.rocket.android.authentication.twofactor.ui
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.authentication.twofactor.presentation.TwoFAPresenter
import chat.rocket.android.authentication.twofactor.presentation.TwoFAView
import chat.rocket.android.util.extension.asObservable
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.util.extensions.ui
import dagger.android.support.AndroidSupportInjection
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.fragment_authentication_two_fa.*
import javax.inject.Inject
fun newInstance(username: String, password: String): Fragment = TwoFAFragment().apply {
arguments = Bundle(2).apply {
putString(BUNDLE_USERNAME, username)
putString(BUNDLE_PASSWORD, password)
}
}
private const val BUNDLE_USERNAME = "username"
private const val BUNDLE_PASSWORD = "password"
class TwoFAFragment : Fragment(), TwoFAView {
@Inject
lateinit var presenter: TwoFAPresenter
@Inject
lateinit var analyticsManager: AnalyticsManager
private lateinit var username: String
private lateinit var password: String
private lateinit var twoFaCodeDisposable: Disposable
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this)
arguments?.run {
username = getString(BUNDLE_USERNAME, "")
password = getString(BUNDLE_PASSWORD, "")
} ?: requireNotNull(arguments) { "no arguments supplied when the fragment was instantiated" }
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = container?.inflate(R.layout.fragment_authentication_two_fa)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
activity?.apply {
text_two_factor_authentication_code.requestFocus()
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(
text_two_factor_authentication_code,
InputMethodManager.RESULT_UNCHANGED_SHOWN
)
}
setupOnClickListener()
subscribeEditText()
analyticsManager.logScreenView(ScreenViewEvent.TwoFa)
}
override fun onDestroyView() {
super.onDestroyView()
unsubscribeEditText()
}
override fun enableButtonConfirm() {
context?.let {
ViewCompat.setBackgroundTintList(
button_confirm, ContextCompat.getColorStateList(it, R.color.colorAccent)
)
button_confirm.isEnabled = true
}
}
override fun disableButtonConfirm() {
context?.let {
ViewCompat.setBackgroundTintList(
button_confirm,
ContextCompat.getColorStateList(it, R.color.colorAuthenticationButtonDisabled)
)
button_confirm.isEnabled = false
}
}
override fun alertInvalidTwoFactorAuthenticationCode() =
showMessage(R.string.msg_invalid_2fa_code)
override fun showLoading() {
ui {
disableUserInput()
view_loading.isVisible = true
}
}
override fun hideLoading() {
ui {
view_loading.isVisible = false
enableUserInput()
}
}
override fun showMessage(resId: Int) {
ui {
showToast(resId)
}
}
override fun showMessage(message: String) {
ui {
showToast(message)
}
}
override fun showGenericErrorMessage() = showMessage(R.string.msg_generic_error)
private fun enableUserInput() {
enableButtonConfirm()
text_two_factor_authentication_code.isEnabled = true
}
private fun disableUserInput() {
disableButtonConfirm()
text_two_factor_authentication_code.isEnabled = false
}
private fun setupOnClickListener() {
button_confirm.setOnClickListener {
presenter.authenticate(
username,
password,
text_two_factor_authentication_code.textContent
)
}
}
private fun subscribeEditText() {
twoFaCodeDisposable = text_two_factor_authentication_code.asObservable()
.subscribe {
if (it.isNotBlank()) {
enableButtonConfirm()
} else {
disableButtonConfirm()
}
}
}
private fun unsubscribeEditText() = twoFaCodeDisposable.dispose()
}