forked from github/wulkanowy-mirror
Refactor student selection screen (#2087)
This commit is contained in:
parent
83974b6550
commit
897eac050a
@ -186,7 +186,7 @@ ext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "io.github.wulkanowy:sdk:1.8.3"
|
implementation "io.github.wulkanowy:sdk:a3b97edd48"
|
||||||
|
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.8'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.8'
|
||||||
|
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
package io.github.wulkanowy.data.mappers
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
|
import io.github.wulkanowy.data.pojos.*
|
||||||
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
|
import io.github.wulkanowy.sdk.mapper.mapSemesters
|
||||||
|
import java.time.Instant
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.register.RegisterStudent as SdkRegisterStudent
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.register.RegisterUser as SdkRegisterUser
|
||||||
|
|
||||||
|
fun SdkRegisterUser.mapToPojo(password: String) = RegisterUser(
|
||||||
|
email = email,
|
||||||
|
login = login,
|
||||||
|
password = password,
|
||||||
|
baseUrl = baseUrl,
|
||||||
|
loginType = loginType,
|
||||||
|
symbols = symbols.map { registerSymbol ->
|
||||||
|
RegisterSymbol(
|
||||||
|
symbol = registerSymbol.symbol,
|
||||||
|
error = registerSymbol.error,
|
||||||
|
userName = registerSymbol.userName,
|
||||||
|
schools = registerSymbol.schools.map {
|
||||||
|
RegisterUnit(
|
||||||
|
userLoginId = it.userLoginId,
|
||||||
|
schoolId = it.schoolId,
|
||||||
|
schoolName = it.schoolName,
|
||||||
|
schoolShortName = it.schoolShortName,
|
||||||
|
parentIds = it.parentIds,
|
||||||
|
studentIds = it.studentIds,
|
||||||
|
employeeIds = it.employeeIds,
|
||||||
|
error = it.error,
|
||||||
|
students = it.subjects
|
||||||
|
.filterIsInstance<SdkRegisterStudent>()
|
||||||
|
.map { registerSubject ->
|
||||||
|
RegisterStudent(
|
||||||
|
studentId = registerSubject.studentId,
|
||||||
|
studentName = registerSubject.studentName,
|
||||||
|
studentSecondName = registerSubject.studentSecondName,
|
||||||
|
studentSurname = registerSubject.studentSurname,
|
||||||
|
className = registerSubject.className,
|
||||||
|
classId = registerSubject.classId,
|
||||||
|
isParent = registerSubject.isParent,
|
||||||
|
semesters = registerSubject.semesters
|
||||||
|
.mapSemesters()
|
||||||
|
.mapToEntities(registerSubject.studentId),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
fun RegisterStudent.mapToStudentWithSemesters(
|
||||||
|
user: RegisterUser,
|
||||||
|
symbol: RegisterSymbol,
|
||||||
|
unit: RegisterUnit,
|
||||||
|
colors: List<Long>,
|
||||||
|
): StudentWithSemesters = StudentWithSemesters(
|
||||||
|
semesters = semesters,
|
||||||
|
student = Student(
|
||||||
|
email = user.login, // for compatibility
|
||||||
|
userName = symbol.userName,
|
||||||
|
userLoginId = unit.userLoginId,
|
||||||
|
isParent = isParent,
|
||||||
|
className = className,
|
||||||
|
classId = classId,
|
||||||
|
studentId = studentId,
|
||||||
|
symbol = symbol.symbol,
|
||||||
|
loginType = user.loginType.name,
|
||||||
|
schoolName = unit.schoolName,
|
||||||
|
schoolShortName = unit.schoolShortName,
|
||||||
|
schoolSymbol = unit.schoolId,
|
||||||
|
studentName = "$studentName $studentSurname",
|
||||||
|
loginMode = Sdk.Mode.SCRAPPER.name,
|
||||||
|
scrapperBaseUrl = user.baseUrl,
|
||||||
|
mobileBaseUrl = "",
|
||||||
|
certificateKey = "",
|
||||||
|
privateKey = "",
|
||||||
|
password = user.password,
|
||||||
|
isCurrent = false,
|
||||||
|
registrationDate = Instant.now(),
|
||||||
|
).apply {
|
||||||
|
avatarColor = colors.random()
|
||||||
|
},
|
||||||
|
)
|
@ -0,0 +1,43 @@
|
|||||||
|
package io.github.wulkanowy.data.pojos
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.Scrapper
|
||||||
|
|
||||||
|
data class RegisterUser(
|
||||||
|
val email: String,
|
||||||
|
val password: String,
|
||||||
|
val login: String, // may be the same as email
|
||||||
|
val baseUrl: String,
|
||||||
|
val loginType: Scrapper.LoginType,
|
||||||
|
val symbols: List<RegisterSymbol>,
|
||||||
|
) : java.io.Serializable
|
||||||
|
|
||||||
|
data class RegisterSymbol(
|
||||||
|
val symbol: String,
|
||||||
|
val error: Throwable?,
|
||||||
|
val userName: String,
|
||||||
|
val schools: List<RegisterUnit>,
|
||||||
|
) : java.io.Serializable
|
||||||
|
|
||||||
|
data class RegisterUnit(
|
||||||
|
val userLoginId: Int,
|
||||||
|
val schoolId: String,
|
||||||
|
val schoolName: String,
|
||||||
|
val schoolShortName: String,
|
||||||
|
val parentIds: List<Int>,
|
||||||
|
val studentIds: List<Int>,
|
||||||
|
val employeeIds: List<Int>,
|
||||||
|
val error: Throwable?,
|
||||||
|
val students: List<RegisterStudent>,
|
||||||
|
) : java.io.Serializable
|
||||||
|
|
||||||
|
data class RegisterStudent(
|
||||||
|
val studentId: Int,
|
||||||
|
val studentName: String,
|
||||||
|
val studentSecondName: String,
|
||||||
|
val studentSurname: String,
|
||||||
|
val className: String,
|
||||||
|
val classId: Int,
|
||||||
|
val isParent: Boolean,
|
||||||
|
val semesters: List<Semester>,
|
||||||
|
) : java.io.Serializable
|
@ -11,6 +11,8 @@ import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
|||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
|
import io.github.wulkanowy.data.mappers.mapToPojo
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import io.github.wulkanowy.utils.DispatchersProvider
|
import io.github.wulkanowy.utils.DispatchersProvider
|
||||||
@ -52,6 +54,14 @@ class StudentRepository @Inject constructor(
|
|||||||
sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol)
|
sdk.getStudentsFromScrapper(email, password, scrapperBaseUrl, symbol)
|
||||||
.mapToEntities(password, appInfo.defaultColorsForAvatar)
|
.mapToEntities(password, appInfo.defaultColorsForAvatar)
|
||||||
|
|
||||||
|
suspend fun getUserSubjectsFromScrapper(
|
||||||
|
email: String,
|
||||||
|
password: String,
|
||||||
|
scrapperBaseUrl: String,
|
||||||
|
symbol: String
|
||||||
|
): RegisterUser = sdk.getUserSubjectsFromScrapper(email, password, scrapperBaseUrl, symbol)
|
||||||
|
.mapToPojo(password)
|
||||||
|
|
||||||
suspend fun getStudentsHybrid(
|
suspend fun getStudentsHybrid(
|
||||||
email: String,
|
email: String,
|
||||||
password: String,
|
password: String,
|
||||||
|
@ -8,10 +8,11 @@ import android.os.Bundle
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE
|
||||||
import androidx.fragment.app.commit
|
import androidx.fragment.app.commit
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.databinding.ActivityLoginBinding
|
import io.github.wulkanowy.databinding.ActivityLoginBinding
|
||||||
import io.github.wulkanowy.ui.base.BaseActivity
|
import io.github.wulkanowy.ui.base.BaseActivity
|
||||||
import io.github.wulkanowy.ui.modules.login.advanced.LoginAdvancedFragment
|
import io.github.wulkanowy.ui.modules.login.advanced.LoginAdvancedFragment
|
||||||
@ -76,8 +77,8 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
|||||||
openFragment(LoginSymbolFragment.newInstance(loginData))
|
openFragment(LoginSymbolFragment.newInstance(loginData))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
|
fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) {
|
||||||
openFragment(LoginStudentSelectFragment.newInstance(studentsWithSemesters))
|
openFragment(LoginStudentSelectFragment.newInstance(loginData, registerUser))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun navigateToNotifications() {
|
fun navigateToNotifications() {
|
||||||
@ -105,6 +106,8 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun openFragment(fragment: Fragment, clearBackStack: Boolean = false) {
|
private fun openFragment(fragment: Fragment, clearBackStack: Boolean = false) {
|
||||||
|
supportFragmentManager.popBackStack(fragment::class.java.name, POP_BACK_STACK_INCLUSIVE)
|
||||||
|
|
||||||
supportFragmentManager.commit {
|
supportFragmentManager.commit {
|
||||||
replace(R.id.loginContainer, fragment)
|
replace(R.id.loginContainer, fragment)
|
||||||
setReorderingAllowed(true)
|
setReorderingAllowed(true)
|
||||||
|
@ -6,4 +6,5 @@ data class LoginData(
|
|||||||
val login: String,
|
val login: String,
|
||||||
val password: String,
|
val password: String,
|
||||||
val baseUrl: String,
|
val baseUrl: String,
|
||||||
|
val symbol: String?,
|
||||||
) : Serializable
|
) : Serializable
|
||||||
|
@ -8,7 +8,7 @@ import android.widget.ArrayAdapter
|
|||||||
import androidx.core.widget.doOnTextChanged
|
import androidx.core.widget.doOnTextChanged
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.databinding.FragmentLoginAdvancedBinding
|
import io.github.wulkanowy.databinding.FragmentLoginAdvancedBinding
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
@ -327,8 +327,8 @@ class LoginAdvancedFragment :
|
|||||||
(activity as? LoginActivity)?.navigateToSymbolFragment(loginData)
|
(activity as? LoginActivity)?.navigateToSymbolFragment(loginData)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
|
override fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) {
|
||||||
(activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters)
|
(activity as? LoginActivity)?.navigateToStudentSelect(loginData, registerUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
@ -4,9 +4,15 @@ import io.github.wulkanowy.data.Resource
|
|||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
import io.github.wulkanowy.data.logResourceStatus
|
import io.github.wulkanowy.data.logResourceStatus
|
||||||
import io.github.wulkanowy.data.onResourceNotLoading
|
import io.github.wulkanowy.data.onResourceNotLoading
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterStudent
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterSymbol
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterUnit
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||||
import io.github.wulkanowy.data.resourceFlow
|
import io.github.wulkanowy.data.resourceFlow
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.Scrapper
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.getNormalizedSymbol
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||||
@ -142,19 +148,23 @@ class LoginAdvancedPresenter @Inject constructor(
|
|||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
analytics.logEvent(
|
analytics.logEvent(
|
||||||
"registration_form",
|
"registration_form",
|
||||||
"success" to true,
|
"success" to true,
|
||||||
"students" to it.data.size,
|
"students" to it.data.size,
|
||||||
"error" to "No error"
|
"error" to "No error"
|
||||||
)
|
)
|
||||||
val loginData = LoginData(
|
val loginData = LoginData(
|
||||||
login = view?.formUsernameValue.orEmpty().trim(),
|
login = view?.formUsernameValue.orEmpty().trim(),
|
||||||
password = view?.formPassValue.orEmpty().trim(),
|
password = view?.formPassValue.orEmpty().trim(),
|
||||||
baseUrl = view?.formHostValue.orEmpty().trim()
|
baseUrl = view?.formHostValue.orEmpty().trim(),
|
||||||
)
|
symbol = view?.formSymbolValue.orEmpty().trim().getNormalizedSymbol(),
|
||||||
when (it.data.size) {
|
)
|
||||||
0 -> view?.navigateToSymbol(loginData)
|
when (it.data.size) {
|
||||||
else -> view?.navigateToStudentSelect(it.data)
|
0 -> view?.navigateToSymbol(loginData)
|
||||||
}
|
else -> view?.navigateToStudentSelect(
|
||||||
|
loginData = loginData,
|
||||||
|
registerUser = it.data.toRegisterUser(loginData),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is Resource.Error -> {
|
is Resource.Error -> {
|
||||||
analytics.logEvent(
|
analytics.logEvent(
|
||||||
@ -173,6 +183,58 @@ class LoginAdvancedPresenter @Inject constructor(
|
|||||||
}.launch("login")
|
}.launch("login")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun List<StudentWithSemesters>.toRegisterUser(loginData: LoginData) = RegisterUser(
|
||||||
|
email = loginData.login,
|
||||||
|
password = loginData.password,
|
||||||
|
login = loginData.login,
|
||||||
|
baseUrl = loginData.baseUrl,
|
||||||
|
loginType = firstOrNull()?.student?.loginType?.let(
|
||||||
|
Scrapper.LoginType::valueOf
|
||||||
|
) ?: Scrapper.LoginType.AUTO,
|
||||||
|
symbols = this
|
||||||
|
.groupBy { students -> students.student.symbol }
|
||||||
|
.map { (symbol, students) ->
|
||||||
|
RegisterSymbol(
|
||||||
|
symbol = symbol,
|
||||||
|
error = null,
|
||||||
|
userName = "",
|
||||||
|
schools = students
|
||||||
|
.groupBy { student ->
|
||||||
|
Triple(
|
||||||
|
first = student.student.schoolSymbol,
|
||||||
|
second = student.student.userLoginId,
|
||||||
|
third = student.student.schoolShortName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.map { (groupKey, students) ->
|
||||||
|
val (schoolId, loginId, schoolName) = groupKey
|
||||||
|
RegisterUnit(
|
||||||
|
students = students.map {
|
||||||
|
RegisterStudent(
|
||||||
|
studentId = it.student.studentId,
|
||||||
|
studentName = it.student.studentName,
|
||||||
|
studentSecondName = it.student.studentName,
|
||||||
|
studentSurname = it.student.studentName,
|
||||||
|
className = it.student.className,
|
||||||
|
classId = it.student.classId,
|
||||||
|
isParent = it.student.isParent,
|
||||||
|
semesters = it.semesters,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
userLoginId = loginId,
|
||||||
|
schoolId = schoolId,
|
||||||
|
schoolName = schoolName,
|
||||||
|
schoolShortName = schoolName,
|
||||||
|
parentIds = listOf(),
|
||||||
|
studentIds = listOf(),
|
||||||
|
employeeIds = listOf(),
|
||||||
|
error = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
private suspend fun getStudentsAppropriatesToLoginType(): List<StudentWithSemesters> {
|
private suspend fun getStudentsAppropriatesToLoginType(): List<StudentWithSemesters> {
|
||||||
val email = view?.formUsernameValue.orEmpty()
|
val email = view?.formUsernameValue.orEmpty()
|
||||||
val password = view?.formPassValue.orEmpty()
|
val password = view?.formPassValue.orEmpty()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package io.github.wulkanowy.ui.modules.login.advanced
|
package io.github.wulkanowy.ui.modules.login.advanced
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||||
|
|
||||||
@ -72,7 +73,7 @@ interface LoginAdvancedView : BaseView {
|
|||||||
|
|
||||||
fun navigateToSymbol(loginData: LoginData)
|
fun navigateToSymbol(loginData: LoginData)
|
||||||
|
|
||||||
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>)
|
fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser)
|
||||||
|
|
||||||
fun setErrorPinRequired()
|
fun setErrorPinRequired()
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import androidx.core.view.isVisible
|
|||||||
import androidx.core.widget.doOnTextChanged
|
import androidx.core.widget.doOnTextChanged
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.databinding.FragmentLoginFormBinding
|
import io.github.wulkanowy.databinding.FragmentLoginFormBinding
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
@ -226,8 +226,8 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
|
|||||||
(activity as? LoginActivity)?.navigateToSymbolFragment(loginData)
|
(activity as? LoginActivity)?.navigateToSymbolFragment(loginData)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
|
override fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) {
|
||||||
(activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters)
|
(activity as? LoginActivity)?.navigateToStudentSelect(loginData, registerUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openAdvancedLogin() {
|
override fun openAdvancedLogin() {
|
||||||
|
@ -93,7 +93,7 @@ class LoginFormPresenter @Inject constructor(
|
|||||||
if (!validateCredentials(email, password, host)) return
|
if (!validateCredentials(email, password, host)) return
|
||||||
|
|
||||||
resourceFlow {
|
resourceFlow {
|
||||||
studentRepository.getStudentsScrapper(
|
studentRepository.getUserSubjectsFromScrapper(
|
||||||
email = email,
|
email = email,
|
||||||
password = password,
|
password = password,
|
||||||
scrapperBaseUrl = host,
|
scrapperBaseUrl = host,
|
||||||
@ -109,14 +109,14 @@ class LoginFormPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onResourceSuccess {
|
.onResourceSuccess {
|
||||||
when (it.size) {
|
val loginData = LoginData(email, password, host, symbol)
|
||||||
0 -> view?.navigateToSymbol(LoginData(email, password, host))
|
when (it.symbols.size) {
|
||||||
else -> view?.navigateToStudentSelect(it)
|
0 -> view?.navigateToSymbol(loginData)
|
||||||
|
else -> view?.navigateToStudentSelect(loginData, it)
|
||||||
}
|
}
|
||||||
analytics.logEvent(
|
analytics.logEvent(
|
||||||
"registration_form",
|
"registration_form",
|
||||||
"success" to true,
|
"success" to true,
|
||||||
"students" to it.size,
|
|
||||||
"scrapperBaseUrl" to host,
|
"scrapperBaseUrl" to host,
|
||||||
"error" to "No error"
|
"error" to "No error"
|
||||||
)
|
)
|
||||||
@ -134,7 +134,6 @@ class LoginFormPresenter @Inject constructor(
|
|||||||
analytics.logEvent(
|
analytics.logEvent(
|
||||||
"registration_form",
|
"registration_form",
|
||||||
"success" to false,
|
"success" to false,
|
||||||
"students" to -1,
|
|
||||||
"scrapperBaseUrl" to host,
|
"scrapperBaseUrl" to host,
|
||||||
"error" to it.message.ifNullOrBlank { "No message" }
|
"error" to it.message.ifNullOrBlank { "No message" }
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package io.github.wulkanowy.ui.modules.login.form
|
package io.github.wulkanowy.ui.modules.login.form
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ interface LoginFormView : BaseView {
|
|||||||
|
|
||||||
fun navigateToSymbol(loginData: LoginData)
|
fun navigateToSymbol(loginData: LoginData)
|
||||||
|
|
||||||
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>)
|
fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser)
|
||||||
|
|
||||||
fun openPrivacyPolicyPage()
|
fun openPrivacyPolicyPage()
|
||||||
|
|
||||||
|
@ -2,65 +2,182 @@ package io.github.wulkanowy.ui.modules.login.studentselect
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.recyclerview.widget.DiffUtil.ItemCallback
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.databinding.ItemLoginStudentSelectBinding
|
import io.github.wulkanowy.databinding.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
class LoginStudentSelectAdapter @Inject constructor() :
|
class LoginStudentSelectAdapter @Inject constructor() :
|
||||||
RecyclerView.Adapter<LoginStudentSelectAdapter.ItemViewHolder>() {
|
ListAdapter<LoginStudentSelectItem, RecyclerView.ViewHolder>(Differ) {
|
||||||
|
|
||||||
private val checkedList = mutableMapOf<Int, Boolean>()
|
override fun getItemViewType(position: Int): Int = getItem(position).type.ordinal
|
||||||
|
|
||||||
var items = emptyList<Pair<StudentWithSemesters, Boolean>>()
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
set(value) {
|
val inflater = LayoutInflater.from(parent.context)
|
||||||
field = value
|
return when (LoginStudentSelectItemType.values()[viewType]) {
|
||||||
checkedList.clear()
|
LoginStudentSelectItemType.EMPTY_SYMBOLS_HEADER -> EmptySymbolsHeaderViewHolder(
|
||||||
|
ItemLoginStudentSelectEmptySymbolHeaderBinding.inflate(inflater, parent, false),
|
||||||
|
)
|
||||||
|
LoginStudentSelectItemType.SYMBOL_HEADER -> SymbolsHeaderViewHolder(
|
||||||
|
ItemLoginStudentSelectHeaderSymbolBinding.inflate(inflater, parent, false)
|
||||||
|
)
|
||||||
|
LoginStudentSelectItemType.SCHOOL_HEADER -> SchoolHeaderViewHolder(
|
||||||
|
ItemLoginStudentSelectHeaderSchoolBinding.inflate(inflater, parent, false)
|
||||||
|
)
|
||||||
|
LoginStudentSelectItemType.STUDENT -> StudentViewHolder(
|
||||||
|
ItemLoginStudentSelectStudentBinding.inflate(inflater, parent, false)
|
||||||
|
)
|
||||||
|
LoginStudentSelectItemType.HELP -> HelpViewHolder(
|
||||||
|
ItemLoginStudentSelectHelpBinding.inflate(inflater, parent, false)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var onClickListener: (StudentWithSemesters, alreadySaved: Boolean) -> Unit = { _, _ -> }
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
|
when (holder) {
|
||||||
|
is EmptySymbolsHeaderViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.EmptySymbolsHeader)
|
||||||
|
is SymbolsHeaderViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.SymbolHeader)
|
||||||
|
is SchoolHeaderViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.SchoolHeader)
|
||||||
|
is StudentViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.Student)
|
||||||
|
is HelpViewHolder -> holder.bind(getItem(position) as LoginStudentSelectItem.Help)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun getItemCount() = items.size
|
private class EmptySymbolsHeaderViewHolder(
|
||||||
|
private val binding: ItemLoginStudentSelectEmptySymbolHeaderBinding,
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
|
fun bind(item: LoginStudentSelectItem.EmptySymbolsHeader) {
|
||||||
ItemLoginStudentSelectBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
with(binding) {
|
||||||
)
|
loginStudentSelectEmptySymbolChevron.rotation = if (item.isExpanded) 270f else 90f
|
||||||
|
root.setOnClickListener { item.onClick() }
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
|
|
||||||
val (studentAndSemesters, alreadySaved) = items[position]
|
|
||||||
val student = studentAndSemesters.student
|
|
||||||
val semesters = studentAndSemesters.semesters
|
|
||||||
val diary = semesters.maxByOrNull { it.semesterId }
|
|
||||||
|
|
||||||
with(holder.binding) {
|
|
||||||
loginItemName.text = "${student.studentName} ${diary?.diaryName.orEmpty()}"
|
|
||||||
loginItemSchool.text = student.schoolName
|
|
||||||
loginItemName.isEnabled = !alreadySaved
|
|
||||||
loginItemSchool.isEnabled = !alreadySaved
|
|
||||||
loginItemSignedIn.visibility = if (alreadySaved) View.VISIBLE else View.GONE
|
|
||||||
|
|
||||||
with(loginItemCheck) {
|
|
||||||
isEnabled = !alreadySaved
|
|
||||||
keyListener = null
|
|
||||||
isChecked = checkedList[position] ?: false
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
root.setOnClickListener {
|
private class SymbolsHeaderViewHolder(
|
||||||
onClickListener(studentAndSemesters, alreadySaved)
|
private val binding: ItemLoginStudentSelectHeaderSymbolBinding,
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
fun bind(item: LoginStudentSelectItem.SymbolHeader) {
|
||||||
|
with(binding) {
|
||||||
|
loginStudentSelectHeaderSymbolValue.text = buildString {
|
||||||
|
append(root.context.getString(R.string.mobile_device_symbol))
|
||||||
|
append(": ")
|
||||||
|
append(item.humanReadableName ?: item.symbol.symbol)
|
||||||
|
if (!item.humanReadableName.isNullOrBlank()) {
|
||||||
|
append(" (${item.symbol.symbol})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loginStudentSelectHeaderSymbolUsername.text = item.symbol.userName
|
||||||
|
loginStudentSelectHeaderSymbolUsername.isVisible = item.symbol.userName.isNotBlank()
|
||||||
|
loginStudentSelectHeaderSymbolError.text = item.symbol.error?.message
|
||||||
|
loginStudentSelectHeaderSymbolError.isVisible = item.symbol.error != null
|
||||||
|
loginStudentSelectHeaderSymbolError.maxLines = when {
|
||||||
|
item.isErrorExpanded -> Int.MAX_VALUE
|
||||||
|
else -> 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.symbol.error != null) {
|
||||||
|
root.setOnClickListener { item.onClick(item.symbol) }
|
||||||
|
} else root.setOnClickListener(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SchoolHeaderViewHolder(
|
||||||
|
private val binding: ItemLoginStudentSelectHeaderSchoolBinding,
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
fun bind(item: LoginStudentSelectItem.SchoolHeader) {
|
||||||
|
with(binding) {
|
||||||
|
loginStudentSelectHeaderSchoolName.text = buildString {
|
||||||
|
append(item.unit.schoolName.trim())
|
||||||
|
append(" (")
|
||||||
|
append(item.unit.schoolShortName)
|
||||||
|
append(")")
|
||||||
|
}
|
||||||
|
loginStudentSelectHeaderSchoolDetails.isVisible = item.unit.students.isEmpty()
|
||||||
|
loginStudentSelectHeaderSchoolError.text = item.unit.error?.message
|
||||||
|
loginStudentSelectHeaderSchoolError.isVisible = item.unit.error != null
|
||||||
|
loginStudentSelectHeaderSchoolError.maxLines = when {
|
||||||
|
item.isErrorExpanded -> Int.MAX_VALUE
|
||||||
|
else -> 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.unit.error != null) {
|
||||||
|
root.setOnClickListener { item.onClick(item.unit) }
|
||||||
|
} else root.setOnClickListener(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StudentViewHolder(
|
||||||
|
private val binding: ItemLoginStudentSelectStudentBinding,
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
fun bind(item: LoginStudentSelectItem.Student) {
|
||||||
|
val student = item.student
|
||||||
|
val semesters = student.semesters
|
||||||
|
val diary = semesters.maxByOrNull { it.semesterId }
|
||||||
|
|
||||||
|
with(binding) {
|
||||||
|
loginItemName.text = "${student.studentName} ${student.studentSurname}"
|
||||||
|
loginItemName.isEnabled = item.isEnabled
|
||||||
|
loginItemSignedIn.text = if (!item.isEnabled) {
|
||||||
|
root.context.getString(R.string.login_signed_in)
|
||||||
|
} else diary?.diaryName
|
||||||
|
|
||||||
with(loginItemCheck) {
|
with(loginItemCheck) {
|
||||||
if (isEnabled) {
|
keyListener = null
|
||||||
isChecked = !isChecked
|
isEnabled = item.isEnabled
|
||||||
checkedList[position] = isChecked
|
isChecked = item.isSelected || !item.isEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
root.isEnabled = item.isEnabled
|
||||||
|
root.setOnClickListener {
|
||||||
|
item.onClick(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ItemViewHolder(val binding: ItemLoginStudentSelectBinding) :
|
private class HelpViewHolder(
|
||||||
RecyclerView.ViewHolder(binding.root)
|
private val binding: ItemLoginStudentSelectHelpBinding,
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
fun bind(item: LoginStudentSelectItem.Help) {
|
||||||
|
with(binding) {
|
||||||
|
loginStudentSelectHelpSymbol.isVisible = item.isSymbolButtonVisible
|
||||||
|
loginStudentSelectHelpSymbol.setOnClickListener { item.onEnterSymbolClick() }
|
||||||
|
loginStudentSelectHelpMail.setOnClickListener { item.onContactUsClick() }
|
||||||
|
loginStudentSelectHelpDiscord.setOnClickListener { item.onDiscordClick() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object Differ : ItemCallback<LoginStudentSelectItem>() {
|
||||||
|
|
||||||
|
override fun areItemsTheSame(
|
||||||
|
oldItem: LoginStudentSelectItem, newItem: LoginStudentSelectItem
|
||||||
|
): Boolean = when {
|
||||||
|
oldItem is LoginStudentSelectItem.EmptySymbolsHeader && newItem is LoginStudentSelectItem.EmptySymbolsHeader -> true
|
||||||
|
oldItem is LoginStudentSelectItem.SymbolHeader && newItem is LoginStudentSelectItem.SymbolHeader -> {
|
||||||
|
oldItem.symbol == newItem.symbol
|
||||||
|
}
|
||||||
|
oldItem is LoginStudentSelectItem.Student && newItem is LoginStudentSelectItem.Student -> {
|
||||||
|
oldItem.student == newItem.student
|
||||||
|
}
|
||||||
|
else -> oldItem == newItem
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(
|
||||||
|
oldItem: LoginStudentSelectItem, newItem: LoginStudentSelectItem
|
||||||
|
): Boolean = oldItem == newItem
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,16 @@ package io.github.wulkanowy.ui.modules.login.studentselect
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.GONE
|
|
||||||
import android.view.View.VISIBLE
|
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.core.view.isVisible
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.databinding.FragmentLoginStudentSelectBinding
|
import io.github.wulkanowy.databinding.FragmentLoginStudentSelectBinding
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
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.AppInfo
|
||||||
import io.github.wulkanowy.utils.openEmailClient
|
import io.github.wulkanowy.utils.openEmailClient
|
||||||
import io.github.wulkanowy.utils.openInternetBrowser
|
import io.github.wulkanowy.utils.openInternetBrowser
|
||||||
@ -36,12 +35,23 @@ class LoginStudentSelectFragment :
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var preferencesRepository: PreferencesRepository
|
lateinit var preferencesRepository: PreferencesRepository
|
||||||
|
|
||||||
companion object {
|
private lateinit var symbolsNames: Array<String>
|
||||||
const val ARG_STUDENTS = "STUDENTS"
|
private lateinit var symbolsValues: Array<String>
|
||||||
|
|
||||||
fun newInstance(studentsWithSemesters: List<StudentWithSemesters>) =
|
override val symbols: Map<String, String> by lazy {
|
||||||
|
symbolsValues.zip(symbolsNames).toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ARG_LOGIN = "LOGIN"
|
||||||
|
private const val ARG_STUDENTS = "STUDENTS"
|
||||||
|
|
||||||
|
fun newInstance(loginData: LoginData, registerUser: RegisterUser) =
|
||||||
LoginStudentSelectFragment().apply {
|
LoginStudentSelectFragment().apply {
|
||||||
arguments = bundleOf(ARG_STUDENTS to studentsWithSemesters)
|
arguments = bundleOf(
|
||||||
|
ARG_LOGIN to loginData,
|
||||||
|
ARG_STUDENTS to registerUser,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,34 +59,32 @@ class LoginStudentSelectFragment :
|
|||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
binding = FragmentLoginStudentSelectBinding.bind(view)
|
binding = FragmentLoginStudentSelectBinding.bind(view)
|
||||||
|
|
||||||
|
symbolsNames = resources.getStringArray(R.array.symbols)
|
||||||
|
symbolsValues = resources.getStringArray(R.array.symbols_values)
|
||||||
|
|
||||||
presenter.onAttachView(
|
presenter.onAttachView(
|
||||||
view = this,
|
view = this,
|
||||||
students = requireArguments().serializable(ARG_STUDENTS),
|
loginData = requireArguments().serializable(ARG_LOGIN),
|
||||||
|
registerUser = requireArguments().serializable(ARG_STUDENTS),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
(requireActivity() as LoginActivity).showActionBar(true)
|
(requireActivity() as LoginActivity).showActionBar(true)
|
||||||
|
|
||||||
loginAdapter.onClickListener = presenter::onItemSelected
|
|
||||||
|
|
||||||
with(binding) {
|
with(binding) {
|
||||||
loginStudentSelectSignIn.setOnClickListener { presenter.onSignIn() }
|
loginStudentSelectSignIn.setOnClickListener { presenter.onSignIn() }
|
||||||
loginStudentSelectContactDiscord.setOnClickListener { presenter.onDiscordClick() }
|
loginStudentSelectRecycler.adapter = loginAdapter
|
||||||
loginStudentSelectContactEmail.setOnClickListener { presenter.onEmailClick() }
|
|
||||||
|
|
||||||
with(loginStudentSelectRecycler) {
|
|
||||||
layoutManager = LinearLayoutManager(context)
|
|
||||||
adapter = loginAdapter
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateData(data: List<Pair<StudentWithSemesters, Boolean>>) {
|
override fun updateData(data: List<LoginStudentSelectItem>) {
|
||||||
with(loginAdapter) {
|
loginAdapter.submitList(data)
|
||||||
items = data
|
}
|
||||||
notifyDataSetChanged()
|
|
||||||
}
|
override fun navigateToSymbol(loginData: LoginData) {
|
||||||
|
(requireActivity() as LoginActivity).navigateToSymbolFragment(loginData)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun navigateToNext() {
|
override fun navigateToNext() {
|
||||||
@ -84,26 +92,17 @@ class LoginStudentSelectFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun showProgress(show: Boolean) {
|
override fun showProgress(show: Boolean) {
|
||||||
binding.loginStudentSelectProgress.visibility = if (show) VISIBLE else GONE
|
binding.loginStudentSelectProgress.isVisible = show
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showContent(show: Boolean) {
|
override fun showContent(show: Boolean) {
|
||||||
binding.loginStudentSelectContent.visibility = if (show) VISIBLE else GONE
|
binding.loginStudentSelectContent.isVisible = show
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun enableSignIn(enable: Boolean) {
|
override fun enableSignIn(enable: Boolean) {
|
||||||
binding.loginStudentSelectSignIn.isEnabled = enable
|
binding.loginStudentSelectSignIn.isEnabled = enable
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showContact(show: Boolean) {
|
|
||||||
binding.loginStudentSelectContact.visibility = if (show) VISIBLE else GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
|
||||||
presenter.onDetachView()
|
|
||||||
super.onDestroyView()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openDiscordInvite() {
|
override fun openDiscordInvite() {
|
||||||
context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
|
context?.openInternetBrowser("https://discord.gg/vccAQBr", ::showMessage)
|
||||||
}
|
}
|
||||||
@ -124,4 +123,9 @@ class LoginStudentSelectFragment :
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
presenter.onDetachView()
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
package io.github.wulkanowy.ui.modules.login.studentselect
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterStudent
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterSymbol
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterUnit
|
||||||
|
|
||||||
|
sealed class LoginStudentSelectItem(val type: LoginStudentSelectItemType) {
|
||||||
|
|
||||||
|
data class EmptySymbolsHeader(
|
||||||
|
val isExpanded: Boolean,
|
||||||
|
val onClick: () -> Unit,
|
||||||
|
) : LoginStudentSelectItem(LoginStudentSelectItemType.EMPTY_SYMBOLS_HEADER)
|
||||||
|
|
||||||
|
data class SymbolHeader(
|
||||||
|
val symbol: RegisterSymbol,
|
||||||
|
val humanReadableName: String?,
|
||||||
|
val isErrorExpanded: Boolean,
|
||||||
|
val onClick: (RegisterSymbol) -> Unit,
|
||||||
|
) : LoginStudentSelectItem(LoginStudentSelectItemType.SYMBOL_HEADER)
|
||||||
|
|
||||||
|
data class SchoolHeader(
|
||||||
|
val unit: RegisterUnit,
|
||||||
|
val isErrorExpanded: Boolean,
|
||||||
|
val onClick: (RegisterUnit) -> Unit,
|
||||||
|
) : LoginStudentSelectItem(LoginStudentSelectItemType.SCHOOL_HEADER)
|
||||||
|
|
||||||
|
data class Student(
|
||||||
|
val symbol: RegisterSymbol,
|
||||||
|
val unit: RegisterUnit,
|
||||||
|
val student: RegisterStudent,
|
||||||
|
val isEnabled: Boolean,
|
||||||
|
val isSelected: Boolean,
|
||||||
|
val onClick: (Student) -> Unit,
|
||||||
|
) : LoginStudentSelectItem(LoginStudentSelectItemType.STUDENT)
|
||||||
|
|
||||||
|
data class Help(
|
||||||
|
val onEnterSymbolClick: () -> Unit,
|
||||||
|
val onContactUsClick: () -> Unit,
|
||||||
|
val onDiscordClick: () -> Unit,
|
||||||
|
val isSymbolButtonVisible: Boolean,
|
||||||
|
) : LoginStudentSelectItem(LoginStudentSelectItemType.HELP)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class LoginStudentSelectItemType {
|
||||||
|
EMPTY_SYMBOLS_HEADER,
|
||||||
|
SYMBOL_HEADER,
|
||||||
|
SCHOOL_HEADER,
|
||||||
|
STUDENT,
|
||||||
|
HELP,
|
||||||
|
}
|
@ -1,15 +1,23 @@
|
|||||||
package io.github.wulkanowy.ui.modules.login.studentselect
|
package io.github.wulkanowy.ui.modules.login.studentselect
|
||||||
|
|
||||||
import io.github.wulkanowy.data.Resource
|
import io.github.wulkanowy.data.Resource
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.dataOrNull
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
import io.github.wulkanowy.data.logResourceStatus
|
import io.github.wulkanowy.data.logResourceStatus
|
||||||
|
import io.github.wulkanowy.data.mappers.mapToStudentWithSemesters
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterStudent
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterSymbol
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterUnit
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||||
import io.github.wulkanowy.data.resourceFlow
|
import io.github.wulkanowy.data.resourceFlow
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.login.AccountPermissionException
|
||||||
import io.github.wulkanowy.services.sync.SyncManager
|
import io.github.wulkanowy.services.sync.SyncManager
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
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.ui.modules.login.LoginErrorHandler
|
||||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||||
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@ -19,18 +27,30 @@ class LoginStudentSelectPresenter @Inject constructor(
|
|||||||
studentRepository: StudentRepository,
|
studentRepository: StudentRepository,
|
||||||
private val loginErrorHandler: LoginErrorHandler,
|
private val loginErrorHandler: LoginErrorHandler,
|
||||||
private val syncManager: SyncManager,
|
private val syncManager: SyncManager,
|
||||||
private val analytics: AnalyticsHelper
|
private val analytics: AnalyticsHelper,
|
||||||
|
private val appInfo: AppInfo,
|
||||||
) : BasePresenter<LoginStudentSelectView>(loginErrorHandler, studentRepository) {
|
) : BasePresenter<LoginStudentSelectView>(loginErrorHandler, studentRepository) {
|
||||||
|
|
||||||
private var lastError: Throwable? = null
|
private var lastError: Throwable? = null
|
||||||
|
|
||||||
private val selectedStudents = mutableListOf<StudentWithSemesters>()
|
private lateinit var registerUser: RegisterUser
|
||||||
|
private lateinit var loginData: LoginData
|
||||||
|
|
||||||
fun onAttachView(view: LoginStudentSelectView, students: List<StudentWithSemesters>) {
|
private lateinit var students: List<StudentWithSemesters>
|
||||||
|
private var isEmptySymbolsExpanded = false
|
||||||
|
private var expandedSymbolError: RegisterSymbol? = null
|
||||||
|
private var expandedSchoolError: RegisterUnit? = null
|
||||||
|
|
||||||
|
private val selectedStudents = mutableListOf<LoginStudentSelectItem.Student>()
|
||||||
|
|
||||||
|
fun onAttachView(
|
||||||
|
view: LoginStudentSelectView,
|
||||||
|
loginData: LoginData,
|
||||||
|
registerUser: RegisterUser,
|
||||||
|
) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
with(view) {
|
with(view) {
|
||||||
initView()
|
initView()
|
||||||
showContact(false)
|
|
||||||
enableSignIn(false)
|
enableSignIn(false)
|
||||||
loginErrorHandler.onStudentDuplicate = {
|
loginErrorHandler.onStudentDuplicate = {
|
||||||
showMessage(it)
|
showMessage(it)
|
||||||
@ -38,50 +58,171 @@ class LoginStudentSelectPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (students.size == 1) registerStudents(students)
|
this.loginData = loginData
|
||||||
loadData(students)
|
this.registerUser = registerUser
|
||||||
|
loadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadData() {
|
||||||
|
resetSelectedState()
|
||||||
|
|
||||||
|
resourceFlow { studentRepository.getSavedStudents(false) }.onEach {
|
||||||
|
students = it.dataOrNull.orEmpty()
|
||||||
|
when (it) {
|
||||||
|
is Resource.Loading -> Timber.d("Login student select students load started")
|
||||||
|
is Resource.Success -> refreshItems()
|
||||||
|
is Resource.Error -> {
|
||||||
|
errorHandler.dispatch(it.error)
|
||||||
|
lastError = it.error
|
||||||
|
refreshItems()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.launch()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createItems(): List<LoginStudentSelectItem> = buildList {
|
||||||
|
val notEmptySymbols = registerUser.symbols.filter { it.schools.isNotEmpty() }
|
||||||
|
val emptySymbols = registerUser.symbols.filter { it.schools.isEmpty() }
|
||||||
|
|
||||||
|
if (emptySymbols.isNotEmpty() && notEmptySymbols.isNotEmpty() && emptySymbols.any { it.symbol == loginData.symbol }) {
|
||||||
|
add(createEmptySymbolItem(emptySymbols.first { it.symbol == loginData.symbol }))
|
||||||
|
}
|
||||||
|
|
||||||
|
addAll(createNotEmptySymbolItems(notEmptySymbols, students))
|
||||||
|
addAll(createEmptySymbolItems(emptySymbols, notEmptySymbols.isNotEmpty()))
|
||||||
|
|
||||||
|
val helpItem = LoginStudentSelectItem.Help(
|
||||||
|
onEnterSymbolClick = ::onEnterSymbol,
|
||||||
|
onContactUsClick = ::onEmailClick,
|
||||||
|
onDiscordClick = ::onDiscordClick,
|
||||||
|
isSymbolButtonVisible = "login" !in loginData.baseUrl,
|
||||||
|
)
|
||||||
|
add(helpItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createNotEmptySymbolItems(
|
||||||
|
notEmptySymbols: List<RegisterSymbol>,
|
||||||
|
students: List<StudentWithSemesters>,
|
||||||
|
) = buildList {
|
||||||
|
notEmptySymbols.forEach { registerSymbol ->
|
||||||
|
val symbolHeader = LoginStudentSelectItem.SymbolHeader(
|
||||||
|
symbol = registerSymbol,
|
||||||
|
humanReadableName = view?.symbols?.get(registerSymbol.symbol),
|
||||||
|
isErrorExpanded = expandedSymbolError == registerSymbol,
|
||||||
|
onClick = ::onSymbolItemClick,
|
||||||
|
)
|
||||||
|
add(symbolHeader)
|
||||||
|
|
||||||
|
registerSymbol.schools.forEach { registerUnit ->
|
||||||
|
val schoolHeader = LoginStudentSelectItem.SchoolHeader(
|
||||||
|
unit = registerUnit,
|
||||||
|
isErrorExpanded = expandedSchoolError == registerUnit,
|
||||||
|
onClick = ::onUnitItemClick,
|
||||||
|
)
|
||||||
|
add(schoolHeader)
|
||||||
|
|
||||||
|
registerUnit.students.forEach {
|
||||||
|
add(createStudentItem(it, registerSymbol, registerUnit, students))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createStudentItem(
|
||||||
|
student: RegisterStudent,
|
||||||
|
symbol: RegisterSymbol,
|
||||||
|
school: RegisterUnit,
|
||||||
|
students: List<StudentWithSemesters>,
|
||||||
|
) = LoginStudentSelectItem.Student(
|
||||||
|
symbol = symbol,
|
||||||
|
unit = school,
|
||||||
|
student = student,
|
||||||
|
onClick = ::onItemSelected,
|
||||||
|
isEnabled = students.none {
|
||||||
|
it.student.email == registerUser.login
|
||||||
|
&& it.student.symbol == symbol.symbol
|
||||||
|
&& it.student.studentId == student.studentId
|
||||||
|
&& it.student.schoolSymbol == school.schoolId
|
||||||
|
&& it.student.classId == student.classId
|
||||||
|
},
|
||||||
|
isSelected = selectedStudents
|
||||||
|
.filter { it.symbol.symbol == symbol.symbol }
|
||||||
|
.filter { it.unit.schoolId == school.schoolId }
|
||||||
|
.filter { it.student.studentId == student.studentId }
|
||||||
|
.filter { it.student.classId == student.classId }
|
||||||
|
.size == 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun createEmptySymbolItems(
|
||||||
|
emptySymbols: List<RegisterSymbol>,
|
||||||
|
isNotEmptySymbolsExist: Boolean,
|
||||||
|
) = buildList {
|
||||||
|
val filteredEmptySymbols = emptySymbols.filter {
|
||||||
|
it.error !is AccountPermissionException
|
||||||
|
}.ifEmpty { emptySymbols.takeIf { !isNotEmptySymbolsExist }.orEmpty() }
|
||||||
|
|
||||||
|
if (filteredEmptySymbols.isNotEmpty() && isNotEmptySymbolsExist) {
|
||||||
|
val emptyHeader = LoginStudentSelectItem.EmptySymbolsHeader(
|
||||||
|
isExpanded = isEmptySymbolsExpanded,
|
||||||
|
onClick = ::onEmptySymbolsToggle,
|
||||||
|
)
|
||||||
|
add(emptyHeader)
|
||||||
|
if (isEmptySymbolsExpanded) {
|
||||||
|
filteredEmptySymbols.forEach {
|
||||||
|
add(createEmptySymbolItem(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filteredEmptySymbols.isNotEmpty() && !isNotEmptySymbolsExist) {
|
||||||
|
filteredEmptySymbols.forEach {
|
||||||
|
add(createEmptySymbolItem(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createEmptySymbolItem(registerSymbol: RegisterSymbol) =
|
||||||
|
LoginStudentSelectItem.SymbolHeader(
|
||||||
|
symbol = registerSymbol,
|
||||||
|
humanReadableName = view?.symbols?.get(registerSymbol.symbol),
|
||||||
|
isErrorExpanded = expandedSymbolError == registerSymbol,
|
||||||
|
onClick = ::onSymbolItemClick,
|
||||||
|
)
|
||||||
|
|
||||||
fun onSignIn() {
|
fun onSignIn() {
|
||||||
registerStudents(selectedStudents)
|
registerStudents(selectedStudents)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onItemSelected(studentWithSemester: StudentWithSemesters, alreadySaved: Boolean) {
|
private fun onEmptySymbolsToggle() {
|
||||||
if (alreadySaved) return
|
isEmptySymbolsExpanded = !isEmptySymbolsExpanded
|
||||||
|
|
||||||
|
refreshItems()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onItemSelected(item: LoginStudentSelectItem.Student) {
|
||||||
|
if (!item.isEnabled) return
|
||||||
|
|
||||||
selectedStudents
|
selectedStudents
|
||||||
.removeAll { it == studentWithSemester }
|
.removeAll {
|
||||||
.let { if (!it) selectedStudents.add(studentWithSemester) }
|
it.student.studentId == item.student.studentId &&
|
||||||
|
it.student.classId == item.student.classId &&
|
||||||
|
it.unit.schoolId == item.unit.schoolId &&
|
||||||
|
it.symbol.symbol == item.symbol.symbol
|
||||||
|
}
|
||||||
|
.let { if (!it) selectedStudents.add(item) }
|
||||||
|
|
||||||
view?.enableSignIn(selectedStudents.isNotEmpty())
|
view?.enableSignIn(selectedStudents.isNotEmpty())
|
||||||
|
refreshItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun compareStudents(a: Student, b: Student): Boolean {
|
private fun onSymbolItemClick(symbol: RegisterSymbol) {
|
||||||
return a.email == b.email
|
expandedSymbolError = if (symbol != expandedSymbolError) symbol else null
|
||||||
&& a.symbol == b.symbol
|
refreshItems()
|
||||||
&& a.studentId == b.studentId
|
|
||||||
&& a.schoolSymbol == b.schoolSymbol
|
|
||||||
&& a.classId == b.classId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadData(studentsWithSemesters: List<StudentWithSemesters>) {
|
private fun onUnitItemClick(unit: RegisterUnit) {
|
||||||
resetSelectedState()
|
expandedSchoolError = if (unit != expandedSchoolError) unit else null
|
||||||
|
refreshItems()
|
||||||
resourceFlow { studentRepository.getSavedStudents(false) }.onEach {
|
|
||||||
when (it) {
|
|
||||||
is Resource.Loading -> Timber.d("Login student select students load started")
|
|
||||||
is Resource.Success -> view?.updateData(studentsWithSemesters.map { studentWithSemesters ->
|
|
||||||
studentWithSemesters to it.data.any { item ->
|
|
||||||
compareStudents(studentWithSemesters.student, item.student)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
is Resource.Error -> {
|
|
||||||
errorHandler.dispatch(it.error)
|
|
||||||
lastError = it.error
|
|
||||||
view?.updateData(studentsWithSemesters.map { student -> student to false })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.launch()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetSelectedState() {
|
private fun resetSelectedState() {
|
||||||
@ -89,7 +230,20 @@ class LoginStudentSelectPresenter @Inject constructor(
|
|||||||
view?.enableSignIn(false)
|
view?.enableSignIn(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerStudents(studentsWithSemesters: List<StudentWithSemesters>) {
|
private fun refreshItems() {
|
||||||
|
view?.updateData(createItems())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun registerStudents(students: List<LoginStudentSelectItem>) {
|
||||||
|
val studentsWithSemesters = students
|
||||||
|
.filterIsInstance<LoginStudentSelectItem.Student>().map { item ->
|
||||||
|
item.student.mapToStudentWithSemesters(
|
||||||
|
user = registerUser,
|
||||||
|
symbol = item.symbol,
|
||||||
|
unit = item.unit,
|
||||||
|
colors = appInfo.defaultColorsForAvatar,
|
||||||
|
)
|
||||||
|
}
|
||||||
resourceFlow { studentRepository.saveStudents(studentsWithSemesters) }
|
resourceFlow { studentRepository.saveStudents(studentsWithSemesters) }
|
||||||
.logResourceStatus("registration")
|
.logResourceStatus("registration")
|
||||||
.onEach {
|
.onEach {
|
||||||
@ -107,7 +261,6 @@ class LoginStudentSelectPresenter @Inject constructor(
|
|||||||
view?.apply {
|
view?.apply {
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
showContent(true)
|
showContent(true)
|
||||||
showContact(true)
|
|
||||||
}
|
}
|
||||||
lastError = it.error
|
lastError = it.error
|
||||||
loginErrorHandler.dispatch(it.error)
|
loginErrorHandler.dispatch(it.error)
|
||||||
@ -117,12 +270,22 @@ class LoginStudentSelectPresenter @Inject constructor(
|
|||||||
}.launch("register")
|
}.launch("register")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDiscordClick() {
|
private fun onEnterSymbol() {
|
||||||
|
view?.navigateToSymbol(loginData)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onDiscordClick() {
|
||||||
view?.openDiscordInvite()
|
view?.openDiscordInvite()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onEmailClick() {
|
private fun onEmailClick() {
|
||||||
view?.openEmail(lastError?.message.ifNullOrBlank { "empty" })
|
view?.openEmail(lastError?.message.ifNullOrBlank {
|
||||||
|
registerUser.symbols.flatMap { symbol ->
|
||||||
|
symbol.schools.map { it.error?.message } + symbol.error?.message
|
||||||
|
}.filterNotNull().distinct().joinToString("; ") {
|
||||||
|
it.take(46) + "..."
|
||||||
|
}.ifEmpty { "blank" }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun logRegisterEvent(
|
private fun logRegisterEvent(
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
package io.github.wulkanowy.ui.modules.login.studentselect
|
package io.github.wulkanowy.ui.modules.login.studentselect
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
|
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||||
|
|
||||||
interface LoginStudentSelectView : BaseView {
|
interface LoginStudentSelectView : BaseView {
|
||||||
|
|
||||||
|
val symbols: Map<String, String>
|
||||||
|
|
||||||
fun initView()
|
fun initView()
|
||||||
|
|
||||||
fun updateData(data: List<Pair<StudentWithSemesters, Boolean>>)
|
fun updateData(data: List<LoginStudentSelectItem>)
|
||||||
|
|
||||||
|
fun navigateToSymbol(loginData: LoginData)
|
||||||
|
|
||||||
fun navigateToNext()
|
fun navigateToNext()
|
||||||
|
|
||||||
@ -17,8 +21,6 @@ interface LoginStudentSelectView : BaseView {
|
|||||||
|
|
||||||
fun enableSignIn(enable: Boolean)
|
fun enableSignIn(enable: Boolean)
|
||||||
|
|
||||||
fun showContact(show: Boolean)
|
|
||||||
|
|
||||||
fun openDiscordInvite()
|
fun openDiscordInvite()
|
||||||
|
|
||||||
fun openEmail(lastError: String)
|
fun openEmail(lastError: String)
|
||||||
|
@ -12,7 +12,7 @@ import androidx.core.text.parseAsHtml
|
|||||||
import androidx.core.widget.doOnTextChanged
|
import androidx.core.widget.doOnTextChanged
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.databinding.FragmentLoginSymbolBinding
|
import io.github.wulkanowy.databinding.FragmentLoginSymbolBinding
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
@ -42,6 +42,8 @@ class LoginSymbolFragment :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val symbolValue: String? get() = binding.loginSymbolName.text?.toString()
|
||||||
|
|
||||||
override val symbolNameError: CharSequence?
|
override val symbolNameError: CharSequence?
|
||||||
get() = binding.loginSymbolNameLayout.error
|
get() = binding.loginSymbolNameLayout.error
|
||||||
|
|
||||||
@ -58,7 +60,7 @@ class LoginSymbolFragment :
|
|||||||
(requireActivity() as LoginActivity).showActionBar(true)
|
(requireActivity() as LoginActivity).showActionBar(true)
|
||||||
|
|
||||||
with(binding) {
|
with(binding) {
|
||||||
loginSymbolSignIn.setOnClickListener { presenter.attemptLogin(loginSymbolName.text.toString()) }
|
loginSymbolSignIn.setOnClickListener { presenter.attemptLogin() }
|
||||||
loginSymbolFaq.setOnClickListener { presenter.onFaqClick() }
|
loginSymbolFaq.setOnClickListener { presenter.onFaqClick() }
|
||||||
loginSymbolContactEmail.setOnClickListener { presenter.onEmailClick() }
|
loginSymbolContactEmail.setOnClickListener { presenter.onEmailClick() }
|
||||||
|
|
||||||
@ -92,9 +94,13 @@ class LoginSymbolFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setErrorSymbolRequire() {
|
override fun setErrorSymbolRequire() {
|
||||||
binding.loginSymbolNameLayout.apply {
|
setErrorSymbol(getString(R.string.error_field_required))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setErrorSymbol(message: String) {
|
||||||
|
with(binding.loginSymbolNameLayout) {
|
||||||
requestFocus()
|
requestFocus()
|
||||||
error = getString(R.string.error_field_required)
|
error = message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,8 +131,8 @@ class LoginSymbolFragment :
|
|||||||
binding.loginSymbolContainer.visibility = if (show) VISIBLE else GONE
|
binding.loginSymbolContainer.visibility = if (show) VISIBLE else GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
|
override fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser) {
|
||||||
(activity as? LoginActivity)?.navigateToStudentSelect(studentsWithSemesters)
|
(activity as? LoginActivity)?.navigateToStudentSelect(loginData, registerUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
package io.github.wulkanowy.ui.modules.login.symbol
|
package io.github.wulkanowy.ui.modules.login.symbol
|
||||||
|
|
||||||
import io.github.wulkanowy.data.Resource
|
import io.github.wulkanowy.data.Resource
|
||||||
|
import io.github.wulkanowy.data.dataOrNull
|
||||||
import io.github.wulkanowy.data.onResourceNotLoading
|
import io.github.wulkanowy.data.onResourceNotLoading
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||||
import io.github.wulkanowy.data.resourceFlow
|
import io.github.wulkanowy.data.resourceFlow
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.getNormalizedSymbol
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginData
|
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||||
@ -23,9 +26,14 @@ class LoginSymbolPresenter @Inject constructor(
|
|||||||
|
|
||||||
lateinit var loginData: LoginData
|
lateinit var loginData: LoginData
|
||||||
|
|
||||||
|
private var registerUser: RegisterUser? = null
|
||||||
|
|
||||||
fun onAttachView(view: LoginSymbolView, loginData: LoginData) {
|
fun onAttachView(view: LoginSymbolView, loginData: LoginData) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
this.loginData = loginData
|
this.loginData = loginData
|
||||||
|
loginErrorHandler.onBadCredentials = {
|
||||||
|
view.setErrorSymbol(it.orEmpty())
|
||||||
|
}
|
||||||
with(view) {
|
with(view) {
|
||||||
initView()
|
initView()
|
||||||
showContact(false)
|
showContact(false)
|
||||||
@ -39,20 +47,24 @@ class LoginSymbolPresenter @Inject constructor(
|
|||||||
view?.apply { if (symbolNameError != null) clearSymbolError() }
|
view?.apply { if (symbolNameError != null) clearSymbolError() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun attemptLogin(symbol: String) {
|
fun attemptLogin() {
|
||||||
if (symbol.isBlank()) {
|
if (view?.symbolValue.isNullOrBlank()) {
|
||||||
view?.setErrorSymbolRequire()
|
view?.setErrorSymbolRequire()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loginData = loginData.copy(
|
||||||
|
symbol = view?.symbolValue?.getNormalizedSymbol(),
|
||||||
|
)
|
||||||
resourceFlow {
|
resourceFlow {
|
||||||
studentRepository.getStudentsScrapper(
|
studentRepository.getUserSubjectsFromScrapper(
|
||||||
email = loginData.login,
|
email = loginData.login,
|
||||||
password = loginData.password,
|
password = loginData.password,
|
||||||
scrapperBaseUrl = loginData.baseUrl,
|
scrapperBaseUrl = loginData.baseUrl,
|
||||||
symbol = symbol,
|
symbol = view?.symbolValue.orEmpty(),
|
||||||
)
|
)
|
||||||
}.onEach {
|
}.onEach {
|
||||||
|
registerUser = it.dataOrNull
|
||||||
when (it) {
|
when (it) {
|
||||||
is Resource.Loading -> view?.run {
|
is Resource.Loading -> view?.run {
|
||||||
Timber.i("Login with symbol started")
|
Timber.i("Login with symbol started")
|
||||||
@ -61,7 +73,7 @@ class LoginSymbolPresenter @Inject constructor(
|
|||||||
showContent(false)
|
showContent(false)
|
||||||
}
|
}
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
when (it.data.size) {
|
when (it.data.symbols.size) {
|
||||||
0 -> {
|
0 -> {
|
||||||
Timber.i("Login with symbol result: Empty student list")
|
Timber.i("Login with symbol result: Empty student list")
|
||||||
view?.run {
|
view?.run {
|
||||||
@ -71,15 +83,14 @@ class LoginSymbolPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
Timber.i("Login with symbol result: Success")
|
Timber.i("Login with symbol result: Success")
|
||||||
view?.navigateToStudentSelect(requireNotNull(it.data))
|
view?.navigateToStudentSelect(loginData, requireNotNull(it.data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
analytics.logEvent(
|
analytics.logEvent(
|
||||||
"registration_symbol",
|
"registration_symbol",
|
||||||
"success" to true,
|
"success" to true,
|
||||||
"students" to it.data.size,
|
|
||||||
"scrapperBaseUrl" to loginData.baseUrl,
|
"scrapperBaseUrl" to loginData.baseUrl,
|
||||||
"symbol" to symbol,
|
"symbol" to view?.symbolValue,
|
||||||
"error" to "No error"
|
"error" to "No error"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -90,7 +101,7 @@ class LoginSymbolPresenter @Inject constructor(
|
|||||||
"success" to false,
|
"success" to false,
|
||||||
"students" to -1,
|
"students" to -1,
|
||||||
"scrapperBaseUrl" to loginData.baseUrl,
|
"scrapperBaseUrl" to loginData.baseUrl,
|
||||||
"symbol" to symbol,
|
"symbol" to view?.symbolValue,
|
||||||
"error" to it.error.message.ifNullOrBlank { "No message" }
|
"error" to it.error.message.ifNullOrBlank { "No message" }
|
||||||
)
|
)
|
||||||
loginErrorHandler.dispatch(it.error)
|
loginErrorHandler.dispatch(it.error)
|
||||||
@ -111,6 +122,12 @@ class LoginSymbolPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onEmailClick() {
|
fun onEmailClick() {
|
||||||
view?.openEmail(loginData.baseUrl, lastError?.message.ifNullOrBlank { "empty" })
|
view?.openEmail(loginData.baseUrl, lastError?.message.ifNullOrBlank {
|
||||||
|
registerUser?.symbols?.flatMap { symbol ->
|
||||||
|
symbol.schools.map { it.error?.message } + symbol.error?.message
|
||||||
|
}?.filterNotNull()?.distinct()?.joinToString(";") {
|
||||||
|
it.take(46) + "..."
|
||||||
|
} ?: "blank"
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package io.github.wulkanowy.ui.modules.login.symbol
|
package io.github.wulkanowy.ui.modules.login.symbol
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.ui.base.BaseView
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
|
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||||
|
|
||||||
interface LoginSymbolView : BaseView {
|
interface LoginSymbolView : BaseView {
|
||||||
|
|
||||||
|
val symbolValue: String?
|
||||||
|
|
||||||
val symbolNameError: CharSequence?
|
val symbolNameError: CharSequence?
|
||||||
|
|
||||||
fun initView()
|
fun initView()
|
||||||
@ -15,6 +18,8 @@ interface LoginSymbolView : BaseView {
|
|||||||
|
|
||||||
fun setErrorSymbolRequire()
|
fun setErrorSymbolRequire()
|
||||||
|
|
||||||
|
fun setErrorSymbol(message: String)
|
||||||
|
|
||||||
fun clearSymbolError()
|
fun clearSymbolError()
|
||||||
|
|
||||||
fun clearAndFocusSymbol()
|
fun clearAndFocusSymbol()
|
||||||
@ -27,7 +32,7 @@ interface LoginSymbolView : BaseView {
|
|||||||
|
|
||||||
fun showContent(show: Boolean)
|
fun showContent(show: Boolean)
|
||||||
|
|
||||||
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>)
|
fun navigateToStudentSelect(loginData: LoginData, registerUser: RegisterUser)
|
||||||
|
|
||||||
fun showContact(show: Boolean)
|
fun showContact(show: Boolean)
|
||||||
|
|
||||||
|
@ -3,92 +3,14 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical"
|
||||||
|
tools:context=".ui.modules.login.studentselect.LoginStudentSelectFragment">
|
||||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
|
||||||
android:id="@+id/loginStudentSelectProgress"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:indeterminate="true"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/loginStudentSelectContent"
|
android:id="@+id/loginStudentSelectContent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/loginStudentSelectContact"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:visibility="visible">
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/loginStudentSelectContactTopDivider"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:background="?android:attr/listDivider" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/loginStudentSelectContactHeader"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="32dp"
|
|
||||||
android:layout_marginLeft="32dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
android:layout_marginRight="32dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:text="@string/login_contact_header"
|
|
||||||
android:textSize="14sp"
|
|
||||||
app:fontFamily="sans-serif-medium" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/loginStudentSelectContactButtons"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/loginStudentSelectContactEmail"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/login_contact_email"
|
|
||||||
app:icon="@drawable/ic_more_messages" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/loginStudentSelectContactDiscord"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginLeft="8dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/login_contact_discord"
|
|
||||||
app:icon="@drawable/ic_about_discord" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/loginStudentSelectContactBottomDivider"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:background="?android:attr/listDivider" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/loginStudentSelectHeader"
|
android:id="@+id/loginStudentSelectHeader"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -106,22 +28,24 @@
|
|||||||
app:layout_constraintBottom_toTopOf="@id/loginStudentSelectRecycler"
|
app:layout_constraintBottom_toTopOf="@id/loginStudentSelectRecycler"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/loginStudentSelectContact"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintVertical_chainStyle="packed" />
|
app:layout_constraintVertical_chainStyle="packed" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/loginStudentSelectRecycler"
|
android:id="@+id/loginStudentSelectRecycler"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="144dp"
|
android:fadingEdge="vertical"
|
||||||
|
android:fadingEdgeLength="100dp"
|
||||||
|
android:requiresFadingEdge="vertical"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
app:layout_constrainedHeight="true"
|
app:layout_constrainedHeight="true"
|
||||||
app:layout_constraintBottom_toTopOf="@id/loginStudentSelectSignIn"
|
app:layout_constraintBottom_toTopOf="@id/loginStudentSelectSignIn"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHeight_max="432dp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/loginStudentSelectHeader"
|
app:layout_constraintTop_toBottomOf="@id/loginStudentSelectHeader"
|
||||||
tools:itemCount="6"
|
tools:itemCount="33"
|
||||||
tools:listitem="@layout/item_login_student_select" />
|
tools:listitem="@layout/item_login_student_select_student" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/loginStudentSelectSignIn"
|
android:id="@+id/loginStudentSelectSignIn"
|
||||||
@ -136,4 +60,12 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/loginStudentSelectRecycler" />
|
app:layout_constraintTop_toBottomOf="@id/loginStudentSelectRecycler" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
|
android:id="@+id/loginStudentSelectProgress"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:visibility="gone" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:background="?selectableItemBackground"
|
||||||
|
android:paddingHorizontal="16dp">
|
||||||
|
|
||||||
|
<com.google.android.material.divider.MaterialDivider
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/login_student_select_empty_symbol_header"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingVertical="16dp"
|
||||||
|
android:text="@string/login_other_search_locations"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/login_student_select_empty_symbol_chevron"
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:rotation="90"
|
||||||
|
android:src="@drawable/ic_chevron_right"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:tint="?android:textColorPrimary"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="24dp"
|
||||||
|
android:paddingVertical="8dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/login_student_select_header_school_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="Publiczna szkoła Wulkanowego" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/login_student_select_header_school_details"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:text="@string/login_no_active_student"
|
||||||
|
android:textColor="?colorTimetableChange"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/login_student_select_header_school_name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/login_student_select_header_school_error"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textColor="?colorError"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/login_student_select_header_school_details"
|
||||||
|
tools:text="@tools:sample/lorem/random" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:paddingVertical="8dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/login_student_select_header_symbol_value"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="powiatjaroslawski" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/login_student_select_header_symbol_username"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:textColor="?android:textColorSecondary"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/login_student_select_header_symbol_value"
|
||||||
|
tools:text="Jan Kowalski" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/login_student_select_header_symbol_error"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textColor="?colorError"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/login_student_select_header_symbol_username"
|
||||||
|
tools:text="@tools:sample/lorem/random" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
61
app/src/main/res/layout/item_login_student_select_help.xml
Normal file
61
app/src/main/res/layout/item_login_student_select_help.xml
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:paddingVertical="8dp">
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/login_student_select_help_symbol"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="@string/login_symbol_enter"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/login_student_select_help_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="@string/login_contact_header"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/login_student_select_help_mail"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/login_student_select_help_symbol" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/login_student_select_help_mail"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:contentDescription="@string/login_contact_email"
|
||||||
|
app:icon="@drawable/ic_more_messages"
|
||||||
|
app:iconGravity="textStart"
|
||||||
|
app:iconPadding="0dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/login_student_select_help_title"
|
||||||
|
app:layout_constraintHorizontal_chainStyle="packed"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/login_student_select_help_title"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/login_student_select_help_symbol" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/login_student_select_help_discord"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:contentDescription="@string/login_contact_discord"
|
||||||
|
app:icon="@drawable/ic_about_discord"
|
||||||
|
app:iconGravity="textStart"
|
||||||
|
app:iconPadding="0dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/login_student_select_help_mail"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/login_student_select_help_mail" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -4,7 +4,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?selectableItemBackground"
|
android:background="?selectableItemBackground"
|
||||||
android:minHeight="72dp"
|
android:minHeight="56dp"
|
||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingBottom="8dp"
|
android:paddingBottom="8dp"
|
||||||
tools:context=".ui.modules.login.studentselect.LoginStudentSelectAdapter">
|
tools:context=".ui.modules.login.studentselect.LoginStudentSelectAdapter">
|
||||||
@ -14,9 +14,10 @@
|
|||||||
android:layout_width="32dp"
|
android:layout_width="32dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginStart="12dp"
|
android:layout_marginStart="32dp"
|
||||||
android:layout_marginEnd="28dp"
|
android:layout_marginEnd="28dp"
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
|
android:clickable="false"
|
||||||
tools:text=" " />
|
tools:text=" " />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -32,34 +33,18 @@
|
|||||||
tools:text="@tools:sample/full_names" />
|
tools:text="@tools:sample/full_names" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/loginItemSchool"
|
android:id="@+id/loginItemSignedIn"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/loginItemName"
|
android:layout_below="@id/loginItemName"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:layout_toEndOf="@id/loginItemCheck"
|
android:layout_toEndOf="@id/loginItemCheck"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:gravity="bottom"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:textColor="?android:textColorSecondary"
|
|
||||||
android:textSize="14sp"
|
|
||||||
tools:text="@tools:sample/lorem/random" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/loginItemSignedIn"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minHeight="20dp"
|
|
||||||
android:layout_below="@id/loginItemSchool"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_toEndOf="@id/loginItemCheck"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
android:gravity="bottom"
|
android:gravity="bottom"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
|
android:minHeight="20dp"
|
||||||
android:text="@string/login_signed_in"
|
android:text="@string/login_signed_in"
|
||||||
android:textColor="?android:textColorSecondary"
|
android:textColor="?android:textColorSecondary"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp" />
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
@ -55,7 +55,7 @@
|
|||||||
<string name="login_invalid_symbol">Invalid symbol</string>
|
<string name="login_invalid_symbol">Invalid symbol</string>
|
||||||
<string name="login_incorrect_symbol">Student not found. Validate the symbol and the chosen variation of the UONET+ register</string>
|
<string name="login_incorrect_symbol">Student not found. Validate the symbol and the chosen variation of the UONET+ register</string>
|
||||||
<string name="login_duplicate_student">Selected student is already logged in</string>
|
<string name="login_duplicate_student">Selected student is already logged in</string>
|
||||||
<string name="login_symbol_helper">The symbol can be found on the register page in <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Zarejestruj urządzenie mobilne</b>.\n\nMake sure that you have set the appropriate register variant in the <b>UONET+ register variant</b> field on the previous screen</string>
|
<string name="login_symbol_helper">The symbol can be found on the register page in <b>Uczeń</b> → <b>Dostęp Mobilny</b> → <b>Wygeneruj kod dostępu</b>.\n\nMake sure that you have set the appropriate register variant in the <b>UONET+ register variant</b> field on the first login screen</string>
|
||||||
<string name="login_select_student">Select students to log in to the application</string>
|
<string name="login_select_student">Select students to log in to the application</string>
|
||||||
<string name="login_advanced">Other options</string>
|
<string name="login_advanced">Other options</string>
|
||||||
<string name="login_advanced_warning_mobile_api">In this mode, a lucky number does not work, a class grade stats, summary of attendance, excuse for absence, completed lessons, school information and preview of the list of registered devices</string>
|
<string name="login_advanced_warning_mobile_api">In this mode, a lucky number does not work, a class grade stats, summary of attendance, excuse for absence, completed lessons, school information and preview of the list of registered devices</string>
|
||||||
@ -74,6 +74,9 @@
|
|||||||
<string name="login_recover">Recover</string>
|
<string name="login_recover">Recover</string>
|
||||||
<string name="login_signed_in">Student is already signed in</string>
|
<string name="login_signed_in">Student is already signed in</string>
|
||||||
<string name="login_host_standard">Standard</string>
|
<string name="login_host_standard">Standard</string>
|
||||||
|
<string name="login_other_search_locations">Other search locations</string>
|
||||||
|
<string name="login_no_active_student">No active students found</string>
|
||||||
|
<string name="login_symbol_enter">Enter a different symbol</string>
|
||||||
<!--Notifications-->
|
<!--Notifications-->
|
||||||
<string name="notifications_header_title">Enable notifications</string>
|
<string name="notifications_header_title">Enable notifications</string>
|
||||||
<string name="notifications_header_description">Enable notifications so you don\'t miss message from teacher or new grade</string>
|
<string name="notifications_header_description">Enable notifications so you don\'t miss message from teacher or new grade</string>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package io.github.wulkanowy.ui.modules.login.form
|
package io.github.wulkanowy.ui.modules.login.form
|
||||||
|
|
||||||
import io.github.wulkanowy.MainCoroutineRule
|
import io.github.wulkanowy.MainCoroutineRule
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
|
||||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.Scrapper
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||||
import io.mockk.*
|
import io.mockk.*
|
||||||
@ -12,7 +12,6 @@ import org.junit.Before
|
|||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
class LoginFormPresenterTest {
|
class LoginFormPresenterTest {
|
||||||
|
|
||||||
@ -33,6 +32,15 @@ class LoginFormPresenterTest {
|
|||||||
|
|
||||||
private lateinit var presenter: LoginFormPresenter
|
private lateinit var presenter: LoginFormPresenter
|
||||||
|
|
||||||
|
private val registerUser = RegisterUser(
|
||||||
|
email = "",
|
||||||
|
password = "",
|
||||||
|
login = "",
|
||||||
|
baseUrl = "",
|
||||||
|
loginType = Scrapper.LoginType.AUTO,
|
||||||
|
symbols = listOf(),
|
||||||
|
)
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockKAnnotations.init(this)
|
MockKAnnotations.init(this)
|
||||||
@ -104,32 +112,9 @@ class LoginFormPresenterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun loginTest() {
|
fun loginTest() {
|
||||||
val studentTest = Student(
|
coEvery {
|
||||||
email = "test@",
|
repository.getUserSubjectsFromScrapper(any(), any(), any(), any())
|
||||||
password = "123",
|
} returns registerUser
|
||||||
scrapperBaseUrl = "https://fakelog.cf/?email",
|
|
||||||
loginType = "AUTO",
|
|
||||||
studentName = "",
|
|
||||||
schoolSymbol = "",
|
|
||||||
schoolName = "",
|
|
||||||
studentId = 0,
|
|
||||||
classId = 1,
|
|
||||||
isCurrent = false,
|
|
||||||
symbol = "",
|
|
||||||
registrationDate = Instant.now(),
|
|
||||||
className = "",
|
|
||||||
mobileBaseUrl = "",
|
|
||||||
privateKey = "",
|
|
||||||
certificateKey = "",
|
|
||||||
loginMode = "",
|
|
||||||
userLoginId = 0,
|
|
||||||
schoolShortName = "",
|
|
||||||
isParent = false,
|
|
||||||
userName = ""
|
|
||||||
)
|
|
||||||
coEvery { repository.getStudentsScrapper(any(), any(), any(), any()) } returns listOf(
|
|
||||||
StudentWithSemesters(studentTest, emptyList())
|
|
||||||
)
|
|
||||||
|
|
||||||
every { loginFormView.formUsernameValue } returns "@"
|
every { loginFormView.formUsernameValue } returns "@"
|
||||||
every { loginFormView.formPassValue } returns "123456"
|
every { loginFormView.formPassValue } returns "123456"
|
||||||
@ -146,7 +131,9 @@ class LoginFormPresenterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun loginEmptyTest() {
|
fun loginEmptyTest() {
|
||||||
coEvery { repository.getStudentsScrapper(any(), any(), any(), any()) } returns listOf()
|
coEvery {
|
||||||
|
repository.getUserSubjectsFromScrapper(any(), any(), any(), any())
|
||||||
|
} returns registerUser
|
||||||
every { loginFormView.formUsernameValue } returns "@"
|
every { loginFormView.formUsernameValue } returns "@"
|
||||||
every { loginFormView.formPassValue } returns "123456"
|
every { loginFormView.formPassValue } returns "123456"
|
||||||
every { loginFormView.formHostValue } returns "https://fakelog.cf/?email"
|
every { loginFormView.formHostValue } returns "https://fakelog.cf/?email"
|
||||||
@ -162,7 +149,9 @@ class LoginFormPresenterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun loginEmptyTwiceTest() {
|
fun loginEmptyTwiceTest() {
|
||||||
coEvery { repository.getStudentsScrapper(any(), any(), any(), any()) } returns listOf()
|
coEvery {
|
||||||
|
repository.getUserSubjectsFromScrapper(any(), any(), any(), any())
|
||||||
|
} returns registerUser
|
||||||
every { loginFormView.formUsernameValue } returns "@"
|
every { loginFormView.formUsernameValue } returns "@"
|
||||||
every { loginFormView.formPassValue } returns "123456"
|
every { loginFormView.formPassValue } returns "123456"
|
||||||
every { loginFormView.formHostValue } returns "https://fakelog.cf/?email"
|
every { loginFormView.formHostValue } returns "https://fakelog.cf/?email"
|
||||||
@ -180,7 +169,14 @@ class LoginFormPresenterTest {
|
|||||||
@Test
|
@Test
|
||||||
fun loginErrorTest() {
|
fun loginErrorTest() {
|
||||||
val testException = IOException("test")
|
val testException = IOException("test")
|
||||||
coEvery { repository.getStudentsScrapper(any(), any(), any(), any()) } throws testException
|
coEvery {
|
||||||
|
repository.getUserSubjectsFromScrapper(
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
any()
|
||||||
|
)
|
||||||
|
} throws testException
|
||||||
every { loginFormView.formUsernameValue } returns "@"
|
every { loginFormView.formUsernameValue } returns "@"
|
||||||
every { loginFormView.formPassValue } returns "123456"
|
every { loginFormView.formPassValue } returns "123456"
|
||||||
every { loginFormView.formHostValue } returns "https://fakelog.cf/?email"
|
every { loginFormView.formHostValue } returns "https://fakelog.cf/?email"
|
||||||
|
@ -1,18 +1,22 @@
|
|||||||
package io.github.wulkanowy.ui.modules.login.studentselect
|
package io.github.wulkanowy.ui.modules.login.studentselect
|
||||||
|
|
||||||
import io.github.wulkanowy.MainCoroutineRule
|
import io.github.wulkanowy.MainCoroutineRule
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.pojos.RegisterStudent
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.pojos.RegisterSymbol
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterUnit
|
||||||
|
import io.github.wulkanowy.data.pojos.RegisterUser
|
||||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.Scrapper
|
||||||
import io.github.wulkanowy.services.sync.SyncManager
|
import io.github.wulkanowy.services.sync.SyncManager
|
||||||
|
import io.github.wulkanowy.ui.modules.login.LoginData
|
||||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||||
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import io.mockk.*
|
import io.mockk.*
|
||||||
import io.mockk.impl.annotations.MockK
|
import io.mockk.impl.annotations.MockK
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
class LoginStudentSelectPresenterTest {
|
class LoginStudentSelectPresenterTest {
|
||||||
|
|
||||||
@ -22,7 +26,7 @@ class LoginStudentSelectPresenterTest {
|
|||||||
@MockK(relaxed = true)
|
@MockK(relaxed = true)
|
||||||
lateinit var errorHandler: LoginErrorHandler
|
lateinit var errorHandler: LoginErrorHandler
|
||||||
|
|
||||||
@MockK(relaxed = true)
|
@MockK
|
||||||
lateinit var loginStudentSelectView: LoginStudentSelectView
|
lateinit var loginStudentSelectView: LoginStudentSelectView
|
||||||
|
|
||||||
@MockK
|
@MockK
|
||||||
@ -34,33 +38,55 @@ class LoginStudentSelectPresenterTest {
|
|||||||
@MockK(relaxed = true)
|
@MockK(relaxed = true)
|
||||||
lateinit var syncManager: SyncManager
|
lateinit var syncManager: SyncManager
|
||||||
|
|
||||||
|
private val appInfo = AppInfo()
|
||||||
|
|
||||||
private lateinit var presenter: LoginStudentSelectPresenter
|
private lateinit var presenter: LoginStudentSelectPresenter
|
||||||
|
|
||||||
private val testStudent by lazy {
|
private val loginData = LoginData(
|
||||||
Student(
|
login = "",
|
||||||
email = "test",
|
password = "",
|
||||||
password = "test123",
|
baseUrl = "",
|
||||||
scrapperBaseUrl = "https://fakelog.cf",
|
symbol = null,
|
||||||
loginType = "AUTO",
|
)
|
||||||
symbol = "",
|
|
||||||
isCurrent = false,
|
private val subject = RegisterStudent(
|
||||||
studentId = 0,
|
studentId = 0,
|
||||||
schoolName = "",
|
studentName = "",
|
||||||
schoolSymbol = "",
|
studentSecondName = "",
|
||||||
classId = 1,
|
studentSurname = "",
|
||||||
studentName = "",
|
className = "",
|
||||||
registrationDate = Instant.now(),
|
classId = 0,
|
||||||
className = "",
|
isParent = false,
|
||||||
loginMode = "",
|
semesters = listOf(),
|
||||||
certificateKey = "",
|
)
|
||||||
privateKey = "",
|
|
||||||
mobileBaseUrl = "",
|
private val school = RegisterUnit(
|
||||||
schoolShortName = "",
|
userLoginId = 0,
|
||||||
userLoginId = 1,
|
schoolId = "",
|
||||||
isParent = false,
|
schoolName = "",
|
||||||
userName = ""
|
schoolShortName = "",
|
||||||
)
|
parentIds = listOf(),
|
||||||
}
|
studentIds = listOf(),
|
||||||
|
employeeIds = listOf(),
|
||||||
|
error = null,
|
||||||
|
students = listOf(subject)
|
||||||
|
)
|
||||||
|
|
||||||
|
private val symbol = RegisterSymbol(
|
||||||
|
symbol = "",
|
||||||
|
error = null,
|
||||||
|
userName = "",
|
||||||
|
schools = listOf(school),
|
||||||
|
)
|
||||||
|
|
||||||
|
private val registerUser = RegisterUser(
|
||||||
|
email = "",
|
||||||
|
password = "",
|
||||||
|
login = "",
|
||||||
|
baseUrl = "",
|
||||||
|
loginType = Scrapper.LoginType.AUTO,
|
||||||
|
symbols = listOf(symbol),
|
||||||
|
)
|
||||||
|
|
||||||
private val testException by lazy { RuntimeException("Problem") }
|
private val testException by lazy { RuntimeException("Problem") }
|
||||||
|
|
||||||
@ -69,30 +95,44 @@ class LoginStudentSelectPresenterTest {
|
|||||||
MockKAnnotations.init(this)
|
MockKAnnotations.init(this)
|
||||||
|
|
||||||
clearMocks(studentRepository, loginStudentSelectView)
|
clearMocks(studentRepository, loginStudentSelectView)
|
||||||
|
|
||||||
|
coEvery { studentRepository.getSavedStudents(false) } returns emptyList()
|
||||||
|
|
||||||
every { loginStudentSelectView.initView() } just Runs
|
every { loginStudentSelectView.initView() } just Runs
|
||||||
every { loginStudentSelectView.showContact(any()) } just Runs
|
every { loginStudentSelectView.symbols } returns emptyMap()
|
||||||
|
|
||||||
every { loginStudentSelectView.enableSignIn(any()) } just Runs
|
every { loginStudentSelectView.enableSignIn(any()) } just Runs
|
||||||
every { loginStudentSelectView.showProgress(any()) } just Runs
|
every { loginStudentSelectView.showProgress(any()) } just Runs
|
||||||
every { loginStudentSelectView.showContent(any()) } just Runs
|
every { loginStudentSelectView.showContent(any()) } just Runs
|
||||||
|
|
||||||
presenter = LoginStudentSelectPresenter(studentRepository, errorHandler, syncManager, analytics)
|
presenter = LoginStudentSelectPresenter(
|
||||||
presenter.onAttachView(loginStudentSelectView, emptyList())
|
studentRepository = studentRepository,
|
||||||
|
loginErrorHandler = errorHandler,
|
||||||
|
syncManager = syncManager,
|
||||||
|
analytics = analytics,
|
||||||
|
appInfo = appInfo,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun initViewTest() {
|
fun initViewTest() {
|
||||||
|
presenter.onAttachView(loginStudentSelectView, loginData, registerUser)
|
||||||
verify { loginStudentSelectView.initView() }
|
verify { loginStudentSelectView.initView() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun onSelectedStudentTest() {
|
fun onSelectedStudentTest() {
|
||||||
coEvery {
|
val itemsSlot = slot<List<LoginStudentSelectItem>>()
|
||||||
studentRepository.saveStudents(listOf(StudentWithSemesters(testStudent, emptyList())))
|
every { loginStudentSelectView.updateData(capture(itemsSlot)) } just Runs
|
||||||
} just Runs
|
presenter.onAttachView(loginStudentSelectView, loginData, registerUser)
|
||||||
|
|
||||||
|
coEvery { studentRepository.saveStudents(any()) } just Runs
|
||||||
|
|
||||||
every { loginStudentSelectView.navigateToNext() } just Runs
|
every { loginStudentSelectView.navigateToNext() } just Runs
|
||||||
|
|
||||||
presenter.onItemSelected(StudentWithSemesters(testStudent, emptyList()), false)
|
itemsSlot.captured.filterIsInstance<LoginStudentSelectItem.Student>().first().let {
|
||||||
|
it.onClick(it)
|
||||||
|
}
|
||||||
presenter.onSignIn()
|
presenter.onSignIn()
|
||||||
|
|
||||||
verify { loginStudentSelectView.showContent(false) }
|
verify { loginStudentSelectView.showContent(false) }
|
||||||
@ -102,13 +142,15 @@ class LoginStudentSelectPresenterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun onSelectedStudentErrorTest() {
|
fun onSelectedStudentErrorTest() {
|
||||||
coEvery {
|
val itemsSlot = slot<List<LoginStudentSelectItem>>()
|
||||||
studentRepository.saveStudents(listOf(StudentWithSemesters(testStudent, emptyList())))
|
every { loginStudentSelectView.updateData(capture(itemsSlot)) } just Runs
|
||||||
} throws testException
|
presenter.onAttachView(loginStudentSelectView, loginData, registerUser)
|
||||||
|
|
||||||
coEvery { studentRepository.logoutStudent(testStudent) } just Runs
|
coEvery { studentRepository.saveStudents(any()) } throws testException
|
||||||
|
|
||||||
presenter.onItemSelected(StudentWithSemesters(testStudent, emptyList()), false)
|
itemsSlot.captured.filterIsInstance<LoginStudentSelectItem.Student>().first().let {
|
||||||
|
it.onClick(it)
|
||||||
|
}
|
||||||
presenter.onSignIn()
|
presenter.onSignIn()
|
||||||
|
|
||||||
verify { loginStudentSelectView.showContent(false) }
|
verify { loginStudentSelectView.showContent(false) }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user