add: hidden settings. almost full customization.

This commit is contained in:
sadorowo 2024-01-02 20:31:36 +01:00
parent d3ff6682ca
commit d0d3b11662
41 changed files with 276 additions and 36 deletions

View File

@ -18,4 +18,13 @@ interface AttendanceDao : BaseDao<Attendance> {
start: LocalDate,
end: LocalDate
): Flow<List<Attendance>>
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :start AND date <= :end" +
" AND (presence OR excused)")
fun loadAllCensored(
diaryId: Int,
studentId: Int,
start: LocalDate,
end: LocalDate
): Flow<List<Attendance>>
}

View File

@ -10,6 +10,10 @@ import javax.inject.Singleton
@Dao
interface GradeDao : BaseDao<Grade> {
@Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId AND entry NOT IN ('1', '1+', '2', '2-', '2+')")
@Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId")
fun loadAll(semesterId: Int, studentId: Int): Flow<List<Grade>>
@Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId " +
"AND entry NOT IN ('1', '1+', '2', '2+', '2-')")
fun loadAllCensored(semesterId: Int, studentId: Int): Flow<List<Grade>>
}

View File

@ -9,8 +9,9 @@ import javax.inject.Singleton
@Singleton
@Dao
interface NoteDao : BaseDao<Note> {
// Disabled notes
@Query("SELECT * FROM Notes WHERE student_id = :studentId AND 1 != 1")
@Query("SELECT * FROM Notes WHERE student_id = :studentId")
fun loadAll(studentId: Int): Flow<List<Note>>
@Query("SELECT * FROM Notes WHERE student_id = :studentId AND 1 != 1")
fun pretendLoadingAll(studentId: Int): Flow<List<Note>>
}

View File

@ -7,6 +7,6 @@ enum class AppTheme(val value: String) {
BLACK("black");
companion object {
fun getByValue(value: String) = values().find { it.value == value } ?: LIGHT
fun getByValue(value: String) = entries.find { it.value == value } ?: LIGHT
}
}
}

View File

@ -8,6 +8,6 @@ enum class GradeColorTheme(val value: String) : Serializable {
GRADE_COLOR("grade_color");
companion object {
fun getByValue(value: String) = values().find { it.value == value } ?: VULCAN
fun getByValue(value: String) = entries.find { it.value == value } ?: VULCAN
}
}
}

View File

@ -6,6 +6,6 @@ enum class GradeExpandMode(val value: String) {
ALWAYS_EXPANDED("always");
companion object {
fun getByValue(value: String) = values().find { it.value == value } ?: ONE
fun getByValue(value: String) = entries.find { it.value == value } ?: ONE
}
}
}

View File

@ -6,6 +6,6 @@ enum class GradeSortingMode(val value: String) {
AVERAGE("average");
companion object {
fun getByValue(value: String) = values().find { it.value == value } ?: ALPHABETIC
fun getByValue(value: String) = entries.find { it.value == value } ?: ALPHABETIC
}
}

View File

@ -6,6 +6,6 @@ enum class TimetableMode(val value: String) {
SMALL_OTHER_GROUP("small");
companion object {
fun getByValue(value: String) = values().find { it.value == value } ?: ONLY_CURRENT_GROUP
fun getByValue(value: String) = entries.find { it.value == value } ?: ONLY_CURRENT_GROUP
}
}
}

View File

