1
0
mirror of https://github.com/wulkanowy/wulkanowy.git synced 2024-09-19 18:59:08 -05:00

Timetable timer refactor (#1785)

This commit is contained in:
Mikołaj Pich 2022-03-13 04:01:14 +01:00 committed by GitHub
parent c3abe50ed4
commit 57ea6379ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 190 additions and 206 deletions

12
.editorconfig Normal file
View File

@ -0,0 +1,12 @@
[*]
charset=utf-8
end_of_line=lf
insert_final_newline=true
indent_style=space
indent_size=4
[*.json]
indent_size=2
[*.{kt,kts}]
disabled_rules=import-ordering,no-wildcard-imports

View File

@ -1,116 +1,69 @@
package io.github.wulkanowy.ui.modules.timetable package io.github.wulkanowy.ui.modules.timetable
import android.graphics.Paint
import android.os.Handler
import android.os.Looper
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View.GONE import android.view.View.GONE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.data.enums.TimetableMode
import io.github.wulkanowy.databinding.ItemTimetableBinding import io.github.wulkanowy.databinding.ItemTimetableBinding
import io.github.wulkanowy.databinding.ItemTimetableSmallBinding import io.github.wulkanowy.databinding.ItemTimetableSmallBinding
import io.github.wulkanowy.utils.* import io.github.wulkanowy.utils.getThemeAttrColor
import timber.log.Timber import io.github.wulkanowy.utils.toFormattedString
import java.time.Instant
import java.util.*
import javax.inject.Inject import javax.inject.Inject
import kotlin.concurrent.timer
class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView.ViewHolder>() { class TimetableAdapter @Inject constructor() :
ListAdapter<TimetableItem, RecyclerView.ViewHolder>(differ) {
private enum class ViewType { override fun getItemViewType(position: Int): Int = getItem(position).type.ordinal
ITEM_NORMAL,
ITEM_SMALL
}
var onClickListener: (Timetable) -> Unit = {}
private var showWholeClassPlan = TimetableMode.ONLY_CURRENT_GROUP
private var showGroupsInPlan: Boolean = false
private var showTimers: Boolean = false
private val timers = mutableMapOf<Int, Timer?>()
private val items = mutableListOf<Timetable>()
fun submitList(
newTimetable: List<Timetable>,
showWholeClassPlan: TimetableMode = this.showWholeClassPlan,
showGroupsInPlan: Boolean = this.showGroupsInPlan,
showTimers: Boolean = this.showTimers
) {
val isFlagsDifferent = this.showWholeClassPlan != showWholeClassPlan
|| this.showGroupsInPlan != showGroupsInPlan
|| this.showTimers != showTimers
val diffResult = DiffUtil.calculateDiff(
TimetableAdapterDiffCallback(
oldList = items.toMutableList(),
newList = newTimetable,
isFlagsDifferent = isFlagsDifferent
)
)
this.showGroupsInPlan = showGroupsInPlan
this.showTimers = showTimers
this.showWholeClassPlan = showWholeClassPlan
items.clear()
items.addAll(newTimetable)
diffResult.dispatchUpdatesTo(this)
}
fun clearTimers() {
Timber.d("Timetable timers (${timers.size}) cleared")
with(timers) {
forEach { (_, timer) ->
timer?.cancel()
timer?.purge()
}
clear()
}
}
override fun getItemCount() = items.size
override fun getItemViewType(position: Int) = when {
!items[position].isStudentPlan && showWholeClassPlan == TimetableMode.SMALL_OTHER_GROUP -> ViewType.ITEM_SMALL.ordinal
else -> ViewType.ITEM_NORMAL.ordinal
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context) val inflater = LayoutInflater.from(parent.context)
return when (viewType) { return when (TimetableItemType.values()[viewType]) {
ViewType.ITEM_NORMAL.ordinal -> ItemViewHolder( TimetableItemType.SMALL -> SmallViewHolder(
ItemTimetableBinding.inflate(inflater, parent, false)
)
ViewType.ITEM_SMALL.ordinal -> SmallItemViewHolder(
ItemTimetableSmallBinding.inflate(inflater, parent, false) ItemTimetableSmallBinding.inflate(inflater, parent, false)
) )
else -> throw IllegalStateException() TimetableItemType.NORMAL -> NormalViewHolder(
ItemTimetableBinding.inflate(inflater, parent, false)
)
} }
} }
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int,
payloads: MutableList<Any>
) {
if (payloads.isEmpty()) return super.onBindViewHolder(holder, position, payloads)
if (holder is NormalViewHolder) updateTimeLeft(
binding = holder.binding,
timeLeft = (getItem(position) as TimetableItem.Normal).timeLeft,
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val lesson = items[position]
when (holder) { when (holder) {
is ItemViewHolder -> bindNormalView(holder.binding, lesson, position) is SmallViewHolder -> bindSmallView(
is SmallItemViewHolder -> bindSmallView(holder.binding, lesson) binding = holder.binding,
item = getItem(position) as TimetableItem.Small,
)
is NormalViewHolder -> bindNormalView(
binding = holder.binding,
item = getItem(position) as TimetableItem.Normal,
)
} }
} }
private fun bindSmallView(binding: ItemTimetableSmallBinding, lesson: Timetable) { private fun bindSmallView(binding: ItemTimetableSmallBinding, item: TimetableItem.Small) {
val lesson = item.lesson
with(binding) { with(binding) {
timetableSmallItemNumber.text = lesson.number.toString() timetableSmallItemNumber.text = lesson.number.toString()
timetableSmallItemSubject.text = lesson.subject timetableSmallItemSubject.text = lesson.subject
@ -122,11 +75,13 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
bindSmallDescription(binding, lesson) bindSmallDescription(binding, lesson)
bindSmallColors(binding, lesson) bindSmallColors(binding, lesson)
root.setOnClickListener { onClickListener(lesson) } root.setOnClickListener { item.onClick(lesson) }
} }
} }
private fun bindNormalView(binding: ItemTimetableBinding, lesson: Timetable, position: Int) { private fun bindNormalView(binding: ItemTimetableBinding, item: TimetableItem.Normal) {
val lesson = item.lesson
with(binding) { with(binding) {
timetableItemNumber.text = lesson.number.toString() timetableItemNumber.text = lesson.number.toString()
timetableItemSubject.text = lesson.subject timetableItemSubject.text = lesson.subject
@ -137,51 +92,19 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
timetableItemTimeFinish.text = lesson.end.toFormattedString("HH:mm") timetableItemTimeFinish.text = lesson.end.toFormattedString("HH:mm")
bindSubjectStyle(timetableItemSubject, lesson) bindSubjectStyle(timetableItemSubject, lesson)
bindNormalDescription(binding, lesson) bindNormalDescription(binding, item)
bindNormalColors(binding, lesson) bindNormalColors(binding, lesson)
updateTimeLeft(binding, item.timeLeft)
timers[position]?.let { root.setOnClickListener { item.onClick(lesson) }
it.cancel()
it.purge()
}
timers[position] = null
if (lesson.isStudentPlan && showTimers) {
timers[position] = timer(period = 1000) {
Handler(Looper.getMainLooper()).post {
updateTimeLeft(binding, lesson, position)
}
}
} else {
// reset item on set changed
timetableItemTimeUntil.visibility = GONE
timetableItemTimeLeft.visibility = GONE
}
root.setOnClickListener { onClickListener(lesson) }
} }
} }
private fun getPreviousLesson(position: Int): Instant? { private fun updateTimeLeft(binding: ItemTimetableBinding, timeLeft: TimeLeft?) {
return items.filter { it.isStudentPlan }
.getOrNull(position - 1 - items.filterIndexed { i, item -> i < position && !item.isStudentPlan }.size)
?.let {
if (!it.canceled && it.isStudentPlan) it.end
else null
}
}
private fun updateTimeLeft(binding: ItemTimetableBinding, lesson: Timetable, position: Int) {
val isShowTimeUntil = lesson.isShowTimeUntil(getPreviousLesson(position))
val until = lesson.until.plusMinutes(1)
val left = lesson.left?.plusMinutes(1)
val isJustFinished = lesson.isJustFinished
with(binding) { with(binding) {
when { when {
// before lesson // before lesson
isShowTimeUntil -> { timeLeft?.until != null -> {
Timber.d("Show time until lesson: $position")
timetableItemTimeLeft.visibility = GONE timetableItemTimeLeft.visibility = GONE
with(timetableItemTimeUntil) { with(timetableItemTimeUntil) {
visibility = VISIBLE visibility = VISIBLE
@ -189,14 +112,13 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
R.string.timetable_time_until, R.string.timetable_time_until,
context.getString( context.getString(
R.string.timetable_minutes, R.string.timetable_minutes,
until.toMinutes().toString(10) timeLeft.until.toMinutes().toString(10)
) )
) )
} }
} }
// after lesson start // after lesson start
left != null -> { timeLeft?.left != null -> {
Timber.d("Show time left lesson: $position")
timetableItemTimeUntil.visibility = GONE timetableItemTimeUntil.visibility = GONE
with(timetableItemTimeLeft) { with(timetableItemTimeLeft) {
visibility = VISIBLE visibility = VISIBLE
@ -204,14 +126,13 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
R.string.timetable_time_left, R.string.timetable_time_left,
context.getString( context.getString(
R.string.timetable_minutes, R.string.timetable_minutes,
left.toMinutes().toString() timeLeft.left.toMinutes().toString()
) )
) )
} }
} }
// right after lesson finish // right after lesson finish
isJustFinished -> { timeLeft?.isJustFinished == true -> {
Timber.d("Show just finished lesson: $position")
timetableItemTimeUntil.visibility = GONE timetableItemTimeUntil.visibility = GONE
timetableItemTimeLeft.visibility = VISIBLE timetableItemTimeLeft.visibility = VISIBLE
timetableItemTimeLeft.text = root.context.getString(R.string.timetable_finished) timetableItemTimeLeft.text = root.context.getString(R.string.timetable_finished)
@ -225,9 +146,7 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
} }
private fun bindSubjectStyle(subjectView: TextView, lesson: Timetable) { private fun bindSubjectStyle(subjectView: TextView, lesson: Timetable) {
subjectView.paintFlags = subjectView.paint.isStrikeThruText = lesson.canceled
if (lesson.canceled) subjectView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
else subjectView.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
} }
private fun bindSmallDescription(binding: ItemTimetableSmallBinding, lesson: Timetable) { private fun bindSmallDescription(binding: ItemTimetableSmallBinding, lesson: Timetable) {
@ -253,7 +172,8 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
} }
} }
private fun bindNormalDescription(binding: ItemTimetableBinding, lesson: Timetable) { private fun bindNormalDescription(binding: ItemTimetableBinding, item: TimetableItem.Normal) {
val lesson = item.lesson
with(binding) { with(binding) {
if (lesson.info.isNotBlank() && !lesson.changes) { if (lesson.info.isNotBlank() && !lesson.changes) {
timetableItemDescription.visibility = VISIBLE timetableItemDescription.visibility = VISIBLE
@ -272,8 +192,7 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
} else { } else {
timetableItemDescription.visibility = GONE timetableItemDescription.visibility = GONE
timetableItemRoom.visibility = VISIBLE timetableItemRoom.visibility = VISIBLE
timetableItemGroup.visibility = timetableItemGroup.isVisible = item.showGroupsInPlan && lesson.group.isNotBlank()
if (showGroupsInPlan && lesson.group.isNotBlank()) VISIBLE else GONE
timetableItemTeacher.visibility = VISIBLE timetableItemTeacher.visibility = VISIBLE
} }
} }
@ -349,26 +268,35 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
) )
} }
private class ItemViewHolder(val binding: ItemTimetableBinding) : private class NormalViewHolder(val binding: ItemTimetableBinding) :
RecyclerView.ViewHolder(binding.root) RecyclerView.ViewHolder(binding.root)
private class SmallItemViewHolder(val binding: ItemTimetableSmallBinding) : private class SmallViewHolder(val binding: ItemTimetableSmallBinding) :
RecyclerView.ViewHolder(binding.root) RecyclerView.ViewHolder(binding.root)
class TimetableAdapterDiffCallback( companion object {
private val oldList: List<Timetable>, private val differ = object : DiffUtil.ItemCallback<TimetableItem>() {
private val newList: List<Timetable>, override fun areItemsTheSame(oldItem: TimetableItem, newItem: TimetableItem): Boolean =
private val isFlagsDifferent: Boolean when {
) : DiffUtil.Callback() { oldItem is TimetableItem.Small && newItem is TimetableItem.Small -> {
oldItem.lesson.start == newItem.lesson.start
}
oldItem is TimetableItem.Normal && newItem is TimetableItem.Normal -> {
oldItem.lesson.start == newItem.lesson.start
}
else -> oldItem == newItem
}
override fun getOldListSize() = oldList.size override fun areContentsTheSame(oldItem: TimetableItem, newItem: TimetableItem) =
oldItem == newItem
override fun getNewListSize() = newList.size override fun getChangePayload(oldItem: TimetableItem, newItem: TimetableItem): Any? {
return if (oldItem is TimetableItem.Normal && newItem is TimetableItem.Normal) {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) = if (oldItem.lesson == newItem.lesson && oldItem.timeLeft != newItem.timeLeft) {
oldList[oldItemPosition].id == newList[newItemPosition].id "time_left"
} else super.getChangePayload(oldItem, newItem)
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = } else super.getChangePayload(oldItem, newItem)
oldList[oldItemPosition] == newList[newItemPosition] && !isFlagsDifferent }
}
} }
} }

