Fix login process after was interrupted (#1505)

This commit is contained in:
Rafał Borcz 2021-09-13 14:36:31 +02:00 committed by GitHub
parent 19c96ee83f
commit 827fb33eeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 76 additions and 76 deletions

View File

@ -14,33 +14,39 @@ import javax.inject.Singleton
@Singleton
@Dao
interface StudentDao {
abstract class StudentDao {
@Insert(onConflict = ABORT)
suspend fun insertAll(student: List<Student>): List<Long>
abstract suspend fun insertAll(student: List<Student>): List<Long>
@Delete
suspend fun delete(student: Student)
abstract suspend fun delete(student: Student)
@Update(entity = Student::class)
suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
abstract suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
@Query("SELECT * FROM Students WHERE is_current = 1")
suspend fun loadCurrent(): Student?
abstract suspend fun loadCurrent(): Student?
@Query("SELECT * FROM Students WHERE id = :id")
suspend fun loadById(id: Long): Student?
abstract suspend fun loadById(id: Long): Student?
@Query("SELECT * FROM Students")
suspend fun loadAll(): List<Student>
abstract suspend fun loadAll(): List<Student>
@Transaction
@Query("SELECT * FROM Students")
suspend fun loadStudentsWithSemesters(): List<StudentWithSemesters>
abstract suspend fun loadStudentsWithSemesters(): List<StudentWithSemesters>
@Query("UPDATE Students SET is_current = 1 WHERE id = :id")
suspend fun updateCurrent(id: Long)
abstract suspend fun updateCurrent(id: Long)
@Query("UPDATE Students SET is_current = 0")
suspend fun resetCurrent()
abstract suspend fun resetCurrent()
@Transaction
open suspend fun switchCurrent(id: Long) {
resetCurrent()
updateCurrent(id)
}
}

View File

@ -1,7 +1,9 @@
package io.github.wulkanowy.data.repositories
import android.content.Context
import androidx.room.withTransaction
import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.dao.SemesterDao
import io.github.wulkanowy.data.db.dao.StudentDao
import io.github.wulkanowy.data.db.entities.Student
@ -25,7 +27,8 @@ class StudentRepository @Inject constructor(
private val studentDb: StudentDao,
private val semesterDb: SemesterDao,
private val sdk: Sdk,
private val appInfo: AppInfo
private val appInfo: AppInfo,
private val appDatabase: AppDatabase
) {
suspend fun isStudentSaved() = getSavedStudents(false).isNotEmpty()
@ -92,7 +95,7 @@ class StudentRepository @Inject constructor(
return student
}
suspend fun saveStudents(studentsWithSemesters: List<StudentWithSemesters>): List<Long> {
suspend fun saveStudents(studentsWithSemesters: List<StudentWithSemesters>) {
val semesters = studentsWithSemesters.flatMap { it.semesters }
val students = studentsWithSemesters.map { it.student }
.map {
@ -104,16 +107,21 @@ class StudentRepository @Inject constructor(
}
}
}
.mapIndexed { index, student ->
if (index == 0) {
student.copy(isCurrent = true).apply { avatarColor = student.avatarColor }
} else student
}
semesterDb.insertSemesters(semesters)
return studentDb.insertAll(students)
appDatabase.withTransaction {
studentDb.resetCurrent()
semesterDb.insertSemesters(semesters)
studentDb.insertAll(students)
}
}
suspend fun switchStudent(studentWithSemesters: StudentWithSemesters) {
with(studentDb) {
resetCurrent()
updateCurrent(studentWithSemesters.student.id)
}
studentDb.switchCurrent(studentWithSemesters.student.id)
}
suspend fun logoutStudent(student: Student) = studentDb.delete(student)

View File

@ -90,10 +90,10 @@ class LoginFormPresenter @Inject constructor(
flowWithResource {
studentRepository.getStudentsScrapper(
email,
password,
host,
symbol
email = email,
password = password,
scrapperBaseUrl = host,
symbol = symbol
)
}.onEach {
when (it.status) {

View File

@ -78,7 +78,9 @@ class LoginStudentSelectPresenter @Inject constructor(
when (it.status) {
Status.LOADING -> Timber.d("Login student select students load started")
Status.SUCCESS -> view?.updateData(studentsWithSemesters.map { studentWithSemesters ->
studentWithSemesters to it.data!!.any { item -> compareStudents(studentWithSemesters.student, item.student) }
studentWithSemesters to it.data!!.any { item ->
compareStudents(studentWithSemesters.student, item.student)
}
})
Status.ERROR -> {
errorHandler.dispatch(it.error!!)
@ -95,35 +97,32 @@ class LoginStudentSelectPresenter @Inject constructor(
}
private fun registerStudents(studentsWithSemesters: List<StudentWithSemesters>) {
flowWithResource {
val savedStudents = studentRepository.saveStudents(studentsWithSemesters)
val firstRegistered = studentsWithSemesters.first().apply { student.id = savedStudents.first() }
studentRepository.switchStudent(firstRegistered)
}.onEach {
when (it.status) {
Status.LOADING -> view?.run {
Timber.i("Registration started")
showProgress(true)
showContent(false)
}
Status.SUCCESS -> {
Timber.i("Registration result: Success")
view?.openMainView()
logRegisterEvent(studentsWithSemesters)
}
Status.ERROR -> {
Timber.i("Registration result: An exception occurred ")
view?.apply {
showProgress(false)
showContent(true)
showContact(true)
flowWithResource { studentRepository.saveStudents(studentsWithSemesters) }
.onEach {
when (it.status) {
Status.LOADING -> view?.run {
Timber.i("Registration started")
showProgress(true)
showContent(false)
}
Status.SUCCESS -> {
Timber.i("Registration result: Success")
view?.openMainView()
logRegisterEvent(studentsWithSemesters)
}
Status.ERROR -> {
Timber.i("Registration result: An exception occurred ")
view?.apply {
showProgress(false)
showContent(true)
showContact(true)
}
lastError = it.error
loginErrorHandler.dispatch(it.error!!)
logRegisterEvent(studentsWithSemesters, it.error)
}
lastError = it.error
loginErrorHandler.dispatch(it.error!!)
logRegisterEvent(studentsWithSemesters, it.error)
}
}
}.launch("register")
}.launch("register")
}
fun onDiscordClick() {
@ -134,7 +133,10 @@ class LoginStudentSelectPresenter @Inject constructor(
view?.openEmail(lastError?.message.ifNullOrBlank { "empty" })
}
private fun logRegisterEvent(studentsWithSemesters: List<StudentWithSemesters>, error: Throwable? = null) {
private fun logRegisterEvent(
studentsWithSemesters: List<StudentWithSemesters>,
error: Throwable? = null
) {
studentsWithSemesters.forEach { student ->
analytics.logEvent(
"registration_student_select",

View File

@ -37,7 +37,8 @@ class StudentTest {
studentDb,
semesterDb,
mockSdk,
AppInfo()
AppInfo(),
mockk()
)
}

View File

@ -89,24 +89,11 @@ class LoginStudentSelectPresenterTest {
@Test
fun onSelectedStudentTest() {
coEvery {
studentRepository.saveStudents(
listOf(
StudentWithSemesters(
testStudent,
emptyList()
)
)
)
} returns listOf(1L)
coEvery {
studentRepository.switchStudent(
StudentWithSemesters(
testStudent,
emptyList()
)
)
studentRepository.saveStudents(listOf(StudentWithSemesters(testStudent, emptyList())))
} just Runs
every { loginStudentSelectView.openMainView() } just Runs
presenter.onItemSelected(StudentWithSemesters(testStudent, emptyList()), false)
presenter.onSignIn()
@ -118,18 +105,14 @@ class LoginStudentSelectPresenterTest {
@Test
fun onSelectedStudentErrorTest() {
coEvery {
studentRepository.saveStudents(
listOf(
StudentWithSemesters(
testStudent,
emptyList()
)
)
)
studentRepository.saveStudents(listOf(StudentWithSemesters(testStudent, emptyList())))
} throws testException
coEvery { studentRepository.logoutStudent(testStudent) } just Runs
presenter.onItemSelected(StudentWithSemesters(testStudent, emptyList()), false)
presenter.onSignIn()
verify { loginStudentSelectView.showContent(false) }
verify { loginStudentSelectView.showProgress(true) }
verify { errorHandler.dispatch(match { testException.message == it.message }) }