From fe0488044157b10c2368c9b3df60e57714b40b1b Mon Sep 17 00:00:00 2001 From: Marius Wagner Date: Sun, 17 Sep 2023 01:52:17 +0200 Subject: [PATCH] Added extra days to month-view (#1600) * Added extra days to month-view * Undo the formatting changes in CalendarFragment * Resolved the problems * Added method comment to dayToIndex * Update * Added method comment * Fixed formatting issues --------- Co-authored-by: ge78fug Co-authored-by: Frank Elsinga --- .../tumui/calendar/CalendarController.kt | 55 ++++++++++++++++--- .../tumui/calendar/CalendarFragment.kt | 14 +++-- .../tumui/calendar/MonthViewAdapter.kt | 35 ++++++++++-- .../tumui/calendar/MonthViewEventAdapter.kt | 16 +++++- 4 files changed, 102 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/CalendarController.kt b/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/CalendarController.kt index c5ba48e59..5ae3fee72 100644 --- a/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/CalendarController.kt +++ b/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/CalendarController.kt @@ -24,6 +24,7 @@ import de.tum.`in`.tumcampusapp.utils.Utils import de.tum.`in`.tumcampusapp.utils.sync.SyncManager import org.joda.time.DateTime import org.joda.time.LocalDate +import java.time.YearMonth import java.util.* /** @@ -62,22 +63,62 @@ class CalendarController(private val context: Context) : ProvidesCard, ProvidesN fun getFromDbNotCancelledBetweenDates(begin: DateTime, end: DateTime) = applyEventColors(calendarDao.getAllNotCancelledBetweenDates(begin, end)) - fun getEventsForMonth(date: LocalDate): Map> { + /** + * Returns all events for one page in the month-view. + * One page in the month-view contains 42 days. + * + * @param date The selected date + * @return A map with the index/day of the page as key and the list of events for the respective day as value + */ + fun getEventsForMonth(date: LocalDate): Map> { val startOfMonth = date.withDayOfMonth(1) val endOfMonth = date.withDayOfMonth(date.dayOfMonth().maximumValue) - val events = getFromDbBetweenDates(startOfMonth.toDateTimeAtCurrentTime(), endOfMonth.toDateTimeAtCurrentTime()) - val eventMap = mutableMapOf>() + val yearMonth = YearMonth.of(date.year, date.monthOfYear) + + // First day of the page, minus offset to the current month + val start = startOfMonth.minusDays(startOfMonth.dayOfWeek) + + // Last day of the page, days of page - length of the current month - offset to the current month + val end = endOfMonth.plusDays(42 - yearMonth.lengthOfMonth() - startOfMonth.dayOfWeek) + val events = getFromDbBetweenDates(start.toDateTimeAtCurrentTime(), end.toDateTimeAtCurrentTime()) + val eventMap = mutableMapOf>() for (event in events) { - val day = event.dtstart.toLocalDate().dayOfMonth.toString() - if (!eventMap.containsKey(day)) { - eventMap[day] = mutableListOf(event) + val day = event.dtstart.toLocalDate() + val index = dayToIndex(day, date) + if (!eventMap.containsKey(index)) { + eventMap[index] = mutableListOf(event) } else { - eventMap[day]?.add(event) + eventMap[index]?.add(event) } } return eventMap } + /** + * Returns the index on the page of the event`s day. + * Index goes from 0 to 41. + * + * @param eventDate The date of the event + * @param date The selected date + * @return The index of the day where the event is on the page + */ + private fun dayToIndex(eventDate: LocalDate, date: LocalDate): Int { + val yearMonth = YearMonth.of(date.year, date.monthOfYear) + val daysInMonth = yearMonth.lengthOfMonth() + val daysInPreviousMonth = yearMonth.minusMonths(1).lengthOfMonth() + val firstDayOfMonth = date.withDayOfMonth(1) + val lastDayOfMonth = date.withDayOfMonth(date.dayOfMonth().maximumValue) + + if (eventDate < firstDayOfMonth) { + return eventDate.dayOfMonth - 1 - daysInPreviousMonth + firstDayOfMonth.dayOfWeek - 1 + } + if (eventDate > lastDayOfMonth) { + return eventDate.dayOfMonth - 1 + firstDayOfMonth.dayOfWeek - 1 + daysInMonth + } + + return eventDate.dayOfMonth - 1 + firstDayOfMonth.dayOfWeek - 1 + } + private fun applyEventColors(calendarItems: List): List { calendarItems.forEach { it.color = eventColorProvider.getColor(it) diff --git a/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/CalendarFragment.kt b/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/CalendarFragment.kt index 75ae3540f..2c709def1 100644 --- a/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/CalendarFragment.kt +++ b/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/CalendarFragment.kt @@ -45,6 +45,7 @@ import org.joda.time.LocalDate import org.joda.time.format.DateTimeFormat import java.time.YearMonth import java.util.* +import kotlin.math.abs class CalendarFragment : FragmentForAccessingTumOnline( @@ -579,10 +580,10 @@ class CalendarFragment : val eventMap = calendarController.getEventsForMonth(selectedDate) if (!::monthViewAdapter.isInitialized) { - monthViewAdapter = MonthViewAdapter(daysInMonth, eventMap) + monthViewAdapter = MonthViewAdapter(daysInMonth, eventMap, selectedDate) monthRecyclerView.adapter = monthViewAdapter } else { - monthViewAdapter.updateData(daysInMonth, eventMap) + monthViewAdapter.updateData(daysInMonth, eventMap, selectedDate) } val layoutManager: RecyclerView.LayoutManager = GridLayoutManager(requireContext(), 7) @@ -593,11 +594,14 @@ class CalendarFragment : val daysInMonthArray: ArrayList = ArrayList() val yearMonth = YearMonth.of(date.year, date.monthOfYear) val daysInMonth = yearMonth.lengthOfMonth() + val daysInPreviousMonth = yearMonth.minusMonths(1).lengthOfMonth() val firstOfMonth = date.withDayOfMonth(1) - var dayOfWeek = firstOfMonth.dayOfWeek().get() - 1 // Monday is the first day of the week in Europe + var dayOfWeek = firstOfMonth.dayOfWeek - 1 // Monday is the first day of the week in Europe for (i in 1..42) { - if (i <= dayOfWeek || i > daysInMonth + dayOfWeek) { - daysInMonthArray.add("") + if (i <= dayOfWeek) { + daysInMonthArray.add((daysInPreviousMonth - dayOfWeek + i).toString()) + } else if (i > daysInMonth + dayOfWeek) { + daysInMonthArray.add((abs(i - daysInMonth - dayOfWeek)).toString()) } else { daysInMonthArray.add((i - dayOfWeek).toString()) } diff --git a/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/MonthViewAdapter.kt b/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/MonthViewAdapter.kt index 753f80c9e..8cd7bd9d9 100644 --- a/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/MonthViewAdapter.kt +++ b/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/MonthViewAdapter.kt @@ -6,33 +6,58 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import de.tum.`in`.tumcampusapp.R import de.tum.`in`.tumcampusapp.component.tumui.calendar.model.CalendarItem +import org.joda.time.LocalDate +import java.time.YearMonth -class MonthViewAdapter(private var daysOfMonth: ArrayList, private var eventMap: Map>) : +class MonthViewAdapter( + private var daysOfMonth: ArrayList, + private var eventMap: Map>, + private var selectedDate: LocalDate +) : RecyclerView.Adapter() { + private lateinit var monthViewEventAdapter: MonthViewEventAdapter override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MonthViewHolder { val inflater = LayoutInflater.from(parent.context) val view = inflater.inflate(R.layout.calendar_month_view_cell, parent, false) val layoutParams = view.layoutParams layoutParams.height = (parent.height * 1 / 6) + monthViewEventAdapter = MonthViewEventAdapter(emptyList(), selectedDate) return MonthViewHolder(view) } override fun onBindViewHolder(holder: MonthViewHolder, position: Int) { - val events = eventMap[daysOfMonth[position]] + val events = eventMap[position] holder.dayOfMonth.text = daysOfMonth[position] - holder.eventsContainer.adapter = events?.let { MonthViewEventAdapter(it) } - holder.eventsContainer.layoutManager = LinearLayoutManager(holder.itemView.context) + + if (events.isNullOrEmpty()) { + holder.eventsContainer.adapter = null + } else { + holder.eventsContainer.adapter = monthViewEventAdapter + holder.eventsContainer.layoutManager = LinearLayoutManager(holder.itemView.context) + monthViewEventAdapter.updateData(events, selectedDate) + } + + if ( + position < selectedDate.withDayOfMonth(1).dayOfWeek - 1 || + position > selectedDate.withDayOfMonth(1).dayOfWeek - 1 + + YearMonth.of(selectedDate.year, selectedDate.monthOfYear).lengthOfMonth() - 1 + ) { + holder.dayOfMonth.alpha = 0.2F + } else { + holder.dayOfMonth.alpha = 1F + } } override fun getItemCount(): Int { return daysOfMonth.size } - fun updateData(daysOfMonth: ArrayList, eventMap: Map>) { + fun updateData(daysOfMonth: ArrayList, eventMap: Map>, selectedDate: LocalDate) { this.daysOfMonth = daysOfMonth this.eventMap = eventMap + this.selectedDate = selectedDate notifyDataSetChanged() } } diff --git a/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/MonthViewEventAdapter.kt b/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/MonthViewEventAdapter.kt index 638872802..2b41dfefd 100644 --- a/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/MonthViewEventAdapter.kt +++ b/app/src/main/java/de/tum/in/tumcampusapp/component/tumui/calendar/MonthViewEventAdapter.kt @@ -6,8 +6,11 @@ import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import de.tum.`in`.tumcampusapp.R import de.tum.`in`.tumcampusapp.component.tumui.calendar.model.CalendarItem +import org.jetbrains.anko.withAlpha +import org.joda.time.LocalDate -class MonthViewEventAdapter(private val events: List) : RecyclerView.Adapter() { +class MonthViewEventAdapter(private var events: List, private var selectedDate: LocalDate) : + RecyclerView.Adapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MonthViewEventViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.calendar_month_event_view, parent, false) @@ -18,10 +21,21 @@ class MonthViewEventAdapter(private val events: List) : RecyclerVi val event = events[position] holder.title.text = event.title val background = holder.title.background as GradientDrawable + background.setColor(event.color!!) + + if (event.eventStart.monthOfYear != selectedDate.monthOfYear) { + background.setColor(event.color!!.withAlpha(100)) + } } override fun getItemCount(): Int { return events.size } + + fun updateData(events: List, selectedDate: LocalDate) { + this.events = events + this.selectedDate = selectedDate + notifyDataSetChanged() + } }