Merge pull request #1442 from KryptKode/feature/show_age_years

Append age/years for birthdays/anniversaries to event title
This commit is contained in:
Tibor Kaputa 2021-08-12 22:03:14 +02:00 committed by GitHub
commit 69a5914ab2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 69 additions and 32 deletions

View File

@ -63,7 +63,7 @@ android {
} }
dependencies { dependencies {
implementation 'com.github.SimpleMobileTools:Simple-Commons:1b72d7ccff' implementation 'com.github.SimpleMobileTools:Simple-Commons:16ae1d2c03'
implementation 'joda-time:joda-time:2.10.3' implementation 'joda-time:joda-time:2.10.3'
implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.multidex:multidex:2.0.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.constraintlayout:constraintlayout:2.0.4'

View File

@ -606,13 +606,14 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
val selectionArgs = arrayOf(CommonDataKinds.Event.CONTENT_ITEM_TYPE, type.toString()) val selectionArgs = arrayOf(CommonDataKinds.Event.CONTENT_ITEM_TYPE, type.toString())
val dateFormats = getDateFormats() val dateFormats = getDateFormats()
val yearDateFormats = getDateFormatsWithYear()
val existingEvents = if (birthdays) eventsDB.getBirthdays() else eventsDB.getAnniversaries() val existingEvents = if (birthdays) eventsDB.getBirthdays() else eventsDB.getAnniversaries()
val importIDs = HashMap<String, Long>() val importIDs = HashMap<String, Long>()
existingEvents.forEach { existingEvents.forEach {
importIDs[it.importId] = it.startTS 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 val source = if (birthdays) SOURCE_CONTACT_BIRTHDAY else SOURCE_CONTACT_ANNIVERSARY
queryCursor(uri, projection, selection, selectionArgs, showErrors = true) { cursor -> queryCursor(uri, projection, selection, selectionArgs, showErrors = true) { cursor ->
@ -624,15 +625,17 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
try { try {
val formatter = SimpleDateFormat(format, Locale.getDefault()) val formatter = SimpleDateFormat(format, Locale.getDefault())
val date = formatter.parse(startDate) val date = formatter.parse(startDate)
if (date.year < 70) { val flags = if (format in yearDateFormats) {
date.year = 70 FLAG_ALL_DAY
} else {
FLAG_ALL_DAY or FLAG_MISSING_YEAR
} }
val timestamp = date.time / 1000L val timestamp = date.time / 1000L
val lastUpdated = cursor.getLongValue(CommonDataKinds.Event.CONTACT_LAST_UPDATED_TIMESTAMP) val lastUpdated = cursor.getLongValue(CommonDataKinds.Event.CONTACT_LAST_UPDATED_TIMESTAMP)
val event = Event( val event = Event(
null, timestamp, timestamp, name, reminder1Minutes = reminders[0], reminder2Minutes = reminders[1], 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 repeatInterval = YEAR, repeatRule = REPEAT_SAME_DAY, eventType = eventTypeId, source = source, lastUpdated = lastUpdated
) )
@ -681,7 +684,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
} }
try { 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 source = if (birthdays) SOURCE_CONTACT_BIRTHDAY else SOURCE_CONTACT_ANNIVERSARY
val existingEvents = if (birthdays) eventsDB.getBirthdays() else eventsDB.getAnniversaries() val existingEvents = if (birthdays) eventsDB.getBirthdays() else eventsDB.getAnniversaries()
@ -743,26 +746,6 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
callback(eventsFound, eventsAdded) 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) { private fun updateView(view: Int) {
calendar_fab.beVisibleIf(view != YEARLY_VIEW && view != WEEKLY_VIEW) calendar_fab.beVisibleIf(view != YEARLY_VIEW && view != WEEKLY_VIEW)
config.storedView = view config.storedView = view

View File

@ -93,6 +93,7 @@ const val REPEAT_ORDER_WEEKDAY = 4 // i.e. every 4th sunday
// special event flags // special event flags
const val FLAG_ALL_DAY = 1 const val FLAG_ALL_DAY = 1
const val FLAG_IS_PAST_EVENT = 2 const val FLAG_IS_PAST_EVENT = 2
const val FLAG_MISSING_YEAR = 4
// constants related to ICS file exporting / importing // constants related to ICS file exporting / importing
const val BEGIN_CALENDAR = "BEGIN:VCALENDAR" 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 // 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 = "X-SMT-CATEGORY-COLOR:"
const val CATEGORY_COLOR_LEGACY = "CATEGORY_COLOR:" const val CATEGORY_COLOR_LEGACY = "CATEGORY_COLOR:"
const val MISSING_YEAR = "X-SMT-MISSING-YEAR:"
const val DISPLAY = "DISPLAY" const val DISPLAY = "DISPLAY"
const val EMAIL = "EMAIL" const val EMAIL = "EMAIL"

View File

@ -3,6 +3,7 @@ package com.simplemobiletools.calendar.pro.helpers
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import androidx.collection.LongSparseArray import androidx.collection.LongSparseArray
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.extensions.* import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.models.Event import com.simplemobiletools.calendar.pro.models.Event
import com.simplemobiletools.calendar.pro.models.EventType 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<Event>) -> Unit) { fun getEventsSync(fromTS: Long, toTS: Long, eventId: Long = -1L, applyTypeFilter: Boolean, callback: (events: ArrayList<Event>) -> Unit) {
val birthDayEventId = getBirthdaysEventTypeId(createIfNotExists = false)
val anniversaryEventId = getAnniversariesEventTypeId(createIfNotExists = false)
var events = if (applyTypeFilter) { var events = if (applyTypeFilter) {
val displayEventTypes = context.config.displayEventTypes val displayEventTypes = context.config.displayEventTypes
if (displayEventTypes.isEmpty()) { if (displayEventTypes.isEmpty()) {
@ -294,12 +298,46 @@ class EventsHelper(val context: Context) {
events.forEach { events.forEach {
it.updateIsPastEvent() 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 it.color = eventTypeColors.get(it.eventType) ?: config.primaryColor
} }
callback(events) 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<Event> { fun getRepeatableEventsFor(fromTS: Long, toTS: Long, eventId: Long = -1L, applyTypeFilter: Boolean = false): List<Event> {
val events = if (applyTypeFilter) { val events = if (applyTypeFilter) {
val displayEventTypes = context.config.displayEventTypes val displayEventTypes = context.config.displayEventTypes

View File

@ -23,7 +23,13 @@ class IcsExporter {
private var eventsFailed = 0 private var eventsFailed = 0
private var calendars = ArrayList<CalDAVCalendar>() private var calendars = ArrayList<CalDAVCalendar>()
fun exportEvents(activity: BaseSimpleActivity, outputStream: OutputStream?, events: ArrayList<Event>, showExportingToast: Boolean, callback: (result: ExportResult) -> Unit) { fun exportEvents(
activity: BaseSimpleActivity,
outputStream: OutputStream?,
events: ArrayList<Event>,
showExportingToast: Boolean,
callback: (result: ExportResult) -> Unit
) {
if (outputStream == null) { if (outputStream == null) {
callback(EXPORT_FAIL) callback(EXPORT_FAIL)
return return
@ -58,6 +64,7 @@ class IcsExporter {
event.startTS.let { out.writeLn("$DTSTART:${Formatter.getExportedTime(it * 1000L)}") } event.startTS.let { out.writeLn("$DTSTART:${Formatter.getExportedTime(it * 1000L)}") }
event.endTS.let { out.writeLn("$DTEND:${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("$DTSTAMP$exportTime")
out.writeLn("$STATUS$CONFIRMED") out.writeLn("$STATUS$CONFIRMED")
@ -73,11 +80,13 @@ class IcsExporter {
out.writeLn(END_CALENDAR) out.writeLn(END_CALENDAR)
} }
callback(when { callback(
eventsExported == 0 -> EXPORT_FAIL when {
eventsFailed > 0 -> EXPORT_PARTIAL eventsExported == 0 -> EXPORT_FAIL
else -> EXPORT_OK eventsFailed > 0 -> EXPORT_PARTIAL
}) else -> EXPORT_OK
}
)
} }
} }

View File

@ -128,6 +128,10 @@ class IcsImporter(val activity: SimpleActivity) {
if (color.trimStart('-').areDigitsOnly()) { if (color.trimStart('-').areDigitsOnly()) {
curCategoryColor = Integer.parseInt(color) 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) { } else if (line.startsWith(CATEGORIES) && !overrideFileEventTypes) {
val categories = line.substring(CATEGORIES.length) val categories = line.substring(CATEGORIES.length)
tryAddCategories(categories) tryAddCategories(categories)

View File

@ -138,6 +138,7 @@ data class Event(
} }
fun getIsAllDay() = flags and FLAG_ALL_DAY != 0 fun getIsAllDay() = flags and FLAG_ALL_DAY != 0
fun hasMissingYear() = flags and FLAG_MISSING_YEAR != 0
fun getReminders() = setOf( fun getReminders() = setOf(
Reminder(reminder1Minutes, reminder1Type), Reminder(reminder1Minutes, reminder1Type),