device_calendar_plus 0.5.2
device_calendar_plus: ^0.5.2 copied to clipboard
A modern, maintained Flutter plugin for reading and writing device calendar events on Android and iOS.
0.5.2 - 2026-06-15 #
Changed #
- No-op updates are now valid instead of throwing.
updateEvent,updateRecurringandupdateCalendarreturn without a platform write when no fields are provided, so "save with no edits" is a harmless no-op rather than anArgumentError(#95).updateRecurringreturns the targeted scope's event id.updateRecurring'sdurationnow accepts zero (an instantaneous event); only a negative duration is rejected.
Fixed #
- Recurrence parsing accepts a negative
BYMONTHDAY(e.g.-1for the last day of the month) instead of rejecting the rule (#91) - Turning a recurring occurrence non-recurring with
thisAndFollowing+Patch.clear()now splits the series on iOS instead of collapsing the whole series into one event (#93) — see thedevice_calendar_plus_ioschangelog listEventsreturns every event across spans longer than ~4 years without dropping or duplicating recurring instances (iOS, #94), and includes zero-duration events sitting exactly on the query start (Android, #416) — see the platform changelogscreateCalendarfails with a clear error on iOS sources that can't hold calendars, instead of an opaque failure (#96) — see thedevice_calendar_plus_ioschangelog- iOS EventKit operations run off the main thread, preventing UI stalls on
large calendars (#79) — see the
device_calendar_plus_ioschangelog
Docs #
- Documented
listEventsper-instance expansion and theeventId@timestampinstanceId format (#97)
0.5.1 - 2026-06-15 #
Fixed #
- iOS:
showEventModal(edit: true)no longer crashes (#77) — see thedevice_calendar_plus_ios0.5.1 changelog
Docs #
- Clarified
showEventModaldocs: the view modal (edit: false) is not read-only — on both iOS and Android the native screen lets the user edit the event, and those edits are saved directly by the OS
0.5.0 - 2026-06-11 #
Changed #
- Breaking:
updateRecurring()is redesigned around series semantics (#69). Times are now expressed asstartTime(EventTimeOfDay) plusdurationinstead of absolutestartDate/endDate, so every occurrence keeps its own date — changing a series' time no longer re-anchors the series to the occurrence you happened to edit (#68, thanks @SuperKrallan). The recurrence rule is now aPatch<RecurrenceRule>:Patch.setreplaces it,Patch.clearcollapses the series into a single event. Returns the event ID of the affected scope. - Breaking:
EventSpan.thisInstanceis gone —EventSpanis now justallEventsandthisAndFollowing. Single occurrences are handled byupdateEvent/deleteEventwith an instance ID (below). - Breaking:
updateEvent()with an instance ID (eventId@timestamp) edits only that occurrence, detaching it from the series; a bare event ID on a recurring event updates the whole series. - Breaking:
deleteEvent()with an instance ID removes only that occurrence; a bare event ID deletes the event (the whole series when recurring).
Added #
EventTimeOfDay— small validating hour/minute value class used byupdateRecurring().
Fixed #
- Occurrence edits with a
startDatepast the occurrence's untouched end are rejected withinvalidArgumentson iOS too, matching Android, instead of saving an inverted event. - Android: events with no status read back as
EventStatus.noneinstead ofEventStatus.tentative— thanks @mauriziopinotti (#70). - Android: all Calendar Provider work runs on a background thread; large calendars could ANR — thanks @mauriziopinotti (#73).
0.4.0 - 2026-05-25 #
Added #
updateRecurring()— update a recurring event with a span choice:EventSpan.allEvents(whole series),thisAndFollowing(this occurrence and every later one), orthisInstance(only this occurrence). Can change or remove the recurrence rule. Resolves the long-standing limitation thatupdateEvent()could not edit recurrence. Based on @SuperKrallan (#36)deleteRecurring()— delete part of a recurring event with a span choice:EventSpan.allEvents(whole series),thisAndFollowing(this occurrence and every later one), orthisInstance(only this occurrence). Now supported on both iOS and Android (Android uses EXDATE on the master rather than a cancelled exception event). Based on @SuperKrallan (#43)EventSpanenum for choosing the scope of a recurring-event operation, shared byupdateRecurring()anddeleteRecurring()urlparameter onupdateEvent()— based on @SuperKrallan (#38)editparameter onshowEventModal()— whentrue, opens the native editor directly (EKEventEditViewControlleron iOS,ACTION_EDITon Android) instead of the read-only viewer. Based on @xonaman (#45)Calendar.colorgetter — derived FlutterColor?parsed fromcolorHex, saving consumers from writing the same hex-parsing helper. Based on @xonaman (#46)
Changed #
- Breaking:
updateEvent()description,locationandurlnow take aPatch<String>instead of aString.nullleaves the field unchanged,Patch.set(value)assigns a value,Patch.clear()removes it — clearing an optional field was previously impossible.
Fixed #
- Missing
availabilityparameter in platform interface test mock — based on @SuperKrallan (#39)
0.3.5 - 2026-04-20 #
Added #
listSources()to discover calendar accounts/sources — based on @magic-fit (#14)- Source selection on
createCalendar— iOS viaCreateCalendarOptionsIos(sourceId:), Android via optionalaccountType supportsCalendarCreationonCalendarSourceavailabilityparameter onupdateEvent()— thanks @SuperKrallan (#29)urlfield on events (iOS:EKEvent.url, Android:CUSTOM_APP_URI) — thanks @magic-fit (#32)showCreateEventModal()with optional pre-fill (title, dates, location, description)- Read-only
attendeeson events (name, email, role, status)
Fixed #
- Android: all-day events appearing in wrong day's query in non-UTC timezones (#20)
- Android:
hasPermissions()now works from background services without an Activity (#31) - Android: calendar/event queries use application context for background compatibility — thanks @vitalii-vov (#26)
- Android:
notDeterminedpermission status correctly distinguished fromdenied— thanks @Albert221 (#12) - iOS: calendar source lookup fallback when default source is unavailable — thanks @zaqwery (#13)
- iOS:
createCalendardefault fallback now picks iCloud over Gmail CalDAV (#33)
0.3.3 - 2025-12-21 #
Fixed #
- Fixed parsing of
instanceIdfor events with@in their event ID (e.g., Google Calendar IDs likeabc123@google.com)
0.3.2 - 2025-12-19 #
Added #
- Android:
CreateCalendarOptionsAndroidfor specifying custom account name when creating calendars createCalendar()now accepts optionalplatformOptionsparameter for platform-specific configuration
0.3.1 - 2025-11-07 #
Fixed #
showEventModal()now properly awaits until the modal is dismissed (iOS and Android)
0.3.0 - 2024-11-05 #
Changed #
- BREAKING:
deleteEvent()now requires named parametereventIdand always deletes entire series for recurring events - BREAKING:
updateEvent()now uses named parametereventId(renamed frominstanceId) and always updates entire series for recurring events - BREAKING: Removed
deleteAllInstancesandupdateAllInstancesparameters - operations on recurring events now always affect the entire series - Renamed
getEvent()andshowEventModal()parameter frominstanceIdtoidto clarify that both event IDs and instance IDs are accepted
Removed #
- BREAKING:
NOT_SUPPORTEDerror code (no longer needed)
0.2.0 - 2024-11-05 #
0.1.0 - 2024-11-04 #
Initial release.
Added #
- Calendar permissions management (request/check)
- List device calendars with metadata (name, color, read-only status, primary flag)
- Query events by date range with optional calendar filtering
- Get single event by ID with support for recurring event instances
- Create events with full metadata support
- Update events including single-instance and all-instance updates for recurring events
- Delete events (single or all instances)
- Show native event modal
- All-day event support with floating date behavior
- Timezone handling for timed events
- Typed exception model with
DeviceCalendarExceptionandDeviceCalendarErrorenum - Federated plugin architecture (Android + iOS)
- Support for Android API 24+ (target/compile 35)
- Support for iOS 13+