From df8094c39c67ebd58c0790f6e3751638c482a094 Mon Sep 17 00:00:00 2001 From: Kacper Ziubryniewicz Date: Tue, 11 Feb 2020 16:34:31 +0100 Subject: [PATCH] [Dialog/LessonChanges] Add a new lesson changes dialog. --- .../edziennik/data/db/dao/TimetableDao.kt | 9 +- .../lessonchange/LessonChangeAdapter.kt | 187 ++++++++++++++++++ .../lessonchange/LessonChangeDialog.java | 69 ------- .../lessonchange/LessonChangeDialog.kt | 61 ++++++ .../ui/modules/agenda/AgendaFragment.kt | 3 +- .../res/layout/dialog_lesson_change_list.xml | 4 +- app/src/main/res/layout/timetable_lesson.xml | 2 +- 7 files changed, 261 insertions(+), 74 deletions(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/lessonchange/LessonChangeAdapter.kt delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/lessonchange/LessonChangeDialog.java create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/lessonchange/LessonChangeDialog.kt 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 57133bd0..295739ea 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 @@ -58,7 +58,14 @@ interface TimetableDao { WHERE timetable.profileId = :profileId AND type != -1 AND type != 0 ORDER BY id, type """) - fun getAllChangesNow(profileId: Int): List + fun getAllChangesNow(profileId: Int): List + + @Query(""" + $QUERY + WHERE timetable.profileId = :profileId AND type != -1 AND type != 0 AND ((type != 3 AND date = :date) OR ((type = 3 OR type = 1) AND oldDate = :date)) + ORDER BY id, type + """) + fun getChangesForDateNow(profileId: Int, date: Date): List @Query(""" $QUERY diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/lessonchange/LessonChangeAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/lessonchange/LessonChangeAdapter.kt new file mode 100644 index 00000000..7f95c5b0 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/lessonchange/LessonChangeAdapter.kt @@ -0,0 +1,187 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2019-12-19. + */ + +package pl.szczodrzynski.edziennik.ui.dialogs.lessonchange + +import android.graphics.PorterDuff +import android.graphics.PorterDuffColorFilter +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.updateLayoutParams +import androidx.recyclerview.widget.RecyclerView +import pl.szczodrzynski.edziennik.* +import pl.szczodrzynski.edziennik.data.db.entity.Lesson +import pl.szczodrzynski.edziennik.data.db.full.LessonFull +import pl.szczodrzynski.edziennik.databinding.TimetableLessonBinding +import pl.szczodrzynski.edziennik.ui.dialogs.timetable.LessonDetailsDialog +import pl.szczodrzynski.navlib.getColorFromAttr + +class LessonChangeAdapter(val activity: AppCompatActivity) : RecyclerView.Adapter() { + + var items = listOf() + + private val arrowRight = " → " + private val bullet = " • " + private val colorSecondary = android.R.attr.textColorSecondary.resolveAttr(activity) + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val inflater = LayoutInflater.from(parent.context) + val view = TimetableLessonBinding.inflate(inflater, parent, false) + return ViewHolder(view) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val lesson = items[position] + val b = holder.b + + b.root.setOnClickListener { + LessonDetailsDialog(activity, lesson) + } + + val startTime = lesson.displayStartTime ?: return + val endTime = lesson.displayEndTime ?: return + + val timeRange = "${startTime.stringHM} - ${endTime.stringHM}".asColoredSpannable(colorSecondary) + + b.unread = false + b.root.background = null + + b.root.updateLayoutParams { + topMargin = 16.dp + } + + // teacher + val teacherInfo = if (lesson.teacherId != null && lesson.teacherId == lesson.oldTeacherId) + lesson.teacherName ?: "?" + else + mutableListOf().apply { + lesson.oldTeacherName?.let { add(it.asStrikethroughSpannable()) } + lesson.teacherName?.let { add(it) } + }.concat(arrowRight) + + // team + val teamInfo = if (lesson.teamId != null && lesson.teamId == lesson.oldTeamId) + lesson.teamName ?: "?" + else + mutableListOf().apply { + lesson.oldTeamName?.let { add(it.asStrikethroughSpannable()) } + lesson.teamName?.let { add(it) } + }.concat(arrowRight) + + // classroom + val classroomInfo = if (lesson.classroom != null && lesson.classroom == lesson.oldClassroom) + lesson.classroom ?: "?" + else + mutableListOf().apply { + lesson.oldClassroom?.let { add(it.asStrikethroughSpannable()) } + lesson.classroom?.let { add(it) } + }.concat(arrowRight) + + + b.lessonNumber = lesson.displayLessonNumber + b.subjectName.text = lesson.displaySubjectName?.let { + if (lesson.type == Lesson.TYPE_CANCELLED || lesson.type == Lesson.TYPE_SHIFTED_SOURCE) + it.asStrikethroughSpannable().asColoredSpannable(colorSecondary) + else + it + } + b.detailsFirst.text = listOfNotEmpty(timeRange, classroomInfo).concat(bullet) + b.detailsSecond.text = listOfNotEmpty(teacherInfo, teamInfo).concat(bullet) + + //lb.subjectName.typeface = Typeface.create("sans-serif-light", Typeface.BOLD) + when (lesson.type) { + Lesson.TYPE_NORMAL -> { + b.annotationVisible = false + } + Lesson.TYPE_CANCELLED -> { + b.annotationVisible = true + b.annotation.setText(R.string.timetable_lesson_cancelled) + b.annotation.background.colorFilter = PorterDuffColorFilter( + getColorFromAttr(activity, R.attr.timetable_lesson_cancelled_color), + PorterDuff.Mode.SRC_ATOP + ) + //lb.subjectName.typeface = Typeface.DEFAULT + } + Lesson.TYPE_CHANGE -> { + b.annotationVisible = true + when { + lesson.subjectId != lesson.oldSubjectId && lesson.teacherId != lesson.oldTeacherId + && lesson.oldSubjectName != null && lesson.oldTeacherName != null -> + b.annotation.setText( + R.string.timetable_lesson_change_format, + "${lesson.oldSubjectName ?: "?"}, ${lesson.oldTeacherName ?: "?"}" + ) + + lesson.subjectId != lesson.oldSubjectId && lesson.oldSubjectName != null -> + b.annotation.setText( + R.string.timetable_lesson_change_format, + lesson.oldSubjectName ?: "?" + ) + + lesson.teacherId != lesson.oldTeacherId && lesson.oldTeacherName != null -> + b.annotation.setText( + R.string.timetable_lesson_change_format, + lesson.oldTeacherName ?: "?" + ) + else -> b.annotation.setText(R.string.timetable_lesson_change) + } + + b.annotation.background.colorFilter = PorterDuffColorFilter( + getColorFromAttr(activity, R.attr.timetable_lesson_change_color), + PorterDuff.Mode.SRC_ATOP + ) + } + Lesson.TYPE_SHIFTED_SOURCE -> { + b.annotationVisible = true + when { + lesson.date != lesson.oldDate && lesson.date != null -> + b.annotation.setText( + R.string.timetable_lesson_shifted_other_day, + lesson.date?.stringY_m_d ?: "?", + lesson.startTime?.stringHM ?: "" + ) + + lesson.startTime != lesson.oldStartTime && lesson.startTime != null -> + b.annotation.setText( + R.string.timetable_lesson_shifted_same_day, + lesson.startTime?.stringHM ?: "?" + ) + + else -> b.annotation.setText(R.string.timetable_lesson_shifted) + } + + b.annotation.background.setTintColor(R.attr.timetable_lesson_shifted_source_color.resolveAttr(activity)) + } + Lesson.TYPE_SHIFTED_TARGET -> { + b.annotationVisible = true + when { + lesson.date != lesson.oldDate && lesson.oldDate != null -> + b.annotation.setText( + R.string.timetable_lesson_shifted_from_other_day, + lesson.oldDate?.stringY_m_d ?: "?", + lesson.oldStartTime?.stringHM ?: "" + ) + + lesson.startTime != lesson.oldStartTime && lesson.oldStartTime != null -> + b.annotation.setText( + R.string.timetable_lesson_shifted_from_same_day, + lesson.oldStartTime?.stringHM ?: "?" + ) + + else -> b.annotation.setText(R.string.timetable_lesson_shifted_from) + } + + b.annotation.background.colorFilter = PorterDuffColorFilter( + getColorFromAttr(activity, R.attr.timetable_lesson_shifted_target_color), + PorterDuff.Mode.SRC_ATOP + ) + } + } + } + + override fun getItemCount() = items.size + + class ViewHolder(val b: TimetableLessonBinding) : RecyclerView.ViewHolder(b.root) +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/lessonchange/LessonChangeDialog.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/lessonchange/LessonChangeDialog.java deleted file mode 100644 index e9fe7f21..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/lessonchange/LessonChangeDialog.java +++ /dev/null @@ -1,69 +0,0 @@ -package pl.szczodrzynski.edziennik.ui.dialogs.lessonchange; - -import android.content.Context; - -import androidx.databinding.DataBindingUtil; -import androidx.recyclerview.widget.LinearLayoutManager; - -import com.afollestad.materialdialogs.MaterialDialog; - -import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.R; -import pl.szczodrzynski.edziennik.databinding.DialogLessonChangeListBinding; -import pl.szczodrzynski.edziennik.utils.models.Date; - -public class LessonChangeDialog { - private App app; - private Context context; - private int profileId; - - public LessonChangeDialog(Context context) { - this.context = context; - this.profileId = App.Companion.getProfileId(); - } - public LessonChangeDialog(Context context, int profileId) { - this.context = context; - this.profileId = profileId; - } - - private MaterialDialog dialog; - private DialogLessonChangeListBinding b; - - public void show(App _app, Date date) - { - this.app = _app; - dialog = new MaterialDialog.Builder(context) - .title(date.getFormattedString()) - .customView(R.layout.dialog_lesson_change_list, false) - .positiveText(R.string.close) - .autoDismiss(false) - .onPositive((dialog, which) -> dialog.dismiss()) - .show(); - if (dialog.getCustomView() == null) - return; - b = DataBindingUtil.bind(dialog.getCustomView()); - if (b == null) - return; - - b.lessonChangeView.setHasFixedSize(true); - b.lessonChangeView.setLayoutManager(new LinearLayoutManager(context)); - - /*app.db.lessonDao().getAllByDate(profileId, date, Time.getNow()).observe((LifecycleOwner) context, lessons -> { - if (app == null || app.profile == null || b == null) - return; - - List changedLessons = new ArrayList<>(); - for (LessonFull lesson: lessons) { - if (lesson.changeId != 0) { - changedLessons.add(lesson); - } - } - - app.db.eventDao().getAllByDate(profileId, date).observe((LifecycleOwner) context, events -> { - TimetableAdapter adapter = new TimetableAdapter(context, date, changedLessons, events == null ? new ArrayList<>() : events); - b.lessonChangeView.setAdapter(adapter); - b.lessonChangeView.setVisibility(View.VISIBLE); - }); - });*/ - } -} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/lessonchange/LessonChangeDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/lessonchange/LessonChangeDialog.kt new file mode 100644 index 00000000..435d89c3 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/lessonchange/LessonChangeDialog.kt @@ -0,0 +1,61 @@ +package pl.szczodrzynski.edziennik.ui.dialogs.lessonchange + +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import androidx.recyclerview.widget.LinearLayoutManager +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import kotlinx.coroutines.* +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.databinding.DialogLessonChangeListBinding +import pl.szczodrzynski.edziennik.utils.models.Date +import kotlin.coroutines.CoroutineContext + +class LessonChangeDialog( + val activity: AppCompatActivity, + val profileId: Int, + private val defaultDate: Date, + val onShowListener: ((tag: String) -> Unit)? = null, + val onDismissListener: ((tag: String) -> Unit)? = null +) : CoroutineScope { + companion object { + const val TAG = "LessonChangeDialog" + } + + private val app by lazy { activity.application as App } + + private lateinit var job: Job + override val coroutineContext: CoroutineContext + get() = job + Dispatchers.Main + + private lateinit var b: DialogLessonChangeListBinding + private lateinit var dialog: AlertDialog + + init { run { + if (activity.isFinishing) + return@run + job = Job() + onShowListener?.invoke(TAG) + b = DialogLessonChangeListBinding.inflate(activity.layoutInflater) + dialog = MaterialAlertDialogBuilder(activity) + .setTitle(defaultDate.formattedString) + .setView(b.root) + .setPositiveButton(R.string.close) { dialog, _ -> dialog.dismiss() } + .setOnDismissListener { + onDismissListener?.invoke(TAG) + } + .create() + loadLessonChanges() + }} + + private fun loadLessonChanges() { launch { + val lessonChanges = withContext(Dispatchers.Default) { + app.db.timetableDao().getChangesForDateNow(profileId, defaultDate) + } + + b.lessonChangeView.adapter = LessonChangeAdapter(activity).apply { items = lessonChanges } + b.lessonChangeView.layoutManager = LinearLayoutManager(activity) + + dialog.show() + }} +} 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 ae4c1805..9804890c 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 @@ -32,6 +32,7 @@ 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 @@ -250,7 +251,7 @@ class AgendaFragment : Fragment(), CoroutineScope { when (event) { is BaseCalendarEvent -> DayDialog(activity, app.profileId, date) - // is LessonChangeEvent -> todo + is LessonChangeEvent -> LessonChangeDialog(activity, app.profileId, date) is TeacherAbsenceEvent -> TeacherAbsenceDialog(activity, app.profileId, date) } } diff --git a/app/src/main/res/layout/dialog_lesson_change_list.xml b/app/src/main/res/layout/dialog_lesson_change_list.xml index bc99ba3a..180eadb4 100644 --- a/app/src/main/res/layout/dialog_lesson_change_list.xml +++ b/app/src/main/res/layout/dialog_lesson_change_list.xml @@ -11,5 +11,5 @@ android:paddingLeft="24dp" android:paddingRight="24dp" android:clipToPadding="false" - tools:listitem="@layout/row_timetable_item" /> - \ No newline at end of file + tools:listitem="@layout/timetable_lesson" /> + diff --git a/app/src/main/res/layout/timetable_lesson.xml b/app/src/main/res/layout/timetable_lesson.xml index ad912e8e..5ca2f56c 100644 --- a/app/src/main/res/layout/timetable_lesson.xml +++ b/app/src/main/res/layout/timetable_lesson.xml @@ -17,7 +17,7 @@