From 2d6cf50ca77f58705ff982920fac1c31eac6683e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Fri, 9 Apr 2021 15:30:58 +0200 Subject: [PATCH 01/15] [Agenda] Refactor agenda UI code. --- .../edziennik/data/db/entity/Event.kt | 9 +- .../ui/modules/agenda/AgendaFragment.kt | 195 +++----------- .../modules/agenda/AgendaFragmentDefault.kt | 142 ++++++++++ .../edziennik/ui/modules/agenda/BaseEvent.kt | 61 +++++ .../ui/modules/agenda/event/AgendaEvent.kt | 19 ++ .../agenda/event/AgendaEventRenderer.kt | 37 +++ .../lessonchange/LessonChangeCounter.kt | 19 -- .../lessonchange/LessonChangeEvent.java | 243 ------------------ .../lessonchange/LessonChangeEventRenderer.kt | 21 -- .../lessonchanges/LessonChangesEvent.kt | 21 ++ .../LessonChangesEventRenderer.kt | 21 ++ .../teacherabsence/TeacherAbsenceCounter.kt | 19 -- .../teacherabsence/TeacherAbsenceEvent.kt | 199 ++------------ .../TeacherAbsenceEventRenderer.kt | 22 +- .../edziennik/utils/models/Date.java | 28 +- app/src/main/res/layout/agenda_event_item.xml | 37 +++ ...tem.xml => agenda_lesson_changes_item.xml} | 16 +- ...em.xml => agenda_teacher_absence_item.xml} | 16 +- ...on_change.xml => agenda_wrapped_event.xml} | 10 +- ....xml => agenda_wrapped_lesson_changes.xml} | 4 +- .../layout/agenda_wrapped_teacher_absence.xml | 14 + app/src/main/res/layout/dialog_day.xml | 4 +- 22 files changed, 452 insertions(+), 705 deletions(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/BaseEvent.kt create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEvent.kt create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchange/LessonChangeCounter.kt delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchange/LessonChangeEvent.java delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchange/LessonChangeEventRenderer.kt create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEvent.kt create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceCounter.kt create mode 100644 app/src/main/res/layout/agenda_event_item.xml rename app/src/main/res/layout/{row_lesson_change_item.xml => agenda_lesson_changes_item.xml} (72%) rename app/src/main/res/layout/{row_teacher_absence_item.xml => agenda_teacher_absence_item.xml} (72%) rename app/src/main/res/layout/{agenda_event_lesson_change.xml => agenda_wrapped_event.xml} (77%) rename app/src/main/res/layout/{agenda_event_teacher_absence.xml => agenda_wrapped_lesson_changes.xml} (86%) create mode 100644 app/src/main/res/layout/agenda_wrapped_teacher_absence.xml diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Event.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Event.kt index 0dcaa83e..a3f44585 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Event.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Event.kt @@ -116,14 +116,7 @@ open class Event( var showAsUnseen: Boolean? = null val startTimeCalendar: Calendar - get() = Calendar.getInstance().also { it.set( - date.year, - date.month - 1, - date.day, - time?.hour ?: 0, - time?.minute ?: 0, - time?.second ?: 0 - ) } + get() = date.getAsCalendar(time) val endTimeCalendar: Calendar get() = startTimeCalendar.also { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt index 367b00da..dd3fbbbc 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt @@ -12,10 +12,6 @@ import android.widget.Toast import androidx.databinding.ViewDataBinding import androidx.fragment.app.Fragment import com.applandeo.materialcalendarview.EventDay -import com.github.tibolte.agendacalendarview.CalendarPickerController -import com.github.tibolte.agendacalendarview.models.BaseCalendarEvent -import com.github.tibolte.agendacalendarview.models.CalendarEvent -import com.github.tibolte.agendacalendarview.models.IDayItem import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import com.mikepenz.iconics.utils.colorInt @@ -31,15 +27,6 @@ import pl.szczodrzynski.edziennik.databinding.FragmentAgendaCalendarBinding import pl.szczodrzynski.edziennik.databinding.FragmentAgendaDefaultBinding import pl.szczodrzynski.edziennik.ui.dialogs.day.DayDialog import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog -import pl.szczodrzynski.edziennik.ui.dialogs.lessonchange.LessonChangeDialog -import pl.szczodrzynski.edziennik.ui.dialogs.teacherabsence.TeacherAbsenceDialog -import pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchange.LessonChangeCounter -import pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchange.LessonChangeEvent -import pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchange.LessonChangeEventRenderer -import pl.szczodrzynski.edziennik.ui.modules.agenda.teacherabsence.TeacherAbsenceCounter -import pl.szczodrzynski.edziennik.ui.modules.agenda.teacherabsence.TeacherAbsenceEvent -import pl.szczodrzynski.edziennik.ui.modules.agenda.teacherabsence.TeacherAbsenceEventRenderer -import pl.szczodrzynski.edziennik.utils.Colors import pl.szczodrzynski.edziennik.utils.Themes import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem @@ -59,7 +46,8 @@ class AgendaFragment : Fragment(), CoroutineScope { get() = job + Dispatchers.Main private var type: Int = Profile.AGENDA_DEFAULT - private var actualDate: Date? = null + + private var agendaDefault: AgendaFragmentDefault? = null override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { if (getActivity() == null || context == null) return null @@ -82,38 +70,50 @@ class AgendaFragment : Fragment(), CoroutineScope { .withTitle(R.string.menu_add_event) .withDescription(R.string.menu_add_event_desc) .withIcon(SzkolnyFont.Icon.szf_calendar_plus_outline) - .withOnClickListener(View.OnClickListener { + .withOnClickListener { activity.bottomSheet.close() - EventManualDialog(activity, app.profileId, defaultDate = actualDate) - }), + EventManualDialog( + activity, + app.profileId, + defaultDate = agendaDefault?.selectedDate + ) + }, BottomSheetPrimaryItem(true) .withTitle(R.string.menu_agenda_change_view) .withIcon(if (type == Profile.AGENDA_DEFAULT) CommunityMaterial.Icon.cmd_calendar_outline else CommunityMaterial.Icon2.cmd_format_list_bulleted_square) - .withOnClickListener(View.OnClickListener { + .withOnClickListener { activity.bottomSheet.close() - type = if (type == Profile.AGENDA_DEFAULT) Profile.AGENDA_CALENDAR else Profile.AGENDA_DEFAULT + type = + if (type == Profile.AGENDA_DEFAULT) Profile.AGENDA_CALENDAR else Profile.AGENDA_DEFAULT app.config.forProfile().ui.agendaViewType = type activity.reloadTarget() - }), + }, BottomSheetSeparatorItem(true), BottomSheetPrimaryItem(true) .withTitle(R.string.menu_mark_as_read) .withIcon(CommunityMaterial.Icon.cmd_eye_check_outline) - .withOnClickListener(View.OnClickListener { launch { - activity.bottomSheet.close() - withContext(Dispatchers.Default) { - App.db.metadataDao().setAllSeen(app.profileId, Metadata.TYPE_EVENT, true) + .withOnClickListener { + launch { + activity.bottomSheet.close() + withContext(Dispatchers.Default) { + App.db.metadataDao() + .setAllSeen(app.profileId, Metadata.TYPE_EVENT, true) + } + Toast.makeText( + activity, + R.string.main_menu_mark_as_read_success, + Toast.LENGTH_SHORT + ).show() } - Toast.makeText(activity, R.string.main_menu_mark_as_read_success, Toast.LENGTH_SHORT).show() - }}) + } ) activity.navView.bottomBar.fabEnable = true activity.navView.bottomBar.fabExtendedText = getString(R.string.add) activity.navView.bottomBar.fabIcon = CommunityMaterial.Icon3.cmd_plus - activity.navView.setFabOnClickListener(View.OnClickListener { - EventManualDialog(activity, app.profileId, defaultDate = actualDate) - }) + activity.navView.setFabOnClickListener { + EventManualDialog(activity, app.profileId, defaultDate = agendaDefault?.selectedDate) + } activity.gainAttention() activity.gainAttentionFAB() @@ -129,141 +129,8 @@ class AgendaFragment : Fragment(), CoroutineScope { return@launch delay(500) - val eventList = mutableListOf() - - val minDate = Calendar.getInstance().apply { - add(Calendar.MONTH, -2) - set(Calendar.DAY_OF_MONTH, 1) - } - val maxDate = Calendar.getInstance().apply { add(Calendar.MONTH, 2) } - - /** - * LESSON CHANGES - */ - if (!isAdded) - return@launch - - val lessons = withContext(Dispatchers.Default) { app.db.timetableDao().getChangesNow(app.profileId) } - val lessonChangeCounters = mutableListOf() - - lessons.forEach { lesson -> - lessonChangeCounters.firstOrNull { it.lessonChangeDate == lesson.displayDate }?.let { - it.lessonChangeCount += 1 - } ?: run { - lessonChangeCounters.add(LessonChangeCounter( - lesson.displayDate ?: return@forEach, - 1 - )) - } - } - - lessonChangeCounters.forEach { counter -> - eventList.add(LessonChangeEvent( - counter.lessonChangeDate.inMillis, - 0xff78909c.toInt(), - Colors.legibleTextColor(0xff78909c.toInt()), - counter.startTime, - counter.endTime, - app.profileId, - counter.lessonChangeDate, - counter.lessonChangeCount - )) - } - - /** - * TEACHER ABSENCES - */ - if (!isAdded) - return@launch - - val showTeacherAbsences = app.profile.getStudentData("showTeacherAbsences", true) - - if (showTeacherAbsences) { - val teacherAbsenceList = withContext(Dispatchers.Default) { app.db.teacherAbsenceDao().getAllNow(app.profileId) } - val teacherAbsenceCounters = mutableListOf() - - teacherAbsenceList.forEach { absence -> - val date = absence.dateFrom.clone() - - while (date <= absence.dateTo) { - teacherAbsenceCounters.firstOrNull { it.teacherAbsenceDate == date }?.let { - it.teacherAbsenceCount += 1 - } ?: run { - teacherAbsenceCounters.add(TeacherAbsenceCounter(date.clone(), 1)) - } - - date.stepForward(0, 0, 1) - } - } - - teacherAbsenceCounters.forEach { counter -> - eventList.add(TeacherAbsenceEvent( - counter.teacherAbsenceDate.inMillis, - 0xffff1744.toInt(), - Colors.legibleTextColor(0xffff1744.toInt()), - counter.startTime, - counter.endTime, - app.profileId, - counter.teacherAbsenceDate, - counter.teacherAbsenceCount - )) - } - } - - /** - * EVENTS - */ - if (!isAdded) - return@launch - - val events = withContext(Dispatchers.Default) { app.db.eventDao().getAllNow(app.profileId) } - val unreadEventDates = mutableSetOf() - - events.forEach { event -> - eventList.add(BaseCalendarEvent( - "${event.typeName ?: "wydarzenie"} - ${event.topic}", - "", - (if (event.time == null) getString(R.string.agenda_event_all_day) else event.time!!.stringHM) + - (event.subjectLongName?.let { ", $it" } ?: "") + - (event.teacherName?.let { ", $it" } ?: "") + - (event.teamName?.let { ", $it" } ?: ""), - event.eventColor, - Colors.legibleTextColor(event.eventColor), - event.startTimeCalendar, - event.endTimeCalendar, - event.time == null, - event.id, - !event.seen - )) - - if (!event.seen) unreadEventDates.add(event.date.value) - } - - b.agendaDefaultView.init(eventList, minDate, maxDate, Locale.getDefault(), object : CalendarPickerController { - override fun onDaySelected(dayItem: IDayItem?) {} - - override fun onScrollToDate(calendar: Calendar) { this@AgendaFragment.launch { - val date = Date.fromCalendar(calendar) - actualDate = date - - // Mark as read scrolled date - if (date.value in unreadEventDates) { - withContext(Dispatchers.Default) { app.db.eventDao().setSeenByDate(app.profileId, date, true) } - unreadEventDates.remove(date.value) - } - }} - - override fun onEventSelected(event: CalendarEvent) { - val date = Date.fromCalendar(event.instanceDay) - - when (event) { - is BaseCalendarEvent -> DayDialog(activity, app.profileId, date) - is LessonChangeEvent -> LessonChangeDialog(activity, app.profileId, date) - is TeacherAbsenceEvent -> TeacherAbsenceDialog(activity, app.profileId, date) - } - } - - }, LessonChangeEventRenderer(), TeacherAbsenceEventRenderer()) + agendaDefault = AgendaFragmentDefault(activity, app, b) + agendaDefault?.initView(this@AgendaFragment) b.progressBar.visibility = View.GONE }}} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt new file mode 100644 index 00000000..9e4e31ab --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt @@ -0,0 +1,142 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-4-8. + */ + +package pl.szczodrzynski.edziennik.ui.modules.agenda + +import android.util.SparseIntArray +import androidx.core.util.forEach +import androidx.core.util.set +import com.github.tibolte.agendacalendarview.CalendarPickerController +import com.github.tibolte.agendacalendarview.models.CalendarEvent +import com.github.tibolte.agendacalendarview.models.IDayItem +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.MainActivity +import pl.szczodrzynski.edziennik.databinding.FragmentAgendaDefaultBinding +import pl.szczodrzynski.edziennik.ui.dialogs.day.DayDialog +import pl.szczodrzynski.edziennik.ui.dialogs.lessonchange.LessonChangeDialog +import pl.szczodrzynski.edziennik.ui.dialogs.teacherabsence.TeacherAbsenceDialog +import pl.szczodrzynski.edziennik.ui.modules.agenda.event.AgendaEvent +import pl.szczodrzynski.edziennik.ui.modules.agenda.event.AgendaEventRenderer +import pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchanges.LessonChangesEvent +import pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchanges.LessonChangesEventRenderer +import pl.szczodrzynski.edziennik.ui.modules.agenda.teacherabsence.TeacherAbsenceEvent +import pl.szczodrzynski.edziennik.ui.modules.agenda.teacherabsence.TeacherAbsenceEventRenderer +import pl.szczodrzynski.edziennik.utils.models.Date +import java.util.* + +class AgendaFragmentDefault( + private val activity: MainActivity, + private val app: App, + private val b: FragmentAgendaDefaultBinding +) { + private val unreadDates = mutableSetOf() + var selectedDate: Date = Date.getToday() + + suspend fun initView(fragment: AgendaFragment) { + val dateStart = app.profile.dateSemester1Start.asCalendar + val dateEnd = app.profile.dateYearEnd.asCalendar + + val events = withContext(Dispatchers.Default) { + val events = mutableListOf() + + addLessonChanges(events) + + val showTeacherAbsences = app.profile.getStudentData("showTeacherAbsences", true) + if (showTeacherAbsences) { + addTeacherAbsence(events) + } + + addEvents(events) + + return@withContext events + } + + if (!fragment.isAdded) + return + b.agendaDefaultView.init( + events, + dateStart, + dateEnd, + Locale.getDefault(), + object : CalendarPickerController { + override fun onDaySelected(dayItem: IDayItem) {} + + override fun onEventSelected(event: CalendarEvent) { + val date = Date.fromCalendar(event.instanceDay) + + when (event) { + is AgendaEvent -> DayDialog(activity, app.profileId, date) + is LessonChangesEvent -> LessonChangeDialog(activity, app.profileId, date) + is TeacherAbsenceEvent -> TeacherAbsenceDialog(activity, app.profileId, date) + } + } + + override fun onScrollToDate(calendar: Calendar) { + selectedDate = Date.fromCalendar(calendar) + + // Mark as read scrolled date + if (selectedDate.value in unreadDates) { + activity.launch(Dispatchers.Default) { + app.db.eventDao().setSeenByDate(app.profileId, selectedDate, true) + } + unreadDates.remove(selectedDate.value) + } + } + }, + AgendaEventRenderer(), + LessonChangesEventRenderer(), + TeacherAbsenceEventRenderer() + ) + } + + private fun addEvents(events: MutableList) { + val eventList = app.db.eventDao().getAllNow(app.profileId) + + events += eventList.map { + if (!it.seen) + unreadDates.add(it.date.value) + AgendaEvent(it) + } + } + + private fun addLessonChanges(events: MutableList) { + val lessons = app.db.timetableDao().getChangesNow(app.profileId) + + val grouped = lessons.groupBy { + it.displayDate + } + + events += grouped.mapNotNull { (date, changes) -> + LessonChangesEvent( + app.profileId, + date = date ?: return@mapNotNull null, + changeCount = changes.size + ) + } + } + + private fun addTeacherAbsence(events: MutableList) { + val teacherAbsence = app.db.teacherAbsenceDao().getAllNow(app.profileId) + + val countMap = SparseIntArray() + + for (absence in teacherAbsence) { + while (absence.dateFrom <= absence.dateTo) { + countMap[absence.dateFrom.value] += 1 + absence.dateFrom.stepForward(0, 0, 1) + } + } + + countMap.forEach { dateInt, count -> + events += TeacherAbsenceEvent( + app.profileId, + date = Date.fromValue(dateInt), + absenceCount = count + ) + } + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/BaseEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/BaseEvent.kt new file mode 100644 index 00000000..f183485b --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/BaseEvent.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-4-9. + */ + +package pl.szczodrzynski.edziennik.ui.modules.agenda + +import com.github.tibolte.agendacalendarview.models.CalendarEvent +import com.github.tibolte.agendacalendarview.models.IDayItem +import com.github.tibolte.agendacalendarview.models.IWeekItem +import java.util.* + +open class BaseEvent( + private val id: Long, + private val time: Calendar, + private val color: Int, + private val showBadge: Boolean +) : CalendarEvent { + + override fun copy() = BaseEvent(id, time, color, showBadge) + + private lateinit var date: Calendar + override fun getInstanceDay() = date + override fun setInstanceDay(value: Calendar) { + date = value + } + + private lateinit var dayReference: IDayItem + override fun getDayReference() = dayReference + override fun setDayReference(value: IDayItem) { + dayReference = value + } + + private lateinit var weekReference: IWeekItem + override fun getWeekReference() = weekReference + override fun setWeekReference(value: IWeekItem) { + weekReference = value + } + + override fun getId() = id + override fun getStartTime() = time + override fun getEndTime() = time + override fun getTitle() = "" + override fun getDescription() = "" + override fun getLocation() = "" + override fun getColor() = color + override fun getTextColor() = 0 + override fun getShowBadge() = showBadge + override fun isPlaceholder() = false + override fun isAllDay() = false + + override fun setId(value: Long) = Unit + override fun setStartTime(value: Calendar) = Unit + override fun setEndTime(value: Calendar) = Unit + override fun setTitle(value: String) = Unit + override fun setDescription(value: String) = Unit + override fun setLocation(value: String) = Unit + override fun setTextColor(value: Int) = Unit + override fun setShowBadge(value: Boolean) = Unit + override fun setPlaceholder(value: Boolean) = Unit + override fun setAllDay(value: Boolean) = Unit +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEvent.kt new file mode 100644 index 00000000..3cd05727 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEvent.kt @@ -0,0 +1,19 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-4-8. + */ + +package pl.szczodrzynski.edziennik.ui.modules.agenda.event + +import pl.szczodrzynski.edziennik.data.db.full.EventFull +import pl.szczodrzynski.edziennik.ui.modules.agenda.BaseEvent + +class AgendaEvent( + val event: EventFull +) : BaseEvent( + id = event.id, + time = event.startTimeCalendar, + color = event.eventColor, + showBadge = !event.seen +) { + override fun copy() = AgendaEvent(event) +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt new file mode 100644 index 00000000..da28ffd5 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-4-8. + */ + +package pl.szczodrzynski.edziennik.ui.modules.agenda.event + +import android.annotation.SuppressLint +import android.view.View +import com.github.tibolte.agendacalendarview.render.EventRenderer +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.databinding.AgendaWrappedEventBinding +import pl.szczodrzynski.edziennik.utils.Colors + +class AgendaEventRenderer : EventRenderer() { + + @SuppressLint("SetTextI18n") + override fun render(view: View, aEvent: AgendaEvent) { + val b = AgendaWrappedEventBinding.bind(view).item + val event = aEvent.event + + b.card.setCardBackgroundColor(event.eventColor) + b.eventTitle.setTextColor(Colors.legibleTextColor(event.eventColor)) + b.eventSubtitle.setTextColor(Colors.legibleTextColor(event.eventColor)) + + b.eventTitle.text = "${event.typeName ?: "wydarzenie"} - ${event.topic}" + b.eventSubtitle.text = + (if (event.time == null) + view.context.getString(R.string.agenda_event_all_day) + else + event.time!!.stringHM) + + (event.subjectLongName?.let { ", $it" } ?: "") + + (event.teacherName?.let { ", $it" } ?: "") + + (event.teamName?.let { ", $it" } ?: "") + } + + override fun getEventLayout(): Int = R.layout.agenda_wrapped_event +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchange/LessonChangeCounter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchange/LessonChangeCounter.kt deleted file mode 100644 index 2b264ede..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchange/LessonChangeCounter.kt +++ /dev/null @@ -1,19 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchange - -import pl.szczodrzynski.edziennik.utils.models.Date -import java.util.* - -class LessonChangeCounter( - val lessonChangeDate: Date, - var lessonChangeCount: Int -) { - val startTime: Calendar - get() = Calendar.getInstance().apply { - set(lessonChangeDate.year, lessonChangeDate.month - 1, lessonChangeDate.day, 10, 0, 0) - } - - val endTime: Calendar - get() = Calendar.getInstance().apply { - timeInMillis = startTime.timeInMillis + (45 * 60 * 1000) - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchange/LessonChangeEvent.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchange/LessonChangeEvent.java deleted file mode 100644 index 077c2206..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchange/LessonChangeEvent.java +++ /dev/null @@ -1,243 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchange; - -import com.github.tibolte.agendacalendarview.models.CalendarEvent; -import com.github.tibolte.agendacalendarview.models.IDayItem; -import com.github.tibolte.agendacalendarview.models.IWeekItem; - -import java.util.Calendar; - -import pl.szczodrzynski.edziennik.utils.models.Date; - -public class LessonChangeEvent implements CalendarEvent { - - /** - * Id of the event. - */ - private long mId; - /** - * Color to be displayed in the agenda view. - */ - private int mColor; - /** - * Text color displayed on the background color - */ - private int mTextColor; - /** - * Calendar instance helping sorting the events per section in the agenda view. - */ - private Calendar mInstanceDay; - /** - * Start time of the event. - */ - private Calendar mStartTime; - /** - * End time of the event. - */ - private Calendar mEndTime; - /** - * References to a DayItem instance for that event, used to link interaction between the - * calendar view and the agenda view. - */ - private IDayItem mDayReference; - /** - * References to a WeekItem instance for that event, used to link interaction between the - * calendar view and the agenda view. - */ - private IWeekItem mWeekReference; - - - private int profileId; - private Date lessonChangeDate; - private int lessonChangeCount; - - public LessonChangeEvent(LessonChangeEvent calendarEvent) { - this.mId = calendarEvent.getId(); - this.mColor = calendarEvent.getColor(); - this.mTextColor = calendarEvent.getTextColor(); - this.mStartTime = calendarEvent.getStartTime(); - this.mEndTime = calendarEvent.getEndTime(); - this.profileId = calendarEvent.getProfileId(); - this.lessonChangeDate = calendarEvent.getLessonChangeDate(); - this.lessonChangeCount = calendarEvent.getLessonChangeCount(); - } - - public LessonChangeEvent(long mId, int mColor, int mTextColor, Calendar mStartTime, Calendar mEndTime, int profileId, Date lessonChangeDate, int lessonChangeCount) { - this.mId = mId; - this.mColor = mColor; - this.mTextColor = mTextColor; - this.mStartTime = mStartTime; - this.mEndTime = mEndTime; - this.profileId = profileId; - this.lessonChangeDate = lessonChangeDate; - this.lessonChangeCount = lessonChangeCount; - } - - public int getProfileId() { - return profileId; - } - - public Date getLessonChangeDate() { - return lessonChangeDate; - } - - public int getLessonChangeCount() { - return lessonChangeCount; - } - - public void setProfileId(int profileId) { - this.profileId = profileId; - } - - public void setLessonChangeDate(Date lessonChangeDate) { - this.lessonChangeDate = lessonChangeDate; - } - - public void setLessonChangeCount(int lessonChangeCount) { - this.lessonChangeCount = lessonChangeCount; - } - - @Override - public void setPlaceholder(boolean placeholder) { - - } - - @Override - public boolean isPlaceholder() { - return false; - } - - @Override - public String getLocation() { - return null; - } - - @Override - public void setLocation(String mLocation) { - - } - - @Override - public long getId() { - return mId; - } - - @Override - public void setId(long mId) { - this.mId = mId; - } - - @Override - public boolean getShowBadge() { - return false; - } - - @Override - public void setShowBadge(boolean mShowBadge) { - - } - - @Override - public int getTextColor() { - return mTextColor; - } - - @Override - public void setTextColor(int mTextColor) { - this.mTextColor = mTextColor; - } - - @Override - public String getDescription() { - return null; - } - - @Override - public void setDescription(String mDescription) { - - } - - @Override - public boolean isAllDay() { - return false; - } - - @Override - public void setAllDay(boolean allDay) { - - } - - @Override - public Calendar getStartTime() { - return mStartTime; - } - - @Override - public void setStartTime(Calendar mStartTime) { - this.mStartTime = mStartTime; - } - - @Override - public Calendar getEndTime() { - return mEndTime; - } - - @Override - public void setEndTime(Calendar mEndTime) { - this.mEndTime = mEndTime; - } - - @Override - public String getTitle() { - return null; - } - - @Override - public void setTitle(String mTitle) { - - } - - @Override - public Calendar getInstanceDay() { - return mInstanceDay; - } - - @Override - public void setInstanceDay(Calendar mInstanceDay) { - this.mInstanceDay = mInstanceDay; - this.mInstanceDay.set(Calendar.HOUR, 0); - this.mInstanceDay.set(Calendar.MINUTE, 0); - this.mInstanceDay.set(Calendar.SECOND, 0); - this.mInstanceDay.set(Calendar.MILLISECOND, 0); - this.mInstanceDay.set(Calendar.AM_PM, 0); - } - - @Override - public IDayItem getDayReference() { - return mDayReference; - } - - @Override - public void setDayReference(IDayItem mDayReference) { - this.mDayReference = mDayReference; - } - - @Override - public IWeekItem getWeekReference() { - return mWeekReference; - } - - @Override - public void setWeekReference(IWeekItem mWeekReference) { - this.mWeekReference = mWeekReference; - } - - @Override - public CalendarEvent copy() { - return new LessonChangeEvent(this); - } - - @Override - public int getColor() { - return mColor; - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchange/LessonChangeEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchange/LessonChangeEventRenderer.kt deleted file mode 100644 index e2306039..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchange/LessonChangeEventRenderer.kt +++ /dev/null @@ -1,21 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchange - -import android.view.View -import android.widget.TextView -import androidx.cardview.widget.CardView -import com.github.tibolte.agendacalendarview.render.EventRenderer -import pl.szczodrzynski.edziennik.R - -class LessonChangeEventRenderer : EventRenderer() { - override fun render(view: View?, event: LessonChangeEvent) { - val card = view?.findViewById(R.id.lesson_change_card) - val changeText = view?.findViewById(R.id.lesson_change_text) - val changeCount = view?.findViewById(R.id.lessonChangeCount) - card?.setCardBackgroundColor(event.color) - changeText?.setTextColor(event.textColor) - changeCount?.setTextColor(event.textColor) - changeCount?.text = event.lessonChangeCount.toString() - } - - override fun getEventLayout(): Int = R.layout.agenda_event_lesson_change -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEvent.kt new file mode 100644 index 00000000..e65c82bd --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEvent.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-4-8. + */ + +package pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchanges + +import pl.szczodrzynski.edziennik.ui.modules.agenda.BaseEvent +import pl.szczodrzynski.edziennik.utils.models.Date + +class LessonChangesEvent( + val profileId: Int, + val date: Date, + val changeCount: Int +) : BaseEvent( + id = date.value.toLong(), + time = date.asCalendar, + color = 0xff78909c.toInt(), + showBadge = false +) { + override fun copy() = LessonChangesEvent(profileId, date, changeCount) +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt new file mode 100644 index 00000000..5ffc788c --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-4-8. + */ + +package pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchanges + +import android.view.View +import com.github.tibolte.agendacalendarview.render.EventRenderer +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.databinding.AgendaWrappedLessonChangesBinding + +class LessonChangesEventRenderer : EventRenderer() { + + override fun render(view: View, event: LessonChangesEvent) { + val b = AgendaWrappedLessonChangesBinding.bind(view).item + + b.lessonChangeCount.text = event.changeCount.toString() + } + + override fun getEventLayout(): Int = R.layout.agenda_wrapped_lesson_changes +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceCounter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceCounter.kt deleted file mode 100644 index 71dea025..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceCounter.kt +++ /dev/null @@ -1,19 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.modules.agenda.teacherabsence - -import pl.szczodrzynski.edziennik.utils.models.Date -import java.util.* - -class TeacherAbsenceCounter ( - val teacherAbsenceDate: Date, - var teacherAbsenceCount: Int = 0 -) { - val startTime: Calendar - get() = Calendar.getInstance().apply { - set(teacherAbsenceDate.year, teacherAbsenceDate.month - 1, teacherAbsenceDate.day, 10, 0, 0) - } - - val endTime: Calendar - get() = Calendar.getInstance().apply { - timeInMillis = startTime.timeInMillis + (45 * 60 * 1000) - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEvent.kt index fc1c28db..4208814b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEvent.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEvent.kt @@ -1,188 +1,21 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-4-8. + */ + package pl.szczodrzynski.edziennik.ui.modules.agenda.teacherabsence -import com.github.tibolte.agendacalendarview.models.CalendarEvent -import com.github.tibolte.agendacalendarview.models.IDayItem -import com.github.tibolte.agendacalendarview.models.IWeekItem +import pl.szczodrzynski.edziennik.ui.modules.agenda.BaseEvent import pl.szczodrzynski.edziennik.utils.models.Date -import java.util.* -class TeacherAbsenceEvent : CalendarEvent { - /** - * Id of the event. - */ - private var mId: Long = 0 - /** - * Color to be displayed in the agenda view. - */ - private var mColor: Int = 0 - /** - * Text color displayed on the background color - */ - private var mTextColor: Int = 0 - /** - * Calendar instance helping sorting the events per section in the agenda view. - */ - private var mInstanceDay: Calendar? = null - /** - * Start time of the event. - */ - private var mStartTime: Calendar? = null - /** - * End time of the event. - */ - private var mEndTime: Calendar? = null - /** - * References to a DayItem instance for that event, used to link interaction between the - * calendar view and the agenda view. - */ - private var mDayReference: IDayItem? = null - /** - * References to a WeekItem instance for that event, used to link interaction between the - * calendar view and the agenda view. - */ - private var mWeekReference: IWeekItem? = null - - - private var profileId: Int = 0 - var teacherAbsenceDate: Date? = null - var teacherAbsenceCount: Int = 0 - - constructor(calendarEvent: TeacherAbsenceEvent) { - this.mId = calendarEvent.id - this.mColor = calendarEvent.color - this.mTextColor = calendarEvent.textColor - this.mStartTime = calendarEvent.startTime - this.mEndTime = calendarEvent.endTime - this.profileId = calendarEvent.profileId - this.teacherAbsenceDate = calendarEvent.teacherAbsenceDate - this.teacherAbsenceCount = calendarEvent.teacherAbsenceCount - } - - constructor(mId: Long, mColor: Int, mTextColor: Int, mStartTime: Calendar, mEndTime: Calendar, profileId: Int, teacherAbsenceDate: Date, teacherAbsenceCount: Int) { - this.mId = mId - this.mColor = mColor - this.mTextColor = mTextColor - this.mStartTime = mStartTime - this.mEndTime = mEndTime - this.profileId = profileId - this.teacherAbsenceDate = teacherAbsenceDate - this.teacherAbsenceCount = teacherAbsenceCount - } - - override fun setPlaceholder(placeholder: Boolean) { - - } - - override fun isPlaceholder(): Boolean { - return false - } - - override fun getLocation(): String? { - return null - } - - override fun setLocation(mLocation: String) { - - } - - override fun getId(): Long { - return mId - } - - override fun setId(mId: Long) { - this.mId = mId - } - - override fun getShowBadge(): Boolean { - return false - } - - override fun setShowBadge(mShowBadge: Boolean) { - - } - - override fun getTextColor(): Int { - return mTextColor - } - - override fun setTextColor(mTextColor: Int) { - this.mTextColor = mTextColor - } - - override fun getDescription(): String? { - return null - } - - override fun setDescription(mDescription: String) { - - } - - override fun isAllDay(): Boolean { - return false - } - - override fun setAllDay(allDay: Boolean) { - - } - - override fun getStartTime(): Calendar? { - return mStartTime - } - - override fun setStartTime(mStartTime: Calendar) { - this.mStartTime = mStartTime - } - - override fun getEndTime(): Calendar? { - return mEndTime - } - - override fun setEndTime(mEndTime: Calendar) { - this.mEndTime = mEndTime - } - - override fun getTitle(): String? { - return null - } - - override fun setTitle(mTitle: String) { - - } - - override fun getInstanceDay(): Calendar? { - return mInstanceDay - } - - override fun setInstanceDay(mInstanceDay: Calendar) { - this.mInstanceDay = mInstanceDay - this.mInstanceDay!!.set(Calendar.HOUR, 0) - this.mInstanceDay!!.set(Calendar.MINUTE, 0) - this.mInstanceDay!!.set(Calendar.SECOND, 0) - this.mInstanceDay!!.set(Calendar.MILLISECOND, 0) - this.mInstanceDay!!.set(Calendar.AM_PM, 0) - } - - override fun getDayReference(): IDayItem? { - return mDayReference - } - - override fun setDayReference(mDayReference: IDayItem) { - this.mDayReference = mDayReference - } - - override fun getWeekReference(): IWeekItem? { - return mWeekReference - } - - override fun setWeekReference(mWeekReference: IWeekItem) { - this.mWeekReference = mWeekReference - } - - override fun copy(): CalendarEvent { - return TeacherAbsenceEvent(this) - } - - override fun getColor(): Int { - return mColor - } +class TeacherAbsenceEvent( + val profileId: Int, + val date: Date, + val absenceCount: Int +) : BaseEvent( + id = date.value.toLong(), + time = date.asCalendar, + color = 0xffff1744.toInt(), + showBadge = false +) { + override fun copy() = TeacherAbsenceEvent(profileId, date, absenceCount) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt index b437769b..756c60c9 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt @@ -1,21 +1,21 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-4-8. + */ + package pl.szczodrzynski.edziennik.ui.modules.agenda.teacherabsence import android.view.View -import android.widget.TextView -import androidx.cardview.widget.CardView import com.github.tibolte.agendacalendarview.render.EventRenderer import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.databinding.AgendaWrappedTeacherAbsenceBinding class TeacherAbsenceEventRenderer : EventRenderer() { - override fun render(view: View?, event: TeacherAbsenceEvent) { - val card = view?.findViewById(R.id.teacherAbsenceCard) - val changeText = view?.findViewById(R.id.teacherAbsenceText) - val changeCount = view?.findViewById(R.id.teacherAbsenceCount) - card?.setCardBackgroundColor(event.color) - changeText?.setTextColor(event.textColor) - changeCount?.setTextColor(event.textColor) - changeCount?.text = event.teacherAbsenceCount.toString() + + override fun render(view: View, event: TeacherAbsenceEvent) { + val b = AgendaWrappedTeacherAbsenceBinding.bind(view).item + + b.teacherAbsenceCount.text = event.absenceCount.toString() } - override fun getEventLayout(): Int = R.layout.agenda_event_teacher_absence + override fun getEventLayout(): Int = R.layout.agenda_wrapped_teacher_absence } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/Date.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/Date.java index b39d0298..ebc4570c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/Date.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/Date.java @@ -94,17 +94,29 @@ public class Date implements Comparable { } } - public long getInMillis() { + public Calendar getAsCalendar() { Calendar c = Calendar.getInstance(); c.set(year, month - 1, day, 0, 0, 0); c.set(Calendar.MILLISECOND, 0); + return c; + } + + public Calendar getAsCalendar(Time time) { + if (time == null) + return getAsCalendar(); + Calendar c = Calendar.getInstance(); + c.set(year, month - 1, day, time.hour, time.minute, time.second); + c.set(Calendar.MILLISECOND, 0); + return c; + } + + public long getInMillis() { + Calendar c = getAsCalendar(); return c.getTimeInMillis(); } public long getInMillisUtc() { - Calendar c = Calendar.getInstance(); - c.set(year, month - 1, day, 0, 0, 0); - c.set(Calendar.MILLISECOND, 0); + Calendar c = getAsCalendar(); c.setTimeZone(TimeZone.getTimeZone("UTC")); return c.getTimeInMillis(); } @@ -179,13 +191,7 @@ public class Date implements Comparable { } public long combineWith(Time time) { - if (time == null) { - return getInMillis(); - } - Calendar c = Calendar.getInstance(); - c.set(this.year, this.month - 1, this.day, time.hour, time.minute, time.second); - c.set(Calendar.MILLISECOND, 0); - return c.getTimeInMillis(); + return getAsCalendar(time).getTimeInMillis(); } public int getWeekDay() { diff --git a/app/src/main/res/layout/agenda_event_item.xml b/app/src/main/res/layout/agenda_event_item.xml new file mode 100644 index 00000000..b07106f5 --- /dev/null +++ b/app/src/main/res/layout/agenda_event_item.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/layout/row_lesson_change_item.xml b/app/src/main/res/layout/agenda_lesson_changes_item.xml similarity index 72% rename from app/src/main/res/layout/row_lesson_change_item.xml rename to app/src/main/res/layout/agenda_lesson_changes_item.xml index 33515e89..8700a575 100644 --- a/app/src/main/res/layout/row_lesson_change_item.xml +++ b/app/src/main/res/layout/agenda_lesson_changes_item.xml @@ -1,11 +1,10 @@ - + app:cardCornerRadius="5dp"> + android:textColor="@color/md_white_1000" /> - - diff --git a/app/src/main/res/layout/row_teacher_absence_item.xml b/app/src/main/res/layout/agenda_teacher_absence_item.xml similarity index 72% rename from app/src/main/res/layout/row_teacher_absence_item.xml rename to app/src/main/res/layout/agenda_teacher_absence_item.xml index da78c625..4b749e8c 100644 --- a/app/src/main/res/layout/row_teacher_absence_item.xml +++ b/app/src/main/res/layout/agenda_teacher_absence_item.xml @@ -1,11 +1,10 @@ - + app:cardCornerRadius="5dp"> + android:textColor="@color/md_white_1000" /> - - diff --git a/app/src/main/res/layout/agenda_event_lesson_change.xml b/app/src/main/res/layout/agenda_wrapped_event.xml similarity index 77% rename from app/src/main/res/layout/agenda_event_lesson_change.xml rename to app/src/main/res/layout/agenda_wrapped_event.xml index c51f9b35..2ca38528 100644 --- a/app/src/main/res/layout/agenda_event_lesson_change.xml +++ b/app/src/main/res/layout/agenda_wrapped_event.xml @@ -1,15 +1,17 @@ + + - diff --git a/app/src/main/res/layout/agenda_event_teacher_absence.xml b/app/src/main/res/layout/agenda_wrapped_lesson_changes.xml similarity index 86% rename from app/src/main/res/layout/agenda_event_teacher_absence.xml rename to app/src/main/res/layout/agenda_wrapped_lesson_changes.xml index 785256d0..834d2ddd 100644 --- a/app/src/main/res/layout/agenda_event_teacher_absence.xml +++ b/app/src/main/res/layout/agenda_wrapped_lesson_changes.xml @@ -5,9 +5,9 @@ android:gravity="center_vertical" android:orientation="horizontal"> - diff --git a/app/src/main/res/layout/agenda_wrapped_teacher_absence.xml b/app/src/main/res/layout/agenda_wrapped_teacher_absence.xml new file mode 100644 index 00000000..4793b0d8 --- /dev/null +++ b/app/src/main/res/layout/agenda_wrapped_teacher_absence.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/app/src/main/res/layout/dialog_day.xml b/app/src/main/res/layout/dialog_day.xml index 59fd7f8c..f1544f59 100644 --- a/app/src/main/res/layout/dialog_day.xml +++ b/app/src/main/res/layout/dialog_day.xml @@ -49,7 +49,7 @@ Date: Fri, 9 Apr 2021 21:52:04 +0200 Subject: [PATCH 02/15] [Agenda] Implement updating event list when changed. --- .../edziennik/data/db/dao/TimetableDao.kt | 2 + .../ui/dialogs/event/EventManualDialog.kt | 5 -- .../ui/modules/agenda/AgendaFragment.kt | 8 ++- .../modules/agenda/AgendaFragmentDefault.kt | 62 ++++++++++++++----- 4 files changed, 55 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/TimetableDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/TimetableDao.kt index c7cbee12..8ce9ed9b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/TimetableDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/TimetableDao.kt @@ -84,6 +84,8 @@ abstract class TimetableDao : BaseDao { "LIMIT 1") fun getBetweenDates(dateFrom: Date, dateTo: Date) = getRaw("$QUERY WHERE (type != 3 AND date >= '${dateFrom.stringY_m_d}' AND date <= '${dateTo.stringY_m_d}') OR ((type = 3 OR type = 1) AND oldDate >= '${dateFrom.stringY_m_d}' AND oldDate <= '${dateTo.stringY_m_d}') $ORDER_BY") + fun getChanges(profileId: Int) = + getRaw("$QUERY WHERE timetable.profileId = $profileId AND $IS_CHANGED $ORDER_BY") // GET ALL - NOW fun getAllNow(profileId: Int) = diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt index 97e34009..9beac76b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt @@ -20,7 +20,6 @@ import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent @@ -599,8 +598,6 @@ class EventManualDialog( dialog.dismiss() Toast.makeText(activity, R.string.saved, Toast.LENGTH_SHORT).show() - if (activity is MainActivity && activity.navTargetId == DRAWER_ITEM_AGENDA) - activity.reloadTarget() } private fun finishRemoving() { editingEvent ?: return @@ -613,7 +610,5 @@ class EventManualDialog( removeEventDialog?.dismiss() dialog.dismiss() Toast.makeText(activity, R.string.removed, Toast.LENGTH_SHORT).show() - if (activity is MainActivity && activity.navTargetId == DRAWER_ITEM_AGENDA) - activity.reloadTarget() } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt index dd3fbbbc..0d5fd425 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt @@ -75,7 +75,7 @@ class AgendaFragment : Fragment(), CoroutineScope { EventManualDialog( activity, app.profileId, - defaultDate = agendaDefault?.selectedDate + defaultDate = AgendaFragmentDefault.selectedDate ) }, BottomSheetPrimaryItem(true) @@ -112,7 +112,11 @@ class AgendaFragment : Fragment(), CoroutineScope { activity.navView.bottomBar.fabExtendedText = getString(R.string.add) activity.navView.bottomBar.fabIcon = CommunityMaterial.Icon3.cmd_plus activity.navView.setFabOnClickListener { - EventManualDialog(activity, app.profileId, defaultDate = agendaDefault?.selectedDate) + EventManualDialog( + activity, + app.profileId, + defaultDate = AgendaFragmentDefault.selectedDate + ) } activity.gainAttention() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt index 9e4e31ab..dff2722c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt @@ -7,7 +7,10 @@ package pl.szczodrzynski.edziennik.ui.modules.agenda import android.util.SparseIntArray import androidx.core.util.forEach import androidx.core.util.set +import com.github.tibolte.agendacalendarview.CalendarManager import com.github.tibolte.agendacalendarview.CalendarPickerController +import com.github.tibolte.agendacalendarview.agenda.AgendaAdapter +import com.github.tibolte.agendacalendarview.models.BaseCalendarEvent import com.github.tibolte.agendacalendarview.models.CalendarEvent import com.github.tibolte.agendacalendarview.models.IDayItem import kotlinx.coroutines.Dispatchers @@ -15,6 +18,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.MainActivity +import pl.szczodrzynski.edziennik.data.db.full.EventFull import pl.szczodrzynski.edziennik.databinding.FragmentAgendaDefaultBinding import pl.szczodrzynski.edziennik.ui.dialogs.day.DayDialog import pl.szczodrzynski.edziennik.ui.dialogs.lessonchange.LessonChangeDialog @@ -33,30 +37,39 @@ class AgendaFragmentDefault( private val app: App, private val b: FragmentAgendaDefaultBinding ) { + companion object { + var selectedDate: Date = Date.getToday() + } + private val unreadDates = mutableSetOf() - var selectedDate: Date = Date.getToday() + private val events = mutableListOf() + private var isInitialized = false suspend fun initView(fragment: AgendaFragment) { - val dateStart = app.profile.dateSemester1Start.asCalendar - val dateEnd = app.profile.dateYearEnd.asCalendar - - val events = withContext(Dispatchers.Default) { - val events = mutableListOf() + isInitialized = false + withContext(Dispatchers.Default) { addLessonChanges(events) val showTeacherAbsences = app.profile.getStudentData("showTeacherAbsences", true) if (showTeacherAbsences) { addTeacherAbsence(events) } - - addEvents(events) - - return@withContext events } - if (!fragment.isAdded) - return + app.db.eventDao().getAll(app.profileId).observe(fragment) { + addEvents(events, it) + if (isInitialized) + updateView() + else + initViewPriv() + } + } + + private fun initViewPriv() { + val dateStart = app.profile.dateSemester1Start.asCalendar + val dateEnd = app.profile.dateYearEnd.asCalendar + b.agendaDefaultView.init( events, dateStart, @@ -71,7 +84,11 @@ class AgendaFragmentDefault( when (event) { is AgendaEvent -> DayDialog(activity, app.profileId, date) is LessonChangesEvent -> LessonChangeDialog(activity, app.profileId, date) - is TeacherAbsenceEvent -> TeacherAbsenceDialog(activity, app.profileId, date) + is TeacherAbsenceEvent -> TeacherAbsenceDialog( + activity, + app.profileId, + date + ) } } @@ -91,10 +108,25 @@ class AgendaFragmentDefault( LessonChangesEventRenderer(), TeacherAbsenceEventRenderer() ) + + isInitialized = true } - private fun addEvents(events: MutableList) { - val eventList = app.db.eventDao().getAllNow(app.profileId) + private fun updateView() { + val manager = CalendarManager.getInstance() + manager.events.clear() + manager.loadEvents(events, BaseCalendarEvent()) + + val adapter = b.agendaDefaultView.agendaView.agendaListView.adapter as? AgendaAdapter + adapter?.updateEvents(manager.events) + b.agendaDefaultView.agendaView.agendaListView.scrollToCurrentDate(selectedDate.asCalendar) + } + + private fun addEvents( + events: MutableList, + eventList: List + ) { + events.removeAll { it is AgendaEvent } events += eventList.map { if (!it.seen) From b14ef5cd78e93fdc2b715855b855862290211f8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sat, 10 Apr 2021 18:49:24 +0200 Subject: [PATCH 03/15] [Agenda] Limit event text to 3 lines max. --- app/src/main/res/layout/agenda_event_item.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/layout/agenda_event_item.xml b/app/src/main/res/layout/agenda_event_item.xml index b07106f5..5f4ff89a 100644 --- a/app/src/main/res/layout/agenda_event_item.xml +++ b/app/src/main/res/layout/agenda_event_item.xml @@ -22,6 +22,8 @@ android:id="@+id/eventTitle" android:layout_width="match_parent" android:layout_height="match_parent" + android:ellipsize="end" + android:maxLines="3" android:textSize="16sp" tools:text="sprawdzian - Język polski" /> From 3eae8fb58b1bbedecedf2d629752ea1264d82199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sat, 10 Apr 2021 20:51:29 +0200 Subject: [PATCH 04/15] [Agenda] Add config dialog. Add compact mode. --- .../edziennik/config/ProfileConfigUI.kt | 30 ++++ .../ui/dialogs/agenda/AgendaConfigDialog.kt | 93 +++++++++++ .../ui/modules/agenda/AgendaFragment.kt | 10 +- .../modules/agenda/AgendaFragmentDefault.kt | 19 ++- .../agenda/event/AgendaEventRenderer.kt | 6 +- .../settings/cards/SettingsRegisterCard.kt | 8 + app/src/main/res/layout/agenda_event_item.xml | 67 ++++---- .../main/res/layout/dialog_config_agenda.xml | 148 ++++++++++++++++++ app/src/main/res/values/strings.xml | 14 ++ 9 files changed, 359 insertions(+), 36 deletions(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/agenda/AgendaConfigDialog.kt create mode 100644 app/src/main/res/layout/dialog_config_agenda.xml diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigUI.kt b/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigUI.kt index 5ce237a0..ca22cb76 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigUI.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigUI.kt @@ -15,6 +15,36 @@ class ProfileConfigUI(private val config: ProfileConfig) { get() { mAgendaViewType = mAgendaViewType ?: config.values.get("agendaViewType", 0); return mAgendaViewType ?: AGENDA_DEFAULT } set(value) { config.set("agendaViewType", value); mAgendaViewType = value } + private var mAgendaCompactMode: Boolean? = null + var agendaCompactMode: Boolean + get() { mAgendaCompactMode = mAgendaCompactMode ?: config.values.get("agendaCompactMode", false); return mAgendaCompactMode ?: false } + set(value) { config.set("agendaCompactMode", value); mAgendaCompactMode = value } + + private var mAgendaGroupByType: Boolean? = null + var agendaGroupByType: Boolean + get() { mAgendaGroupByType = mAgendaGroupByType ?: config.values.get("agendaGroupByType", false); return mAgendaGroupByType ?: false } + set(value) { config.set("agendaGroupByType", value); mAgendaGroupByType = value } + + private var mAgendaLessonChanges: Boolean? = null + var agendaLessonChanges: Boolean + get() { mAgendaLessonChanges = mAgendaLessonChanges ?: config.values.get("agendaLessonChanges", true); return mAgendaLessonChanges ?: true } + set(value) { config.set("agendaLessonChanges", value); mAgendaLessonChanges = value } + + private var mAgendaTeacherAbsence: Boolean? = null + var agendaTeacherAbsence: Boolean + get() { mAgendaTeacherAbsence = mAgendaTeacherAbsence ?: config.values.get("agendaTeacherAbsence", true); return mAgendaTeacherAbsence ?: true } + set(value) { config.set("agendaTeacherAbsence", value); mAgendaTeacherAbsence = value } + + private var mAgendaElearningMark: Boolean? = null + var agendaElearningMark: Boolean + get() { mAgendaElearningMark = mAgendaElearningMark ?: config.values.get("agendaElearningMark", false); return mAgendaElearningMark ?: false } + set(value) { config.set("agendaElearningMark", value); mAgendaElearningMark = value } + + private var mAgendaElearningGroup: Boolean? = null + var agendaElearningGroup: Boolean + get() { mAgendaElearningGroup = mAgendaElearningGroup ?: config.values.get("agendaElearningGroup", true); return mAgendaElearningGroup ?: true } + set(value) { config.set("agendaElearningGroup", value); mAgendaElearningGroup = value } + private var mHomeCards: List? = null var homeCards: List get() { mHomeCards = mHomeCards ?: config.values.get("homeCards", listOf(), HomeCardModel::class.java); return mHomeCards ?: listOf() } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/agenda/AgendaConfigDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/agenda/AgendaConfigDialog.kt new file mode 100644 index 00000000..150d7d65 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/agenda/AgendaConfigDialog.kt @@ -0,0 +1,93 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-4-10. + */ + +package pl.szczodrzynski.edziennik.ui.dialogs.agenda + +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import pl.szczodrzynski.edziennik.* +import pl.szczodrzynski.edziennik.data.db.entity.Profile +import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.REGISTRATION_ENABLED +import pl.szczodrzynski.edziennik.databinding.DialogConfigAgendaBinding +import pl.szczodrzynski.edziennik.ui.dialogs.sync.RegistrationConfigDialog +import java.util.* + +class AgendaConfigDialog( + private val activity: AppCompatActivity, + private val reloadOnDismiss: Boolean = true, + private val onShowListener: ((tag: String) -> Unit)? = null, + private val onDismissListener: ((tag: String) -> Unit)? = null +) { + companion object { + const val TAG = "AgendaConfigDialog" + } + + private val app by lazy { activity.application as App } + private val config by lazy { app.config.ui } + private val profileConfig by lazy { app.config.forProfile().ui } + + private lateinit var b: DialogConfigAgendaBinding + private lateinit var dialog: AlertDialog + + init { run { + if (activity.isFinishing) + return@run + b = DialogConfigAgendaBinding.inflate(activity.layoutInflater) + onShowListener?.invoke(TAG) + dialog = MaterialAlertDialogBuilder(activity) + .setTitle(R.string.menu_agenda_config) + .setView(b.root) + .setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() } + .setOnDismissListener { + saveConfig() + onDismissListener?.invoke(TAG) + if (reloadOnDismiss) (activity as? MainActivity)?.reloadTarget() + } + .create() + loadConfig() + dialog.show() + }} + + private fun loadConfig() { + b.config = profileConfig + b.isAgendaMode = profileConfig.agendaViewType == Profile.AGENDA_DEFAULT + + b.eventSharingEnabled.isChecked = app.profile.enableSharedEvents + && app.profile.registration == REGISTRATION_ENABLED + b.eventSharingEnabled.onChange { _, isChecked -> + if (isChecked && app.profile.registration != REGISTRATION_ENABLED) { + b.eventSharingEnabled.isChecked = false + val dialog = RegistrationConfigDialog(activity, app.profile, onChangeListener = { enabled -> + b.eventSharingEnabled.isChecked = enabled + setEventSharingEnabled(enabled) + }, onShowListener, onDismissListener) + dialog.showEnableDialog() + return@onChange + } + setEventSharingEnabled(isChecked) + } + } + + private fun setEventSharingEnabled(enabled: Boolean) { + if (enabled == app.profile.enableSharedEvents) + return + app.profile.enableSharedEvents = enabled + app.profileSave() + MaterialAlertDialogBuilder(activity) + .setTitle(R.string.event_sharing) + .setMessage( + if (enabled) + R.string.settings_register_shared_events_dialog_enabled_text + else + R.string.settings_register_shared_events_dialog_disabled_text + ) + .setPositiveButton(R.string.ok, null) + .show() + } + + private fun saveConfig() { + + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt index 0d5fd425..8d228dcc 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt @@ -25,6 +25,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.databinding.FragmentAgendaCalendarBinding import pl.szczodrzynski.edziennik.databinding.FragmentAgendaDefaultBinding +import pl.szczodrzynski.edziennik.ui.dialogs.agenda.AgendaConfigDialog import pl.szczodrzynski.edziennik.ui.dialogs.day.DayDialog import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog import pl.szczodrzynski.edziennik.utils.Themes @@ -78,6 +79,13 @@ class AgendaFragment : Fragment(), CoroutineScope { defaultDate = AgendaFragmentDefault.selectedDate ) }, + BottomSheetPrimaryItem(true) + .withTitle(R.string.menu_agenda_config) + .withIcon(CommunityMaterial.Icon.cmd_cog_outline) + .withOnClickListener { + activity.bottomSheet.close() + AgendaConfigDialog(activity, true, null, null) + }, BottomSheetPrimaryItem(true) .withTitle(R.string.menu_agenda_change_view) .withIcon(if (type == Profile.AGENDA_DEFAULT) CommunityMaterial.Icon.cmd_calendar_outline else CommunityMaterial.Icon2.cmd_format_list_bulleted_square) @@ -135,8 +143,6 @@ class AgendaFragment : Fragment(), CoroutineScope { agendaDefault = AgendaFragmentDefault(activity, app, b) agendaDefault?.initView(this@AgendaFragment) - - b.progressBar.visibility = View.GONE }}} private fun createCalendarAgendaView() { (b as? FragmentAgendaCalendarBinding)?.let { b -> launch { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt index dff2722c..680eeb18 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt @@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.ui.modules.agenda import android.util.SparseIntArray import androidx.core.util.forEach import androidx.core.util.set +import androidx.core.view.isVisible import com.github.tibolte.agendacalendarview.CalendarManager import com.github.tibolte.agendacalendarview.CalendarPickerController import com.github.tibolte.agendacalendarview.agenda.AgendaAdapter @@ -21,6 +22,7 @@ import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.data.db.full.EventFull import pl.szczodrzynski.edziennik.databinding.FragmentAgendaDefaultBinding import pl.szczodrzynski.edziennik.ui.dialogs.day.DayDialog +import pl.szczodrzynski.edziennik.ui.dialogs.event.EventDetailsDialog import pl.szczodrzynski.edziennik.ui.dialogs.lessonchange.LessonChangeDialog import pl.szczodrzynski.edziennik.ui.dialogs.teacherabsence.TeacherAbsenceDialog import pl.szczodrzynski.edziennik.ui.modules.agenda.event.AgendaEvent @@ -44,17 +46,17 @@ class AgendaFragmentDefault( private val unreadDates = mutableSetOf() private val events = mutableListOf() private var isInitialized = false + private val profileConfig by lazy { app.config.forProfile().ui } suspend fun initView(fragment: AgendaFragment) { isInitialized = false withContext(Dispatchers.Default) { - addLessonChanges(events) + if (profileConfig.agendaLessonChanges) + addLessonChanges(events) - val showTeacherAbsences = app.profile.getStudentData("showTeacherAbsences", true) - if (showTeacherAbsences) { + if (profileConfig.agendaTeacherAbsence) addTeacherAbsence(events) - } } app.db.eventDao().getAll(app.profileId).observe(fragment) { @@ -70,6 +72,8 @@ class AgendaFragmentDefault( val dateStart = app.profile.dateSemester1Start.asCalendar val dateEnd = app.profile.dateYearEnd.asCalendar + val isCompactMode = profileConfig.agendaCompactMode + b.agendaDefaultView.init( events, dateStart, @@ -82,13 +86,15 @@ class AgendaFragmentDefault( val date = Date.fromCalendar(event.instanceDay) when (event) { - is AgendaEvent -> DayDialog(activity, app.profileId, date) + is AgendaEvent -> EventDetailsDialog(activity, event.event) is LessonChangesEvent -> LessonChangeDialog(activity, app.profileId, date) is TeacherAbsenceEvent -> TeacherAbsenceDialog( activity, app.profileId, date ) + is BaseCalendarEvent -> if (event.isPlaceHolder) + DayDialog(activity, app.profileId, date) } } @@ -104,12 +110,13 @@ class AgendaFragmentDefault( } } }, - AgendaEventRenderer(), + AgendaEventRenderer(isCompactMode), LessonChangesEventRenderer(), TeacherAbsenceEventRenderer() ) isInitialized = true + b.progressBar.isVisible = false } private fun updateView() { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt index da28ffd5..6e78776a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt @@ -11,13 +11,17 @@ import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.AgendaWrappedEventBinding import pl.szczodrzynski.edziennik.utils.Colors -class AgendaEventRenderer : EventRenderer() { +class AgendaEventRenderer( + private val isCompact: Boolean +) : EventRenderer() { @SuppressLint("SetTextI18n") override fun render(view: View, aEvent: AgendaEvent) { val b = AgendaWrappedEventBinding.bind(view).item val event = aEvent.event + b.isCompact = isCompact + b.card.setCardBackgroundColor(event.eventColor) b.eventTitle.setTextColor(Colors.legibleTextColor(event.eventColor)) b.eventSubtitle.setTextColor(Colors.legibleTextColor(event.eventColor)) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/cards/SettingsRegisterCard.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/cards/SettingsRegisterCard.kt index 36239083..3dacd82d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/cards/SettingsRegisterCard.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/cards/SettingsRegisterCard.kt @@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.after import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_LIBRUS import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.REGISTRATION_ENABLED +import pl.szczodrzynski.edziennik.ui.dialogs.agenda.AgendaConfigDialog import pl.szczodrzynski.edziennik.ui.dialogs.bell.BellSyncConfigDialog import pl.szczodrzynski.edziennik.ui.dialogs.grade.GradesConfigDialog import pl.szczodrzynski.edziennik.ui.dialogs.settings.AttendanceConfigDialog @@ -58,6 +59,13 @@ class SettingsRegisterCard(util: SettingsUtil) : SettingsCard(util) { } override fun getItems() = listOfNotNull( + util.createActionItem( + text = R.string.menu_agenda_config, + icon = CommunityMaterial.Icon.cmd_calendar_outline + ) { + AgendaConfigDialog(activity, reloadOnDismiss = false) + }, + util.createActionItem( text = R.string.menu_grades_config, icon = CommunityMaterial.Icon3.cmd_numeric_5_box_outline diff --git a/app/src/main/res/layout/agenda_event_item.xml b/app/src/main/res/layout/agenda_event_item.xml index 5f4ff89a..c70c4a95 100644 --- a/app/src/main/res/layout/agenda_event_item.xml +++ b/app/src/main/res/layout/agenda_event_item.xml @@ -3,37 +3,50 @@ ~ Copyright (c) Kuba Szczodrzyński 2021-4-8. --> - + xmlns:tools="http://schemas.android.com/tools"> - + + + + + + + + app:cardCornerRadius="5dp" + tools:cardBackgroundColor="@color/blue_selected"> - - - - - + android:orientation="vertical" + android:padding="10dp"> + + + + + + + diff --git a/app/src/main/res/layout/dialog_config_agenda.xml b/app/src/main/res/layout/dialog_config_agenda.xml new file mode 100644 index 00000000..475c9d84 --- /dev/null +++ b/app/src/main/res/layout/dialog_config_agenda.xml @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e5f21e05..6f3021e4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1425,4 +1425,18 @@ Aby móc zapisać wygenerowany plan lekcji musisz przyznać uprawnienia dostępu do pamięci urządzenia.\n\nKliknij OK, aby przyznać uprawnienia. przeczytanie Polityki prywatności i akceptujesz jej postanowienia.

Autorzy aplikacji nie biorą odpowiedzialności za korzystanie z aplikacji Szkolny.eu.]]>
Szkolny.eu v%s\n%s + Ustawienia terminarza + Wygląd + Pokazuj zmiany planu lekcji + Pokazuj nieobecności nauczycieli + Tryb kompaktowy + Mniejszy rozmiar wydarzeń na liście + Grupuj wydarzenia tego samego typu + Niedostępne w trybie kalendarza + Udostępnianie wydarzeń + Włącz Udostępnianie wydarzeń + Nauczanie zdalne + Ustaw wydarzenia jako lekcje on-line + Wybierz rodzaj wydarzeń + Grupuj lekcje on-line na liście From 777ae945e0e8ce7d477449d83f10bbd3242f711c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sat, 10 Apr 2021 22:26:43 +0200 Subject: [PATCH 05/15] [Agenda] Implement grouping events by type. --- .../modules/agenda/AgendaFragmentDefault.kt | 34 ++++++++++-- .../modules/agenda/event/AgendaEventGroup.kt | 23 ++++++++ .../agenda/event/AgendaEventGroupRenderer.kt | 31 +++++++++++ app/src/main/res/layout/agenda_group_item.xml | 55 +++++++++++++++++++ .../main/res/layout/agenda_wrapped_group.xml | 18 ++++++ 5 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroup.kt create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroupRenderer.kt create mode 100644 app/src/main/res/layout/agenda_group_item.xml create mode 100644 app/src/main/res/layout/agenda_wrapped_group.xml diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt index 680eeb18..9aaf3d5a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt @@ -26,6 +26,8 @@ import pl.szczodrzynski.edziennik.ui.dialogs.event.EventDetailsDialog import pl.szczodrzynski.edziennik.ui.dialogs.lessonchange.LessonChangeDialog import pl.szczodrzynski.edziennik.ui.dialogs.teacherabsence.TeacherAbsenceDialog import pl.szczodrzynski.edziennik.ui.modules.agenda.event.AgendaEvent +import pl.szczodrzynski.edziennik.ui.modules.agenda.event.AgendaEventGroup +import pl.szczodrzynski.edziennik.ui.modules.agenda.event.AgendaEventGroupRenderer import pl.szczodrzynski.edziennik.ui.modules.agenda.event.AgendaEventRenderer import pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchanges.LessonChangesEvent import pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchanges.LessonChangesEventRenderer @@ -111,6 +113,7 @@ class AgendaFragmentDefault( } }, AgendaEventRenderer(isCompactMode), + AgendaEventGroupRenderer(), LessonChangesEventRenderer(), TeacherAbsenceEventRenderer() ) @@ -135,10 +138,33 @@ class AgendaFragmentDefault( ) { events.removeAll { it is AgendaEvent } - events += eventList.map { - if (!it.seen) - unreadDates.add(it.date.value) - AgendaEvent(it) + if (!profileConfig.agendaGroupByType) { + events += eventList.map { + if (!it.seen) + unreadDates.add(it.date.value) + AgendaEvent(it) + } + return + } + + eventList.groupBy { + it.date.value to it.type + }.forEach { (_, list) -> + val event = list.first() + if (list.size == 1) { + if (!event.seen) + unreadDates.add(event.date.value) + events += AgendaEvent(event) + } + else { + events.add(0, AgendaEventGroup( + profileId = event.profileId, + date = event.date, + typeName = event.typeName ?: "-", + typeColor = event.typeColor ?: event.eventColor, + eventCount = list.size + )) + } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroup.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroup.kt new file mode 100644 index 00000000..60e5f769 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroup.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-4-10. + */ + +package pl.szczodrzynski.edziennik.ui.modules.agenda.event + +import pl.szczodrzynski.edziennik.ui.modules.agenda.BaseEvent +import pl.szczodrzynski.edziennik.utils.models.Date + +class AgendaEventGroup( + val profileId: Int, + val date: Date, + val typeName: String, + val typeColor: Int, + val eventCount: Int +) : BaseEvent( + id = date.value.toLong(), + time = date.asCalendar, + color = typeColor, + showBadge = false +) { + override fun copy() = AgendaEventGroup(profileId, date, typeName, typeColor, eventCount) +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroupRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroupRenderer.kt new file mode 100644 index 00000000..191f526c --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroupRenderer.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-4-10. + */ + +package pl.szczodrzynski.edziennik.ui.modules.agenda.event + +import android.view.View +import com.github.tibolte.agendacalendarview.render.EventRenderer +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.databinding.AgendaWrappedGroupBinding +import pl.szczodrzynski.edziennik.resolveAttr +import pl.szczodrzynski.edziennik.setTintColor +import pl.szczodrzynski.edziennik.utils.Colors + +class AgendaEventGroupRenderer : EventRenderer() { + + override fun render(view: View, event: AgendaEventGroup) { + val b = AgendaWrappedGroupBinding.bind(view).item + + b.foreground.foreground.setTintColor(event.typeColor) + b.background.background.setTintColor(event.typeColor) + b.name.background.setTintColor(event.typeColor) + b.name.text = event.typeName + b.name.setTextColor(Colors.legibleTextColor(event.typeColor)) + b.count.text = event.eventCount.toString() + b.count.background.setTintColor(android.R.attr.colorBackground.resolveAttr(view.context)) + } + + override fun getEventLayout(): Int = R.layout.agenda_wrapped_group +} + diff --git a/app/src/main/res/layout/agenda_group_item.xml b/app/src/main/res/layout/agenda_group_item.xml new file mode 100644 index 00000000..23d3486d --- /dev/null +++ b/app/src/main/res/layout/agenda_group_item.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/layout/agenda_wrapped_group.xml b/app/src/main/res/layout/agenda_wrapped_group.xml new file mode 100644 index 00000000..6b081d8e --- /dev/null +++ b/app/src/main/res/layout/agenda_wrapped_group.xml @@ -0,0 +1,18 @@ + + + + + + + From f5ceaa9afe612d8104d6a5fa04147cbf81a5df94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sun, 11 Apr 2021 22:08:33 +0200 Subject: [PATCH 06/15] [Agenda] Add unread badges to events and groups. --- .../ui/dialogs/event/EventDetailsDialog.kt | 4 + .../modules/agenda/AgendaFragmentDefault.kt | 117 ++++++++++++++++-- .../edziennik/ui/modules/agenda/BaseEvent.kt | 11 +- .../ui/modules/agenda/event/AgendaEvent.kt | 7 +- .../modules/agenda/event/AgendaEventGroup.kt | 7 +- .../agenda/event/AgendaEventGroupRenderer.kt | 12 +- .../agenda/event/AgendaEventRenderer.kt | 68 +++++++--- .../lessonchanges/LessonChangesEvent.kt | 10 +- .../LessonChangesEventRenderer.kt | 23 +++- .../teacherabsence/TeacherAbsenceEvent.kt | 4 +- .../TeacherAbsenceEventRenderer.kt | 19 ++- .../main/res/layout/agenda_counter_item.xml | 61 +++++++++ .../res/layout/agenda_event_compact_item.xml | 57 +++++++++ app/src/main/res/layout/agenda_event_item.xml | 66 ++++++---- app/src/main/res/layout/agenda_group_item.xml | 23 ++-- ...changes.xml => agenda_wrapped_counter.xml} | 6 +- ...e.xml => agenda_wrapped_event_compact.xml} | 6 +- 17 files changed, 407 insertions(+), 94 deletions(-) create mode 100644 app/src/main/res/layout/agenda_counter_item.xml create mode 100644 app/src/main/res/layout/agenda_event_compact_item.xml rename app/src/main/res/layout/{agenda_wrapped_lesson_changes.xml => agenda_wrapped_counter.xml} (83%) rename app/src/main/res/layout/{agenda_wrapped_teacher_absence.xml => agenda_wrapped_event_compact.xml} (83%) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt index cdd2e50a..0958188e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt @@ -92,6 +92,10 @@ class EventDetailsDialog( b.eventShared = eventShared b.eventOwn = eventOwn + if (!event.seen) { + app.eventManager.markAsSeen(event) + } + val bullet = " • " val colorSecondary = android.R.attr.textColorSecondary.resolveAttr(activity) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt index 9aaf3d5a..1aee0ab7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt @@ -5,6 +5,8 @@ package pl.szczodrzynski.edziennik.ui.modules.agenda import android.util.SparseIntArray +import android.widget.AbsListView +import android.widget.AbsListView.OnScrollListener import androidx.core.util.forEach import androidx.core.util.set import androidx.core.view.isVisible @@ -14,9 +16,7 @@ import com.github.tibolte.agendacalendarview.agenda.AgendaAdapter import com.github.tibolte.agendacalendarview.models.BaseCalendarEvent import com.github.tibolte.agendacalendarview.models.CalendarEvent import com.github.tibolte.agendacalendarview.models.IDayItem -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.data.db.full.EventFull @@ -40,16 +40,67 @@ class AgendaFragmentDefault( private val activity: MainActivity, private val app: App, private val b: FragmentAgendaDefaultBinding -) { +) : OnScrollListener, CoroutineScope { companion object { var selectedDate: Date = Date.getToday() } + override val coroutineContext = Job() + Dispatchers.Main + private val unreadDates = mutableSetOf() private val events = mutableListOf() private var isInitialized = false private val profileConfig by lazy { app.config.forProfile().ui } + private val listView + get() = b.agendaDefaultView.agendaView.agendaListView + private val adapter + get() = listView.adapter as? AgendaAdapter + private val manager + get() = CalendarManager.getInstance() + + // TODO: 2021-04-11 find a way to attach the OnScrollListener automatically + // then set this to IDLE by default + // the FAB also needs the original listener, though + private var scrollState = OnScrollListener.SCROLL_STATE_TOUCH_SCROLL + private var updatePending = false + private var notifyPending = false + override fun onScrollStateChanged(view: AbsListView?, newScrollState: Int) { + scrollState = newScrollState + if (updatePending) updateData() + if (notifyPending) notifyDataSetChanged() + } + + /** + * Mark the data as needing update, either after 1 second (when + * not scrolling) or 1 second after scrolling stops. + */ + private fun updateData() = launch { + if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) { + updatePending = false + delay(1000) + notifyDataSetChanged() + } else updatePending = true + } + + /** + * Notify the adapter about changes, either instantly or after + * scrolling stops. + */ + private fun notifyDataSetChanged() { + if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) { + notifyPending = false + adapter?.notifyDataSetChanged() + } else notifyPending = true + } + + override fun onScroll( + view: AbsListView?, + firstVisibleItem: Int, + visibleItemCount: Int, + totalItemCount: Int + ) = Unit + suspend fun initView(fragment: AgendaFragment) { isInitialized = false @@ -95,9 +146,22 @@ class AgendaFragmentDefault( app.profileId, date ) + is AgendaEventGroup -> DayDialog(activity, app.profileId, date) is BaseCalendarEvent -> if (event.isPlaceHolder) DayDialog(activity, app.profileId, date) } + + if (event is BaseEvent && event.showItemBadge) { + val unreadCount = manager.events.count { + it.instanceDay.equals(event.instanceDay) && it.showBadge + } + // only clicked event is unread, remove the day badge + if (unreadCount == 1 && event.showBadge) { + event.dayReference.showBadge = false + unreadDates.remove(date.value) + } + setAsRead(event) + } } override fun onScrollToDate(calendar: Calendar) { @@ -105,6 +169,7 @@ class AgendaFragmentDefault( // Mark as read scrolled date if (selectedDate.value in unreadDates) { + setAsRead(calendar) activity.launch(Dispatchers.Default) { app.db.eventDao().setSeenByDate(app.profileId, selectedDate, true) } @@ -123,20 +188,45 @@ class AgendaFragmentDefault( } private fun updateView() { - val manager = CalendarManager.getInstance() manager.events.clear() manager.loadEvents(events, BaseCalendarEvent()) - val adapter = b.agendaDefaultView.agendaView.agendaListView.adapter as? AgendaAdapter adapter?.updateEvents(manager.events) - b.agendaDefaultView.agendaView.agendaListView.scrollToCurrentDate(selectedDate.asCalendar) + listView.scrollToCurrentDate(selectedDate.asCalendar) + } + + private fun setAsRead(date: Calendar) { + // get all events matching the date + val events = manager.events.filter { + if (it.instanceDay.equals(date) && it.showBadge && it is AgendaEvent) { + // hide the day badge for the date + it.dayReference.showBadge = false + return@filter true + } + false + } + // set this date's events as read + setAsRead(*events.toTypedArray()) + } + + private fun setAsRead(vararg event: CalendarEvent) { + // hide per-event badges + for (e in event) { + events.firstOrNull { + it == e + }?.showBadge = false + e.showBadge = false + } + + listView.setOnScrollListener(this) + updateData() } private fun addEvents( events: MutableList, eventList: List ) { - events.removeAll { it is AgendaEvent } + events.removeAll { it is AgendaEvent || it is AgendaEventGroup } if (!profileConfig.agendaGroupByType) { events += eventList.map { @@ -155,14 +245,14 @@ class AgendaFragmentDefault( if (!event.seen) unreadDates.add(event.date.value) events += AgendaEvent(event) - } - else { + } else { events.add(0, AgendaEventGroup( profileId = event.profileId, date = event.date, typeName = event.typeName ?: "-", typeColor = event.typeColor ?: event.eventColor, - eventCount = list.size + count = list.size, + showBadge = list.any { !it.seen } )) } } @@ -179,7 +269,8 @@ class AgendaFragmentDefault( LessonChangesEvent( app.profileId, date = date ?: return@mapNotNull null, - changeCount = changes.size + count = changes.size, + showBadge = changes.any { !it.seen } ) } } @@ -200,7 +291,7 @@ class AgendaFragmentDefault( events += TeacherAbsenceEvent( app.profileId, date = Date.fromValue(dateInt), - absenceCount = count + count = count ) } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/BaseEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/BaseEvent.kt index f183485b..62569504 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/BaseEvent.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/BaseEvent.kt @@ -13,7 +13,8 @@ open class BaseEvent( private val id: Long, private val time: Calendar, private val color: Int, - private val showBadge: Boolean + private var showBadge: Boolean, + var showItemBadge: Boolean = showBadge ) : CalendarEvent { override fun copy() = BaseEvent(id, time, color, showBadge) @@ -36,6 +37,12 @@ open class BaseEvent( weekReference = value } + override fun getShowBadge() = showBadge + override fun setShowBadge(value: Boolean) { + showBadge = value + showItemBadge = value + } + override fun getId() = id override fun getStartTime() = time override fun getEndTime() = time @@ -44,7 +51,6 @@ open class BaseEvent( override fun getLocation() = "" override fun getColor() = color override fun getTextColor() = 0 - override fun getShowBadge() = showBadge override fun isPlaceholder() = false override fun isAllDay() = false @@ -55,7 +61,6 @@ open class BaseEvent( override fun setDescription(value: String) = Unit override fun setLocation(value: String) = Unit override fun setTextColor(value: Int) = Unit - override fun setShowBadge(value: Boolean) = Unit override fun setPlaceholder(value: Boolean) = Unit override fun setAllDay(value: Boolean) = Unit } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEvent.kt index 3cd05727..e6ba6e23 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEvent.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEvent.kt @@ -8,12 +8,13 @@ import pl.szczodrzynski.edziennik.data.db.full.EventFull import pl.szczodrzynski.edziennik.ui.modules.agenda.BaseEvent class AgendaEvent( - val event: EventFull + val event: EventFull, + showBadge: Boolean = !event.seen ) : BaseEvent( id = event.id, time = event.startTimeCalendar, color = event.eventColor, - showBadge = !event.seen + showBadge = showBadge ) { - override fun copy() = AgendaEvent(event) + override fun copy() = AgendaEvent(event, showBadge) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroup.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroup.kt index 60e5f769..e50be2c3 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroup.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroup.kt @@ -12,12 +12,13 @@ class AgendaEventGroup( val date: Date, val typeName: String, val typeColor: Int, - val eventCount: Int + val count: Int, + showBadge: Boolean ) : BaseEvent( id = date.value.toLong(), time = date.asCalendar, color = typeColor, - showBadge = false + showBadge = showBadge ) { - override fun copy() = AgendaEventGroup(profileId, date, typeName, typeColor, eventCount) + override fun copy() = AgendaEventGroup(profileId, date, typeName, typeColor, count, showBadge) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroupRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroupRenderer.kt index 191f526c..2a1f9af8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroupRenderer.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroupRenderer.kt @@ -5,6 +5,7 @@ package pl.szczodrzynski.edziennik.ui.modules.agenda.event import android.view.View +import androidx.core.view.isVisible import com.github.tibolte.agendacalendarview.render.EventRenderer import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.AgendaWrappedGroupBinding @@ -17,13 +18,14 @@ class AgendaEventGroupRenderer : EventRenderer() { override fun render(view: View, event: AgendaEventGroup) { val b = AgendaWrappedGroupBinding.bind(view).item - b.foreground.foreground.setTintColor(event.typeColor) - b.background.background.setTintColor(event.typeColor) - b.name.background.setTintColor(event.typeColor) + b.card.foreground.setTintColor(event.color) + b.card.background.setTintColor(event.color) b.name.text = event.typeName - b.name.setTextColor(Colors.legibleTextColor(event.typeColor)) - b.count.text = event.eventCount.toString() + b.name.setTextColor(Colors.legibleTextColor(event.color)) + b.count.text = event.count.toString() b.count.background.setTintColor(android.R.attr.colorBackground.resolveAttr(view.context)) + + b.badge.isVisible = event.showItemBadge } override fun getEventLayout(): Int = R.layout.agenda_wrapped_group diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt index 6e78776a..dafdb853 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt @@ -6,36 +6,72 @@ package pl.szczodrzynski.edziennik.ui.modules.agenda.event import android.annotation.SuppressLint import android.view.View +import androidx.core.view.isVisible import com.github.tibolte.agendacalendarview.render.EventRenderer import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.AgendaWrappedEventBinding +import pl.szczodrzynski.edziennik.databinding.AgendaWrappedEventCompactBinding +import pl.szczodrzynski.edziennik.join +import pl.szczodrzynski.edziennik.resolveAttr +import pl.szczodrzynski.edziennik.setTintColor import pl.szczodrzynski.edziennik.utils.Colors class AgendaEventRenderer( - private val isCompact: Boolean + val isCompact: Boolean ) : EventRenderer() { @SuppressLint("SetTextI18n") override fun render(view: View, aEvent: AgendaEvent) { - val b = AgendaWrappedEventBinding.bind(view).item val event = aEvent.event - b.isCompact = isCompact + val timeText = if (event.time == null) + view.context.getString(R.string.agenda_event_all_day) + else + event.time!!.stringHM - b.card.setCardBackgroundColor(event.eventColor) - b.eventTitle.setTextColor(Colors.legibleTextColor(event.eventColor)) - b.eventSubtitle.setTextColor(Colors.legibleTextColor(event.eventColor)) + val eventTitle = "${event.typeName ?: "wydarzenie"} - ${event.topic}" - b.eventTitle.text = "${event.typeName ?: "wydarzenie"} - ${event.topic}" - b.eventSubtitle.text = - (if (event.time == null) - view.context.getString(R.string.agenda_event_all_day) - else - event.time!!.stringHM) + - (event.subjectLongName?.let { ", $it" } ?: "") + - (event.teacherName?.let { ", $it" } ?: "") + - (event.teamName?.let { ", $it" } ?: "") + val eventSubtitle = listOfNotNull( + timeText, + event.subjectLongName, + event.teacherName, + event.teamName + ).join(", ") + + if (isCompact) { + val b = AgendaWrappedEventCompactBinding.bind(view).item + + b.card.foreground.setTintColor(event.eventColor) + b.card.background.setTintColor(event.eventColor) + b.title.text = eventTitle + b.title.setTextColor(Colors.legibleTextColor(event.eventColor)) + + b.badgeBackground.isVisible = aEvent.showItemBadge + b.badgeBackground.background.setTintColor( + android.R.attr.colorBackground.resolveAttr(view.context) + ) + b.badge.isVisible = aEvent.showItemBadge + } + else { + val b = AgendaWrappedEventBinding.bind(view).item + + b.card.foreground.setTintColor(event.eventColor) + b.card.background.setTintColor(event.eventColor) + b.title.text = eventTitle + b.title.setTextColor(Colors.legibleTextColor(event.eventColor)) + b.subtitle.text = eventSubtitle + b.subtitle.setTextColor(Colors.legibleTextColor(event.eventColor)) + + b.badgeBackground.isVisible = aEvent.showItemBadge + b.badgeBackground.background.setTintColor( + android.R.attr.colorBackground.resolveAttr(view.context) + ) + b.badge.isVisible = aEvent.showItemBadge + } } - override fun getEventLayout(): Int = R.layout.agenda_wrapped_event + override fun getEventLayout() = if (isCompact) + R.layout.agenda_wrapped_event_compact + else + R.layout.agenda_wrapped_event } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEvent.kt index e65c82bd..b38d8829 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEvent.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEvent.kt @@ -10,12 +10,16 @@ import pl.szczodrzynski.edziennik.utils.models.Date class LessonChangesEvent( val profileId: Int, val date: Date, - val changeCount: Int + val count: Int, + showBadge: Boolean ) : BaseEvent( id = date.value.toLong(), time = date.asCalendar, color = 0xff78909c.toInt(), - showBadge = false + showBadge = false, + showItemBadge = showBadge ) { - override fun copy() = LessonChangesEvent(profileId, date, changeCount) + override fun copy() = LessonChangesEvent(profileId, date, count, showItemBadge) + + override fun getShowBadge() = false } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt index 5ffc788c..8b8ff81b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt @@ -5,17 +5,32 @@ package pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchanges import android.view.View +import androidx.core.view.isVisible import com.github.tibolte.agendacalendarview.render.EventRenderer import pl.szczodrzynski.edziennik.R -import pl.szczodrzynski.edziennik.databinding.AgendaWrappedLessonChangesBinding +import pl.szczodrzynski.edziennik.databinding.AgendaWrappedCounterBinding +import pl.szczodrzynski.edziennik.resolveAttr +import pl.szczodrzynski.edziennik.setTintColor +import pl.szczodrzynski.edziennik.utils.Colors class LessonChangesEventRenderer : EventRenderer() { override fun render(view: View, event: LessonChangesEvent) { - val b = AgendaWrappedLessonChangesBinding.bind(view).item + val b = AgendaWrappedCounterBinding.bind(view).item - b.lessonChangeCount.text = event.changeCount.toString() + b.card.foreground.setTintColor(event.color) + b.card.background.setTintColor(event.color) + b.name.setText(R.string.agenda_lesson_changes) + b.name.setTextColor(Colors.legibleTextColor(event.color)) + b.count.text = event.count.toString() + b.count.setTextColor(b.name.currentTextColor) + + b.badgeBackground.isVisible = event.showItemBadge + b.badgeBackground.background.setTintColor( + android.R.attr.colorBackground.resolveAttr(view.context) + ) + b.badge.isVisible = event.showItemBadge } - override fun getEventLayout(): Int = R.layout.agenda_wrapped_lesson_changes + override fun getEventLayout(): Int = R.layout.agenda_wrapped_counter } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEvent.kt index 4208814b..b0b01f50 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEvent.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEvent.kt @@ -10,12 +10,12 @@ import pl.szczodrzynski.edziennik.utils.models.Date class TeacherAbsenceEvent( val profileId: Int, val date: Date, - val absenceCount: Int + val count: Int ) : BaseEvent( id = date.value.toLong(), time = date.asCalendar, color = 0xffff1744.toInt(), showBadge = false ) { - override fun copy() = TeacherAbsenceEvent(profileId, date, absenceCount) + override fun copy() = TeacherAbsenceEvent(profileId, date, count) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt index 756c60c9..ec0a3915 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt @@ -5,17 +5,28 @@ package pl.szczodrzynski.edziennik.ui.modules.agenda.teacherabsence import android.view.View +import androidx.core.view.isVisible import com.github.tibolte.agendacalendarview.render.EventRenderer import pl.szczodrzynski.edziennik.R -import pl.szczodrzynski.edziennik.databinding.AgendaWrappedTeacherAbsenceBinding +import pl.szczodrzynski.edziennik.databinding.AgendaWrappedCounterBinding +import pl.szczodrzynski.edziennik.setTintColor +import pl.szczodrzynski.edziennik.utils.Colors class TeacherAbsenceEventRenderer : EventRenderer() { override fun render(view: View, event: TeacherAbsenceEvent) { - val b = AgendaWrappedTeacherAbsenceBinding.bind(view).item + val b = AgendaWrappedCounterBinding.bind(view).item - b.teacherAbsenceCount.text = event.absenceCount.toString() + b.card.foreground.setTintColor(event.color) + b.card.background.setTintColor(event.color) + b.name.setText(R.string.agenda_teacher_absence) + b.name.setTextColor(Colors.legibleTextColor(event.color)) + b.count.text = event.count.toString() + b.count.setTextColor(b.name.currentTextColor) + + b.badgeBackground.isVisible = false + b.badge.isVisible = false } - override fun getEventLayout(): Int = R.layout.agenda_wrapped_teacher_absence + override fun getEventLayout(): Int = R.layout.agenda_wrapped_counter } diff --git a/app/src/main/res/layout/agenda_counter_item.xml b/app/src/main/res/layout/agenda_counter_item.xml new file mode 100644 index 00000000..334c419c --- /dev/null +++ b/app/src/main/res/layout/agenda_counter_item.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/agenda_event_compact_item.xml b/app/src/main/res/layout/agenda_event_compact_item.xml new file mode 100644 index 00000000..df48e70c --- /dev/null +++ b/app/src/main/res/layout/agenda_event_compact_item.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/agenda_event_item.xml b/app/src/main/res/layout/agenda_event_item.xml index c70c4a95..3ede7682 100644 --- a/app/src/main/res/layout/agenda_event_item.xml +++ b/app/src/main/res/layout/agenda_event_item.xml @@ -3,50 +3,64 @@ ~ Copyright (c) Kuba Szczodrzyński 2021-4-8. --> - + - - - - - - - - + android:orientation="horizontal"> + tools:text="sprawdzian - Język polski" + tools:textColor="@color/md_white_1000" /> + tools:text="9:05, biologia, Jan Kowalski, 7a" + tools:textColor="@color/md_white_1000" /> - - + + + + + + diff --git a/app/src/main/res/layout/agenda_group_item.xml b/app/src/main/res/layout/agenda_group_item.xml index 23d3486d..4787a8cf 100644 --- a/app/src/main/res/layout/agenda_group_item.xml +++ b/app/src/main/res/layout/agenda_group_item.xml @@ -5,33 +5,29 @@ + android:orientation="horizontal"> @@ -43,7 +39,6 @@ android:layout_marginRight="-1dp" android:background="@drawable/bg_rounded_8dp" android:gravity="center" - android:paddingVertical="10dp" android:paddingStart="16dp" android:paddingLeft="16dp" android:paddingEnd="18dp" @@ -52,4 +47,12 @@ tools:backgroundTint="?android:colorBackground" tools:text="3" /> + + diff --git a/app/src/main/res/layout/agenda_wrapped_lesson_changes.xml b/app/src/main/res/layout/agenda_wrapped_counter.xml similarity index 83% rename from app/src/main/res/layout/agenda_wrapped_lesson_changes.xml rename to app/src/main/res/layout/agenda_wrapped_counter.xml index 834d2ddd..31864636 100644 --- a/app/src/main/res/layout/agenda_wrapped_lesson_changes.xml +++ b/app/src/main/res/layout/agenda_wrapped_counter.xml @@ -1,4 +1,8 @@ + + diff --git a/app/src/main/res/layout/agenda_wrapped_teacher_absence.xml b/app/src/main/res/layout/agenda_wrapped_event_compact.xml similarity index 83% rename from app/src/main/res/layout/agenda_wrapped_teacher_absence.xml rename to app/src/main/res/layout/agenda_wrapped_event_compact.xml index 4793b0d8..997c24db 100644 --- a/app/src/main/res/layout/agenda_wrapped_teacher_absence.xml +++ b/app/src/main/res/layout/agenda_wrapped_event_compact.xml @@ -1,4 +1,8 @@ + + From 12619f6bde218e251745438b0a474223f0bda656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Mon, 12 Apr 2021 11:50:54 +0200 Subject: [PATCH 07/15] [Agenda] Update scroll listeners code. --- app/build.gradle | 2 +- .../modules/agenda/AgendaFragmentDefault.kt | 27 +++++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 72c03e94..26ac63c8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -152,7 +152,7 @@ dependencies { implementation "pl.droidsonroids.retrofit2:converter-jspoon:1.3.2" // Szkolny.eu libraries/forks - implementation "eu.szkolny:agendacalendarview:1799f8ef47" + implementation "eu.szkolny:agendacalendarview:5431f03098" implementation "eu.szkolny:cafebar:5bf0c618de" implementation "eu.szkolny.fslogin:lib:2.0.0" implementation "eu.szkolny:material-about-library:1d5ebaf47c" diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt index 1aee0ab7..eb6f74fb 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt @@ -59,18 +59,28 @@ class AgendaFragmentDefault( private val manager get() = CalendarManager.getInstance() - // TODO: 2021-04-11 find a way to attach the OnScrollListener automatically - // then set this to IDLE by default - // the FAB also needs the original listener, though - private var scrollState = OnScrollListener.SCROLL_STATE_TOUCH_SCROLL + private var scrollState = OnScrollListener.SCROLL_STATE_IDLE private var updatePending = false private var notifyPending = false override fun onScrollStateChanged(view: AbsListView?, newScrollState: Int) { + b.agendaDefaultView.agendaScrollListener.onScrollStateChanged(view, scrollState) scrollState = newScrollState if (updatePending) updateData() if (notifyPending) notifyDataSetChanged() } + override fun onScroll( + view: AbsListView?, + firstVisibleItem: Int, + visibleItemCount: Int, + totalItemCount: Int + ) = b.agendaDefaultView.agendaScrollListener.onScroll( + view, + firstVisibleItem, + visibleItemCount, + totalItemCount + ) + /** * Mark the data as needing update, either after 1 second (when * not scrolling) or 1 second after scrolling stops. @@ -94,13 +104,6 @@ class AgendaFragmentDefault( } else notifyPending = true } - override fun onScroll( - view: AbsListView?, - firstVisibleItem: Int, - visibleItemCount: Int, - totalItemCount: Int - ) = Unit - suspend fun initView(fragment: AgendaFragment) { isInitialized = false @@ -183,6 +186,8 @@ class AgendaFragmentDefault( TeacherAbsenceEventRenderer() ) + listView.setOnScrollListener(this) + isInitialized = true b.progressBar.isVisible = false } From 5eaa754401277f956b52a9cc3b555c48b943ee03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Tue, 13 Apr 2021 20:50:51 +0200 Subject: [PATCH 08/15] [UI] Add icons for done and manual events. --- .../agenda/event/AgendaEventRenderer.kt | 81 ++++++++++++------- .../LessonChangesEventRenderer.kt | 5 +- .../TeacherAbsenceEventRenderer.kt | 5 +- .../res/layout/agenda_event_compact_item.xml | 2 +- app/src/main/res/layout/agenda_event_item.xml | 2 +- 5 files changed, 60 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt index dafdb853..ac65fcef 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt @@ -6,8 +6,15 @@ package pl.szczodrzynski.edziennik.ui.modules.agenda.event import android.annotation.SuppressLint import android.view.View +import android.widget.FrameLayout +import android.widget.TextView import androidx.core.view.isVisible import com.github.tibolte.agendacalendarview.render.EventRenderer +import com.mikepenz.iconics.IconicsDrawable +import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial +import com.mikepenz.iconics.utils.colorInt +import com.mikepenz.iconics.utils.sizeDp +import com.mikepenz.iconics.view.IconicsTextView import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.AgendaWrappedEventBinding import pl.szczodrzynski.edziennik.databinding.AgendaWrappedEventCompactBinding @@ -22,14 +29,33 @@ class AgendaEventRenderer( @SuppressLint("SetTextI18n") override fun render(view: View, aEvent: AgendaEvent) { + if (isCompact) { + val b = AgendaWrappedEventCompactBinding.bind(view).item + bindView(aEvent, b.card, b.title, null, b.badgeBackground, b.badge) + } else { + val b = AgendaWrappedEventBinding.bind(view).item + bindView(aEvent, b.card, b.title, b.subtitle, b.badgeBackground, b.badge) + } + } + + private fun bindView( + aEvent: AgendaEvent, + card: FrameLayout, + title: IconicsTextView, + subtitle: TextView?, + badgeBackground: View, + badge: View + ) { val event = aEvent.event + val textColor = Colors.legibleTextColor(event.eventColor) + val timeText = if (event.time == null) - view.context.getString(R.string.agenda_event_all_day) + card.context.getString(R.string.agenda_event_all_day) else event.time!!.stringHM - val eventTitle = "${event.typeName ?: "wydarzenie"} - ${event.topic}" + var eventTitle = "${event.typeName ?: "wydarzenie"} - ${event.topic}" val eventSubtitle = listOfNotNull( timeText, @@ -38,36 +64,33 @@ class AgendaEventRenderer( event.teamName ).join(", ") - if (isCompact) { - val b = AgendaWrappedEventCompactBinding.bind(view).item - - b.card.foreground.setTintColor(event.eventColor) - b.card.background.setTintColor(event.eventColor) - b.title.text = eventTitle - b.title.setTextColor(Colors.legibleTextColor(event.eventColor)) - - b.badgeBackground.isVisible = aEvent.showItemBadge - b.badgeBackground.background.setTintColor( - android.R.attr.colorBackground.resolveAttr(view.context) - ) - b.badge.isVisible = aEvent.showItemBadge + if (event.addedManually) { + eventTitle = "{cmd-clipboard-edit-outline} $eventTitle" } - else { - val b = AgendaWrappedEventBinding.bind(view).item - b.card.foreground.setTintColor(event.eventColor) - b.card.background.setTintColor(event.eventColor) - b.title.text = eventTitle - b.title.setTextColor(Colors.legibleTextColor(event.eventColor)) - b.subtitle.text = eventSubtitle - b.subtitle.setTextColor(Colors.legibleTextColor(event.eventColor)) + card.foreground.setTintColor(event.eventColor) + card.background.setTintColor(event.eventColor) + title.text = eventTitle + title.setTextColor(textColor) + subtitle?.text = eventSubtitle + subtitle?.setTextColor(textColor) - b.badgeBackground.isVisible = aEvent.showItemBadge - b.badgeBackground.background.setTintColor( - android.R.attr.colorBackground.resolveAttr(view.context) - ) - b.badge.isVisible = aEvent.showItemBadge - } + title.setCompoundDrawables( + null, + null, + if (event.isDone) IconicsDrawable(card.context).apply { + icon = CommunityMaterial.Icon.cmd_check + colorInt = textColor + sizeDp = 24 + } else null, + null + ) + + badgeBackground.isVisible = aEvent.showItemBadge + badgeBackground.background.setTintColor( + android.R.attr.colorBackground.resolveAttr(card.context) + ) + badge.isVisible = aEvent.showItemBadge } override fun getEventLayout() = if (isCompact) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt index 8b8ff81b..2a904016 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt @@ -17,13 +17,14 @@ class LessonChangesEventRenderer : EventRenderer() { override fun render(view: View, event: LessonChangesEvent) { val b = AgendaWrappedCounterBinding.bind(view).item + val textColor = Colors.legibleTextColor(event.color) b.card.foreground.setTintColor(event.color) b.card.background.setTintColor(event.color) b.name.setText(R.string.agenda_lesson_changes) - b.name.setTextColor(Colors.legibleTextColor(event.color)) + b.name.setTextColor(textColor) b.count.text = event.count.toString() - b.count.setTextColor(b.name.currentTextColor) + b.count.setTextColor(textColor) b.badgeBackground.isVisible = event.showItemBadge b.badgeBackground.background.setTintColor( diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt index ec0a3915..12dd1947 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt @@ -16,13 +16,14 @@ class TeacherAbsenceEventRenderer : EventRenderer() { override fun render(view: View, event: TeacherAbsenceEvent) { val b = AgendaWrappedCounterBinding.bind(view).item + val textColor = Colors.legibleTextColor(event.color) b.card.foreground.setTintColor(event.color) b.card.background.setTintColor(event.color) b.name.setText(R.string.agenda_teacher_absence) - b.name.setTextColor(Colors.legibleTextColor(event.color)) + b.name.setTextColor(textColor) b.count.text = event.count.toString() - b.count.setTextColor(b.name.currentTextColor) + b.count.setTextColor(textColor) b.badgeBackground.isVisible = false b.badge.isVisible = false diff --git a/app/src/main/res/layout/agenda_event_compact_item.xml b/app/src/main/res/layout/agenda_event_compact_item.xml index df48e70c..b97ddfa3 100644 --- a/app/src/main/res/layout/agenda_event_compact_item.xml +++ b/app/src/main/res/layout/agenda_event_compact_item.xml @@ -25,7 +25,7 @@ android:orientation="vertical" android:padding="10dp"> - - Date: Wed, 14 Apr 2021 10:16:22 +0200 Subject: [PATCH 09/15] [UI] Fix updating event dialog when editing or removing. --- .../ui/dialogs/event/EventDetailsDialog.kt | 14 +++++++++++--- .../ui/dialogs/event/EventManualDialog.kt | 3 +++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt index 0958188e..664cc078 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt @@ -32,7 +32,7 @@ import kotlin.coroutines.CoroutineContext class EventDetailsDialog( val activity: AppCompatActivity, - val event: EventFull, + var event: EventFull, val onShowListener: ((tag: String) -> Unit)? = null, val onDismissListener: ((tag: String) -> Unit)? = null ) : CoroutineScope { @@ -139,6 +139,7 @@ class EventDetailsDialog( launch(Dispatchers.Default) { app.db.eventDao().replace(event) } + update() b.checkDoneButton.isChecked = true } .setNegativeButton(R.string.cancel, null) @@ -149,6 +150,7 @@ class EventDetailsDialog( launch(Dispatchers.Default) { app.db.eventDao().replace(event) } + update() } } b.checkDoneButton.attachToastHint(R.string.hint_mark_as_done) @@ -160,6 +162,14 @@ class EventDetailsDialog( activity, event.profileId, editingEvent = event, + onSaveListener = { + if (it == null) { + dialog.dismiss() + return@EventManualDialog + } + event = it + update() + }, onShowListener = onShowListener, onDismissListener = onDismissListener ) @@ -327,8 +337,6 @@ class EventDetailsDialog( removeEventDialog?.dismiss() dialog.dismiss() Toast.makeText(activity, R.string.removed, Toast.LENGTH_SHORT).show() - if (activity is MainActivity && activity.navTargetId == MainActivity.DRAWER_ITEM_AGENDA) - activity.reloadTarget() } private fun openInCalendar() { launch { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt index 9beac76b..a40c5772 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt @@ -48,6 +48,7 @@ class EventManualDialog( val defaultTime: Time? = null, val defaultType: Long? = null, val editingEvent: EventFull? = null, + val onSaveListener: ((event: EventFull?) -> Unit)? = null, val onShowListener: ((tag: String) -> Unit)? = null, val onDismissListener: ((tag: String) -> Unit)? = null ) : CoroutineScope { @@ -596,6 +597,7 @@ class EventManualDialog( } } + onSaveListener?.invoke(eventObject.withMetadata(metadataObject)) dialog.dismiss() Toast.makeText(activity, R.string.saved, Toast.LENGTH_SHORT).show() } @@ -608,6 +610,7 @@ class EventManualDialog( } removeEventDialog?.dismiss() + onSaveListener?.invoke(null) dialog.dismiss() Toast.makeText(activity, R.string.removed, Toast.LENGTH_SHORT).show() } From db598af28aa73cba9f6cf02ddd0c9b1bfcab9cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Wed, 14 Apr 2021 10:20:00 +0200 Subject: [PATCH 10/15] [UI] Add legend in event details dialog. --- .../ui/dialogs/event/EventDetailsDialog.kt | 6 ++++++ app/src/main/res/layout/dialog_event_details.xml | 14 ++++++++++++++ app/src/main/res/values/strings.xml | 2 ++ 3 files changed, 22 insertions(+) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt index 664cc078..4feb1d53 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt @@ -104,6 +104,12 @@ class EventDetailsDialog( } catch (_: Exception) {} + b.legend.text = listOfNotNull( + if (event.addedManually) R.string.legend_event_added_manually else null, + if (event.isDone) R.string.legend_event_is_done else null + ).map { activity.getString(it) }.join("\n") + b.legend.isVisible = b.legend.text.isNotBlank() + b.typeColor.background?.setTintColor(event.eventColor) b.details = mutableListOf( diff --git a/app/src/main/res/layout/dialog_event_details.xml b/app/src/main/res/layout/dialog_event_details.xml index 7a77a813..a2fe00f5 100644 --- a/app/src/main/res/layout/dialog_event_details.xml +++ b/app/src/main/res/layout/dialog_event_details.xml @@ -105,9 +105,23 @@ + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6f3021e4..303100f2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1439,4 +1439,6 @@ Ustaw wydarzenia jako lekcje on-line Wybierz rodzaj wydarzeń Grupuj lekcje on-line na liście + {cmd-clipboard-edit-outline} wydarzenie dodane ręcznie + {cmd-check} oznaczono jako wykonane From 297867cbf3ed09ad73f30f1f1d28d910de1f49b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Wed, 14 Apr 2021 11:21:45 +0200 Subject: [PATCH 11/15] [UI] Add event type colors to type dropdown. --- .../ui/dialogs/event/EventManualDialog.kt | 69 +++++------ .../ui/modules/views/EventTypeDropdown.kt | 111 ++++++++++++++++++ .../ui/modules/views/TeacherDropdown.kt | 6 + .../edziennik/utils/TextInputDropDown.kt | 42 ++++++- .../res/layout/dialog_event_manual_v2.xml | 2 +- 5 files changed, 181 insertions(+), 49 deletions(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/EventTypeDropdown.kt diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt index a40c5772..0cd2affe 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt @@ -4,8 +4,6 @@ package pl.szczodrzynski.edziennik.ui.dialogs.event -import android.graphics.PorterDuff -import android.graphics.PorterDuffColorFilter import android.view.View import android.widget.Toast import androidx.appcompat.app.AlertDialog @@ -26,7 +24,6 @@ import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskFinishedEvent import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi import pl.szczodrzynski.edziennik.data.db.entity.Event -import pl.szczodrzynski.edziennik.data.db.entity.EventType import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Profile import pl.szczodrzynski.edziennik.data.db.full.EventFull @@ -35,7 +32,6 @@ import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding import pl.szczodrzynski.edziennik.ui.dialogs.sync.RegistrationConfigDialog import pl.szczodrzynski.edziennik.ui.modules.views.TimeDropdown.Companion.DISPLAY_LESSONS import pl.szczodrzynski.edziennik.utils.Anim -import pl.szczodrzynski.edziennik.utils.TextInputDropDown import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Time import kotlin.coroutines.CoroutineContext @@ -323,57 +319,41 @@ class EventManualDialog( selectDefault(defaultLesson?.displayTeacherId) } + with (b.typeDropdown) { + db = app.db + profileId = this@EventManualDialog.profileId + loadItems() + selectDefault(editingEvent?.type) + selectDefault(defaultType) - val deferred = async(Dispatchers.Default) { - // get the event type list - var eventTypes = app.db.eventTypeDao().getAllNow(profileId) - - if (eventTypes.none { it.id in -1L..10L }) { - eventTypes = app.db.eventTypeDao().addDefaultTypes(activity, profileId) + onTypeSelected = { + b.typeColor.background.setTintColor(it.color) + customColor = null } - - b.typeDropdown.clear() - b.typeDropdown += eventTypes.map { TextInputDropDown.Item(it.id, it.name, tag = it) } - } - deferred.await() - - b.typeDropdown.isEnabled = true - - defaultType?.let { - b.typeDropdown.select(it) } - b.typeDropdown.selected?.let { item -> - customColor = (item.tag as EventType).color - } - - // copy IDs from event being edited + // copy data from event being edited editingEvent?.let { b.topic.setText(it.topic) - b.typeDropdown.select(it.type)?.let { item -> - customColor = (item.tag as EventType).color - } - if (it.color != null && it.color != -1) + if (it.color != -1) customColor = it.color } + b.typeColor.background.setTintColor( + customColor + ?: b.typeDropdown.getSelected()?.color + ?: Event.COLOR_DEFAULT + ) + // copy IDs from the LessonFull defaultLesson?.let { b.teamDropdown.select(it.displayTeamId) } - b.typeDropdown.setOnChangeListener { - b.typeColor.background.colorFilter = PorterDuffColorFilter((it.tag as EventType).color, PorterDuff.Mode.SRC_ATOP) - customColor = null - return@setOnChangeListener true - } - - (customColor ?: Event.COLOR_DEFAULT).let { - b.typeColor.background.colorFilter = PorterDuffColorFilter(it, PorterDuff.Mode.SRC_ATOP) - } - b.typeColor.onClick { - val currentColor = (b.typeDropdown.selected?.tag as EventType?)?.color ?: Event.COLOR_DEFAULT + val currentColor = customColor + ?: b.typeDropdown.getSelected()?.color + ?: Event.COLOR_DEFAULT val colorPickerDialog = ColorPickerDialog.newBuilder() .setColor(currentColor) .create() @@ -381,7 +361,7 @@ class EventManualDialog( object : ColorPickerDialogListener { override fun onDialogDismissed(dialogId: Int) {} override fun onColorSelected(dialogId: Int, color: Int) { - b.typeColor.background.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP) + b.typeColor.background.setTintColor(color) customColor = color } }) @@ -597,7 +577,12 @@ class EventManualDialog( } } - onSaveListener?.invoke(eventObject.withMetadata(metadataObject)) + onSaveListener?.invoke(eventObject.withMetadata(metadataObject).also { + it.subjectLongName = b.subjectDropdown.selected?.text?.toString() + it.teacherName = b.teacherDropdown.selected?.text?.toString() + it.teamName = b.teamDropdown.selected?.text?.toString() + it.typeName = b.typeDropdown.selected?.text?.toString() + }) dialog.dismiss() Toast.makeText(activity, R.string.saved, Toast.LENGTH_SHORT).show() } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/EventTypeDropdown.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/EventTypeDropdown.kt new file mode 100644 index 00000000..5527c50e --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/EventTypeDropdown.kt @@ -0,0 +1,111 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2021-4-14. + */ + +package pl.szczodrzynski.edziennik.ui.modules.views + +import android.content.Context +import android.content.ContextWrapper +import android.util.AttributeSet +import androidx.appcompat.app.AppCompatActivity +import com.mikepenz.iconics.IconicsDrawable +import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial +import com.mikepenz.iconics.utils.colorInt +import com.mikepenz.iconics.utils.sizeDp +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import pl.szczodrzynski.edziennik.data.db.AppDb +import pl.szczodrzynski.edziennik.data.db.entity.EventType +import pl.szczodrzynski.edziennik.utils.TextInputDropDown + +class EventTypeDropdown : TextInputDropDown { + constructor(context: Context) : super(context) + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) + + private val activity: AppCompatActivity? + get() { + var context: Context? = context ?: return null + if (context is AppCompatActivity) return context + while (context is ContextWrapper) { + if (context is AppCompatActivity) + return context + context = context.baseContext + } + return null + } + + lateinit var db: AppDb + var profileId: Int = 0 + var onTypeSelected: ((eventType: EventType) -> Unit)? = null + + override fun create(context: Context) { + super.create(context) + isEnabled = false + } + + suspend fun loadItems() { + val types = withContext(Dispatchers.Default) { + val list = mutableListOf() + + var types = db.eventTypeDao().getAllNow(profileId) + + if (types.none { it.id in -1L..10L }) { + types = db.eventTypeDao().addDefaultTypes(context, profileId) + } + + list += types.map { + Item(it.id, it.name, tag = it, icon = IconicsDrawable(context).apply { + icon = CommunityMaterial.Icon.cmd_circle + sizeDp = 24 + colorInt = it.color + }) + } + + list + } + + clear().append(types) + isEnabled = true + + setOnChangeListener { + when (it.tag) { + is EventType -> { + // selected an event type + onTypeSelected?.invoke(it.tag) + true + } + else -> false + } + } + } + + /** + * Select an event type by the [typeId]. + */ + fun selectType(typeId: Long) { + select(typeId) + } + + /** + * Select an event type by the [typeId] **if it's not selected yet**. + */ + fun selectDefault(typeId: Long?) { + if (typeId == null || selected != null) + return + selectType(typeId) + } + + /** + * Get the currently selected event type. + * ### Returns: + * - null if no valid type is selected + * - [EventType] - the selected event type + */ + fun getSelected(): EventType? { + return when (selected?.tag) { + is EventType -> selected?.tag as EventType + else -> null + } + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TeacherDropdown.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TeacherDropdown.kt index 6411426b..684412f1 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TeacherDropdown.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TeacherDropdown.kt @@ -84,6 +84,9 @@ class TeacherDropdown : TextInputDropDown { } } + /** + * Select a teacher by the [teacherId]. + */ fun selectTeacher(teacherId: Long) { if (select(teacherId) == null) select(Item( @@ -93,6 +96,9 @@ class TeacherDropdown : TextInputDropDown { )) } + /** + * Select a teacher by the [teacherId] **if it's not selected yet**. + */ fun selectDefault(teacherId: Long?) { if (teacherId == null || selected != null) return diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/TextInputDropDown.kt b/app/src/main/java/pl/szczodrzynski/edziennik/utils/TextInputDropDown.kt index f8836374..19aa27d6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/TextInputDropDown.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/TextInputDropDown.kt @@ -1,7 +1,11 @@ package pl.szczodrzynski.edziennik.utils +import android.annotation.SuppressLint import android.content.Context +import android.graphics.drawable.Drawable import android.util.AttributeSet +import androidx.appcompat.view.menu.MenuBuilder +import androidx.appcompat.view.menu.MenuPopupHelper import androidx.appcompat.widget.PopupMenu import com.google.android.material.textfield.TextInputEditText import com.mikepenz.iconics.IconicsDrawable @@ -33,6 +37,7 @@ open class TextInputDropDown : TextInputEditText { setText(selected?.displayText ?: selected?.text) } + @SuppressLint("RestrictedApi") open fun create(context: Context) { val drawable = IconicsDrawable(context, CommunityMaterial.Icon.cmd_chevron_down).apply { colorInt = Themes.getPrimaryTextColor(context) @@ -58,7 +63,9 @@ open class TextInputDropDown : TextInputEditText { val popup = PopupMenu(context, this) items.forEachIndexed { index, item -> - popup.menu.add(0, item.id.toInt(), index, item.text) + popup.menu.add(0, item.id.toInt(), index, item.text).also { + it.icon = item.icon + } } popup.setOnMenuItemClickListener { menuItem -> @@ -70,29 +77,46 @@ open class TextInputDropDown : TextInputEditText { true } - popup.setOnDismissListener { + val helper = MenuPopupHelper(context, popup.menu as MenuBuilder, this) + helper.setForceShowIcon(true) + helper.setOnDismissListener { clearFocus() } - - popup.show() + helper.show() } } - fun select(item: Item): Item? { + /** + * Select an arbitrary [item]. Allows to select an item not present + * in the original list. + */ + fun select(item: Item): Item { selected = item updateText() error = null return item } + /** + * Select an item by its ID. Returns the selected item + * if found. + */ fun select(id: Long?): Item? { return items.singleOrNull { it.id == id }?.let { select(it) } } + /** + * Select an item by its tag. Returns the selected item + * if found. + */ fun select(tag: Any?): Item? { return items.singleOrNull { it.tag == tag }?.let { select(it) } } + /** + * Select an item by its index. Returns the selected item + * if the index exists. + */ fun select(index: Int): Item? { return items.getOrNull(index)?.let { select(it) } } @@ -143,5 +167,11 @@ open class TextInputDropDown : TextInputEditText { } } - class Item(val id: Long, val text: CharSequence, val displayText: CharSequence? = null, val tag: Any? = null) + class Item( + val id: Long, + val text: CharSequence, + val displayText: CharSequence? = null, + val tag: Any? = null, + val icon: Drawable? = null + ) } diff --git a/app/src/main/res/layout/dialog_event_manual_v2.xml b/app/src/main/res/layout/dialog_event_manual_v2.xml index 8d2fc267..228fcc74 100644 --- a/app/src/main/res/layout/dialog_event_manual_v2.xml +++ b/app/src/main/res/layout/dialog_event_manual_v2.xml @@ -94,7 +94,7 @@ android:layout_weight="1" android:hint="@string/dialog_event_manual_type"> - Date: Wed, 14 Apr 2021 11:59:58 +0200 Subject: [PATCH 12/15] [UI] Refactor dropdown inputs code. --- .../ui/dialogs/event/EventManualDialog.kt | 32 +++++------ .../ui/modules/views/DateDropdown.kt | 2 +- .../ui/modules/views/EventTypeDropdown.kt | 18 +----- .../ui/modules/views/SubjectDropdown.kt | 41 +++++++------ .../ui/modules/views/TeacherDropdown.kt | 49 ++++++---------- .../ui/modules/views/TeamDropdown.kt | 57 +++++++++---------- .../ui/modules/views/TimeDropdown.kt | 2 +- .../edziennik/utils/TextInputDropDown.kt | 2 +- 8 files changed, 87 insertions(+), 116 deletions(-) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt index 0cd2affe..da684520 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt @@ -23,9 +23,7 @@ import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent import pl.szczodrzynski.edziennik.data.api.events.ApiTaskFinishedEvent import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi -import pl.szczodrzynski.edziennik.data.db.entity.Event -import pl.szczodrzynski.edziennik.data.db.entity.Metadata -import pl.szczodrzynski.edziennik.data.db.entity.Profile +import pl.szczodrzynski.edziennik.data.db.entity.* import pl.szczodrzynski.edziennik.data.db.full.EventFull import pl.szczodrzynski.edziennik.data.db.full.LessonFull import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding @@ -396,11 +394,11 @@ class EventManualDialog( private fun saveEvent() { val date = b.dateDropdown.getSelected() as? Date val timeSelected = b.timeDropdown.getSelected() - val teamId = b.teamDropdown.getSelected() as? Long - val type = b.typeDropdown.selected?.id + val team = b.teamDropdown.getSelected() + val type = b.typeDropdown.getSelected() val topic = b.topic.text?.toString() - val subjectId = b.subjectDropdown.getSelected() as? Long - val teacherId = b.teacherDropdown.getSelected() + val subject = b.subjectDropdown.getSelected() as? Subject + val teacher = b.teacherDropdown.getSelected() val share = b.shareSwitch.isChecked @@ -431,7 +429,7 @@ class EventManualDialog( isError = true } - if (share && teamId == null) { + if (share && team == null) { b.teamDropdown.error = app.getString(R.string.dialog_event_manual_team_choose) if (!isError) b.teamDropdown.parent.requestChildFocus(b.teamDropdown, b.teamDropdown) isError = true @@ -467,10 +465,10 @@ class EventManualDialog( time = startTime, topic = topic, color = customColor, - type = type ?: Event.TYPE_DEFAULT, - teacherId = teacherId ?: -1, - subjectId = subjectId ?: -1, - teamId = teamId ?: -1, + type = type?.id ?: Event.TYPE_DEFAULT, + teacherId = teacher?.id ?: -1, + subjectId = subject?.id ?: -1, + teamId = team?.id ?: -1, addedDate = editingEvent?.addedDate ?: System.currentTimeMillis() ).also { it.addedManually = true @@ -478,7 +476,7 @@ class EventManualDialog( val metadataObject = Metadata( profileId, - when (type) { + when (type?.id) { Event.TYPE_HOMEWORK -> Metadata.TYPE_HOMEWORK else -> Metadata.TYPE_EVENT }, @@ -578,10 +576,10 @@ class EventManualDialog( } onSaveListener?.invoke(eventObject.withMetadata(metadataObject).also { - it.subjectLongName = b.subjectDropdown.selected?.text?.toString() - it.teacherName = b.teacherDropdown.selected?.text?.toString() - it.teamName = b.teamDropdown.selected?.text?.toString() - it.typeName = b.typeDropdown.selected?.text?.toString() + it.subjectLongName = (b.subjectDropdown.getSelected() as? Subject)?.longName + it.teacherName = b.teacherDropdown.getSelected()?.fullName + it.teamName = b.teamDropdown.getSelected()?.name + it.typeName = b.typeDropdown.getSelected()?.name }) dialog.dismiss() Toast.makeText(activity, R.string.saved, Toast.LENGTH_SHORT).show() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/DateDropdown.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/DateDropdown.kt index 92bf0515..6c96c352 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/DateDropdown.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/DateDropdown.kt @@ -175,7 +175,7 @@ class DateDropdown : TextInputDropDown { } } - fun pickerDialog() { + private fun pickerDialog() { val date = getSelected() as? Date ?: Date.getToday() MaterialDatePicker.Builder.datePicker() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/EventTypeDropdown.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/EventTypeDropdown.kt index 5527c50e..878264c6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/EventTypeDropdown.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/EventTypeDropdown.kt @@ -5,9 +5,7 @@ package pl.szczodrzynski.edziennik.ui.modules.views import android.content.Context -import android.content.ContextWrapper import android.util.AttributeSet -import androidx.appcompat.app.AppCompatActivity import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import com.mikepenz.iconics.utils.colorInt @@ -23,18 +21,6 @@ class EventTypeDropdown : TextInputDropDown { constructor(context: Context, attrs: AttributeSet) : super(context, attrs) constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) - private val activity: AppCompatActivity? - get() { - var context: Context? = context ?: return null - if (context is AppCompatActivity) return context - while (context is ContextWrapper) { - if (context is AppCompatActivity) - return context - context = context.baseContext - } - return null - } - lateinit var db: AppDb var profileId: Int = 0 var onTypeSelected: ((eventType: EventType) -> Unit)? = null @@ -83,9 +69,7 @@ class EventTypeDropdown : TextInputDropDown { /** * Select an event type by the [typeId]. */ - fun selectType(typeId: Long) { - select(typeId) - } + fun selectType(typeId: Long) = select(typeId) /** * Select an event type by the [typeId] **if it's not selected yet**. diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/SubjectDropdown.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/SubjectDropdown.kt index 06e01225..4285ec7d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/SubjectDropdown.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/SubjectDropdown.kt @@ -15,6 +15,7 @@ import kotlinx.coroutines.withContext import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.crc16 import pl.szczodrzynski.edziennik.data.db.AppDb +import pl.szczodrzynski.edziennik.data.db.entity.Subject import pl.szczodrzynski.edziennik.ui.dialogs.input import pl.szczodrzynski.edziennik.utils.TextInputDropDown @@ -40,7 +41,7 @@ class SubjectDropdown : TextInputDropDown { var showNoSubject = true var showCustomSubject = false var customSubjectName = "" - var onSubjectSelected: ((subjectId: Long?) -> Unit)? = null + var onSubjectSelected: ((subject: Subject?) -> Unit)? = null var onCustomSubjectSelected: ((subjectName: String) -> Unit)? = null override fun create(context: Context) { @@ -73,7 +74,7 @@ class SubjectDropdown : TextInputDropDown { list += subjects.map { Item( it.id, it.longName, - tag = it.id + tag = it ) } list @@ -91,10 +92,11 @@ class SubjectDropdown : TextInputDropDown { } -1L -> { // no subject + deselect() onSubjectSelected?.invoke(null) - true + false } - is Long -> { + is Subject -> { // selected a subject onSubjectSelected?.invoke(it.tag) true @@ -104,7 +106,7 @@ class SubjectDropdown : TextInputDropDown { } } - fun customNameDialog() { + private fun customNameDialog() { activity ?: return MaterialAlertDialogBuilder(activity!!) .setTitle("Własny przedmiot") @@ -127,32 +129,37 @@ class SubjectDropdown : TextInputDropDown { .show() } - fun selectSubject(subjectId: Long) { - if (select(subjectId) == null) - select(Item( - subjectId, - "nieznany przedmiot ($subjectId)", - tag = subjectId - )) + /** + * Select a subject by the [subjectId]. + */ + fun selectSubject(subjectId: Long): Item? { + if (subjectId == -1L) { + deselect() + return null + } + return select(subjectId) } - fun selectDefault(subjectId: Long?) { + /** + * Select a subject by the [subjectId] **if it's not selected yet**. + */ + fun selectDefault(subjectId: Long?): Item? { if (subjectId == null || selected != null) - return - selectSubject(subjectId) + return null + return selectSubject(subjectId) } /** * Get the currently selected subject. * ### Returns: * - null if no valid subject is selected - * - [Long] - the selected subject's ID + * - [Subject] - the selected subject * - [String] - a custom subject name entered, if [showCustomSubject] == true */ fun getSelected(): Any? { return when (selected?.tag) { -1L -> null - is Long -> selected?.tag as Long + is Subject -> selected?.tag as Subject is String -> selected?.tag as String else -> null } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TeacherDropdown.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TeacherDropdown.kt index 684412f1..23053359 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TeacherDropdown.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TeacherDropdown.kt @@ -5,13 +5,12 @@ package pl.szczodrzynski.edziennik.ui.modules.views import android.content.Context -import android.content.ContextWrapper import android.util.AttributeSet -import androidx.appcompat.app.AppCompatActivity import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.data.db.AppDb +import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.utils.TextInputDropDown class TeacherDropdown : TextInputDropDown { @@ -19,22 +18,10 @@ class TeacherDropdown : TextInputDropDown { constructor(context: Context, attrs: AttributeSet) : super(context, attrs) constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) - private val activity: AppCompatActivity? - get() { - var context: Context? = context ?: return null - if (context is AppCompatActivity) return context - while (context is ContextWrapper) { - if (context is AppCompatActivity) - return context - context = context.baseContext - } - return null - } - lateinit var db: AppDb var profileId: Int = 0 var showNoTeacher = true - var onTeacherSelected: ((teacherId: Long?) -> Unit)? = null + var onTeacherSelected: ((teacher: Teacher?) -> Unit)? = null override fun create(context: Context) { super.create(context) @@ -58,7 +45,7 @@ class TeacherDropdown : TextInputDropDown { list += teachers.map { Item( it.id, it.fullName, - tag = it.id + tag = it ) } list @@ -71,10 +58,11 @@ class TeacherDropdown : TextInputDropDown { when (it.tag) { -1L -> { // no teacher + deselect() onTeacherSelected?.invoke(null) - true + false } - is Long -> { + is Teacher -> { // selected a teacher onTeacherSelected?.invoke(it.tag) true @@ -87,34 +75,33 @@ class TeacherDropdown : TextInputDropDown { /** * Select a teacher by the [teacherId]. */ - fun selectTeacher(teacherId: Long) { - if (select(teacherId) == null) - select(Item( - teacherId, - "nieznany nauczyciel ($teacherId)", - tag = teacherId - )) + fun selectTeacher(teacherId: Long): Item? { + if (teacherId == -1L) { + deselect() + return null + } + return select(teacherId) } /** * Select a teacher by the [teacherId] **if it's not selected yet**. */ - fun selectDefault(teacherId: Long?) { + fun selectDefault(teacherId: Long?): Item? { if (teacherId == null || selected != null) - return - selectTeacher(teacherId) + return null + return selectTeacher(teacherId) } /** * Get the currently selected teacher. * ### Returns: * - null if no valid teacher is selected - * - [Long] - the selected teacher's ID + * - [Teacher] - the selected teacher */ - fun getSelected(): Long? { + fun getSelected(): Teacher? { return when (selected?.tag) { -1L -> null - is Long -> selected?.tag as Long + is Teacher -> selected?.tag as Teacher else -> null } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TeamDropdown.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TeamDropdown.kt index b31d2ca8..b5eee0ac 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TeamDropdown.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TeamDropdown.kt @@ -5,9 +5,7 @@ package pl.szczodrzynski.edziennik.ui.modules.views import android.content.Context -import android.content.ContextWrapper import android.util.AttributeSet -import androidx.appcompat.app.AppCompatActivity import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import pl.szczodrzynski.edziennik.R @@ -20,22 +18,10 @@ class TeamDropdown : TextInputDropDown { constructor(context: Context, attrs: AttributeSet) : super(context, attrs) constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) - private val activity: AppCompatActivity? - get() { - var context: Context? = context ?: return null - if (context is AppCompatActivity) return context - while (context is ContextWrapper) { - if (context is AppCompatActivity) - return context - context = context.baseContext - } - return null - } - lateinit var db: AppDb var profileId: Int = 0 var showNoTeam = true - var onTeamSelected: ((teamId: Long?) -> Unit)? = null + var onTeamSelected: ((team: Team?) -> Unit)? = null override fun create(context: Context) { super.create(context) @@ -59,7 +45,7 @@ class TeamDropdown : TextInputDropDown { list += teams.map { Item( it.id, it.name, - tag = it.id + tag = it ) } list @@ -72,10 +58,11 @@ class TeamDropdown : TextInputDropDown { when (it.tag) { -1L -> { // no team + deselect() onTeamSelected?.invoke(null) - true + false } - is Long -> { + is Team -> { // selected a team onTeamSelected?.invoke(it.tag) true @@ -85,21 +72,29 @@ class TeamDropdown : TextInputDropDown { } } - fun selectTeam(teamId: Long) { - if (select(teamId) == null) - select(Item( - teamId, - "nieznana grupa ($teamId)", - tag = teamId - )) + /** + * Select a teacher by the [teamId]. + */ + fun selectTeam(teamId: Long): Item? { + if (teamId == -1L) { + deselect() + return null + } + return select(teamId) } - fun selectDefault(teamId: Long?) { + /** + * Select a team by the [teamId] **if it's not selected yet**. + */ + fun selectDefault(teamId: Long?): Item? { if (teamId == null || selected != null) - return - selectTeam(teamId) + return null + return selectTeam(teamId) } + /** + * Select a team of the [Team.TYPE_CLASS] type. + */ fun selectTeamClass() { select(items.singleOrNull { it.tag is Team && it.tag.type == Team.TYPE_CLASS @@ -110,12 +105,12 @@ class TeamDropdown : TextInputDropDown { * Get the currently selected team. * ### Returns: * - null if no valid team is selected - * - [Long] - the team's ID + * - [Team] - the selected team */ - fun getSelected(): Any? { + fun getSelected(): Team? { return when (selected?.tag) { -1L -> null - is Long -> selected?.tag as Long + is Team -> selected?.tag as Team else -> null } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TimeDropdown.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TimeDropdown.kt index 989184af..afecaf7e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TimeDropdown.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/TimeDropdown.kt @@ -175,7 +175,7 @@ class TimeDropdown : TextInputDropDown { return !noTimetable } - fun pickerDialog() { + private fun pickerDialog() { val time = (getSelected() as? Pair<*, *>)?.first as? Time ?: Time.getNow() MaterialTimePicker.Builder() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/TextInputDropDown.kt b/app/src/main/java/pl/szczodrzynski/edziennik/utils/TextInputDropDown.kt index 19aa27d6..44db5d9a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/TextInputDropDown.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/TextInputDropDown.kt @@ -33,7 +33,7 @@ open class TextInputDropDown : TextInputEditText { val selectedId get() = selected?.id - fun updateText() { + private fun updateText() { setText(selected?.displayText ?: selected?.text) } From 755b846b508bd51a5c7638f41cb95ccbb25ec06f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Wed, 14 Apr 2021 16:34:31 +0200 Subject: [PATCH 13/15] [UI/Agenda] Move common code to EventManager. --- .../ui/dialogs/event/EventDetailsDialog.kt | 10 ++-- .../ui/dialogs/event/EventListAdapter.kt | 7 ++- .../dialogs/timetable/LessonDetailsDialog.kt | 3 +- .../modules/agenda/AgendaFragmentDefault.kt | 12 +++-- .../agenda/event/AgendaEventRenderer.kt | 25 ++-------- .../attendance/AttendanceListFragment.kt | 3 +- .../attendance/AttendanceSummaryFragment.kt | 3 +- .../ui/modules/grades/GradesAdapter.kt | 3 +- .../ui/modules/grades/GradesListFragment.kt | 9 ++-- .../modules/timetable/TimetableDayFragment.kt | 3 +- .../edziennik/utils/managers/EventManager.kt | 46 ++++++++++++++++++- app/src/main/res/layout/event_list_item.xml | 23 ++-------- 12 files changed, 84 insertions(+), 63 deletions(-) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt index 4feb1d53..c80f0c63 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventDetailsDialog.kt @@ -46,6 +46,8 @@ class EventDetailsDialog( private var removeEventDialog: AlertDialog? = null private val eventShared = event.sharedBy != null private val eventOwn = event.sharedBy == "self" + private val manager + get() = app.eventManager private val job = Job() override val coroutineContext: CoroutineContext @@ -93,7 +95,7 @@ class EventDetailsDialog( b.eventOwn = eventOwn if (!event.seen) { - app.eventManager.markAsSeen(event) + manager.markAsSeen(event) } val bullet = " • " @@ -104,11 +106,7 @@ class EventDetailsDialog( } catch (_: Exception) {} - b.legend.text = listOfNotNull( - if (event.addedManually) R.string.legend_event_added_manually else null, - if (event.isDone) R.string.legend_event_is_done else null - ).map { activity.getString(it) }.join("\n") - b.legend.isVisible = b.legend.text.isNotBlank() + manager.setLegendText(b.legend, event) b.typeColor.background?.setTintColor(event.eventColor) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventListAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventListAdapter.kt index 34cc6a2d..9bb199ea 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventListAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventListAdapter.kt @@ -33,7 +33,8 @@ class EventListAdapter( ) : RecyclerView.Adapter(), CoroutineScope { private val app = context.applicationContext as App - private val manager = app.eventManager + private val manager + get() = app.eventManager private val job = Job() override val coroutineContext: CoroutineContext @@ -67,7 +68,7 @@ class EventListAdapter( b.simpleMode = simpleMode - b.topic.text = event.topic + manager.setEventTopic(b.topic, event, showType = false) b.topic.maxLines = if (simpleMode) 2 else 3 b.details.text = mutableListOf( @@ -102,8 +103,6 @@ class EventListAdapter( } b.editButton.attachToastHint(R.string.hint_edit_event) - b.isDone.isVisible = event.isDone - if (event.showAsUnseen == null) event.showAsUnseen = !event.seen diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt index f444f38e..9b43f9be 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt @@ -50,7 +50,8 @@ class LessonDetailsDialog( get() = job + Dispatchers.Main private lateinit var adapter: EventListAdapter - private val manager by lazy { app.timetableManager } + private val manager + get() = app.timetableManager init { run { if (activity.isFinishing) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt index eb6f74fb..cc25c42f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt @@ -136,7 +136,13 @@ class AgendaFragmentDefault( dateEnd, Locale.getDefault(), object : CalendarPickerController { - override fun onDaySelected(dayItem: IDayItem) {} + override fun onDaySelected(dayItem: IDayItem) { + val c = Calendar.getInstance() + c.time = dayItem.date + if (c.timeInMillis == selectedDate.inMillis) { + DayDialog(activity, app.profileId, selectedDate) + } + } override fun onEventSelected(event: CalendarEvent) { val date = Date.fromCalendar(event.instanceDay) @@ -180,7 +186,7 @@ class AgendaFragmentDefault( } } }, - AgendaEventRenderer(isCompactMode), + AgendaEventRenderer(app.eventManager, isCompactMode), AgendaEventGroupRenderer(), LessonChangesEventRenderer(), TeacherAbsenceEventRenderer() @@ -197,7 +203,7 @@ class AgendaFragmentDefault( manager.loadEvents(events, BaseCalendarEvent()) adapter?.updateEvents(manager.events) - listView.scrollToCurrentDate(selectedDate.asCalendar) + //listView.scrollToCurrentDate(selectedDate.asCalendar) } private fun setAsRead(date: Calendar) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt index ac65fcef..2e857cd3 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventRenderer.kt @@ -10,10 +10,6 @@ import android.widget.FrameLayout import android.widget.TextView import androidx.core.view.isVisible import com.github.tibolte.agendacalendarview.render.EventRenderer -import com.mikepenz.iconics.IconicsDrawable -import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial -import com.mikepenz.iconics.utils.colorInt -import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.view.IconicsTextView import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.AgendaWrappedEventBinding @@ -22,8 +18,10 @@ import pl.szczodrzynski.edziennik.join import pl.szczodrzynski.edziennik.resolveAttr import pl.szczodrzynski.edziennik.setTintColor import pl.szczodrzynski.edziennik.utils.Colors +import pl.szczodrzynski.edziennik.utils.managers.EventManager class AgendaEventRenderer( + val manager: EventManager, val isCompact: Boolean ) : EventRenderer() { @@ -55,8 +53,6 @@ class AgendaEventRenderer( else event.time!!.stringHM - var eventTitle = "${event.typeName ?: "wydarzenie"} - ${event.topic}" - val eventSubtitle = listOfNotNull( timeText, event.subjectLongName, @@ -64,28 +60,13 @@ class AgendaEventRenderer( event.teamName ).join(", ") - if (event.addedManually) { - eventTitle = "{cmd-clipboard-edit-outline} $eventTitle" - } - card.foreground.setTintColor(event.eventColor) card.background.setTintColor(event.eventColor) - title.text = eventTitle + manager.setEventTopic(title, event, doneIconColor = textColor) title.setTextColor(textColor) subtitle?.text = eventSubtitle subtitle?.setTextColor(textColor) - title.setCompoundDrawables( - null, - null, - if (event.isDone) IconicsDrawable(card.context).apply { - icon = CommunityMaterial.Icon.cmd_check - colorInt = textColor - sizeDp = 24 - } else null, - null - ) - badgeBackground.isVisible = aEvent.showItemBadge badgeBackground.background.setTintColor( android.R.attr.colorBackground.resolveAttr(card.context) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceListFragment.kt index 8e68cdbb..523dd09c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceListFragment.kt @@ -41,7 +41,8 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope { get() = job + Dispatchers.Main // local/private variables go here - private val manager by lazy { app.attendanceManager } + private val manager + get() = app.attendanceManager private var viewType = AttendanceFragment.VIEW_DAYS private var expandSubjectId = 0L diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceSummaryFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceSummaryFragment.kt index 5f61020b..39282325 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceSummaryFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceSummaryFragment.kt @@ -47,7 +47,8 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope { get() = job + Dispatchers.Main // local/private variables go here - private val manager by lazy { app.attendanceManager } + private val manager + get() = app.attendanceManager private var expandSubjectId = 0L private var attendance = listOf() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesAdapter.kt index 46c75d8d..086f073d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesAdapter.kt @@ -40,7 +40,8 @@ class GradesAdapter( } private val app = activity.applicationContext as App - private val manager = app.gradesManager + private val manager + get() = app.gradesManager private val job = Job() override val coroutineContext: CoroutineContext diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt index 63521e97..63c935ff 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt @@ -48,9 +48,12 @@ class GradesListFragment : Fragment(), CoroutineScope { get() = job + Dispatchers.Main // local/private variables go here - private val manager by lazy { app.gradesManager } - private val dontCountEnabled by lazy { manager.dontCountEnabled } - private val dontCountGrades by lazy { manager.dontCountGrades } + private val manager + get() = app.gradesManager + private val dontCountEnabled + get() = manager.dontCountEnabled + private val dontCountGrades + get() = manager.dontCountGrades private var expandSubjectId = 0L override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableDayFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableDayFragment.kt index e6464d7d..e92ca55c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableDayFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableDayFragment.kt @@ -54,7 +54,8 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope { private var endHour = DEFAULT_END_HOUR private var firstEventMinute = 24 * 60 - private val manager by lazy { app.timetableManager } + private val manager + get() = app.timetableManager // find SwipeRefreshLayout in the hierarchy private val refreshLayout by lazy { view?.findParentById(R.id.refreshLayout) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/EventManager.kt b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/EventManager.kt index ca444ca5..f5b7faa9 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/EventManager.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/EventManager.kt @@ -4,12 +4,17 @@ package pl.szczodrzynski.edziennik.utils.managers +import androidx.core.view.isVisible +import com.mikepenz.iconics.IconicsDrawable +import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial +import com.mikepenz.iconics.utils.colorInt +import com.mikepenz.iconics.utils.sizeDp +import com.mikepenz.iconics.view.IconicsTextView import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.db.full.EventFull -import pl.szczodrzynski.edziennik.startCoroutineTimer import kotlin.coroutines.CoroutineContext class EventManager(val app: App) : CoroutineScope { @@ -32,4 +37,41 @@ class EventManager(val app: App) : CoroutineScope { app.db.metadataDao().setSeen(event.profileId, event, true) } } + + fun setEventTopic( + title: IconicsTextView, + event: EventFull, + showType: Boolean = true, + doneIconColor: Int? = null + ) { + var eventTopic = if (showType) + "${event.typeName ?: "wydarzenie"} - ${event.topic}" + else + event.topic + + if (event.addedManually) { + eventTopic = "{cmd-clipboard-edit-outline} $eventTopic" + } + + title.text = eventTopic + + title.setCompoundDrawables( + null, + null, + if (event.isDone) IconicsDrawable(title.context).apply { + icon = CommunityMaterial.Icon.cmd_check + colorInt = doneIconColor ?: R.color.md_green_500.resolveColor(title.context) + sizeDp = 24 + } else null, + null + ) + } + + fun setLegendText(legend: IconicsTextView, event: EventFull) { + legend.text = listOfNotNull( + if (event.addedManually) R.string.legend_event_added_manually else null, + if (event.isDone) R.string.legend_event_is_done else null + ).map { legend.context.getString(it) }.join("\n") + legend.isVisible = legend.text.isNotBlank() + } } diff --git a/app/src/main/res/layout/event_list_item.xml b/app/src/main/res/layout/event_list_item.xml index 24445327..a69b74c0 100644 --- a/app/src/main/res/layout/event_list_item.xml +++ b/app/src/main/res/layout/event_list_item.xml @@ -4,8 +4,7 @@ --> + xmlns:android="http://schemas.android.com/apk/res/android"> @@ -61,12 +60,10 @@ android:gravity="center_vertical" android:orientation="horizontal"> - - - - + tools:visibility="visible" /> Date: Wed, 14 Apr 2021 16:59:12 +0200 Subject: [PATCH 14/15] [UI/Agenda] Update DayDialog for showing event group. --- .../edziennik/ui/dialogs/day/DayDialog.kt | 62 ++++-- .../modules/agenda/AgendaFragmentDefault.kt | 3 +- .../modules/agenda/event/AgendaEventGroup.kt | 3 +- .../LessonChangesEventRenderer.kt | 18 ++ .../TeacherAbsenceEventRenderer.kt | 15 ++ .../res/layout/agenda_lesson_changes_item.xml | 33 --- .../layout/agenda_teacher_absence_item.xml | 33 --- app/src/main/res/layout/dialog_day.xml | 192 +++++++++--------- 8 files changed, 170 insertions(+), 189 deletions(-) delete mode 100644 app/src/main/res/layout/agenda_lesson_changes_item.xml delete mode 100644 app/src/main/res/layout/agenda_teacher_absence_item.xml diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/day/DayDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/day/DayDialog.kt index e5b7768d..74ba0030 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/day/DayDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/day/DayDialog.kt @@ -7,7 +7,7 @@ package pl.szczodrzynski.edziennik.ui.dialogs.day import android.view.View import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.Observer +import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.* @@ -19,6 +19,10 @@ import pl.szczodrzynski.edziennik.ui.dialogs.event.EventListAdapter import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog import pl.szczodrzynski.edziennik.ui.dialogs.lessonchange.LessonChangeDialog import pl.szczodrzynski.edziennik.ui.dialogs.teacherabsence.TeacherAbsenceDialog +import pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchanges.LessonChangesEvent +import pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchanges.LessonChangesEventRenderer +import pl.szczodrzynski.edziennik.ui.modules.agenda.teacherabsence.TeacherAbsenceEvent +import pl.szczodrzynski.edziennik.ui.modules.agenda.teacherabsence.TeacherAbsenceEventRenderer import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Time @@ -29,6 +33,7 @@ class DayDialog( val activity: AppCompatActivity, val profileId: Int, val date: Date, + val eventTypeId: Long? = null, val onShowListener: ((tag: String) -> Unit)? = null, val onDismissListener: ((tag: String) -> Unit)? = null ) : CoroutineScope { @@ -109,38 +114,51 @@ class DayDialog( } lessonChanges.ifNotEmpty { - b.lessonChangeContainer.root.visibility = View.VISIBLE - b.lessonChangeContainer.lessonChangeCount.text = it.size.toString() + LessonChangesEventRenderer().render( + b.lessonChanges, LessonChangesEvent( + profileId = profileId, + date = date, + count = it.size, + showBadge = false + ) + ) - b.lessonChangeLayout.onClick { + b.lessonChangesFrame.onClick { LessonChangeDialog( - activity, - profileId, - date, - onShowListener = onShowListener, - onDismissListener = onDismissListener + activity, + profileId, + date, + onShowListener = onShowListener, + onDismissListener = onDismissListener ) } } + b.lessonChangesFrame.isVisible = lessonChanges.isNotEmpty() val teacherAbsences = withContext(Dispatchers.Default) { app.db.teacherAbsenceDao().getAllByDateNow(profileId, date) } teacherAbsences.ifNotEmpty { - b.teacherAbsenceContainer.root.visibility = View.VISIBLE - b.teacherAbsenceContainer.teacherAbsenceCount.text = it.size.toString() + TeacherAbsenceEventRenderer().render( + b.teacherAbsence, TeacherAbsenceEvent( + profileId = profileId, + date = date, + count = it.size + ) + ) - b.teacherAbsenceLayout.onClick { + b.teacherAbsenceFrame.onClick { TeacherAbsenceDialog( - activity, - profileId, - date, - onShowListener = onShowListener, - onDismissListener = onDismissListener + activity, + profileId, + date, + onShowListener = onShowListener, + onDismissListener = onDismissListener ) } } + b.teacherAbsenceFrame.isVisible = teacherAbsences.isNotEmpty() adapter = EventListAdapter( activity, @@ -169,8 +187,12 @@ class DayDialog( } ) - app.db.eventDao().getAllByDate(profileId, date).observe(activity, Observer { events -> - adapter.items = events + app.db.eventDao().getAllByDate(profileId, date).observe(activity) { events -> + adapter.items = if (eventTypeId != null) + events.filter { it.type == eventTypeId } + else + events + if (b.eventsView.adapter == null) { b.eventsView.adapter = adapter b.eventsView.apply { @@ -189,6 +211,6 @@ class DayDialog( b.eventsView.visibility = View.GONE b.eventsNoData.visibility = View.VISIBLE } - }) + } }} } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt index cc25c42f..9167fb9a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragmentDefault.kt @@ -155,7 +155,7 @@ class AgendaFragmentDefault( app.profileId, date ) - is AgendaEventGroup -> DayDialog(activity, app.profileId, date) + is AgendaEventGroup -> DayDialog(activity, app.profileId, date, eventTypeId = event.typeId) is BaseCalendarEvent -> if (event.isPlaceHolder) DayDialog(activity, app.profileId, date) } @@ -260,6 +260,7 @@ class AgendaFragmentDefault( events.add(0, AgendaEventGroup( profileId = event.profileId, date = event.date, + typeId = event.type, typeName = event.typeName ?: "-", typeColor = event.typeColor ?: event.eventColor, count = list.size, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroup.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroup.kt index e50be2c3..3ef4eb47 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroup.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/event/AgendaEventGroup.kt @@ -10,6 +10,7 @@ import pl.szczodrzynski.edziennik.utils.models.Date class AgendaEventGroup( val profileId: Int, val date: Date, + val typeId: Long, val typeName: String, val typeColor: Int, val count: Int, @@ -20,5 +21,5 @@ class AgendaEventGroup( color = typeColor, showBadge = showBadge ) { - override fun copy() = AgendaEventGroup(profileId, date, typeName, typeColor, count, showBadge) + override fun copy() = AgendaEventGroup(profileId, date, typeId, typeName, typeColor, count, showBadge) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt index 2a904016..5f66cc27 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/lessonchanges/LessonChangesEventRenderer.kt @@ -8,6 +8,7 @@ import android.view.View import androidx.core.view.isVisible import com.github.tibolte.agendacalendarview.render.EventRenderer import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.databinding.AgendaCounterItemBinding import pl.szczodrzynski.edziennik.databinding.AgendaWrappedCounterBinding import pl.szczodrzynski.edziennik.resolveAttr import pl.szczodrzynski.edziennik.setTintColor @@ -33,5 +34,22 @@ class LessonChangesEventRenderer : EventRenderer() { b.badge.isVisible = event.showItemBadge } + fun render(b: AgendaCounterItemBinding, event: LessonChangesEvent) { + val textColor = Colors.legibleTextColor(event.color) + + b.card.foreground.setTintColor(event.color) + b.card.background.setTintColor(event.color) + b.name.setText(R.string.agenda_lesson_changes) + b.name.setTextColor(textColor) + b.count.text = event.count.toString() + b.count.setTextColor(textColor) + + b.badgeBackground.isVisible = event.showItemBadge + b.badgeBackground.background.setTintColor( + android.R.attr.colorBackground.resolveAttr(b.root.context) + ) + b.badge.isVisible = event.showItemBadge + } + override fun getEventLayout(): Int = R.layout.agenda_wrapped_counter } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt index 12dd1947..8d70f941 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/teacherabsence/TeacherAbsenceEventRenderer.kt @@ -8,6 +8,7 @@ import android.view.View import androidx.core.view.isVisible import com.github.tibolte.agendacalendarview.render.EventRenderer import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.databinding.AgendaCounterItemBinding import pl.szczodrzynski.edziennik.databinding.AgendaWrappedCounterBinding import pl.szczodrzynski.edziennik.setTintColor import pl.szczodrzynski.edziennik.utils.Colors @@ -29,5 +30,19 @@ class TeacherAbsenceEventRenderer : EventRenderer() { b.badge.isVisible = false } + fun render(b: AgendaCounterItemBinding, event: TeacherAbsenceEvent) { + val textColor = Colors.legibleTextColor(event.color) + + b.card.foreground.setTintColor(event.color) + b.card.background.setTintColor(event.color) + b.name.setText(R.string.agenda_teacher_absence) + b.name.setTextColor(textColor) + b.count.text = event.count.toString() + b.count.setTextColor(textColor) + + b.badgeBackground.isVisible = false + b.badge.isVisible = false + } + override fun getEventLayout(): Int = R.layout.agenda_wrapped_counter } diff --git a/app/src/main/res/layout/agenda_lesson_changes_item.xml b/app/src/main/res/layout/agenda_lesson_changes_item.xml deleted file mode 100644 index 8700a575..00000000 --- a/app/src/main/res/layout/agenda_lesson_changes_item.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - diff --git a/app/src/main/res/layout/agenda_teacher_absence_item.xml b/app/src/main/res/layout/agenda_teacher_absence_item.xml deleted file mode 100644 index 4b749e8c..00000000 --- a/app/src/main/res/layout/agenda_teacher_absence_item.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - diff --git a/app/src/main/res/layout/dialog_day.xml b/app/src/main/res/layout/dialog_day.xml index f1544f59..8bbc7b64 100644 --- a/app/src/main/res/layout/dialog_day.xml +++ b/app/src/main/res/layout/dialog_day.xml @@ -3,118 +3,108 @@ ~ Copyright (c) Kuba Szczodrzyński 2019-12-16. --> - - + android:layout_width="match_parent" + android:layout_height="match_parent"> - - - + + + + + + + + + + + + + + + + + android:paddingVertical="16dp" + android:visibility="gone" + tools:visibility="visible"> - + android:layout_gravity="center" + android:drawablePadding="16dp" + android:fontFamily="sans-serif-light" + android:gravity="center" + android:text="@string/dialog_day_no_events" + android:textSize="24sp" + app:drawableTopCompat="@drawable/ic_no_events" /> - - - - - - - - - - - - - - - - - - - - - + android:layout_gravity="center" + android:gravity="center" + android:text="@string/dialog_no_events_hint" + android:textStyle="italic" /> - - + + + + From 02eb5b7ee4499916a5eeca1cf7e3409cdc8d673c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Wed, 14 Apr 2021 17:03:44 +0200 Subject: [PATCH 15/15] [UI/Agenda] Disable not available config options. --- app/src/main/res/layout/dialog_config_agenda.xml | 14 +++++++++++--- app/src/main/res/values/strings.xml | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/layout/dialog_config_agenda.xml b/app/src/main/res/layout/dialog_config_agenda.xml index 475c9d84..f17b5989 100644 --- a/app/src/main/res/layout/dialog_config_agenda.xml +++ b/app/src/main/res/layout/dialog_config_agenda.xml @@ -1,5 +1,4 @@ - - @@ -67,7 +66,7 @@ android:layout_marginHorizontal="16dp" android:enabled="@{isAgendaMode}" android:text="@string/agenda_config_compact_mode_hint" - android:textAppearance="@style/NavView.TextView.Small" + android:textAppearance="@style/NavView.TextView.Helper" tools:enabled="false" /> + + @@ -141,6 +148,7 @@ android:layout_height="wrap_content" android:layout_marginTop="8dp" android:checked="@={config.agendaElearningGroup}" + android:enabled="false" android:minHeight="32dp" android:text="@string/agenda_config_elearning_group" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 80e158d8..9196508e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1443,4 +1443,5 @@ Grupuj lekcje on-line na liście {cmd-clipboard-edit-outline} wydarzenie dodane ręcznie {cmd-check} oznaczono jako wykonane + Funkcja jeszcze nie jest dostępna.