forked from github/wulkanowy-mirror
Add dashboard (#1267)
This commit is contained in:
@ -0,0 +1,713 @@
|
||||
package io.github.wulkanowy.ui.modules.dashboard
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Typeface
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.data.db.entities.TimetableHeader
|
||||
import io.github.wulkanowy.databinding.ItemDashboardAccountBinding
|
||||
import io.github.wulkanowy.databinding.ItemDashboardAnnouncementsBinding
|
||||
import io.github.wulkanowy.databinding.ItemDashboardConferencesBinding
|
||||
import io.github.wulkanowy.databinding.ItemDashboardExamsBinding
|
||||
import io.github.wulkanowy.databinding.ItemDashboardGradesBinding
|
||||
import io.github.wulkanowy.databinding.ItemDashboardHomeworkBinding
|
||||
import io.github.wulkanowy.databinding.ItemDashboardHorizontalGroupBinding
|
||||
import io.github.wulkanowy.databinding.ItemDashboardLessonsBinding
|
||||
import io.github.wulkanowy.utils.createNameInitialsDrawable
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.left
|
||||
import io.github.wulkanowy.utils.nickOrName
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import java.time.Duration
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.util.Timer
|
||||
import javax.inject.Inject
|
||||
import kotlin.concurrent.timer
|
||||
|
||||
class DashboardAdapter @Inject constructor() :
|
||||
ListAdapter<DashboardItem, RecyclerView.ViewHolder>(DashboardAdapterDiffCallback()) {
|
||||
|
||||
var lessonsTimer: Timer? = null
|
||||
|
||||
var onAccountTileClickListener: () -> Unit = {}
|
||||
|
||||
var onLuckyNumberTileClickListener: () -> Unit = {}
|
||||
|
||||
var onMessageTileClickListener: () -> Unit = {}
|
||||
|
||||
var onGradeTileClickListener: () -> Unit = {}
|
||||
|
||||
var onAttendanceTileClickListener: () -> Unit = {}
|
||||
|
||||
var onLessonsTileClickListener: () -> Unit = {}
|
||||
|
||||
var onHomeworkTileClickListener: () -> Unit = {}
|
||||
|
||||
var onAnnouncementsTileClickListener: () -> Unit = {}
|
||||
|
||||
var onExamsTileClickListener: () -> Unit = {}
|
||||
|
||||
var onConferencesTileClickListener: () -> Unit = {}
|
||||
|
||||
override fun getItemViewType(position: Int) = getItem(position).type.ordinal
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
|
||||
return when (viewType) {
|
||||
DashboardItem.Type.ACCOUNT.ordinal -> AccountViewHolder(
|
||||
ItemDashboardAccountBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
DashboardItem.Type.HORIZONTAL_GROUP.ordinal -> HorizontalGroupViewHolder(
|
||||
ItemDashboardHorizontalGroupBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
DashboardItem.Type.GRADES.ordinal -> GradesViewHolder(
|
||||
ItemDashboardGradesBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
DashboardItem.Type.LESSONS.ordinal -> LessonsViewHolder(
|
||||
ItemDashboardLessonsBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
DashboardItem.Type.HOMEWORK.ordinal -> HomeworkViewHolder(
|
||||
ItemDashboardHomeworkBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
DashboardItem.Type.ANNOUNCEMENTS.ordinal -> AnnouncementsViewHolder(
|
||||
ItemDashboardAnnouncementsBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
DashboardItem.Type.EXAMS.ordinal -> ExamsViewHolder(
|
||||
ItemDashboardExamsBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
DashboardItem.Type.CONFERENCES.ordinal -> ConferencesViewHolder(
|
||||
ItemDashboardConferencesBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is AccountViewHolder -> bindAccountViewHolder(holder, position)
|
||||
is HorizontalGroupViewHolder -> bindHorizontalGroupViewHolder(holder, position)
|
||||
is GradesViewHolder -> bindGradesViewHolder(holder, position)
|
||||
is LessonsViewHolder -> bindLessonsViewHolder(holder, position)
|
||||
is HomeworkViewHolder -> bindHomeworkViewHolder(holder, position)
|
||||
is AnnouncementsViewHolder -> bindAnnouncementsViewHolder(holder, position)
|
||||
is ExamsViewHolder -> bindExamsViewHolder(holder, position)
|
||||
is ConferencesViewHolder -> bindConferencesViewHolder(holder, position)
|
||||
}
|
||||
}
|
||||
|
||||
fun clearTimers() {
|
||||
lessonsTimer?.let {
|
||||
it.cancel()
|
||||
it.purge()
|
||||
}
|
||||
lessonsTimer = null
|
||||
}
|
||||
|
||||
private fun bindAccountViewHolder(accountViewHolder: AccountViewHolder, position: Int) {
|
||||
val item = getItem(position) as DashboardItem.Account
|
||||
val student = item.student
|
||||
val isLoading = item.isLoading
|
||||
|
||||
val avatar = student?.let {
|
||||
accountViewHolder.binding.root.context.createNameInitialsDrawable(
|
||||
text = it.nickOrName,
|
||||
backgroundColor = it.avatarColor
|
||||
)
|
||||
}
|
||||
|
||||
with(accountViewHolder.binding) {
|
||||
dashboardAccountItemContent.isVisible = !isLoading
|
||||
dashboardAccountItemProgress.isVisible = isLoading
|
||||
|
||||
dashboardAccountItemAvatar.setImageDrawable(avatar)
|
||||
dashboardAccountItemName.text = student?.nickOrName.orEmpty()
|
||||
dashboardAccountItemSchoolName.text = student?.schoolName.orEmpty()
|
||||
|
||||
root.setOnClickListener { onAccountTileClickListener() }
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun bindHorizontalGroupViewHolder(
|
||||
horizontalGroupViewHolder: HorizontalGroupViewHolder,
|
||||
position: Int
|
||||
) {
|
||||
val item = getItem(position) as DashboardItem.HorizontalGroup
|
||||
val unreadMessagesCount = item.unreadMessagesCount
|
||||
val attendancePercentage = item.attendancePercentage
|
||||
val luckyNumber = item.luckyNumber
|
||||
val error = item.error
|
||||
val isLoading = item.isLoading
|
||||
val binding = horizontalGroupViewHolder.binding
|
||||
val context = binding.root.context
|
||||
val attendanceColor = when {
|
||||
attendancePercentage ?: 0.0 <= ATTENDANCE_SECOND_WARNING_THRESHOLD -> {
|
||||
context.getThemeAttrColor(R.attr.colorPrimary)
|
||||
}
|
||||
attendancePercentage ?: 0.0 <= ATTENDANCE_FIRST_WARNING_THRESHOLD -> {
|
||||
context.getThemeAttrColor(R.attr.colorTimetableChange)
|
||||
}
|
||||
else -> context.getThemeAttrColor(R.attr.colorOnSurface)
|
||||
}
|
||||
|
||||
with(binding.dashboardHorizontalGroupItemAttendanceValue) {
|
||||
text = "%.2f%%".format(attendancePercentage)
|
||||
setTextColor(attendanceColor)
|
||||
}
|
||||
|
||||
with(binding) {
|
||||
dashboardHorizontalGroupItemMessageValue.text = unreadMessagesCount.toString()
|
||||
dashboardHorizontalGroupItemLuckyValue.text = if (luckyNumber == -1) {
|
||||
context.getString(R.string.dashboard_horizontal_group_no_lukcy_number)
|
||||
} else luckyNumber?.toString()
|
||||
|
||||
if (dashboardHorizontalGroupItemInfoContainer.isVisible != (error != null || isLoading)) {
|
||||
dashboardHorizontalGroupItemInfoContainer.isVisible = error != null || isLoading
|
||||
}
|
||||
|
||||
if (dashboardHorizontalGroupItemInfoProgress.isVisible != isLoading) {
|
||||
dashboardHorizontalGroupItemInfoProgress.isVisible = isLoading
|
||||
}
|
||||
|
||||
dashboardHorizontalGroupItemInfoErrorText.isVisible = error != null
|
||||
|
||||
with(dashboardHorizontalGroupItemLuckyContainer) {
|
||||
isVisible = error == null && !isLoading && luckyNumber != null
|
||||
setOnClickListener { onLuckyNumberTileClickListener() }
|
||||
}
|
||||
|
||||
with(dashboardHorizontalGroupItemAttendanceContainer) {
|
||||
isVisible = error == null && !isLoading && attendancePercentage != null
|
||||
updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
matchConstraintPercentWidth = when {
|
||||
luckyNumber == null && unreadMessagesCount == null -> 1.0f
|
||||
luckyNumber == null || unreadMessagesCount == null -> 0.5f
|
||||
else -> 0.4f
|
||||
}
|
||||
}
|
||||
setOnClickListener { onAttendanceTileClickListener() }
|
||||
}
|
||||
|
||||
with(dashboardHorizontalGroupItemMessageContainer) {
|
||||
isVisible = error == null && !isLoading && unreadMessagesCount != null
|
||||
setOnClickListener { onMessageTileClickListener() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindGradesViewHolder(gradesViewHolder: GradesViewHolder, position: Int) {
|
||||
val item = getItem(position) as DashboardItem.Grades
|
||||
val subjectWithGrades = item.subjectWithGrades.orEmpty()
|
||||
val gradeTheme = item.gradeTheme
|
||||
val error = item.error
|
||||
val isLoading = item.isLoading
|
||||
val dashboardGradesAdapter = gradesViewHolder.adapter.apply {
|
||||
this.items = subjectWithGrades.toList()
|
||||
this.gradeTheme = gradeTheme.orEmpty()
|
||||
}
|
||||
|
||||
with(gradesViewHolder.binding) {
|
||||
dashboardGradesItemEmpty.isVisible =
|
||||
subjectWithGrades.isEmpty() && error == null && !isLoading
|
||||
dashboardGradesItemError.isVisible = error != null && !isLoading
|
||||
dashboardGradesItemProgress.isVisible =
|
||||
isLoading && error == null && subjectWithGrades.isEmpty()
|
||||
|
||||
with(dashboardGradesItemRecycler) {
|
||||
adapter = dashboardGradesAdapter
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
isVisible = subjectWithGrades.isNotEmpty() && error == null
|
||||
suppressLayout(true)
|
||||
}
|
||||
|
||||
root.setOnClickListener { onGradeTileClickListener() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindLessonsViewHolder(lessonsViewHolder: LessonsViewHolder, position: Int) {
|
||||
val item = getItem(position) as DashboardItem.Lessons
|
||||
val timetableFull = item.lessons
|
||||
val binding = lessonsViewHolder.binding
|
||||
|
||||
fun updateLessonState() {
|
||||
val currentDateTime = LocalDateTime.now()
|
||||
val currentDate = LocalDate.now()
|
||||
|
||||
val currentTimetable = timetableFull?.lessons
|
||||
.orEmpty()
|
||||
.filter { it.date == currentDate }
|
||||
.filter { it.end.isAfter(currentDateTime) }
|
||||
.filterNot { it.canceled }
|
||||
val currentDayHeader =
|
||||
timetableFull?.headers.orEmpty().singleOrNull { it.date == currentDate }
|
||||
|
||||
val tomorrowTimetable = timetableFull?.lessons.orEmpty()
|
||||
.filter { it.date == currentDate.plusDays(1) }
|
||||
.filterNot { it.canceled }
|
||||
val tomorrowDayHeader =
|
||||
timetableFull?.headers.orEmpty().singleOrNull { it.date == currentDate.plusDays(1) }
|
||||
|
||||
when {
|
||||
currentTimetable.isNotEmpty() -> {
|
||||
updateLessonView(item, currentTimetable, binding)
|
||||
binding.dashboardLessonsItemTitleTomorrow.isVisible = false
|
||||
}
|
||||
currentDayHeader != null && currentDayHeader.content.isNotBlank() -> {
|
||||
updateLessonView(item, emptyList(), binding, currentDayHeader)
|
||||
binding.dashboardLessonsItemTitleTomorrow.isVisible = false
|
||||
}
|
||||
tomorrowTimetable.isNotEmpty() -> {
|
||||
updateLessonView(item, tomorrowTimetable, binding)
|
||||
binding.dashboardLessonsItemTitleTomorrow.isVisible = true
|
||||
}
|
||||
tomorrowDayHeader != null && tomorrowDayHeader.content.isNotBlank() -> {
|
||||
updateLessonView(item, emptyList(), binding, tomorrowDayHeader)
|
||||
binding.dashboardLessonsItemTitleTomorrow.isVisible = true
|
||||
}
|
||||
else -> {
|
||||
updateLessonView(item, emptyList(), binding)
|
||||
binding.dashboardLessonsItemTitleTomorrow.isVisible =
|
||||
!(item.isLoading && item.error == null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateLessonState()
|
||||
|
||||
lessonsTimer?.cancel()
|
||||
lessonsTimer = timer(period = 1000) {
|
||||
Handler(Looper.getMainLooper()).post { updateLessonState() }
|
||||
}
|
||||
|
||||
binding.root.setOnClickListener { onLessonsTileClickListener() }
|
||||
}
|
||||
|
||||
private fun updateLessonView(
|
||||
item: DashboardItem.Lessons,
|
||||
timetableToShow: List<Timetable>,
|
||||
binding: ItemDashboardLessonsBinding,
|
||||
header: TimetableHeader? = null,
|
||||
) {
|
||||
val currentDateTime = LocalDateTime.now()
|
||||
val nextLessons = timetableToShow.filter { it.end.isAfter(currentDateTime) }
|
||||
.sortedBy { it.start }
|
||||
|
||||
with(binding) {
|
||||
dashboardLessonsItemEmpty.isVisible =
|
||||
(timetableToShow.isEmpty() || nextLessons.isEmpty()) && item.error == null && header == null && !item.isLoading
|
||||
dashboardLessonsItemError.isVisible = item.error != null && !item.isLoading
|
||||
dashboardLessonsItemProgress.isVisible =
|
||||
item.isLoading && (timetableToShow.isEmpty() || nextLessons.isEmpty()) && item.error == null && header == null
|
||||
|
||||
val secondLesson = nextLessons.getOrNull(1)
|
||||
val firstLesson = nextLessons.getOrNull(0)
|
||||
|
||||
updateFirstLessonView(binding, firstLesson, currentDateTime)
|
||||
updateSecondLesson(binding, firstLesson, secondLesson)
|
||||
updateLessonSummary(binding, nextLessons)
|
||||
updateLessonHeader(binding, header)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateFirstLessonView(
|
||||
binding: ItemDashboardLessonsBinding,
|
||||
firstLesson: Timetable?,
|
||||
currentDateTime: LocalDateTime
|
||||
) {
|
||||
val context = binding.root.context
|
||||
val sansSerifFont = Typeface.create("sans-serif", Typeface.NORMAL)
|
||||
val sansSerifMediumFont = Typeface.create("sans-serif-medium", Typeface.NORMAL)
|
||||
|
||||
with(binding) {
|
||||
dashboardLessonsItemFirstTitle.isVisible = firstLesson != null
|
||||
dashboardLessonsItemFirstTime.isVisible = firstLesson != null
|
||||
dashboardLessonsItemFirstTimeRange.isVisible = firstLesson != null
|
||||
dashboardLessonsItemFirstValue.isVisible = firstLesson != null
|
||||
}
|
||||
|
||||
firstLesson ?: return
|
||||
|
||||
val minutesToStartLesson =
|
||||
Duration.between(currentDateTime, firstLesson.start).toMinutes()
|
||||
val isFirstTimeVisible: Boolean
|
||||
val isFirstTimeRangeVisible: Boolean
|
||||
val firstTimeText: String
|
||||
val firstTimeRangeText: String
|
||||
val firstTitleText: String
|
||||
val firstTitleAndValueTextColor: Int
|
||||
val firstTitleAndValueTextFont: Typeface
|
||||
|
||||
if (currentDateTime.isBefore(firstLesson.start)) {
|
||||
if (minutesToStartLesson > 60) {
|
||||
val formattedStartTime = firstLesson.start.toFormattedString("HH:mm")
|
||||
val formattedEndTime = firstLesson.end.toFormattedString("HH:mm")
|
||||
|
||||
firstTimeRangeText = "${formattedStartTime}-${formattedEndTime}"
|
||||
firstTimeText = ""
|
||||
|
||||
isFirstTimeRangeVisible = true
|
||||
isFirstTimeVisible = false
|
||||
} else {
|
||||
firstTimeText = context.resources.getQuantityString(
|
||||
R.plurals.dashboard_timetable_first_lesson_time_in_minutes,
|
||||
minutesToStartLesson.toInt(),
|
||||
minutesToStartLesson
|
||||
)
|
||||
firstTimeRangeText = ""
|
||||
|
||||
isFirstTimeRangeVisible = false
|
||||
isFirstTimeVisible = true
|
||||
}
|
||||
|
||||
when {
|
||||
minutesToStartLesson < 60 -> {
|
||||
firstTitleAndValueTextColor = context.getThemeAttrColor(R.attr.colorPrimary)
|
||||
firstTitleAndValueTextFont = sansSerifMediumFont
|
||||
firstTitleText =
|
||||
context.getString(R.string.dashboard_timetable_first_lesson_title_moment)
|
||||
}
|
||||
minutesToStartLesson < 240 -> {
|
||||
firstTitleAndValueTextColor =
|
||||
context.getThemeAttrColor(R.attr.colorOnSurface)
|
||||
firstTitleAndValueTextFont = sansSerifFont
|
||||
firstTitleText =
|
||||
context.getString(R.string.dashboard_timetable_first_lesson_title_soon)
|
||||
}
|
||||
else -> {
|
||||
firstTitleAndValueTextColor =
|
||||
context.getThemeAttrColor(R.attr.colorOnSurface)
|
||||
firstTitleAndValueTextFont = sansSerifFont
|
||||
firstTitleText =
|
||||
context.getString(R.string.dashboard_timetable_first_lesson_title_first)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val minutesToEndLesson = firstLesson.left!!.toMinutes()
|
||||
|
||||
firstTimeText = context.resources.getQuantityString(
|
||||
R.plurals.dashboard_timetable_first_lesson_time_more_minutes,
|
||||
minutesToEndLesson.toInt(),
|
||||
minutesToEndLesson
|
||||
)
|
||||
firstTimeRangeText = ""
|
||||
|
||||
isFirstTimeRangeVisible = false
|
||||
isFirstTimeVisible = true
|
||||
|
||||
firstTitleAndValueTextColor = context.getThemeAttrColor(R.attr.colorPrimary)
|
||||
firstTitleAndValueTextFont = sansSerifMediumFont
|
||||
firstTitleText = context.getString(R.string.dashboard_timetable_first_lesson_title_now)
|
||||
}
|
||||
|
||||
with(binding.dashboardLessonsItemFirstTime) {
|
||||
isVisible = isFirstTimeVisible
|
||||
text = firstTimeText
|
||||
}
|
||||
with(binding.dashboardLessonsItemFirstTimeRange) {
|
||||
isVisible = isFirstTimeRangeVisible
|
||||
text = firstTimeRangeText
|
||||
}
|
||||
with(binding.dashboardLessonsItemFirstTitle) {
|
||||
setTextColor(firstTitleAndValueTextColor)
|
||||
typeface = firstTitleAndValueTextFont
|
||||
text = firstTitleText
|
||||
}
|
||||
with(binding.dashboardLessonsItemFirstValue) {
|
||||
setTextColor(firstTitleAndValueTextColor)
|
||||
typeface = firstTitleAndValueTextFont
|
||||
text = context.getString(
|
||||
R.string.dashboard_timetable_lesson_value,
|
||||
firstLesson.subject,
|
||||
firstLesson.room
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSecondLesson(
|
||||
binding: ItemDashboardLessonsBinding,
|
||||
firstLesson: Timetable?,
|
||||
secondLesson: Timetable?
|
||||
) {
|
||||
val context = binding.root.context
|
||||
|
||||
val formattedStartTime = secondLesson?.start?.toFormattedString("HH:mm")
|
||||
val formattedEndTime = secondLesson?.end?.toFormattedString("HH:mm")
|
||||
|
||||
val secondTimeText = "${formattedStartTime}-${formattedEndTime}"
|
||||
val secondValueText = if (secondLesson != null) {
|
||||
context.getString(
|
||||
R.string.dashboard_timetable_lesson_value,
|
||||
secondLesson.subject,
|
||||
secondLesson.room
|
||||
)
|
||||
} else {
|
||||
context.getString(R.string.dashboard_timetable_second_lesson_value_end)
|
||||
}
|
||||
|
||||
with(binding.dashboardLessonsItemSecondTime) {
|
||||
isVisible = secondLesson != null
|
||||
text = secondTimeText
|
||||
}
|
||||
with(binding.dashboardLessonsItemSecondValue) {
|
||||
isVisible = !(secondLesson == null && firstLesson == null)
|
||||
text = secondValueText
|
||||
}
|
||||
binding.dashboardLessonsItemSecondTitle.isVisible =
|
||||
!(secondLesson == null && firstLesson == null)
|
||||
}
|
||||
|
||||
private fun updateLessonSummary(
|
||||
binding: ItemDashboardLessonsBinding,
|
||||
nextLessons: List<Timetable>
|
||||
) {
|
||||
val context = binding.root.context
|
||||
val formattedEndTime = nextLessons.lastOrNull()?.end?.toFormattedString("HH:mm")
|
||||
|
||||
with(binding) {
|
||||
dashboardLessonsItemThirdTime.isVisible =
|
||||
nextLessons.size > LESSON_SUMMARY_VISIBILITY_THRESHOLD
|
||||
dashboardLessonsItemThirdTitle.isVisible =
|
||||
nextLessons.size > LESSON_SUMMARY_VISIBILITY_THRESHOLD
|
||||
dashboardLessonsItemThirdValue.isVisible =
|
||||
nextLessons.size > LESSON_SUMMARY_VISIBILITY_THRESHOLD
|
||||
dashboardLessonsItemDivider.isVisible =
|
||||
nextLessons.size > LESSON_SUMMARY_VISIBILITY_THRESHOLD
|
||||
|
||||
dashboardLessonsItemThirdValue.text = context.resources.getQuantityString(
|
||||
R.plurals.dashboard_timetable_third_value,
|
||||
nextLessons.size - LESSON_SUMMARY_VISIBILITY_THRESHOLD,
|
||||
nextLessons.size - LESSON_SUMMARY_VISIBILITY_THRESHOLD
|
||||
)
|
||||
dashboardLessonsItemThirdTime.text =
|
||||
context.getString(R.string.dashboard_timetable_third_time, formattedEndTime)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateLessonHeader(
|
||||
binding: ItemDashboardLessonsBinding,
|
||||
header: TimetableHeader?
|
||||
) {
|
||||
with(binding.dashboardLessonsItemDayHeader) {
|
||||
isVisible = header != null
|
||||
text = header?.content
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindHomeworkViewHolder(homeworkViewHolder: HomeworkViewHolder, position: Int) {
|
||||
val item = getItem(position) as DashboardItem.Homework
|
||||
val homeworkList = item.homework.orEmpty()
|
||||
val error = item.error
|
||||
val isLoading = item.isLoading
|
||||
val context = homeworkViewHolder.binding.root.context
|
||||
val homeworkAdapter = homeworkViewHolder.adapter.apply {
|
||||
this.items = homeworkList.take(MAX_VISIBLE_LIST_ITEMS)
|
||||
}
|
||||
|
||||
with(homeworkViewHolder.binding) {
|
||||
dashboardHomeworkItemEmpty.isVisible =
|
||||
homeworkList.isEmpty() && error == null && !isLoading
|
||||
dashboardHomeworkItemError.isVisible = error != null && !isLoading
|
||||
dashboardHomeworkItemProgress.isVisible =
|
||||
isLoading && error == null && homeworkList.isEmpty()
|
||||
dashboardHomeworkItemDivider.isVisible = homeworkList.size > MAX_VISIBLE_LIST_ITEMS
|
||||
dashboardHomeworkItemMore.isVisible = homeworkList.size > MAX_VISIBLE_LIST_ITEMS
|
||||
dashboardHomeworkItemMore.text = context.resources.getQuantityString(
|
||||
R.plurals.dashboard_homework_more,
|
||||
homeworkList.size - MAX_VISIBLE_LIST_ITEMS,
|
||||
homeworkList.size - MAX_VISIBLE_LIST_ITEMS
|
||||
)
|
||||
|
||||
with(dashboardHomeworkItemRecycler) {
|
||||
adapter = homeworkAdapter
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
isVisible = homeworkList.isNotEmpty() && error == null
|
||||
suppressLayout(true)
|
||||
}
|
||||
|
||||
root.setOnClickListener { onHomeworkTileClickListener() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindAnnouncementsViewHolder(
|
||||
announcementsViewHolder: AnnouncementsViewHolder,
|
||||
position: Int
|
||||
) {
|
||||
val item = getItem(position) as DashboardItem.Announcements
|
||||
val schoolAnnouncementList = item.announcement.orEmpty()
|
||||
val error = item.error
|
||||
val isLoading = item.isLoading
|
||||
val context = announcementsViewHolder.binding.root.context
|
||||
val schoolAnnouncementsAdapter = announcementsViewHolder.adapter.apply {
|
||||
this.items = schoolAnnouncementList.take(MAX_VISIBLE_LIST_ITEMS)
|
||||
}
|
||||
|
||||
with(announcementsViewHolder.binding) {
|
||||
dashboardAnnouncementsItemEmpty.isVisible =
|
||||
schoolAnnouncementList.isEmpty() && error == null && !isLoading
|
||||
dashboardAnnouncementsItemError.isVisible = error != null && !isLoading
|
||||
dashboardAnnouncementsItemProgress.isVisible =
|
||||
isLoading && error == null && schoolAnnouncementList.isEmpty()
|
||||
dashboardAnnouncementsItemDivider.isVisible =
|
||||
schoolAnnouncementList.size > MAX_VISIBLE_LIST_ITEMS
|
||||
dashboardAnnouncementsItemMore.isVisible =
|
||||
schoolAnnouncementList.size > MAX_VISIBLE_LIST_ITEMS
|
||||
dashboardAnnouncementsItemMore.text = context.resources.getQuantityString(
|
||||
R.plurals.dashboard_announcements_more,
|
||||
schoolAnnouncementList.size - MAX_VISIBLE_LIST_ITEMS,
|
||||
schoolAnnouncementList.size - MAX_VISIBLE_LIST_ITEMS
|
||||
)
|
||||
|
||||
with(dashboardAnnouncementsItemRecycler) {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = schoolAnnouncementsAdapter
|
||||
isVisible = schoolAnnouncementList.isNotEmpty() && error == null
|
||||
suppressLayout(true)
|
||||
}
|
||||
|
||||
root.setOnClickListener { onAnnouncementsTileClickListener() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindExamsViewHolder(examsViewHolder: ExamsViewHolder, position: Int) {
|
||||
val item = getItem(position) as DashboardItem.Exams
|
||||
val exams = item.exams.orEmpty()
|
||||
val error = item.error
|
||||
val isLoading = item.isLoading
|
||||
val context = examsViewHolder.binding.root.context
|
||||
val examAdapter = examsViewHolder.adapter.apply {
|
||||
this.items = exams.take(MAX_VISIBLE_LIST_ITEMS)
|
||||
}
|
||||
|
||||
with(examsViewHolder.binding) {
|
||||
dashboardExamsItemEmpty.isVisible = exams.isEmpty() && error == null && !isLoading
|
||||
dashboardExamsItemError.isVisible = error != null && !isLoading
|
||||
dashboardExamsItemProgress.isVisible = isLoading && error == null && exams.isEmpty()
|
||||
dashboardExamsItemDivider.isVisible = exams.size > MAX_VISIBLE_LIST_ITEMS
|
||||
dashboardExamsItemMore.isVisible = exams.size > MAX_VISIBLE_LIST_ITEMS
|
||||
dashboardExamsItemMore.text = context.resources.getQuantityString(
|
||||
R.plurals.dashboard_exams_more,
|
||||
exams.size - MAX_VISIBLE_LIST_ITEMS,
|
||||
exams.size - MAX_VISIBLE_LIST_ITEMS
|
||||
)
|
||||
|
||||
with(dashboardExamsItemRecycler) {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = examAdapter
|
||||
isVisible = exams.isNotEmpty() && error == null
|
||||
suppressLayout(true)
|
||||
}
|
||||
|
||||
root.setOnClickListener { onExamsTileClickListener() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindConferencesViewHolder(
|
||||
conferencesViewHolder: ConferencesViewHolder,
|
||||
position: Int
|
||||
) {
|
||||
val item = getItem(position) as DashboardItem.Conferences
|
||||
val conferences = item.conferences.orEmpty()
|
||||
val error = item.error
|
||||
val isLoading = item.isLoading
|
||||
val context = conferencesViewHolder.binding.root.context
|
||||
val conferenceAdapter = conferencesViewHolder.adapter.apply {
|
||||
this.items = conferences.take(MAX_VISIBLE_LIST_ITEMS)
|
||||
}
|
||||
|
||||
with(conferencesViewHolder.binding) {
|
||||
dashboardConferencesItemEmpty.isVisible =
|
||||
conferences.isEmpty() && error == null && !isLoading
|
||||
dashboardConferencesItemError.isVisible = error != null && !isLoading
|
||||
dashboardConferencesItemProgress.isVisible =
|
||||
isLoading && error == null && conferences.isEmpty()
|
||||
dashboardConferencesItemDivider.isVisible = conferences.size > MAX_VISIBLE_LIST_ITEMS
|
||||
dashboardConferencesItemMore.isVisible = conferences.size > MAX_VISIBLE_LIST_ITEMS
|
||||
dashboardConferencesItemMore.text = context.resources.getQuantityString(
|
||||
R.plurals.dashboard_conference_more,
|
||||
conferences.size - MAX_VISIBLE_LIST_ITEMS,
|
||||
conferences.size - MAX_VISIBLE_LIST_ITEMS
|
||||
)
|
||||
|
||||
with(dashboardConferencesItemRecycler) {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = conferenceAdapter
|
||||
isVisible = conferences.isNotEmpty() && error == null
|
||||
suppressLayout(true)
|
||||
}
|
||||
|
||||
root.setOnClickListener { onConferencesTileClickListener() }
|
||||
}
|
||||
}
|
||||
|
||||
class AccountViewHolder(val binding: ItemDashboardAccountBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
class HorizontalGroupViewHolder(val binding: ItemDashboardHorizontalGroupBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
class GradesViewHolder(val binding: ItemDashboardGradesBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
val adapter by lazy { DashboardGradesAdapter() }
|
||||
}
|
||||
|
||||
class LessonsViewHolder(val binding: ItemDashboardLessonsBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
class HomeworkViewHolder(val binding: ItemDashboardHomeworkBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
val adapter by lazy { DashboardHomeworkAdapter() }
|
||||
}
|
||||
|
||||
class AnnouncementsViewHolder(val binding: ItemDashboardAnnouncementsBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
val adapter by lazy { DashboardAnnouncementsAdapter() }
|
||||
}
|
||||
|
||||
class ExamsViewHolder(val binding: ItemDashboardExamsBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
val adapter by lazy { DashboardExamsAdapter() }
|
||||
}
|
||||
|
||||
class ConferencesViewHolder(val binding: ItemDashboardConferencesBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
val adapter by lazy { DashboardConferencesAdapter() }
|
||||
}
|
||||
|
||||
class DashboardAdapterDiffCallback : DiffUtil.ItemCallback<DashboardItem>() {
|
||||
|
||||
override fun areItemsTheSame(oldItem: DashboardItem, newItem: DashboardItem) =
|
||||
oldItem.type == newItem.type
|
||||
|
||||
override fun areContentsTheSame(oldItem: DashboardItem, newItem: DashboardItem) =
|
||||
oldItem == newItem
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
private const val LESSON_SUMMARY_VISIBILITY_THRESHOLD = 2
|
||||
|
||||
private const val MAX_VISIBLE_LIST_ITEMS = 5
|
||||
|
||||
private const val ATTENDANCE_FIRST_WARNING_THRESHOLD = 75.0
|
||||
|
||||
private const val ATTENDANCE_SECOND_WARNING_THRESHOLD = 50.0
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package io.github.wulkanowy.ui.modules.dashboard
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
||||
import io.github.wulkanowy.databinding.SubitemDashboardAnnouncementsBinding
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
|
||||
class DashboardAnnouncementsAdapter :
|
||||
RecyclerView.Adapter<DashboardAnnouncementsAdapter.ViewHolder>() {
|
||||
|
||||
var items = emptyList<SchoolAnnouncement>()
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
|
||||
SubitemDashboardAnnouncementsBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
|
||||
with(holder.binding) {
|
||||
dashboardHomeworkSubitemTime.text = item.date.toFormattedString()
|
||||
dashboardHomeworkSubitemTitle.text = item.subject
|
||||
}
|
||||
}
|
||||
|
||||
class ViewHolder(val binding: SubitemDashboardAnnouncementsBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package io.github.wulkanowy.ui.modules.dashboard
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.data.db.entities.Conference
|
||||
import io.github.wulkanowy.databinding.SubitemDashboardConferencesBinding
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
|
||||
class DashboardConferencesAdapter :
|
||||
RecyclerView.Adapter<DashboardConferencesAdapter.ViewHolder>() {
|
||||
|
||||
var items = emptyList<Conference>()
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
|
||||
SubitemDashboardConferencesBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
|
||||
with(holder.binding) {
|
||||
dashboardHomeworkSubitemTime.text = item.date.toFormattedString("HH:mm dd.MM.yyyy")
|
||||
dashboardHomeworkSubitemTitle.text = item.title
|
||||
}
|
||||
}
|
||||
|
||||
class ViewHolder(val binding: SubitemDashboardConferencesBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package io.github.wulkanowy.ui.modules.dashboard
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.databinding.SubitemDashboardExamsBinding
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import java.time.LocalDate
|
||||
|
||||
class DashboardExamsAdapter :
|
||||
RecyclerView.Adapter<DashboardExamsAdapter.ViewHolder>() {
|
||||
|
||||
var items = emptyList<Exam>()
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
|
||||
SubitemDashboardExamsBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
val context = holder.binding.root.context
|
||||
val primaryWarningTextColor = context.getThemeAttrColor(
|
||||
if (item.date == LocalDate.now()) {
|
||||
R.attr.colorPrimary
|
||||
} else {
|
||||
android.R.attr.textColorPrimary
|
||||
}
|
||||
)
|
||||
val secondaryWarningTextColor = context.getThemeAttrColor(
|
||||
if (item.date == LocalDate.now()) {
|
||||
R.attr.colorPrimary
|
||||
} else {
|
||||
android.R.attr.textColorSecondary
|
||||
}
|
||||
)
|
||||
|
||||
with(holder.binding) {
|
||||
dashboardHomeworkSubitemTime.text = item.date.toFormattedString("dd.MM")
|
||||
dashboardHomeworkSubitemTime.setTextColor(secondaryWarningTextColor)
|
||||
|
||||
dashboardHomeworkSubitemTitle.text = "${item.type} - ${item.subject}"
|
||||
dashboardHomeworkSubitemTitle.setTextColor(primaryWarningTextColor)
|
||||
}
|
||||
}
|
||||
|
||||
class ViewHolder(val binding: SubitemDashboardExamsBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
package io.github.wulkanowy.ui.modules.dashboard
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.databinding.FragmentDashboardBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.account.AccountFragment
|
||||
import io.github.wulkanowy.ui.modules.attendance.AttendanceFragment
|
||||
import io.github.wulkanowy.ui.modules.conference.ConferenceFragment
|
||||
import io.github.wulkanowy.ui.modules.exam.ExamFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
||||
import io.github.wulkanowy.ui.modules.homework.HomeworkFragment
|
||||
import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.ui.modules.message.MessageFragment
|
||||
import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment
|
||||
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
|
||||
import io.github.wulkanowy.utils.capitalise
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import java.time.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class DashboardFragment : BaseFragment<FragmentDashboardBinding>(R.layout.fragment_dashboard),
|
||||
DashboardView, MainView.TitledView, MainView.MainChildView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: DashboardPresenter
|
||||
|
||||
@Inject
|
||||
lateinit var dashboardAdapter: DashboardAdapter
|
||||
|
||||
override val titleStringId get() = R.string.dashboard_title
|
||||
|
||||
override var subtitleString =
|
||||
LocalDate.now().toFormattedString("EEEE, d MMMM yyyy").capitalise()
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance() = DashboardFragment()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding = FragmentDashboardBinding.bind(view)
|
||||
presenter.onAttachView(this)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.action_menu_dashboard, menu)
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
val mainActivity = requireActivity() as MainActivity
|
||||
|
||||
dashboardAdapter.apply {
|
||||
onAccountTileClickListener = { mainActivity.pushView(AccountFragment.newInstance()) }
|
||||
onLuckyNumberTileClickListener = {
|
||||
mainActivity.pushView(LuckyNumberFragment.newInstance())
|
||||
}
|
||||
onMessageTileClickListener = { mainActivity.pushView(MessageFragment.newInstance()) }
|
||||
onAttendanceTileClickListener = {
|
||||
mainActivity.pushView(AttendanceFragment.newInstance())
|
||||
}
|
||||
onLessonsTileClickListener = { mainActivity.pushView(TimetableFragment.newInstance()) }
|
||||
onGradeTileClickListener = { mainActivity.pushView(GradeFragment.newInstance()) }
|
||||
onHomeworkTileClickListener = { mainActivity.pushView(HomeworkFragment.newInstance()) }
|
||||
onAnnouncementsTileClickListener = {
|
||||
mainActivity.pushView(SchoolAnnouncementFragment.newInstance())
|
||||
}
|
||||
onExamsTileClickListener = { mainActivity.pushView(ExamFragment.newInstance()) }
|
||||
onConferencesTileClickListener = {
|
||||
mainActivity.pushView(ConferenceFragment.newInstance())
|
||||
}
|
||||
}
|
||||
|
||||
with(binding) {
|
||||
dashboardErrorRetry.setOnClickListener { presenter.onRetry() }
|
||||
dashboardErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||
dashboardSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
||||
dashboardSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary))
|
||||
dashboardSwipe.setProgressBackgroundColorSchemeColor(
|
||||
requireContext().getThemeAttrColor(R.attr.colorSwipeRefresh)
|
||||
)
|
||||
|
||||
with(dashboardRecycler) {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = dashboardAdapter
|
||||
(itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.dashboard_menu_tiles -> presenter.onDashboardTileSettingsSelected()
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
override fun showDashboardTileSettings(selectedItems: List<DashboardItem.Tile>) {
|
||||
val entries = requireContext().resources.getStringArray(R.array.dashboard_tile_entries)
|
||||
val values = requireContext().resources.getStringArray(R.array.dashboard_tile_values)
|
||||
val selectedItemsState = values.map { value -> selectedItems.any { it.name == value } }
|
||||
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.pref_dashboard_appearance_tiles_title)
|
||||
.setMultiChoiceItems(entries, selectedItemsState.toBooleanArray()) { _, _, _ -> }
|
||||
.setPositiveButton(android.R.string.ok) { dialog, _ ->
|
||||
val selectedState = (dialog as AlertDialog).listView.checkedItemPositions
|
||||
val selectedValues = values.filterIndexed { index, _ -> selectedState[index] }
|
||||
|
||||
presenter.onDashboardTileSettingSelected(selectedValues)
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun updateData(data: List<DashboardItem>) {
|
||||
dashboardAdapter.submitList(data.toMutableList())
|
||||
}
|
||||
|
||||
override fun showMessage(text: String) {
|
||||
//Empty function to avoid message flood
|
||||
}
|
||||
|
||||
override fun showRefresh(show: Boolean) {
|
||||
binding.dashboardSwipe.isRefreshing = show
|
||||
}
|
||||
|
||||
override fun showProgress(show: Boolean) {
|
||||
binding.dashboardProgress.isVisible = show
|
||||
}
|
||||
|
||||
override fun showContent(show: Boolean) {
|
||||
binding.dashboardRecycler.isVisible = show
|
||||
}
|
||||
|
||||
override fun showErrorView(show: Boolean) {
|
||||
binding.dashboardErrorContainer.isVisible = show
|
||||
}
|
||||
|
||||
override fun setErrorDetails(message: String) {
|
||||
binding.dashboardErrorMessage.text = message
|
||||
}
|
||||
|
||||
override fun resetView() {
|
||||
binding.dashboardRecycler.smoothScrollToPosition(0)
|
||||
}
|
||||
|
||||
override fun popViewToRoot() {
|
||||
(requireActivity() as MainActivity).popView(20)
|
||||
}
|
||||
|
||||
override fun onFragmentReselected() {
|
||||
if (::presenter.isInitialized) presenter.onViewReselected()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
dashboardAdapter.clearTimers()
|
||||
presenter.onDetachView()
|
||||
super.onDestroyView()
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package io.github.wulkanowy.ui.modules.dashboard
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.databinding.SubitemDashboardGradesBinding
|
||||
import io.github.wulkanowy.databinding.SubitemDashboardSmallGradeBinding
|
||||
import io.github.wulkanowy.utils.getBackgroundColor
|
||||
|
||||
class DashboardGradesAdapter : RecyclerView.Adapter<DashboardGradesAdapter.ViewHolder>() {
|
||||
|
||||
var items = listOf<Pair<String, List<Grade>>>()
|
||||
|
||||
var gradeTheme = ""
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
|
||||
SubitemDashboardGradesBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
)
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val (subject, grades) = items[position]
|
||||
val context = holder.binding.root.context
|
||||
|
||||
with(holder.binding) {
|
||||
dashboardGradesSubitemTitle.text = subject
|
||||
|
||||
grades.forEach {
|
||||
val subitemBinding = SubitemDashboardSmallGradeBinding.inflate(
|
||||
LayoutInflater.from(context),
|
||||
dashboardGradesSubitemGradeContainer,
|
||||
false
|
||||
)
|
||||
|
||||
with(subitemBinding.dashboardSmallGradeSubitemValue) {
|
||||
text = it.entry
|
||||
setBackgroundResource(it.getBackgroundColor(gradeTheme))
|
||||
}
|
||||
|
||||
dashboardGradesSubitemGradeContainer.addView(subitemBinding.root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ViewHolder(val binding: SubitemDashboardGradesBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package io.github.wulkanowy.ui.modules.dashboard
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Homework
|
||||
import io.github.wulkanowy.databinding.SubitemDashboardHomeworkBinding
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.toFormattedString
|
||||
import java.time.LocalDate
|
||||
|
||||
class DashboardHomeworkAdapter : RecyclerView.Adapter<DashboardHomeworkAdapter.ViewHolder>() {
|
||||
|
||||
var items = emptyList<Homework>()
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
|
||||
SubitemDashboardHomeworkBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
)
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
val context = holder.binding.root.context
|
||||
val formattedDate = item.date.toFormattedString("dd.MM")
|
||||
val primaryWarningTextColor = context.getThemeAttrColor(
|
||||
if (item.date == LocalDate.now()) {
|
||||
R.attr.colorPrimary
|
||||
} else {
|
||||
android.R.attr.textColorPrimary
|
||||
}
|
||||
)
|
||||
val secondaryWarningTextColor = context.getThemeAttrColor(
|
||||
if (item.date == LocalDate.now()) {
|
||||
R.attr.colorPrimary
|
||||
} else {
|
||||
android.R.attr.textColorSecondary
|
||||
}
|
||||
)
|
||||
|
||||
with(holder.binding) {
|
||||
dashboardHomeworkSubitemTitle.text = "${item.subject} - ${item.content}"
|
||||
dashboardHomeworkSubitemTitle.setTextColor(primaryWarningTextColor)
|
||||
|
||||
dashboardHomeworkSubitemTime.text =
|
||||
context.getString(R.string.dashboard_homework_time, formattedDate)
|
||||
dashboardHomeworkSubitemTime.setTextColor(secondaryWarningTextColor)
|
||||
}
|
||||
}
|
||||
|
||||
class ViewHolder(val binding: SubitemDashboardHomeworkBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
package io.github.wulkanowy.ui.modules.dashboard
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Conference
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.pojos.TimetableFull
|
||||
import io.github.wulkanowy.data.db.entities.Homework as EntitiesHomework
|
||||
|
||||
sealed class DashboardItem(val type: Type) {
|
||||
|
||||
abstract val error: Throwable?
|
||||
|
||||
abstract val isLoading: Boolean
|
||||
|
||||
abstract val isDataLoaded: Boolean
|
||||
|
||||
data class Account(
|
||||
val student: Student? = null,
|
||||
override val error: Throwable? = null,
|
||||
override val isLoading: Boolean = false
|
||||
) : DashboardItem(Type.ACCOUNT) {
|
||||
|
||||
override val isDataLoaded get() = student != null
|
||||
}
|
||||
|
||||
data class HorizontalGroup(
|
||||
val unreadMessagesCount: Int? = null,
|
||||
val attendancePercentage: Double? = null,
|
||||
val luckyNumber: Int? = null,
|
||||
override val error: Throwable? = null,
|
||||
override val isLoading: Boolean = false
|
||||
) : DashboardItem(Type.HORIZONTAL_GROUP) {
|
||||
|
||||
override val isDataLoaded
|
||||
get() = unreadMessagesCount != null || attendancePercentage != null || luckyNumber != null
|
||||
}
|
||||
|
||||
data class Grades(
|
||||
val subjectWithGrades: Map<String, List<Grade>>? = null,
|
||||
val gradeTheme: String? = null,
|
||||
override val error: Throwable? = null,
|
||||
override val isLoading: Boolean = false
|
||||
) : DashboardItem(Type.GRADES) {
|
||||
|
||||
override val isDataLoaded get() = subjectWithGrades != null
|
||||
}
|
||||
|
||||
data class Lessons(
|
||||
val lessons: TimetableFull? = null,
|
||||
override val error: Throwable? = null,
|
||||
override val isLoading: Boolean = false
|
||||
) : DashboardItem(Type.LESSONS) {
|
||||
|
||||
override val isDataLoaded get() = lessons != null
|
||||
}
|
||||
|
||||
data class Homework(
|
||||
val homework: List<EntitiesHomework>? = null,
|
||||
override val error: Throwable? = null,
|
||||
override val isLoading: Boolean = false
|
||||
) : DashboardItem(Type.HOMEWORK) {
|
||||
|
||||
override val isDataLoaded get() = homework != null
|
||||
}
|
||||
|
||||
data class Announcements(
|
||||
val announcement: List<SchoolAnnouncement>? = null,
|
||||
override val error: Throwable? = null,
|
||||
override val isLoading: Boolean = false
|
||||
) : DashboardItem(Type.ANNOUNCEMENTS) {
|
||||
|
||||
override val isDataLoaded get() = announcement != null
|
||||
}
|
||||
|
||||
data class Exams(
|
||||
val exams: List<Exam>? = null,
|
||||
override val error: Throwable? = null,
|
||||
override val isLoading: Boolean = false
|
||||
) : DashboardItem(Type.EXAMS) {
|
||||
|
||||
override val isDataLoaded get() = exams != null
|
||||
}
|
||||
|
||||
data class Conferences(
|
||||
val conferences: List<Conference>? = null,
|
||||
override val error: Throwable? = null,
|
||||
override val isLoading: Boolean = false
|
||||
) : DashboardItem(Type.CONFERENCES) {
|
||||
|
||||
override val isDataLoaded get() = conferences != null
|
||||
}
|
||||
|
||||
enum class Type {
|
||||
ACCOUNT,
|
||||
HORIZONTAL_GROUP,
|
||||
LESSONS,
|
||||
GRADES,
|
||||
HOMEWORK,
|
||||
ANNOUNCEMENTS,
|
||||
EXAMS,
|
||||
CONFERENCES,
|
||||
ADS
|
||||
}
|
||||
|
||||
enum class Tile {
|
||||
ACCOUNT,
|
||||
LUCKY_NUMBER,
|
||||
MESSAGES,
|
||||
ATTENDANCE,
|
||||
LESSONS,
|
||||
GRADES,
|
||||
HOMEWORK,
|
||||
ANNOUNCEMENTS,
|
||||
EXAMS,
|
||||
CONFERENCES,
|
||||
ADS
|
||||
}
|
||||
}
|
||||
|
||||
fun DashboardItem.Tile.toDashboardItemType() = when (this) {
|
||||
DashboardItem.Tile.ACCOUNT -> DashboardItem.Type.ACCOUNT
|
||||
DashboardItem.Tile.LUCKY_NUMBER -> DashboardItem.Type.HORIZONTAL_GROUP
|
||||
DashboardItem.Tile.MESSAGES -> DashboardItem.Type.HORIZONTAL_GROUP
|
||||
DashboardItem.Tile.ATTENDANCE -> DashboardItem.Type.HORIZONTAL_GROUP
|
||||
DashboardItem.Tile.LESSONS -> DashboardItem.Type.LESSONS
|
||||
DashboardItem.Tile.GRADES -> DashboardItem.Type.GRADES
|
||||
DashboardItem.Tile.HOMEWORK -> DashboardItem.Type.HOMEWORK
|
||||
DashboardItem.Tile.ANNOUNCEMENTS -> DashboardItem.Type.ANNOUNCEMENTS
|
||||
DashboardItem.Tile.EXAMS -> DashboardItem.Type.EXAMS
|
||||
DashboardItem.Tile.CONFERENCES -> DashboardItem.Type.CONFERENCES
|
||||
DashboardItem.Tile.ADS -> DashboardItem.Type.ADS
|
||||
}
|
@ -0,0 +1,684 @@
|
||||
package io.github.wulkanowy.ui.modules.dashboard
|
||||
|
||||
import io.github.wulkanowy.data.Resource
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.enums.MessageFolder
|
||||
import io.github.wulkanowy.data.repositories.AttendanceSummaryRepository
|
||||
import io.github.wulkanowy.data.repositories.ConferenceRepository
|
||||
import io.github.wulkanowy.data.repositories.ExamRepository
|
||||
import io.github.wulkanowy.data.repositories.GradeRepository
|
||||
import io.github.wulkanowy.data.repositories.HomeworkRepository
|
||||
import io.github.wulkanowy.data.repositories.LuckyNumberRepository
|
||||
import io.github.wulkanowy.data.repositories.MessageRepository
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.SchoolAnnouncementRepository
|
||||
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.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.calculatePercentage
|
||||
import io.github.wulkanowy.utils.flowWithResource
|
||||
import io.github.wulkanowy.utils.flowWithResourceIn
|
||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import javax.inject.Inject
|
||||
|
||||
class DashboardPresenter @Inject constructor(
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val luckyNumberRepository: LuckyNumberRepository,
|
||||
private val gradeRepository: GradeRepository,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val messageRepository: MessageRepository,
|
||||
private val attendanceSummaryRepository: AttendanceSummaryRepository,
|
||||
private val timetableRepository: TimetableRepository,
|
||||
private val homeworkRepository: HomeworkRepository,
|
||||
private val examRepository: ExamRepository,
|
||||
private val conferenceRepository: ConferenceRepository,
|
||||
private val preferencesRepository: PreferencesRepository,
|
||||
private val schoolAnnouncementRepository: SchoolAnnouncementRepository
|
||||
) : BasePresenter<DashboardView>(errorHandler, studentRepository) {
|
||||
|
||||
private val dashboardItemLoadedList = mutableListOf<DashboardItem>()
|
||||
|
||||
private val dashboardItemRefreshLoadedList = mutableListOf<DashboardItem>()
|
||||
|
||||
private lateinit var dashboardItemsToLoad: Set<DashboardItem.Type>
|
||||
|
||||
private var dashboardTilesToLoad: Set<DashboardItem.Tile> = emptySet()
|
||||
|
||||
private lateinit var lastError: Throwable
|
||||
|
||||
override fun onAttachView(view: DashboardView) {
|
||||
super.onAttachView(view)
|
||||
|
||||
with(view) {
|
||||
initView()
|
||||
showProgress(true)
|
||||
showContent(false)
|
||||
}
|
||||
|
||||
preferencesRepository.selectedDashboardTilesFlow
|
||||
.onEach { loadData(tilesToLoad = it) }
|
||||
.launch("dashboard_pref")
|
||||
}
|
||||
|
||||
fun loadData(forceRefresh: Boolean = false, tilesToLoad: Set<DashboardItem.Tile>) {
|
||||
val oldDashboardDataToLoad = dashboardTilesToLoad
|
||||
|
||||
dashboardTilesToLoad = tilesToLoad
|
||||
dashboardItemsToLoad = dashboardTilesToLoad.map { it.toDashboardItemType() }.toSet()
|
||||
|
||||
removeUnselectedTiles()
|
||||
|
||||
val newTileList = generateTileListToLoad(oldDashboardDataToLoad, forceRefresh)
|
||||
loadTiles(forceRefresh, newTileList)
|
||||
}
|
||||
|
||||
private fun removeUnselectedTiles() {
|
||||
val isLuckyNumberToLoad =
|
||||
dashboardTilesToLoad.any { it == DashboardItem.Tile.LUCKY_NUMBER }
|
||||
val isMessagesToLoad =
|
||||
dashboardTilesToLoad.any { it == DashboardItem.Tile.MESSAGES }
|
||||
val isAttendanceToLoad =
|
||||
dashboardTilesToLoad.any { it == DashboardItem.Tile.ATTENDANCE }
|
||||
|
||||
dashboardItemLoadedList.removeAll { loadedTile -> dashboardItemsToLoad.none { it == loadedTile.type } }
|
||||
|
||||
val horizontalGroup =
|
||||
dashboardItemLoadedList.find { it is DashboardItem.HorizontalGroup } as DashboardItem.HorizontalGroup?
|
||||
|
||||
if (horizontalGroup != null) {
|
||||
val horizontalIndex = dashboardItemLoadedList.indexOf(horizontalGroup)
|
||||
dashboardItemLoadedList.remove(horizontalGroup)
|
||||
|
||||
var updatedHorizontalGroup = horizontalGroup
|
||||
|
||||
if (horizontalGroup.luckyNumber != null && !isLuckyNumberToLoad) {
|
||||
updatedHorizontalGroup = updatedHorizontalGroup.copy(luckyNumber = null)
|
||||
}
|
||||
|
||||
if (horizontalGroup.attendancePercentage != null && !isAttendanceToLoad) {
|
||||
updatedHorizontalGroup = updatedHorizontalGroup.copy(attendancePercentage = null)
|
||||
}
|
||||
|
||||
if (horizontalGroup.unreadMessagesCount != null && !isMessagesToLoad) {
|
||||
updatedHorizontalGroup = updatedHorizontalGroup.copy(unreadMessagesCount = null)
|
||||
}
|
||||
|
||||
if (horizontalGroup.error != null) {
|
||||
updatedHorizontalGroup = updatedHorizontalGroup.copy(error = null, isLoading = true)
|
||||
}
|
||||
|
||||
dashboardItemLoadedList.add(horizontalIndex, updatedHorizontalGroup)
|
||||
}
|
||||
|
||||
view?.updateData(dashboardItemLoadedList)
|
||||
}
|
||||
|
||||
private fun loadTiles(forceRefresh: Boolean, tileList: List<DashboardItem.Tile>) {
|
||||
tileList.forEach {
|
||||
when (it) {
|
||||
DashboardItem.Tile.ACCOUNT -> loadCurrentAccount(forceRefresh)
|
||||
DashboardItem.Tile.LUCKY_NUMBER -> loadLuckyNumber(forceRefresh)
|
||||
DashboardItem.Tile.MESSAGES -> loadMessages(forceRefresh)
|
||||
DashboardItem.Tile.ATTENDANCE -> loadAttendance(forceRefresh)
|
||||
DashboardItem.Tile.LESSONS -> loadLessons(forceRefresh)
|
||||
DashboardItem.Tile.GRADES -> loadGrades(forceRefresh)
|
||||
DashboardItem.Tile.HOMEWORK -> loadHomework(forceRefresh)
|
||||
DashboardItem.Tile.ANNOUNCEMENTS -> loadSchoolAnnouncements(forceRefresh)
|
||||
DashboardItem.Tile.EXAMS -> loadExams(forceRefresh)
|
||||
DashboardItem.Tile.CONFERENCES -> loadConferences(forceRefresh)
|
||||
DashboardItem.Tile.ADS -> TODO()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateTileListToLoad(
|
||||
oldDashboardTileToLoad: Set<DashboardItem.Tile>,
|
||||
forceRefresh: Boolean
|
||||
) = dashboardTilesToLoad.filter { newTileToLoad ->
|
||||
oldDashboardTileToLoad.none { it == newTileToLoad } || forceRefresh
|
||||
}
|
||||
|
||||
fun onSwipeRefresh() {
|
||||
Timber.i("Force refreshing the dashboard")
|
||||
loadData(true, preferencesRepository.selectedDashboardTiles)
|
||||
}
|
||||
|
||||
fun onRetry() {
|
||||
view?.run {
|
||||
showErrorView(false)
|
||||
showProgress(true)
|
||||
}
|
||||
loadData(true, preferencesRepository.selectedDashboardTiles)
|
||||
}
|
||||
|
||||
fun onViewReselected() {
|
||||
Timber.i("Dashboard view is reselected")
|
||||
view?.run {
|
||||
resetView()
|
||||
popViewToRoot()
|
||||
}
|
||||
}
|
||||
|
||||
fun onDetailsClick() {
|
||||
view?.showErrorDetailsDialog(lastError)
|
||||
}
|
||||
|
||||
fun onDashboardTileSettingsSelected(): Boolean {
|
||||
view?.showDashboardTileSettings(preferencesRepository.selectedDashboardTiles.toList())
|
||||
return true
|
||||
}
|
||||
|
||||
fun onDashboardTileSettingSelected(selectedItems: List<String>) {
|
||||
preferencesRepository.selectedDashboardTiles = selectedItems.map {
|
||||
DashboardItem.Tile.valueOf(it)
|
||||
}.toSet()
|
||||
}
|
||||
|
||||
private fun loadCurrentAccount(forceRefresh: Boolean) {
|
||||
flowWithResource { studentRepository.getCurrentStudent(false) }
|
||||
.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> {
|
||||
Timber.i("Loading dashboard account data started")
|
||||
if (forceRefresh) return@onEach
|
||||
updateData(DashboardItem.Account(it.data, isLoading = true), forceRefresh)
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading dashboard account result: Success")
|
||||
updateData(DashboardItem.Account(it.data), forceRefresh)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading dashboard account result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
updateData(DashboardItem.Account(error = it.error), forceRefresh)
|
||||
}
|
||||
}
|
||||
}
|
||||
.launch("dashboard_account")
|
||||
}
|
||||
|
||||
private fun loadLuckyNumber(forceRefresh: Boolean) {
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent(true)
|
||||
|
||||
luckyNumberRepository.getLuckyNumber(student, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> {
|
||||
Timber.i("Loading dashboard lucky number data started")
|
||||
if (forceRefresh) return@onEach
|
||||
processHorizontalGroupData(
|
||||
luckyNumber = it.data?.luckyNumber,
|
||||
isLoading = true,
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading dashboard lucky number result: Success")
|
||||
processHorizontalGroupData(
|
||||
luckyNumber = it.data?.luckyNumber ?: -1,
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading dashboard lucky number result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
processHorizontalGroupData(error = it.error, forceRefresh = forceRefresh)
|
||||
}
|
||||
}
|
||||
}.launch("dashboard_lucky_number")
|
||||
}
|
||||
|
||||
private fun loadMessages(forceRefresh: Boolean) {
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent(true)
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
|
||||
messageRepository.getMessages(student, semester, MessageFolder.RECEIVED, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> {
|
||||
Timber.i("Loading dashboard messages data started")
|
||||
if (forceRefresh) return@onEach
|
||||
val unreadMessagesCount = it.data?.count { message -> message.unread }
|
||||
|
||||
processHorizontalGroupData(
|
||||
unreadMessagesCount = unreadMessagesCount,
|
||||
isLoading = true,
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading dashboard messages result: Success")
|
||||
val unreadMessagesCount = it.data?.count { message -> message.unread }
|
||||
|
||||
processHorizontalGroupData(
|
||||
unreadMessagesCount = unreadMessagesCount,
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading dashboard messages result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
processHorizontalGroupData(error = it.error, forceRefresh = forceRefresh)
|
||||
}
|
||||
}
|
||||
}.launch("dashboard_messages")
|
||||
}
|
||||
|
||||
private fun loadAttendance(forceRefresh: Boolean) {
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent(true)
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
|
||||
attendanceSummaryRepository.getAttendanceSummary(student, semester, -1, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> {
|
||||
Timber.i("Loading dashboard attendance data started")
|
||||
if (forceRefresh) return@onEach
|
||||
val attendancePercentage = it.data?.calculatePercentage()
|
||||
|
||||
processHorizontalGroupData(
|
||||
attendancePercentage = attendancePercentage,
|
||||
isLoading = true,
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading dashboard attendance result: Success")
|
||||
val attendancePercentage = it.data?.calculatePercentage()
|
||||
|
||||
processHorizontalGroupData(
|
||||
attendancePercentage = attendancePercentage,
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading dashboard attendance result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
|
||||
processHorizontalGroupData(error = it.error, forceRefresh = forceRefresh)
|
||||
}
|
||||
}
|
||||
}.launch("dashboard_attendance")
|
||||
}
|
||||
|
||||
private fun loadGrades(forceRefresh: Boolean) {
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent(true)
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
|
||||
gradeRepository.getGrades(student, semester, forceRefresh)
|
||||
}.map { originalResource ->
|
||||
val filteredSubjectWithGrades = originalResource.data?.first.orEmpty()
|
||||
.filter { grade ->
|
||||
grade.date.isAfter(LocalDate.now().minusDays(7))
|
||||
}
|
||||
.groupBy { grade -> grade.subject }
|
||||
.mapValues { entry ->
|
||||
entry.value
|
||||
.take(5)
|
||||
.sortedBy { grade -> grade.date }
|
||||
}
|
||||
.toList()
|
||||
.sortedBy { subjectWithGrades -> subjectWithGrades.second[0].date }
|
||||
.toMap()
|
||||
|
||||
Resource(
|
||||
status = originalResource.status,
|
||||
data = filteredSubjectWithGrades.takeIf { originalResource.data != null },
|
||||
error = originalResource.error
|
||||
)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> {
|
||||
Timber.i("Loading dashboard grades data started")
|
||||
if (forceRefresh) return@onEach
|
||||
updateData(
|
||||
DashboardItem.Grades(
|
||||
subjectWithGrades = it.data,
|
||||
gradeTheme = preferencesRepository.gradeColorTheme,
|
||||
isLoading = true
|
||||
), forceRefresh
|
||||
)
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading dashboard grades result: Success")
|
||||
updateData(
|
||||
DashboardItem.Grades(
|
||||
subjectWithGrades = it.data,
|
||||
gradeTheme = preferencesRepository.gradeColorTheme
|
||||
), forceRefresh
|
||||
)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading dashboard grades result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
updateData(DashboardItem.Grades(error = it.error), forceRefresh)
|
||||
}
|
||||
}
|
||||
}.launch("dashboard_grades")
|
||||
}
|
||||
|
||||
private fun loadLessons(forceRefresh: Boolean) {
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent(true)
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
val date = LocalDate.now().nextOrSameSchoolDay
|
||||
|
||||
timetableRepository.getTimetable(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = date,
|
||||
end = date.plusDays(1),
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> {
|
||||
Timber.i("Loading dashboard lessons data started")
|
||||
if (forceRefresh) return@onEach
|
||||
updateData(DashboardItem.Lessons(it.data, isLoading = true), forceRefresh)
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading dashboard lessons result: Success")
|
||||
updateData(DashboardItem.Lessons(it.data), forceRefresh)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading dashboard lessons result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
updateData(DashboardItem.Lessons(error = it.error), forceRefresh)
|
||||
}
|
||||
}
|
||||
}.launch("dashboard_lessons")
|
||||
}
|
||||
|
||||
private fun loadHomework(forceRefresh: Boolean) {
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent(true)
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
val date = LocalDate.now().nextOrSameSchoolDay
|
||||
|
||||
homeworkRepository.getHomework(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = date,
|
||||
end = date,
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}.map { homeworkResource ->
|
||||
val currentDate = LocalDate.now()
|
||||
|
||||
val filteredHomework = homeworkResource.data?.filter {
|
||||
(it.date.isAfter(currentDate) || it.date == currentDate) && !it.isDone
|
||||
}
|
||||
|
||||
homeworkResource.copy(data = filteredHomework)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> {
|
||||
Timber.i("Loading dashboard homework data started")
|
||||
if (forceRefresh) return@onEach
|
||||
updateData(
|
||||
DashboardItem.Homework(it.data ?: emptyList(), isLoading = true),
|
||||
forceRefresh
|
||||
)
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading dashboard homework result: Success")
|
||||
updateData(DashboardItem.Homework(it.data ?: emptyList()), forceRefresh)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading dashboard homework result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
updateData(DashboardItem.Homework(error = it.error), forceRefresh)
|
||||
}
|
||||
}
|
||||
}.launch("dashboard_homework")
|
||||
}
|
||||
|
||||
private fun loadSchoolAnnouncements(forceRefresh: Boolean) {
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent(true)
|
||||
|
||||
schoolAnnouncementRepository.getSchoolAnnouncements(student, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> {
|
||||
Timber.i("Loading dashboard announcements data started")
|
||||
if (forceRefresh) return@onEach
|
||||
updateData(
|
||||
DashboardItem.Announcements(
|
||||
it.data ?: emptyList(),
|
||||
isLoading = true
|
||||
), forceRefresh
|
||||
)
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading dashboard announcements result: Success")
|
||||
updateData(DashboardItem.Announcements(it.data ?: emptyList()), forceRefresh)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading dashboard announcements result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
updateData(DashboardItem.Announcements(error = it.error), forceRefresh)
|
||||
}
|
||||
}
|
||||
}.launch("dashboard_announcements")
|
||||
}
|
||||
|
||||
private fun loadExams(forceRefresh: Boolean) {
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent(true)
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
|
||||
examRepository.getExams(
|
||||
student = student,
|
||||
semester = semester,
|
||||
start = LocalDate.now(),
|
||||
end = LocalDate.now().plusDays(7),
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> {
|
||||
Timber.i("Loading dashboard exams data started")
|
||||
if (forceRefresh) return@onEach
|
||||
updateData(
|
||||
DashboardItem.Exams(it.data.orEmpty(), isLoading = true),
|
||||
forceRefresh
|
||||
)
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading dashboard exams result: Success")
|
||||
updateData(DashboardItem.Exams(it.data ?: emptyList()), forceRefresh)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading dashboard exams result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
updateData(DashboardItem.Exams(error = it.error), forceRefresh)
|
||||
}
|
||||
}
|
||||
}.launch("dashboard_exams")
|
||||
}
|
||||
|
||||
private fun loadConferences(forceRefresh: Boolean) {
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent(true)
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
|
||||
conferenceRepository.getConferences(
|
||||
student = student,
|
||||
semester = semester,
|
||||
forceRefresh = forceRefresh,
|
||||
startDate = LocalDateTime.now()
|
||||
)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> {
|
||||
Timber.i("Loading dashboard conferences data started")
|
||||
if (forceRefresh) return@onEach
|
||||
updateData(
|
||||
DashboardItem.Conferences(it.data ?: emptyList(), isLoading = true),
|
||||
forceRefresh
|
||||
)
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading dashboard conferences result: Success")
|
||||
updateData(DashboardItem.Conferences(it.data ?: emptyList()), forceRefresh)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading dashboard conferences result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
updateData(DashboardItem.Conferences(error = it.error), forceRefresh)
|
||||
}
|
||||
}
|
||||
}.launch("dashboard_conferences")
|
||||
}
|
||||
|
||||
private fun processHorizontalGroupData(
|
||||
luckyNumber: Int? = null,
|
||||
unreadMessagesCount: Int? = null,
|
||||
attendancePercentage: Double? = null,
|
||||
error: Throwable? = null,
|
||||
isLoading: Boolean = false,
|
||||
forceRefresh: Boolean
|
||||
) {
|
||||
val isLuckyNumberToLoad =
|
||||
dashboardTilesToLoad.any { it == DashboardItem.Tile.LUCKY_NUMBER }
|
||||
val isMessagesToLoad =
|
||||
dashboardTilesToLoad.any { it == DashboardItem.Tile.MESSAGES }
|
||||
val isAttendanceToLoad =
|
||||
dashboardTilesToLoad.any { it == DashboardItem.Tile.ATTENDANCE }
|
||||
val isPushedToList =
|
||||
dashboardItemLoadedList.any { it.type == DashboardItem.Type.HORIZONTAL_GROUP }
|
||||
|
||||
if (error != null) {
|
||||
updateData(DashboardItem.HorizontalGroup(error = error), forceRefresh)
|
||||
return
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
val horizontalGroup =
|
||||
dashboardItemLoadedList.find { it is DashboardItem.HorizontalGroup } as DashboardItem.HorizontalGroup?
|
||||
val updatedHorizontalGroup =
|
||||
horizontalGroup?.copy(isLoading = true) ?: DashboardItem.HorizontalGroup(isLoading = true)
|
||||
|
||||
updateData(updatedHorizontalGroup, forceRefresh)
|
||||
}
|
||||
|
||||
if (forceRefresh && !isPushedToList) {
|
||||
updateData(DashboardItem.HorizontalGroup(), forceRefresh)
|
||||
}
|
||||
|
||||
val horizontalGroup =
|
||||
dashboardItemLoadedList.single { it is DashboardItem.HorizontalGroup } as DashboardItem.HorizontalGroup
|
||||
|
||||
when {
|
||||
luckyNumber != null -> {
|
||||
updateData(horizontalGroup.copy(luckyNumber = luckyNumber), forceRefresh)
|
||||
}
|
||||
unreadMessagesCount != null -> {
|
||||
updateData(
|
||||
horizontalGroup.copy(unreadMessagesCount = unreadMessagesCount),
|
||||
forceRefresh
|
||||
)
|
||||
}
|
||||
attendancePercentage != null -> {
|
||||
updateData(
|
||||
horizontalGroup.copy(attendancePercentage = attendancePercentage),
|
||||
forceRefresh
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val isHorizontalGroupLoaded = dashboardItemLoadedList.any {
|
||||
if (it !is DashboardItem.HorizontalGroup) return@any false
|
||||
|
||||
val isLuckyNumberStateCorrect = (it.luckyNumber != null) == isLuckyNumberToLoad
|
||||
val isMessagesStateCorrect = (it.unreadMessagesCount != null) == isMessagesToLoad
|
||||
val isAttendanceStateCorrect = (it.attendancePercentage != null) == isAttendanceToLoad
|
||||
|
||||
isLuckyNumberStateCorrect && isAttendanceStateCorrect && isMessagesStateCorrect
|
||||
}
|
||||
|
||||
if (isHorizontalGroupLoaded) {
|
||||
val updatedHorizontalGroup =
|
||||
dashboardItemLoadedList.single { it is DashboardItem.HorizontalGroup } as DashboardItem.HorizontalGroup
|
||||
|
||||
updateData(updatedHorizontalGroup.copy(isLoading = false, error = null), forceRefresh)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateData(dashboardItem: DashboardItem, forceRefresh: Boolean) {
|
||||
val isForceRefreshError = forceRefresh && dashboardItem.error != null
|
||||
|
||||
with(dashboardItemLoadedList) {
|
||||
removeAll { it.type == dashboardItem.type && !isForceRefreshError }
|
||||
if (!isForceRefreshError) add(dashboardItem)
|
||||
sortBy { tile -> dashboardItemsToLoad.single { it == tile.type }.ordinal }
|
||||
}
|
||||
|
||||
if (forceRefresh) {
|
||||
with(dashboardItemRefreshLoadedList) {
|
||||
removeAll { it.type == dashboardItem.type }
|
||||
add(dashboardItem)
|
||||
}
|
||||
}
|
||||
|
||||
dashboardItemLoadedList.sortBy { tile -> dashboardItemsToLoad.single { it == tile.type }.ordinal }
|
||||
|
||||
val isItemsLoaded =
|
||||
dashboardItemsToLoad.all { type -> dashboardItemLoadedList.any { it.type == type } }
|
||||
val isRefreshItemLoaded =
|
||||
dashboardItemsToLoad.all { type -> dashboardItemRefreshLoadedList.any { it.type == type } }
|
||||
val isItemsDataLoaded = isItemsLoaded && dashboardItemLoadedList.all {
|
||||
it.isDataLoaded || it.error != null
|
||||
}
|
||||
val isRefreshItemsDataLoaded = isRefreshItemLoaded && dashboardItemRefreshLoadedList.all {
|
||||
it.isDataLoaded || it.error != null
|
||||
}
|
||||
|
||||
if (isRefreshItemsDataLoaded) {
|
||||
view?.showRefresh(false)
|
||||
dashboardItemRefreshLoadedList.clear()
|
||||
}
|
||||
|
||||
view?.run {
|
||||
if (!forceRefresh) {
|
||||
showProgress(!isItemsDataLoaded)
|
||||
showContent(isItemsDataLoaded)
|
||||
}
|
||||
updateData(dashboardItemLoadedList.toList())
|
||||
}
|
||||
|
||||
if (isItemsLoaded) {
|
||||
val filteredItems =
|
||||
dashboardItemLoadedList.filterNot { it.type == DashboardItem.Type.ACCOUNT }
|
||||
val isAccountItemError =
|
||||
dashboardItemLoadedList.single { it.type == DashboardItem.Type.ACCOUNT }.error != null
|
||||
val isGeneralError =
|
||||
filteredItems.all { it.error != null } && filteredItems.isNotEmpty() || isAccountItemError
|
||||
|
||||
val errorMessage = filteredItems.map { it.error?.stackTraceToString() }.toString()
|
||||
|
||||
lastError = Exception(errorMessage)
|
||||
|
||||
view?.run {
|
||||
showProgress(false)
|
||||
showContent(!isGeneralError)
|
||||
showErrorView(isGeneralError)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package io.github.wulkanowy.ui.modules.dashboard
|
||||
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface DashboardView : BaseView {
|
||||
|
||||
fun initView()
|
||||
|
||||
fun updateData(data: List<DashboardItem>)
|
||||
|
||||
fun showDashboardTileSettings(selectedItems: List<DashboardItem.Tile>)
|
||||
|
||||
fun showProgress(show: Boolean)
|
||||
|
||||
fun showContent(show: Boolean)
|
||||
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun showErrorView(show: Boolean)
|
||||
|
||||
fun setErrorDetails(message: String)
|
||||
|
||||
fun resetView()
|
||||
|
||||
fun popViewToRoot()
|
||||
}
|
@ -33,7 +33,7 @@ import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.ui.modules.account.accountquick.AccountQuickDialog
|
||||
import io.github.wulkanowy.ui.modules.attendance.AttendanceFragment
|
||||
import io.github.wulkanowy.ui.modules.conference.ConferenceFragment
|
||||
import io.github.wulkanowy.ui.modules.exam.ExamFragment
|
||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
||||
import io.github.wulkanowy.ui.modules.homework.HomeworkFragment
|
||||
import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment
|
||||
@ -218,12 +218,12 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
|
||||
with(binding.mainBottomNav) {
|
||||
with(menu) {
|
||||
add(Menu.NONE, 0, Menu.NONE, R.string.grade_title)
|
||||
add(Menu.NONE, 0, Menu.NONE, R.string.dashboard_title)
|
||||
.setIcon(R.drawable.ic_main_dashboard)
|
||||
add(Menu.NONE, 1, Menu.NONE, R.string.grade_title)
|
||||
.setIcon(R.drawable.ic_main_grade)
|
||||
add(Menu.NONE, 1, Menu.NONE, R.string.attendance_title)
|
||||
add(Menu.NONE, 2, Menu.NONE, R.string.attendance_title)
|
||||
.setIcon(R.drawable.ic_main_attendance)
|
||||
add(Menu.NONE, 2, Menu.NONE, R.string.exam_title)
|
||||
.setIcon(R.drawable.ic_main_exam)
|
||||
add(Menu.NONE, 3, Menu.NONE, R.string.timetable_title)
|
||||
.setIcon(R.drawable.ic_main_timetable)
|
||||
add(Menu.NONE, 4, Menu.NONE, R.string.more_title)
|
||||
@ -256,9 +256,9 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
}
|
||||
fragmentHideStrategy = HIDE
|
||||
rootFragments = listOf(
|
||||
DashboardFragment.newInstance(),
|
||||
GradeFragment.newInstance(),
|
||||
AttendanceFragment.newInstance(),
|
||||
ExamFragment.newInstance(),
|
||||
TimetableFragment.newInstance(),
|
||||
MoreFragment.newInstance()
|
||||
)
|
||||
|
@ -9,15 +9,15 @@ import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.databinding.FragmentMoreBinding
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.modules.conference.ConferenceFragment
|
||||
import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment
|
||||
import io.github.wulkanowy.ui.modules.exam.ExamFragment
|
||||
import io.github.wulkanowy.ui.modules.homework.HomeworkFragment
|
||||
import io.github.wulkanowy.ui.modules.luckynumber.LuckyNumberFragment
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.ui.modules.message.MessageFragment
|
||||
import io.github.wulkanowy.ui.modules.mobiledevice.MobileDeviceFragment
|
||||
import io.github.wulkanowy.ui.modules.note.NoteFragment
|
||||
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersFragment
|
||||
import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment
|
||||
import io.github.wulkanowy.ui.modules.settings.SettingsFragment
|
||||
import io.github.wulkanowy.utils.getCompatDrawable
|
||||
import javax.inject.Inject
|
||||
@ -48,9 +48,6 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
|
||||
override val noteRes: Pair<String, Drawable?>?
|
||||
get() = context?.run { getString(R.string.note_title) to getCompatDrawable(R.drawable.ic_more_note) }
|
||||
|
||||
override val luckyNumberRes: Pair<String, Drawable?>?
|
||||
get() = context?.run { getString(R.string.lucky_number_title) to getCompatDrawable(R.drawable.ic_more_lucky_number) }
|
||||
|
||||
override val conferencesRes: Pair<String, Drawable?>?
|
||||
get() = context?.run { getString(R.string.conferences_title) to getCompatDrawable(R.drawable.ic_more_conferences) }
|
||||
|
||||
@ -66,6 +63,9 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
|
||||
override val settingsRes: Pair<String, Drawable?>?
|
||||
get() = context?.run { getString(R.string.settings_title) to getCompatDrawable(R.drawable.ic_more_settings) }
|
||||
|
||||
override val examRes: Pair<String, Drawable?>?
|
||||
get() = context?.run { getString(R.string.exam_title) to getCompatDrawable(R.drawable.ic_main_exam) }
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding = FragmentMoreBinding.bind(view)
|
||||
@ -104,10 +104,6 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
|
||||
(activity as? MainActivity)?.pushView(NoteFragment.newInstance())
|
||||
}
|
||||
|
||||
override fun openLuckyNumberView() {
|
||||
(activity as? MainActivity)?.pushView(LuckyNumberFragment.newInstance())
|
||||
}
|
||||
|
||||
override fun openSchoolAnnouncementView() {
|
||||
(activity as? MainActivity)?.pushView(SchoolAnnouncementFragment.newInstance())
|
||||
}
|
||||
@ -128,6 +124,10 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
|
||||
(activity as? MainActivity)?.pushView(SettingsFragment.newInstance())
|
||||
}
|
||||
|
||||
override fun openExamView() {
|
||||
(activity as? MainActivity)?.pushView(ExamFragment.newInstance())
|
||||
}
|
||||
|
||||
override fun popView(depth: Int) {
|
||||
(activity as? MainActivity)?.popView(depth)
|
||||
}
|
||||
|
@ -23,9 +23,9 @@ class MorePresenter @Inject constructor(
|
||||
view?.run {
|
||||
when (title) {
|
||||
messagesRes?.first -> openMessagesView()
|
||||
examRes?.first -> openExamView()
|
||||
homeworkRes?.first -> openHomeworkView()
|
||||
noteRes?.first -> openNoteView()
|
||||
luckyNumberRes?.first -> openLuckyNumberView()
|
||||
conferencesRes?.first -> openConferencesView()
|
||||
schoolAnnouncementRes?.first -> openSchoolAnnouncementView()
|
||||
schoolAndTeachersRes?.first -> openSchoolAndTeachersView()
|
||||
@ -45,9 +45,9 @@ class MorePresenter @Inject constructor(
|
||||
view?.run {
|
||||
updateData(listOfNotNull(
|
||||
messagesRes,
|
||||
examRes,
|
||||
homeworkRes,
|
||||
noteRes,
|
||||
luckyNumberRes,
|
||||
conferencesRes,
|
||||
schoolAnnouncementRes,
|
||||
schoolAndTeachersRes,
|
||||
|
@ -11,8 +11,6 @@ interface MoreView : BaseView {
|
||||
|
||||
val noteRes: Pair<String, Drawable?>?
|
||||
|
||||
val luckyNumberRes: Pair<String, Drawable?>?
|
||||
|
||||
val conferencesRes: Pair<String, Drawable?>?
|
||||
|
||||
val schoolAnnouncementRes: Pair<String, Drawable?>?
|
||||
@ -23,6 +21,8 @@ interface MoreView : BaseView {
|
||||
|
||||
val settingsRes: Pair<String, Drawable?>?
|
||||
|
||||
val examRes: Pair<String, Drawable?>?
|
||||
|
||||
fun initView()
|
||||
|
||||
fun updateData(data: List<Pair<String, Drawable?>>)
|
||||
@ -37,8 +37,6 @@ interface MoreView : BaseView {
|
||||
|
||||
fun openNoteView()
|
||||
|
||||
fun openLuckyNumberView()
|
||||
|
||||
fun openSchoolAnnouncementView()
|
||||
|
||||
fun openConferencesView()
|
||||
@ -46,4 +44,6 @@ interface MoreView : BaseView {
|
||||
fun openSchoolAndTeachersView()
|
||||
|
||||
fun openMobileDevicesView()
|
||||
|
||||
fun openExamView()
|
||||
}
|
||||
|
Reference in New Issue
Block a user