@ -9,6 +9,7 @@ import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.Absent
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import io.github.wulkanowy.utils.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
@ -26,8 +27,8 @@ class AttendanceRepository @Inject constructor(
private val timetableDb: TimetableDao,
private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
private val preferencesRepository: PreferencesRepository
) {
private val saveFetchResultMutex = Mutex()
private val cacheKey = "attendance"
@ -49,18 +50,38 @@ class AttendanceRepository @Inject constructor(
it.isEmpty() || forceRefresh || isExpired
},
query = {
attendanceDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday)
val badAttendanceHidden = preferencesRepository
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.BAD_ATTENDANCE)
if (badAttendanceHidden) {
attendanceDb.loadAllCensored(semester.diaryId, semester.studentId, start, end)
} else {
attendanceDb.loadAll(semester.diaryId, semester.studentId, start, end)
}
},
fetch = {
val badAttendanceHidden = preferencesRepository
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.BAD_ATTENDANCE)
val lessons = withContext(Dispatchers.IO) {
timetableDb.load(
semester.diaryId, semester.studentId, start.monday, end.sunday
)
}
sdk.init(student)
val attendance = sdk.init(student)
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
.getAttendance(start.monday, end.sunday)
.mapToEntities(semester, lessons)
val censoredAttendance = if (badAttendanceHidden) {
attendance.filter { it.presence || it.excused }
} else {
attendance
}
censoredAttendance.mapToEntities(semester, lessons)
},
saveFetchResult = { old, new ->
attendanceDb.deleteAll(old uniqueSubtract new)
@ -79,7 +100,15 @@ class AttendanceRepository @Inject constructor(
start: LocalDate,
end: LocalDate
): Flow<List<Attendance>> {
return attendanceDb.loadAll(semester.diaryId, semester.studentId, start, end)
val badAttendanceHidden = preferencesRepository
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.BAD_ATTENDANCE)
return if (badAttendanceHidden) {
attendanceDb.loadAllCensored(semester.diaryId, semester.studentId, start, end)
} else {
attendanceDb.loadAll(semester.diaryId, semester.studentId, start, end)
}
}
suspend fun updateTimetable(timetable: List<Attendance>) {

View File

@ -9,11 +9,13 @@ import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import io.github.wulkanowy.utils.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.sync.Mutex
import timber.log.Timber
import java.time.Instant
import javax.inject.Inject
import javax.inject.Singleton
@ -24,12 +26,25 @@ class GradeRepository @Inject constructor(
private val gradeSummaryDb: GradeSummaryDao,
private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
private val preferencesRepository: PreferencesRepository
) {
private val saveFetchResultMutex = Mutex()
private val cacheKey = "grade"
private fun loadGrades(semesterId: Int, studentId: Int): Flow<List<Grade>> {
val badGradesHidden = preferencesRepository
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.BAD_GRADES)
Timber.i("Load grades for semester $semesterId student $studentId / $badGradesHidden")
return if (badGradesHidden) {
gradeDb.loadAllCensored(semesterId, studentId)
} else {
gradeDb.loadAll(semesterId, studentId)
}
}
fun getGrades(
student: Student,
semester: Semester,
@ -46,16 +61,26 @@ class GradeRepository @Inject constructor(
details.isEmpty() || summaries.isEmpty() || forceRefresh || isExpired
},
query = {
val detailsFlow = gradeDb.loadAll(semester.semesterId, semester.studentId)
val detailsFlow = loadGrades(semester.semesterId, semester.studentId)
val summaryFlow = gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)
detailsFlow.combine(summaryFlow) { details, summaries -> details to summaries }
},
fetch = {
val badGradesHidden = preferencesRepository
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.BAD_GRADES)
val (details, summary) = sdk.init(student)
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
.getGrades(semester.semesterId)
details.mapToEntities(semester) to summary.mapToEntities(semester)
val censoredDetails = if (badGradesHidden) {
details.filter { !listOf("1", "1+", "2", "2+", "2-").contains(it.entry) }
} else {
details
}
censoredDetails.mapToEntities(semester) to summary.mapToEntities(semester)
},
saveFetchResult = { (oldDetails, oldSummary), (newDetails, newSummary) ->
refreshGradeDetails(student, oldDetails, newDetails, notify)
@ -115,13 +140,13 @@ class GradeRepository @Inject constructor(
}
fun getUnreadGrades(semester: Semester): Flow<List<Grade>> {
return gradeDb.loadAll(semester.semesterId, semester.studentId).map {
return loadGrades(semester.semesterId, semester.studentId).map {
it.filter { grade -> !grade.isRead }
}
}
fun getGradesFromDatabase(semester: Semester): Flow<List<Grade>> {
return gradeDb.loadAll(semester.semesterId, semester.studentId)
return loadGrades(semester.semesterId, semester.studentId)
}
fun getGradesPredictedFromDatabase(semester: Semester): Flow<List<GradeSummary>> {

View File

@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.networkBoundResource
import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import io.github.wulkanowy.utils.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.sync.Mutex
@ -17,8 +18,8 @@ class NoteRepository @Inject constructor(
private val noteDb: NoteDao,
private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper,
private val preferencesRepository: PreferencesRepository
) {
private val saveFetchResultMutex = Mutex()
private val cacheKey = "note"
@ -30,14 +31,24 @@ class NoteRepository @Inject constructor(
notify: Boolean = false,
) = networkBoundResource(
mutex = saveFetchResultMutex,
isResultEmpty = { true },
isResultEmpty = { it.isEmpty() },
shouldFetch = {
val isExpired = refreshHelper.shouldBeRefreshed(
getRefreshKey(cacheKey, semester)
)
it.isEmpty() || forceRefresh || isExpired
},
query = { noteDb.loadAll(student.studentId) },
query = {
val notesHidden = preferencesRepository
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.NOTES)
if (notesHidden) {
noteDb.pretendLoadingAll(student.studentId)
} else {
noteDb.loadAll(student.studentId)
}
},
fetch = { listOf<Note>() },
saveFetchResult = { old, new ->
noteDb.deleteAll(old uniqueSubtract new)
@ -53,7 +64,15 @@ class NoteRepository @Inject constructor(
)
fun getNotesFromDatabase(student: Student): Flow<List<Note>> {
return noteDb.loadAll(student.studentId)
val notesHidden = preferencesRepository
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.NOTES)
return if (notesHidden) {
noteDb.pretendLoadingAll(student.studentId)
} else {
noteDb.loadAll(student.studentId)
}
}
suspend fun updateNote(note: Note) {

View File

@ -17,6 +17,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import okhttp3.internal.notifyAll
import java.time.Instant
import java.util.*
import javax.inject.Inject
@ -29,7 +30,6 @@ class PreferencesRepository @Inject constructor(
private val flowSharedPref: FlowSharedPreferences,
private val json: Json,
) {
val isShowPresent: Boolean
get() = getBoolean(
R.string.pref_key_attendance_present,
@ -267,6 +267,17 @@ class PreferencesRepository @Inject constructor(
selectedDashboardTilesPreference.set(filteredValue)
}
var selectedHiddenSettingTiles: List<DashboardItem.HiddenSettingTile>
get() = selectedHiddenSettingTilesPreference.get()
.map { DashboardItem.HiddenSettingTile.valueOf(it) }
set(value) {
val filteredValue = value
.map { it.name }
.toSet()
selectedHiddenSettingTilesPreference.set(filteredValue)
}
private val selectedDashboardTilesPreference: Preference<Set<String>>
get() {
val defaultSet =
@ -276,6 +287,15 @@ class PreferencesRepository @Inject constructor(
return flowSharedPref.getStringSet(prefKey, defaultSet)
}
private val selectedHiddenSettingTilesPreference: Preference<Set<String>>
get() {
val defaultSet =
context.resources.getStringArray(R.array.pref_default_hidden_settings_tiles).toSet()
val prefKey = "hidden_settings_tiles"
return flowSharedPref.getStringSet(prefKey, defaultSet)
}
var dismissedAdminMessageIds: List<Int>
get() = sharedPref.getStringSet(PREF_KEY_ADMIN_DISMISSED_MESSAGE_IDS, emptySet())
.orEmpty()

View File

@ -5,17 +5,13 @@ import io.github.wulkanowy.data.*
import io.github.wulkanowy.data.db.entities.Attendance
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.repositories.AttendanceRepository
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 kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onEach
import timber.log.Timber
import java.time.DayOfWeek
@ -32,7 +28,6 @@ class AttendancePresenter @Inject constructor(
private val prefRepository: PreferencesRepository,
private val analytics: AnalyticsHelper
) : BasePresenter<AttendanceView>(errorHandler, studentRepository) {
private var initialDate: LocalDate? = null
private var isWeekendHasLessons: Boolean = false

View File

@ -147,6 +147,12 @@ sealed class DashboardItem(val type: Type) {
EXAMS,
CONFERENCES,
}
enum class HiddenSettingTile {
BAD_GRADES,
BAD_ATTENDANCE,
NOTES
}
}
fun DashboardItem.Tile.toDashboardItemType() = when (this) {

View File

@ -6,6 +6,6 @@ enum class GradeAverageMode(val value: String) {
BOTH_SEMESTERS("both_semesters");
companion object {
fun getByValue(value: String) = values().firstOrNull { it.value == value } ?: ONE_SEMESTER
fun getByValue(value: String) = entries.firstOrNull { it.value == value } ?: ONE_SEMESTER
}
}

View File

@ -12,6 +12,8 @@ class MoreAdapter @Inject constructor() : RecyclerView.Adapter<MoreAdapter.ItemV
var onClickListener: (moreItem: MoreItem) -> Unit = {}
var onLongClickListener: (moreItem: MoreItem) -> Unit = {}
override fun getItemCount() = items.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
@ -27,6 +29,10 @@ class MoreAdapter @Inject constructor() : RecyclerView.Adapter<MoreAdapter.ItemV
moreItemImage.setImageResource(item.icon)
root.setOnClickListener { onClickListener(item) }
root.setOnLongClickListener {
onLongClickListener(item)
true
}
}
}

View File

@ -2,15 +2,19 @@ package io.github.wulkanowy.ui.modules.more
import android.os.Bundle
import android.view.View
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.databinding.FragmentMoreBinding
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.message.MessageFragment
import timber.log.Timber
import javax.inject.Inject
@AndroidEntryPoint
@ -38,6 +42,7 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
override fun initView() {
moreAdapter.onClickListener = presenter::onItemSelected
moreAdapter.onLongClickListener = presenter::onItemHold
with(binding.moreRecycler) {
layoutManager = LinearLayoutManager(context)
@ -73,4 +78,28 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
presenter.onDetachView()
super.onDestroyView()
}
override fun showHiddenSettings(data: List<DashboardItem.HiddenSettingTile>) {
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 } }
MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.pref_hidden_settings_title)
.setMultiChoiceItems(entries, selectedItemsState.toBooleanArray()) { _, _, _ -> }
.setPositiveButton(android.R.string.ok) { dialog, _ ->
val selectedState = (dialog as AlertDialog).listView.checkedItemPositions
val selectedValues = values.filterIndexed { index, _ -> selectedState[index] }
Timber.i("Selected hidden settings: $selectedValues")
presenter.onHiddenSettingsSelected(selectedValues)
}
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
}
override fun restartApp() {
startActivity(MainActivity.getStartIntent(requireContext()))
requireActivity().finishAffinity()
}
}

View File

@ -6,19 +6,23 @@ import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import okhttp3.internal.notify
import timber.log.Timber
import javax.inject.Inject
class MorePresenter @Inject constructor(
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
preferencesRepository: PreferencesRepository
private val preferencesRepository: PreferencesRepository
) : BasePresenter<MoreView>(errorHandler, studentRepository) {
private val moreAppMenuItem = preferencesRepository.appMenuItemOrder
.sortedBy { it.order }
.drop(4)
private val selectedHiddenSettingsTiles = preferencesRepository.selectedHiddenSettingTiles
override fun onAttachView(view: MoreView) {
super.onAttachView(view)
view.initView()
@ -32,6 +36,23 @@ class MorePresenter @Inject constructor(
view?.openView(moreItem.destination)
}
fun onItemHold(moreItem: MoreItem) {
Timber.i("More item hold")
when (moreItem.destination) {
Destination.Settings -> view?.showHiddenSettings(selectedHiddenSettingsTiles)
else -> return
}
}
fun onHiddenSettingsSelected(selectedItems: List<String>) {
preferencesRepository.selectedHiddenSettingTiles = selectedItems.map {
DashboardItem.HiddenSettingTile.valueOf(it)
}
view?.restartApp()
}
fun onViewReselected() {
Timber.i("More view is reselected")
view?.popView(2)

View File

@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.more
import io.github.wulkanowy.ui.base.BaseView
import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
interface MoreView : BaseView {
@ -12,4 +13,8 @@ interface MoreView : BaseView {
fun popView(depth: Int)
fun openView(destination: Destination)
fun showHiddenSettings(data: List<DashboardItem.HiddenSettingTile>)
fun restartApp()
}

View File

@ -67,4 +67,10 @@
<item>Zkoušky</item>
<item>Setkání</item>
</string-array>
<string-array name="hidden_settings_entries">
<item>Špatné hodnocení</item>
<item>Špatná účast</item>
<item>Poznámky</item>
</string-array>
</resources>

View File

@ -784,6 +784,7 @@
<string name="pref_grades_appearance_header">Známky</string>
<string name="pref_dashboard_appearance_header">Domů</string>
<string name="pref_dashboard_appearance_tiles_title">Viditelnost dlaždic</string>
<string name="pref_hidden_settings_title">Tajná nastavení</string>
<string name="pref_attendance_appearance_view">Frekvence</string>
<string name="pref_timetable_appearance_view">Plán lekce</string>
<string name="pref_grades_advanced_header">Známky</string>

View File

@ -67,4 +67,9 @@
<item>Exams</item>
<item>Conferences</item>
</string-array>
<string-array name="hidden_settings_entries">
<item>Bad grades</item>
<item>Bad attendance</item>
<item>Notes</item>
</string-array>
</resources>

View File

@ -694,6 +694,7 @@
<string name="pref_grades_appearance_header">Grades</string>
<string name="pref_dashboard_appearance_header">Dashboard</string>
<string name="pref_dashboard_appearance_tiles_title">Tiles visibility</string>
<string name="pref_hidden_settings_title">Hidden settings</string>
<string name="pref_attendance_appearance_view">Attendance</string>
<string name="pref_timetable_appearance_view">Timetable</string>
<string name="pref_grades_advanced_header">Grades</string>

View File

@ -67,4 +67,9 @@
<item>Prüfungen</item>
<item>Sitzungen</item>
</string-array>
<string-array name="hidden_settings_entries">
<item>Schlechte Noten</item>
<item>Schlechte Anwesenheit</item>
<item>Notizen</item>
</string-array>
</resources>

View File

@ -694,6 +694,7 @@
<string name="pref_grades_appearance_header">Noten</string>
<string name="pref_dashboard_appearance_header">Dashboard</string>
<string name="pref_dashboard_appearance_tiles_title">Sichtbarkeit der Kacheln</string>
<string name="pref_hidden_settings_title">Geheime Einstellungen</string>
<string name="pref_attendance_appearance_view">Schulbesuch</string>
<string name="pref_timetable_appearance_view">Stundenplan</string>
<string name="pref_grades_advanced_header">Noten</string>

View File

@ -67,4 +67,9 @@
<item>Exams</item>
<item>Conferences</item>
</string-array>
<string-array name="hidden_settings_entries">
<item>Bad grades</item>
<item>Bad attendance</item>
<item>Notes</item>
</string-array>
</resources>

View File

@ -694,6 +694,7 @@
<string name="pref_grades_appearance_header">Grades</string>
<string name="pref_dashboard_appearance_header">Dashboard</string>
<string name="pref_dashboard_appearance_tiles_title">Tiles visibility</string>
<string name="pref_hidden_settings_title">Hidden settings</string>
<string name="pref_attendance_appearance_view">Attendance</string>
<string name="pref_timetable_appearance_view">Timetable</string>
<string name="pref_grades_advanced_header">Grades</string>

View File

@ -67,4 +67,9 @@
<item>Exams</item>
<item>Conferences</item>
</string-array>
<string-array name="hidden_settings_entries">
<item>Bad grades</item>
<item>Bad attendance</item>
<item>Notes</item>
</string-array>
</resources>

View File

@ -694,6 +694,7 @@
<string name="pref_grades_appearance_header">Grades</string>
<string name="pref_dashboard_appearance_header">Dashboard</string>
<string name="pref_dashboard_appearance_tiles_title">Tiles visibility</string>
<string name="pref_hidden_settings_title">Hidden settings</string>
<string name="pref_attendance_appearance_view">Attendance</string>
<string name="pref_timetable_appearance_view">Timetable</string>
<string name="pref_grades_advanced_header">Grades</string>

View File

@ -67,4 +67,9 @@
<item>Sprawdziany</item>
<item>Zebrania</item>
</string-array>
<string-array name="hidden_settings_entries">
<item>Słabe oceny</item>
<item>Słaba frekwencja</item>
<item>Uwagi</item>
</string-array>
</resources>

View File

@ -784,6 +784,7 @@
<string name="pref_grades_appearance_header">Oceny</string>
<string name="pref_dashboard_appearance_header">Start</string>
<string name="pref_dashboard_appearance_tiles_title">Widoczność kafelków</string>
<string name="pref_hidden_settings_title">Sekretne ustawienia</string>
<string name="pref_attendance_appearance_view">Frekwencja</string>
<string name="pref_timetable_appearance_view">Plan lekcji</string>
<string name="pref_grades_advanced_header">Oceny</string>

View File

@ -67,4 +67,9 @@
<item>Тесты</item>
<item>Встречи</item>
</string-array>
<string-array name="hidden_settings_entries">
<item>Плохие оценки</item>
<item>Плохая посещаемость</item>
<item>Примечания</item>
</string-array>
</resources>

View File

@ -784,6 +784,7 @@
<string name="pref_grades_appearance_header">Оценки</string>
<string name="pref_dashboard_appearance_header">Главная</string>
<string name="pref_dashboard_appearance_tiles_title">Видимость плиток</string>
<string name="pref_hidden_settings_title">Секретные настройки</string>
<string name="pref_attendance_appearance_view">Посещаемость</string>
<string name="pref_timetable_appearance_view">Расписание</string>
<string name="pref_grades_advanced_header">Оценки</string>

View File

@ -67,4 +67,9 @@
<item>Skúšky</item>
<item>Stretnutie</item>
</string-array>
<string-array name="hidden_settings_entries">
<item>Zlé známky</item>
<item>Zlá účasť</item>
<item>Poznámky</item>
</string-array>
</resources>

View File

@ -784,6 +784,7 @@
<string name="pref_grades_appearance_header">Známky</string>
<string name="pref_dashboard_appearance_header">Domov</string>
<string name="pref_dashboard_appearance_tiles_title">Viditeľnosť dlaždíc</string>
<string name="pref_hidden_settings_title">Tajné nastavenia</string>
<string name="pref_attendance_appearance_view">Frekvencia</string>
<string name="pref_timetable_appearance_view">Plán lekcie</string>
<string name="pref_grades_advanced_header">Známky</string>

View File

@ -67,4 +67,9 @@
<item>Тести</item>
<item>Зустрічі</item>
</string-array>
<string-array name="hidden_settings_entries">
<item>Погані оцінки</item>
<item>Погана відвідуваність</item>
<item>Примітки</item>
</string-array>
</resources>

View File

@ -784,6 +784,7 @@
<string name="pref_grades_appearance_header">Оцінки</string>
<string name="pref_dashboard_appearance_header">Головна</string>
<string name="pref_dashboard_appearance_tiles_title">Видимість плиток</string>
<string name="pref_hidden_settings_title">Секретні налаштування</string>
<string name="pref_attendance_appearance_view">Відвідуваність</string>
<string name="pref_timetable_appearance_view">Розклад</string>
<string name="pref_grades_advanced_header">Оцінки</string>

View File

@ -36,6 +36,9 @@
<item>GRADES</item>
<item>ANNOUNCEMENTS</item>
</string-array>
<string-array name="pref_default_hidden_settings_tiles">
<item>BAD_GRADES</item>
</string-array>
<bool name="pref_default_ads_enabled">false</bool>
<bool name="pref_default_ads_consent_data_processing">false</bool>
<bool name="pref_default_incognito_mode">false</bool>

View File

@ -156,4 +156,15 @@
<item>EXAMS</item>
<item>CONFERENCES</item>
</string-array>
<string-array name="hidden_settings_entries">
<item>Bad grades</item>
<item>Bad attendance</item>
<item>Notes</item>
</string-array>
<string-array name="hidden_settings_values" translatable="false">
<item>BAD_GRADES</item>
<item>BAD_ATTENDANCE</item>
<item>NOTES</item>
</string-array>
</resources>

View File

@ -773,6 +773,7 @@
<string name="pref_grades_appearance_header">Grades</string>
<string name="pref_dashboard_appearance_header">Dashboard</string>
<string name="pref_dashboard_appearance_tiles_title">Tiles visibility</string>
<string name="pref_hidden_settings_title">Hidden settings</string>
<string name="pref_attendance_appearance_view">Attendance</string>
<string name="pref_timetable_appearance_view">Timetable</string>
<string name="pref_grades_advanced_header">Grades</string>

View File

@ -14,7 +14,8 @@ buildscript {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20-Beta2"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:$kotlin_version-1.0.15"
classpath 'com.android.tools.build:gradle:8.2.0'
// NOTE: Version downgraded due to https://github.com/appwrite/sdk-for-android/issues/42.
classpath 'com.android.tools.build:gradle:8.1.1'
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
classpath 'com.google.gms:google-services:4.4.0'
classpath 'com.huawei.agconnect:agcp:1.9.1.301'