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, start: LocalDate,
end: LocalDate end: LocalDate
): Flow<List<Attendance>> ): 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 @Dao
interface GradeDao : BaseDao<Grade> { 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>> 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 @Singleton
@Dao @Dao
interface NoteDao : BaseDao<Note> { interface NoteDao : BaseDao<Note> {
@Query("SELECT * FROM Notes WHERE student_id = :studentId")
// Disabled notes
@Query("SELECT * FROM Notes WHERE student_id = :studentId AND 1 != 1")
fun loadAll(studentId: Int): Flow<List<Note>> 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"); BLACK("black");
companion object { 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"); GRADE_COLOR("grade_color");
companion object { 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"); ALWAYS_EXPANDED("always");
companion object { 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"); AVERAGE("average");
companion object { 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"); SMALL_OTHER_GROUP("small");
companion object { 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.data.networkBoundResource
import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.pojo.Absent import io.github.wulkanowy.sdk.pojo.Absent
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import io.github.wulkanowy.utils.* import io.github.wulkanowy.utils.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -26,8 +27,8 @@ class AttendanceRepository @Inject constructor(
private val timetableDb: TimetableDao, private val timetableDb: TimetableDao,
private val sdk: Sdk, private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper, private val refreshHelper: AutoRefreshHelper,
private val preferencesRepository: PreferencesRepository
) { ) {
private val saveFetchResultMutex = Mutex() private val saveFetchResultMutex = Mutex()
private val cacheKey = "attendance" private val cacheKey = "attendance"
@ -49,18 +50,38 @@ class AttendanceRepository @Inject constructor(
it.isEmpty() || forceRefresh || isExpired it.isEmpty() || forceRefresh || isExpired
}, },
query = { 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 = { fetch = {
val badAttendanceHidden = preferencesRepository
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.BAD_ATTENDANCE)
val lessons = withContext(Dispatchers.IO) { val lessons = withContext(Dispatchers.IO) {
timetableDb.load( timetableDb.load(
semester.diaryId, semester.studentId, start.monday, end.sunday semester.diaryId, semester.studentId, start.monday, end.sunday
) )
} }
sdk.init(student)
val attendance = sdk.init(student)
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
.getAttendance(start.monday, end.sunday) .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 -> saveFetchResult = { old, new ->
attendanceDb.deleteAll(old uniqueSubtract new) attendanceDb.deleteAll(old uniqueSubtract new)
@ -79,7 +100,15 @@ class AttendanceRepository @Inject constructor(
start: LocalDate, start: LocalDate,
end: LocalDate end: LocalDate
): Flow<List<Attendance>> { ): 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>) { 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.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource import io.github.wulkanowy.data.networkBoundResource
import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import io.github.wulkanowy.utils.* import io.github.wulkanowy.utils.*
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import timber.log.Timber
import java.time.Instant import java.time.Instant
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -24,12 +26,25 @@ class GradeRepository @Inject constructor(
private val gradeSummaryDb: GradeSummaryDao, private val gradeSummaryDb: GradeSummaryDao,
private val sdk: Sdk, private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper, private val refreshHelper: AutoRefreshHelper,
private val preferencesRepository: PreferencesRepository
) { ) {
private val saveFetchResultMutex = Mutex() private val saveFetchResultMutex = Mutex()
private val cacheKey = "grade" 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( fun getGrades(
student: Student, student: Student,
semester: Semester, semester: Semester,
@ -46,16 +61,26 @@ class GradeRepository @Inject constructor(
details.isEmpty() || summaries.isEmpty() || forceRefresh || isExpired details.isEmpty() || summaries.isEmpty() || forceRefresh || isExpired
}, },
query = { query = {
val detailsFlow = gradeDb.loadAll(semester.semesterId, semester.studentId) val detailsFlow = loadGrades(semester.semesterId, semester.studentId)
val summaryFlow = gradeSummaryDb.loadAll(semester.semesterId, semester.studentId) val summaryFlow = gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)
detailsFlow.combine(summaryFlow) { details, summaries -> details to summaries } detailsFlow.combine(summaryFlow) { details, summaries -> details to summaries }
}, },
fetch = { fetch = {
val badGradesHidden = preferencesRepository
.selectedHiddenSettingTiles
.contains(DashboardItem.HiddenSettingTile.BAD_GRADES)
val (details, summary) = sdk.init(student) val (details, summary) = sdk.init(student)
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear) .switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
.getGrades(semester.semesterId) .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) -> saveFetchResult = { (oldDetails, oldSummary), (newDetails, newSummary) ->
refreshGradeDetails(student, oldDetails, newDetails, notify) refreshGradeDetails(student, oldDetails, newDetails, notify)
@ -115,13 +140,13 @@ class GradeRepository @Inject constructor(
} }
fun getUnreadGrades(semester: Semester): Flow<List<Grade>> { 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 } it.filter { grade -> !grade.isRead }
} }
} }
fun getGradesFromDatabase(semester: Semester): Flow<List<Grade>> { 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>> { 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.db.entities.Student
import io.github.wulkanowy.data.networkBoundResource import io.github.wulkanowy.data.networkBoundResource
import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import io.github.wulkanowy.utils.* import io.github.wulkanowy.utils.*
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
@ -17,8 +18,8 @@ class NoteRepository @Inject constructor(
private val noteDb: NoteDao, private val noteDb: NoteDao,
private val sdk: Sdk, private val sdk: Sdk,
private val refreshHelper: AutoRefreshHelper, private val refreshHelper: AutoRefreshHelper,
private val preferencesRepository: PreferencesRepository
) { ) {
private val saveFetchResultMutex = Mutex() private val saveFetchResultMutex = Mutex()
private val cacheKey = "note" private val cacheKey = "note"
@ -30,14 +31,24 @@ class NoteRepository @Inject constructor(
notify: Boolean = false, notify: Boolean = false,
) = networkBoundResource( ) = networkBoundResource(
mutex = saveFetchResultMutex, mutex = saveFetchResultMutex,
isResultEmpty = { true }, isResultEmpty = { it.isEmpty() },
shouldFetch = { shouldFetch = {
val isExpired = refreshHelper.shouldBeRefreshed( val isExpired = refreshHelper.shouldBeRefreshed(
getRefreshKey(cacheKey, semester) getRefreshKey(cacheKey, semester)
) )
it.isEmpty() || forceRefresh || isExpired 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>() }, fetch = { listOf<Note>() },
saveFetchResult = { old, new -> saveFetchResult = { old, new ->
noteDb.deleteAll(old uniqueSubtract new) noteDb.deleteAll(old uniqueSubtract new)
@ -53,7 +64,15 @@ class NoteRepository @Inject constructor(
) )
fun getNotesFromDatabase(student: Student): Flow<List<Note>> { 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) { suspend fun updateNote(note: Note) {

View File

@ -17,6 +17,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.internal.notifyAll
import java.time.Instant import java.time.Instant
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -29,7 +30,6 @@ class PreferencesRepository @Inject constructor(
private val flowSharedPref: FlowSharedPreferences, private val flowSharedPref: FlowSharedPreferences,
private val json: Json, private val json: Json,
) { ) {
val isShowPresent: Boolean val isShowPresent: Boolean
get() = getBoolean( get() = getBoolean(
R.string.pref_key_attendance_present, R.string.pref_key_attendance_present,
@ -267,6 +267,17 @@ class PreferencesRepository @Inject constructor(
selectedDashboardTilesPreference.set(filteredValue) 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>> private val selectedDashboardTilesPreference: Preference<Set<String>>
get() { get() {
val defaultSet = val defaultSet =
@ -276,6 +287,15 @@ class PreferencesRepository @Inject constructor(
return flowSharedPref.getStringSet(prefKey, defaultSet) 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> var dismissedAdminMessageIds: List<Int>
get() = sharedPref.getStringSet(PREF_KEY_ADMIN_DISMISSED_MESSAGE_IDS, emptySet()) get() = sharedPref.getStringSet(PREF_KEY_ADMIN_DISMISSED_MESSAGE_IDS, emptySet())
.orEmpty() .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.Attendance
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.repositories.AttendanceRepository import io.github.wulkanowy.data.repositories.AttendanceRepository
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.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.*
import kotlinx.coroutines.flow.catch
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.DayOfWeek import java.time.DayOfWeek
@ -32,7 +28,6 @@ class AttendancePresenter @Inject constructor(
private val prefRepository: PreferencesRepository, private val prefRepository: PreferencesRepository,
private val analytics: AnalyticsHelper private val analytics: AnalyticsHelper
) : BasePresenter<AttendanceView>(errorHandler, studentRepository) { ) : BasePresenter<AttendanceView>(errorHandler, studentRepository) {
private var initialDate: LocalDate? = null private var initialDate: LocalDate? = null
private var isWeekendHasLessons: Boolean = false private var isWeekendHasLessons: Boolean = false

View File

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

View File

@ -6,6 +6,6 @@ enum class GradeAverageMode(val value: String) {
BOTH_SEMESTERS("both_semesters"); BOTH_SEMESTERS("both_semesters");
companion object { 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 onClickListener: (moreItem: MoreItem) -> Unit = {}
var onLongClickListener: (moreItem: MoreItem) -> Unit = {}
override fun getItemCount() = items.size override fun getItemCount() = items.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemViewHolder(
@ -27,6 +29,10 @@ class MoreAdapter @Inject constructor() : RecyclerView.Adapter<MoreAdapter.ItemV
moreItemImage.setImageResource(item.icon) moreItemImage.setImageResource(item.icon)
root.setOnClickListener { onClickListener(item) } 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.os.Bundle
import android.view.View import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R import io.github.wulkanowy.R
import io.github.wulkanowy.databinding.FragmentMoreBinding import io.github.wulkanowy.databinding.FragmentMoreBinding
import io.github.wulkanowy.ui.base.BaseFragment import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.Destination 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.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.message.MessageFragment import io.github.wulkanowy.ui.modules.message.MessageFragment
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
@ -38,6 +42,7 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
override fun initView() { override fun initView() {
moreAdapter.onClickListener = presenter::onItemSelected moreAdapter.onClickListener = presenter::onItemSelected
moreAdapter.onLongClickListener = presenter::onItemHold
with(binding.moreRecycler) { with(binding.moreRecycler) {
layoutManager = LinearLayoutManager(context) layoutManager = LinearLayoutManager(context)
@ -73,4 +78,28 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>(R.layout.fragment_more),
presenter.onDetachView() presenter.onDetachView()
super.onDestroyView() 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.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.Destination import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
import okhttp3.internal.notify
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
class MorePresenter @Inject constructor( class MorePresenter @Inject constructor(
errorHandler: ErrorHandler, errorHandler: ErrorHandler,
studentRepository: StudentRepository, studentRepository: StudentRepository,
preferencesRepository: PreferencesRepository private val preferencesRepository: PreferencesRepository
) : BasePresenter<MoreView>(errorHandler, studentRepository) { ) : BasePresenter<MoreView>(errorHandler, studentRepository) {
private val moreAppMenuItem = preferencesRepository.appMenuItemOrder private val moreAppMenuItem = preferencesRepository.appMenuItemOrder
.sortedBy { it.order } .sortedBy { it.order }
.drop(4) .drop(4)
private val selectedHiddenSettingsTiles = preferencesRepository.selectedHiddenSettingTiles
override fun onAttachView(view: MoreView) { override fun onAttachView(view: MoreView) {
super.onAttachView(view) super.onAttachView(view)
view.initView() view.initView()
@ -32,6 +36,23 @@ class MorePresenter @Inject constructor(
view?.openView(moreItem.destination) 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() { fun onViewReselected() {
Timber.i("More view is reselected") Timber.i("More view is reselected")
view?.popView(2) 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.base.BaseView
import io.github.wulkanowy.ui.modules.Destination import io.github.wulkanowy.ui.modules.Destination
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
interface MoreView : BaseView { interface MoreView : BaseView {
@ -12,4 +13,8 @@ interface MoreView : BaseView {
fun popView(depth: Int) fun popView(depth: Int)
fun openView(destination: Destination) fun openView(destination: Destination)
fun showHiddenSettings(data: List<DashboardItem.HiddenSettingTile>)
fun restartApp()
} }

View File

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

View File

@ -784,6 +784,7 @@
<string name="pref_grades_appearance_header">Známky</string> <string name="pref_grades_appearance_header">Známky</string>
<string name="pref_dashboard_appearance_header">Domů</string> <string name="pref_dashboard_appearance_header">Domů</string>
<string name="pref_dashboard_appearance_tiles_title">Viditelnost dlaždic</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_attendance_appearance_view">Frekvence</string>
<string name="pref_timetable_appearance_view">Plán lekce</string> <string name="pref_timetable_appearance_view">Plán lekce</string>
<string name="pref_grades_advanced_header">Známky</string> <string name="pref_grades_advanced_header">Známky</string>

View File

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

View File

@ -694,6 +694,7 @@
<string name="pref_grades_appearance_header">Grades</string> <string name="pref_grades_appearance_header">Grades</string>
<string name="pref_dashboard_appearance_header">Dashboard</string> <string name="pref_dashboard_appearance_header">Dashboard</string>
<string name="pref_dashboard_appearance_tiles_title">Tiles visibility</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_attendance_appearance_view">Attendance</string>
<string name="pref_timetable_appearance_view">Timetable</string> <string name="pref_timetable_appearance_view">Timetable</string>
<string name="pref_grades_advanced_header">Grades</string> <string name="pref_grades_advanced_header">Grades</string>

View File

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

View File

@ -694,6 +694,7 @@
<string name="pref_grades_appearance_header">Noten</string> <string name="pref_grades_appearance_header">Noten</string>
<string name="pref_dashboard_appearance_header">Dashboard</string> <string name="pref_dashboard_appearance_header">Dashboard</string>
<string name="pref_dashboard_appearance_tiles_title">Sichtbarkeit der Kacheln</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_attendance_appearance_view">Schulbesuch</string>
<string name="pref_timetable_appearance_view">Stundenplan</string> <string name="pref_timetable_appearance_view">Stundenplan</string>
<string name="pref_grades_advanced_header">Noten</string> <string name="pref_grades_advanced_header">Noten</string>

View File

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

View File

@ -694,6 +694,7 @@
<string name="pref_grades_appearance_header">Grades</string> <string name="pref_grades_appearance_header">Grades</string>
<string name="pref_dashboard_appearance_header">Dashboard</string> <string name="pref_dashboard_appearance_header">Dashboard</string>
<string name="pref_dashboard_appearance_tiles_title">Tiles visibility</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_attendance_appearance_view">Attendance</string>
<string name="pref_timetable_appearance_view">Timetable</string> <string name="pref_timetable_appearance_view">Timetable</string>
<string name="pref_grades_advanced_header">Grades</string> <string name="pref_grades_advanced_header">Grades</string>

View File

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

View File

@ -694,6 +694,7 @@
<string name="pref_grades_appearance_header">Grades</string> <string name="pref_grades_appearance_header">Grades</string>
<string name="pref_dashboard_appearance_header">Dashboard</string> <string name="pref_dashboard_appearance_header">Dashboard</string>
<string name="pref_dashboard_appearance_tiles_title">Tiles visibility</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_attendance_appearance_view">Attendance</string>
<string name="pref_timetable_appearance_view">Timetable</string> <string name="pref_timetable_appearance_view">Timetable</string>
<string name="pref_grades_advanced_header">Grades</string> <string name="pref_grades_advanced_header">Grades</string>

View File

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

View File

@ -784,6 +784,7 @@
<string name="pref_grades_appearance_header">Oceny</string> <string name="pref_grades_appearance_header">Oceny</string>
<string name="pref_dashboard_appearance_header">Start</string> <string name="pref_dashboard_appearance_header">Start</string>
<string name="pref_dashboard_appearance_tiles_title">Widoczność kafelków</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_attendance_appearance_view">Frekwencja</string>
<string name="pref_timetable_appearance_view">Plan lekcji</string> <string name="pref_timetable_appearance_view">Plan lekcji</string>
<string name="pref_grades_advanced_header">Oceny</string> <string name="pref_grades_advanced_header">Oceny</string>

View File

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

View File

@ -784,6 +784,7 @@
<string name="pref_grades_appearance_header">Оценки</string> <string name="pref_grades_appearance_header">Оценки</string>
<string name="pref_dashboard_appearance_header">Главная</string> <string name="pref_dashboard_appearance_header">Главная</string>
<string name="pref_dashboard_appearance_tiles_title">Видимость плиток</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_attendance_appearance_view">Посещаемость</string>
<string name="pref_timetable_appearance_view">Расписание</string> <string name="pref_timetable_appearance_view">Расписание</string>
<string name="pref_grades_advanced_header">Оценки</string> <string name="pref_grades_advanced_header">Оценки</string>

View File

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

View File

@ -784,6 +784,7 @@
<string name="pref_grades_appearance_header">Známky</string> <string name="pref_grades_appearance_header">Známky</string>
<string name="pref_dashboard_appearance_header">Domov</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_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_attendance_appearance_view">Frekvencia</string>
<string name="pref_timetable_appearance_view">Plán lekcie</string> <string name="pref_timetable_appearance_view">Plán lekcie</string>
<string name="pref_grades_advanced_header">Známky</string> <string name="pref_grades_advanced_header">Známky</string>

View File

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

View File

@ -784,6 +784,7 @@
<string name="pref_grades_appearance_header">Оцінки</string> <string name="pref_grades_appearance_header">Оцінки</string>
<string name="pref_dashboard_appearance_header">Головна</string> <string name="pref_dashboard_appearance_header">Головна</string>
<string name="pref_dashboard_appearance_tiles_title">Видимість плиток</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_attendance_appearance_view">Відвідуваність</string>
<string name="pref_timetable_appearance_view">Розклад</string> <string name="pref_timetable_appearance_view">Розклад</string>
<string name="pref_grades_advanced_header">Оцінки</string> <string name="pref_grades_advanced_header">Оцінки</string>

View File

@ -36,6 +36,9 @@
<item>GRADES</item> <item>GRADES</item>
<item>ANNOUNCEMENTS</item> <item>ANNOUNCEMENTS</item>
</string-array> </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_enabled">false</bool>
<bool name="pref_default_ads_consent_data_processing">false</bool> <bool name="pref_default_ads_consent_data_processing">false</bool>
<bool name="pref_default_incognito_mode">false</bool> <bool name="pref_default_incognito_mode">false</bool>

View File

@ -156,4 +156,15 @@
<item>EXAMS</item> <item>EXAMS</item>
<item>CONFERENCES</item> <item>CONFERENCES</item>
</string-array> </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> </resources>

View File

@ -773,6 +773,7 @@
<string name="pref_grades_appearance_header">Grades</string> <string name="pref_grades_appearance_header">Grades</string>
<string name="pref_dashboard_appearance_header">Dashboard</string> <string name="pref_dashboard_appearance_header">Dashboard</string>
<string name="pref_dashboard_appearance_tiles_title">Tiles visibility</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_attendance_appearance_view">Attendance</string>
<string name="pref_timetable_appearance_view">Timetable</string> <string name="pref_timetable_appearance_view">Timetable</string>
<string name="pref_grades_advanced_header">Grades</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-gradle-plugin:1.9.20-Beta2"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" 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.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.dagger:hilt-android-gradle-plugin:$hilt_version"
classpath 'com.google.gms:google-services:4.4.0' classpath 'com.google.gms:google-services:4.4.0'
classpath 'com.huawei.agconnect:agcp:1.9.1.301' classpath 'com.huawei.agconnect:agcp:1.9.1.301'