diff --git a/app/build.gradle b/app/build.gradle index ce22316a8..c0cc358c5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -63,7 +63,7 @@ android { } dependencies { - implementation 'com.github.SimpleMobileTools:Simple-Commons:1b72d7ccff' + implementation 'com.github.SimpleMobileTools:Simple-Commons:16ae1d2c03' implementation 'joda-time:joda-time:2.10.3' implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/MainActivity.kt index 029897abf..7356f9b25 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/MainActivity.kt @@ -606,13 +606,14 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { val selectionArgs = arrayOf(CommonDataKinds.Event.CONTENT_ITEM_TYPE, type.toString()) val dateFormats = getDateFormats() + val yearDateFormats = getDateFormatsWithYear() val existingEvents = if (birthdays) eventsDB.getBirthdays() else eventsDB.getAnniversaries() val importIDs = HashMap() existingEvents.forEach { importIDs[it.importId] = it.startTS } - val eventTypeId = if (birthdays) getBirthdaysEventTypeId() else getAnniversariesEventTypeId() + val eventTypeId = if (birthdays) eventsHelper.getBirthdaysEventTypeId() else eventsHelper.getAnniversariesEventTypeId() val source = if (birthdays) SOURCE_CONTACT_BIRTHDAY else SOURCE_CONTACT_ANNIVERSARY queryCursor(uri, projection, selection, selectionArgs, showErrors = true) { cursor -> @@ -624,15 +625,17 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { try { val formatter = SimpleDateFormat(format, Locale.getDefault()) val date = formatter.parse(startDate) - if (date.year < 70) { - date.year = 70 + val flags = if (format in yearDateFormats) { + FLAG_ALL_DAY + } else { + FLAG_ALL_DAY or FLAG_MISSING_YEAR } val timestamp = date.time / 1000L val lastUpdated = cursor.getLongValue(CommonDataKinds.Event.CONTACT_LAST_UPDATED_TIMESTAMP) val event = Event( null, timestamp, timestamp, name, reminder1Minutes = reminders[0], reminder2Minutes = reminders[1], - reminder3Minutes = reminders[2], importId = contactId, timeZone = DateTimeZone.getDefault().id, flags = FLAG_ALL_DAY, + reminder3Minutes = reminders[2], importId = contactId, timeZone = DateTimeZone.getDefault().id, flags = flags, repeatInterval = YEAR, repeatRule = REPEAT_SAME_DAY, eventType = eventTypeId, source = source, lastUpdated = lastUpdated ) @@ -681,7 +684,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { } try { - val eventTypeId = if (birthdays) getBirthdaysEventTypeId() else getAnniversariesEventTypeId() + val eventTypeId = if (birthdays) eventsHelper.getBirthdaysEventTypeId() else eventsHelper.getAnniversariesEventTypeId() val source = if (birthdays) SOURCE_CONTACT_BIRTHDAY else SOURCE_CONTACT_ANNIVERSARY val existingEvents = if (birthdays) eventsDB.getBirthdays() else eventsDB.getAnniversaries() @@ -743,26 +746,6 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { callback(eventsFound, eventsAdded) } - private fun getBirthdaysEventTypeId(): Long { - val birthdays = getString(R.string.birthdays) - var eventTypeId = eventsHelper.getEventTypeIdWithTitle(birthdays) - if (eventTypeId == -1L) { - val eventType = EventType(null, birthdays, resources.getColor(R.color.default_birthdays_color)) - eventTypeId = eventsHelper.insertOrUpdateEventTypeSync(eventType) - } - return eventTypeId - } - - private fun getAnniversariesEventTypeId(): Long { - val anniversaries = getString(R.string.anniversaries) - var eventTypeId = eventsHelper.getEventTypeIdWithTitle(anniversaries) - if (eventTypeId == -1L) { - val eventType = EventType(null, anniversaries, resources.getColor(R.color.default_anniversaries_color)) - eventTypeId = eventsHelper.insertOrUpdateEventTypeSync(eventType) - } - return eventTypeId - } - private fun updateView(view: Int) { calendar_fab.beVisibleIf(view != YEARLY_VIEW && view != WEEKLY_VIEW) config.storedView = view diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/Constants.kt index 2a40446d7..0cfcda6ce 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/Constants.kt @@ -93,6 +93,7 @@ const val REPEAT_ORDER_WEEKDAY = 4 // i.e. every 4th sunday // special event flags const val FLAG_ALL_DAY = 1 const val FLAG_IS_PAST_EVENT = 2 +const val FLAG_MISSING_YEAR = 4 // constants related to ICS file exporting / importing const val BEGIN_CALENDAR = "BEGIN:VCALENDAR" @@ -129,6 +130,7 @@ const val SEQUENCE = "SEQUENCE" // this tag isn't a standard ICS tag, but there's no official way of adding a category color in an ics file const val CATEGORY_COLOR = "X-SMT-CATEGORY-COLOR:" const val CATEGORY_COLOR_LEGACY = "CATEGORY_COLOR:" +const val MISSING_YEAR = "X-SMT-MISSING-YEAR:" const val DISPLAY = "DISPLAY" const val EMAIL = "EMAIL" 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 f5445cc1c..3a4224e64 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 @@ -3,6 +3,7 @@ package com.simplemobiletools.calendar.pro.helpers import android.app.Activity import android.content.Context import androidx.collection.LongSparseArray +import com.simplemobiletools.calendar.pro.R import com.simplemobiletools.calendar.pro.extensions.* import com.simplemobiletools.calendar.pro.models.Event import com.simplemobiletools.calendar.pro.models.EventType @@ -259,6 +260,9 @@ class EventsHelper(val context: Context) { } fun getEventsSync(fromTS: Long, toTS: Long, eventId: Long = -1L, applyTypeFilter: Boolean, callback: (events: ArrayList) -> Unit) { + val birthDayEventId = getBirthdaysEventTypeId(createIfNotExists = false) + val anniversaryEventId = getAnniversariesEventTypeId(createIfNotExists = false) + var events = if (applyTypeFilter) { val displayEventTypes = context.config.displayEventTypes if (displayEventTypes.isEmpty()) { @@ -294,12 +298,46 @@ class EventsHelper(val context: Context) { events.forEach { it.updateIsPastEvent() + val originalEvent = eventsDB.getEventWithId(it.id!!) + if (originalEvent != null && + (birthDayEventId != -1L && it.eventType == birthDayEventId) or + (anniversaryEventId != -1L && it.eventType == anniversaryEventId) + ) { + val eventStartDate = Formatter.getDateFromTS(it.startTS) + val originalEventStartDate = Formatter.getDateFromTS(originalEvent.startTS) + if (it.hasMissingYear().not()) { + val years = (eventStartDate.year - originalEventStartDate.year).coerceAtLeast(0) + if (years > 0) { + it.title = "${it.title} ($years)" + } + } + } it.color = eventTypeColors.get(it.eventType) ?: config.primaryColor } callback(events) } + fun getBirthdaysEventTypeId(createIfNotExists: Boolean = true): Long { + val birthdays = context.getString(R.string.birthdays) + var eventTypeId = getEventTypeIdWithTitle(birthdays) + if (eventTypeId == -1L && createIfNotExists) { + val eventType = EventType(null, birthdays, context.resources.getColor(R.color.default_birthdays_color)) + eventTypeId = insertOrUpdateEventTypeSync(eventType) + } + return eventTypeId + } + + fun getAnniversariesEventTypeId(createIfNotExists: Boolean = true): Long { + val anniversaries = context.getString(R.string.anniversaries) + var eventTypeId = getEventTypeIdWithTitle(anniversaries) + if (eventTypeId == -1L && createIfNotExists) { + val eventType = EventType(null, anniversaries, context.resources.getColor(R.color.default_anniversaries_color)) + eventTypeId = insertOrUpdateEventTypeSync(eventType) + } + return eventTypeId + } + fun getRepeatableEventsFor(fromTS: Long, toTS: Long, eventId: Long = -1L, applyTypeFilter: Boolean = false): List { val events = if (applyTypeFilter) { val displayEventTypes = context.config.displayEventTypes diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/IcsExporter.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/IcsExporter.kt index ced32bae0..84b41f7ee 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/IcsExporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/IcsExporter.kt @@ -23,7 +23,13 @@ class IcsExporter { private var eventsFailed = 0 private var calendars = ArrayList() - fun exportEvents(activity: BaseSimpleActivity, outputStream: OutputStream?, events: ArrayList, showExportingToast: Boolean, callback: (result: ExportResult) -> Unit) { + fun exportEvents( + activity: BaseSimpleActivity, + outputStream: OutputStream?, + events: ArrayList, + showExportingToast: Boolean, + callback: (result: ExportResult) -> Unit + ) { if (outputStream == null) { callback(EXPORT_FAIL) return @@ -58,6 +64,7 @@ class IcsExporter { event.startTS.let { out.writeLn("$DTSTART:${Formatter.getExportedTime(it * 1000L)}") } event.endTS.let { out.writeLn("$DTEND:${Formatter.getExportedTime(it * 1000L)}") } } + event.hasMissingYear().let { out.writeLn("$MISSING_YEAR${if (it) 1 else 0}") } out.writeLn("$DTSTAMP$exportTime") out.writeLn("$STATUS$CONFIRMED") @@ -73,11 +80,13 @@ class IcsExporter { out.writeLn(END_CALENDAR) } - callback(when { - eventsExported == 0 -> EXPORT_FAIL - eventsFailed > 0 -> EXPORT_PARTIAL - else -> EXPORT_OK - }) + callback( + when { + eventsExported == 0 -> EXPORT_FAIL + eventsFailed > 0 -> EXPORT_PARTIAL + else -> EXPORT_OK + } + ) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/IcsImporter.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/IcsImporter.kt index b884e1632..1b7b9a75b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/IcsImporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/IcsImporter.kt @@ -128,6 +128,10 @@ class IcsImporter(val activity: SimpleActivity) { if (color.trimStart('-').areDigitsOnly()) { curCategoryColor = Integer.parseInt(color) } + } else if (line.startsWith(MISSING_YEAR)) { + if (line.substring(MISSING_YEAR.length) == "1") { + curFlags = curFlags or FLAG_MISSING_YEAR + } } else if (line.startsWith(CATEGORIES) && !overrideFileEventTypes) { val categories = line.substring(CATEGORIES.length) tryAddCategories(categories) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Event.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Event.kt index 8f08aec5f..d6020ae47 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Event.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Event.kt @@ -138,6 +138,7 @@ data class Event( } fun getIsAllDay() = flags and FLAG_ALL_DAY != 0 + fun hasMissingYear() = flags and FLAG_MISSING_YEAR != 0 fun getReminders() = setOf( Reminder(reminder1Minutes, reminder1Type),