diff --git a/README.en.md b/README.en.md index 0238bb75..e7151d7e 100644 --- a/README.en.md +++ b/README.en.md @@ -6,7 +6,7 @@ * hide bad grades (1, 1+, 2, 2+, 2-) * hide bad attendance (everything except present/excused attendance) * hide comments -* fake attendance (always 100%) +* fake attendance To get to the hidden panel, go to the "More" tab and then long-press the "Settings" tile. 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 550eaa10..7b356244 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 @@ -2,6 +2,8 @@ package io.github.wulkanowy.data.repositories import android.content.Context import android.content.SharedPreferences +import android.os.Build +import androidx.annotation.RequiresApi import androidx.annotation.StringRes import androidx.core.content.edit import com.fredporciuncula.flow.preferences.FlowSharedPreferences @@ -283,6 +285,18 @@ class PreferencesRepository @Inject constructor( selectedHiddenSettingTilesPreference.set(filteredValue) } + var attendancePercentage: Float? + get() { + val value = attendancePercentagePreference.get() + return if (value == context.resources.getInteger(R.integer.pref_default_attendance_percentage).toFloat()) { + null + } else { + value + } + } + set(value) = value?.let { attendancePercentagePreference.set(it) } + ?: attendancePercentagePreference.delete() + private val selectedDashboardTilesPreference: Preference> get() { val defaultSet = @@ -301,6 +315,12 @@ class PreferencesRepository @Inject constructor( return flowSharedPref.getStringSet(prefKey, defaultSet) } + private val attendancePercentagePreference: Preference + get() = flowSharedPref.getFloat( + context.getString(R.string.pref_key_attendance_percentage), + context.resources.getInteger(R.integer.pref_default_attendance_percentage).toFloat() + ) + var dismissedAdminMessageIds: List get() = sharedPref.getStringSet(PREF_KEY_ADMIN_DISMISSED_MESSAGE_IDS, emptySet()) .orEmpty() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryAdapter.kt index 70c97740..ae0a189f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryAdapter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/attendance/summary/AttendanceSummaryAdapter.kt @@ -8,7 +8,6 @@ import io.github.wulkanowy.data.db.entities.AttendanceSummary import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.databinding.ItemAttendanceSummaryBinding import io.github.wulkanowy.databinding.ScrollableHeaderAttendanceSummaryBinding -import io.github.wulkanowy.ui.modules.dashboard.DashboardItem import io.github.wulkanowy.utils.calculatePercentage import io.github.wulkanowy.utils.getFormattedName import java.time.Month @@ -20,9 +19,7 @@ class AttendanceSummaryAdapter @Inject constructor( ) : RecyclerView.Adapter() { - private val fake = preferencesRepository - .selectedHiddenSettingTiles - .contains(DashboardItem.HiddenSettingTile.ATTENDANCE) + private val attendancePercentage = preferencesRepository.attendancePercentage private enum class ViewType(val id: Int) { HEADER(1), @@ -56,7 +53,10 @@ class AttendanceSummaryAdapter @Inject constructor( } private fun bindHeaderViewHolder(binding: ScrollableHeaderAttendanceSummaryBinding) { - binding.attendanceSummaryScrollableHeaderPercentage.text = formatPercentage(items.calculatePercentage(fake)) + binding.attendanceSummaryScrollableHeaderPercentage.text = formatPercentage( + attendancePercentage?.toDouble() ?: + items.calculatePercentage() + ) } private fun bindItemViewHolder(binding: ItemAttendanceSummaryBinding, position: Int) { @@ -68,8 +68,8 @@ class AttendanceSummaryAdapter @Inject constructor( else -> item.month.getFormattedName() } attendanceSummaryPercentage.text = when (position) { - -1 -> formatPercentage(items.calculatePercentage(fake)) - else -> formatPercentage(item.calculatePercentage(fake)) + -1 -> formatPercentage(attendancePercentage?.toDouble() ?: item.calculatePercentage()) + else -> formatPercentage(attendancePercentage?.toDouble() ?: item.calculatePercentage()) } attendanceSummaryPresent.text = item.presence.toString() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt index bda74a4b..86e62501 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/dashboard/DashboardPresenter.kt @@ -284,9 +284,7 @@ class DashboardPresenter @Inject constructor( private fun loadHorizontalGroup(student: Student, forceRefresh: Boolean) { flow { - val fake = preferencesRepository - .selectedHiddenSettingTiles - .contains(DashboardItem.HiddenSettingTile.ATTENDANCE) + val attendancePercentage = preferencesRepository.attendancePercentage val selectedTiles = selectedDashboardTiles val flowSuccess = flowOf(Resource.Success(null)) @@ -339,7 +337,7 @@ class DashboardPresenter @Inject constructor( } else null }, attendancePercentage = DashboardItem.HorizontalGroup.Cell( - data = attendanceResource.dataOrNull?.calculatePercentage(fake), + data = attendancePercentage?.toDouble() ?: attendanceResource.dataOrNull?.calculatePercentage(), error = attendanceResource.errorOrNull != null, isLoading = attendanceResource is Resource.Loading, ), diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt index 33e75bee..dfedb7c0 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MoreFragment.kt @@ -1,12 +1,17 @@ package io.github.wulkanowy.ui.modules.more import android.os.Bundle +import android.text.InputFilter +import android.text.InputType +import android.text.Spanned import android.view.View +import android.widget.EditText import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import io.github.wulkanowy.R +import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.databinding.FragmentMoreBinding import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.modules.Destination @@ -17,6 +22,24 @@ import io.github.wulkanowy.ui.modules.message.MessageFragment import timber.log.Timber import javax.inject.Inject +private class AttendancePercentageFilter : InputFilter { + override fun filter( + source: CharSequence?, + start: Int, + end: Int, + dest: Spanned?, + dstart: Int, + dend: Int + ): CharSequence? { + val input = dest.toString() + source.toString() + val floatRepresentation = input.toFloatOrNull() + + if (floatRepresentation != null && floatRepresentation in 0.0..100.0) return null + + return "" + } +} + @AndroidEntryPoint class MoreFragment : BaseFragment(R.layout.fragment_more), MoreView, MainView.TitledView, MainView.MainChildView { @@ -27,6 +50,9 @@ class MoreFragment : BaseFragment(R.layout.fragment_more), @Inject lateinit var moreAdapter: MoreAdapter + @Inject + lateinit var preferencesRepository: PreferencesRepository + companion object { fun newInstance() = MoreFragment() } @@ -80,19 +106,44 @@ class MoreFragment : BaseFragment(R.layout.fragment_more), } override fun showHiddenSettings(data: List) { + val badGradesEntries = requireContext().resources.getStringArray(R.array.hidden_settings_bad_grades_entries) val entries = requireContext().resources.getStringArray(R.array.hidden_settings_entries) val values = requireContext().resources.getStringArray(R.array.hidden_settings_values) val selectedItemsState = values.map { value -> data.any { it.name == value } } + val attendancePercentage = preferencesRepository.attendancePercentage + val badGrades = preferencesRepository.badGrades + + val input = EditText(requireContext()).apply { + setPadding(40, 20, 40, 20) + hint = requireContext().getString(R.string.pref_hidden_settings_hint) + filters = arrayOf(AttendancePercentageFilter()) + inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL + } + + // enable only if attendance modifier is enabled + val attendanceModifierEnabled = data.any { it == DashboardItem.HiddenSettingTile.ATTENDANCE } + input.isEnabled = attendanceModifierEnabled + + if (attendancePercentage != null) input.setText(attendancePercentage.toString()) + MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.pref_hidden_settings_title) - .setMultiChoiceItems(entries, selectedItemsState.toBooleanArray()) { _, _, _ -> } + .setMultiChoiceItems(entries, selectedItemsState.toBooleanArray()) { dialog, index, _ -> + // if attendance modifier is enabled, enable text input + if (index == values.indexOf(DashboardItem.HiddenSettingTile.ATTENDANCE.name)) + input.isEnabled = (dialog as AlertDialog).listView.checkedItemPositions[index] + } + .setView(input) .setPositiveButton(android.R.string.ok) { dialog, _ -> val selectedState = (dialog as AlertDialog).listView.checkedItemPositions val selectedValues = values.filterIndexed { index, _ -> selectedState[index] } + val inputAttendancePercentage = selectedValues + .find { it == DashboardItem.HiddenSettingTile.ATTENDANCE.name } + ?.let { input.text.toString().toFloatOrNull() } Timber.i("Selected hidden settings: $selectedValues") - presenter.onHiddenSettingsSelected(selectedValues) + presenter.onHiddenSettingsSelected(selectedValues, inputAttendancePercentage) } .setNegativeButton(android.R.string.cancel) { _, _ -> } .show() diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt index c81d4a1b..dd586d41 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/modules/more/MorePresenter.kt @@ -45,11 +45,13 @@ class MorePresenter @Inject constructor( } } - fun onHiddenSettingsSelected(selectedItems: List) { + fun onHiddenSettingsSelected(selectedItems: List, attendance: Float?) { preferencesRepository.selectedHiddenSettingTiles = selectedItems.map { DashboardItem.HiddenSettingTile.valueOf(it) } + preferencesRepository.attendancePercentage = attendance + view?.restartApp() } diff --git a/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt index d20f991d..397c9595 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt +++ b/app/src/main/java/io/github/wulkanowy/utils/AttendanceExtension.kt @@ -19,18 +19,10 @@ private inline val AttendanceSummary.allAbsences: Double inline val Attendance.isExcusableOrNotExcused: Boolean get() = (excusable || ((absence || lateness) && !excused)) && excuseStatus == null -fun AttendanceSummary.calculatePercentage(fake: Boolean = false) = if (fake) { - 100.0 -} else { - calculatePercentage(allPresences, allAbsences) -} +fun AttendanceSummary.calculatePercentage() = calculatePercentage(allPresences, allAbsences) -fun List.calculatePercentage(fake: Boolean = false): Double { - return if (fake) { - 100.0 - } else { - calculatePercentage(sumOf { it.allPresences }, sumOf { it.allAbsences }) - } +fun List.calculatePercentage(): Double { + return calculatePercentage(sumOf { it.allPresences }, sumOf { it.allAbsences }) } private fun calculatePercentage(presence: Double, absence: Double): Double { diff --git a/app/src/main/res/values-cs/preferences_values.xml b/app/src/main/res/values-cs/preferences_values.xml index e1a3956b..425fe8ae 100644 --- a/app/src/main/res/values-cs/preferences_values.xml +++ b/app/src/main/res/values-cs/preferences_values.xml @@ -72,6 +72,6 @@ Špatné hodnocení Špatná účast Poznámky - Falešná 100% účast + Falešná účast diff --git a/app/src/main/res/values-da-rDK/preferences_values.xml b/app/src/main/res/values-da-rDK/preferences_values.xml index c71d83c6..b2760e11 100644 --- a/app/src/main/res/values-da-rDK/preferences_values.xml +++ b/app/src/main/res/values-da-rDK/preferences_values.xml @@ -71,6 +71,6 @@ Bad grades Bad attendance Notes - Fake 100% attendance + Fake attendance diff --git a/app/src/main/res/values-es-rES/preferences_values.xml b/app/src/main/res/values-es-rES/preferences_values.xml index c71d83c6..b2760e11 100644 --- a/app/src/main/res/values-es-rES/preferences_values.xml +++ b/app/src/main/res/values-es-rES/preferences_values.xml @@ -71,6 +71,6 @@ Bad grades Bad attendance Notes - Fake 100% attendance + Fake attendance diff --git a/app/src/main/res/values-it-rIT/preferences_values.xml b/app/src/main/res/values-it-rIT/preferences_values.xml index c71d83c6..b2760e11 100644 --- a/app/src/main/res/values-it-rIT/preferences_values.xml +++ b/app/src/main/res/values-it-rIT/preferences_values.xml @@ -71,6 +71,6 @@ Bad grades Bad attendance Notes - Fake 100% attendance + Fake attendance diff --git a/app/src/main/res/values-pl/preferences_values.xml b/app/src/main/res/values-pl/preferences_values.xml index 8547e4f5..cf809f23 100644 --- a/app/src/main/res/values-pl/preferences_values.xml +++ b/app/src/main/res/values-pl/preferences_values.xml @@ -71,6 +71,6 @@ Słabe oceny Słaba frekwencja Uwagi - Fałszywa 100% frekwencja + Fałszywa frekwencja diff --git a/app/src/main/res/values-ru/preferences_values.xml b/app/src/main/res/values-ru/preferences_values.xml index b900f2f9..c10cb4c1 100644 --- a/app/src/main/res/values-ru/preferences_values.xml +++ b/app/src/main/res/values-ru/preferences_values.xml @@ -71,6 +71,6 @@ Плохие оценки Плохая посещаемость Примечания - Фейковая 100% посещаемость + Фейковая посещаемость diff --git a/app/src/main/res/values-sk/preferences_values.xml b/app/src/main/res/values-sk/preferences_values.xml index 244fb99a..eeceb77f 100644 --- a/app/src/main/res/values-sk/preferences_values.xml +++ b/app/src/main/res/values-sk/preferences_values.xml @@ -71,6 +71,6 @@ Zlé známky Zlá účasť Poznámky - Falošná 100% účasť + Falošná účasť diff --git a/app/src/main/res/values-uk/preferences_values.xml b/app/src/main/res/values-uk/preferences_values.xml index a1968b3e..2f3786fd 100644 --- a/app/src/main/res/values-uk/preferences_values.xml +++ b/app/src/main/res/values-uk/preferences_values.xml @@ -71,6 +71,6 @@ Погані оцінки Погана відвідуваність Примітки - Фальшива 100% явка + Фальшива явка diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml new file mode 100644 index 00000000..a1c270e6 --- /dev/null +++ b/app/src/main/res/values/integers.xml @@ -0,0 +1,4 @@ + + + -1 + diff --git a/app/src/main/res/values/preferences_values.xml b/app/src/main/res/values/preferences_values.xml index bac474dc..54455670 100644 --- a/app/src/main/res/values/preferences_values.xml +++ b/app/src/main/res/values/preferences_values.xml @@ -161,7 +161,7 @@ Bad grades Bad attendance Notes - Fake 100% attendance + Fake attendance BAD_GRADES diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 652019fb..947fed54 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -865,4 +865,7 @@ Feature disabled by your school Feature not available. Login in a mode other than Mobile API This field is required + Attendance percentage + attendance_percentage + Bad grades