forked from github/wulkanowy-mirror
Merge branch 'release/2.2.2'
This commit is contained in:
commit
6071b7571b
@ -20,15 +20,15 @@ apply from: 'hooks.gradle'
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
namespace 'io.github.wulkanowy'
|
namespace 'io.github.wulkanowy'
|
||||||
compileSdk 33
|
compileSdk 34
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "io.github.wulkanowy"
|
applicationId "io.github.wulkanowy"
|
||||||
testApplicationId "io.github.tests.wulkanowy"
|
testApplicationId "io.github.tests.wulkanowy"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 33
|
targetSdkVersion 34
|
||||||
versionCode 133
|
versionCode 134
|
||||||
versionName "2.2.1"
|
versionName "2.2.2"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
resValue "string", "app_name", "Wulkanowy"
|
resValue "string", "app_name", "Wulkanowy"
|
||||||
@ -185,34 +185,34 @@ huaweiPublish {
|
|||||||
ext {
|
ext {
|
||||||
work_manager = "2.8.1"
|
work_manager = "2.8.1"
|
||||||
android_hilt = "1.0.0"
|
android_hilt = "1.0.0"
|
||||||
room = "2.5.2"
|
room = "2.6.0"
|
||||||
chucker = "3.5.2"
|
chucker = "3.5.2"
|
||||||
mockk = "1.13.8"
|
mockk = "1.13.8"
|
||||||
coroutines = "1.7.3"
|
coroutines = "1.7.3"
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'io.github.wulkanowy:sdk:2.2.1'
|
implementation 'io.github.wulkanowy:sdk:2.2.2'
|
||||||
|
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0"
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
||||||
|
|
||||||
implementation "androidx.core:core-ktx:1.10.1"
|
implementation 'androidx.core:core-ktx:1.12.0'
|
||||||
implementation 'androidx.core:core-splashscreen:1.0.1'
|
implementation 'androidx.core:core-splashscreen:1.0.1'
|
||||||
implementation "androidx.activity:activity-ktx:1.7.2"
|
implementation "androidx.activity:activity-ktx:1.8.0"
|
||||||
implementation "androidx.appcompat:appcompat:1.6.1"
|
implementation "androidx.appcompat:appcompat:1.6.1"
|
||||||
implementation "androidx.fragment:fragment-ktx:1.6.1"
|
implementation "androidx.fragment:fragment-ktx:1.6.1"
|
||||||
implementation "androidx.annotation:annotation:1.7.0"
|
implementation "androidx.annotation:annotation:1.7.0"
|
||||||
|
|
||||||
implementation "androidx.preference:preference-ktx:1.2.1"
|
implementation "androidx.preference:preference-ktx:1.2.1"
|
||||||
implementation "androidx.recyclerview:recyclerview:1.3.1"
|
implementation "androidx.recyclerview:recyclerview:1.3.2"
|
||||||
implementation "androidx.viewpager2:viewpager2:1.1.0-beta02"
|
implementation "androidx.viewpager2:viewpager2:1.1.0-beta02"
|
||||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||||
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
|
||||||
implementation "com.google.android.material:material:1.9.0"
|
implementation "com.google.android.material:material:1.10.0"
|
||||||
implementation "com.github.wulkanowy:material-chips-input:2.3.1"
|
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.3.0'
|
implementation 'com.github.lopspower:CircularImageView:4.3.0'
|
||||||
@ -236,7 +236,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||||
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0"
|
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0"
|
||||||
implementation "com.squareup.okhttp3:logging-interceptor:4.11.0"
|
implementation "com.squareup.okhttp3:logging-interceptor:4.12.0"
|
||||||
|
|
||||||
implementation "com.jakewharton.timber:timber:5.0.1"
|
implementation "com.jakewharton.timber:timber:5.0.1"
|
||||||
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
implementation "at.favre.lib:slf4j-timber:1.0.1"
|
||||||
@ -248,7 +248,7 @@ dependencies {
|
|||||||
implementation 'com.fredporciuncula:flow-preferences:1.9.1'
|
implementation 'com.fredporciuncula:flow-preferences:1.9.1'
|
||||||
implementation 'org.apache.commons:commons-text:1.10.0'
|
implementation 'org.apache.commons:commons-text:1.10.0'
|
||||||
|
|
||||||
playImplementation platform('com.google.firebase:firebase-bom:32.3.1')
|
playImplementation platform('com.google.firebase:firebase-bom:32.4.0')
|
||||||
playImplementation 'com.google.firebase:firebase-analytics-ktx'
|
playImplementation 'com.google.firebase:firebase-analytics-ktx'
|
||||||
playImplementation 'com.google.firebase:firebase-messaging:'
|
playImplementation 'com.google.firebase:firebase-messaging:'
|
||||||
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
apply plugin: "jacoco"
|
apply plugin: "jacoco"
|
||||||
|
|
||||||
jacoco {
|
jacoco {
|
||||||
toolVersion "0.8.7"
|
toolVersion "0.8.10"
|
||||||
reportsDirectory.set(file("$buildDir/reports"))
|
reportsDirectory.set(file("$buildDir/reports"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(Test) {
|
tasks.withType(Test).configureEach {
|
||||||
jacoco.includeNoLocationClasses = true
|
jacoco.includeNoLocationClasses = true
|
||||||
jacoco.excludes = ['jdk.internal.*']
|
jacoco.excludes = ['jdk.internal.*']
|
||||||
}
|
}
|
||||||
|
|
||||||
task jacocoTestReport(type: JacocoReport) {
|
tasks.register('jacocoTestReport', JacocoReport) {
|
||||||
|
|
||||||
group = "Reporting"
|
group = "Reporting"
|
||||||
description = "Generate Jacoco coverage reports"
|
description = "Generate Jacoco coverage reports"
|
||||||
|
@ -148,6 +148,10 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
|||||||
binding.attendanceNavDate.text = date
|
binding.attendanceNavDate.text = date
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showNavigation(show: Boolean) {
|
||||||
|
binding.attendanceNavContainer.isVisible = show
|
||||||
|
}
|
||||||
|
|
||||||
override fun clearData() {
|
override fun clearData() {
|
||||||
with(attendanceAdapter) {
|
with(attendanceAdapter) {
|
||||||
items = emptyList()
|
items = emptyList()
|
||||||
@ -281,7 +285,9 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
|||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
|
presenter.currentDate?.let {
|
||||||
|
outState.putLong(SAVED_DATE_KEY, it.toEpochDay())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -3,10 +3,14 @@ package io.github.wulkanowy.ui.modules.attendance
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import io.github.wulkanowy.data.*
|
import io.github.wulkanowy.data.*
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
import io.github.wulkanowy.data.repositories.AttendanceRepository
|
import io.github.wulkanowy.data.repositories.AttendanceRepository
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||||
|
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.*
|
import io.github.wulkanowy.utils.*
|
||||||
@ -14,6 +18,7 @@ import kotlinx.coroutines.flow.catch
|
|||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.time.DayOfWeek
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDate.now
|
import java.time.LocalDate.now
|
||||||
import java.time.LocalDate.ofEpochDay
|
import java.time.LocalDate.ofEpochDay
|
||||||
@ -28,9 +33,10 @@ class AttendancePresenter @Inject constructor(
|
|||||||
private val analytics: AnalyticsHelper
|
private val analytics: AnalyticsHelper
|
||||||
) : BasePresenter<AttendanceView>(errorHandler, studentRepository) {
|
) : BasePresenter<AttendanceView>(errorHandler, studentRepository) {
|
||||||
|
|
||||||
private var baseDate: LocalDate = now().previousOrSameSchoolDay
|
private var initialDate: LocalDate? = null
|
||||||
|
private var isWeekendHasLessons: Boolean = false
|
||||||
|
|
||||||
lateinit var currentDate: LocalDate
|
var currentDate: LocalDate? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private lateinit var lastError: Throwable
|
private lateinit var lastError: Throwable
|
||||||
@ -44,27 +50,34 @@ class AttendancePresenter @Inject constructor(
|
|||||||
view.initView()
|
view.initView()
|
||||||
Timber.i("Attendance view was initialized")
|
Timber.i("Attendance view was initialized")
|
||||||
errorHandler.showErrorMessage = ::showErrorViewOnError
|
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||||
reloadView(ofEpochDay(date ?: baseDate.toEpochDay()))
|
currentDate = date?.let(::ofEpochDay)
|
||||||
loadData()
|
loadData()
|
||||||
if (currentDate.isHolidays) setBaseDateOnHolidays()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onPreviousDay() {
|
fun onPreviousDay() {
|
||||||
|
val date = if (isWeekendHasLessons) {
|
||||||
|
currentDate?.minusDays(1)
|
||||||
|
} else currentDate?.previousSchoolDay
|
||||||
|
|
||||||
view?.finishActionMode()
|
view?.finishActionMode()
|
||||||
attendanceToExcuseList.clear()
|
attendanceToExcuseList.clear()
|
||||||
reloadView(currentDate.previousSchoolDay)
|
reloadView(date ?: return)
|
||||||
loadData()
|
loadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onNextDay() {
|
fun onNextDay() {
|
||||||
|
val date = if (isWeekendHasLessons) {
|
||||||
|
currentDate?.plusDays(1)
|
||||||
|
} else currentDate?.nextSchoolDay
|
||||||
|
|
||||||
view?.finishActionMode()
|
view?.finishActionMode()
|
||||||
attendanceToExcuseList.clear()
|
attendanceToExcuseList.clear()
|
||||||
reloadView(currentDate.nextSchoolDay)
|
reloadView(date ?: return)
|
||||||
loadData()
|
loadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onPickDate() {
|
fun onPickDate() {
|
||||||
view?.showDatePickerDialog(currentDate)
|
view?.showDatePickerDialog(currentDate ?: return)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDateSet(year: Int, month: Int, day: Int) {
|
fun onDateSet(year: Int, month: Int, day: Int) {
|
||||||
@ -93,10 +106,8 @@ class AttendancePresenter @Inject constructor(
|
|||||||
Timber.i("Attendance view is reselected")
|
Timber.i("Attendance view is reselected")
|
||||||
view?.let { view ->
|
view?.let { view ->
|
||||||
if (view.currentStackSize == 1) {
|
if (view.currentStackSize == 1) {
|
||||||
baseDate = now().previousOrSameSchoolDay
|
if (currentDate != initialDate) {
|
||||||
|
reloadView(initialDate ?: return)
|
||||||
if (currentDate != baseDate) {
|
|
||||||
reloadView(baseDate)
|
|
||||||
loadData()
|
loadData()
|
||||||
} else if (!view.isViewEmpty) {
|
} else if (!view.isViewEmpty) {
|
||||||
view.resetView()
|
view.resetView()
|
||||||
@ -188,19 +199,6 @@ class AttendancePresenter @Inject constructor(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setBaseDateOnHolidays() {
|
|
||||||
flow {
|
|
||||||
val student = studentRepository.getCurrentStudent()
|
|
||||||
emit(semesterRepository.getCurrentSemester(student))
|
|
||||||
}.catch {
|
|
||||||
Timber.i("Loading semester result: An exception occurred")
|
|
||||||
}.onEach {
|
|
||||||
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
|
||||||
currentDate = baseDate
|
|
||||||
reloadNavigation()
|
|
||||||
}.launch("holidays")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadData(forceRefresh: Boolean = false) {
|
private fun loadData(forceRefresh: Boolean = false) {
|
||||||
Timber.i("Loading attendance data started")
|
Timber.i("Loading attendance data started")
|
||||||
|
|
||||||
@ -211,11 +209,13 @@ class AttendancePresenter @Inject constructor(
|
|||||||
isParent = student.isParent
|
isParent = student.isParent
|
||||||
|
|
||||||
val semester = semesterRepository.getCurrentSemester(student)
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
|
|
||||||
|
checkInitialAndCurrentDate(student, semester)
|
||||||
attendanceRepository.getAttendance(
|
attendanceRepository.getAttendance(
|
||||||
student = student,
|
student = student,
|
||||||
semester = semester,
|
semester = semester,
|
||||||
start = currentDate,
|
start = currentDate ?: now(),
|
||||||
end = currentDate,
|
end = currentDate ?: now(),
|
||||||
forceRefresh = forceRefresh
|
forceRefresh = forceRefresh
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -231,6 +231,8 @@ class AttendancePresenter @Inject constructor(
|
|||||||
}.sortedBy { item -> item.number }
|
}.sortedBy { item -> item.number }
|
||||||
}
|
}
|
||||||
.onResourceData {
|
.onResourceData {
|
||||||
|
isWeekendHasLessons = isWeekendHasLessons || isWeekendHasLessons(it)
|
||||||
|
|
||||||
view?.run {
|
view?.run {
|
||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
@ -238,6 +240,7 @@ class AttendancePresenter @Inject constructor(
|
|||||||
showEmpty(it.isEmpty())
|
showEmpty(it.isEmpty())
|
||||||
showContent(it.isNotEmpty())
|
showContent(it.isNotEmpty())
|
||||||
updateData(it)
|
updateData(it)
|
||||||
|
reloadNavigation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onResourceIntermediate { view?.showRefresh(true) }
|
.onResourceIntermediate { view?.showRefresh(true) }
|
||||||
@ -263,6 +266,43 @@ class AttendancePresenter @Inject constructor(
|
|||||||
.launch()
|
.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun checkInitialAndCurrentDate(student: Student, semester: Semester) {
|
||||||
|
if (initialDate == null) {
|
||||||
|
val lessons = attendanceRepository.getAttendance(
|
||||||
|
student = student,
|
||||||
|
semester = semester,
|
||||||
|
start = now().monday,
|
||||||
|
end = now().sunday,
|
||||||
|
forceRefresh = false,
|
||||||
|
).toFirstResult().dataOrNull.orEmpty()
|
||||||
|
isWeekendHasLessons = isWeekendHasLessons(lessons)
|
||||||
|
initialDate = getInitialDate(semester)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentDate == null) {
|
||||||
|
currentDate = initialDate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isWeekendHasLessons(
|
||||||
|
lessons: List<Attendance>,
|
||||||
|
): Boolean = lessons.any {
|
||||||
|
it.date.dayOfWeek in listOf(
|
||||||
|
DayOfWeek.SATURDAY,
|
||||||
|
DayOfWeek.SUNDAY,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getInitialDate(semester: Semester): LocalDate {
|
||||||
|
val now = now()
|
||||||
|
|
||||||
|
return when {
|
||||||
|
now.isHolidays -> now.getLastSchoolDayIfHoliday(semester.schoolYear)
|
||||||
|
isWeekendHasLessons -> now
|
||||||
|
else -> now.previousOrSameSchoolDay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun excuseAbsence(reason: String?, toExcuseList: List<Attendance>) {
|
private fun excuseAbsence(reason: String?, toExcuseList: List<Attendance>) {
|
||||||
resourceFlow {
|
resourceFlow {
|
||||||
val student = studentRepository.getCurrentStudent()
|
val student = studentRepository.getCurrentStudent()
|
||||||
@ -311,7 +351,7 @@ class AttendancePresenter @Inject constructor(
|
|||||||
private fun reloadView(date: LocalDate) {
|
private fun reloadView(date: LocalDate) {
|
||||||
currentDate = date
|
currentDate = date
|
||||||
|
|
||||||
Timber.i("Reload attendance view with the date ${currentDate.toFormattedString()}")
|
Timber.i("Reload attendance view with the date ${currentDate?.toFormattedString()}")
|
||||||
view?.apply {
|
view?.apply {
|
||||||
showProgress(true)
|
showProgress(true)
|
||||||
enableSwipe(false)
|
enableSwipe(false)
|
||||||
@ -326,10 +366,13 @@ class AttendancePresenter @Inject constructor(
|
|||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
private fun reloadNavigation() {
|
private fun reloadNavigation() {
|
||||||
|
val currentDate = currentDate ?: return
|
||||||
|
|
||||||
view?.apply {
|
view?.apply {
|
||||||
showPreButton(!currentDate.minusDays(1).isHolidays)
|
showPreButton(!currentDate.minusDays(1).isHolidays)
|
||||||
showNextButton(!currentDate.plusDays(1).isHolidays)
|
showNextButton(!currentDate.plusDays(1).isHolidays)
|
||||||
updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalise())
|
updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalise())
|
||||||
|
showNavigation(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,8 @@ interface AttendanceView : BaseView {
|
|||||||
|
|
||||||
fun showContent(show: Boolean)
|
fun showContent(show: Boolean)
|
||||||
|
|
||||||
|
fun showNavigation(show: Boolean)
|
||||||
|
|
||||||
fun showPreButton(show: Boolean)
|
fun showPreButton(show: Boolean)
|
||||||
|
|
||||||
fun showNextButton(show: Boolean)
|
fun showNextButton(show: Boolean)
|
||||||
|
@ -386,7 +386,7 @@ class DashboardPresenter @Inject constructor(
|
|||||||
private fun loadLessons(student: Student, forceRefresh: Boolean) {
|
private fun loadLessons(student: Student, forceRefresh: Boolean) {
|
||||||
flatResourceFlow {
|
flatResourceFlow {
|
||||||
val semester = semesterRepository.getCurrentSemester(student)
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
val date = LocalDate.now().nextOrSameSchoolDay
|
val date = LocalDate.now()
|
||||||
|
|
||||||
timetableRepository.getTimetable(
|
timetableRepository.getTimetable(
|
||||||
student = student,
|
student = student,
|
||||||
|
@ -22,6 +22,8 @@ import io.github.wulkanowy.databinding.ItemGradeStatisticsHeaderBinding
|
|||||||
import io.github.wulkanowy.databinding.ItemGradeStatisticsPieBinding
|
import io.github.wulkanowy.databinding.ItemGradeStatisticsPieBinding
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class GradeStatisticsAdapter @Inject constructor() :
|
class GradeStatisticsAdapter @Inject constructor() :
|
||||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
@ -269,7 +271,7 @@ class GradeStatisticsAdapter @Inject constructor() :
|
|||||||
valueTextSize = 12f
|
valueTextSize = 12f
|
||||||
valueTextColor = binding.root.context.getThemeAttrColor(android.R.attr.textColorPrimary)
|
valueTextColor = binding.root.context.getThemeAttrColor(android.R.attr.textColorPrimary)
|
||||||
valueFormatter = object : ValueFormatter() {
|
valueFormatter = object : ValueFormatter() {
|
||||||
override fun getBarLabel(barEntry: BarEntry) = "${barEntry.y}%"
|
override fun getBarLabel(barEntry: BarEntry) = "${barEntry.y}"
|
||||||
}
|
}
|
||||||
colors = gradePointsColors
|
colors = gradePointsColors
|
||||||
}
|
}
|
||||||
@ -304,15 +306,20 @@ class GradeStatisticsAdapter @Inject constructor() :
|
|||||||
}
|
}
|
||||||
xAxis.setDrawLabels(false)
|
xAxis.setDrawLabels(false)
|
||||||
xAxis.setDrawGridLines(false)
|
xAxis.setDrawGridLines(false)
|
||||||
|
|
||||||
|
val yMaxFromValues = (max(points.others, points.student)).roundToInt() + 30f
|
||||||
|
val yMaxFromValuesWithMargin = ((yMaxFromValues / 10.0).roundToInt() * 10).toFloat()
|
||||||
|
val yMax = yMaxFromValuesWithMargin.coerceAtLeast(100f)
|
||||||
|
val yLabelCount = (yMax / 10).toInt() + 1
|
||||||
with(axisLeft) {
|
with(axisLeft) {
|
||||||
axisMinimum = 0f
|
axisMinimum = 0f
|
||||||
axisMaximum = 100f
|
axisMaximum = yMax
|
||||||
labelCount = 11
|
labelCount = yLabelCount
|
||||||
}
|
}
|
||||||
with(axisRight) {
|
with(axisRight) {
|
||||||
axisMinimum = 0f
|
axisMinimum = 0f
|
||||||
axisMaximum = 100f
|
axisMaximum = yMax
|
||||||
labelCount = 11
|
labelCount = yLabelCount
|
||||||
}
|
}
|
||||||
invalidate()
|
invalidate()
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,10 @@ class TeacherPresenter @Inject constructor(
|
|||||||
.logResourceStatus("load teachers data")
|
.logResourceStatus("load teachers data")
|
||||||
.onResourceData {
|
.onResourceData {
|
||||||
view?.run {
|
view?.run {
|
||||||
updateData(it.filter { item -> item.name.isNotBlank() })
|
updateData(it
|
||||||
|
.filter { item -> item.name.isNotBlank() }
|
||||||
|
.sortedBy { it.name }
|
||||||
|
)
|
||||||
showContent(it.isNotEmpty())
|
showContent(it.isNotEmpty())
|
||||||
showEmpty(it.isEmpty())
|
showEmpty(it.isEmpty())
|
||||||
showErrorView(false)
|
showErrorView(false)
|
||||||
|
@ -35,7 +35,7 @@ class AdvancedFragment : PreferenceFragmentCompat(),
|
|||||||
setPreferencesFromResource(R.xml.scheme_preferences_advanced, rootKey)
|
setPreferencesFromResource(R.xml.scheme_preferences_advanced, rootKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||||
presenter.onSharedPreferenceChanged(key)
|
presenter.onSharedPreferenceChanged(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,8 @@ class AdvancedPresenter @Inject constructor(
|
|||||||
Timber.i("Settings advanced view was initialized")
|
Timber.i("Settings advanced view was initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSharedPreferenceChanged(key: String) {
|
fun onSharedPreferenceChanged(key: String?) {
|
||||||
|
key ?: return
|
||||||
Timber.i("Change settings $key")
|
Timber.i("Change settings $key")
|
||||||
analytics.logEvent("setting_changed", "name" to key)
|
analytics.logEvent("setting_changed", "name" to key)
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ class AppearanceFragment : PreferenceFragmentCompat(),
|
|||||||
setPreferencesFromResource(R.xml.scheme_preferences_appearance, rootKey)
|
setPreferencesFromResource(R.xml.scheme_preferences_appearance, rootKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||||
presenter.onSharedPreferenceChanged(key)
|
presenter.onSharedPreferenceChanged(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,8 @@ class AppearancePresenter @Inject constructor(
|
|||||||
Timber.i("Settings appearance view was initialized")
|
Timber.i("Settings appearance view was initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSharedPreferenceChanged(key: String) {
|
fun onSharedPreferenceChanged(key: String?) {
|
||||||
|
key ?: return
|
||||||
Timber.i("Change settings $key")
|
Timber.i("Change settings $key")
|
||||||
|
|
||||||
preferencesRepository.apply {
|
preferencesRepository.apply {
|
||||||
|
@ -114,7 +114,7 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
|||||||
setPreferencesFromResource(R.xml.scheme_preferences_notifications, rootKey)
|
setPreferencesFromResource(R.xml.scheme_preferences_notifications, rootKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||||
presenter.onSharedPreferenceChanged(key)
|
presenter.onSharedPreferenceChanged(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,8 @@ class NotificationsPresenter @Inject constructor(
|
|||||||
Timber.i("Settings notifications view was initialized")
|
Timber.i("Settings notifications view was initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSharedPreferenceChanged(key: String) {
|
fun onSharedPreferenceChanged(key: String?) {
|
||||||
|
key ?: return
|
||||||
Timber.i("Change settings $key")
|
Timber.i("Change settings $key")
|
||||||
|
|
||||||
preferencesRepository.apply {
|
preferencesRepository.apply {
|
||||||
|
@ -52,7 +52,7 @@ class SyncFragment : PreferenceFragmentCompat(),
|
|||||||
setPreferencesFromResource(R.xml.scheme_preferences_sync, rootKey)
|
setPreferencesFromResource(R.xml.scheme_preferences_sync, rootKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||||
presenter.onSharedPreferenceChanged(key)
|
presenter.onSharedPreferenceChanged(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,8 @@ class SyncPresenter @Inject constructor(
|
|||||||
setSyncDateInView()
|
setSyncDateInView()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSharedPreferenceChanged(key: String) {
|
fun onSharedPreferenceChanged(key: String?) {
|
||||||
|
key ?: return
|
||||||
Timber.i("Change settings $key")
|
Timber.i("Change settings $key")
|
||||||
|
|
||||||
preferencesRepository.apply {
|
preferencesRepository.apply {
|
||||||
@ -52,10 +53,12 @@ class SyncPresenter @Inject constructor(
|
|||||||
Timber.i("Setting sync now started")
|
Timber.i("Setting sync now started")
|
||||||
analytics.logEvent("sync_now", "status" to "started")
|
analytics.logEvent("sync_now", "status" to "started")
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkInfo.State.SUCCEEDED -> {
|
WorkInfo.State.SUCCEEDED -> {
|
||||||
showMessage(syncSuccessString)
|
showMessage(syncSuccessString)
|
||||||
analytics.logEvent("sync_now", "status" to "success")
|
analytics.logEvent("sync_now", "status" to "success")
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkInfo.State.FAILED -> {
|
WorkInfo.State.FAILED -> {
|
||||||
showError(
|
showError(
|
||||||
syncFailedString,
|
syncFailedString,
|
||||||
@ -66,6 +69,7 @@ class SyncPresenter @Inject constructor(
|
|||||||
)
|
)
|
||||||
analytics.logEvent("sync_now", "status" to "failed")
|
analytics.logEvent("sync_now", "status" to "failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> Timber.d("Sync now state: ${workInfo?.state}")
|
else -> Timber.d("Sync now state: ${workInfo?.state}")
|
||||||
}
|
}
|
||||||
if (workInfo?.state?.isFinished == true) {
|
if (workInfo?.state?.isFinished == true) {
|
||||||
|
@ -9,6 +9,7 @@ import android.view.View.GONE
|
|||||||
import android.view.View.VISIBLE
|
import android.view.View.VISIBLE
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.text.parseAsHtml
|
import androidx.core.text.parseAsHtml
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
@ -160,6 +161,10 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
|
|||||||
binding.timetableRecycler.visibility = if (show) VISIBLE else GONE
|
binding.timetableRecycler.visibility = if (show) VISIBLE else GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showNavigation(show: Boolean) {
|
||||||
|
binding.timetableNavContainer.isVisible = true
|
||||||
|
}
|
||||||
|
|
||||||
override fun showPreButton(show: Boolean) {
|
override fun showPreButton(show: Boolean) {
|
||||||
binding.timetablePreviousButton.visibility = if (show) VISIBLE else View.INVISIBLE
|
binding.timetablePreviousButton.visibility = if (show) VISIBLE else View.INVISIBLE
|
||||||
}
|
}
|
||||||
@ -193,7 +198,9 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
|
|||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
|
presenter.currentDate?.toEpochDay()?.let {
|
||||||
|
outState.putLong(SAVED_DATE_KEY, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package io.github.wulkanowy.ui.modules.timetable
|
package io.github.wulkanowy.ui.modules.timetable
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.dataOrNull
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
import io.github.wulkanowy.data.enums.TimetableGapsMode.BETWEEN_AND_BEFORE_LESSONS
|
import io.github.wulkanowy.data.enums.TimetableGapsMode.BETWEEN_AND_BEFORE_LESSONS
|
||||||
import io.github.wulkanowy.data.enums.TimetableGapsMode.NO_GAPS
|
import io.github.wulkanowy.data.enums.TimetableGapsMode.NO_GAPS
|
||||||
@ -15,6 +18,8 @@ import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|||||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||||
|
import io.github.wulkanowy.data.toFirstResult
|
||||||
|
import io.github.wulkanowy.data.waitForResult
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||||
@ -24,15 +29,16 @@ import io.github.wulkanowy.utils.isHolidays
|
|||||||
import io.github.wulkanowy.utils.isJustFinished
|
import io.github.wulkanowy.utils.isJustFinished
|
||||||
import io.github.wulkanowy.utils.isShowTimeUntil
|
import io.github.wulkanowy.utils.isShowTimeUntil
|
||||||
import io.github.wulkanowy.utils.left
|
import io.github.wulkanowy.utils.left
|
||||||
|
import io.github.wulkanowy.utils.monday
|
||||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||||
import io.github.wulkanowy.utils.nextSchoolDay
|
import io.github.wulkanowy.utils.nextSchoolDay
|
||||||
import io.github.wulkanowy.utils.previousSchoolDay
|
import io.github.wulkanowy.utils.previousSchoolDay
|
||||||
|
import io.github.wulkanowy.utils.sunday
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import io.github.wulkanowy.utils.until
|
import io.github.wulkanowy.utils.until
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
import kotlinx.coroutines.flow.flow
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.time.DayOfWeek
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDate.now
|
import java.time.LocalDate.now
|
||||||
@ -51,9 +57,10 @@ class TimetablePresenter @Inject constructor(
|
|||||||
private val analytics: AnalyticsHelper,
|
private val analytics: AnalyticsHelper,
|
||||||
) : BasePresenter<TimetableView>(errorHandler, studentRepository) {
|
) : BasePresenter<TimetableView>(errorHandler, studentRepository) {
|
||||||
|
|
||||||
private var baseDate: LocalDate = now().nextOrSameSchoolDay
|
private var initialDate: LocalDate? = null
|
||||||
|
private var isWeekendHasLessons: Boolean = false
|
||||||
|
|
||||||
lateinit var currentDate: LocalDate
|
var currentDate: LocalDate? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private lateinit var lastError: Throwable
|
private lateinit var lastError: Throwable
|
||||||
@ -65,23 +72,30 @@ class TimetablePresenter @Inject constructor(
|
|||||||
view.initView()
|
view.initView()
|
||||||
Timber.i("Timetable was initialized")
|
Timber.i("Timetable was initialized")
|
||||||
errorHandler.showErrorMessage = ::showErrorViewOnError
|
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||||
reloadView(ofEpochDay(date ?: baseDate.toEpochDay()))
|
currentDate = date?.let(::ofEpochDay)
|
||||||
loadData()
|
loadData()
|
||||||
if (currentDate.isHolidays) setBaseDateOnHolidays()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onPreviousDay() {
|
fun onPreviousDay() {
|
||||||
reloadView(currentDate.previousSchoolDay)
|
val date = if (isWeekendHasLessons) {
|
||||||
|
currentDate?.minusDays(1)
|
||||||
|
} else currentDate?.previousSchoolDay
|
||||||
|
|
||||||
|
reloadView(date ?: return)
|
||||||
loadData()
|
loadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onNextDay() {
|
fun onNextDay() {
|
||||||
reloadView(currentDate.nextSchoolDay)
|
val date = if (isWeekendHasLessons) {
|
||||||
|
currentDate?.plusDays(1)
|
||||||
|
} else currentDate?.nextSchoolDay
|
||||||
|
|
||||||
|
reloadView(date ?: return)
|
||||||
loadData()
|
loadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onPickDate() {
|
fun onPickDate() {
|
||||||
view?.showDatePickerDialog(currentDate)
|
view?.showDatePickerDialog(currentDate ?: return)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDateSet(year: Int, month: Int, day: Int) {
|
fun onDateSet(year: Int, month: Int, day: Int) {
|
||||||
@ -110,10 +124,8 @@ class TimetablePresenter @Inject constructor(
|
|||||||
Timber.i("Timetable view is reselected")
|
Timber.i("Timetable view is reselected")
|
||||||
view?.let { view ->
|
view?.let { view ->
|
||||||
if (view.currentStackSize == 1) {
|
if (view.currentStackSize == 1) {
|
||||||
baseDate = now().nextOrSameSchoolDay
|
if (currentDate != initialDate) {
|
||||||
|
reloadView(initialDate ?: return)
|
||||||
if (currentDate != baseDate) {
|
|
||||||
reloadView(baseDate)
|
|
||||||
loadData()
|
loadData()
|
||||||
} else if (!view.isViewEmpty) {
|
} else if (!view.isViewEmpty) {
|
||||||
view.resetView()
|
view.resetView()
|
||||||
@ -134,34 +146,25 @@ class TimetablePresenter @Inject constructor(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setBaseDateOnHolidays() {
|
|
||||||
flow {
|
|
||||||
val student = studentRepository.getCurrentStudent()
|
|
||||||
emit(semesterRepository.getCurrentSemester(student))
|
|
||||||
}.catch {
|
|
||||||
Timber.i("Loading semester result: An exception occurred")
|
|
||||||
}.onEach {
|
|
||||||
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
|
||||||
currentDate = baseDate
|
|
||||||
reloadNavigation()
|
|
||||||
}.launch("holidays")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadData(forceRefresh: Boolean = false) {
|
private fun loadData(forceRefresh: Boolean = false) {
|
||||||
flatResourceFlow {
|
flatResourceFlow {
|
||||||
val student = studentRepository.getCurrentStudent()
|
val student = studentRepository.getCurrentStudent()
|
||||||
val semester = semesterRepository.getCurrentSemester(student)
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
|
|
||||||
|
checkInitialAndCurrentDate(student, semester)
|
||||||
timetableRepository.getTimetable(
|
timetableRepository.getTimetable(
|
||||||
student = student,
|
student = student,
|
||||||
semester = semester,
|
semester = semester,
|
||||||
start = currentDate,
|
start = currentDate ?: now(),
|
||||||
end = currentDate,
|
end = currentDate ?: now(),
|
||||||
forceRefresh = forceRefresh,
|
forceRefresh = forceRefresh,
|
||||||
timetableType = TimetableRepository.TimetableType.NORMAL
|
timetableType = TimetableRepository.TimetableType.NORMAL
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.logResourceStatus("load timetable data")
|
.logResourceStatus("load timetable data")
|
||||||
.onResourceData {
|
.onResourceData {
|
||||||
|
isWeekendHasLessons = isWeekendHasLessons || isWeekendHasLessons(it.lessons)
|
||||||
|
|
||||||
view?.run {
|
view?.run {
|
||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
@ -169,7 +172,8 @@ class TimetablePresenter @Inject constructor(
|
|||||||
showContent(it.lessons.isNotEmpty())
|
showContent(it.lessons.isNotEmpty())
|
||||||
showEmpty(it.lessons.isEmpty())
|
showEmpty(it.lessons.isEmpty())
|
||||||
updateData(it.lessons)
|
updateData(it.lessons)
|
||||||
setDayHeaderMessage(it.headers.singleOrNull { header -> header.date == currentDate }?.content)
|
setDayHeaderMessage(it.headers.find { header -> header.date == currentDate }?.content)
|
||||||
|
reloadNavigation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onResourceIntermediate { view?.showRefresh(true) }
|
.onResourceIntermediate { view?.showRefresh(true) }
|
||||||
@ -191,6 +195,44 @@ class TimetablePresenter @Inject constructor(
|
|||||||
.launch()
|
.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun checkInitialAndCurrentDate(student: Student, semester: Semester) {
|
||||||
|
if (initialDate == null) {
|
||||||
|
val lessons = timetableRepository.getTimetable(
|
||||||
|
student = student,
|
||||||
|
semester = semester,
|
||||||
|
start = now().monday,
|
||||||
|
end = now().sunday,
|
||||||
|
forceRefresh = false,
|
||||||
|
timetableType = TimetableRepository.TimetableType.NORMAL
|
||||||
|
).toFirstResult().dataOrNull?.lessons.orEmpty()
|
||||||
|
isWeekendHasLessons = isWeekendHasLessons(lessons)
|
||||||
|
initialDate = getInitialDate(semester)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentDate == null) {
|
||||||
|
currentDate = initialDate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isWeekendHasLessons(
|
||||||
|
lessons: List<Timetable>,
|
||||||
|
): Boolean = lessons.any {
|
||||||
|
it.date.dayOfWeek in listOf(
|
||||||
|
DayOfWeek.SATURDAY,
|
||||||
|
DayOfWeek.SUNDAY,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getInitialDate(semester: Semester): LocalDate {
|
||||||
|
val now = now()
|
||||||
|
|
||||||
|
return when {
|
||||||
|
now.isHolidays -> now.getLastSchoolDayIfHoliday(semester.schoolYear)
|
||||||
|
isWeekendHasLessons -> now
|
||||||
|
else -> now.nextOrSameSchoolDay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateData(lessons: List<Timetable>) {
|
private fun updateData(lessons: List<Timetable>) {
|
||||||
tickTimer?.cancel()
|
tickTimer?.cancel()
|
||||||
|
|
||||||
@ -285,7 +327,7 @@ class TimetablePresenter @Inject constructor(
|
|||||||
private fun reloadView(date: LocalDate) {
|
private fun reloadView(date: LocalDate) {
|
||||||
currentDate = date
|
currentDate = date
|
||||||
|
|
||||||
Timber.i("Reload timetable view with the date ${currentDate.toFormattedString()}")
|
Timber.i("Reload timetable view with the date ${currentDate?.toFormattedString()}")
|
||||||
view?.apply {
|
view?.apply {
|
||||||
showProgress(true)
|
showProgress(true)
|
||||||
enableSwipe(false)
|
enableSwipe(false)
|
||||||
@ -298,10 +340,13 @@ class TimetablePresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun reloadNavigation() {
|
private fun reloadNavigation() {
|
||||||
|
val currentDate = currentDate ?: return
|
||||||
|
|
||||||
view?.apply {
|
view?.apply {
|
||||||
showPreButton(!currentDate.minusDays(1).isHolidays)
|
showPreButton(!currentDate.minusDays(1).isHolidays)
|
||||||
showNextButton(!currentDate.plusDays(1).isHolidays)
|
showNextButton(!currentDate.plusDays(1).isHolidays)
|
||||||
updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalise())
|
updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalise())
|
||||||
|
showNavigation(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@ interface TimetableView : BaseView {
|
|||||||
|
|
||||||
fun showContent(show: Boolean)
|
fun showContent(show: Boolean)
|
||||||
|
|
||||||
|
fun showNavigation(show: Boolean)
|
||||||
|
|
||||||
fun showPreButton(show: Boolean)
|
fun showPreButton(show: Boolean)
|
||||||
|
|
||||||
fun showNextButton(show: Boolean)
|
fun showNextButton(show: Boolean)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
Wersja 2.2.1
|
Wersja 2.2.2
|
||||||
|
|
||||||
– dokonaliśmy kilka poprawek na ekranie logowania
|
— dodaliśmy możliwość łatwego wejścia w sobotę i niedziele w planie lekcji przy użyciu strzałek
|
||||||
– naprawiliśmy przypadek z błędnym wyświetlaniem starej klasy ucznia po zalogowaniu się na konto z nowej klasy
|
— poprawiliśmy wsparcie dla statystyk ocen z systemem punktowym
|
||||||
|
— poprawiliśmy sortowanie nauczycieli w widoku Szkoła i nauczyciele
|
||||||
|
|
||||||
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases
|
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases
|
||||||
|
@ -128,7 +128,9 @@
|
|||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
tools:ignore="UnusedAttribute">
|
android:visibility="gone"
|
||||||
|
tools:ignore="UnusedAttribute"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/attendancePreviousButton"
|
android:id="@+id/attendancePreviousButton"
|
||||||
|
@ -128,7 +128,9 @@
|
|||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
tools:ignore="UnusedAttribute">
|
android:visibility="gone"
|
||||||
|
tools:ignore="UnusedAttribute"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/timetablePreviousButton"
|
android:id="@+id/timetablePreviousButton"
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
kotlin_version = '1.9.10'
|
kotlin_version = '1.9.10'
|
||||||
about_libraries = '10.9.0'
|
about_libraries = '10.9.1'
|
||||||
hilt_version = "2.48"
|
hilt_version = '2.48.1'
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@ -21,7 +21,7 @@ buildscript {
|
|||||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9'
|
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9'
|
||||||
classpath "com.github.triplet.gradle:play-publisher:3.8.4"
|
classpath "com.github.triplet.gradle:play-publisher:3.8.4"
|
||||||
classpath "ru.cian:huawei-publish-gradle-plugin:1.4.0"
|
classpath "ru.cian:huawei-publish-gradle-plugin:1.4.0"
|
||||||
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:4.4.0.3356"
|
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:4.4.1.3373"
|
||||||
classpath "gradle.plugin.com.star-zero.gradle:githook:1.2.0"
|
classpath "gradle.plugin.com.star-zero.gradle:githook:1.2.0"
|
||||||
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:$about_libraries"
|
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:$about_libraries"
|
||||||
}
|
}
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
5
gradlew
vendored
5
gradlew
vendored
@ -130,11 +130,14 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
|
@ -1,4 +1 @@
|
|||||||
plugins {
|
|
||||||
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
|
|
||||||
}
|
|
||||||
include ':app'
|
include ':app'
|
||||||
|
Loading…
Reference in New Issue
Block a user