properly handle multiple days lasting all-day events at caldav
This commit is contained in:
parent
8f0c8f6018
commit
3d2ba4d0ef
|
@ -85,7 +85,7 @@ class CalDAVEventsHandler(val context: Context) {
|
||||||
|
|
||||||
if (endTS == 0) {
|
if (endTS == 0) {
|
||||||
val duration = cursor.getStringValue(CalendarContract.Events.DURATION)
|
val duration = cursor.getStringValue(CalendarContract.Events.DURATION)
|
||||||
endTS = startTS + Parser().parseDuration(duration)
|
endTS = startTS + Parser().parseDurationSeconds(duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
val importId = getCalDAVEventImportId(calendarId, id)
|
val importId = getCalDAVEventImportId(calendarId, id)
|
||||||
|
@ -120,7 +120,6 @@ class CalDAVEventsHandler(val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addCalDAVEvent(event: Event, calendarId: Long) {
|
fun addCalDAVEvent(event: Event, calendarId: Long) {
|
||||||
val durationMinutes = (event.endTS - event.startTS) / 1000 / 60
|
|
||||||
val uri = CalendarContract.Events.CONTENT_URI
|
val uri = CalendarContract.Events.CONTENT_URI
|
||||||
val values = ContentValues().apply {
|
val values = ContentValues().apply {
|
||||||
put(CalendarContract.Events.CALENDAR_ID, calendarId)
|
put(CalendarContract.Events.CALENDAR_ID, calendarId)
|
||||||
|
@ -128,14 +127,14 @@ class CalDAVEventsHandler(val context: Context) {
|
||||||
put(CalendarContract.Events.DESCRIPTION, event.description)
|
put(CalendarContract.Events.DESCRIPTION, event.description)
|
||||||
put(CalendarContract.Events.DTSTART, event.startTS * 1000L)
|
put(CalendarContract.Events.DTSTART, event.startTS * 1000L)
|
||||||
put(CalendarContract.Events.ALL_DAY, if (event.getIsAllDay()) 1 else 0)
|
put(CalendarContract.Events.ALL_DAY, if (event.getIsAllDay()) 1 else 0)
|
||||||
put(CalendarContract.Events.RRULE, Parser().getShortRepeatInterval(event))
|
put(CalendarContract.Events.RRULE, Parser().getRepeatCode(event))
|
||||||
put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().toString())
|
put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().toString())
|
||||||
|
|
||||||
if (event.getIsAllDay() && event.endTS > event.startTS)
|
if (event.getIsAllDay() && event.endTS > event.startTS)
|
||||||
event.endTS += DAY
|
event.endTS += DAY
|
||||||
|
|
||||||
if (event.repeatInterval > 0) {
|
if (event.repeatInterval > 0) {
|
||||||
put(CalendarContract.Events.DURATION, Parser().getDurationString(durationMinutes))
|
put(CalendarContract.Events.DURATION, getDurationCode(event))
|
||||||
} else {
|
} else {
|
||||||
put(CalendarContract.Events.DTEND, event.endTS * 1000L)
|
put(CalendarContract.Events.DTEND, event.endTS * 1000L)
|
||||||
}
|
}
|
||||||
|
@ -148,6 +147,15 @@ class CalDAVEventsHandler(val context: Context) {
|
||||||
context.dbHelper.updateEventImportIdAndSource(event.id, importId, "$CALDAV-$calendarId")
|
context.dbHelper.updateEventImportIdAndSource(event.id, importId, "$CALDAV-$calendarId")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getDurationCode(event: Event): String {
|
||||||
|
return if (event.getIsAllDay()) {
|
||||||
|
val dur = Math.max(1, (event.endTS - event.startTS) / DAY)
|
||||||
|
"P${dur}D"
|
||||||
|
} else {
|
||||||
|
Parser().getDurationCode((event.endTS - event.startTS) / 60)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getCalDAVEventReminders(eventId: Long): List<Int> {
|
fun getCalDAVEventReminders(eventId: Long): List<Int> {
|
||||||
val reminders = ArrayList<Int>()
|
val reminders = ArrayList<Int>()
|
||||||
val uri = CalendarContract.Reminders.CONTENT_URI
|
val uri = CalendarContract.Reminders.CONTENT_URI
|
||||||
|
|
|
@ -38,7 +38,7 @@ class IcsExporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
out.writeLn("$STATUS$CONFIRMED")
|
out.writeLn("$STATUS$CONFIRMED")
|
||||||
Parser().getShortRepeatInterval(event).let { if (it.isNotEmpty()) out.writeLn("$RRULE$it") }
|
Parser().getRepeatCode(event).let { if (it.isNotEmpty()) out.writeLn("$RRULE$it") }
|
||||||
|
|
||||||
fillReminders(event, out)
|
fillReminders(event, out)
|
||||||
fillIgnoredOccurrences(event, out)
|
fillIgnoredOccurrences(event, out)
|
||||||
|
@ -69,7 +69,7 @@ class IcsExporter {
|
||||||
if (minutes != -1) {
|
if (minutes != -1) {
|
||||||
out.writeLn(BEGIN_ALARM)
|
out.writeLn(BEGIN_ALARM)
|
||||||
out.writeLn("$ACTION$DISPLAY")
|
out.writeLn("$ACTION$DISPLAY")
|
||||||
out.writeLn("$TRIGGER${Parser().getDurationString(minutes)}")
|
out.writeLn("$TRIGGER-${Parser().getDurationCode(minutes)}")
|
||||||
out.writeLn(END_ALARM)
|
out.writeLn(END_ALARM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ class IcsImporter {
|
||||||
curEnd = getTimestamp(line.substring(DTEND.length))
|
curEnd = getTimestamp(line.substring(DTEND.length))
|
||||||
} else if (line.startsWith(DURATION)) {
|
} else if (line.startsWith(DURATION)) {
|
||||||
val duration = line.substring(DURATION.length)
|
val duration = line.substring(DURATION.length)
|
||||||
curEnd = curStart + Parser().parseDuration(duration)
|
curEnd = curStart + Parser().parseDurationSeconds(duration)
|
||||||
} else if (line.startsWith(SUMMARY) && !isNotificationDescription) {
|
} else if (line.startsWith(SUMMARY) && !isNotificationDescription) {
|
||||||
curTitle = line.substring(SUMMARY.length)
|
curTitle = line.substring(SUMMARY.length)
|
||||||
curTitle = getTitle(curTitle).replace("\\n", "\n")
|
curTitle = getTitle(curTitle).replace("\\n", "\n")
|
||||||
|
@ -81,7 +81,7 @@ class IcsImporter {
|
||||||
lastReminderAction = line.substring(ACTION.length)
|
lastReminderAction = line.substring(ACTION.length)
|
||||||
} else if (line.startsWith(TRIGGER)) {
|
} else if (line.startsWith(TRIGGER)) {
|
||||||
if (lastReminderAction == DISPLAY)
|
if (lastReminderAction == DISPLAY)
|
||||||
curReminderMinutes.add(Parser().parseDuration(line.substring(TRIGGER.length)) / 60)
|
curReminderMinutes.add(Parser().parseDurationSeconds(line.substring(TRIGGER.length)) / 60)
|
||||||
} else if (line.startsWith(CATEGORIES)) {
|
} else if (line.startsWith(CATEGORIES)) {
|
||||||
val categories = line.substring(CATEGORIES.length)
|
val categories = line.substring(CATEGORIES.length)
|
||||||
tryAddCategories(categories, context)
|
tryAddCategories(categories, context)
|
||||||
|
|
|
@ -50,14 +50,12 @@ class Parser {
|
||||||
return RepeatRule(repeatInterval, repeatRule, repeatLimit)
|
return RepeatRule(repeatInterval, repeatRule, repeatLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFrequencySeconds(interval: String): Int {
|
private fun getFrequencySeconds(interval: String) = when (interval) {
|
||||||
return when (interval) {
|
DAILY -> DAY
|
||||||
DAILY -> DAY
|
WEEKLY -> WEEK
|
||||||
WEEKLY -> WEEK
|
MONTHLY -> MONTH
|
||||||
MONTHLY -> MONTH
|
YEARLY -> YEAR
|
||||||
YEARLY -> YEAR
|
else -> 0
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleRepeatRule(value: String): Int {
|
private fun handleRepeatRule(value: String): Int {
|
||||||
|
@ -96,7 +94,7 @@ class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// from Daily, 5x... to RRULE:FREQ=DAILY;COUNT=5
|
// from Daily, 5x... to RRULE:FREQ=DAILY;COUNT=5
|
||||||
fun getShortRepeatInterval(event: Event): String {
|
fun getRepeatCode(event: Event): String {
|
||||||
val repeatInterval = event.repeatInterval
|
val repeatInterval = event.repeatInterval
|
||||||
if (repeatInterval == 0)
|
if (repeatInterval == 0)
|
||||||
return ""
|
return ""
|
||||||
|
@ -108,35 +106,24 @@ class Parser {
|
||||||
return "$FREQ=$freq;$INTERVAL=$interval$repeatLimit$byDay"
|
return "$FREQ=$freq;$INTERVAL=$interval$repeatLimit$byDay"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFreq(interval: Int): String {
|
private fun getFreq(interval: Int) = when {
|
||||||
return if (interval % YEAR == 0)
|
interval % YEAR == 0 -> YEARLY
|
||||||
YEARLY
|
interval % MONTH == 0 -> MONTHLY
|
||||||
else if (interval % MONTH == 0)
|
interval % WEEK == 0 -> WEEKLY
|
||||||
MONTHLY
|
else -> DAILY
|
||||||
else if (interval % WEEK == 0)
|
|
||||||
WEEKLY
|
|
||||||
else
|
|
||||||
DAILY
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getInterval(interval: Int): Int {
|
private fun getInterval(interval: Int) = when {
|
||||||
return if (interval % YEAR == 0)
|
interval % YEAR == 0 -> interval / YEAR
|
||||||
interval / YEAR
|
interval % MONTH == 0 -> interval / MONTH
|
||||||
else if (interval % MONTH == 0)
|
interval % WEEK == 0 -> interval / WEEK
|
||||||
interval / MONTH
|
else -> interval / DAY
|
||||||
else if (interval % WEEK == 0)
|
|
||||||
interval / WEEK
|
|
||||||
else
|
|
||||||
interval / DAY
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRepeatLimitString(event: Event): String {
|
private fun getRepeatLimitString(event: Event) = when {
|
||||||
return if (event.repeatLimit == 0)
|
event.repeatLimit == 0 -> ""
|
||||||
""
|
event.repeatLimit < 0 -> ";$COUNT=${-event.repeatLimit}"
|
||||||
else if (event.repeatLimit < 0)
|
else -> ";$UNTIL=${Formatter.getDayCodeFromTS(event.repeatLimit)}"
|
||||||
";$COUNT=${-event.repeatLimit}"
|
|
||||||
else
|
|
||||||
";$UNTIL=${Formatter.getDayCodeFromTS(event.repeatLimit)}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getByDay(event: Event): String {
|
private fun getByDay(event: Event): String {
|
||||||
|
@ -179,22 +166,20 @@ class Parser {
|
||||||
return result.trimEnd(',')
|
return result.trimEnd(',')
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDayLetters(dayOfWeek: Int): String {
|
private fun getDayLetters(dayOfWeek: Int) = when (dayOfWeek) {
|
||||||
return when (dayOfWeek) {
|
1 -> MO
|
||||||
1 -> MO
|
2 -> TU
|
||||||
2 -> TU
|
3 -> WE
|
||||||
3 -> WE
|
4 -> TH
|
||||||
4 -> TH
|
5 -> FR
|
||||||
5 -> FR
|
6 -> SA
|
||||||
6 -> SA
|
else -> SU
|
||||||
else -> SU
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// from P0DT1H5M0S to 3900 (seconds)
|
// from P0DT1H5M0S to 3900 (seconds)
|
||||||
fun parseDuration(duration: String): Int {
|
fun parseDurationSeconds(duration: String): Int {
|
||||||
val weeks = getDurationValue(duration, "W")
|
val weeks = getDurationValue(duration, "W")
|
||||||
val days = getDurationValue(duration, "DT")
|
val days = getDurationValue(duration, "D")
|
||||||
val hours = getDurationValue(duration, "H")
|
val hours = getDurationValue(duration, "H")
|
||||||
val minutes = getDurationValue(duration, "M")
|
val minutes = getDurationValue(duration, "M")
|
||||||
val seconds = getDurationValue(duration, "S")
|
val seconds = getDurationValue(duration, "S")
|
||||||
|
@ -210,7 +195,7 @@ class Parser {
|
||||||
private fun getDurationValue(duration: String, char: String) = Regex("[0-9]+(?=$char)").find(duration)?.value?.toInt() ?: 0
|
private fun getDurationValue(duration: String, char: String) = Regex("[0-9]+(?=$char)").find(duration)?.value?.toInt() ?: 0
|
||||||
|
|
||||||
// from 65 to P0DT1H5M0S
|
// from 65 to P0DT1H5M0S
|
||||||
fun getDurationString(minutes: Int): String {
|
fun getDurationCode(minutes: Int): String {
|
||||||
var days = 0
|
var days = 0
|
||||||
var hours = 0
|
var hours = 0
|
||||||
var remainder = minutes
|
var remainder = minutes
|
||||||
|
@ -222,6 +207,6 @@ class Parser {
|
||||||
hours = Math.floor((remainder / 60).toDouble()).toInt()
|
hours = Math.floor((remainder / 60).toDouble()).toInt()
|
||||||
remainder -= hours * 60
|
remainder -= hours * 60
|
||||||
}
|
}
|
||||||
return "-P${days}DT${hours}H${remainder}M0S"
|
return "P${days}DT${hours}H${remainder}M0S"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue