@@ -9,18 +9,18 @@ import biweekly.ICalendar
99import com.itsmatok.matcal.data.calendar.events.CalendarEvent
1010import com.itsmatok.matcal.data.calendar.events.CalendarEventDatabase
1111import com.itsmatok.matcal.data.calendar.events.EventMapper
12- import com.itsmatok.matcal.data.calendar.events.RecurrenceType
12+ import com.itsmatok.matcal.data.calendar.events.RecurrenceUtil
1313import com.itsmatok.matcal.data.calendar.subscriptions.CalendarSubscription
1414import kotlinx.coroutines.Dispatchers
1515import kotlinx.coroutines.flow.Flow
1616import kotlinx.coroutines.flow.MutableStateFlow
1717import kotlinx.coroutines.flow.asStateFlow
18+ import kotlinx.coroutines.flow.flowOn
1819import kotlinx.coroutines.flow.map
1920import kotlinx.coroutines.launch
2021import kotlinx.coroutines.withContext
2122import java.net.URL
2223import java.time.LocalDate
23- import java.time.temporal.ChronoUnit
2424
2525class CalendarViewModel (application : Application ) : AndroidViewModel(application) {
2626 private val db = CalendarEventDatabase .getDatabase(application)
@@ -30,27 +30,13 @@ class CalendarViewModel(application: Application) : AndroidViewModel(application
3030 private val _selectedDate = MutableStateFlow (LocalDate .now())
3131 val selectedDate = _selectedDate .asStateFlow()
3232
33+ val subscriptions: Flow <List <CalendarSubscription >> = subDao.getAllSubscriptionsFlow()
34+
3335 val events: Flow <Map <LocalDate , List <CalendarEvent >>> =
34- eventDao.getAllEvents().map { allEvents ->
35- val resultMap = mutableMapOf<LocalDate , MutableList <CalendarEvent >>()
36-
37- val currentYear = LocalDate .now().year
38- val startYear = currentYear - 10
39- val endYear = currentYear + 10
40-
41- allEvents.forEach { event ->
42- if (event.recurrenceType == RecurrenceType .NONE ) {
43- resultMap.getOrPut(event.date) { mutableListOf () }.add(event)
44- } else {
45- generateOccurrences(event, startYear, endYear).forEach { entry ->
46- resultMap.getOrPut(entry.key) { mutableListOf () }.add(entry.value)
47- }
48- }
49- }
50- resultMap
51- }
36+ eventDao.getAllEvents()
37+ .map { list -> RecurrenceUtil .expandEvents(list) }
38+ .flowOn(Dispatchers .Default )
5239
53- val subscriptions: Flow <List <CalendarSubscription >> = subDao.getAllSubscriptionsFlow()
5440
5541 fun onDateSelected (date : LocalDate ) {
5642 _selectedDate .value = date
@@ -146,103 +132,13 @@ class CalendarViewModel(application: Application) : AndroidViewModel(application
146132 }
147133 }
148134
149-
150- private fun generateOccurrences (
151- originalEvent : CalendarEvent ,
152- startYear : Int ,
153- endYear : Int
154- ): Map <LocalDate , CalendarEvent > {
155- val occurrences = mutableMapOf<LocalDate , CalendarEvent >()
156-
157- val rangeStartDate = LocalDate .of(startYear, 1 , 1 )
158- val rangeEndDate = LocalDate .of(endYear, 12 , 31 )
159-
160- if (originalEvent.date.isAfter(rangeEndDate)) {
161- return occurrences
162- }
163-
164- var currentDate = originalEvent.date
165-
166- when (originalEvent.recurrenceType) {
167- RecurrenceType .DAILY -> {
168- if (currentDate.isBefore(rangeStartDate)) {
169- currentDate = rangeStartDate
170- }
171-
172- while (! currentDate.isAfter(rangeEndDate)) {
173- occurrences[currentDate] = originalEvent.copy(date = currentDate)
174- currentDate = currentDate.plusDays(1 )
175- }
176- }
177-
178- RecurrenceType .WEEKLY -> {
179- if (currentDate.isBefore(rangeStartDate)) {
180- val weeksToSkip = ChronoUnit .WEEKS .between(currentDate, rangeStartDate)
181- currentDate = currentDate.plusWeeks(weeksToSkip)
182-
183- if (currentDate.isBefore(rangeStartDate)) {
184- currentDate = currentDate.plusWeeks(1 )
185- }
186- }
187-
188- while (! currentDate.isAfter(rangeEndDate)) {
189- occurrences[currentDate] = originalEvent.copy(date = currentDate)
190- currentDate = currentDate.plusWeeks(1 )
191- }
192- }
193-
194- RecurrenceType .MONTHLY -> {
195- if (currentDate.year < startYear) {
196- currentDate = currentDate.withYear(startYear - 1 )
197- }
198-
199- while (! currentDate.isAfter(rangeEndDate)) {
200- if (! currentDate.isBefore(rangeStartDate)) {
201- occurrences[currentDate] = originalEvent.copy(date = currentDate)
202- }
203- currentDate = currentDate.plusMonths(1 )
204- }
205- }
206-
207- RecurrenceType .YEARLY -> {
208- var yearIter = if (currentDate.year < startYear) startYear else currentDate.year
209-
210- while (yearIter <= endYear) {
211- // leap year
212- val newDate = try {
213- currentDate.withYear(yearIter)
214- } catch (_: Exception ) {
215- // if no feb 29, use feb 28
216- currentDate.withYear(yearIter - 1 ).plusYears(1 )
217- }
218-
219- if (! newDate.isBefore(originalEvent.date)) {
220- occurrences[newDate] = originalEvent.copy(date = newDate)
221- }
222- yearIter++
223- }
224- }
225-
226- RecurrenceType .NONE -> {
227- if (! currentDate.isBefore(rangeStartDate) && ! currentDate.isAfter(rangeEndDate)) {
228- occurrences[currentDate] = originalEvent
229- }
230- }
231-
232- null -> {}
233- }
234-
235- return occurrences
236- }
237-
238135 private suspend fun processAndSaveEvents (url : String , iCal : ICalendar , sourceName : String ) {
239136 val eventsToSync = iCal.events.mapNotNull { vEvent ->
240137 EventMapper .mapVEventToCalendarEvent(vEvent, url, sourceName)
241138 }
242139 eventDao.syncEvents(url, eventsToSync)
243140 }
244141
245-
246142 private suspend fun showToast (message : String ) {
247143 withContext(Dispatchers .Main ) {
248144 Toast .makeText(getApplication(), message, Toast .LENGTH_SHORT ).show()
0 commit comments