rewrite CalDAV calendar updating a bit, try avoiding duplicate events

This commit is contained in:
tibbi 2018-12-04 14:37:54 +01:00
parent dd9dd2c021
commit c4ba7d1165
6 changed files with 96 additions and 56 deletions

View File

@ -4,12 +4,10 @@ import android.app.SearchManager
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.database.ContentObserver
import android.database.Cursor
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.provider.ContactsContract
import android.view.Menu
import android.view.MenuItem
@ -140,7 +138,6 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
override fun onStop() {
super.onStop()
contentResolver.unregisterContentObserver(calDAVSyncObserver)
closeSearch()
}
@ -367,21 +364,14 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
toast(R.string.refreshing)
}
syncCalDAVCalendars(this, calDAVSyncObserver)
scheduleCalDAVSync(true)
}
private val calDAVSyncObserver = object : ContentObserver(Handler()) {
override fun onChange(selfChange: Boolean) {
super.onChange(selfChange)
if (!selfChange) {
syncCalDAVCalendars(this) {
calDAVHelper.refreshCalendars(this) {
calDAVChanged()
}
}
}
private fun calDAVChanged() {
contentResolver.unregisterContentObserver(calDAVSyncObserver)
recheckCalDAVCalendars {
refreshViewPager()
if (showCalDAVRefreshToast) {

View File

@ -217,7 +217,14 @@ class SettingsActivity : SimpleActivity() {
eventsHelper.insertOrUpdateEventType(this, eventType)
}
}
calDAVHelper.refreshCalendars(this) {}
syncCalDAVCalendars(this) {
calDAVHelper.refreshCalendars(this) {
if (settings_caldav_sync.isChecked) {
toast(R.string.synchronization_completed)
}
}
}
}
val removedCalendarIds = oldCalendarIds.filter { !newCalendarIds.contains(it) }
@ -229,9 +236,6 @@ class SettingsActivity : SimpleActivity() {
}
eventTypesDB.deleteEventTypesWithCalendarId(removedCalendarIds)
if (settings_caldav_sync.isChecked) {
toast(R.string.synchronization_completed)
}
}.start()
}
}

View File

