From 95e41b5570a0c143ab81e576222a625b77eac90c Mon Sep 17 00:00:00 2001 From: Michael <5672750+mibac138@users.noreply.github.com> Date: Mon, 11 Mar 2024 20:19:24 +0100 Subject: [PATCH] Handle subjects with no attendances in attendance calculator better (#2478) --------- Co-authored-by: Faierbel --- .../java/io/github/wulkanowy/data/Resource.kt | 3 ++ .../repositories/PreferencesRepository.kt | 9 ++++ .../GetAttendanceCalculatorDataUseCase.kt | 3 ++ .../calculator/AttendanceCalculatorAdapter.kt | 54 ++++++++++--------- .../main/res/values/preferences_defaults.xml | 1 + app/src/main/res/values/preferences_keys.xml | 1 + app/src/main/res/values/strings.xml | 2 + .../res/xml/scheme_preferences_appearance.xml | 5 ++ 8 files changed, 53 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/data/Resource.kt b/app/src/main/java/io/github/wulkanowy/data/Resource.kt index c698c42d5..b4982b9a0 100644 --- a/app/src/main/java/io/github/wulkanowy/data/Resource.kt +++ b/app/src/main/java/io/github/wulkanowy/data/Resource.kt @@ -71,6 +71,9 @@ fun Resource.mapData(block: (T) -> U) = when (this) { is Resource.Error -> Resource.Error(this.error) } +/** + * Injects another flow into this flow's resource data. + */ inline fun Flow>.combineWithResourceData( flow: Flow, crossinline block: suspend (T1, T2) -> R diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt index 4735293c0..2bb1538cb 100644 --- a/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt +++ b/app/src/main/java/io/github/wulkanowy/data/repositories/PreferencesRepository.kt @@ -54,6 +54,15 @@ class PreferencesRepository @Inject constructor( context.resources.getString(R.string.pref_default_attendance_calculator_sorting_mode) ).asFlow().map(AttendanceCalculatorSortingMode::getByValue) + /** + * Subjects are empty when they don't have any attendances (total = 0, attendances = 0, absences = 0). + */ + val attendanceCalculatorShowEmptySubjects: Flow + get() = flowSharedPref.getBoolean( + context.getString(R.string.pref_key_attendance_calculator_show_empty_subjects), + context.resources.getBoolean(R.bool.pref_default_attendance_calculator_show_empty_subjects) + ).asFlow() + private val gradeAverageModePref: Preference get() = getObjectFlow( R.string.pref_key_grade_average_mode, diff --git a/app/src/main/java/io/github/wulkanowy/domain/attendance/GetAttendanceCalculatorDataUseCase.kt b/app/src/main/java/io/github/wulkanowy/domain/attendance/GetAttendanceCalculatorDataUseCase.kt index ea68050d5..294abd1be 100644 --- a/app/src/main/java/io/github/wulkanowy/domain/attendance/GetAttendanceCalculatorDataUseCase.kt +++ b/app/src/main/java/io/github/wulkanowy/domain/attendance/GetAttendanceCalculatorDataUseCase.kt @@ -49,6 +49,9 @@ class GetAttendanceCalculatorDataUseCase @Inject constructor( // intermediates that will be visible for barely any time. .debounceIntermediates() } + .combineWithResourceData(preferencesRepository.attendanceCalculatorShowEmptySubjects) { attendanceDataList, showEmptySubjects -> + attendanceDataList.filter { it.total != 0 || showEmptySubjects } + } .combineWithResourceData(preferencesRepository.attendanceCalculatorSortingModeFlow, List::sortedBy) } diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorAdapter.kt index 73c08fd32..4b908bba8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/calculator/AttendanceCalculatorAdapter.kt @@ -1,6 +1,5 @@ package io.github.wulkanowy.ui.modules.attendance.calculator -import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.view.isVisible @@ -19,42 +18,47 @@ class AttendanceCalculatorAdapter @Inject constructor() : override fun getItemCount() = items.size - override fun onCreateViewHolder( - parent: ViewGroup, viewType: Int - ) = ViewHolder( + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder( ItemAttendanceCalculatorHeaderBinding.inflate( LayoutInflater.from(parent.context), parent, false ) ) - @SuppressLint("SetTextI18n") override fun onBindViewHolder(parent: ViewHolder, position: Int) { + val context = parent.binding.root.context + val item = items[position] + with(parent.binding) { - val item = items[position] attendanceCalculatorPercentage.text = "${item.presencePercentage.roundToInt()}" - if (item.lessonBalance > 0) { - attendanceCalculatorSummaryBalance.text = root.context.getString( - R.string.attendance_calculator_summary_balance_positive, - item.lessonBalance - ) - } else if (item.lessonBalance < 0) { - attendanceCalculatorSummaryBalance.text = root.context.getString( - R.string.attendance_calculator_summary_balance_negative, - abs(item.lessonBalance) - ) - } else { - attendanceCalculatorSummaryBalance.text = root.context.getString( - R.string.attendance_calculator_summary_balance_neutral, - ) + attendanceCalculatorSummaryBalance.text = when { + item.lessonBalance > 0 -> { + context.getString( + R.string.attendance_calculator_summary_balance_positive, + item.lessonBalance + ) + } + + item.lessonBalance < 0 -> { + context.getString( + R.string.attendance_calculator_summary_balance_negative, + abs(item.lessonBalance) + ) + } + + else -> context.getString(R.string.attendance_calculator_summary_balance_neutral) } attendanceCalculatorWarning.isVisible = item.lessonBalance < 0 attendanceCalculatorTitle.text = item.subjectName - attendanceCalculatorSummaryValues.text = root.context.getString( - R.string.attendance_calculator_summary_values, - item.presences, - item.total - ) + attendanceCalculatorSummaryValues.text = if (item.total == 0) { + context.getString(R.string.attendance_calculator_summary_values_empty) + } else { + context.getString( + R.string.attendance_calculator_summary_values, + item.presences, + item.total + ) + } } } diff --git a/app/src/main/res/values/preferences_defaults.xml b/app/src/main/res/values/preferences_defaults.xml index 109418893..2981e1845 100644 --- a/app/src/main/res/values/preferences_defaults.xml +++ b/app/src/main/res/values/preferences_defaults.xml @@ -4,6 +4,7 @@ true 50 alphabetic + false only_one_semester false one diff --git a/app/src/main/res/values/preferences_keys.xml b/app/src/main/res/values/preferences_keys.xml index e95c59405..080456ef9 100644 --- a/app/src/main/res/values/preferences_keys.xml +++ b/app/src/main/res/values/preferences_keys.xml @@ -4,6 +4,7 @@ attendance_present attendance_target attendance_calculator_sorting_mode + attendance_calculator_show_empty_subjects app_theme dashboard_tiles grade_color_scheme diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ae6d91408..56cf94f04 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -263,6 +263,7 @@ right on target %1$d under target %1$d/%2$d presences + No attendances recorded Absent for school reasons Excused absence Unexcused absence @@ -721,6 +722,7 @@ Force average calculation by app Show presence Attendance target + Show subjects without any attendances Attendance calculator sorting Theme Grades expanding diff --git a/app/src/main/res/xml/scheme_preferences_appearance.xml b/app/src/main/res/xml/scheme_preferences_appearance.xml index 46a0e6a92..a05d95c04 100644 --- a/app/src/main/res/xml/scheme_preferences_appearance.xml +++ b/app/src/main/res/xml/scheme_preferences_appearance.xml @@ -104,6 +104,11 @@ app:key="@string/pref_key_attendance_calculator_sorting_mode" app:title="@string/pref_view_attendance_calculator_sorting_mode" app:useSimpleSummaryProvider="true" /> +