forked from github/wulkanowy-mirror
Additional lessons in timetable view (#2491)
Co-authored-by: Mikołaj Pich <m.pich@outlook.com>
This commit is contained in:
parent
cde2121b60
commit
6f2168d641
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.data.enums
|
||||
|
||||
enum class ShowAdditionalLessonsMode(val value: String) {
|
||||
NONE("none"),
|
||||
INLINE("inline"),
|
||||
BELOW("below");
|
||||
|
||||
companion object {
|
||||
fun getByValue(value: String) = entries.find { it.value == value } ?: INLINE
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ import io.github.wulkanowy.data.enums.AttendanceCalculatorSortingMode
|
||||
import io.github.wulkanowy.data.enums.GradeColorTheme
|
||||
import io.github.wulkanowy.data.enums.GradeExpandMode
|
||||
import io.github.wulkanowy.data.enums.GradeSortingMode
|
||||
import io.github.wulkanowy.data.enums.ShowAdditionalLessonsMode
|
||||
import io.github.wulkanowy.data.enums.TimetableGapsMode
|
||||
import io.github.wulkanowy.data.enums.TimetableMode
|
||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
||||
@ -213,6 +214,12 @@ class PreferencesRepository @Inject constructor(
|
||||
)
|
||||
)
|
||||
|
||||
val showAdditionalLessonsInPlan: ShowAdditionalLessonsMode
|
||||
get() = getString(
|
||||
R.string.pref_key_timetable_show_additional_lessons,
|
||||
R.string.pref_default_timetable_show_additional_lessons
|
||||
).let { ShowAdditionalLessonsMode.getByValue(it) }
|
||||
|
||||
val gradeSortingMode: GradeSortingMode
|
||||
get() = GradeSortingMode.getByValue(
|
||||
getString(
|
||||
|
@ -12,6 +12,7 @@ import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.databinding.ItemTimetableBinding
|
||||
import io.github.wulkanowy.databinding.ItemTimetableEmptyBinding
|
||||
import io.github.wulkanowy.databinding.ItemTimetableMainAdditionalBinding
|
||||
import io.github.wulkanowy.databinding.ItemTimetableSmallBinding
|
||||
import io.github.wulkanowy.utils.SyncListAdapter
|
||||
import io.github.wulkanowy.utils.getPlural
|
||||
@ -39,6 +40,10 @@ class TimetableAdapter @Inject constructor() :
|
||||
TimetableItemType.EMPTY -> EmptyViewHolder(
|
||||
ItemTimetableEmptyBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
|
||||
TimetableItemType.ADDITIONAL -> AdditionalViewHolder(
|
||||
ItemTimetableMainAdditionalBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,6 +74,22 @@ class TimetableAdapter @Inject constructor() :
|
||||
binding = holder.binding,
|
||||
item = getItem(position) as TimetableItem.Empty,
|
||||
)
|
||||
|
||||
is AdditionalViewHolder -> bindAdditionalView(
|
||||
binding = holder.binding,
|
||||
item = getItem(position) as TimetableItem.Additional,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindAdditionalView(
|
||||
binding: ItemTimetableMainAdditionalBinding,
|
||||
item: TimetableItem.Additional
|
||||
) {
|
||||
with(binding) {
|
||||
timetableItemSubject.text = item.additional.subject
|
||||
timetableItemTimeStart.text = item.additional.start.toFormattedString("HH:mm")
|
||||
timetableItemTimeFinish.text = item.additional.end.toFormattedString("HH:mm")
|
||||
}
|
||||
}
|
||||
|
||||
@ -305,6 +326,9 @@ class TimetableAdapter @Inject constructor() :
|
||||
private class EmptyViewHolder(val binding: ItemTimetableEmptyBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
private class AdditionalViewHolder(val binding: ItemTimetableMainAdditionalBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
private object Differ : DiffUtil.ItemCallback<TimetableItem>() {
|
||||
override fun areItemsTheSame(oldItem: TimetableItem, newItem: TimetableItem): Boolean =
|
||||
when {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.github.wulkanowy.ui.modules.timetable
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
||||
import java.time.Duration
|
||||
|
||||
sealed class TimetableItem(val type: TimetableItemType) {
|
||||
@ -23,6 +24,10 @@ sealed class TimetableItem(val type: TimetableItemType) {
|
||||
val numFrom: Int,
|
||||
val numTo: Int
|
||||
) : TimetableItem(TimetableItemType.EMPTY)
|
||||
|
||||
data class Additional(
|
||||
val additional: TimetableAdditional,
|
||||
) : TimetableItem(TimetableItemType.ADDITIONAL)
|
||||
}
|
||||
|
||||
data class TimeLeft(
|
||||
@ -34,5 +39,6 @@ data class TimeLeft(
|
||||
enum class TimetableItemType {
|
||||
SMALL,
|
||||
NORMAL,
|
||||
EMPTY
|
||||
EMPTY,
|
||||
ADDITIONAL,
|
||||
}
|
||||
|
@ -4,6 +4,9 @@ import android.os.Handler
|
||||
import android.os.Looper
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
||||
import io.github.wulkanowy.data.enums.ShowAdditionalLessonsMode.BELOW
|
||||
import io.github.wulkanowy.data.enums.ShowAdditionalLessonsMode.NONE
|
||||
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.TimetableMode
|
||||
@ -14,6 +17,7 @@ import io.github.wulkanowy.data.onResourceError
|
||||
import io.github.wulkanowy.data.onResourceIntermediate
|
||||
import io.github.wulkanowy.data.onResourceNotLoading
|
||||
import io.github.wulkanowy.data.onResourceSuccess
|
||||
import io.github.wulkanowy.data.pojos.TimetableFull
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
@ -169,9 +173,9 @@ class TimetablePresenter @Inject constructor(
|
||||
enableSwipe(true)
|
||||
showProgress(false)
|
||||
showErrorView(false)
|
||||
updateData(it.lessons, isDayChanged)
|
||||
showContent(it.lessons.isNotEmpty())
|
||||
showEmpty(it.lessons.isEmpty())
|
||||
updateData(it, isDayChanged)
|
||||
showContent(it.lessons.isNotEmpty() || it.additional.isNotEmpty())
|
||||
showEmpty(it.lessons.isEmpty() && it.additional.isEmpty())
|
||||
setDayHeaderMessage(it.headers.find { header -> header.date == currentDate }?.content)
|
||||
reloadNavigation()
|
||||
}
|
||||
@ -216,7 +220,7 @@ class TimetablePresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateData(lessons: List<Timetable>, isDayChanged: Boolean) {
|
||||
private fun updateData(lessons: TimetableFull, isDayChanged: Boolean) {
|
||||
tickTimer?.cancel()
|
||||
|
||||
view?.updateData(createItems(lessons), isDayChanged)
|
||||
@ -229,53 +233,84 @@ class TimetablePresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun createItems(items: List<Timetable>): List<TimetableItem> {
|
||||
val filteredItems = items
|
||||
.filter {
|
||||
if (prefRepository.showWholeClassPlan == TimetableMode.ONLY_CURRENT_GROUP) {
|
||||
it.isStudentPlan
|
||||
} else true
|
||||
}
|
||||
.sortedWith(compareBy({ item -> item.start }, { item -> !item.isStudentPlan }))
|
||||
private sealed class Item(
|
||||
val isStudentPlan: Boolean,
|
||||
val start: Instant,
|
||||
val number: Int?,
|
||||
) {
|
||||
class Lesson(val lesson: Timetable) :
|
||||
Item(lesson.isStudentPlan, lesson.start, lesson.number)
|
||||
|
||||
class Additional(val additional: TimetableAdditional) : Item(true, additional.start, null)
|
||||
}
|
||||
|
||||
private fun createItems(fullTimetable: TimetableFull): List<TimetableItem> {
|
||||
val showAdditionalLessonsInPlan = prefRepository.showAdditionalLessonsInPlan
|
||||
val allItems =
|
||||
fullTimetable.lessons.map(Item::Lesson) + fullTimetable.additional.map(Item::Additional)
|
||||
.takeIf { showAdditionalLessonsInPlan != NONE }.orEmpty()
|
||||
|
||||
val filteredItems = allItems.filter {
|
||||
if (prefRepository.showWholeClassPlan == TimetableMode.ONLY_CURRENT_GROUP) {
|
||||
it.isStudentPlan
|
||||
} else true
|
||||
}.sortedWith(
|
||||
(compareBy<Item> { it is Item.Additional }
|
||||
.takeIf { showAdditionalLessonsInPlan == BELOW } ?: EmptyComparator())
|
||||
.thenBy { it.start }
|
||||
.thenBy { !it.isStudentPlan }
|
||||
)
|
||||
|
||||
var prevNum = when (prefRepository.showTimetableGaps) {
|
||||
BETWEEN_AND_BEFORE_LESSONS -> 0
|
||||
else -> null
|
||||
}
|
||||
var prevIsAdditional = false
|
||||
return buildList {
|
||||
filteredItems.forEachIndexed { i, it ->
|
||||
if (prefRepository.showTimetableGaps != NO_GAPS && prevNum != null && it.number > prevNum!! + 1) {
|
||||
val emptyLesson = TimetableItem.Empty(
|
||||
numFrom = prevNum!! + 1,
|
||||
numTo = it.number - 1
|
||||
)
|
||||
add(emptyLesson)
|
||||
if (prefRepository.showTimetableGaps != NO_GAPS) {
|
||||
if (prevNum != null && it.number != null && it.number > prevNum!! + 1) {
|
||||
if (!prevIsAdditional) {
|
||||
// Additional lessons do count as a lesson so don't add empty lessons
|
||||
// when there is an additional lesson present
|
||||
val emptyLesson = TimetableItem.Empty(
|
||||
numFrom = prevNum!! + 1, numTo = it.number - 1
|
||||
)
|
||||
add(emptyLesson)
|
||||
}
|
||||
}
|
||||
prevNum = it.number
|
||||
prevIsAdditional = it is Item.Additional
|
||||
}
|
||||
|
||||
if (it.isStudentPlan) {
|
||||
val normalLesson = TimetableItem.Normal(
|
||||
lesson = it,
|
||||
showGroupsInPlan = prefRepository.showGroupsInPlan,
|
||||
timeLeft = filteredItems.getTimeLeftForLesson(it, i),
|
||||
onClick = ::onTimetableItemSelected,
|
||||
isLessonNumberVisible = !isEduOne
|
||||
)
|
||||
add(normalLesson)
|
||||
} else {
|
||||
val smallLesson = TimetableItem.Small(
|
||||
lesson = it,
|
||||
onClick = ::onTimetableItemSelected,
|
||||
isLessonNumberVisible = !isEduOne
|
||||
)
|
||||
add(smallLesson)
|
||||
if (it is Item.Lesson) {
|
||||
if (it.isStudentPlan) {
|
||||
val normalLesson = TimetableItem.Normal(
|
||||
lesson = it.lesson,
|
||||
showGroupsInPlan = prefRepository.showGroupsInPlan,
|
||||
timeLeft = filteredItems.getTimeLeftForLesson(it.lesson, i),
|
||||
onClick = ::onTimetableItemSelected,
|
||||
isLessonNumberVisible = !isEduOne
|
||||
)
|
||||
add(normalLesson)
|
||||
} else {
|
||||
val smallLesson = TimetableItem.Small(
|
||||
lesson = it.lesson,
|
||||
onClick = ::onTimetableItemSelected,
|
||||
isLessonNumberVisible = !isEduOne
|
||||
)
|
||||
add(smallLesson)
|
||||
}
|
||||
} else if (it is Item.Additional) {
|
||||
// If the user disabled showing additional lessons, they would've been filtered
|
||||
// out already, so there's no need to check it again.
|
||||
add(TimetableItem.Additional(it.additional))
|
||||
}
|
||||
|
||||
prevNum = it.number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<Timetable>.getTimeLeftForLesson(lesson: Timetable, index: Int): TimeLeft {
|
||||
private fun List<Item>.getTimeLeftForLesson(lesson: Timetable, index: Int): TimeLeft {
|
||||
val isShowTimeUntil = lesson.isShowTimeUntil(getPreviousLesson(index))
|
||||
return TimeLeft(
|
||||
until = lesson.until.plusMinutes(1).takeIf { isShowTimeUntil },
|
||||
@ -284,11 +319,20 @@ class TimetablePresenter @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private fun List<Timetable>.getPreviousLesson(position: Int): Instant? {
|
||||
return filter { it.isStudentPlan }
|
||||
.getOrNull(position - 1 - filterIndexed { i, item -> i < position && !item.isStudentPlan }.size)
|
||||
private fun List<Item>.getPreviousLesson(position: Int): Instant? {
|
||||
val lessonAdditionalOffset = filterIndexed { i, item ->
|
||||
i < position && item is Item.Additional
|
||||
}.size
|
||||
val lessonStudentPlanOffset = filterIndexed { i, item ->
|
||||
i < position && !item.isStudentPlan
|
||||
}.size
|
||||
val lessonIndex = position - 1 - lessonAdditionalOffset - lessonStudentPlanOffset
|
||||
|
||||
return filterIsInstance<Item.Lesson>()
|
||||
.filter { it.isStudentPlan }
|
||||
.getOrNull(lessonIndex)
|
||||
?.let {
|
||||
if (!it.canceled && it.isStudentPlan) it.end
|
||||
if (!it.lesson.canceled && it.isStudentPlan) it.lesson.end
|
||||
else null
|
||||
}
|
||||
}
|
||||
@ -341,3 +385,7 @@ class TimetablePresenter @Inject constructor(
|
||||
super.onDetachView()
|
||||
}
|
||||
}
|
||||
|
||||
private class EmptyComparator<T> : Comparator<T> {
|
||||
override fun compare(o1: T, o2: T) = 0
|
||||
}
|
||||
|
@ -13,7 +13,11 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.ui.modules.timetable.additional.add.AdditionalLessonAddDialog
|
||||
import io.github.wulkanowy.ui.widgets.DividerItemDecoration
|
||||
import io.github.wulkanowy.utils.*
|
||||
import io.github.wulkanowy.utils.dpToPx
|
||||
import io.github.wulkanowy.utils.firstSchoolDayInSchoolYear
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.lastSchoolDayInSchoolYear
|
||||
import io.github.wulkanowy.utils.openMaterialDatePicker
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -132,8 +136,12 @@ class AdditionalLessonsFragment :
|
||||
binding.additionalLessonsNextButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
||||
}
|
||||
|
||||
override fun showAddAdditionalLessonDialog() {
|
||||
(activity as? MainActivity)?.showDialogFragment(AdditionalLessonAddDialog.newInstance())
|
||||
override fun showAddAdditionalLessonDialog(currentDate: LocalDate) {
|
||||
(activity as? MainActivity)?.showDialogFragment(
|
||||
AdditionalLessonAddDialog.newInstance(
|
||||
currentDate
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun showDatePickerDialog(selectedDate: LocalDate) {
|
||||
|
@ -1,14 +1,27 @@
|
||||
package io.github.wulkanowy.ui.modules.timetable.additional
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import io.github.wulkanowy.data.*
|
||||
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
||||
import io.github.wulkanowy.data.flatResourceFlow
|
||||
import io.github.wulkanowy.data.logResourceStatus
|
||||
import io.github.wulkanowy.data.onResourceData
|
||||
import io.github.wulkanowy.data.onResourceError
|
||||
import io.github.wulkanowy.data.onResourceNotLoading
|
||||
import io.github.wulkanowy.data.onResourceSuccess
|
||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||
import io.github.wulkanowy.domain.timetable.IsStudentHasLessonsOnWeekendUseCase
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.*
|
||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||
import io.github.wulkanowy.utils.capitalise
|
||||
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
|
||||
import io.github.wulkanowy.utils.isHolidays
|
||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||
import io.github.wulkanowy.utils.nextSchoolDay
|
||||
import io.github.wulkanowy.utils.previousSchoolDay
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
@ -22,11 +35,14 @@ class AdditionalLessonsPresenter @Inject constructor(
|
||||
errorHandler: ErrorHandler,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val timetableRepository: TimetableRepository,
|
||||
private val isStudentHasLessonsOnWeekendUseCase: IsStudentHasLessonsOnWeekendUseCase,
|
||||
private val analytics: AnalyticsHelper
|
||||
) : BasePresenter<AdditionalLessonsView>(errorHandler, studentRepository) {
|
||||
|
||||
private var baseDate: LocalDate = LocalDate.now().nextOrSameSchoolDay
|
||||
|
||||
private var isWeekendHasLessons: Boolean = false
|
||||
|
||||
lateinit var currentDate: LocalDate
|
||||
private set
|
||||
|
||||
@ -43,12 +59,18 @@ class AdditionalLessonsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onPreviousDay() {
|
||||
loadData(currentDate.previousSchoolDay)
|
||||
val date = if (isWeekendHasLessons) {
|
||||
currentDate.minusDays(1)
|
||||
} else currentDate.previousSchoolDay
|
||||
loadData(date)
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onNextDay() {
|
||||
loadData(currentDate.nextSchoolDay)
|
||||
val date = if (isWeekendHasLessons) {
|
||||
currentDate.plusDays(1)
|
||||
} else currentDate.nextSchoolDay
|
||||
loadData(date)
|
||||
reloadView()
|
||||
}
|
||||
|
||||
@ -57,7 +79,7 @@ class AdditionalLessonsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onAdditionalLessonAddButtonClicked() {
|
||||
view?.showAddAdditionalLessonDialog()
|
||||
view?.showAddAdditionalLessonDialog(currentDate)
|
||||
}
|
||||
|
||||
fun onDateSet(year: Int, month: Int, day: Int) {
|
||||
@ -131,6 +153,8 @@ class AdditionalLessonsPresenter @Inject constructor(
|
||||
flatResourceFlow {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
|
||||
isWeekendHasLessons = isStudentHasLessonsOnWeekendUseCase(semester, currentDate)
|
||||
timetableRepository.getTimetable(
|
||||
student = student,
|
||||
semester = semester,
|
||||
|
@ -36,7 +36,7 @@ interface AdditionalLessonsView : BaseView {
|
||||
|
||||
fun showDatePickerDialog(selectedDate: LocalDate)
|
||||
|
||||
fun showAddAdditionalLessonDialog()
|
||||
fun showAddAdditionalLessonDialog(currentDate: LocalDate)
|
||||
|
||||
fun showSuccessMessage()
|
||||
|
||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.ui.modules.timetable.additional.add
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.timepicker.MaterialTimePicker
|
||||
@ -26,10 +27,12 @@ class AdditionalLessonAddDialog : BaseDialogFragment<DialogAdditionalAddBinding>
|
||||
lateinit var presenter: AdditionalLessonAddPresenter
|
||||
|
||||
companion object {
|
||||
fun newInstance() = AdditionalLessonAddDialog()
|
||||
const val ARGUMENT_KEY = "additional_lesson_default_date"
|
||||
fun newInstance(defaultDate: LocalDate) = AdditionalLessonAddDialog().apply {
|
||||
arguments = bundleOf(ARGUMENT_KEY to defaultDate.toEpochDay())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
return MaterialAlertDialogBuilder(requireContext(), theme)
|
||||
.setView(
|
||||
@ -40,10 +43,13 @@ class AdditionalLessonAddDialog : BaseDialogFragment<DialogAdditionalAddBinding>
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
arguments?.getLong(ARGUMENT_KEY)?.let(LocalDate::ofEpochDay)?.let {
|
||||
presenter.onDateSelected(it)
|
||||
}
|
||||
presenter.onAttachView(this)
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
override fun initView(selectedDate: LocalDate) {
|
||||
with(binding) {
|
||||
additionalLessonDialogStartEdit.doOnTextChanged { _, _, _, _ ->
|
||||
additionalLessonDialogStart.isErrorEnabled = false
|
||||
@ -53,6 +59,7 @@ class AdditionalLessonAddDialog : BaseDialogFragment<DialogAdditionalAddBinding>
|
||||
additionalLessonDialogEnd.isErrorEnabled = false
|
||||
additionalLessonDialogEnd.error = null
|
||||
}
|
||||
additionalLessonDialogDateEdit.setText(selectedDate.toFormattedString())
|
||||
additionalLessonDialogDateEdit.doOnTextChanged { _, _, _, _ ->
|
||||
additionalLessonDialogDate.isErrorEnabled = false
|
||||
additionalLessonDialogDate.error = null
|
||||
@ -61,7 +68,6 @@ class AdditionalLessonAddDialog : BaseDialogFragment<DialogAdditionalAddBinding>
|
||||
additionalLessonDialogContent.isErrorEnabled = false
|
||||
additionalLessonDialogContent.error = null
|
||||
}
|
||||
|
||||
additionalLessonDialogAdd.setOnClickListener {
|
||||
presenter.onAddAdditionalClicked(
|
||||
start = additionalLessonDialogStartEdit.text?.toString(),
|
||||
|
@ -10,9 +10,12 @@ import io.github.wulkanowy.utils.lastSchoolDayInSchoolYear
|
||||
import io.github.wulkanowy.utils.toLocalDate
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import java.time.*
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalTime
|
||||
import java.time.ZoneId
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
|
||||
class AdditionalLessonAddPresenter @Inject constructor(
|
||||
@ -30,7 +33,7 @@ class AdditionalLessonAddPresenter @Inject constructor(
|
||||
|
||||
override fun onAttachView(view: AdditionalLessonAddView) {
|
||||
super.onAttachView(view)
|
||||
view.initView()
|
||||
view.initView(selectedDate)
|
||||
Timber.i("AdditionalLesson details view was initialized")
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import java.time.LocalTime
|
||||
|
||||
interface AdditionalLessonAddView : BaseView {
|
||||
|
||||
fun initView()
|
||||
fun initView(selectedDate: LocalDate)
|
||||
|
||||
fun closeDialog()
|
||||
|
||||
|
153
app/src/main/res/layout/item_timetable_main_additional.xml
Normal file
153
app/src/main/res/layout/item_timetable_main_additional.xml
Normal file
@ -0,0 +1,153 @@
|
||||
<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:background="?selectableItemBackground"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingBottom="6dp"
|
||||
tools:context=".ui.modules.timetable.TimetableAdapter">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableItemNumber"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:maxLength="2"
|
||||
android:minWidth="40dp"
|
||||
android:minHeight="40dp"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="32sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableItemSubject"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="15sp"
|
||||
app:layout_constraintEnd_toStartOf="@id/timetableItemTimeBarrier"
|
||||
app:layout_constraintStart_toEndOf="@+id/timetableItemTimeStart"
|
||||
app:layout_constraintTop_toTopOf="@id/timetableItemTimeStart"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableItemTimeStart"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="13sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/timetableItemTimeFinish"
|
||||
app:layout_constraintStart_toEndOf="@id/timetableItemNumber"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="11:11" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableItemTimeFinish"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="13sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/timetableItemNumber"
|
||||
app:layout_constraintTop_toBottomOf="@id/timetableItemTimeStart"
|
||||
tools:text="12:00" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableItemTeacher"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="13sp"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/timetableItemTimeStart"
|
||||
app:layout_constraintTop_toTopOf="@id/timetableItemTimeFinish"
|
||||
android:text="@string/timetable_additional_lesson"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableItemDescription"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="0dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textColor="?colorTimetableChange"
|
||||
android:textSize="13sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/timetableItemTimeFinish"
|
||||
app:layout_constraintTop_toTopOf="@id/timetableItemTimeFinish"
|
||||
tools:text="Lekcja odwołana: uczniowie zwolnieni do domu"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/timetableItemTimeBarrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="start"
|
||||
app:constraint_referenced_ids="timetableItemTimeUntil,timetableItemTimeLeft" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableItemTimeUntil"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:textColor="?colorPrimary"
|
||||
android:textSize="13sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="za 15 min"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableItemTimeLeft"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginStart="4dp"
|
||||
android:background="@drawable/background_timetable_time_left"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="7dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingRight="7dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:textColor="?colorOnPrimary"
|
||||
android:textSize="13sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="?colorPrimary"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/timetableItemTimeStart"
|
||||
tools:text="jeszcze 15 min"
|
||||
tools:visibility="visible" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -22,7 +22,8 @@
|
||||
<string name="pref_default_grade_modifier_plus">0.33</string>
|
||||
<string name="pref_default_grade_modifier_minus">0.33</string>
|
||||
<bool name="pref_default_fill_message_content">true</bool>
|
||||
<bool name="pref_default_timetable_show_groups">false</bool>
|
||||
<bool name="pref_default_timetable_show_groups">true</bool>
|
||||
<string name="pref_default_timetable_show_additional_lessons">below</string>
|
||||
<string name="pref_default_timetable_show_whole_class">no</string>
|
||||
<string name="pref_default_grade_sorting_mode">alphabetic</string>
|
||||
<string name="pref_default_timetable_show_gaps">between</string>
|
||||
|
@ -31,6 +31,7 @@
|
||||
<string name="pref_key_grade_sorting_mode">grade_sorting_mode</string>
|
||||
<string name="pref_key_timetable_show_whole_class">show_whole_class_plan</string>
|
||||
<string name="pref_key_timetable_show_groups">show_groups_in_plan</string>
|
||||
<string name="pref_key_timetable_show_additional_lessons">show_additional_lessons</string>
|
||||
<string name="pref_key_timetable_show_gaps">timetable_show_gaps</string>
|
||||
<string name="pref_key_subjects_without_grades">subjects_without_grades</string>
|
||||
<string name="pref_key_optional_arithmetic_average">optional_arithmetic_average</string>
|
||||
|
@ -152,6 +152,17 @@
|
||||
<item>before_and_between</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="timetable_show_additional_lessons_entries">
|
||||
<item>Don\'t show</item>
|
||||
<item>Show inline</item>
|
||||
<item>Show below regular lessons</item>
|
||||
</string-array>
|
||||
<string-array name="timetable_show_additional_lessons_values" translatable="false">
|
||||
<item>none</item>
|
||||
<item>inline</item>
|
||||
<item>below</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="dashboard_tile_entries">
|
||||
<item>Lucky number</item>
|
||||
<item>Unread messages</item>
|
||||
|
@ -195,6 +195,7 @@
|
||||
|
||||
<!--Timetable-->
|
||||
<string name="timetable_lesson">Lesson</string>
|
||||
<string name="timetable_additional_lesson">Additional lesson</string>
|
||||
<string name="timetable_room">Room</string>
|
||||
<string name="timetable_group">Group</string>
|
||||
<string name="timetable_time">Hours</string>
|
||||
@ -731,6 +732,7 @@
|
||||
<string name="pref_view_app_theme">Theme</string>
|
||||
<string name="pref_view_expand_grade">Grades expanding</string>
|
||||
<string name="pref_view_timetable_show_groups">Show groups next to subjects</string>
|
||||
<string name="pref_view_timetable_show_additional_lessons">Show additional lessons</string>
|
||||
<string name="pref_view_timetable_show_gaps">Show empty tiles where there\'s no lesson</string>
|
||||
<string name="pref_view_grade_statistics_list">Show chart list in class grades</string>
|
||||
<string name="pref_view_subjects_without_grades">Show subjects without grades</string>
|
||||
|
@ -88,19 +88,18 @@
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
app:iconSpaceReserved="false"
|
||||
app:title="@string/pref_attendance_calculator_appearance_view"
|
||||
app:key="@string/pref_key_attendance_calculator">
|
||||
app:key="@string/pref_key_attendance_calculator"
|
||||
app:title="@string/pref_attendance_calculator_appearance_view">
|
||||
<SeekBarPreference
|
||||
android:layout="@layout/pref_target_attendance"
|
||||
android:max="99"
|
||||
app:defaultValue="@integer/pref_default_attendance_target"
|
||||
app:iconSpaceReserved="false"
|
||||
android:layout="@layout/pref_target_attendance"
|
||||
app:key="@string/pref_key_attendance_target"
|
||||
app:title="@string/pref_attendance_target"
|
||||
app:min="1"
|
||||
app:updatesContinuously="true"
|
||||
android:max="99"
|
||||
app:showSeekBarValue="true"
|
||||
/>
|
||||
app:title="@string/pref_attendance_target"
|
||||
app:updatesContinuously="true" />
|
||||
<ListPreference
|
||||
app:defaultValue="@string/pref_default_attendance_calculator_sorting_mode"
|
||||
app:entries="@array/attendance_calculator_sorting_mode_entries"
|
||||
@ -143,5 +142,13 @@
|
||||
app:key="@string/pref_key_timetable_show_gaps"
|
||||
app:title="@string/pref_view_timetable_show_gaps"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
<ListPreference
|
||||
app:defaultValue="@string/pref_default_timetable_show_additional_lessons"
|
||||
app:entries="@array/timetable_show_additional_lessons_entries"
|
||||
app:entryValues="@array/timetable_show_additional_lessons_values"
|
||||
app:iconSpaceReserved="false"
|
||||
app:key="@string/pref_key_timetable_show_additional_lessons"
|
||||
app:title="@string/pref_view_timetable_show_additional_lessons"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
|
Loading…
x
Reference in New Issue
Block a user