@ -1,9 +1,19 @@
package com.simplemobiletools.calendar.pro.activities
import android.content.Context
import android.database.ContentObserver
import android.os.Handler
import android.provider.CalendarContract
import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.extensions.config
import com.simplemobiletools.calendar.pro.extensions.refreshCalDAVCalendars
import com.simplemobiletools.commons.activities.BaseSimpleActivity
open class SimpleActivity : BaseSimpleActivity() {
val CALDAV_REFRESH_DELAY = 3000L
val calDAVRefreshHandler = Handler()
var calDAVRefreshCallback: (() -> Unit)? = null
override fun getAppIconIDs() = arrayListOf(
R.mipmap.ic_launcher_red,
R.mipmap.ic_launcher_pink,
@ -27,4 +37,35 @@ open class SimpleActivity : BaseSimpleActivity() {
)
override fun getAppLauncherName() = getString(R.string.app_launcher_name)
fun Context.syncCalDAVCalendars(activity: SimpleActivity?, callback: () -> Unit) {
calDAVRefreshCallback = callback
Thread {
val uri = CalendarContract.Calendars.CONTENT_URI
contentResolver.unregisterContentObserver(calDAVSyncObserver)
contentResolver.registerContentObserver(uri, false, calDAVSyncObserver)
refreshCalDAVCalendars(activity, config.caldavSyncedCalendarIDs)
}.start()
}
// caldav refresh content observer triggers multiple times in a row at updating, so call the callback only a few seconds after the (hopefully) last one
private val calDAVSyncObserver = object : ContentObserver(Handler()) {
override fun onChange(selfChange: Boolean) {
super.onChange(selfChange)
if (!selfChange) {
calDAVRefreshHandler.removeCallbacksAndMessages(null)
calDAVRefreshHandler.postDelayed({
Thread {
unregisterObserver()
calDAVRefreshCallback?.invoke()
calDAVRefreshCallback = null
}.start()
}, CALDAV_REFRESH_DELAY)
}
}
}
private fun unregisterObserver() {
contentResolver.unregisterContentObserver(calDAVSyncObserver)
}
}

View File

@ -9,7 +9,6 @@ import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.database.ContentObserver
import android.media.AudioAttributes
import android.net.Uri
import android.os.Bundle
@ -330,32 +329,6 @@ fun Context.scheduleCalDAVSync(activate: Boolean) {
}
}
fun Context.syncCalDAVCalendars(activity: SimpleActivity?, calDAVSyncObserver: ContentObserver) {
Thread {
val uri = CalendarContract.Calendars.CONTENT_URI
contentResolver.unregisterContentObserver(calDAVSyncObserver)
contentResolver.registerContentObserver(uri, false, calDAVSyncObserver)
refreshCalDAVCalendars(activity, config.caldavSyncedCalendarIDs)
}.start()
}
fun Context.refreshCalDAVCalendars(activity: SimpleActivity?, ids: String) {
val uri = CalendarContract.Calendars.CONTENT_URI
val accounts = HashSet<Account>()
val calendars = calDAVHelper.getCalDAVCalendars(activity, ids)
calendars.forEach {
accounts.add(Account(it.accountName, it.accountType))
}
Bundle().apply {
putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true)
putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true)
accounts.forEach {
ContentResolver.requestSync(it, uri.authority, this)
}
}
}
fun Context.addDayNumber(rawTextColor: Int, day: DayMonthly, linearLayout: LinearLayout, dayLabelHeight: Int, callback: (Int) -> Unit) {
var textColor = rawTextColor
if (!day.isThisMonth)
@ -453,3 +426,20 @@ fun Context.handleEventDeleting(eventIds: List<Long>, timestamps: List<Long>, ac
}
}
}
fun Context.refreshCalDAVCalendars(activity: SimpleActivity?, ids: String) {
val uri = CalendarContract.Calendars.CONTENT_URI
val accounts = HashSet<Account>()
val calendars = calDAVHelper.getCalDAVCalendars(activity, ids)
calendars.forEach {
accounts.add(Account(it.accountName, it.accountType))
}
Bundle().apply {
putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true)
putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true)
accounts.forEach {
ContentResolver.requestSync(it, uri.authority, this)
}
}
}

View File

@ -13,6 +13,7 @@ import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.models.CalDAVCalendar
import com.simplemobiletools.calendar.pro.models.Event
import com.simplemobiletools.calendar.pro.models.EventType
import com.simplemobiletools.calendar.pro.objects.States.isUpdatingCalDAV
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CALENDAR
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CALENDAR
@ -23,20 +24,29 @@ class CalDAVHelper(val context: Context) {
private val eventsHelper = context.eventsHelper
fun refreshCalendars(activity: SimpleActivity? = null, callback: () -> Unit) {
val calDAVCalendars = getCalDAVCalendars(activity, context.config.caldavSyncedCalendarIDs)
for (calendar in calDAVCalendars) {
val localEventType = eventsHelper.getEventTypeWithCalDAVCalendarId(calendar.id) ?: continue
localEventType.apply {
title = calendar.displayName
caldavDisplayName = calendar.displayName
caldavEmail = calendar.accountName
eventsHelper.insertOrUpdateEventTypeSync(this)
}
fetchCalDAVCalendarEvents(calendar.id, localEventType.id!!, activity)
if (isUpdatingCalDAV) {
return
}
isUpdatingCalDAV = true
try {
val calDAVCalendars = getCalDAVCalendars(activity, context.config.caldavSyncedCalendarIDs)
for (calendar in calDAVCalendars) {
val localEventType = eventsHelper.getEventTypeWithCalDAVCalendarId(calendar.id) ?: continue
localEventType.apply {
title = calendar.displayName
caldavDisplayName = calendar.displayName
caldavEmail = calendar.accountName
eventsHelper.insertOrUpdateEventTypeSync(this)
}
fetchCalDAVCalendarEvents(calendar.id, localEventType.id!!, activity)
}
context.scheduleCalDAVSync(true)
callback()
} finally {
isUpdatingCalDAV = false
}
context.scheduleCalDAVSync(true)
callback()
}
@SuppressLint("MissingPermission")

View File

@ -0,0 +1,5 @@
package com.simplemobiletools.calendar.pro.objects
object States {
var isUpdatingCalDAV = false
}