View File

@ -12,7 +12,6 @@ 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
import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.data.enums.TimetableMode
import io.github.wulkanowy.databinding.FragmentTimetableBinding import io.github.wulkanowy.databinding.FragmentTimetableBinding
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
@ -20,11 +19,7 @@ import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.timetable.additional.AdditionalLessonsFragment import io.github.wulkanowy.ui.modules.timetable.additional.AdditionalLessonsFragment
import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment import io.github.wulkanowy.ui.modules.timetable.completed.CompletedLessonsFragment
import io.github.wulkanowy.ui.widgets.DividerItemDecoration import io.github.wulkanowy.ui.widgets.DividerItemDecoration
import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.*
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 java.time.LocalDate
import javax.inject.Inject import javax.inject.Inject
@ -73,8 +68,6 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
} }
override fun initView() { override fun initView() {
timetableAdapter.onClickListener = presenter::onTimetableItemSelected
with(binding.timetableRecycler) { with(binding.timetableRecycler) {
layoutManager = LinearLayoutManager(context) layoutManager = LinearLayoutManager(context)
adapter = timetableAdapter adapter = timetableAdapter
@ -110,18 +103,8 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
} }
} }
override fun updateData( override fun updateData(data: List<TimetableItem>) {
data: List<Timetable>, timetableAdapter.submitList(data)
showWholeClassPlanType: TimetableMode,
showGroupsInPlanType: Boolean,
showTimetableTimers: Boolean
) {
timetableAdapter.submitList(
newTimetable = data.toMutableList(),
showGroupsInPlan = showGroupsInPlanType,
showTimers = showTimetableTimers,
showWholeClassPlan = showWholeClassPlanType
)
} }
override fun clearData() { override fun clearData() {
@ -214,7 +197,6 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
} }
override fun onDestroyView() { override fun onDestroyView() {
timetableAdapter.clearTimers()
presenter.onDetachView() presenter.onDetachView()
super.onDestroyView() super.onDestroyView()
} }

