mirror of
https://github.com/wulkanowy/wulkanowy.git
synced 2025-01-20 02:16:44 -06:00
Merge branch 'release/1.2.2'
This commit is contained in:
commit
6a00e75816
2
.github/workflows/deploy-store.yml
vendored
2
.github/workflows/deploy-store.yml
vendored
@ -71,4 +71,4 @@ jobs:
|
|||||||
PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
|
PLAY_KEY_ALIAS: ${{ secrets.PLAY_KEY_ALIAS }}
|
||||||
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
|
PLAY_KEY_PASSWORD: ${{ secrets.PLAY_KEY_PASSWORD }}
|
||||||
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
PLAY_STORE_PASSWORD: ${{ secrets.PLAY_STORE_PASSWORD }}
|
||||||
run: ./gradlew assembleHmsRelease --stacktrace && ./gradlew publishHuaweiAppGalleryHmsRelease --stacktrace
|
run: ./gradlew bundleHmsRelease --stacktrace && ./gradlew publishHuaweiAppGalleryHmsRelease --stacktrace
|
||||||
|
@ -21,8 +21,8 @@ android {
|
|||||||
testApplicationId "io.github.tests.wulkanowy"
|
testApplicationId "io.github.tests.wulkanowy"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode 94
|
versionCode 95
|
||||||
versionName "1.2.1"
|
versionName "1.2.2"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|
||||||
@ -141,14 +141,14 @@ huaweiPublish {
|
|||||||
instances {
|
instances {
|
||||||
hmsRelease {
|
hmsRelease {
|
||||||
credentialsPath = "$rootDir/app/src/release/agconnect-credentials.json"
|
credentialsPath = "$rootDir/app/src/release/agconnect-credentials.json"
|
||||||
buildFormat = "apk"
|
buildFormat = "aab"
|
||||||
deployType = "draft"
|
deployType = "draft"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
work_manager = "2.5.0"
|
work_manager = "2.6.0"
|
||||||
android_hilt = "1.0.0"
|
android_hilt = "1.0.0"
|
||||||
room = "2.3.0"
|
room = "2.3.0"
|
||||||
chucker = "3.5.2"
|
chucker = "3.5.2"
|
||||||
@ -157,7 +157,7 @@ ext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "io.github.wulkanowy:sdk:1.2.1"
|
implementation "io.github.wulkanowy:sdk:1.2.2"
|
||||||
|
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ dependencies {
|
|||||||
implementation "androidx.constraintlayout:constraintlayout:2.1.0"
|
implementation "androidx.constraintlayout:constraintlayout:2.1.0"
|
||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
||||||
implementation "com.google.android.material:material:1.4.0"
|
implementation "com.google.android.material:material:1.4.0"
|
||||||
implementation "com.github.wulkanowy:material-chips-input:2.2.0"
|
implementation "com.github.wulkanowy:material-chips-input:2.3.1"
|
||||||
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
implementation "com.github.PhilJay:MPAndroidChart:v3.1.0"
|
||||||
implementation 'com.github.lopspower:CircularImageView:4.2.0'
|
implementation 'com.github.lopspower:CircularImageView:4.2.0'
|
||||||
|
|
||||||
|
@ -119,11 +119,9 @@
|
|||||||
<receiver android:name=".services.alarm.TimetableNotificationReceiver" />
|
<receiver android:name=".services.alarm.TimetableNotificationReceiver" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.work.impl.WorkManagerInitializer"
|
android:name="androidx.startup.InitializationProvider"
|
||||||
android:authorities="${applicationId}.workmanager-init"
|
android:authorities="${applicationId}.androidx-startup"
|
||||||
android:exported="false"
|
|
||||||
tools:node="remove" />
|
tools:node="remove" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}.fileprovider"
|
android:authorities="${applicationId}.fileprovider"
|
||||||
|
@ -14,33 +14,39 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Dao
|
@Dao
|
||||||
interface StudentDao {
|
abstract class StudentDao {
|
||||||
|
|
||||||
@Insert(onConflict = ABORT)
|
@Insert(onConflict = ABORT)
|
||||||
suspend fun insertAll(student: List<Student>): List<Long>
|
abstract suspend fun insertAll(student: List<Student>): List<Long>
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
suspend fun delete(student: Student)
|
abstract suspend fun delete(student: Student)
|
||||||
|
|
||||||
@Update(entity = Student::class)
|
@Update(entity = Student::class)
|
||||||
suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
|
abstract suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
|
||||||
|
|
||||||
@Query("SELECT * FROM Students WHERE is_current = 1")
|
@Query("SELECT * FROM Students WHERE is_current = 1")
|
||||||
suspend fun loadCurrent(): Student?
|
abstract suspend fun loadCurrent(): Student?
|
||||||
|
|
||||||
@Query("SELECT * FROM Students WHERE id = :id")
|
@Query("SELECT * FROM Students WHERE id = :id")
|
||||||
suspend fun loadById(id: Long): Student?
|
abstract suspend fun loadById(id: Long): Student?
|
||||||
|
|
||||||
@Query("SELECT * FROM Students")
|
@Query("SELECT * FROM Students")
|
||||||
suspend fun loadAll(): List<Student>
|
abstract suspend fun loadAll(): List<Student>
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM Students")
|
@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")
|
@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")
|
@Query("UPDATE Students SET is_current = 0")
|
||||||
suspend fun resetCurrent()
|
abstract suspend fun resetCurrent()
|
||||||
|
|
||||||
|
@Transaction
|
||||||
|
open suspend fun switchCurrent(id: Long) {
|
||||||
|
resetCurrent()
|
||||||
|
updateCurrent(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package io.github.wulkanowy.data.repositories
|
package io.github.wulkanowy.data.repositories
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.room.withTransaction
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
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.SemesterDao
|
||||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
@ -25,7 +27,8 @@ class StudentRepository @Inject constructor(
|
|||||||
private val studentDb: StudentDao,
|
private val studentDb: StudentDao,
|
||||||
private val semesterDb: SemesterDao,
|
private val semesterDb: SemesterDao,
|
||||||
private val sdk: Sdk,
|
private val sdk: Sdk,
|
||||||
private val appInfo: AppInfo
|
private val appInfo: AppInfo,
|
||||||
|
private val appDatabase: AppDatabase
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun isStudentSaved() = getSavedStudents(false).isNotEmpty()
|
suspend fun isStudentSaved() = getSavedStudents(false).isNotEmpty()
|
||||||
@ -92,7 +95,7 @@ class StudentRepository @Inject constructor(
|
|||||||
return student
|
return student
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun saveStudents(studentsWithSemesters: List<StudentWithSemesters>): List<Long> {
|
suspend fun saveStudents(studentsWithSemesters: List<StudentWithSemesters>) {
|
||||||
val semesters = studentsWithSemesters.flatMap { it.semesters }
|
val semesters = studentsWithSemesters.flatMap { it.semesters }
|
||||||
val students = studentsWithSemesters.map { it.student }
|
val students = studentsWithSemesters.map { it.student }
|
||||||
.map {
|
.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)
|
appDatabase.withTransaction {
|
||||||
return studentDb.insertAll(students)
|
studentDb.resetCurrent()
|
||||||
|
semesterDb.insertSemesters(semesters)
|
||||||
|
studentDb.insertAll(students)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun switchStudent(studentWithSemesters: StudentWithSemesters) {
|
suspend fun switchStudent(studentWithSemesters: StudentWithSemesters) {
|
||||||
with(studentDb) {
|
studentDb.switchCurrent(studentWithSemesters.student.id)
|
||||||
resetCurrent()
|
|
||||||
updateCurrent(studentWithSemesters.student.id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun logoutStudent(student: Student) = studentDb.delete(student)
|
suspend fun logoutStudent(student: Student) = studentDb.delete(student)
|
||||||
|
@ -245,7 +245,9 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
|||||||
presenter.onDateSet(date.year, date.monthValue, date.dayOfMonth)
|
presenter.onDateSet(date.year, date.monthValue, date.dayOfMonth)
|
||||||
}
|
}
|
||||||
|
|
||||||
datePicker.show(this@AttendanceFragment.parentFragmentManager, null)
|
if (!parentFragmentManager.isStateSaved) {
|
||||||
|
datePicker.show(parentFragmentManager, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showExcuseDialog() {
|
override fun showExcuseDialog() {
|
||||||
|
@ -152,6 +152,8 @@ class AttendancePresenter @Inject constructor(
|
|||||||
fun onExcuseDialogSubmit(reason: String) {
|
fun onExcuseDialogSubmit(reason: String) {
|
||||||
view?.finishActionMode()
|
view?.finishActionMode()
|
||||||
|
|
||||||
|
if (attendanceToExcuseList.isEmpty()) return
|
||||||
|
|
||||||
if (isVulcanExcusedFunctionEnabled) {
|
if (isVulcanExcusedFunctionEnabled) {
|
||||||
excuseAbsence(
|
excuseAbsence(
|
||||||
reason = reason.takeIf { it.isNotBlank() },
|
reason = reason.takeIf { it.isNotBlank() },
|
||||||
@ -234,6 +236,7 @@ class AttendancePresenter @Inject constructor(
|
|||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
showRefresh(true)
|
showRefresh(true)
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
|
showErrorView(false)
|
||||||
showEmpty(filteredAttendance.isEmpty())
|
showEmpty(filteredAttendance.isEmpty())
|
||||||
showContent(filteredAttendance.isNotEmpty())
|
showContent(filteredAttendance.isNotEmpty())
|
||||||
updateData(filteredAttendance.sortedBy { item -> item.number })
|
updateData(filteredAttendance.sortedBy { item -> item.number })
|
||||||
|
@ -82,7 +82,13 @@ class AttendanceSummaryPresenter @Inject constructor(
|
|||||||
flowWithResourceIn {
|
flowWithResourceIn {
|
||||||
val student = studentRepository.getCurrentStudent()
|
val student = studentRepository.getCurrentStudent()
|
||||||
val semester = semesterRepository.getCurrentSemester(student)
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
attendanceSummaryRepository.getAttendanceSummary(student, semester, subjectId, forceRefresh)
|
|
||||||
|
attendanceSummaryRepository.getAttendanceSummary(
|
||||||
|
student = student,
|
||||||
|
semester = semester,
|
||||||
|
subjectId = subjectId,
|
||||||
|
forceRefresh = forceRefresh
|
||||||
|
)
|
||||||
}.onEach {
|
}.onEach {
|
||||||
when (it.status) {
|
when (it.status) {
|
||||||
Status.LOADING -> {
|
Status.LOADING -> {
|
||||||
@ -92,6 +98,7 @@ class AttendanceSummaryPresenter @Inject constructor(
|
|||||||
showRefresh(true)
|
showRefresh(true)
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
showContent(true)
|
showContent(true)
|
||||||
|
showErrorView(false)
|
||||||
updateDataSet(sortItems(it.data))
|
updateDataSet(sortItems(it.data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,6 +106,7 @@ class AttendanceSummaryPresenter @Inject constructor(
|
|||||||
Status.SUCCESS -> {
|
Status.SUCCESS -> {
|
||||||
Timber.i("Loading attendance summary result: Success")
|
Timber.i("Loading attendance summary result: Success")
|
||||||
view?.apply {
|
view?.apply {
|
||||||
|
showErrorView(false)
|
||||||
showEmpty(it.data!!.isEmpty())
|
showEmpty(it.data!!.isEmpty())
|
||||||
showContent(it.data.isNotEmpty())
|
showContent(it.data.isNotEmpty())
|
||||||
updateDataSet(sortItems(it.data))
|
updateDataSet(sortItems(it.data))
|
||||||
|
@ -31,6 +31,7 @@ import io.github.wulkanowy.utils.getThemeAttrColor
|
|||||||
import io.github.wulkanowy.utils.left
|
import io.github.wulkanowy.utils.left
|
||||||
import io.github.wulkanowy.utils.nickOrName
|
import io.github.wulkanowy.utils.nickOrName
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
|
import timber.log.Timber
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
@ -170,6 +171,8 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
|
|||||||
val isLoading = item.isLoading
|
val isLoading = item.isLoading
|
||||||
val binding = horizontalGroupViewHolder.binding
|
val binding = horizontalGroupViewHolder.binding
|
||||||
val context = binding.root.context
|
val context = binding.root.context
|
||||||
|
val isLoadingVisible =
|
||||||
|
(isLoading && !item.isDataLoaded) || (isLoading && !item.isFullDataLoaded)
|
||||||
val attendanceColor = when {
|
val attendanceColor = when {
|
||||||
attendancePercentage == null || attendancePercentage == .0 -> {
|
attendancePercentage == null || attendancePercentage == .0 -> {
|
||||||
context.getThemeAttrColor(R.attr.colorOnSurface)
|
context.getThemeAttrColor(R.attr.colorOnSurface)
|
||||||
@ -199,13 +202,12 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
|
|||||||
context.getString(R.string.dashboard_horizontal_group_no_data)
|
context.getString(R.string.dashboard_horizontal_group_no_data)
|
||||||
} else luckyNumber?.toString()
|
} else luckyNumber?.toString()
|
||||||
|
|
||||||
dashboardHorizontalGroupItemInfoContainer.isVisible = error != null || isLoading
|
dashboardHorizontalGroupItemInfoContainer.isVisible = error != null || isLoadingVisible
|
||||||
dashboardHorizontalGroupItemInfoProgress.isVisible =
|
dashboardHorizontalGroupItemInfoProgress.isVisible = isLoadingVisible
|
||||||
(isLoading && !item.isDataLoaded) || (isLoading && !item.isFullDataLoaded)
|
|
||||||
dashboardHorizontalGroupItemInfoErrorText.isVisible = error != null
|
dashboardHorizontalGroupItemInfoErrorText.isVisible = error != null
|
||||||
|
|
||||||
with(dashboardHorizontalGroupItemLuckyContainer) {
|
with(dashboardHorizontalGroupItemLuckyContainer) {
|
||||||
isVisible = luckyNumber != null && luckyNumber != -1
|
isVisible = luckyNumber != null && luckyNumber != -1 && !isLoadingVisible
|
||||||
setOnClickListener { onLuckyNumberTileClickListener() }
|
setOnClickListener { onLuckyNumberTileClickListener() }
|
||||||
|
|
||||||
updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
@ -220,7 +222,8 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
|
|||||||
}
|
}
|
||||||
|
|
||||||
with(dashboardHorizontalGroupItemAttendanceContainer) {
|
with(dashboardHorizontalGroupItemAttendanceContainer) {
|
||||||
isVisible = attendancePercentage != null && attendancePercentage != -1.0
|
isVisible =
|
||||||
|
attendancePercentage != null && attendancePercentage != -1.0 && !isLoadingVisible
|
||||||
updateLayoutParams<ConstraintLayout.LayoutParams> {
|
updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||||
matchConstraintPercentWidth = when {
|
matchConstraintPercentWidth = when {
|
||||||
luckyNumber == null && unreadMessagesCount == null -> 1.0f
|
luckyNumber == null && unreadMessagesCount == null -> 1.0f
|
||||||
@ -232,7 +235,8 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
|
|||||||
}
|
}
|
||||||
|
|
||||||
with(dashboardHorizontalGroupItemMessageContainer) {
|
with(dashboardHorizontalGroupItemMessageContainer) {
|
||||||
isVisible = unreadMessagesCount != null && unreadMessagesCount != -1
|
isVisible =
|
||||||
|
unreadMessagesCount != null && unreadMessagesCount != -1 && !isLoadingVisible
|
||||||
setOnClickListener { onMessageTileClickListener() }
|
setOnClickListener { onMessageTileClickListener() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,7 +430,10 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val minutesToEndLesson = firstLesson.left!!.toMinutes() + 1
|
val minutesToEndLesson = firstLesson.left?.toMinutes()?.plus(1) ?: run {
|
||||||
|
Timber.e(IllegalArgumentException("Lesson left is null. START ${firstLesson.start} ; END ${firstLesson.end} ; CURRENT ${LocalDateTime.now()}"))
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
firstTimeText = context.resources.getQuantityString(
|
firstTimeText = context.resources.getQuantityString(
|
||||||
R.plurals.dashboard_timetable_first_lesson_time_more_minutes,
|
R.plurals.dashboard_timetable_first_lesson_time_more_minutes,
|
||||||
|
@ -90,10 +90,10 @@ class LoginFormPresenter @Inject constructor(
|
|||||||
|
|
||||||
flowWithResource {
|
flowWithResource {
|
||||||
studentRepository.getStudentsScrapper(
|
studentRepository.getStudentsScrapper(
|
||||||
email,
|
email = email,
|
||||||
password,
|
password = password,
|
||||||
host,
|
scrapperBaseUrl = host,
|
||||||
symbol
|
symbol = symbol
|
||||||
)
|
)
|
||||||
}.onEach {
|
}.onEach {
|
||||||
when (it.status) {
|
when (it.status) {
|
||||||
|
@ -78,7 +78,9 @@ class LoginStudentSelectPresenter @Inject constructor(
|
|||||||
when (it.status) {
|
when (it.status) {
|
||||||
Status.LOADING -> Timber.d("Login student select students load started")
|
Status.LOADING -> Timber.d("Login student select students load started")
|
||||||
Status.SUCCESS -> view?.updateData(studentsWithSemesters.map { studentWithSemesters ->
|
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 -> {
|
Status.ERROR -> {
|
||||||
errorHandler.dispatch(it.error!!)
|
errorHandler.dispatch(it.error!!)
|
||||||
@ -95,35 +97,32 @@ class LoginStudentSelectPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun registerStudents(studentsWithSemesters: List<StudentWithSemesters>) {
|
private fun registerStudents(studentsWithSemesters: List<StudentWithSemesters>) {
|
||||||
flowWithResource {
|
flowWithResource { studentRepository.saveStudents(studentsWithSemesters) }
|
||||||
val savedStudents = studentRepository.saveStudents(studentsWithSemesters)
|
.onEach {
|
||||||
val firstRegistered = studentsWithSemesters.first().apply { student.id = savedStudents.first() }
|
when (it.status) {
|
||||||
studentRepository.switchStudent(firstRegistered)
|
Status.LOADING -> view?.run {
|
||||||
}.onEach {
|
Timber.i("Registration started")
|
||||||
when (it.status) {
|
showProgress(true)
|
||||||
Status.LOADING -> view?.run {
|
showContent(false)
|
||||||
Timber.i("Registration started")
|
}
|
||||||
showProgress(true)
|
Status.SUCCESS -> {
|
||||||
showContent(false)
|
Timber.i("Registration result: Success")
|
||||||
}
|
view?.openMainView()
|
||||||
Status.SUCCESS -> {
|
logRegisterEvent(studentsWithSemesters)
|
||||||
Timber.i("Registration result: Success")
|
}
|
||||||
view?.openMainView()
|
Status.ERROR -> {
|
||||||
logRegisterEvent(studentsWithSemesters)
|
Timber.i("Registration result: An exception occurred ")
|
||||||
}
|
view?.apply {
|
||||||
Status.ERROR -> {
|
showProgress(false)
|
||||||
Timber.i("Registration result: An exception occurred ")
|
showContent(true)
|
||||||
view?.apply {
|
showContact(true)
|
||||||
showProgress(false)
|
}
|
||||||
showContent(true)
|
lastError = it.error
|
||||||
showContact(true)
|
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() {
|
fun onDiscordClick() {
|
||||||
@ -134,7 +133,10 @@ class LoginStudentSelectPresenter @Inject constructor(
|
|||||||
view?.openEmail(lastError?.message.ifNullOrBlank { "empty" })
|
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 ->
|
studentsWithSemesters.forEach { student ->
|
||||||
analytics.logEvent(
|
analytics.logEvent(
|
||||||
"registration_student_select",
|
"registration_student_select",
|
||||||
|
@ -131,7 +131,9 @@ class LuckyNumberHistoryFragment :
|
|||||||
presenter.onDateSet(date.year, date.monthValue, date.dayOfMonth)
|
presenter.onDateSet(date.year, date.monthValue, date.dayOfMonth)
|
||||||
}
|
}
|
||||||
|
|
||||||
datePicker.show(this@LuckyNumberHistoryFragment.parentFragmentManager, null)
|
if (!parentFragmentManager.isStateSaved) {
|
||||||
|
datePicker.show(parentFragmentManager, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showContent(show: Boolean) {
|
override fun showContent(show: Boolean) {
|
||||||
|
@ -117,6 +117,7 @@ class MessageTabPresenter @Inject constructor(
|
|||||||
if (!it.data.isNullOrEmpty()) {
|
if (!it.data.isNullOrEmpty()) {
|
||||||
view?.run {
|
view?.run {
|
||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
|
showErrorView(false)
|
||||||
showRefresh(true)
|
showRefresh(true)
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
showContent(true)
|
showContent(true)
|
||||||
|
@ -11,6 +11,7 @@ import io.github.wulkanowy.ui.base.BaseFragment
|
|||||||
import io.github.wulkanowy.ui.modules.conference.ConferenceFragment
|
import io.github.wulkanowy.ui.modules.conference.ConferenceFragment
|
||||||
import io.github.wulkanowy.ui.modules.exam.ExamFragment
|
import io.github.wulkanowy.ui.modules.exam.ExamFragment
|
||||||
import io.github.wulkanowy.ui.modules.homework.HomeworkFragment
|
import io.github.wulkanowy.ui.modules.homework.HomeworkFragment
|
||||||
|
import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment
|
||||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
import io.github.wulkanowy.ui.modules.message.MessageFragment
|
import io.github.wulkanowy.ui.modules.message.MessageFragment
|
||||||
@ -66,6 +67,9 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
|
|||||||
override val examRes: Pair<String, Drawable?>?
|
override val examRes: Pair<String, Drawable?>?
|
||||||
get() = context?.run { getString(R.string.exam_title) to getCompatDrawable(R.drawable.ic_main_exam) }
|
get() = context?.run { getString(R.string.exam_title) to getCompatDrawable(R.drawable.ic_main_exam) }
|
||||||
|
|
||||||
|
override val luckyNumberRes: Pair<String, Drawable?>?
|
||||||
|
get() = context?.run { getString(R.string.lucky_number_title) to getCompatDrawable(R.drawable.ic_more_lucky_number) }
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
binding = FragmentMoreBinding.bind(view)
|
binding = FragmentMoreBinding.bind(view)
|
||||||
@ -128,6 +132,10 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
|
|||||||
(activity as? MainActivity)?.pushView(ExamFragment.newInstance())
|
(activity as? MainActivity)?.pushView(ExamFragment.newInstance())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun openLuckyNumberView() {
|
||||||
|
(activity as? MainActivity)?.pushView(LuckyNumberFragment.newInstance())
|
||||||
|
}
|
||||||
|
|
||||||
override fun popView(depth: Int) {
|
override fun popView(depth: Int) {
|
||||||
(activity as? MainActivity)?.popView(depth)
|
(activity as? MainActivity)?.popView(depth)
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ class MorePresenter @Inject constructor(
|
|||||||
schoolAndTeachersRes?.first -> openSchoolAndTeachersView()
|
schoolAndTeachersRes?.first -> openSchoolAndTeachersView()
|
||||||
mobileDevicesRes?.first -> openMobileDevicesView()
|
mobileDevicesRes?.first -> openMobileDevicesView()
|
||||||
settingsRes?.first -> openSettingsView()
|
settingsRes?.first -> openSettingsView()
|
||||||
|
luckyNumberRes?.first -> openLuckyNumberView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,6 +49,7 @@ class MorePresenter @Inject constructor(
|
|||||||
examRes,
|
examRes,
|
||||||
homeworkRes,
|
homeworkRes,
|
||||||
noteRes,
|
noteRes,
|
||||||
|
luckyNumberRes,
|
||||||
conferencesRes,
|
conferencesRes,
|
||||||
schoolAnnouncementRes,
|
schoolAnnouncementRes,
|
||||||
schoolAndTeachersRes,
|
schoolAndTeachersRes,
|
||||||
|
@ -23,6 +23,8 @@ interface MoreView : BaseView {
|
|||||||
|
|
||||||
val examRes: Pair<String, Drawable?>?
|
val examRes: Pair<String, Drawable?>?
|
||||||
|
|
||||||
|
val luckyNumberRes: Pair<String, Drawable?>?
|
||||||
|
|
||||||
fun initView()
|
fun initView()
|
||||||
|
|
||||||
fun updateData(data: List<Pair<String, Drawable?>>)
|
fun updateData(data: List<Pair<String, Drawable?>>)
|
||||||
@ -46,4 +48,6 @@ interface MoreView : BaseView {
|
|||||||
fun openMobileDevicesView()
|
fun openMobileDevicesView()
|
||||||
|
|
||||||
fun openExamView()
|
fun openExamView()
|
||||||
|
|
||||||
|
fun openLuckyNumberView()
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,7 @@ class SchoolAnnouncementPresenter @Inject constructor(
|
|||||||
view?.run {
|
view?.run {
|
||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
showRefresh(true)
|
showRefresh(true)
|
||||||
|
showErrorView(false)
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
showContent(true)
|
showContent(true)
|
||||||
updateData(it.data)
|
updateData(it.data)
|
||||||
|
@ -202,7 +202,9 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
|
|||||||
presenter.onDateSet(date.year, date.monthValue, date.dayOfMonth)
|
presenter.onDateSet(date.year, date.monthValue, date.dayOfMonth)
|
||||||
}
|
}
|
||||||
|
|
||||||
datePicker.show(this@TimetableFragment.parentFragmentManager, null)
|
if (!parentFragmentManager.isStateSaved) {
|
||||||
|
datePicker.show(parentFragmentManager, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openAdditionalLessonsView() {
|
override fun openAdditionalLessonsView() {
|
||||||
|
@ -149,6 +149,7 @@ class TimetablePresenter @Inject constructor(
|
|||||||
view?.run {
|
view?.run {
|
||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
showRefresh(true)
|
showRefresh(true)
|
||||||
|
showErrorView(false)
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
showContent(true)
|
showContent(true)
|
||||||
updateData(it.data!!.lessons)
|
updateData(it.data!!.lessons)
|
||||||
|
@ -152,7 +152,9 @@ class AdditionalLessonsFragment :
|
|||||||
presenter.onDateSet(date.year, date.monthValue, date.dayOfMonth)
|
presenter.onDateSet(date.year, date.monthValue, date.dayOfMonth)
|
||||||
}
|
}
|
||||||
|
|
||||||
datePicker.show(this@AdditionalLessonsFragment.parentFragmentManager, null)
|
if (!parentFragmentManager.isStateSaved) {
|
||||||
|
datePicker.show(parentFragmentManager, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
@ -173,7 +173,9 @@ class CompletedLessonsFragment :
|
|||||||
presenter.onDateSet(date.year, date.monthValue, date.dayOfMonth)
|
presenter.onDateSet(date.year, date.monthValue, date.dayOfMonth)
|
||||||
}
|
}
|
||||||
|
|
||||||
datePicker.show(this@CompletedLessonsFragment.parentFragmentManager, null)
|
if (!parentFragmentManager.isStateSaved) {
|
||||||
|
datePicker.show(parentFragmentManager, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
@ -102,7 +102,9 @@ fun Context.openNavigation(location: String) {
|
|||||||
fun Context.openDialer(phone: String) {
|
fun Context.openDialer(phone: String) {
|
||||||
val intentUri = Uri.parse("tel:$phone")
|
val intentUri = Uri.parse("tel:$phone")
|
||||||
val intent = Intent(Intent.ACTION_DIAL, intentUri)
|
val intent = Intent(Intent.ACTION_DIAL, intentUri)
|
||||||
startActivity(intent)
|
if (intent.resolveActivity(packageManager) != null) {
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.shareText(text: String, subject: String?) {
|
fun Context.shareText(text: String, subject: String?) {
|
||||||
|
@ -2,7 +2,6 @@ package io.github.wulkanowy.utils
|
|||||||
|
|
||||||
import com.google.android.material.datepicker.CalendarConstraints
|
import com.google.android.material.datepicker.CalendarConstraints
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import java.time.DayOfWeek
|
|
||||||
import java.time.temporal.ChronoUnit
|
import java.time.temporal.ChronoUnit
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
@ -12,7 +11,6 @@ class SchoolDaysValidator(val start: Long, val end: Long) : CalendarConstraints.
|
|||||||
val date = dateLong.toLocalDateTime()
|
val date = dateLong.toLocalDateTime()
|
||||||
|
|
||||||
return date.until(end.toLocalDateTime(), ChronoUnit.DAYS) >= 0 &&
|
return date.until(end.toLocalDateTime(), ChronoUnit.DAYS) >= 0 &&
|
||||||
date.until(start.toLocalDateTime(), ChronoUnit.DAYS) <= 0 &&
|
date.until(start.toLocalDateTime(), ChronoUnit.DAYS) <= 0
|
||||||
date.dayOfWeek != DayOfWeek.SUNDAY
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
Wersja 1.2.1
|
Wersja 1.2.2
|
||||||
|
|
||||||
- dodaliśmy brakujące okienka z podglądem szczegółów ogłoszeń szkolnych
|
- naprawiliśmy problem z widocznością zadań w aplikacji gdy widoczne są one na stronie www dziennika (nadal pozostaje błąd z zadaniami widocznymi tylko w oficjalnej aplikacji - czekamy na poprawkę po stronie VULCANa)
|
||||||
- naprawiliśmy rzucające się w oczy błędy na ekranie startowym
|
- odblokowaliśmy niedzielę w wyborze daty w planie lekcji i innych zakładkach
|
||||||
- naprawiliśmy też inne drobne błędy w wyglądzie i stabilności aplikacji
|
- przywróciliśmy odnośnik do szczęśliwego numerka w menu Więcej
|
||||||
|
- naprawiliśmy drobne błędy ze stabilnością i wyglądem
|
||||||
|
|
||||||
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases
|
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
<string name="login_contact_discord">Discord</string>
|
<string name="login_contact_discord">Discord</string>
|
||||||
<string name="login_email_intent_title">Send email</string>
|
<string name="login_email_intent_title">Send email</string>
|
||||||
<string name="login_email_subject" translatable="false">Zgłoszenie: Problemy z logowaniem</string>
|
<string name="login_email_subject" translatable="false">Zgłoszenie: Problemy z logowaniem</string>
|
||||||
<string name="login_email_text" translatable="false">Informacje o aplikacji:\n\nUrządzenie: %1$s\nWersja SDK: %2$s\nWersja aplikacji: %3$s\nDodatkowe informacje: %4$s\nOstatni błąd: %5$s\n\nOpis problemu: </string>
|
<string name="login_email_text" translatable="false">Informacje o aplikacji:\n\nUrządzenie: %1$s\nWersja SDK: %2$s\nWersja aplikacji: %3$s\nDodatkowe informacje: %4$s\nOstatni błąd: %5$s\n\nOpis problemu (pełna nazwa szkoły, klasa ucznia): </string>
|
||||||
<string name="login_recover_warning">Make sure you select the correct UONET+ register variation!</string>
|
<string name="login_recover_warning">Make sure you select the correct UONET+ register variation!</string>
|
||||||
<string name="login_recover_button">I forgot my password</string>
|
<string name="login_recover_button">I forgot my password</string>
|
||||||
<string name="login_recover_title">Recover your account</string>
|
<string name="login_recover_title">Recover your account</string>
|
||||||
|
@ -37,7 +37,8 @@ class StudentTest {
|
|||||||
studentDb,
|
studentDb,
|
||||||
semesterDb,
|
semesterDb,
|
||||||
mockSdk,
|
mockSdk,
|
||||||
AppInfo()
|
AppInfo(),
|
||||||
|
mockk()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,24 +89,11 @@ class LoginStudentSelectPresenterTest {
|
|||||||
@Test
|
@Test
|
||||||
fun onSelectedStudentTest() {
|
fun onSelectedStudentTest() {
|
||||||
coEvery {
|
coEvery {
|
||||||
studentRepository.saveStudents(
|
studentRepository.saveStudents(listOf(StudentWithSemesters(testStudent, emptyList())))
|
||||||
listOf(
|
|
||||||
StudentWithSemesters(
|
|
||||||
testStudent,
|
|
||||||
emptyList()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} returns listOf(1L)
|
|
||||||
coEvery {
|
|
||||||
studentRepository.switchStudent(
|
|
||||||
StudentWithSemesters(
|
|
||||||
testStudent,
|
|
||||||
emptyList()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} just Runs
|
} just Runs
|
||||||
|
|
||||||
every { loginStudentSelectView.openMainView() } just Runs
|
every { loginStudentSelectView.openMainView() } just Runs
|
||||||
|
|
||||||
presenter.onItemSelected(StudentWithSemesters(testStudent, emptyList()), false)
|
presenter.onItemSelected(StudentWithSemesters(testStudent, emptyList()), false)
|
||||||
presenter.onSignIn()
|
presenter.onSignIn()
|
||||||
|
|
||||||
@ -118,18 +105,14 @@ class LoginStudentSelectPresenterTest {
|
|||||||
@Test
|
@Test
|
||||||
fun onSelectedStudentErrorTest() {
|
fun onSelectedStudentErrorTest() {
|
||||||
coEvery {
|
coEvery {
|
||||||
studentRepository.saveStudents(
|
studentRepository.saveStudents(listOf(StudentWithSemesters(testStudent, emptyList())))
|
||||||
listOf(
|
|
||||||
StudentWithSemesters(
|
|
||||||
testStudent,
|
|
||||||
emptyList()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} throws testException
|
} throws testException
|
||||||
|
|
||||||
coEvery { studentRepository.logoutStudent(testStudent) } just Runs
|
coEvery { studentRepository.logoutStudent(testStudent) } just Runs
|
||||||
|
|
||||||
presenter.onItemSelected(StudentWithSemesters(testStudent, emptyList()), false)
|
presenter.onItemSelected(StudentWithSemesters(testStudent, emptyList()), false)
|
||||||
presenter.onSignIn()
|
presenter.onSignIn()
|
||||||
|
|
||||||
verify { loginStudentSelectView.showContent(false) }
|
verify { loginStudentSelectView.showContent(false) }
|
||||||
verify { loginStudentSelectView.showProgress(true) }
|
verify { loginStudentSelectView.showProgress(true) }
|
||||||
verify { errorHandler.dispatch(match { testException.message == it.message }) }
|
verify { errorHandler.dispatch(match { testException.message == it.message }) }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user