More strongly typed data in preferences (#1697)

This commit is contained in:
Michael 2021-12-11 17:14:46 +01:00 committed by GitHub
parent 70f038f15f
commit 79b970256f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 113 additions and 42 deletions

View File

@ -0,0 +1,12 @@
package io.github.wulkanowy.data.enums
enum class AppTheme(val value: String) {
SYSTEM("system"),
LIGHT("light"),
DARK("dark"),
BLACK("black");
companion object {
fun getByValue(value: String) = values().find { it.value == value } ?: LIGHT
}
}

View File

@ -0,0 +1,11 @@
package io.github.wulkanowy.data.enums
enum class TimetableMode(val value: String) {
WHOLE_PLAN("yes"),
ONLY_CURRENT_GROUP("no"),
SMALL_OTHER_GROUP("small");
companion object {
fun getByValue(value: String) = values().find { it.value == value } ?: ONLY_CURRENT_GROUP
}
}

View File

@ -7,9 +7,11 @@ import com.fredporciuncula.flow.preferences.FlowSharedPreferences
import com.fredporciuncula.flow.preferences.Preference import com.fredporciuncula.flow.preferences.Preference
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.enums.AppTheme
import io.github.wulkanowy.data.enums.GradeColorTheme import io.github.wulkanowy.data.enums.GradeColorTheme
import io.github.wulkanowy.data.enums.GradeExpandMode import io.github.wulkanowy.data.enums.GradeExpandMode
import io.github.wulkanowy.data.enums.GradeSortingMode import io.github.wulkanowy.data.enums.GradeSortingMode
import io.github.wulkanowy.data.enums.TimetableMode
import io.github.wulkanowy.sdk.toLocalDate import io.github.wulkanowy.sdk.toLocalDate
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode import io.github.wulkanowy.ui.modules.grade.GradeAverageMode
@ -73,8 +75,8 @@ class PreferencesRepository @Inject constructor(
) )
val appThemeKey = context.getString(R.string.pref_key_app_theme) val appThemeKey = context.getString(R.string.pref_key_app_theme)
val appTheme: String val appTheme: AppTheme
get() = getString(appThemeKey, R.string.pref_default_app_theme) get() = AppTheme.getByValue(getString(appThemeKey, R.string.pref_default_app_theme))
val gradeColorTheme: GradeColorTheme val gradeColorTheme: GradeColorTheme
get() = GradeColorTheme.getByValue( get() = GradeColorTheme.getByValue(
@ -159,11 +161,13 @@ class PreferencesRepository @Inject constructor(
R.bool.pref_default_timetable_show_groups R.bool.pref_default_timetable_show_groups
) )
val showWholeClassPlan: String val showWholeClassPlan: TimetableMode
get() = getString( get() = TimetableMode.getByValue(
getString(
R.string.pref_key_timetable_show_whole_class, R.string.pref_key_timetable_show_whole_class,
R.string.pref_default_timetable_show_whole_class R.string.pref_default_timetable_show_whole_class
) )
)
val gradeSortingMode: GradeSortingMode val gradeSortingMode: GradeSortingMode
get() = GradeSortingMode.getByValue( get() = GradeSortingMode.getByValue(

View File

@ -7,6 +7,7 @@ import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.enums.AppTheme
import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.ui.modules.login.LoginActivity import io.github.wulkanowy.ui.modules.login.LoginActivity
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
@ -20,7 +21,7 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer
fun applyActivityTheme(activity: AppCompatActivity) { fun applyActivityTheme(activity: AppCompatActivity) {
if (isThemeApplicable(activity)) { if (isThemeApplicable(activity)) {
applyDefaultTheme() applyDefaultTheme()
if (preferencesRepository.appTheme == "black") { if (preferencesRepository.appTheme == AppTheme.BLACK) {
when (activity) { when (activity) {
is MainActivity -> activity.setTheme(R.style.WulkanowyTheme_Black) is MainActivity -> activity.setTheme(R.style.WulkanowyTheme_Black)
is LoginActivity -> activity.setTheme(R.style.WulkanowyTheme_Login_Black) is LoginActivity -> activity.setTheme(R.style.WulkanowyTheme_Login_Black)
@ -32,11 +33,10 @@ class ThemeManager @Inject constructor(private val preferencesRepository: Prefer
fun applyDefaultTheme() { fun applyDefaultTheme() {
AppCompatDelegate.setDefaultNightMode( AppCompatDelegate.setDefaultNightMode(
when (val theme = preferencesRepository.appTheme) { when (preferencesRepository.appTheme) {
"light" -> MODE_NIGHT_NO AppTheme.LIGHT -> MODE_NIGHT_NO
"dark", "black" -> MODE_NIGHT_YES AppTheme.DARK, AppTheme.BLACK -> MODE_NIGHT_YES
"system" -> MODE_NIGHT_FOLLOW_SYSTEM AppTheme.SYSTEM -> MODE_NIGHT_FOLLOW_SYSTEM
else -> throw IllegalArgumentException("Wrong theme: $theme")
} }
) )
} }

View File

@ -12,6 +12,7 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.data.enums.TimetableMode
import io.github.wulkanowy.databinding.ItemTimetableBinding import io.github.wulkanowy.databinding.ItemTimetableBinding
import io.github.wulkanowy.databinding.ItemTimetableSmallBinding import io.github.wulkanowy.databinding.ItemTimetableSmallBinding
import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.getThemeAttrColor
@ -35,7 +36,7 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
var onClickListener: (Timetable) -> Unit = {} var onClickListener: (Timetable) -> Unit = {}
private var showWholeClassPlan: String = "no" private lateinit var showWholeClassPlan: TimetableMode
private var showGroupsInPlan: Boolean = false private var showGroupsInPlan: Boolean = false
@ -47,7 +48,7 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
fun submitList( fun submitList(
newTimetable: List<Timetable>, newTimetable: List<Timetable>,
showWholeClassPlan: String = this.showWholeClassPlan, showWholeClassPlan: TimetableMode = this.showWholeClassPlan,
showGroupsInPlan: Boolean = this.showGroupsInPlan, showGroupsInPlan: Boolean = this.showGroupsInPlan,
showTimers: Boolean = this.showTimers showTimers: Boolean = this.showTimers
) { ) {
@ -87,7 +88,7 @@ class TimetableAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
override fun getItemCount() = items.size override fun getItemCount() = items.size
override fun getItemViewType(position: Int) = when { override fun getItemViewType(position: Int) = when {
!items[position].isStudentPlan && showWholeClassPlan == "small" -> ViewType.ITEM_SMALL.ordinal !items[position].isStudentPlan && showWholeClassPlan == TimetableMode.SMALL_OTHER_GROUP -> ViewType.ITEM_SMALL.ordinal
else -> ViewType.ITEM_NORMAL.ordinal else -> ViewType.ITEM_NORMAL.ordinal
} }

View File

@ -14,6 +14,7 @@ import com.google.android.material.datepicker.MaterialDatePicker
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.data.enums.TimetableMode
import io.github.wulkanowy.databinding.FragmentTimetableBinding import io.github.wulkanowy.databinding.FragmentTimetableBinding
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainActivity import io.github.wulkanowy.ui.modules.main.MainActivity
@ -115,7 +116,7 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
override fun updateData( override fun updateData(
data: List<Timetable>, data: List<Timetable>,
showWholeClassPlanType: String, showWholeClassPlanType: TimetableMode,
showGroupsInPlanType: Boolean, showGroupsInPlanType: Boolean,
showTimetableTimers: Boolean showTimetableTimers: Boolean
) { ) {

View File

@ -3,6 +3,7 @@ package io.github.wulkanowy.ui.modules.timetable
import android.annotation.SuppressLint import android.annotation.SuppressLint
import io.github.wulkanowy.data.Status import io.github.wulkanowy.data.Status
import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.data.enums.TimetableMode
import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.data.repositories.SemesterRepository import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
@ -197,7 +198,7 @@ class TimetablePresenter @Inject constructor(
} }
private fun createItems(items: List<Timetable>) = items.filter { item -> private fun createItems(items: List<Timetable>) = items.filter { item ->
if (prefRepository.showWholeClassPlan == "no") item.isStudentPlan else true if (prefRepository.showWholeClassPlan == TimetableMode.ONLY_CURRENT_GROUP) item.isStudentPlan else true
}.sortedWith(compareBy({ item -> item.number }, { item -> !item.isStudentPlan })) }.sortedWith(compareBy({ item -> item.number }, { item -> !item.isStudentPlan }))
private fun showErrorViewOnError(message: String, error: Throwable) { private fun showErrorViewOnError(message: String, error: Throwable) {

View File

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

View File

@ -14,6 +14,7 @@ import android.widget.RemoteViewsService
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.SharedPrefProvider import io.github.wulkanowy.data.db.SharedPrefProvider
import io.github.wulkanowy.data.db.entities.Timetable import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.data.enums.TimetableMode
import io.github.wulkanowy.data.repositories.PreferencesRepository import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.data.repositories.SemesterRepository import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
@ -88,7 +89,7 @@ class TimetableWidgetFactory(
private fun getItemLayout(lesson: Timetable): Int { private fun getItemLayout(lesson: Timetable): Int {
return when { return when {
prefRepository.showWholeClassPlan == "small" && !lesson.isStudentPlan -> { prefRepository.showWholeClassPlan == TimetableMode.SMALL_OTHER_GROUP && !lesson.isStudentPlan -> {
if (savedCurrentTheme == 0L) R.layout.item_widget_timetable_small if (savedCurrentTheme == 0L) R.layout.item_widget_timetable_small
else R.layout.item_widget_timetable_small_dark else R.layout.item_widget_timetable_small_dark
} }
@ -109,7 +110,11 @@ class TimetableWidgetFactory(
timetableRepository.getTimetable(student, semester, date, date, false) timetableRepository.getTimetable(student, semester, date, date, false)
.toFirstResult().data?.lessons.orEmpty() .toFirstResult().data?.lessons.orEmpty()
.sortedWith(compareBy({ it.number }, { !it.isStudentPlan })) .sortedWith(compareBy({ it.number }, { !it.isStudentPlan }))
.filter { if (prefRepository.showWholeClassPlan == "no") it.isStudentPlan else true } .filter {
if (prefRepository.showWholeClassPlan == TimetableMode.ONLY_CURRENT_GROUP) {
it.isStudentPlan
} else true
}
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e, "An error has occurred in timetable widget factory") Timber.e(e, "An error has occurred in timetable widget factory")
@ -124,8 +129,14 @@ class TimetableWidgetFactory(
return RemoteViews(context.packageName, getItemLayout(lesson)).apply { return RemoteViews(context.packageName, getItemLayout(lesson)).apply {
setTextViewText(R.id.timetableWidgetItemSubject, lesson.subject) setTextViewText(R.id.timetableWidgetItemSubject, lesson.subject)
setTextViewText(R.id.timetableWidgetItemNumber, lesson.number.toString()) setTextViewText(R.id.timetableWidgetItemNumber, lesson.number.toString())
setTextViewText(R.id.timetableWidgetItemTimeStart, lesson.start.toFormattedString("HH:mm")) setTextViewText(
setTextViewText(R.id.timetableWidgetItemTimeFinish, lesson.end.toFormattedString("HH:mm")) R.id.timetableWidgetItemTimeStart,
lesson.start.toFormattedString("HH:mm")
)
setTextViewText(
R.id.timetableWidgetItemTimeFinish,
lesson.end.toFormattedString("HH:mm")
)
updateDescription(this, lesson) updateDescription(this, lesson)
@ -156,11 +167,16 @@ class TimetableWidgetFactory(
private fun updateStylesCanceled(remoteViews: RemoteViews) { private fun updateStylesCanceled(remoteViews: RemoteViews) {
with(remoteViews) { with(remoteViews) {
setInt(R.id.timetableWidgetItemSubject, "setPaintFlags", setInt(
STRIKE_THRU_TEXT_FLAG or ANTI_ALIAS_FLAG) R.id.timetableWidgetItemSubject, "setPaintFlags",
STRIKE_THRU_TEXT_FLAG or ANTI_ALIAS_FLAG
)
setTextColor(R.id.timetableWidgetItemNumber, context.getCompatColor(primaryColor!!)) setTextColor(R.id.timetableWidgetItemNumber, context.getCompatColor(primaryColor!!))
setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor(primaryColor!!)) setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor(primaryColor!!))
setTextColor(R.id.timetableWidgetItemDescription, context.getCompatColor(primaryColor!!)) setTextColor(
R.id.timetableWidgetItemDescription,
context.getCompatColor(primaryColor!!)
)
} }
} }
@ -168,7 +184,10 @@ class TimetableWidgetFactory(
with(remoteViews) { with(remoteViews) {
setInt(R.id.timetableWidgetItemSubject, "setPaintFlags", ANTI_ALIAS_FLAG) setInt(R.id.timetableWidgetItemSubject, "setPaintFlags", ANTI_ALIAS_FLAG)
setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor(textColor!!)) setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor(textColor!!))
setTextColor(R.id.timetableWidgetItemDescription, context.getCompatColor(timetableChangeColor!!)) setTextColor(
R.id.timetableWidgetItemDescription,
context.getCompatColor(timetableChangeColor!!)
)
updateNotCanceledLessonNumberColor(this, lesson) updateNotCanceledLessonNumberColor(this, lesson)
updateNotCanceledSubjectColor(this, lesson) updateNotCanceledSubjectColor(this, lesson)
@ -180,37 +199,53 @@ class TimetableWidgetFactory(
} }
private fun updateNotCanceledLessonNumberColor(remoteViews: RemoteViews, lesson: Timetable) { private fun updateNotCanceledLessonNumberColor(remoteViews: RemoteViews, lesson: Timetable) {
remoteViews.setTextColor(R.id.timetableWidgetItemNumber, context.getCompatColor( remoteViews.setTextColor(
R.id.timetableWidgetItemNumber, context.getCompatColor(
if (lesson.changes || (lesson.info.isNotBlank() && !lesson.canceled)) timetableChangeColor!! if (lesson.changes || (lesson.info.isNotBlank() && !lesson.canceled)) timetableChangeColor!!
else textColor!! else textColor!!
)) )
)
} }
private fun updateNotCanceledSubjectColor(remoteViews: RemoteViews, lesson: Timetable) { private fun updateNotCanceledSubjectColor(remoteViews: RemoteViews, lesson: Timetable) {
remoteViews.setTextColor(R.id.timetableWidgetItemSubject, context.getCompatColor( remoteViews.setTextColor(
R.id.timetableWidgetItemSubject, context.getCompatColor(
if (lesson.subjectOld.isNotBlank() && lesson.subject != lesson.subjectOld) timetableChangeColor!! if (lesson.subjectOld.isNotBlank() && lesson.subject != lesson.subjectOld) timetableChangeColor!!
else textColor!! else textColor!!
)) )
)
} }
private fun updateNotCanceledRoom(remoteViews: RemoteViews, lesson: Timetable, teacherChange: Boolean) { private fun updateNotCanceledRoom(
remoteViews: RemoteViews,
lesson: Timetable,
teacherChange: Boolean
) {
with(remoteViews) { with(remoteViews) {
if (lesson.room.isNotBlank()) { if (lesson.room.isNotBlank()) {
setTextViewText(R.id.timetableWidgetItemRoom, setTextViewText(
R.id.timetableWidgetItemRoom,
if (teacherChange) lesson.room if (teacherChange) lesson.room
else "${context.getString(R.string.timetable_room)} ${lesson.room}" else "${context.getString(R.string.timetable_room)} ${lesson.room}"
) )
setTextColor(R.id.timetableWidgetItemRoom, context.getCompatColor( setTextColor(
R.id.timetableWidgetItemRoom, context.getCompatColor(
if (lesson.roomOld.isNotBlank() && lesson.room != lesson.roomOld) timetableChangeColor!! if (lesson.roomOld.isNotBlank() && lesson.room != lesson.roomOld) timetableChangeColor!!
else textColor!! else textColor!!
)) )
)
} else setTextViewText(R.id.timetableWidgetItemRoom, "") } else setTextViewText(R.id.timetableWidgetItemRoom, "")
} }
} }
private fun updateNotCanceledTeacher(remoteViews: RemoteViews, lesson: Timetable, teacherChange: Boolean) { private fun updateNotCanceledTeacher(
remoteViews.setTextViewText(R.id.timetableWidgetItemTeacher, remoteViews: RemoteViews,
lesson: Timetable,
teacherChange: Boolean
) {
remoteViews.setTextViewText(
R.id.timetableWidgetItemTeacher,
if (teacherChange) lesson.teacher if (teacherChange) lesson.teacher
else "" else ""
) )