forked from github/wulkanowy-mirror
Fix OOM in grade statistics (#1192)
This commit is contained in:
parent
9139febbdf
commit
1afa7ecf3c
@ -5,10 +5,9 @@ import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||
import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.pojos.GradeStatisticsItem
|
||||
import io.github.wulkanowy.ui.modules.grade.statistics.ViewType
|
||||
import io.github.wulkanowy.sdk.pojo.GradeStatisticsSubject as SdkGradeStatisticsSubject
|
||||
import io.github.wulkanowy.sdk.pojo.GradeStatisticsSemester as SdkGradeStatisticsSemester
|
||||
import io.github.wulkanowy.sdk.pojo.GradePointsStatistics as SdkGradePointsStatistics
|
||||
import io.github.wulkanowy.sdk.pojo.GradeStatisticsSemester as SdkGradeStatisticsSemester
|
||||
import io.github.wulkanowy.sdk.pojo.GradeStatisticsSubject as SdkGradeStatisticsSubject
|
||||
|
||||
@JvmName("mapToEntitiesSubject")
|
||||
fun List<SdkGradeStatisticsSubject>.mapToEntities(semester: Semester) = map {
|
||||
@ -51,7 +50,7 @@ fun List<SdkGradePointsStatistics>.mapToEntities(semester: Semester) = map {
|
||||
|
||||
fun List<GradePartialStatistics>.mapPartialToStatisticItems() = filterNot { it.classAmounts.isEmpty() }.map {
|
||||
GradeStatisticsItem(
|
||||
type = ViewType.PARTIAL,
|
||||
type = GradeStatisticsItem.DataType.PARTIAL,
|
||||
average = it.classAverage,
|
||||
partial = it,
|
||||
points = null,
|
||||
@ -61,7 +60,7 @@ fun List<GradePartialStatistics>.mapPartialToStatisticItems() = filterNot { it.c
|
||||
|
||||
fun List<GradeSemesterStatistics>.mapSemesterToStatisticItems() = filterNot { it.amounts.isEmpty() }.map {
|
||||
GradeStatisticsItem(
|
||||
type = ViewType.SEMESTER,
|
||||
type = GradeStatisticsItem.DataType.SEMESTER,
|
||||
partial = null,
|
||||
points = null,
|
||||
average = "",
|
||||
@ -71,7 +70,7 @@ fun List<GradeSemesterStatistics>.mapSemesterToStatisticItems() = filterNot { it
|
||||
|
||||
fun List<GradePointsStatistics>.mapPointsToStatisticsItems() = map {
|
||||
GradeStatisticsItem(
|
||||
type = ViewType.POINTS,
|
||||
type = GradeStatisticsItem.DataType.POINTS,
|
||||
partial = null,
|
||||
semester = null,
|
||||
average = "",
|
||||
|
@ -3,11 +3,10 @@ package io.github.wulkanowy.data.pojos
|
||||
import io.github.wulkanowy.data.db.entities.GradePartialStatistics
|
||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||
import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
|
||||
import io.github.wulkanowy.ui.modules.grade.statistics.ViewType
|
||||
|
||||
data class GradeStatisticsItem(
|
||||
|
||||
val type: ViewType,
|
||||
val type: DataType,
|
||||
|
||||
val average: String,
|
||||
|
||||
@ -16,4 +15,11 @@ data class GradeStatisticsItem(
|
||||
val semester: GradeSemesterStatistics?,
|
||||
|
||||
val points: GradePointsStatistics?
|
||||
)
|
||||
|
||||
) {
|
||||
enum class DataType {
|
||||
SEMESTER,
|
||||
PARTIAL,
|
||||
POINTS,
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ class GradeFragment : BaseFragment<FragmentGradeBinding>(R.layout.fragment_grade
|
||||
|
||||
override val titleStringId get() = R.string.grade_title
|
||||
|
||||
override var subtitleString = " "
|
||||
override var subtitleString = ""
|
||||
|
||||
override val currentPageIndex get() = binding.gradeViewPager.currentItem
|
||||
|
||||
|
@ -22,6 +22,7 @@ import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||
import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
|
||||
import io.github.wulkanowy.data.pojos.GradeStatisticsItem
|
||||
import io.github.wulkanowy.databinding.ItemGradeStatisticsBarBinding
|
||||
import io.github.wulkanowy.databinding.ItemGradeStatisticsHeaderBinding
|
||||
import io.github.wulkanowy.databinding.ItemGradeStatisticsPieBinding
|
||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import javax.inject.Inject
|
||||
@ -29,12 +30,16 @@ import javax.inject.Inject
|
||||
class GradeStatisticsAdapter @Inject constructor() :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
var currentDataType = GradeStatisticsItem.DataType.PARTIAL
|
||||
|
||||
var items = emptyList<GradeStatisticsItem>()
|
||||
|
||||
var theme: String = "vulcan"
|
||||
|
||||
var showAllSubjectsOnList: Boolean = false
|
||||
|
||||
var onDataTypeChangeListener: () -> Unit = {}
|
||||
|
||||
private val vulcanGradeColors = listOf(
|
||||
6 to R.color.grade_vulcan_six,
|
||||
5 to R.color.grade_vulcan_five,
|
||||
@ -62,37 +67,90 @@ class GradeStatisticsAdapter @Inject constructor() :
|
||||
"6, 6-", "5, 5-, 5+", "4, 4-, 4+", "3, 3-, 3+", "2, 2-, 2+", "1, 1+"
|
||||
)
|
||||
|
||||
override fun getItemCount() = if (showAllSubjectsOnList) items.size else (if (items.isEmpty()) 0 else 1)
|
||||
override fun getItemCount() =
|
||||
(if (showAllSubjectsOnList) items.size else (if (items.isEmpty()) 0 else 1)) + 1
|
||||
|
||||
override fun getItemViewType(position: Int) = items[position].type.id
|
||||
override fun getItemViewType(position: Int) =
|
||||
if (position == 0) {
|
||||
ViewType.HEADER.id
|
||||
} else {
|
||||
when (items[position - 1].type) {
|
||||
GradeStatisticsItem.DataType.PARTIAL -> ViewType.PARTIAL.id
|
||||
GradeStatisticsItem.DataType.POINTS -> ViewType.POINTS.id
|
||||
GradeStatisticsItem.DataType.SEMESTER -> ViewType.SEMESTER.id
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return when (viewType) {
|
||||
ViewType.PARTIAL.id -> PartialViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false))
|
||||
ViewType.SEMESTER.id -> SemesterViewHolder(ItemGradeStatisticsPieBinding.inflate(inflater, parent, false))
|
||||
ViewType.POINTS.id -> PointsViewHolder(ItemGradeStatisticsBarBinding.inflate(inflater, parent, false))
|
||||
ViewType.PARTIAL.id -> PartialViewHolder(
|
||||
ItemGradeStatisticsPieBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
ViewType.SEMESTER.id -> SemesterViewHolder(
|
||||
ItemGradeStatisticsPieBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
ViewType.POINTS.id -> PointsViewHolder(
|
||||
ItemGradeStatisticsBarBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
ViewType.HEADER.id -> HeaderViewHolder(
|
||||
ItemGradeStatisticsHeaderBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val index = position - 1
|
||||
|
||||
when (holder) {
|
||||
is PartialViewHolder -> bindPartialChart(holder.binding, items[position].partial!!)
|
||||
is SemesterViewHolder -> bindSemesterChart(holder.binding, items[position].semester!!)
|
||||
is PointsViewHolder -> bindBarChart(holder.binding, items[position].points!!)
|
||||
is PartialViewHolder -> bindPartialChart(holder.binding, items[index].partial!!)
|
||||
is SemesterViewHolder -> bindSemesterChart(holder.binding, items[index].semester!!)
|
||||
is PointsViewHolder -> bindBarChart(holder.binding, items[index].points!!)
|
||||
is HeaderViewHolder -> bindHeader(holder.binding)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindPartialChart(binding: ItemGradeStatisticsPieBinding, partials: GradePartialStatistics) {
|
||||
private fun bindHeader(binding: ItemGradeStatisticsHeaderBinding) {
|
||||
binding.gradeStatisticsTypeSwitch.check(
|
||||
when (currentDataType) {
|
||||
GradeStatisticsItem.DataType.PARTIAL -> R.id.gradeStatisticsTypePartial
|
||||
GradeStatisticsItem.DataType.SEMESTER -> R.id.gradeStatisticsTypeSemester
|
||||
GradeStatisticsItem.DataType.POINTS -> R.id.gradeStatisticsTypePoints
|
||||
}
|
||||
)
|
||||
|
||||
binding.gradeStatisticsTypeSwitch.setOnCheckedChangeListener { _, checkedId ->
|
||||
currentDataType = when (checkedId) {
|
||||
R.id.gradeStatisticsTypePartial -> GradeStatisticsItem.DataType.PARTIAL
|
||||
R.id.gradeStatisticsTypeSemester -> GradeStatisticsItem.DataType.SEMESTER
|
||||
R.id.gradeStatisticsTypePoints -> GradeStatisticsItem.DataType.POINTS
|
||||
else -> GradeStatisticsItem.DataType.PARTIAL
|
||||
}
|
||||
onDataTypeChangeListener()
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindPartialChart(
|
||||
binding: ItemGradeStatisticsPieBinding,
|
||||
partials: GradePartialStatistics
|
||||
) {
|
||||
bindPieChart(binding, partials.subject, partials.classAverage, partials.classAmounts)
|
||||
}
|
||||
|
||||
private fun bindSemesterChart(binding: ItemGradeStatisticsPieBinding, semester: GradeSemesterStatistics) {
|
||||
private fun bindSemesterChart(
|
||||
binding: ItemGradeStatisticsPieBinding,
|
||||
semester: GradeSemesterStatistics
|
||||
) {
|
||||
bindPieChart(binding, semester.subject, semester.average, semester.amounts)
|
||||
}
|
||||
|
||||
private fun bindPieChart(binding: ItemGradeStatisticsPieBinding, subject: String, average: String, amounts: List<Int>) {
|
||||
private fun bindPieChart(
|
||||
binding: ItemGradeStatisticsPieBinding,
|
||||
subject: String,
|
||||
average: String,
|
||||
amounts: List<Int>
|
||||
) {
|
||||
with(binding.gradeStatisticsPieTitle) {
|
||||
text = subject
|
||||
visibility = if (items.size == 1 || !showAllSubjectsOnList) GONE else VISIBLE
|
||||
@ -114,7 +172,8 @@ class GradeStatisticsAdapter @Inject constructor() :
|
||||
valueTextSize = 12f
|
||||
sliceSpace = 1f
|
||||
valueTextColor = Color.WHITE
|
||||
val grades = amounts.mapIndexed { grade, amount -> (grade + 1) to amount }.filterNot { it.second == 0 }
|
||||
val grades = amounts.mapIndexed { grade, amount -> (grade + 1) to amount }
|
||||
.filterNot { it.second == 0 }
|
||||
setColors(grades.reversed().map { (grade, _) ->
|
||||
gradeColors.single { color -> color.first == grade }.second
|
||||
}.toIntArray(), binding.root.context)
|
||||
@ -126,7 +185,11 @@ class GradeStatisticsAdapter @Inject constructor() :
|
||||
data = PieData(dataset).apply {
|
||||
setValueFormatter(object : ValueFormatter() {
|
||||
override fun getPieLabel(value: Float, pieEntry: PieEntry): String {
|
||||
return resources.getQuantityString(R.plurals.grade_number_item, value.toInt(), value.toInt())
|
||||
return resources.getQuantityString(
|
||||
R.plurals.grade_number_item,
|
||||
value.toInt(),
|
||||
value.toInt()
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -143,11 +206,14 @@ class GradeStatisticsAdapter @Inject constructor() :
|
||||
|
||||
val numberOfGradesString = amounts.fold(0) { acc, it -> acc + it }
|
||||
.let { resources.getQuantityString(R.plurals.grade_number_item, it, it) }
|
||||
val averageString = binding.root.context.getString(R.string.grade_statistics_average, average)
|
||||
val averageString =
|
||||
binding.root.context.getString(R.string.grade_statistics_average, average)
|
||||
|
||||
minAngleForSlices = 25f
|
||||
description.isEnabled = false
|
||||
centerText = numberOfGradesString + ("\n\n" + averageString).takeIf { average.isNotBlank() }.orEmpty()
|
||||
centerText =
|
||||
numberOfGradesString + ("\n\n" + averageString).takeIf { average.isNotBlank() }
|
||||
.orEmpty()
|
||||
|
||||
setHoleColor(context.getThemeAttrColor(android.R.attr.windowBackground))
|
||||
setCenterTextColor(context.getThemeAttrColor(android.R.attr.textColorPrimary))
|
||||
@ -155,16 +221,21 @@ class GradeStatisticsAdapter @Inject constructor() :
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindBarChart(binding: ItemGradeStatisticsBarBinding, points: GradePointsStatistics) {
|
||||
private fun bindBarChart(
|
||||
binding: ItemGradeStatisticsBarBinding,
|
||||
points: GradePointsStatistics
|
||||
) {
|
||||
with(binding.gradeStatisticsBarTitle) {
|
||||
text = points.subject
|
||||
visibility = if (items.size == 1) GONE else VISIBLE
|
||||
}
|
||||
|
||||
val dataset = BarDataSet(listOf(
|
||||
BarEntry(1f, points.others.toFloat()),
|
||||
BarEntry(2f, points.student.toFloat())
|
||||
), binding.root.context.getString(R.string.grade_statistics_legend))
|
||||
val dataset = BarDataSet(
|
||||
listOf(
|
||||
BarEntry(1f, points.others.toFloat()),
|
||||
BarEntry(2f, points.student.toFloat())
|
||||
), binding.root.context.getString(R.string.grade_statistics_legend)
|
||||
)
|
||||
|
||||
with(dataset) {
|
||||
valueTextSize = 12f
|
||||
@ -189,7 +260,8 @@ class GradeStatisticsAdapter @Inject constructor() :
|
||||
form = Legend.LegendForm.SQUARE
|
||||
},
|
||||
LegendEntry().apply {
|
||||
label = binding.root.context.getString(R.string.grade_statistics_average_student)
|
||||
label =
|
||||
binding.root.context.getString(R.string.grade_statistics_average_student)
|
||||
formColor = gradePointsColors[1]
|
||||
form = Legend.LegendForm.SQUARE
|
||||
}
|
||||
@ -226,4 +298,7 @@ class GradeStatisticsAdapter @Inject constructor() :
|
||||
|
||||
private class PointsViewHolder(val binding: ItemGradeStatisticsBarBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
private class HeaderViewHolder(val binding: ItemGradeStatisticsHeaderBinding) :
|
||||
RecyclerView.ViewHolder(binding.root)
|
||||
}
|
||||
|
@ -38,27 +38,28 @@ class GradeStatisticsFragment :
|
||||
|
||||
override val isViewEmpty get() = statisticsAdapter.items.isEmpty()
|
||||
|
||||
override val currentType
|
||||
get() = when (binding.gradeStatisticsTypeSwitch.checkedRadioButtonId) {
|
||||
R.id.gradeStatisticsTypeSemester -> ViewType.SEMESTER
|
||||
R.id.gradeStatisticsTypePartial -> ViewType.PARTIAL
|
||||
else -> ViewType.POINTS
|
||||
}
|
||||
override val currentType get() = statisticsAdapter.currentDataType
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding = FragmentGradeStatisticsBinding.bind(view)
|
||||
messageContainer = binding.gradeStatisticsSwipe
|
||||
presenter.onAttachView(this, savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? ViewType)
|
||||
presenter.onAttachView(
|
||||
this,
|
||||
savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? GradeStatisticsItem.DataType
|
||||
)
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
statisticsAdapter.onDataTypeChangeListener = presenter::onTypeChange
|
||||
|
||||
with(binding.gradeStatisticsRecycler) {
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
adapter = statisticsAdapter
|
||||
}
|
||||
|
||||
subjectsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf())
|
||||
subjectsAdapter =
|
||||
ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, mutableListOf())
|
||||
subjectsAdapter.setDropDownViewResource(R.layout.item_attendance_summary_subject)
|
||||
|
||||
with(binding.gradeStatisticsSubjects) {
|
||||
@ -71,7 +72,9 @@ class GradeStatisticsFragment :
|
||||
|
||||
gradeStatisticsSwipe.setOnRefreshListener(presenter::onSwipeRefresh)
|
||||
gradeStatisticsSwipe.setColorSchemeColors(requireContext().getThemeAttrColor(R.attr.colorPrimary))
|
||||
gradeStatisticsSwipe.setProgressBackgroundColorSchemeColor(requireContext().getThemeAttrColor(R.attr.colorSwipeRefresh))
|
||||
gradeStatisticsSwipe.setProgressBackgroundColorSchemeColor(
|
||||
requireContext().getThemeAttrColor(R.attr.colorSwipeRefresh)
|
||||
)
|
||||
gradeStatisticsErrorRetry.setOnClickListener { presenter.onRetry() }
|
||||
gradeStatisticsErrorDetails.setOnClickListener { presenter.onDetailsClick() }
|
||||
}
|
||||
@ -85,11 +88,15 @@ class GradeStatisticsFragment :
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateData(items: List<GradeStatisticsItem>, theme: String, showAllSubjectsOnStatisticsList: Boolean) {
|
||||
override fun updateData(
|
||||
newItems: List<GradeStatisticsItem>,
|
||||
newTheme: String,
|
||||
showAllSubjectsOnStatisticsList: Boolean
|
||||
) {
|
||||
with(statisticsAdapter) {
|
||||
this.showAllSubjectsOnList = showAllSubjectsOnStatisticsList
|
||||
this.theme = theme
|
||||
this.items = items
|
||||
showAllSubjectsOnList = showAllSubjectsOnStatisticsList
|
||||
theme = newTheme
|
||||
items = newItems
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
@ -103,11 +110,7 @@ class GradeStatisticsFragment :
|
||||
}
|
||||
|
||||
override fun resetView() {
|
||||
binding.gradeStatisticsScroll.scrollTo(0, 0)
|
||||
}
|
||||
|
||||
override fun showContent(show: Boolean) {
|
||||
binding.gradeStatisticsRecycler.visibility = if (show) View.VISIBLE else View.GONE
|
||||
binding.gradeStatisticsRecycler.scrollToPosition(0)
|
||||
}
|
||||
|
||||
override fun showEmpty(show: Boolean) {
|
||||
@ -154,11 +157,6 @@ class GradeStatisticsFragment :
|
||||
(parentFragment as? GradeFragment)?.onChildRefresh()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.gradeStatisticsTypeSwitch.setOnCheckedChangeListener { _, _ -> presenter.onTypeChange() }
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putSerializable(SAVED_CHART_TYPE, presenter.currentType)
|
||||
|
@ -35,12 +35,12 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
|
||||
private lateinit var lastError: Throwable
|
||||
|
||||
var currentType: ViewType = ViewType.PARTIAL
|
||||
var currentType: GradeStatisticsItem.DataType = GradeStatisticsItem.DataType.PARTIAL
|
||||
private set
|
||||
|
||||
fun onAttachView(view: GradeStatisticsView, type: ViewType?) {
|
||||
fun onAttachView(view: GradeStatisticsView, type: GradeStatisticsItem.DataType?) {
|
||||
super.onAttachView(view)
|
||||
currentType = type ?: ViewType.PARTIAL
|
||||
currentType = type ?: GradeStatisticsItem.DataType.PARTIAL
|
||||
view.initView()
|
||||
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||
}
|
||||
@ -59,11 +59,11 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onParentViewChangeSemester() {
|
||||
clearDataInView()
|
||||
view?.run {
|
||||
showProgress(true)
|
||||
enableSwipe(false)
|
||||
showRefresh(false)
|
||||
showContent(false)
|
||||
showErrorView(false)
|
||||
showEmpty(false)
|
||||
clearView()
|
||||
@ -90,8 +90,8 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
|
||||
fun onSubjectSelected(name: String?) {
|
||||
Timber.i("Select grade stats subject $name")
|
||||
clearDataInView()
|
||||
view?.run {
|
||||
showContent(false)
|
||||
showProgress(true)
|
||||
enableSwipe(false)
|
||||
showEmpty(false)
|
||||
@ -104,11 +104,11 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onTypeChange() {
|
||||
val type = view?.currentType ?: ViewType.POINTS
|
||||
val type = view?.currentType ?: GradeStatisticsItem.DataType.POINTS
|
||||
Timber.i("Select grade stats semester: $type")
|
||||
cancelJobs("load")
|
||||
clearDataInView()
|
||||
view?.run {
|
||||
showContent(false)
|
||||
showProgress(true)
|
||||
enableSwipe(false)
|
||||
showEmpty(false)
|
||||
@ -143,10 +143,16 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
}.launch("subjects")
|
||||
}
|
||||
|
||||
private fun loadDataByType(semesterId: Int, subjectName: String, type: ViewType, forceRefresh: Boolean = false) {
|
||||
private fun loadDataByType(
|
||||
semesterId: Int,
|
||||
subjectName: String,
|
||||
type: GradeStatisticsItem.DataType,
|
||||
forceRefresh: Boolean = false
|
||||
) {
|
||||
Timber.i("Loading grade stats data started")
|
||||
|
||||
currentSubjectName = if (preferencesRepository.showAllSubjectsOnStatisticsList) "Wszystkie" else subjectName
|
||||
currentSubjectName =
|
||||
if (preferencesRepository.showAllSubjectsOnStatisticsList) "Wszystkie" else subjectName
|
||||
currentType = type
|
||||
|
||||
flowWithResourceIn {
|
||||
@ -156,9 +162,30 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
|
||||
with(gradeStatisticsRepository) {
|
||||
when (type) {
|
||||
ViewType.PARTIAL -> getGradesPartialStatistics(student, semester, currentSubjectName, forceRefresh)
|
||||
ViewType.SEMESTER -> getGradesSemesterStatistics(student, semester, currentSubjectName, forceRefresh)
|
||||
ViewType.POINTS -> getGradesPointsStatistics(student, semester, currentSubjectName, forceRefresh)
|
||||
GradeStatisticsItem.DataType.PARTIAL -> {
|
||||
getGradesPartialStatistics(
|
||||
student = student,
|
||||
semester = semester,
|
||||
subjectName = currentSubjectName,
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}
|
||||
GradeStatisticsItem.DataType.SEMESTER -> {
|
||||
getGradesSemesterStatistics(
|
||||
student = student,
|
||||
semester = semester,
|
||||
subjectName = currentSubjectName,
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}
|
||||
GradeStatisticsItem.DataType.POINTS -> {
|
||||
getGradesPointsStatistics(
|
||||
student = student,
|
||||
semester = semester,
|
||||
subjectName = currentSubjectName,
|
||||
forceRefresh = forceRefresh
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.onEach {
|
||||
@ -168,12 +195,15 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
if (!isNoContent) {
|
||||
view?.run {
|
||||
showEmpty(isNoContent)
|
||||
showContent(!isNoContent)
|
||||
showErrorView(false)
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
updateData(it.data!!, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList)
|
||||
updateData(
|
||||
if (isNoContent) emptyList() else it.data!!,
|
||||
preferencesRepository.gradeColorTheme,
|
||||
preferencesRepository.showAllSubjectsOnStatisticsList
|
||||
)
|
||||
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
|
||||
}
|
||||
}
|
||||
@ -183,9 +213,12 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
view?.run {
|
||||
val isNoContent = checkIsNoContent(it.data!!, type)
|
||||
showEmpty(isNoContent)
|
||||
showContent(!isNoContent)
|
||||
showErrorView(false)
|
||||
updateData(it.data, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList)
|
||||
updateData(
|
||||
if (isNoContent) emptyList() else it.data,
|
||||
preferencesRepository.gradeColorTheme,
|
||||
preferencesRepository.showAllSubjectsOnStatisticsList
|
||||
)
|
||||
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
|
||||
}
|
||||
analytics.logEvent(
|
||||
@ -209,16 +242,31 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
}.launch("load")
|
||||
}
|
||||
|
||||
private fun checkIsNoContent(items: List<GradeStatisticsItem>, type: ViewType): Boolean {
|
||||
private fun checkIsNoContent(
|
||||
items: List<GradeStatisticsItem>,
|
||||
type: GradeStatisticsItem.DataType
|
||||
): Boolean {
|
||||
return items.isEmpty() || when (type) {
|
||||
ViewType.SEMESTER -> items.firstOrNull()?.semester?.amounts.orEmpty().sum() == 0
|
||||
ViewType.PARTIAL -> items.firstOrNull()?.partial?.classAmounts.orEmpty().sum() == 0
|
||||
ViewType.POINTS -> items.firstOrNull()?.points?.let { points ->
|
||||
points.student == .0 && points.others == .0
|
||||
} ?: false
|
||||
GradeStatisticsItem.DataType.SEMESTER -> {
|
||||
items.firstOrNull()?.semester?.amounts.orEmpty().sum() == 0
|
||||
}
|
||||
GradeStatisticsItem.DataType.PARTIAL -> {
|
||||
items.firstOrNull()?.partial?.classAmounts.orEmpty().sum() == 0
|
||||
}
|
||||
GradeStatisticsItem.DataType.POINTS -> {
|
||||
items.firstOrNull()?.points?.let { points -> points.student == .0 && points.others == .0 } ?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearDataInView() {
|
||||
view?.updateData(
|
||||
emptyList(),
|
||||
preferencesRepository.gradeColorTheme,
|
||||
preferencesRepository.showAllSubjectsOnStatisticsList
|
||||
)
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
view?.run {
|
||||
if (isViewEmpty) {
|
||||
|
@ -7,13 +7,17 @@ interface GradeStatisticsView : BaseView {
|
||||
|
||||
val isViewEmpty: Boolean
|
||||
|
||||
val currentType: ViewType
|
||||
val currentType: GradeStatisticsItem.DataType
|
||||
|
||||
fun initView()
|
||||
|
||||
fun updateSubjects(data: ArrayList<String>)
|
||||
|
||||
fun updateData(items: List<GradeStatisticsItem>, theme: String, showAllSubjectsOnStatisticsList: Boolean)
|
||||
fun updateData(
|
||||
newItems: List<GradeStatisticsItem>,
|
||||
newTheme: String,
|
||||
showAllSubjectsOnStatisticsList: Boolean
|
||||
)
|
||||
|
||||
fun showSubjects(show: Boolean)
|
||||
|
||||
@ -25,8 +29,6 @@ interface GradeStatisticsView : BaseView {
|
||||
|
||||
fun resetView()
|
||||
|
||||
fun showContent(show: Boolean)
|
||||
|
||||
fun showEmpty(show: Boolean)
|
||||
|
||||
fun showErrorView(show: Boolean)
|
||||
|
@ -3,5 +3,6 @@ package io.github.wulkanowy.ui.modules.grade.statistics
|
||||
enum class ViewType(val id: Int) {
|
||||
SEMESTER(1),
|
||||
PARTIAL(2),
|
||||
POINTS(3)
|
||||
POINTS(3),
|
||||
HEADER(4)
|
||||
}
|
||||
|
@ -3,8 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.modules.grade.statistics.GradeStatisticsFragment">
|
||||
android:orientation="vertical">
|
||||
|
||||
<io.github.wulkanowy.ui.widgets.MaterialLinearLayout
|
||||
android:id="@+id/gradeStatisticsSubjectsContainer"
|
||||
@ -12,7 +11,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:windowBackground"
|
||||
android:padding="5dp"
|
||||
android:visibility="gone"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="UnusedAttribute"
|
||||
tools:listitem="@layout/item_attendance_summary"
|
||||
tools:visibility="visible">
|
||||
@ -34,153 +34,101 @@
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/gradeStatisticsSwipe"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/gradeStatisticsScroll"
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/gradeStatisticsProgress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/gradeStatisticsRecycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/item_grade_statistics_pie" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/gradeStatisticsEmpty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="invisible"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<HorizontalScrollView
|
||||
<ImageView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
app:srcCompat="@drawable/ic_main_grade"
|
||||
app:tint="?colorOnBackground"
|
||||
tools:ignore="contentDescription" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center">
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/gradeStatisticsTypeSwitch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingEnd="16dp">
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/gradeStatisticsTypePartial"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:tag="partial"
|
||||
android:text="@string/grade_statistics_partial" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/gradeStatisticsTypeSemester"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:tag="annual"
|
||||
android:text="@string/grade_statistics_semester" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/gradeStatisticsTypePoints"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:tag="points"
|
||||
android:text="@string/grade_statistics_points" />
|
||||
</RadioGroup>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/gradeStatisticsRecycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/item_grade_statistics_pie" />
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/gradeStatisticsProgress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/gradeStatisticsEmpty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="invisible"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
app:srcCompat="@drawable/ic_main_grade"
|
||||
app:tint="?colorOnBackground"
|
||||
tools:ignore="contentDescription" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/grade_no_items"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/gradeStatisticsError"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="invisible"
|
||||
tools:ignore="UseCompoundDrawables"
|
||||
tools:visibility="invisible">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
app:srcCompat="@drawable/ic_error"
|
||||
app:tint="?colorOnBackground"
|
||||
tools:ignore="contentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/gradeStatisticsErrorMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="@string/error_unknown"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/gradeStatisticsErrorDetails"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:text="@string/all_details" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/gradeStatisticsErrorRetry"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/all_retry" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/grade_no_items"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/gradeStatisticsError"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="invisible"
|
||||
tools:ignore="UseCompoundDrawables"
|
||||
tools:visibility="invisible">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
app:srcCompat="@drawable/ic_error"
|
||||
app:tint="?colorOnBackground"
|
||||
tools:ignore="contentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/gradeStatisticsErrorMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center"
|
||||
android:padding="8dp"
|
||||
android:text="@string/error_unknown"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/gradeStatisticsErrorDetails"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:text="@string/all_details" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/gradeStatisticsErrorRetry"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/all_retry" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
</LinearLayout>
|
||||
|
47
app/src/main/res/layout/item_grade_statistics_header.xml
Normal file
47
app/src/main/res/layout/item_grade_statistics_header.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/gradeStatisticsTypeSwitch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingEnd="16dp">
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/gradeStatisticsTypePartial"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:tag="partial"
|
||||
android:text="@string/grade_statistics_partial" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/gradeStatisticsTypeSemester"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:tag="annual"
|
||||
android:text="@string/grade_statistics_semester" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/gradeStatisticsTypePoints"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:tag="points"
|
||||
android:text="@string/grade_statistics_points" />
|
||||
</RadioGroup>
|
||||
</HorizontalScrollView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
x
Reference in New Issue
Block a user