1
0
mirror of https://github.com/wulkanowy/wulkanowy.git synced 2025-01-19 00:26:45 -06:00

Replace view pager in login activity with simple fragment transactions (#1686)

This commit is contained in:
Mikołaj Pich 2021-12-27 07:58:57 +01:00 committed by GitHub
parent 8560fd7e81
commit 2eee50ad81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 186 additions and 318 deletions

View File

@ -4,18 +4,19 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.MenuItem
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.databinding.ActivityLoginBinding
import io.github.wulkanowy.ui.base.BaseActivity
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
import io.github.wulkanowy.ui.modules.login.advanced.LoginAdvancedFragment
import io.github.wulkanowy.ui.modules.login.form.LoginFormFragment
import io.github.wulkanowy.ui.modules.login.recover.LoginRecoverFragment
import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment
import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
import io.github.wulkanowy.utils.UpdateHelper
import io.github.wulkanowy.utils.setOnSelectPageListener
import javax.inject.Inject
@AndroidEntryPoint
@ -24,21 +25,10 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
@Inject
override lateinit var presenter: LoginPresenter
private val pagerAdapter by lazy {
BaseFragmentPagerAdapter(
fragmentManager = supportFragmentManager,
pagesCount = 5,
lifecycle = lifecycle,
)
}
@Inject
lateinit var updateHelper: UpdateHelper
override val currentViewIndex get() = binding.loginViewpager.currentItem
companion object {
fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java)
}
@ -51,6 +41,50 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
presenter.onAttachView(this)
updateHelper.checkAndInstallUpdates(this)
if (savedInstanceState == null) {
openFragment(LoginFormFragment.newInstance(), clearBackStack = true)
}
}
override fun initView() {
with(requireNotNull(supportActionBar)) {
setDisplayHomeAsUpEnabled(true)
setDisplayShowTitleEnabled(false)
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) onBackPressed()
return true
}
fun showActionBar(show: Boolean) {
supportActionBar?.run { if (show) show() else hide() }
}
fun navigateToSymbolFragment(loginData: LoginData) {
openFragment(LoginSymbolFragment.newInstance(loginData))
}
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
openFragment(LoginStudentSelectFragment.newInstance(studentsWithSemesters))
}
fun onAdvancedLoginClick() {
openFragment(LoginAdvancedFragment.newInstance())
}
fun onRecoverClick() {
openFragment(LoginRecoverFragment.newInstance())
}
private fun openFragment(fragment: Fragment, clearBackStack: Boolean = false) {
supportFragmentManager.commit {
replace(R.id.loginContainer, fragment)
setReorderingAllowed(true)
if (!clearBackStack) addToBackStack(fragment::class.java.name)
}
}
override fun onResume() {
@ -64,78 +98,4 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
super.onActivityResult(requestCode, resultCode, data)
updateHelper.onActivityResult(requestCode, resultCode)
}
override fun initView() {
with(requireNotNull(supportActionBar)) {
setDisplayHomeAsUpEnabled(true)
setDisplayShowTitleEnabled(false)
}
with(binding.loginViewpager) {
adapter = pagerAdapter
isUserInputEnabled = false
offscreenPageLimit = 2
setOnSelectPageListener(presenter::onViewSelected)
}
with(pagerAdapter) {
containerId = binding.loginViewpager.id
itemFactory = {
when (it) {
0 -> LoginFormFragment.newInstance()
1 -> LoginSymbolFragment.newInstance()
2 -> LoginStudentSelectFragment.newInstance()
3 -> LoginAdvancedFragment.newInstance()
4 -> LoginRecoverFragment.newInstance()
else -> throw IllegalStateException()
}
}
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) onBackPressed()
return true
}
override fun switchView(index: Int) {
binding.loginViewpager.setCurrentItem(index, false)
}
override fun showActionBar(show: Boolean) {
supportActionBar?.run { if (show) show() else hide() }
}
override fun onBackPressed() {
presenter.onBackPressed { super.onBackPressed() }
}
override fun notifyInitSymbolFragment(loginData: Triple<String, String, String>) {
(pagerAdapter.getFragmentInstance(1) as? LoginSymbolFragment)
?.onParentInitSymbolFragment(loginData)
}
override fun notifyInitStudentSelectFragment(studentsWithSemesters: List<StudentWithSemesters>) {
(pagerAdapter.getFragmentInstance(2) as? LoginStudentSelectFragment)
?.onParentInitStudentSelectFragment(studentsWithSemesters)
}
fun onFormFragmentAccountLogged(
studentsWithSemesters: List<StudentWithSemesters>,
loginData: Triple<String, String, String>
) {
presenter.onFormViewAccountLogged(studentsWithSemesters, loginData)
}
fun onSymbolFragmentAccountLogged(studentsWithSemesters: List<StudentWithSemesters>) {
presenter.onSymbolViewAccountLogged(studentsWithSemesters)
}
fun onAdvancedLoginClick() {
presenter.onAdvancedLoginClick()
}
fun onRecoverClick() {
presenter.onRecoverClick()
}
}