View File

@ -0,0 +1,30 @@
package io.github.wulkanowy.ui.modules.timetable
import io.github.wulkanowy.data.db.entities.Timetable
import java.time.Duration
sealed class TimetableItem(val type: TimetableItemType) {
data class Small(
val lesson: Timetable,
val onClick: (Timetable) -> Unit,
) : TimetableItem(TimetableItemType.SMALL)
data class Normal(
val lesson: Timetable,
val showGroupsInPlan: Boolean,
val timeLeft: TimeLeft?,
val onClick: (Timetable) -> Unit,
) : TimetableItem(TimetableItemType.NORMAL)
}
data class TimeLeft(
val until: Duration?,
val left: Duration?,
val isJustFinished: Boolean,
)
enum class TimetableItemType {
SMALL,
NORMAL,
}

View File

@ -1,6 +1,5 @@
package io.github.wulkanowy.ui.modules.timetable package io.github.wulkanowy.ui.modules.timetable
import android.annotation.SuppressLint
import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.data.enums.TimetableMode import io.github.wulkanowy.data.enums.TimetableMode
@ -10,25 +9,17 @@ 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.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.*
import io.github.wulkanowy.utils.afterLoading
import io.github.wulkanowy.utils.capitalise
import io.github.wulkanowy.utils.flowWithResourceIn
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.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.Instant
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalDate.now import java.time.LocalDate.*
import java.time.LocalDate.of import java.util.*
import java.time.LocalDate.ofEpochDay
import javax.inject.Inject import javax.inject.Inject
import kotlin.concurrent.timer
class TimetablePresenter @Inject constructor( class TimetablePresenter @Inject constructor(
errorHandler: ErrorHandler, errorHandler: ErrorHandler,
@ -46,6 +37,8 @@ class TimetablePresenter @Inject constructor(
private lateinit var lastError: Throwable private lateinit var lastError: Throwable
private var tickTimer: Timer? = null
fun onAttachView(view: TimetableView, date: Long?) { fun onAttachView(view: TimetableView, date: Long?) {
super.onAttachView(view) super.onAttachView(view)
view.initView() view.initView()
@ -106,11 +99,6 @@ class TimetablePresenter @Inject constructor(
} }
} }
fun onTimetableItemSelected(lesson: Timetable) {
Timber.i("Select timetable item ${lesson.id}")
view?.showTimetableDialog(lesson)
}
fun onAdditionalLessonsSwitchSelected(): Boolean { fun onAdditionalLessonsSwitchSelected(): Boolean {
view?.openAdditionalLessonsView() view?.openAdditionalLessonsView()
return true return true
@ -148,12 +136,12 @@ class TimetablePresenter @Inject constructor(
Status.LOADING -> { Status.LOADING -> {
if (!it.data?.lessons.isNullOrEmpty()) { if (!it.data?.lessons.isNullOrEmpty()) {
view?.run { view?.run {
updateData(it.data!!.lessons)
enableSwipe(true) enableSwipe(true)
showRefresh(true) showRefresh(true)
showErrorView(false) showErrorView(false)
showProgress(false) showProgress(false)
showContent(true) showContent(true)
updateData(it.data!!.lessons)
} }
} }
} }
@ -189,17 +177,62 @@ class TimetablePresenter @Inject constructor(
} }
private fun updateData(lessons: List<Timetable>) { private fun updateData(lessons: List<Timetable>) {
view?.updateData( tickTimer?.cancel()
showWholeClassPlanType = prefRepository.showWholeClassPlan,
showGroupsInPlanType = prefRepository.showGroupsInPlan, if (!prefRepository.showTimetableTimers) {
showTimetableTimers = prefRepository.showTimetableTimers, view?.updateData(createItems(lessons))
data = createItems(lessons) } else {
tickTimer = timer(period = 2_000) {
view?.updateData(createItems(lessons))
}
}
}
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.number }, { item -> !item.isStudentPlan })
)
return filteredItems.mapIndexed { i, it ->
if (it.isStudentPlan) TimetableItem.Normal(
lesson = it,
showGroupsInPlan = prefRepository.showGroupsInPlan,
timeLeft = filteredItems.getTimeLeftForLesson(it, i),
onClick = ::onTimetableItemSelected
) else TimetableItem.Small(
lesson = it,
onClick = ::onTimetableItemSelected
)
}
}
private fun List<Timetable>.getTimeLeftForLesson(lesson: Timetable, index: Int): TimeLeft {
val isShowTimeUntil = lesson.isShowTimeUntil(getPreviousLesson(index))
return TimeLeft(
until = lesson.until.plusMinutes(1).takeIf { isShowTimeUntil },
left = lesson.left?.plusMinutes(1),
isJustFinished = lesson.isJustFinished,
) )
} }
private fun createItems(items: List<Timetable>) = items.filter { item -> private fun List<Timetable>.getPreviousLesson(position: Int): Instant? {
if (prefRepository.showWholeClassPlan == TimetableMode.ONLY_CURRENT_GROUP) item.isStudentPlan else true return filter { it.isStudentPlan }
}.sortedWith(compareBy({ item -> item.number }, { item -> !item.isStudentPlan })) .getOrNull(position - 1 - filterIndexed { i, item -> i < position && !item.isStudentPlan }.size)
?.let {
if (!it.canceled && it.isStudentPlan) it.end
else null
}
}
private fun onTimetableItemSelected(lesson: Timetable) {
Timber.i("Select timetable item ${lesson.id}")
view?.showTimetableDialog(lesson)
}
private fun showErrorViewOnError(message: String, error: Throwable) { private fun showErrorViewOnError(message: String, error: Throwable) {
view?.run { view?.run {
@ -227,7 +260,6 @@ class TimetablePresenter @Inject constructor(
} }
} }
@SuppressLint("DefaultLocale")
private fun reloadNavigation() { private fun reloadNavigation() {
view?.apply { view?.apply {
showPreButton(!currentDate.minusDays(1).isHolidays) showPreButton(!currentDate.minusDays(1).isHolidays)
@ -235,4 +267,10 @@ class TimetablePresenter @Inject constructor(
updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalise()) updateNavigationDay(currentDate.toFormattedString("EEEE, dd.MM").capitalise())
} }
} }
override fun onDetachView() {
tickTimer?.cancel()
tickTimer = null
super.onDetachView()
}
} }

View File

@ -1,7 +1,6 @@
package io.github.wulkanowy.ui.modules.timetable package io.github.wulkanowy.ui.modules.timetable
import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.data.enums.TimetableMode
import io.github.wulkanowy.ui.base.BaseView import io.github.wulkanowy.ui.base.BaseView
import java.time.LocalDate import java.time.LocalDate
@ -13,12 +12,7 @@ interface TimetableView : BaseView {
fun initView() fun initView()
fun updateData( fun updateData(data: List<TimetableItem>)
data: List<Timetable>,
showWholeClassPlanType: TimetableMode,
showGroupsInPlanType: Boolean,
showTimetableTimers: Boolean
)
fun updateNavigationDay(date: String) fun updateNavigationDay(date: String)