From 50c6826ec068598555876d11b18ac88429499204 Mon Sep 17 00:00:00 2001 From: tibbi Date: Fri, 16 Nov 2018 15:15:07 +0100 Subject: [PATCH] handle repeatable event fetching in Room --- .../calendar/pro/extensions/Context.kt | 2 +- .../calendar/pro/helpers/DBHelper.kt | 147 +----------------- .../calendar/pro/helpers/EventsHelper.kt | 132 +++++++++++++++- .../calendar/pro/interfaces/EventsDao.kt | 9 ++ 4 files changed, 137 insertions(+), 153 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/Context.kt index d49f672dc..fa06f454c 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/Context.kt @@ -166,7 +166,7 @@ fun Context.notifyEvent(originalEvent: Event) { var eventStartTS = if (event.getIsAllDay()) Formatter.getDayStartTS(Formatter.getDayCodeFromTS(event.startTS)) else event.startTS // make sure refer to the proper repeatable event instance with "Tomorrow", or the specific date if (event.repeatInterval != 0 && eventStartTS - event.reminder1Minutes * 60 < currentSeconds) { - val events = dbHelper.getRepeatableEventsFor(currentSeconds - WEEK_SECONDS, currentSeconds + YEAR_SECONDS, event.id!!) + val events = eventsHelper.getRepeatableEventsFor(currentSeconds - WEEK_SECONDS, currentSeconds + YEAR_SECONDS, event.id!!) for (currEvent in events) { eventStartTS = if (currEvent.getIsAllDay()) Formatter.getDayStartTS(Formatter.getDayCodeFromTS(currEvent.startTS)) else currEvent.startTS if (eventStartTS - currEvent.reminder1Minutes * 60 > currentSeconds) { diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/DBHelper.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/DBHelper.kt index c05f38597..4e624bc38 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/DBHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/DBHelper.kt @@ -4,12 +4,8 @@ import android.content.Context import android.database.Cursor import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper -import android.text.TextUtils import androidx.collection.LongSparseArray -import com.simplemobiletools.calendar.pro.extensions.config import com.simplemobiletools.calendar.pro.extensions.eventTypesDB -import com.simplemobiletools.calendar.pro.extensions.isTsOnProperDay -import com.simplemobiletools.calendar.pro.extensions.isXWeeklyRepetition import com.simplemobiletools.calendar.pro.models.Event import com.simplemobiletools.commons.extensions.getIntValue import com.simplemobiletools.commons.extensions.getLongValue @@ -57,131 +53,6 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {} - fun getRepeatableEventsFor(fromTS: Long, toTS: Long, eventId: Long = -1L, applyTypeFilter: Boolean = false): List { - val newEvents = ArrayList() - //var selection = "$COL_REPEAT_INTERVAL != 0 AND $COL_START_TS <= $toTS AND $COL_START_TS != 0" - var selection = "$COL_START_TS <= $toTS AND $COL_START_TS != 0" - if (eventId != -1L) - selection += " AND $MAIN_TABLE_NAME.$COL_ID = $eventId" - - if (applyTypeFilter) { - val displayEventTypes = context.config.displayEventTypes - if (displayEventTypes.isEmpty()) { - return ArrayList() - } else { - val types = TextUtils.join(",", displayEventTypes) - selection += " AND $COL_EVENT_TYPE IN ($types)" - } - } - - val events = getEvents(selection) - val startTimes = LongSparseArray() - events.forEach { - startTimes.put(it.id!!, it.startTS) - if (it.repeatLimit >= 0) { - newEvents.addAll(getEventsRepeatingTillDateOrForever(fromTS, toTS, startTimes, it)) - } else { - newEvents.addAll(getEventsRepeatingXTimes(fromTS, toTS, startTimes, it)) - } - } - - return newEvents - } - - private fun getEventsRepeatingTillDateOrForever(fromTS: Long, toTS: Long, startTimes: LongSparseArray, event: Event): ArrayList { - val original = event.copy() - val events = ArrayList() - while (event.startTS <= toTS && (event.repeatLimit == 0L || event.repeatLimit >= event.startTS)) { - if (event.endTS >= fromTS) { - if (event.repeatInterval.isXWeeklyRepetition()) { - if (event.startTS.isTsOnProperDay(event)) { - if (event.isOnProperWeek(startTimes)) { - event.copy().apply { - updateIsPastEvent() - color = event.color - events.add(this) - } - } - } - } else { - event.copy().apply { - updateIsPastEvent() - color = event.color - events.add(this) - } - } - } - - if (event.getIsAllDay()) { - if (event.repeatInterval.isXWeeklyRepetition()) { - if (event.endTS >= toTS && event.startTS.isTsOnProperDay(event)) { - if (event.isOnProperWeek(startTimes)) { - event.copy().apply { - updateIsPastEvent() - color = event.color - events.add(this) - } - } - } - } else { - val dayCode = Formatter.getDayCodeFromTS(fromTS) - val endDayCode = Formatter.getDayCodeFromTS(event.endTS) - if (dayCode == endDayCode) { - event.copy().apply { - updateIsPastEvent() - color = event.color - events.add(this) - } - } - } - } - event.addIntervalTime(original) - } - return events - } - - private fun getEventsRepeatingXTimes(fromTS: Long, toTS: Long, startTimes: LongSparseArray, event: Event): ArrayList { - val original = event.copy() - val events = ArrayList() - while (event.repeatLimit < 0 && event.startTS <= toTS) { - if (event.repeatInterval.isXWeeklyRepetition()) { - if (event.startTS.isTsOnProperDay(event)) { - if (event.isOnProperWeek(startTimes)) { - if (event.endTS >= fromTS) { - event.copy().apply { - updateIsPastEvent() - color = event.color - events.add(this) - } - } - event.repeatLimit++ - } - } - } else { - if (event.endTS >= fromTS) { - event.copy().apply { - updateIsPastEvent() - color = event.color - events.add(this) - } - } else if (event.getIsAllDay()) { - val dayCode = Formatter.getDayCodeFromTS(fromTS) - val endDayCode = Formatter.getDayCodeFromTS(event.endTS) - if (dayCode == endDayCode) { - event.copy().apply { - updateIsPastEvent() - color = event.color - events.add(this) - } - } - } - event.repeatLimit++ - } - event.addIntervalTime(original) - } - return events - } - fun getRunningEvents(): List { val events = ArrayList() val ts = getNowSeconds() @@ -191,23 +62,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont val cursor = getEventsCursor(selection, selectionArgs) events.addAll(fillEvents(cursor)) - events.addAll(getRepeatableEventsFor(ts, ts)) - return events - } - - private fun getEvents(selection: String): List { - val events = ArrayList() - var cursor: Cursor? = null - try { - cursor = getEventsCursor(selection) - if (cursor != null) { - val currEvents = fillEvents(cursor) - events.addAll(currEvents) - } - } finally { - cursor?.close() - } - + //events.addAll(getRepeatableEventsFor(ts, ts)) return events } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/EventsHelper.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/EventsHelper.kt index d868124eb..65ff2e186 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/EventsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/EventsHelper.kt @@ -245,11 +245,7 @@ class EventsHelper(val context: Context) { } fun getEventsSync(fromTS: Long, toTS: Long, eventId: Long = -1L, applyTypeFilter: Boolean, callback: (events: ArrayList) -> Unit) { - var events: ArrayList - - //var selection = "$COL_START_TS <= ? AND $COL_END_TS >= ? AND $COL_REPEAT_INTERVAL IS NULL AND $COL_START_TS != 0" - - events = if (applyTypeFilter) { + var events = if (applyTypeFilter) { val displayEventTypes = context.config.displayEventTypes if (displayEventTypes.isEmpty()) { callback(ArrayList()) @@ -265,7 +261,7 @@ class EventsHelper(val context: Context) { } } - // events.addAll(getRepeatableEventsFor(fromTS, toTS, eventId, applyTypeFilter)) + events.addAll(getRepeatableEventsFor(fromTS, toTS, eventId, applyTypeFilter)) events = events .asSequence() @@ -285,4 +281,128 @@ class EventsHelper(val context: Context) { callback(events) } + + fun getRepeatableEventsFor(fromTS: Long, toTS: Long, eventId: Long = -1L, applyTypeFilter: Boolean = false): List { + val events = if (applyTypeFilter) { + val displayEventTypes = context.config.displayEventTypes + if (displayEventTypes.isEmpty()) { + return ArrayList() + } else { + eventsDB.getRepeatableEventsFromToWithTypes(toTS, context.config.getDisplayEventTypessAsList()).toMutableList() as ArrayList + } + } else { + if (eventId == -1L) { + eventsDB.getRepeatableEventsFromTo(toTS).toMutableList() as ArrayList + } else { + eventsDB.getRepeatableEventFromToWithId(eventId, toTS).toMutableList() as ArrayList + } + } + + val startTimes = LongSparseArray() + val newEvents = ArrayList() + events.forEach { + startTimes.put(it.id!!, it.startTS) + if (it.repeatLimit >= 0) { + newEvents.addAll(getEventsRepeatingTillDateOrForever(fromTS, toTS, startTimes, it)) + } else { + newEvents.addAll(getEventsRepeatingXTimes(fromTS, toTS, startTimes, it)) + } + } + + return newEvents + } + + private fun getEventsRepeatingXTimes(fromTS: Long, toTS: Long, startTimes: LongSparseArray, event: Event): ArrayList { + val original = event.copy() + val events = ArrayList() + while (event.repeatLimit < 0 && event.startTS <= toTS) { + if (event.repeatInterval.isXWeeklyRepetition()) { + if (event.startTS.isTsOnProperDay(event)) { + if (event.isOnProperWeek(startTimes)) { + if (event.endTS >= fromTS) { + event.copy().apply { + updateIsPastEvent() + color = event.color + events.add(this) + } + } + event.repeatLimit++ + } + } + } else { + if (event.endTS >= fromTS) { + event.copy().apply { + updateIsPastEvent() + color = event.color + events.add(this) + } + } else if (event.getIsAllDay()) { + val dayCode = Formatter.getDayCodeFromTS(fromTS) + val endDayCode = Formatter.getDayCodeFromTS(event.endTS) + if (dayCode == endDayCode) { + event.copy().apply { + updateIsPastEvent() + color = event.color + events.add(this) + } + } + } + event.repeatLimit++ + } + event.addIntervalTime(original) + } + return events + } + + private fun getEventsRepeatingTillDateOrForever(fromTS: Long, toTS: Long, startTimes: LongSparseArray, event: Event): ArrayList { + val original = event.copy() + val events = ArrayList() + while (event.startTS <= toTS && (event.repeatLimit == 0L || event.repeatLimit >= event.startTS)) { + if (event.endTS >= fromTS) { + if (event.repeatInterval.isXWeeklyRepetition()) { + if (event.startTS.isTsOnProperDay(event)) { + if (event.isOnProperWeek(startTimes)) { + event.copy().apply { + updateIsPastEvent() + color = event.color + events.add(this) + } + } + } + } else { + event.copy().apply { + updateIsPastEvent() + color = event.color + events.add(this) + } + } + } + + if (event.getIsAllDay()) { + if (event.repeatInterval.isXWeeklyRepetition()) { + if (event.endTS >= toTS && event.startTS.isTsOnProperDay(event)) { + if (event.isOnProperWeek(startTimes)) { + event.copy().apply { + updateIsPastEvent() + color = event.color + events.add(this) + } + } + } + } else { + val dayCode = Formatter.getDayCodeFromTS(fromTS) + val endDayCode = Formatter.getDayCodeFromTS(event.endTS) + if (dayCode == endDayCode) { + event.copy().apply { + updateIsPastEvent() + color = event.color + events.add(this) + } + } + } + } + event.addIntervalTime(original) + } + return events + } } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/interfaces/EventsDao.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/interfaces/EventsDao.kt index a078fcf1f..db9418753 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/interfaces/EventsDao.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/interfaces/EventsDao.kt @@ -26,6 +26,15 @@ interface EventsDao { @Query("SELECT * FROM events WHERE start_ts <= :toTS AND end_ts >= :fromTS AND start_ts != 0 AND repeat_interval = 0 AND event_type IN (:eventTypeIds)") fun getOneTimeEventsFromToWithTypes(toTS: Long, fromTS: Long, eventTypeIds: List): List + @Query("SELECT * FROM events WHERE start_ts <= :toTS AND repeat_interval != 0") + fun getRepeatableEventsFromTo(toTS: Long): List + + @Query("SELECT * FROM events WHERE id = :id AND start_ts <= :toTS AND repeat_interval != 0") + fun getRepeatableEventFromToWithId(id: Long, toTS: Long): List + + @Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts != 0 AND repeat_interval != 0 AND event_type IN (:eventTypeIds)") + fun getRepeatableEventsFromToWithTypes(toTS: Long, eventTypeIds: List): List + @Query("SELECT * FROM events WHERE id IN (:ids) AND import_id != \"\"") fun getEventsByIdsWithImportIds(ids: List): List