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:
Antoni Paduch 2023-08-22 23:47:12 +02:00 committed by GitHub
parent 024ca89708
commit 533157709b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 363 additions and 47 deletions

View File

@ -50,5 +50,9 @@
{
"displayName": "Tomasz F.",
"githubUsername": "Pengwius"
},
{
"displayName": "Antoni Paduch",
"githubUsername": "janAte1"
}
]

View File

@ -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
}
}

View File

@ -15,7 +15,6 @@ import io.github.wulkanowy.ui.modules.grade.GradeAverageMode
import io.github.wulkanowy.ui.modules.settings.appearance.menuorder.AppMenuItem
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.time.Instant
@ -201,6 +200,14 @@ class PreferencesRepository @Inject constructor(
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
get() = getBoolean(
R.string.pref_key_subjects_without_grades,

View File

@ -4,6 +4,7 @@ import android.content.Intent
import android.widget.RemoteViewsService
import dagger.hilt.android.AndroidEntryPoint
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.StudentRepository
import io.github.wulkanowy.data.repositories.TimetableRepository
@ -26,10 +27,19 @@ class TimetableWidgetService : RemoteViewsService() {
@Inject
lateinit var sharedPref: SharedPrefProvider
@Inject
lateinit var prefRepository: PreferencesRepository
override fun onGetViewFactory(intent: Intent?): RemoteViewsFactory {
Timber.d("TimetableWidgetFactory created")
return TimetableWidgetFactory(
timetableRepo, studentRepo, semesterRepo, sharedPref, applicationContext, intent
timetableRepository = timetableRepo,
studentRepository = studentRepo,
semesterRepository = semesterRepo,
sharedPref = sharedPref,
prefRepository = prefRepository,
context = applicationContext,
intent = intent,
)
}
}

View File

@ -12,7 +12,9 @@ import androidx.recyclerview.widget.RecyclerView
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Timetable
import io.github.wulkanowy.databinding.ItemTimetableBinding
import io.github.wulkanowy.databinding.ItemTimetableEmptyBinding
import io.github.wulkanowy.databinding.ItemTimetableSmallBinding
import io.github.wulkanowy.utils.getPlural
import io.github.wulkanowy.utils.getThemeAttrColor
import io.github.wulkanowy.utils.toFormattedString
import javax.inject.Inject
@ -29,9 +31,14 @@ class TimetableAdapter @Inject constructor() :
TimetableItemType.SMALL -> SmallViewHolder(
ItemTimetableSmallBinding.inflate(inflater, parent, false)
)
TimetableItemType.NORMAL -> NormalViewHolder(
ItemTimetableBinding.inflate(inflater, parent, false)
)
TimetableItemType.EMPTY -> EmptyViewHolder(
ItemTimetableEmptyBinding.inflate(inflater, parent, false)
)
}
}
@ -40,12 +47,12 @@ class TimetableAdapter @Inject constructor() :
position: Int,
payloads: MutableList<Any>
) {
if (payloads.isEmpty()) return super.onBindViewHolder(holder, position, payloads)
if (holder is NormalViewHolder) updateTimeLeft(
if (payloads.isNotEmpty() && holder is NormalViewHolder) {
updateTimeLeft(
binding = holder.binding,
timeLeft = (getItem(position) as TimetableItem.Normal).timeLeft,
)
} else super.onBindViewHolder(holder, position, payloads)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
@ -54,10 +61,16 @@ class TimetableAdapter @Inject constructor() :
binding = holder.binding,
item = getItem(position) as TimetableItem.Small,
)
is NormalViewHolder -> bindNormalView(
binding = holder.binding,
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?) {
with(binding) {
when {
@ -137,6 +163,7 @@ class TimetableAdapter @Inject constructor() :
timetableItemTimeLeft.visibility = VISIBLE
timetableItemTimeLeft.text = root.context.getString(R.string.timetable_finished)
}
else -> {
timetableItemTimeUntil.visibility = GONE
timetableItemTimeLeft.visibility = GONE
@ -191,7 +218,8 @@ class TimetableAdapter @Inject constructor() :
)
} else {
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()
timetableItemTeacher.visibility = VISIBLE
}
@ -274,6 +302,9 @@ class TimetableAdapter @Inject constructor() :
private class SmallViewHolder(val binding: ItemTimetableSmallBinding) :
RecyclerView.ViewHolder(binding.root)
private class EmptyViewHolder(val binding: ItemTimetableEmptyBinding) :
RecyclerView.ViewHolder(binding.root)
companion object {
private val differ = object : DiffUtil.ItemCallback<TimetableItem>() {
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.lesson.start == newItem.lesson.start
}
oldItem is TimetableItem.Normal && newItem is TimetableItem.Normal -> {
oldItem.lesson.start == newItem.lesson.start
}
else -> oldItem == newItem
}

View File

@ -16,6 +16,11 @@ sealed class TimetableItem(val type: TimetableItemType) {
val timeLeft: TimeLeft?,
val onClick: (Timetable) -> Unit,
) : TimetableItem(TimetableItemType.NORMAL)
data class Empty(
val numFrom: Int,
val numTo: Int
) : TimetableItem(TimetableItemType.EMPTY)
}
data class TimeLeft(
@ -27,4 +32,5 @@ data class TimeLeft(
enum class TimetableItemType {
SMALL,
NORMAL,
EMPTY
}

View File

@ -1,23 +1,44 @@
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.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.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.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.data.repositories.TimetableRepository
import io.github.wulkanowy.ui.base.BasePresenter
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.flow
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDate.*
import java.util.*
import java.time.LocalDate.now
import java.time.LocalDate.of
import java.time.LocalDate.ofEpochDay
import java.util.Timer
import javax.inject.Inject
import kotlin.concurrent.timer
@ -192,16 +213,38 @@ class TimetablePresenter @Inject constructor(
compareBy({ item -> item.number }, { item -> !item.isStudentPlan })
)
return filteredItems.mapIndexed { i, it ->
if (it.isStudentPlan) TimetableItem.Normal(
var prevNum = when (prefRepository.showTimetableGaps) {
BETWEEN_AND_BEFORE_LESSONS -> 0
else -> null
}
return buildList {
filteredItems.forEachIndexed { i, it ->
if (prefRepository.showTimetableGaps != NO_GAPS && prevNum != null && it.number > prevNum!! + 1) {
val emptyLesson = TimetableItem.Empty(
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
) else TimetableItem.Small(
)
add(normalLesson)
} else {
val smallLesson = TimetableItem.Small(
lesson = it,
onClick = ::onTimetableItemSelected
)
add(smallLesson)
}
prevNum = it.number
}
}
}

View File

@ -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.Student
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.StudentRepository
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.getTodayLastLessonEndDateTimeWidgetKey
import io.github.wulkanowy.utils.getCompatColor
import io.github.wulkanowy.utils.getPlural
import io.github.wulkanowy.utils.toFormattedString
import kotlinx.coroutines.runBlocking
import timber.log.Timber
@ -35,11 +39,12 @@ class TimetableWidgetFactory(
private val studentRepository: StudentRepository,
private val semesterRepository: SemesterRepository,
private val sharedPref: SharedPrefProvider,
private val prefRepository: PreferencesRepository,
private val context: Context,
private val intent: Intent?
) : RemoteViewsService.RemoteViewsFactory {
private var lessons = emptyList<Timetable>()
private var items = emptyList<TimetableWidgetItem>()
private var timetableCanceledColor: Int? = null
@ -47,18 +52,13 @@ class TimetableWidgetFactory(
private var timetableChangeColor: Int? = null
private var lastSyncInstant: Instant? = null
override fun getLoadingView() = null
override fun hasStableIds() = true
override fun getCount() = when {
lessons.isEmpty() -> 0
else -> lessons.size + 1
}
override fun getCount() = items.size
override fun getViewTypeCount() = 2
override fun getViewTypeCount() = 3
override fun getItemId(position: Int) = position.toLong()
@ -75,9 +75,10 @@ class TimetableWidgetFactory(
runBlocking {
val student = getStudent(studentId) ?: return@runBlocking
val semester = semesterRepository.getCurrentSemester(student)
lessons = getLessons(student, semester, date)
lastSyncInstant =
timetableRepository.getLastRefreshTimestamp(semester, date, date)
items = createItems(
lessons = getLessons(student, semester, date),
lastSync = timetableRepository.getLastRefreshTimestamp(semester, date, date)
)
if (date == LocalDate.now()) {
updateTodayLastLessonEnd(appWidgetId)
}
@ -101,8 +102,33 @@ class TimetableWidgetFactory(
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) {
val todayLastLessonEnd = lessons.maxOfOrNull { it.end } ?: return
val todayLastLessonEnd = items.filterIsInstance<TimetableWidgetItem.Normal>()
.maxOfOrNull { it.lesson.end } ?: return
val key = getTodayLastLessonEndDateTimeWidgetKey(appWidgetId)
sharedPref.putLong(key, todayLastLessonEnd.epochSecond, true)
}
@ -112,15 +138,15 @@ class TimetableWidgetFactory(
}
override fun getViewAt(position: Int): RemoteViews? {
if (position == lessons.size) {
val synchronizationInstant = lastSyncInstant ?: Instant.MIN
val synchronizationText = getSynchronizationInfoText(synchronizationInstant)
return RemoteViews(context.packageName, R.layout.item_widget_timetable_footer).apply {
setTextViewText(R.id.timetableWidgetSynchronizationTime, synchronizationText)
return when (val item = items.getOrNull(position) ?: return null) {
is TimetableWidgetItem.Normal -> getNormalItemRemoteView(item)
is TimetableWidgetItem.Empty -> getEmptyItemRemoteView(item)
is TimetableWidgetItem.Synchronized -> getSynchronizedItemRemoteView(item)
}
}
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 lessonEndTime = lesson.end.toFormattedString(TIME_FORMAT_STYLE)
@ -130,30 +156,63 @@ class TimetableWidgetFactory(
setTextViewText(R.id.timetableWidgetItemTimeStart, lessonStartTime)
setTextViewText(R.id.timetableWidgetItemTimeFinish, lessonEndTime)
setTextViewText(R.id.timetableWidgetItemSubject, lesson.subject)
setTextViewText(R.id.timetableWidgetItemTeacher, lesson.teacher)
setTextViewText(R.id.timetableWidgetItemDescription, lesson.info)
setOnClickFillInIntent(R.id.timetableWidgetItemContainer, Intent())
}
updateTheme()
clearLessonStyles(remoteViews)
if (lesson.room.isBlank()) {
remoteViews.setViewVisibility(R.id.timetableWidgetItemRoom, GONE)
} else {
remoteViews.setTextViewText(R.id.timetableWidgetItemRoom, lesson.room)
}
when {
lesson.canceled -> applyCancelledLessonStyles(remoteViews)
lesson.changes or lesson.info.isNotBlank() -> applyChangedLessonStyles(
remoteViews, lesson
remoteViews = remoteViews,
lesson = lesson,
)
}
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() {
when (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_YES -> {

View File

@ -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,
}

View 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>

View 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>

View File

@ -51,6 +51,11 @@
<item>Średnia ze średnich z obu semestrów</item>
<item>Średnia wszystkich ocen z całego roku</item>
</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">
<item>Szczęśliwy numerek</item>
<item>Nieprzeczytane wiadomości</item>

View File

@ -185,6 +185,12 @@
<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_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">
<item quantity="one">Zmiana 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_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_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_subjects_without_grades">Pokazuj przedmioty bez ocen</string>
<string name="pref_view_grade_color_scheme">Schemat kolorów ocen</string>

View File

@ -23,6 +23,7 @@
<string name="pref_default_timetable_show_whole_class">no</string>
<string name="pref_default_grade_sorting_mode">alphabetic</string>
<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_optional_arithmetic_average">false</bool>
<string name="pref_default_last_sync_date">0</string>

View File

@ -28,6 +28,7 @@
<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_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_optional_arithmetic_average">optional_arithmetic_average</string>
<string name="pref_key_message_draft">message_draft</string>

View File

@ -123,6 +123,17 @@
<item>all_year</item>
</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">
<item>Lucky number</item>
<item>Unread messages</item>

View File

@ -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_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>
<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">
<item quantity="one">Timetable change</item>
<item quantity="other">Timetable changes</item>
@ -690,6 +694,7 @@
<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_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_subjects_without_grades">Show subjects without grades</string>
<string name="pref_view_grade_color_scheme">Grades color scheme</string>

View File

@ -111,5 +111,13 @@
app:title="@string/pref_view_timetable_show_whole_class"
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>
</PreferenceScreen>