Skip to content

Commit

Permalink
Implementing Rrule package (builttoroam#403)
Browse files Browse the repository at this point in the history
Co-authored-by: GoldenSoju <pol82fa91!>
Co-authored-by: thomassth <thomassth@users.noreply.github.com>
  • Loading branch information
GoldenSoju and thomassth authored Oct 6, 2022
1 parent 405ed57 commit 40b1135
Showing 35 changed files with 2,396 additions and 1,972 deletions.
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
@@ -51,6 +51,6 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.google.code.gson:gson:2.8.8'
api 'androidx.appcompat:appcompat:1.3.1'
implementation 'org.dmfs:lib-recur:0.11.2'
implementation 'org.dmfs:lib-recur:0.12.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
}
3 changes: 1 addition & 2 deletions android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#Thu May 17 10:56:13 AEST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
Original file line number Diff line number Diff line change
@@ -4,9 +4,13 @@ import com.builttoroam.devicecalendar.models.Availability
import com.google.gson.*
import java.lang.reflect.Type

class AvailabilitySerializer: JsonSerializer<Availability> {
override fun serialize(src: Availability?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
if(src != null) {
class AvailabilitySerializer : JsonSerializer<Availability> {
override fun serialize(
src: Availability?,
typeOfSrc: Type?,
context: JsonSerializationContext?
): JsonElement {
if (src != null) {
return JsonPrimitive(src.name)
}
return JsonObject()

Large diffs are not rendered by default.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -4,20 +4,70 @@ import android.app.Activity
import android.content.Context
import androidx.annotation.NonNull
import com.builttoroam.devicecalendar.common.Constants
import com.builttoroam.devicecalendar.common.DayOfWeek
import com.builttoroam.devicecalendar.common.RecurrenceFrequency
import com.builttoroam.devicecalendar.models.*
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import org.dmfs.rfc5545.recur.Freq

const val CHANNEL_NAME = "plugins.builttoroam.com/device_calendar"

class DeviceCalendarPlugin() : FlutterPlugin, MethodCallHandler, ActivityAware {
// Methods
private const val REQUEST_PERMISSIONS_METHOD = "requestPermissions"
private const val HAS_PERMISSIONS_METHOD = "hasPermissions"
private const val RETRIEVE_CALENDARS_METHOD = "retrieveCalendars"
private const val RETRIEVE_EVENTS_METHOD = "retrieveEvents"
private const val DELETE_EVENT_METHOD = "deleteEvent"
private const val DELETE_EVENT_INSTANCE_METHOD = "deleteEventInstance"
private const val CREATE_OR_UPDATE_EVENT_METHOD = "createOrUpdateEvent"
private const val CREATE_CALENDAR_METHOD = "createCalendar"
private const val DELETE_CALENDAR_METHOD = "deleteCalendar"

// Method arguments
private const val CALENDAR_ID_ARGUMENT = "calendarId"
private const val CALENDAR_NAME_ARGUMENT = "calendarName"
private const val START_DATE_ARGUMENT = "startDate"
private const val END_DATE_ARGUMENT = "endDate"
private const val EVENT_IDS_ARGUMENT = "eventIds"
private const val EVENT_ID_ARGUMENT = "eventId"
private const val EVENT_TITLE_ARGUMENT = "eventTitle"
private const val EVENT_LOCATION_ARGUMENT = "eventLocation"
private const val EVENT_URL_ARGUMENT = "eventURL"
private const val EVENT_DESCRIPTION_ARGUMENT = "eventDescription"
private const val EVENT_ALL_DAY_ARGUMENT = "eventAllDay"
private const val EVENT_START_DATE_ARGUMENT = "eventStartDate"
private const val EVENT_END_DATE_ARGUMENT = "eventEndDate"
private const val EVENT_START_TIMEZONE_ARGUMENT = "eventStartTimeZone"
private const val EVENT_END_TIMEZONE_ARGUMENT = "eventEndTimeZone"
private const val RECURRENCE_RULE_ARGUMENT = "recurrenceRule"
private const val FREQUENCY_ARGUMENT = "freq"
private const val COUNT_ARGUMENT = "count"
private const val UNTIL_ARGUMENT = "until"
private const val INTERVAL_ARGUMENT = "interval"
private const val BY_WEEK_DAYS_ARGUMENT = "byday"
private const val BY_MONTH_DAYS_ARGUMENT = "bymonthday"
private const val BY_YEAR_DAYS_ARGUMENT = "byyearday"
private const val BY_WEEKS_ARGUMENT = "byweekno"
private const val BY_MONTH_ARGUMENT = "bymonth"
private const val BY_SET_POSITION_ARGUMENT = "bysetpos"

private const val ATTENDEES_ARGUMENT = "attendees"
private const val EMAIL_ADDRESS_ARGUMENT = "emailAddress"
private const val NAME_ARGUMENT = "name"
private const val ROLE_ARGUMENT = "role"
private const val REMINDERS_ARGUMENT = "reminders"
private const val MINUTES_ARGUMENT = "minutes"
private const val FOLLOWING_INSTANCES = "followingInstances"
private const val CALENDAR_COLOR_ARGUMENT = "calendarColor"
private const val LOCAL_ACCOUNT_NAME_ARGUMENT = "localAccountName"
private const val EVENT_AVAILABILITY_ARGUMENT = "availability"
private const val ATTENDANCE_STATUS_ARGUMENT = "attendanceStatus"
private const val EVENT_STATUS_ARGUMENT = "eventStatus"

class DeviceCalendarPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {

/// The MethodChannel that will the communication between Flutter and native Android
///
@@ -27,54 +77,6 @@ class DeviceCalendarPlugin() : FlutterPlugin, MethodCallHandler, ActivityAware {
private var context: Context? = null
private var activity: Activity? = null

// Methods
private val REQUEST_PERMISSIONS_METHOD = "requestPermissions"
private val HAS_PERMISSIONS_METHOD = "hasPermissions"
private val RETRIEVE_CALENDARS_METHOD = "retrieveCalendars"
private val RETRIEVE_EVENTS_METHOD = "retrieveEvents"
private val DELETE_EVENT_METHOD = "deleteEvent"
private val DELETE_EVENT_INSTANCE_METHOD = "deleteEventInstance"
private val CREATE_OR_UPDATE_EVENT_METHOD = "createOrUpdateEvent"
private val CREATE_CALENDAR_METHOD = "createCalendar"
private val DELETE_CALENDAR_METHOD = "deleteCalendar"

// Method arguments
private val CALENDAR_ID_ARGUMENT = "calendarId"
private val CALENDAR_NAME_ARGUMENT = "calendarName"
private val START_DATE_ARGUMENT = "startDate"
private val END_DATE_ARGUMENT = "endDate"
private val EVENT_IDS_ARGUMENT = "eventIds"
private val EVENT_ID_ARGUMENT = "eventId"
private val EVENT_TITLE_ARGUMENT = "eventTitle"
private val EVENT_LOCATION_ARGUMENT = "eventLocation"
private val EVENT_URL_ARGUMENT = "eventURL"
private val EVENT_DESCRIPTION_ARGUMENT = "eventDescription"
private val EVENT_ALL_DAY_ARGUMENT = "eventAllDay"
private val EVENT_START_DATE_ARGUMENT = "eventStartDate"
private val EVENT_END_DATE_ARGUMENT = "eventEndDate"
private val EVENT_START_TIMEZONE_ARGUMENT = "eventStartTimeZone"
private val EVENT_END_TIMEZONE_ARGUMENT = "eventEndTimeZone"
private val RECURRENCE_RULE_ARGUMENT = "recurrenceRule"
private val RECURRENCE_FREQUENCY_ARGUMENT = "recurrenceFrequency"
private val TOTAL_OCCURRENCES_ARGUMENT = "totalOccurrences"
private val INTERVAL_ARGUMENT = "interval"
private val DAYS_OF_WEEK_ARGUMENT = "daysOfWeek"
private val DAY_OF_MONTH_ARGUMENT = "dayOfMonth"
private val MONTH_OF_YEAR_ARGUMENT = "monthOfYear"
private val WEEK_OF_MONTH_ARGUMENT = "weekOfMonth"
private val ATTENDEES_ARGUMENT = "attendees"
private val EMAIL_ADDRESS_ARGUMENT = "emailAddress"
private val NAME_ARGUMENT = "name"
private val ROLE_ARGUMENT = "role"
private val REMINDERS_ARGUMENT = "reminders"
private val MINUTES_ARGUMENT = "minutes"
private val FOLLOWING_INSTANCES = "followingInstances"
private val CALENDAR_COLOR_ARGUMENT = "calendarColor"
private val LOCAL_ACCOUNT_NAME_ARGUMENT = "localAccountName"
private val EVENT_AVAILABILITY_ARGUMENT = "availability"
private val ATTENDANCE_STATUS_ARGUMENT = "attendanceStatus"
private val EVENT_STATUS_ARGUMENT = "eventStatus"

private lateinit var _calendarDelegate: CalendarDelegate

override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
@@ -108,7 +110,7 @@ class DeviceCalendarPlugin() : FlutterPlugin, MethodCallHandler, ActivityAware {
activity = null
}

override fun onMethodCall(call: MethodCall, result: Result) {
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
REQUEST_PERMISSIONS_METHOD -> {
_calendarDelegate.requestPermissions(result)
@@ -124,13 +126,11 @@ class DeviceCalendarPlugin() : FlutterPlugin, MethodCallHandler, ActivityAware {
val startDate = call.argument<Long>(START_DATE_ARGUMENT)
val endDate = call.argument<Long>(END_DATE_ARGUMENT)
val eventIds = call.argument<List<String>>(EVENT_IDS_ARGUMENT) ?: listOf()

_calendarDelegate.retrieveEvents(calendarId!!, startDate, endDate, eventIds, result)
}
CREATE_OR_UPDATE_EVENT_METHOD -> {
val calendarId = call.argument<String>(CALENDAR_ID_ARGUMENT)
val event = parseEventArgs(call, calendarId)

_calendarDelegate.createOrUpdateEvent(calendarId!!, event, result)
}
DELETE_EVENT_METHOD -> {
@@ -146,18 +146,30 @@ class DeviceCalendarPlugin() : FlutterPlugin, MethodCallHandler, ActivityAware {
val endDate = call.argument<Long>(EVENT_END_DATE_ARGUMENT)
val followingInstances = call.argument<Boolean>(FOLLOWING_INSTANCES)

_calendarDelegate.deleteEvent(calendarId!!, eventId!!, result, startDate, endDate, followingInstances)
_calendarDelegate.deleteEvent(
calendarId!!,
eventId!!,
result,
startDate,
endDate,
followingInstances
)
}
CREATE_CALENDAR_METHOD -> {
val calendarName = call.argument<String>(CALENDAR_NAME_ARGUMENT)
val calendarColor = call.argument<String>(CALENDAR_COLOR_ARGUMENT)
val localAccountName = call.argument<String>(LOCAL_ACCOUNT_NAME_ARGUMENT)

_calendarDelegate.createCalendar(calendarName!!, calendarColor, localAccountName!!, result)
_calendarDelegate.createCalendar(
calendarName!!,
calendarColor,
localAccountName!!,
result
)
}
DELETE_CALENDAR_METHOD -> {
val calendarId = call.argument<String>(CALENDAR_ID_ARGUMENT)
_calendarDelegate.deleteCalendar(calendarId!!,result)
_calendarDelegate.deleteCalendar(calendarId!!, result)
}
else -> {
result.notImplemented()
@@ -181,78 +193,98 @@ class DeviceCalendarPlugin() : FlutterPlugin, MethodCallHandler, ActivityAware {
event.availability = parseAvailability(call.argument<String>(EVENT_AVAILABILITY_ARGUMENT))
event.eventStatus = parseEventStatus(call.argument<String>(EVENT_STATUS_ARGUMENT))

if (call.hasArgument(RECURRENCE_RULE_ARGUMENT) && call.argument<Map<String, Any>>(RECURRENCE_RULE_ARGUMENT) != null) {
if (call.hasArgument(RECURRENCE_RULE_ARGUMENT) && call.argument<Map<String, Any>>(
RECURRENCE_RULE_ARGUMENT
) != null
) {
val recurrenceRule = parseRecurrenceRuleArgs(call)
event.recurrenceRule = recurrenceRule
}

if (call.hasArgument(ATTENDEES_ARGUMENT) && call.argument<List<Map<String, Any>>>(ATTENDEES_ARGUMENT) != null) {
if (call.hasArgument(ATTENDEES_ARGUMENT) && call.argument<List<Map<String, Any>>>(
ATTENDEES_ARGUMENT
) != null
) {
event.attendees = mutableListOf()
val attendeesArgs = call.argument<List<Map<String, Any>>>(ATTENDEES_ARGUMENT)!!
for (attendeeArgs in attendeesArgs) {
event.attendees.add(Attendee(
event.attendees.add(
Attendee(
attendeeArgs[EMAIL_ADDRESS_ARGUMENT] as String,
attendeeArgs[NAME_ARGUMENT] as String?,
attendeeArgs[ROLE_ARGUMENT] as Int,
attendeeArgs[ATTENDANCE_STATUS_ARGUMENT] as Int?,
null, null))
null, null
)
)
}
}

if (call.hasArgument(REMINDERS_ARGUMENT) && call.argument<List<Map<String, Any>>>(REMINDERS_ARGUMENT) != null) {
if (call.hasArgument(REMINDERS_ARGUMENT) && call.argument<List<Map<String, Any>>>(
REMINDERS_ARGUMENT
) != null
) {
event.reminders = mutableListOf()
val remindersArgs = call.argument<List<Map<String, Any>>>(REMINDERS_ARGUMENT)!!
for (reminderArgs in remindersArgs) {
event.reminders.add(Reminder(reminderArgs[MINUTES_ARGUMENT] as Int))
}
}

return event
}

private fun parseRecurrenceRuleArgs(call: MethodCall): RecurrenceRule {
val recurrenceRuleArgs = call.argument<Map<String, Any>>(RECURRENCE_RULE_ARGUMENT)!!
val recurrenceFrequencyIndex = recurrenceRuleArgs[RECURRENCE_FREQUENCY_ARGUMENT] as Int
val recurrenceRule = RecurrenceRule(RecurrenceFrequency.values()[recurrenceFrequencyIndex])
if (recurrenceRuleArgs.containsKey(TOTAL_OCCURRENCES_ARGUMENT)) {
recurrenceRule.totalOccurrences = recurrenceRuleArgs[TOTAL_OCCURRENCES_ARGUMENT] as Int
val recurrenceFrequencyString = recurrenceRuleArgs[FREQUENCY_ARGUMENT] as String
val recurrenceFrequency = Freq.valueOf(recurrenceFrequencyString)
val recurrenceRule = RecurrenceRule(recurrenceFrequency)

if (recurrenceRuleArgs.containsKey(COUNT_ARGUMENT)) {
recurrenceRule.count = recurrenceRuleArgs[COUNT_ARGUMENT] as Int?
}

if (recurrenceRuleArgs.containsKey(INTERVAL_ARGUMENT)) {
recurrenceRule.interval = recurrenceRuleArgs[INTERVAL_ARGUMENT] as Int
}

if (recurrenceRuleArgs.containsKey(END_DATE_ARGUMENT)) {
recurrenceRule.endDate = recurrenceRuleArgs[END_DATE_ARGUMENT] as Long
if (recurrenceRuleArgs.containsKey(UNTIL_ARGUMENT)) {
recurrenceRule.until = recurrenceRuleArgs[UNTIL_ARGUMENT] as String?
}

if (recurrenceRuleArgs.containsKey(DAYS_OF_WEEK_ARGUMENT)) {
recurrenceRule.daysOfWeek = recurrenceRuleArgs[DAYS_OF_WEEK_ARGUMENT].toListOf<Int>()?.map { DayOfWeek.values()[it] }?.toMutableList()
if (recurrenceRuleArgs.containsKey(BY_WEEK_DAYS_ARGUMENT)) {
recurrenceRule.byday =
recurrenceRuleArgs[BY_WEEK_DAYS_ARGUMENT].toListOf<String>()?.toMutableList()
}

if (recurrenceRuleArgs.containsKey(DAY_OF_MONTH_ARGUMENT)) {
recurrenceRule.dayOfMonth = recurrenceRuleArgs[DAY_OF_MONTH_ARGUMENT] as Int
if (recurrenceRuleArgs.containsKey(BY_MONTH_DAYS_ARGUMENT)) {
recurrenceRule.bymonthday =
recurrenceRuleArgs[BY_MONTH_DAYS_ARGUMENT] as MutableList<Int>?
}

if (recurrenceRuleArgs.containsKey(MONTH_OF_YEAR_ARGUMENT)) {
recurrenceRule.monthOfYear = recurrenceRuleArgs[MONTH_OF_YEAR_ARGUMENT] as Int
if (recurrenceRuleArgs.containsKey(BY_YEAR_DAYS_ARGUMENT)) {
recurrenceRule.byyearday =
recurrenceRuleArgs[BY_YEAR_DAYS_ARGUMENT] as MutableList<Int>?
}

if (recurrenceRuleArgs.containsKey(WEEK_OF_MONTH_ARGUMENT)) {
recurrenceRule.weekOfMonth = recurrenceRuleArgs[WEEK_OF_MONTH_ARGUMENT] as Int
if (recurrenceRuleArgs.containsKey(BY_WEEKS_ARGUMENT)) {
recurrenceRule.byweekno = recurrenceRuleArgs[BY_WEEKS_ARGUMENT] as MutableList<Int>?
}

if (recurrenceRuleArgs.containsKey(BY_MONTH_ARGUMENT)) {
recurrenceRule.bymonth = recurrenceRuleArgs[BY_MONTH_ARGUMENT] as MutableList<Int>?
}

if (recurrenceRuleArgs.containsKey(BY_SET_POSITION_ARGUMENT)) {
recurrenceRule.bysetpos =
recurrenceRuleArgs[BY_SET_POSITION_ARGUMENT] as MutableList<Int>?
}
return recurrenceRule
}

private inline fun <reified T : Any> Any?.toListOf(): List<T>? {
return (this as List<*>?)?.filterIsInstance<T>()?.toList()
}

private inline fun <reified T : Any> Any?.toMutableListOf(): MutableList<T>? {
return this?.toListOf<T>()?.toMutableList()
}

private fun parseAvailability(value: String?): Availability? =
if (value == null || value == Constants.AVAILABILITY_UNAVAILABLE) {
null

This file was deleted.

Loading

0 comments on commit 40b1135

Please sign in to comment.