View File

@ -0,0 +1,9 @@
package io.github.wulkanowy.ui.modules.login
import java.io.Serializable
data class LoginData(
val login: String,
val password: String,
val baseUrl: String,
) : Serializable

View File

@ -12,8 +12,9 @@ import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException
import io.github.wulkanowy.ui.base.ErrorHandler
import javax.inject.Inject
class LoginErrorHandler @Inject constructor(@ApplicationContext context: Context) :
ErrorHandler(context) {
class LoginErrorHandler @Inject constructor(
@ApplicationContext context: Context,
) : ErrorHandler(context) {
var onBadCredentials: (String?) -> Unit = {}

View File

@ -1,6 +1,5 @@
package io.github.wulkanowy.ui.modules.login
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
@ -14,59 +13,7 @@ class LoginPresenter @Inject constructor(
override fun onAttachView(view: LoginView) {
super.onAttachView(view)
with(view) {
initView()
showActionBar(false)
}
view.initView()
Timber.i("Login view was initialized")
}
fun onFormViewAccountLogged(studentsWithSemesters: List<StudentWithSemesters>, loginData: Triple<String, String, String>) {
view?.apply {
if (studentsWithSemesters.isEmpty()) {
Timber.i("Switch to symbol form")
notifyInitSymbolFragment(loginData)
switchView(1)
} else {
Timber.i("Switch to student select")
notifyInitStudentSelectFragment(studentsWithSemesters)
switchView(2)
}
}
}
fun onSymbolViewAccountLogged(studentsWithSemesters: List<StudentWithSemesters>) {
view?.apply {
Timber.i("Switch to student select")
notifyInitStudentSelectFragment(studentsWithSemesters)
switchView(2)
}
}
fun onAdvancedLoginClick() {
view?.switchView(3)
}
fun onRecoverClick() {
view?.switchView(4)
}
fun onViewSelected(index: Int) {
view?.apply {
when (index) {
0 -> showActionBar(false)
1, 2, 3, 4 -> showActionBar(true)
}
}
}
fun onBackPressed(default: () -> Unit) {
Timber.i("Back pressed in login view")
view?.apply {
when (currentViewIndex) {
1, 2, 3, 4 -> switchView(0)
else -> default()
}
}
}
}

View File

@ -1,19 +1,8 @@
package io.github.wulkanowy.ui.modules.login
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.ui.base.BaseView
interface LoginView : BaseView {
val currentViewIndex: Int
fun initView()
fun switchView(index: Int)
fun showActionBar(show: Boolean)
fun notifyInitSymbolFragment(loginData: Triple<String, String, String>)
fun notifyInitStudentSelectFragment(studentsWithSemesters: List<StudentWithSemesters>)
}

View File

@ -13,6 +13,7 @@ import io.github.wulkanowy.databinding.FragmentLoginAdvancedBinding
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.ui.modules.login.LoginData
import io.github.wulkanowy.ui.modules.login.form.LoginSymbolAdapter
import io.github.wulkanowy.utils.hideSoftInput
import io.github.wulkanowy.utils.setOnEditorDoneSignIn
@ -80,6 +81,8 @@ class LoginAdvancedFragment :
}
override fun initView() {
(requireActivity() as LoginActivity).showActionBar(true)
hostKeys = resources.getStringArray(R.array.hosts_keys)
hostValues = resources.getStringArray(R.array.hosts_values)
hostSymbols = resources.getStringArray(R.array.hosts_symbols)
@ -320,14 +323,12 @@ class LoginAdvancedFragment :
binding.loginFormContainer.visibility = if (show) VISIBLE else GONE
}
override fun notifyParentAccountLogged(studentsWithSemesters: List<StudentWithSemesters>) {
(activity as? LoginActivity)?.onFormFragmentAccountLogged(
studentsWithSemesters, Triple(
binding.loginFormUsername.text.toString(),
binding.loginFormPass.text.toString(),
resources.getStringArray(R.array.hosts_values)[1]
)
)
override fun navigateToSymbol(loginData: LoginData) {
(activity as? LoginActivity)?.navigateToSymbolFragment(loginData)
}
override fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
(activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters)
}
override fun onResume() {

View File

@ -5,6 +5,7 @@ import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginData
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
@ -77,7 +78,9 @@ class LoginAdvancedPresenter @Inject constructor(
clearPassError()
clearUsernameError()
if (formHostValue.contains("fakelog")) {
setDefaultCredentials("jan@fakelog.cf", "jan123", "powiatwulkanowy", "FK100000", "999999")
setDefaultCredentials(
"jan@fakelog.cf", "jan123", "powiatwulkanowy", "FK100000", "999999"
)
}
setSymbol(formHostSymbol)
updateUsernameLabel()
@ -136,12 +139,21 @@ class LoginAdvancedPresenter @Inject constructor(
}
Status.SUCCESS -> {
Timber.i("Login result: Success")
analytics.logEvent("registration_form",
analytics.logEvent(
"registration_form",
"success" to true,
"students" to it.data!!.size,
"error" to "No error"
)
view?.notifyParentAccountLogged(it.data)
val loginData = LoginData(
login = view?.formUsernameValue.orEmpty().trim(),
password = view?.formPassValue.orEmpty().trim(),
baseUrl = view?.formHostValue.orEmpty().trim()
)
when (it.data.size) {
0 -> view?.navigateToSymbol(loginData)
else -> view?.navigateToStudentSelect(it.data)
}
}
Status.ERROR -> {
Timber.i("Login result: An exception occurred")
@ -172,8 +184,12 @@ class LoginAdvancedPresenter @Inject constructor(
return when (Sdk.Mode.valueOf(view?.formLoginType.orEmpty())) {
Sdk.Mode.API -> studentRepository.getStudentsApi(pin, symbol, token)
Sdk.Mode.SCRAPPER -> studentRepository.getStudentsScrapper(email, password, endpoint, symbol)
Sdk.Mode.HYBRID -> studentRepository.getStudentsHybrid(email, password, endpoint, symbol)
Sdk.Mode.SCRAPPER -> studentRepository.getStudentsScrapper(
email, password, endpoint, symbol
)
Sdk.Mode.HYBRID -> studentRepository.getStudentsHybrid(
email, password, endpoint, symbol
)
}
}

View File

@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.login.advanced
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.ui.base.BaseView
import io.github.wulkanowy.ui.modules.login.LoginData
interface LoginAdvancedView : BaseView {
@ -69,7 +70,9 @@ interface LoginAdvancedView : BaseView {
fun showContent(show: Boolean)
fun notifyParentAccountLogged(studentsWithSemesters: List<StudentWithSemesters>)
fun navigateToSymbol(loginData: LoginData)
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>)
fun setErrorPinRequired()

View File

@ -13,6 +13,7 @@ import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.databinding.FragmentLoginFormBinding
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.ui.modules.login.LoginData
import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.hideSoftInput
import io.github.wulkanowy.utils.openEmailClient
@ -68,6 +69,8 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
}
override fun initView() {
(requireActivity() as LoginActivity).showActionBar(false)
hostKeys = resources.getStringArray(R.array.hosts_keys)
hostValues = resources.getStringArray(R.array.hosts_values)
hostSymbols = resources.getStringArray(R.array.hosts_symbols)
@ -203,11 +206,9 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
binding.loginFormVersion.text = "v${appInfo.versionName}"
}
override fun notifyParentAccountLogged(
studentsWithSemesters: List<StudentWithSemesters>,
loginData: Triple<String, String, String>
) {
(activity as? LoginActivity)?.onFormFragmentAccountLogged(studentsWithSemesters, loginData)
override fun showContact(show: Boolean) {
binding.loginFormContact.visibility = if (show) VISIBLE else GONE
binding.loginFormRecoverLink.visibility = if (show) GONE else VISIBLE
}
override fun openPrivacyPolicyPage() {
@ -217,9 +218,12 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
)
}
override fun showContact(show: Boolean) {
binding.loginFormContact.visibility = if (show) VISIBLE else GONE
binding.loginFormRecoverLink.visibility = if (show) GONE else VISIBLE
override fun navigateToSymbol(loginData: LoginData) {
(activity as? LoginActivity)?.navigateToSymbolFragment(loginData)
}
override fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
(activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters)
}
override fun openAdvancedLogin() {

View File

@ -4,6 +4,7 @@ import androidx.core.net.toUri
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginData
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
@ -118,7 +119,10 @@ class LoginFormPresenter @Inject constructor(
"scrapperBaseUrl" to host,
"error" to "No error"
)
view?.notifyParentAccountLogged(it.data, Triple(email, password, host))
when (it.data.size) {
0 -> view?.navigateToSymbol(LoginData(email, password, host))
else -> view?.navigateToStudentSelect(it.data)
}
}
Status.ERROR -> {
Timber.i("Login result: An exception occurred")

View File

@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.login.form
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.ui.base.BaseView
import io.github.wulkanowy.ui.modules.login.LoginData
interface LoginFormView : BaseView {
@ -57,7 +58,9 @@ interface LoginFormView : BaseView {
fun showVersion()
fun notifyParentAccountLogged(studentsWithSemesters: List<StudentWithSemesters>, loginData: Triple<String, String, String>)
fun navigateToSymbol(loginData: LoginData)
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>)
fun openPrivacyPolicyPage()

View File

@ -69,6 +69,8 @@ class LoginRecoverFragment :
}
override fun initView() {
(requireActivity() as LoginActivity).showActionBar(true)
hostKeys = resources.getStringArray(R.array.hosts_keys)
hostValues = resources.getStringArray(R.array.hosts_values)
hostSymbols = resources.getStringArray(R.array.hosts_symbols)
@ -80,7 +82,7 @@ class LoginRecoverFragment :
loginRecoverButton.setOnClickListener { presenter.onRecoverClick() }
loginRecoverErrorRetry.setOnClickListener { presenter.onRecoverClick() }
loginRecoverErrorDetails.setOnClickListener { presenter.onDetailsClick() }
loginRecoverLogin.setOnClickListener { (activity as LoginActivity).switchView(0) }
loginRecoverLogin.setOnClickListener { (activity as LoginActivity).onBackPressed() }
}
with(bindingLocal.loginRecoverHost) {

View File

@ -8,8 +8,9 @@ import io.github.wulkanowy.sdk.scrapper.exception.NoAccountFoundException
import io.github.wulkanowy.ui.base.ErrorHandler
import javax.inject.Inject
class RecoverErrorHandler @Inject constructor(@ApplicationContext context: Context) :
ErrorHandler(context) {
class RecoverErrorHandler @Inject constructor(
@ApplicationContext context: Context,
) : ErrorHandler(context) {
var onInvalidUsername: (String) -> Unit = {}

View File

@ -4,17 +4,18 @@ import android.os.Bundle
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
import androidx.core.os.bundleOf
import androidx.recyclerview.widget.LinearLayoutManager
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.databinding.FragmentLoginStudentSelectBinding
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.openEmailClient
import io.github.wulkanowy.utils.openInternetBrowser
import java.io.Serializable
import javax.inject.Inject
@AndroidEntryPoint
@ -32,18 +33,27 @@ class LoginStudentSelectFragment :
lateinit var appInfo: AppInfo
companion object {
const val SAVED_STUDENTS = "STUDENTS"
const val ARG_STUDENTS = "STUDENTS"
fun newInstance() = LoginStudentSelectFragment()
fun newInstance(studentsWithSemesters: List<StudentWithSemesters>) =
LoginStudentSelectFragment().apply {
arguments = bundleOf(ARG_STUDENTS to studentsWithSemesters)
}
}
@Suppress("UNCHECKED_CAST")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentLoginStudentSelectBinding.bind(view)
presenter.onAttachView(this, savedInstanceState?.getSerializable(SAVED_STUDENTS))
presenter.onAttachView(
view = this,
students = requireArguments().getSerializable(ARG_STUDENTS) as List<StudentWithSemesters>,
)
}
override fun initView() {
(requireActivity() as LoginActivity).showActionBar(true)
loginAdapter.onClickListener = presenter::onItemSelected
with(binding) {
@ -82,15 +92,6 @@ class LoginStudentSelectFragment :
binding.loginStudentSelectSignIn.isEnabled = enable
}
fun onParentInitStudentSelectFragment(studentsWithSemesters: List<StudentWithSemesters>) {
presenter.onParentInitStudentSelectView(studentsWithSemesters)
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putSerializable(SAVED_STUDENTS, presenter.students as Serializable)
}
override fun showContact(show: Boolean) {
binding.loginStudentSelectContact.visibility = if (show) VISIBLE else GONE
}

View File

@ -11,7 +11,6 @@ import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.ifNullOrBlank
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
import java.io.Serializable
import javax.inject.Inject
class LoginStudentSelectPresenter @Inject constructor(
@ -22,11 +21,9 @@ class LoginStudentSelectPresenter @Inject constructor(
private var lastError: Throwable? = null
var students = emptyList<StudentWithSemesters>()
private val selectedStudents = mutableListOf<StudentWithSemesters>()
fun onAttachView(view: LoginStudentSelectView, students: Serializable?) {
fun onAttachView(view: LoginStudentSelectView, students: List<StudentWithSemesters>) {
super.onAttachView(view)
with(view) {
initView()
@ -38,20 +35,14 @@ class LoginStudentSelectPresenter @Inject constructor(
}
}
if (students is List<*> && students.isNotEmpty()) {
loadData(students.filterIsInstance<StudentWithSemesters>())
}
if (students.size == 1) registerStudents(students)
loadData(students)
}
fun onSignIn() {
registerStudents(selectedStudents)
}
fun onParentInitStudentSelectView(studentsWithSemesters: List<StudentWithSemesters>) {
loadData(studentsWithSemesters)
if (studentsWithSemesters.size == 1) registerStudents(studentsWithSemesters)
}
fun onItemSelected(studentWithSemester: StudentWithSemesters, alreadySaved: Boolean) {
if (alreadySaved) return
@ -72,7 +63,6 @@ class LoginStudentSelectPresenter @Inject constructor(
private fun loadData(studentsWithSemesters: List<StudentWithSemesters>) {
resetSelectedState()
this.students = studentsWithSemesters
flowWithResource { studentRepository.getSavedStudents(false) }.onEach {
when (it.status) {
@ -143,7 +133,8 @@ class LoginStudentSelectPresenter @Inject constructor(
"success" to (error != null),
"scrapperBaseUrl" to student.student.scrapperBaseUrl,
"symbol" to student.student.symbol,
"error" to (error?.message?.ifBlank { "No message" } ?: "No error"))
"error" to (error?.message?.ifBlank { "No message" } ?: "No error")
)
}
}
}

View File

@ -7,6 +7,7 @@ import android.view.View.VISIBLE
import android.view.inputmethod.EditorInfo.IME_ACTION_DONE
import android.view.inputmethod.EditorInfo.IME_NULL
import android.widget.ArrayAdapter
import androidx.core.os.bundleOf
import androidx.core.text.parseAsHtml
import androidx.core.widget.doOnTextChanged
import dagger.hilt.android.AndroidEntryPoint
@ -15,6 +16,7 @@ import io.github.wulkanowy.data.db.entities.StudentWithSemesters
import io.github.wulkanowy.databinding.FragmentLoginSymbolBinding
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.ui.modules.login.LoginData
import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.hideSoftInput
import io.github.wulkanowy.utils.openEmailClient
@ -35,7 +37,9 @@ class LoginSymbolFragment :
companion object {
private const val SAVED_LOGIN_DATA = "LOGIN_DATA"
fun newInstance() = LoginSymbolFragment()
fun newInstance(loginData: LoginData) = LoginSymbolFragment().apply {
arguments = bundleOf(SAVED_LOGIN_DATA to loginData)
}
}
override val symbolNameError: CharSequence?
@ -44,10 +48,15 @@ class LoginSymbolFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentLoginSymbolBinding.bind(view)
presenter.onAttachView(this, savedInstanceState?.getSerializable(SAVED_LOGIN_DATA))
presenter.onAttachView(
view = this,
loginData = requireArguments().getSerializable(SAVED_LOGIN_DATA) as LoginData,
)
}
override fun initView() {
(requireActivity() as LoginActivity).showActionBar(true)
with(binding) {
loginSymbolSignIn.setOnClickListener { presenter.attemptLogin(loginSymbolName.text.toString()) }
loginSymbolFaq.setOnClickListener { presenter.onFaqClick() }
@ -70,12 +79,9 @@ class LoginSymbolFragment :
}
}
fun onParentInitSymbolFragment(loginData: Triple<String, String, String>) {
presenter.onParentInitSymbolView(loginData)
}
override fun setLoginToHeading(login: String) {
binding.loginSymbolHeader.text = getString(R.string.login_header_symbol, login).parseAsHtml()
binding.loginSymbolHeader.text =
getString(R.string.login_header_symbol, login).parseAsHtml()
}
override fun setErrorSymbolIncorrect() {
@ -119,8 +125,8 @@ class LoginSymbolFragment :
binding.loginSymbolContainer.visibility = if (show) VISIBLE else GONE
}
override fun notifyParentAccountLogged(studentsWithSemesters: List<StudentWithSemesters>) {
(activity as? LoginActivity)?.onSymbolFragmentAccountLogged(studentsWithSemesters)
override fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
(activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters)
}
override fun onSaveInstanceState(outState: Bundle) {

View File

@ -3,6 +3,7 @@ package io.github.wulkanowy.ui.modules.login.symbol
import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.modules.login.LoginData
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.afterLoading
@ -10,7 +11,6 @@ import io.github.wulkanowy.utils.flowWithResource
import io.github.wulkanowy.utils.ifNullOrBlank
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
import java.io.Serializable
import javax.inject.Inject
class LoginSymbolPresenter @Inject constructor(
@ -21,25 +21,15 @@ class LoginSymbolPresenter @Inject constructor(
private var lastError: Throwable? = null
var loginData: Triple<String, String, String>? = null
lateinit var loginData: LoginData
@Suppress("UNCHECKED_CAST")
fun onAttachView(view: LoginSymbolView, savedLoginData: Serializable?) {
fun onAttachView(view: LoginSymbolView, loginData: LoginData) {
super.onAttachView(view)
view.run {
this.loginData = loginData
with(view) {
initView()
showContact(false)
}
if (savedLoginData is Triple<*, *, *>) {
loginData = savedLoginData as Triple<String, String, String>
view.setLoginToHeading(requireNotNull(loginData?.first))
}
}
fun onParentInitSymbolView(loginData: Triple<String, String, String>) {
this.loginData = loginData
view?.apply {
setLoginToHeading(loginData.first)
setLoginToHeading(loginData.login)
clearAndFocusSymbol()
showSoftKeyboard()
}
@ -50,11 +40,6 @@ class LoginSymbolPresenter @Inject constructor(
}
fun attemptLogin(symbol: String) {
if (loginData == null) {
Timber.w("LoginSymbolPresenter - Login data is null")
return
}
if (symbol.isBlank()) {
view?.setErrorSymbolRequire()
return
@ -62,9 +47,9 @@ class LoginSymbolPresenter @Inject constructor(
flowWithResource {
studentRepository.getStudentsScrapper(
email = loginData!!.first,
password = loginData!!.second,
scrapperBaseUrl = loginData!!.third,
email = loginData.login,
password = loginData.password,
scrapperBaseUrl = loginData.baseUrl,
symbol = symbol,
)
}.onEach {
@ -76,21 +61,24 @@ class LoginSymbolPresenter @Inject constructor(
showContent(false)
}
Status.SUCCESS -> {
view?.run {
if (it.data!!.isEmpty()) {
when (it.data?.size) {
0 -> {
Timber.i("Login with symbol result: Empty student list")
setErrorSymbolIncorrect()
view?.showContact(true)
} else {
view?.run {
setErrorSymbolIncorrect()
showContact(true)
}
}
else -> {
Timber.i("Login with symbol result: Success")
notifyParentAccountLogged(it.data)
view?.navigateToStudentSelect(requireNotNull(it.data))
}
}
analytics.logEvent(
"registration_symbol",
"success" to true,
"students" to it.data!!.size,
"scrapperBaseUrl" to loginData?.third,
"scrapperBaseUrl" to loginData.baseUrl,
"symbol" to symbol,
"error" to "No error"
)
@ -101,7 +89,7 @@ class LoginSymbolPresenter @Inject constructor(
"registration_symbol",
"success" to false,
"students" to -1,
"scrapperBaseUrl" to loginData?.third,
"scrapperBaseUrl" to loginData.baseUrl,
"symbol" to symbol,
"error" to it.error!!.message.ifNullOrBlank { "No message" }
)
@ -123,6 +111,6 @@ class LoginSymbolPresenter @Inject constructor(
}
fun onEmailClick() {
view?.openEmail(loginData?.third.orEmpty(), lastError?.message.ifNullOrBlank { "empty" })
view?.openEmail(loginData.baseUrl, lastError?.message.ifNullOrBlank { "empty" })
}
}

View File

@ -27,7 +27,7 @@ interface LoginSymbolView : BaseView {
fun showContent(show: Boolean)
fun notifyParentAccountLogged(studentsWithSemesters: List<StudentWithSemesters>)
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>)
fun showContact(show: Boolean)

View File

@ -4,7 +4,6 @@ import android.content.SharedPreferences
import android.os.Bundle
import android.view.View
import androidx.preference.PreferenceFragmentCompat
import com.yariksoffice.lingver.Lingver
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseActivity
@ -24,9 +23,6 @@ class AdvancedFragment : PreferenceFragmentCompat(),
@Inject
lateinit var appInfo: AppInfo
@Inject
lateinit var lingver: Lingver
override val titleStringId get() = R.string.pref_settings_advanced_title
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View File

@ -1,5 +1,5 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/loginContainer"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@ -10,8 +10,11 @@
android:layout_height="wrap_content"
android:background="@android:color/transparent" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/loginViewpager"
<androidx.fragment.app.FragmentContainerView
android:id="@+id/loginContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="0dp"
android:layout_weight="1"
tools:layout="@layout/fragment_login_form" />
</LinearLayout>

View File

@ -155,7 +155,7 @@
android:orientation="vertical"
android:visibility="invisible"
tools:ignore="UseCompoundDrawables"
tools:visibility="visible">
tools:visibility="gone">
<ImageView
android:layout_width="100dp"

View File

@ -1,57 +0,0 @@
package io.github.wulkanowy.ui.modules.login
import io.github.wulkanowy.data.repositories.StudentRepository
import io.mockk.MockKAnnotations
import io.mockk.clearMocks
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.verify
import org.junit.Assert.assertNotEquals
import org.junit.Before
import org.junit.Test
class LoginPresenterTest {
@MockK(relaxed = true)
lateinit var loginView: LoginView
@MockK(relaxed = true)
lateinit var errorHandler: LoginErrorHandler
@MockK
lateinit var studentRepository: StudentRepository
private lateinit var presenter: LoginPresenter
@Before
fun initPresenter() {
MockKAnnotations.init(this)
clearMocks(loginView)
presenter = LoginPresenter(errorHandler, studentRepository)
presenter.onAttachView(loginView)
}
@Test
fun initViewTest() {
verify { loginView.initView() }
verify { loginView.showActionBar(false) }
}
@Test
fun onBackPressedTest() {
clearMocks(loginView)
every { loginView.currentViewIndex } returns 1
presenter.onBackPressed { }
verify { loginView.switchView(0) }
}
@Test
fun onBackPressedDefaultTest() {
var i = 0
every { loginView.currentViewIndex } returns 0
presenter.onBackPressed { i++ }
assertNotEquals(0, i)
}
}

View File

@ -78,7 +78,7 @@ class LoginStudentSelectPresenterTest {
every { loginStudentSelectView.showContent(any()) } just Runs
presenter = LoginStudentSelectPresenter(studentRepository, errorHandler, analytics)
presenter.onAttachView(loginStudentSelectView, null)
presenter.onAttachView(loginStudentSelectView, emptyList())
}
@Test