forked from github/wulkanowy-mirror
Add option to show empty tiles in the timetable (#2236)
Co-authored-by: Mikołaj Pich <m.pich@outlook.com>
This commit is contained in:
parent
024ca89708
commit
533157709b
@ -50,5 +50,9 @@
|
|||||||
{
|
{
|
||||||
"displayName": "Tomasz F.",
|
"displayName": "Tomasz F.",
|
||||||
"githubUsername": "Pengwius"
|
"githubUsername": "Pengwius"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "Antoni Paduch",
|
||||||
|
"githubUsername": "janAte1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package io.github.wulkanowy.data.enums
|
||||||
|
|
||||||
|
enum class TimetableGapsMode(val value: String) {
|
||||||
|
NO_GAPS("no_gaps"),
|
||||||
|
BETWEEN_LESSONS("between"),
|
||||||
|
BETWEEN_AND_BEFORE_LESSONS("before_and_between");
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getByValue(value: String) = entries.find { it.value == value } ?: BETWEEN_LESSONS
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,6 @@ import io.github.wulkanowy.ui.modules.grade.GradeAverageMode
|
|||||||
import io.github.wulkanowy.ui.modules.settings.appearance.menuorder.AppMenuItem
|
import io.github.wulkanowy.ui.modules.settings.appearance.menuorder.AppMenuItem
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.serialization.decodeFromString
|
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@ -201,6 +200,14 @@ class PreferencesRepository @Inject constructor(
|
|||||||
R.bool.pref_default_timetable_show_timers
|
R.bool.pref_default_timetable_show_timers
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val showTimetableGaps: TimetableGapsMode
|
||||||
|
get() = TimetableGapsMode.getByValue(
|
||||||
|
getString(
|
||||||
|
R.string.pref_key_timetable_show_gaps,
|
||||||
|
R.string.pref_default_timetable_show_gaps
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
val showSubjectsWithoutGrades: Boolean
|
val showSubjectsWithoutGrades: Boolean
|
||||||
get() = getBoolean(
|
get() = getBoolean(
|
||||||
R.string.pref_key_subjects_without_grades,
|
R.string.pref_key_subjects_without_grades,
|
||||||
|
@ -4,6 +4,7 @@ import android.content.Intent
|
|||||||
import android.widget.RemoteViewsService
|
import android.widget.RemoteViewsService
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||||
|
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
|
||||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||||
@ -26,10 +27,19 @@ class TimetableWidgetService : RemoteViewsService() {
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var sharedPref: SharedPrefProvider
|
lateinit var sharedPref: SharedPrefProvider
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var prefRepository: PreferencesRepository
|
||||||
|
|
||||||
override fun onGetViewFactory(intent: Intent?): RemoteViewsFactory {
|
override fun onGetViewFactory(intent: Intent?): RemoteViewsFactory {
|
||||||
Timber.d("TimetableWidgetFactory created")
|
Timber.d("TimetableWidgetFactory created")
|
||||||
return TimetableWidgetFactory(
|
return TimetableWidgetFactory(
|
||||||
timetableRepo, studentRepo, semesterRepo, sharedPref, applicationContext, intent
|
timetableRepository = timetableRepo,
|
||||||
|
studentRepository = studentRepo,
|
||||||
|
semesterRepository = semesterRepo,
|
||||||
|
sharedPref = sharedPref,
|
||||||
|
prefRepository = prefRepository,
|
||||||
|
context = applicationContext,
|
||||||
|
intent = intent,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,9 @@ 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.databinding.ItemTimetableBinding
|
import io.github.wulkanowy.databinding.ItemTimetableBinding
|
||||||
|
import io.github.wulkanowy.databinding.ItemTimetableEmptyBinding
|
||||||
import io.github.wulkanowy.databinding.ItemTimetableSmallBinding
|
import io.github.wulkanowy.databinding.ItemTimetableSmallBinding
|
||||||
|
import io.github.wulkanowy.utils.getPlural
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -29,9 +31,14 @@ class TimetableAdapter @Inject constructor() :
|
|||||||
TimetableItemType.SMALL -> SmallViewHolder(
|
TimetableItemType.SMALL -> SmallViewHolder(
|
||||||
ItemTimetableSmallBinding.inflate(inflater, parent, false)
|
ItemTimetableSmallBinding.inflate(inflater, parent, false)
|
||||||
)
|
)
|
||||||
|
|
||||||
TimetableItemType.NORMAL -> NormalViewHolder(
|
TimetableItemType.NORMAL -> NormalViewHolder(
|
||||||
ItemTimetableBinding.inflate(inflater, parent, false)
|
ItemTimetableBinding.inflate(inflater, parent, false)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
TimetableItemType.EMPTY -> EmptyViewHolder(
|
||||||
|
ItemTimetableEmptyBinding.inflate(inflater, parent, false)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,12 +47,12 @@ class TimetableAdapter @Inject constructor() :
|
|||||||
position: Int,
|
position: Int,
|
||||||
payloads: MutableList<Any>
|
payloads: MutableList<Any>
|
||||||
) {
|
) {
|
||||||
if (payloads.isEmpty()) return super.onBindViewHolder(holder, position, payloads)
|
if (payloads.isNotEmpty() && holder is NormalViewHolder) {
|
||||||
|
updateTimeLeft(
|
||||||
if (holder is NormalViewHolder) updateTimeLeft(
|
binding = holder.binding,
|
||||||
binding = holder.binding,
|
timeLeft = (getItem(position) as TimetableItem.Normal).timeLeft,
|
||||||
timeLeft = (getItem(position) as TimetableItem.Normal).timeLeft,
|
)
|
||||||
)
|
} else super.onBindViewHolder(holder, position, payloads)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
@ -54,10 +61,16 @@ class TimetableAdapter @Inject constructor() :
|
|||||||
binding = holder.binding,
|
binding = holder.binding,
|
||||||
item = getItem(position) as TimetableItem.Small,
|
item = getItem(position) as TimetableItem.Small,
|
||||||
)
|
)
|
||||||
|
|
||||||
is NormalViewHolder -> bindNormalView(
|
is NormalViewHolder -> bindNormalView(
|
||||||
binding = holder.binding,
|
binding = holder.binding,
|
||||||
item = getItem(position) as TimetableItem.Normal,
|
item = getItem(position) as TimetableItem.Normal,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
is EmptyViewHolder -> bindEmptyView(
|
||||||
|
binding = holder.binding,
|
||||||
|
item = getItem(position) as TimetableItem.Empty,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +113,19 @@ class TimetableAdapter @Inject constructor() :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun bindEmptyView(binding: ItemTimetableEmptyBinding, item: TimetableItem.Empty) {
|
||||||
|
with(binding) {
|
||||||
|
timetableEmptyItemNumber.text = when (item.numFrom) {
|
||||||
|
item.numTo -> item.numFrom.toString()
|
||||||
|
else -> "${item.numFrom}-${item.numTo}"
|
||||||
|
}
|
||||||
|
timetableEmptyItemSubject.text = timetableEmptyItemSubject.context.getPlural(
|
||||||
|
R.plurals.timetable_no_lesson,
|
||||||
|
item.numTo - item.numFrom + 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateTimeLeft(binding: ItemTimetableBinding, timeLeft: TimeLeft?) {
|
private fun updateTimeLeft(binding: ItemTimetableBinding, timeLeft: TimeLeft?) {
|
||||||
with(binding) {
|
with(binding) {
|
||||||
when {
|
when {
|
||||||
@ -137,6 +163,7 @@ class TimetableAdapter @Inject constructor() :
|
|||||||
timetableItemTimeLeft.visibility = VISIBLE
|
timetableItemTimeLeft.visibility = VISIBLE
|
||||||
timetableItemTimeLeft.text = root.context.getString(R.string.timetable_finished)
|
timetableItemTimeLeft.text = root.context.getString(R.string.timetable_finished)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
timetableItemTimeUntil.visibility = GONE
|
timetableItemTimeUntil.visibility = GONE
|
||||||
timetableItemTimeLeft.visibility = GONE
|
timetableItemTimeLeft.visibility = GONE
|
||||||
@ -191,7 +218,8 @@ class TimetableAdapter @Inject constructor() :
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
timetableItemDescription.visibility = GONE
|
timetableItemDescription.visibility = GONE
|
||||||
timetableItemRoom.isVisible = lesson.room.isNotBlank() || lesson.roomOld.isNotBlank()
|
timetableItemRoom.isVisible =
|
||||||
|
lesson.room.isNotBlank() || lesson.roomOld.isNotBlank()
|
||||||
timetableItemGroup.isVisible = item.showGroupsInPlan && lesson.group.isNotBlank()
|
timetableItemGroup.isVisible = item.showGroupsInPlan && lesson.group.isNotBlank()
|
||||||
timetableItemTeacher.visibility = VISIBLE
|
timetableItemTeacher.visibility = VISIBLE
|
||||||
}
|
}
|
||||||
@ -274,6 +302,9 @@ class TimetableAdapter @Inject constructor() :
|
|||||||
private class SmallViewHolder(val binding: ItemTimetableSmallBinding) :
|
private class SmallViewHolder(val binding: ItemTimetableSmallBinding) :
|
||||||
RecyclerView.ViewHolder(binding.root)
|
RecyclerView.ViewHolder(binding.root)
|
||||||
|
|
||||||
|
private class EmptyViewHolder(val binding: ItemTimetableEmptyBinding) :
|
||||||
|
RecyclerView.ViewHolder(binding.root)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val differ = object : DiffUtil.ItemCallback<TimetableItem>() {
|
private val differ = object : DiffUtil.ItemCallback<TimetableItem>() {
|
||||||
override fun areItemsTheSame(oldItem: TimetableItem, newItem: TimetableItem): Boolean =
|
override fun areItemsTheSame(oldItem: TimetableItem, newItem: TimetableItem): Boolean =
|
||||||
@ -281,9 +312,11 @@ class TimetableAdapter @Inject constructor() :
|
|||||||
oldItem is TimetableItem.Small && newItem is TimetableItem.Small -> {
|
oldItem is TimetableItem.Small && newItem is TimetableItem.Small -> {
|
||||||
oldItem.lesson.start == newItem.lesson.start
|
oldItem.lesson.start == newItem.lesson.start
|
||||||
}
|
}
|
||||||
|
|
||||||
oldItem is TimetableItem.Normal && newItem is TimetableItem.Normal -> {
|
oldItem is TimetableItem.Normal && newItem is TimetableItem.Normal -> {
|
||||||
oldItem.lesson.start == newItem.lesson.start
|
oldItem.lesson.start == newItem.lesson.start
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> oldItem == newItem
|
else -> oldItem == newItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,11 @@ sealed class TimetableItem(val type: TimetableItemType) {
|
|||||||
val timeLeft: TimeLeft?,
|
val timeLeft: TimeLeft?,
|
||||||
val onClick: (Timetable) -> Unit,
|
val onClick: (Timetable) -> Unit,
|
||||||
) : TimetableItem(TimetableItemType.NORMAL)
|
) : TimetableItem(TimetableItemType.NORMAL)
|
||||||
|
|
||||||
|
data class Empty(
|
||||||
|
val numFrom: Int,
|
||||||
|
val numTo: Int
|
||||||
|
) : TimetableItem(TimetableItemType.EMPTY)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class TimeLeft(
|
data class TimeLeft(
|
||||||
@ -27,4 +32,5 @@ data class TimeLeft(
|
|||||||
enum class TimetableItemType {
|
enum class TimetableItemType {
|
||||||
SMALL,
|
SMALL,
|
||||||
NORMAL,
|
NORMAL,
|
||||||
|
EMPTY
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,44 @@
|
|||||||
package io.github.wulkanowy.ui.modules.timetable
|
package io.github.wulkanowy.ui.modules.timetable
|
||||||
|
|
||||||
import io.github.wulkanowy.data.*
|
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
|
import io.github.wulkanowy.data.enums.TimetableGapsMode.BETWEEN_AND_BEFORE_LESSONS
|
||||||
|
import io.github.wulkanowy.data.enums.TimetableGapsMode.NO_GAPS
|
||||||
import io.github.wulkanowy.data.enums.TimetableMode
|
import io.github.wulkanowy.data.enums.TimetableMode
|
||||||
|
import io.github.wulkanowy.data.flatResourceFlow
|
||||||
|
import io.github.wulkanowy.data.logResourceStatus
|
||||||
|
import io.github.wulkanowy.data.onResourceData
|
||||||
|
import io.github.wulkanowy.data.onResourceError
|
||||||
|
import io.github.wulkanowy.data.onResourceIntermediate
|
||||||
|
import io.github.wulkanowy.data.onResourceNotLoading
|
||||||
|
import io.github.wulkanowy.data.onResourceSuccess
|
||||||
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
|
||||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.*
|
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||||
|
import io.github.wulkanowy.utils.capitalise
|
||||||
|
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
|
||||||
|
import io.github.wulkanowy.utils.isHolidays
|
||||||
|
import io.github.wulkanowy.utils.isJustFinished
|
||||||
|
import io.github.wulkanowy.utils.isShowTimeUntil
|
||||||
|
import io.github.wulkanowy.utils.left
|
||||||
|
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||||
|
import io.github.wulkanowy.utils.nextSchoolDay
|
||||||
|
import io.github.wulkanowy.utils.previousSchoolDay
|
||||||
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
|
import io.github.wulkanowy.utils.until
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDate.*
|
import java.time.LocalDate.now
|
||||||
import java.util.*
|
import java.time.LocalDate.of
|
||||||
|
import java.time.LocalDate.ofEpochDay
|
||||||
|
import java.util.Timer
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.concurrent.timer
|
import kotlin.concurrent.timer
|
||||||
|
|
||||||
@ -192,16 +213,38 @@ class TimetablePresenter @Inject constructor(
|
|||||||
compareBy({ item -> item.number }, { item -> !item.isStudentPlan })
|
compareBy({ item -> item.number }, { item -> !item.isStudentPlan })
|
||||||
)
|
)
|
||||||
|
|
||||||
return filteredItems.mapIndexed { i, it ->
|
var prevNum = when (prefRepository.showTimetableGaps) {
|
||||||
if (it.isStudentPlan) TimetableItem.Normal(
|
BETWEEN_AND_BEFORE_LESSONS -> 0
|
||||||
lesson = it,
|
else -> null
|
||||||
showGroupsInPlan = prefRepository.showGroupsInPlan,
|
}
|
||||||
timeLeft = filteredItems.getTimeLeftForLesson(it, i),
|
return buildList {
|
||||||
onClick = ::onTimetableItemSelected
|
filteredItems.forEachIndexed { i, it ->
|
||||||
) else TimetableItem.Small(
|
if (prefRepository.showTimetableGaps != NO_GAPS && prevNum != null && it.number > prevNum!! + 1) {
|
||||||
lesson = it,
|
val emptyLesson = TimetableItem.Empty(
|
||||||
onClick = ::onTimetableItemSelected
|
numFrom = prevNum!! + 1,
|
||||||
)
|
numTo = it.number - 1
|
||||||
|
)
|
||||||
|
add(emptyLesson)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it.isStudentPlan) {
|
||||||
|
val normalLesson = TimetableItem.Normal(
|
||||||
|
lesson = it,
|
||||||
|
showGroupsInPlan = prefRepository.showGroupsInPlan,
|
||||||
|
timeLeft = filteredItems.getTimeLeftForLesson(it, i),
|
||||||
|
onClick = ::onTimetableItemSelected
|
||||||
|
)
|
||||||
|
add(normalLesson)
|
||||||
|
} else {
|
||||||
|
val smallLesson = TimetableItem.Small(
|
||||||
|
lesson = it,
|
||||||
|
onClick = ::onTimetableItemSelected
|
||||||
|
)
|
||||||
|
add(smallLesson)
|
||||||
|
}
|
||||||
|
|
||||||
|
prevNum = it.number
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,9 @@ import io.github.wulkanowy.data.db.SharedPrefProvider
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
|
import io.github.wulkanowy.data.enums.TimetableGapsMode.BETWEEN_AND_BEFORE_LESSONS
|
||||||
|
import io.github.wulkanowy.data.enums.TimetableGapsMode.NO_GAPS
|
||||||
|
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
|
||||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||||
@ -24,6 +27,7 @@ import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Co
|
|||||||
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey
|
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey
|
||||||
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getTodayLastLessonEndDateTimeWidgetKey
|
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getTodayLastLessonEndDateTimeWidgetKey
|
||||||
import io.github.wulkanowy.utils.getCompatColor
|
import io.github.wulkanowy.utils.getCompatColor
|
||||||
|
import io.github.wulkanowy.utils.getPlural
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@ -35,11 +39,12 @@ class TimetableWidgetFactory(
|
|||||||
private val studentRepository: StudentRepository,
|
private val studentRepository: StudentRepository,
|
||||||
private val semesterRepository: SemesterRepository,
|
private val semesterRepository: SemesterRepository,
|
||||||
private val sharedPref: SharedPrefProvider,
|
private val sharedPref: SharedPrefProvider,
|
||||||
|
private val prefRepository: PreferencesRepository,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val intent: Intent?
|
private val intent: Intent?
|
||||||
) : RemoteViewsService.RemoteViewsFactory {
|
) : RemoteViewsService.RemoteViewsFactory {
|
||||||
|
|
||||||
private var lessons = emptyList<Timetable>()
|
private var items = emptyList<TimetableWidgetItem>()
|
||||||
|
|
||||||
private var timetableCanceledColor: Int? = null
|
private var timetableCanceledColor: Int? = null
|
||||||
|
|
||||||
@ -47,18 +52,13 @@ class TimetableWidgetFactory(
|
|||||||
|
|
||||||
private var timetableChangeColor: Int? = null
|
private var timetableChangeColor: Int? = null
|
||||||
|
|
||||||
private var lastSyncInstant: Instant? = null
|
|
||||||
|
|
||||||
override fun getLoadingView() = null
|
override fun getLoadingView() = null
|
||||||
|
|
||||||
override fun hasStableIds() = true
|
override fun hasStableIds() = true
|
||||||
|
|
||||||
override fun getCount() = when {
|
override fun getCount() = items.size
|
||||||
lessons.isEmpty() -> 0
|
|
||||||
else -> lessons.size + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getViewTypeCount() = 2
|
override fun getViewTypeCount() = 3
|
||||||
|
|
||||||
override fun getItemId(position: Int) = position.toLong()
|
override fun getItemId(position: Int) = position.toLong()
|
||||||
|
|
||||||
@ -75,9 +75,10 @@ class TimetableWidgetFactory(
|
|||||||
runBlocking {
|
runBlocking {
|
||||||
val student = getStudent(studentId) ?: return@runBlocking
|
val student = getStudent(studentId) ?: return@runBlocking
|
||||||
val semester = semesterRepository.getCurrentSemester(student)
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
lessons = getLessons(student, semester, date)
|
items = createItems(
|
||||||
lastSyncInstant =
|
lessons = getLessons(student, semester, date),
|
||||||
timetableRepository.getLastRefreshTimestamp(semester, date, date)
|
lastSync = timetableRepository.getLastRefreshTimestamp(semester, date, date)
|
||||||
|
)
|
||||||
if (date == LocalDate.now()) {
|
if (date == LocalDate.now()) {
|
||||||
updateTodayLastLessonEnd(appWidgetId)
|
updateTodayLastLessonEnd(appWidgetId)
|
||||||
}
|
}
|
||||||
@ -101,8 +102,33 @@ class TimetableWidgetFactory(
|
|||||||
return lessons.sortedBy { it.number }
|
return lessons.sortedBy { it.number }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createItems(
|
||||||
|
lessons: List<Timetable>,
|
||||||
|
lastSync: Instant?,
|
||||||
|
): List<TimetableWidgetItem> {
|
||||||
|
var prevNum = when (prefRepository.showTimetableGaps) {
|
||||||
|
BETWEEN_AND_BEFORE_LESSONS -> 0
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
return buildList {
|
||||||
|
lessons.forEach {
|
||||||
|
if (prefRepository.showTimetableGaps != NO_GAPS && prevNum != null && it.number > prevNum!! + 1) {
|
||||||
|
val emptyItem = TimetableWidgetItem.Empty(
|
||||||
|
numFrom = prevNum!! + 1,
|
||||||
|
numTo = it.number - 1
|
||||||
|
)
|
||||||
|
add(emptyItem)
|
||||||
|
}
|
||||||
|
add(TimetableWidgetItem.Normal(it))
|
||||||
|
prevNum = it.number
|
||||||
|
}
|
||||||
|
add(TimetableWidgetItem.Synchronized(lastSync ?: Instant.MIN))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateTodayLastLessonEnd(appWidgetId: Int) {
|
private fun updateTodayLastLessonEnd(appWidgetId: Int) {
|
||||||
val todayLastLessonEnd = lessons.maxOfOrNull { it.end } ?: return
|
val todayLastLessonEnd = items.filterIsInstance<TimetableWidgetItem.Normal>()
|
||||||
|
.maxOfOrNull { it.lesson.end } ?: return
|
||||||
val key = getTodayLastLessonEndDateTimeWidgetKey(appWidgetId)
|
val key = getTodayLastLessonEndDateTimeWidgetKey(appWidgetId)
|
||||||
sharedPref.putLong(key, todayLastLessonEnd.epochSecond, true)
|
sharedPref.putLong(key, todayLastLessonEnd.epochSecond, true)
|
||||||
}
|
}
|
||||||
@ -112,15 +138,15 @@ class TimetableWidgetFactory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getViewAt(position: Int): RemoteViews? {
|
override fun getViewAt(position: Int): RemoteViews? {
|
||||||
if (position == lessons.size) {
|
return when (val item = items.getOrNull(position) ?: return null) {
|
||||||
val synchronizationInstant = lastSyncInstant ?: Instant.MIN
|
is TimetableWidgetItem.Normal -> getNormalItemRemoteView(item)
|
||||||
val synchronizationText = getSynchronizationInfoText(synchronizationInstant)
|
is TimetableWidgetItem.Empty -> getEmptyItemRemoteView(item)
|
||||||
return RemoteViews(context.packageName, R.layout.item_widget_timetable_footer).apply {
|
is TimetableWidgetItem.Synchronized -> getSynchronizedItemRemoteView(item)
|
||||||
setTextViewText(R.id.timetableWidgetSynchronizationTime, synchronizationText)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val lesson = lessons.getOrNull(position) ?: return null
|
private fun getNormalItemRemoteView(item: TimetableWidgetItem.Normal): RemoteViews {
|
||||||
|
val lesson = item.lesson
|
||||||
|
|
||||||
val lessonStartTime = lesson.start.toFormattedString(TIME_FORMAT_STYLE)
|
val lessonStartTime = lesson.start.toFormattedString(TIME_FORMAT_STYLE)
|
||||||
val lessonEndTime = lesson.end.toFormattedString(TIME_FORMAT_STYLE)
|
val lessonEndTime = lesson.end.toFormattedString(TIME_FORMAT_STYLE)
|
||||||
@ -130,30 +156,63 @@ class TimetableWidgetFactory(
|
|||||||
setTextViewText(R.id.timetableWidgetItemTimeStart, lessonStartTime)
|
setTextViewText(R.id.timetableWidgetItemTimeStart, lessonStartTime)
|
||||||
setTextViewText(R.id.timetableWidgetItemTimeFinish, lessonEndTime)
|
setTextViewText(R.id.timetableWidgetItemTimeFinish, lessonEndTime)
|
||||||
setTextViewText(R.id.timetableWidgetItemSubject, lesson.subject)
|
setTextViewText(R.id.timetableWidgetItemSubject, lesson.subject)
|
||||||
|
|
||||||
setTextViewText(R.id.timetableWidgetItemTeacher, lesson.teacher)
|
setTextViewText(R.id.timetableWidgetItemTeacher, lesson.teacher)
|
||||||
setTextViewText(R.id.timetableWidgetItemDescription, lesson.info)
|
setTextViewText(R.id.timetableWidgetItemDescription, lesson.info)
|
||||||
setOnClickFillInIntent(R.id.timetableWidgetItemContainer, Intent())
|
setOnClickFillInIntent(R.id.timetableWidgetItemContainer, Intent())
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTheme()
|
updateTheme()
|
||||||
clearLessonStyles(remoteViews)
|
clearLessonStyles(remoteViews)
|
||||||
|
|
||||||
if (lesson.room.isBlank()) {
|
if (lesson.room.isBlank()) {
|
||||||
remoteViews.setViewVisibility(R.id.timetableWidgetItemRoom, GONE)
|
remoteViews.setViewVisibility(R.id.timetableWidgetItemRoom, GONE)
|
||||||
} else {
|
} else {
|
||||||
remoteViews.setTextViewText(R.id.timetableWidgetItemRoom, lesson.room)
|
remoteViews.setTextViewText(R.id.timetableWidgetItemRoom, lesson.room)
|
||||||
}
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
lesson.canceled -> applyCancelledLessonStyles(remoteViews)
|
lesson.canceled -> applyCancelledLessonStyles(remoteViews)
|
||||||
lesson.changes or lesson.info.isNotBlank() -> applyChangedLessonStyles(
|
lesson.changes or lesson.info.isNotBlank() -> applyChangedLessonStyles(
|
||||||
remoteViews, lesson
|
remoteViews = remoteViews,
|
||||||
|
lesson = lesson,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return remoteViews
|
return remoteViews
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getEmptyItemRemoteView(item: TimetableWidgetItem.Empty): RemoteViews {
|
||||||
|
return RemoteViews(
|
||||||
|
context.packageName,
|
||||||
|
R.layout.item_widget_timetable_empty
|
||||||
|
).apply {
|
||||||
|
setTextViewText(
|
||||||
|
R.id.timetableWidgetEmptyItemNumber,
|
||||||
|
when (item.numFrom) {
|
||||||
|
item.numTo -> item.numFrom.toString()
|
||||||
|
else -> "${item.numFrom}-${item.numTo}"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
setTextViewText(
|
||||||
|
R.id.timetableWidgetEmptyItemText,
|
||||||
|
context.getPlural(
|
||||||
|
R.plurals.timetable_no_lesson,
|
||||||
|
item.numTo - item.numFrom + 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
setOnClickFillInIntent(R.id.timetableWidgetEmptyItemContainer, Intent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSynchronizedItemRemoteView(item: TimetableWidgetItem.Synchronized): RemoteViews {
|
||||||
|
return RemoteViews(
|
||||||
|
context.packageName,
|
||||||
|
R.layout.item_widget_timetable_footer
|
||||||
|
).apply {
|
||||||
|
setTextViewText(
|
||||||
|
R.id.timetableWidgetSynchronizationTime,
|
||||||
|
getSynchronizationInfoText(item.timestamp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateTheme() {
|
private fun updateTheme() {
|
||||||
when (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
|
when (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
|
||||||
Configuration.UI_MODE_NIGHT_YES -> {
|
Configuration.UI_MODE_NIGHT_YES -> {
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package io.github.wulkanowy.ui.modules.timetablewidget
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
sealed class TimetableWidgetItem(val type: TimetableWidgetItemType) {
|
||||||
|
|
||||||
|
data class Normal(
|
||||||
|
val lesson: Timetable,
|
||||||
|
) : TimetableWidgetItem(TimetableWidgetItemType.NORMAL)
|
||||||
|
|
||||||
|
data class Empty(
|
||||||
|
val numFrom: Int,
|
||||||
|
val numTo: Int
|
||||||
|
) : TimetableWidgetItem(TimetableWidgetItemType.EMPTY)
|
||||||
|
|
||||||
|
data class Synchronized(
|
||||||
|
val timestamp: Instant,
|
||||||
|
) : TimetableWidgetItem(TimetableWidgetItemType.SYNCHRONIZED)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class TimetableWidgetItemType {
|
||||||
|
NORMAL,
|
||||||
|
EMPTY,
|
||||||
|
SYNCHRONIZED,
|
||||||
|
}
|
43
app/src/main/res/layout/item_timetable_empty.xml
Normal file
43
app/src/main/res/layout/item_timetable_empty.xml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?selectableItemBackground"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingTop="6dp"
|
||||||
|
android:paddingEnd="12dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
|
tools:context=".ui.modules.timetable.TimetableAdapter">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/timetableEmptyItemNumber"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:includeFontPadding="false"
|
||||||
|
android:maxLength="5"
|
||||||
|
android:minWidth="40dp"
|
||||||
|
android:minHeight="40dp"
|
||||||
|
android:textColor="?android:textColorHint"
|
||||||
|
android:textSize="32sp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="1-4" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/timetableEmptyItemSubject"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="?android:textColorHint"
|
||||||
|
android:textSize="15sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/timetableEmptyItemNumber"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/timetableEmptyItemNumber"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/timetableEmptyItemNumber"
|
||||||
|
tools:text="No lessons" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
36
app/src/main/res/layout/item_widget_timetable_empty.xml
Normal file
36
app/src/main/res/layout/item_widget_timetable_empty.xml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/timetableWidgetEmptyItemContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/background_widget_item_timetable"
|
||||||
|
android:backgroundTint="?attr/colorSurface"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingHorizontal="12dp"
|
||||||
|
android:paddingVertical="8dp"
|
||||||
|
android:theme="@style/Wulkanowy.Widget.Theme"
|
||||||
|
tools:context=".ui.modules.timetablewidget.TimetableWidgetFactory">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/timetableWidgetEmptyItemNumber"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||||
|
android:textColor="?android:textColorHint"
|
||||||
|
android:textSize="22sp"
|
||||||
|
tools:text="1-4" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/timetableWidgetEmptyItemText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:lines="1"
|
||||||
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
|
android:textColor="?android:textColorHint"
|
||||||
|
tools:text="No lessons" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -51,6 +51,11 @@
|
|||||||
<item>Średnia ze średnich z obu semestrów</item>
|
<item>Średnia ze średnich z obu semestrów</item>
|
||||||
<item>Średnia wszystkich ocen z całego roku</item>
|
<item>Średnia wszystkich ocen z całego roku</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string-array name="timetable_show_gaps_entries">
|
||||||
|
<item>Nie pokauj</item>
|
||||||
|
<item>Tylko między lekcjami</item>
|
||||||
|
<item>Przed i między lekcjami</item>
|
||||||
|
</string-array>
|
||||||
<string-array name="dashboard_tile_entries">
|
<string-array name="dashboard_tile_entries">
|
||||||
<item>Szczęśliwy numerek</item>
|
<item>Szczęśliwy numerek</item>
|
||||||
<item>Nieprzeczytane wiadomości</item>
|
<item>Nieprzeczytane wiadomości</item>
|
||||||
|
@ -185,6 +185,12 @@
|
|||||||
<string name="timetable_notify_change_room">Zmiana sali z %1$s na %2$s</string>
|
<string name="timetable_notify_change_room">Zmiana sali z %1$s na %2$s</string>
|
||||||
<string name="timetable_notify_change_teacher">Zmiana nauczyciela z %1$s na %2$s</string>
|
<string name="timetable_notify_change_teacher">Zmiana nauczyciela z %1$s na %2$s</string>
|
||||||
<string name="timetable_notify_change_subject">Zmiana przedmiotu z %1$s na %2$s</string>
|
<string name="timetable_notify_change_subject">Zmiana przedmiotu z %1$s na %2$s</string>
|
||||||
|
<plurals name="timetable_no_lesson">
|
||||||
|
<item quantity="one">Brak lekcji</item>
|
||||||
|
<item quantity="few">Brak lekcji</item>
|
||||||
|
<item quantity="many">Brak lekcji</item>
|
||||||
|
<item quantity="other">Brak lekcji</item>
|
||||||
|
</plurals>
|
||||||
<plurals name="timetable_notify_new_items_title">
|
<plurals name="timetable_notify_new_items_title">
|
||||||
<item quantity="one">Zmiana planu lekcji</item>
|
<item quantity="one">Zmiana planu lekcji</item>
|
||||||
<item quantity="few">Zmiany planu lekcji</item>
|
<item quantity="few">Zmiany planu lekcji</item>
|
||||||
@ -700,6 +706,7 @@
|
|||||||
<string name="pref_view_expand_grade">Rozwijanie ocen</string>
|
<string name="pref_view_expand_grade">Rozwijanie ocen</string>
|
||||||
<string name="pref_view_timetable_show_timers">Oznaczaj bieżącą lekcję</string>
|
<string name="pref_view_timetable_show_timers">Oznaczaj bieżącą lekcję</string>
|
||||||
<string name="pref_view_timetable_show_groups">Pokazuj grupę obok przedmiotu</string>
|
<string name="pref_view_timetable_show_groups">Pokazuj grupę obok przedmiotu</string>
|
||||||
|
<string name="pref_view_timetable_show_gaps">Pokazuj puste kafelki gdzie nie ma lekcji</string>
|
||||||
<string name="pref_view_grade_statistics_list">Pokazuj listę wykresów w ocenach klasy</string>
|
<string name="pref_view_grade_statistics_list">Pokazuj listę wykresów w ocenach klasy</string>
|
||||||
<string name="pref_view_subjects_without_grades">Pokazuj przedmioty bez ocen</string>
|
<string name="pref_view_subjects_without_grades">Pokazuj przedmioty bez ocen</string>
|
||||||
<string name="pref_view_grade_color_scheme">Schemat kolorów ocen</string>
|
<string name="pref_view_grade_color_scheme">Schemat kolorów ocen</string>
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<string name="pref_default_timetable_show_whole_class">no</string>
|
<string name="pref_default_timetable_show_whole_class">no</string>
|
||||||
<string name="pref_default_grade_sorting_mode">alphabetic</string>
|
<string name="pref_default_grade_sorting_mode">alphabetic</string>
|
||||||
<bool name="pref_default_timetable_show_timers">false</bool>
|
<bool name="pref_default_timetable_show_timers">false</bool>
|
||||||
|
<string name="pref_default_timetable_show_gaps">between</string>
|
||||||
<bool name="pref_default_subjects_without_grades">false</bool>
|
<bool name="pref_default_subjects_without_grades">false</bool>
|
||||||
<bool name="pref_default_optional_arithmetic_average">false</bool>
|
<bool name="pref_default_optional_arithmetic_average">false</bool>
|
||||||
<string name="pref_default_last_sync_date">0</string>
|
<string name="pref_default_last_sync_date">0</string>
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
<string name="pref_key_timetable_show_whole_class">show_whole_class_plan</string>
|
<string name="pref_key_timetable_show_whole_class">show_whole_class_plan</string>
|
||||||
<string name="pref_key_timetable_show_groups">show_groups_in_plan</string>
|
<string name="pref_key_timetable_show_groups">show_groups_in_plan</string>
|
||||||
<string name="pref_key_timetable_show_timers">timetable_show_timers</string>
|
<string name="pref_key_timetable_show_timers">timetable_show_timers</string>
|
||||||
|
<string name="pref_key_timetable_show_gaps">timetable_show_gaps</string>
|
||||||
<string name="pref_key_subjects_without_grades">subjects_without_grades</string>
|
<string name="pref_key_subjects_without_grades">subjects_without_grades</string>
|
||||||
<string name="pref_key_optional_arithmetic_average">optional_arithmetic_average</string>
|
<string name="pref_key_optional_arithmetic_average">optional_arithmetic_average</string>
|
||||||
<string name="pref_key_message_draft">message_draft</string>
|
<string name="pref_key_message_draft">message_draft</string>
|
||||||
|
@ -123,6 +123,17 @@
|
|||||||
<item>all_year</item>
|
<item>all_year</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="timetable_show_gaps_entries">
|
||||||
|
<item>Don\'t show</item>
|
||||||
|
<item>Only between lessons</item>
|
||||||
|
<item>Before and between lessons</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="timetable_show_gaps_values" translatable="false">
|
||||||
|
<item>no_gaps</item>
|
||||||
|
<item>between</item>
|
||||||
|
<item>before_and_between</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string-array name="dashboard_tile_entries">
|
<string-array name="dashboard_tile_entries">
|
||||||
<item>Lucky number</item>
|
<item>Lucky number</item>
|
||||||
<item>Unread messages</item>
|
<item>Unread messages</item>
|
||||||
|
@ -186,6 +186,10 @@
|
|||||||
<string name="timetable_notify_change_room">Change of room from %1$s to %2$s</string>
|
<string name="timetable_notify_change_room">Change of room from %1$s to %2$s</string>
|
||||||
<string name="timetable_notify_change_teacher">Change of teacher from %1$s to %2$s</string>
|
<string name="timetable_notify_change_teacher">Change of teacher from %1$s to %2$s</string>
|
||||||
<string name="timetable_notify_change_subject">Change of subject from %1$s to %2$s</string>
|
<string name="timetable_notify_change_subject">Change of subject from %1$s to %2$s</string>
|
||||||
|
<plurals name="timetable_no_lesson">
|
||||||
|
<item quantity="one">No lesson</item>
|
||||||
|
<item quantity="other">No lessons</item>
|
||||||
|
</plurals>
|
||||||
<plurals name="timetable_notify_new_items_title">
|
<plurals name="timetable_notify_new_items_title">
|
||||||
<item quantity="one">Timetable change</item>
|
<item quantity="one">Timetable change</item>
|
||||||
<item quantity="other">Timetable changes</item>
|
<item quantity="other">Timetable changes</item>
|
||||||
@ -690,6 +694,7 @@
|
|||||||
<string name="pref_view_expand_grade">Grades expanding</string>
|
<string name="pref_view_expand_grade">Grades expanding</string>
|
||||||
<string name="pref_view_timetable_show_timers">Mark current lesson</string>
|
<string name="pref_view_timetable_show_timers">Mark current lesson</string>
|
||||||
<string name="pref_view_timetable_show_groups">Show groups next to subjects</string>
|
<string name="pref_view_timetable_show_groups">Show groups next to subjects</string>
|
||||||
|
<string name="pref_view_timetable_show_gaps">Show empty tiles where there\'s no lesson</string>
|
||||||
<string name="pref_view_grade_statistics_list">Show chart list in class grades</string>
|
<string name="pref_view_grade_statistics_list">Show chart list in class grades</string>
|
||||||
<string name="pref_view_subjects_without_grades">Show subjects without grades</string>
|
<string name="pref_view_subjects_without_grades">Show subjects without grades</string>
|
||||||
<string name="pref_view_grade_color_scheme">Grades color scheme</string>
|
<string name="pref_view_grade_color_scheme">Grades color scheme</string>
|
||||||
|
@ -111,5 +111,13 @@
|
|||||||
app:title="@string/pref_view_timetable_show_whole_class"
|
app:title="@string/pref_view_timetable_show_whole_class"
|
||||||
app:useSimpleSummaryProvider="true" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
-->
|
-->
|
||||||
|
<ListPreference
|
||||||
|
app:defaultValue="@string/pref_default_timetable_show_gaps"
|
||||||
|
app:entries="@array/timetable_show_gaps_entries"
|
||||||
|
app:entryValues="@array/timetable_show_gaps_values"
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
app:key="@string/pref_key_timetable_show_gaps"
|
||||||
|
app:title="@string/pref_view_timetable_show_gaps"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user