UNPKG

16.5 kBJavaScriptView Raw
1// @flow
2
3import { NativeModules, Platform, processColor } from 'react-native';
4
5type RecurringEventOptions = {
6 futureEvents?: boolean,
7 instanceStartDate?: string,
8}; // iOS
9
10type Calendar = {
11 id?: string,
12 title?: string,
13 sourceId?: string, // iOS
14 source?: Source,
15 type?: string, // iOS
16 color?: string,
17 entityType?: string, // iOS
18 allowsModifications?: boolean,
19 allowedAvailabilities?: boolean,
20 isPrimary?: boolean, // Android
21 name?: string, // Android
22 ownerAccount?: string, // Android
23 timeZone?: string, // Android
24 allowedReminders?: Array<string>, // Android
25 allowedAttendeeTypes?: Array<string>, // Android
26 isVisible?: boolean, // Android
27 isSynced?: boolean, // Android
28 accessLevel?: string, // Android
29};
30
31type Source = {
32 id?: string, // iOS only ??
33 type?: string,
34 name?: string,
35 isLocalAccount?: boolean, // Android
36};
37
38type Event = {
39 id?: string,
40 calendarId?: string,
41 title?: string,
42 location?: string,
43 creationDate?: string, // iOS
44 lastModifiedDate?: string, // iOS
45 timeZone?: string,
46 endTimeZone?: string, // Android
47 url?: string, // iOS
48 notes?: string,
49 alarms?: Array<Alarm>,
50 recurrenceRule?: RecurrenceRule,
51 startDate?: string,
52 endDate?: string,
53 originalStartDate?: string, // iOS
54 isDetached?: boolean, // iOS
55 allDay?: boolean,
56 availability?: string, // Availability
57 status?: string, // Status
58 organizer?: string, // Organizer - iOS
59 organizerEmail?: string, // Android
60 accessLevel?: string, // Android,
61 guestsCanModify?: boolean, // Android,
62 guestsCanInviteOthers?: boolean, // Android
63 guestsCanSeeGuests?: boolean, // Android
64 originalId?: string, // Android
65 instanceId?: string, // Android
66};
67
68type Reminder = {
69 id?: string,
70 calendarId?: string,
71 title?: string,
72 location?: string,
73 creationDate?: string,
74 lastModifiedDate?: string,
75 timeZone?: string,
76 url?: string,
77 notes?: string,
78 alarms?: Array<Alarm>,
79 recurrenceRule?: RecurrenceRule,
80 startDate?: string,
81 dueDate?: string,
82 completed?: boolean,
83 completionDate?: string,
84};
85
86type Attendee = {
87 id?: string, // Android
88 isCurrentUser?: boolean, // iOS
89 name?: string,
90 role?: string,
91 status?: string,
92 type?: string,
93 url?: string, // iOS
94 email?: string, // Android
95};
96
97type Alarm = {
98 absoluteDate?: string, // iOS
99 relativeOffset?: string,
100 structuredLocation?: {
101 // iOS
102 title?: string,
103 proximity?: string, // Proximity
104 radius?: number,
105 coords?: {
106 latitude?: number,
107 longitude?: number,
108 },
109 },
110 method?: string, // Method, Android
111};
112
113type RecurrenceRule = {
114 frequency: string, // Frequency
115 interval?: number,
116 endDate?: string,
117 occurrence?: number,
118};
119
120export async function getCalendarsAsync(entityType?: string): Promise<void> {
121 if (!entityType) {
122 return NativeModules.ExponentCalendar.getCalendarsAsync(null);
123 }
124 return NativeModules.ExponentCalendar.getCalendarsAsync(entityType);
125}
126
127export async function createCalendarAsync(details: Calendar = {}): Promise<string> {
128 let color = details.color;
129 if (color) {
130 color = processColor(color);
131 }
132 const newDetails = { ...details, id: undefined, color };
133 return NativeModules.ExponentCalendar.saveCalendarAsync(newDetails);
134}
135
136export async function updateCalendarAsync(id: string, details: Calendar = {}): Promise<string> {
137 if (!id) {
138 throw new Error(
139 'updateCalendarAsync must be called with an id (string) of the target calendar'
140 );
141 }
142 let color = details.color;
143 if (color) {
144 color = processColor(color);
145 }
146
147 if (Platform.OS === 'android') {
148 if (
149 details.hasOwnProperty('source') ||
150 details.hasOwnProperty('color') ||
151 details.hasOwnProperty('allowsModifications') ||
152 details.hasOwnProperty('allowedAvailabilities') ||
153 details.hasOwnProperty('isPrimary') ||
154 details.hasOwnProperty('ownerAccount') ||
155 details.hasOwnProperty('timeZone') ||
156 details.hasOwnProperty('allowedReminders') ||
157 details.hasOwnProperty('allowedAttendeeTypes') ||
158 details.hasOwnProperty('accessLevel')
159 ) {
160 console.warn(
161 'updateCalendarAsync was called with one or more read-only properties, which will not be updated'
162 );
163 }
164 } else {
165 if (
166 details.hasOwnProperty('source') ||
167 details.hasOwnProperty('type') ||
168 details.hasOwnProperty('entityType') ||
169 details.hasOwnProperty('allowsModifications') ||
170 details.hasOwnProperty('allowedAvailabilities')
171 ) {
172 console.warn(
173 'updateCalendarAsync was called with one or more read-only properties, which will not be updated'
174 );
175 }
176 }
177
178 const newDetails = { ...details, id, color };
179 return NativeModules.ExponentCalendar.saveCalendarAsync(newDetails);
180}
181
182export async function deleteCalendarAsync(id: string): Promise<void> {
183 if (!id) {
184 throw new Error(
185 'deleteCalendarAsync must be called with an id (string) of the target calendar'
186 );
187 }
188 return NativeModules.ExponentCalendar.deleteCalendarAsync(id);
189}
190
191export async function getEventsAsync(
192 calendarIds: Array<string>,
193 startDate: Date,
194 endDate: Date
195): Promise<Array<Event>> {
196 if (!startDate) {
197 throw new Error('getEventsAsync must be called with a startDate (date) to search for events');
198 }
199 if (!endDate) {
200 throw new Error('getEventsAsync must be called with an endDate (date) to search for events');
201 }
202 if (!calendarIds || !calendarIds.length) {
203 throw new Error(
204 'getEventsAsync must be called with a non-empty array of calendarIds to search'
205 );
206 }
207 return NativeModules.ExponentCalendar.getEventsAsync(startDate, endDate, calendarIds);
208}
209
210export async function getEventAsync(
211 id: string,
212 { futureEvents = false, instanceStartDate }: RecurringEventOptions = {}
213): Promise<Event> {
214 if (!id) {
215 throw new Error('getEventAsync must be called with an id (string) of the target event');
216 }
217 if (Platform.OS === 'ios') {
218 return NativeModules.ExponentCalendar.getEventByIdAsync(id, instanceStartDate);
219 } else {
220 return NativeModules.ExponentCalendar.getEventByIdAsync(id);
221 }
222}
223
224export async function createEventAsync(calendarId: string, details: Event = {}): Promise<string> {
225 if (!calendarId) {
226 throw new Error('createEventAsync must be called with an id (string) of the target calendar');
227 }
228
229 if (Platform.OS === 'android') {
230 if (!details.startDate) {
231 throw new Error('createEventAsync requires a startDate (Date)');
232 }
233 if (!details.endDate) {
234 throw new Error('createEventAsync requires an endDate (Date)');
235 }
236 if (!details.timeZone) {
237 throw new Error('createEventAsync requires a timeZone (string)');
238 }
239 }
240
241 const newDetails = { ...details, id: undefined, calendarId };
242 return NativeModules.ExponentCalendar.saveEventAsync(newDetails, {});
243}
244
245export async function updateEventAsync(
246 id: string,
247 details: Event = {},
248 { futureEvents = false, instanceStartDate }: RecurringEventOptions = {}
249): Promise<string> {
250 if (!id) {
251 throw new Error('updateEventAsync must be called with an id (string) of the target event');
252 }
253
254 if (Platform.OS === 'ios') {
255 if (
256 details.hasOwnProperty('creationDate') ||
257 details.hasOwnProperty('lastModifiedDate') ||
258 details.hasOwnProperty('originalStartDate') ||
259 details.hasOwnProperty('isDetached') ||
260 details.hasOwnProperty('status') ||
261 details.hasOwnProperty('organizer')
262 ) {
263 console.warn(
264 'updateEventAsync was called with one or more read-only properties, which will not be updated'
265 );
266 }
267 }
268
269 const newDetails = { ...details, id, instanceStartDate };
270 return NativeModules.ExponentCalendar.saveEventAsync(newDetails, { futureEvents });
271}
272
273export async function deleteEventAsync(
274 id: string,
275 { futureEvents = false, instanceStartDate }: RecurringEventOptions = {}
276): Promise<void> {
277 if (!id) {
278 throw new Error('deleteEventAsync must be called with an id (string) of the target event');
279 }
280 return NativeModules.ExponentCalendar.deleteEventAsync(
281 { id, instanceStartDate },
282 { futureEvents }
283 );
284}
285
286export async function getAttendeesForEventAsync(
287 id: string,
288 { futureEvents = false, instanceStartDate }: RecurringEventOptions = {}
289): Promise<Array<Attendee>> {
290 if (!id) {
291 throw new Error(
292 'getAttendeesForEventAsync must be called with an id (string) of the target event'
293 );
294 }
295 // Android only takes an ID, iOS takes an object
296 const params = Platform.OS === 'ios' ? { id, instanceStartDate } : id;
297 return NativeModules.ExponentCalendar.getAttendeesForEventAsync(params);
298}
299
300export async function createAttendeeAsync(
301 eventId: string,
302 details: Attendee = {}
303): Promise<string> {
304 if (Platform.OS === 'ios') {
305 throw new Error('createAttendeeAsync is not available on iOS');
306 }
307 if (!eventId) {
308 throw new Error('createAttendeeAsync must be called with an id (string) of the target event');
309 }
310 if (!details.email) {
311 throw new Error('createAttendeeAsync requires an email (string)');
312 }
313 if (!details.role) {
314 throw new Error('createAttendeeAsync requires a role (string)');
315 }
316 if (!details.type) {
317 throw new Error('createAttendeeAsync requires a type (string)');
318 }
319 if (!details.status) {
320 throw new Error('createAttendeeAsync requires a status (string)');
321 }
322 const newDetails = { ...details, id: undefined };
323 return NativeModules.ExponentCalendar.saveAttendeeForEventAsync(newDetails, eventId);
324} // Android
325
326export async function updateAttendeeAsync(id: string, details: Attendee = {}): Promise<string> {
327 if (Platform.OS === 'ios') {
328 throw new Error('updateAttendeeAsync is not available on iOS');
329 }
330 if (!id) {
331 throw new Error('updateAttendeeAsync must be called with an id (string) of the target event');
332 }
333 const newDetails = { ...details, id };
334 return NativeModules.ExponentCalendar.saveAttendeeForEventAsync(newDetails, null);
335} // Android
336
337export async function deleteAttendeeAsync(id: string): Promise<void> {
338 if (Platform.OS === 'ios') {
339 throw new Error('deleteAttendeeAsync is not available on iOS');
340 }
341 if (!id) {
342 throw new Error('deleteAttendeeAsync must be called with an id (string) of the target event');
343 }
344 return NativeModules.ExponentCalendar.deleteAttendeeAsync(id);
345} // Android
346
347export async function getRemindersAsync(
348 calendarIds: Array<string>,
349 status?: string,
350 startDate: Date,
351 endDate: Date
352): Promise<Array<Reminder>> {
353 if (Platform.OS === 'android') {
354 throw new Error('getRemindersAsync is not available on Android');
355 }
356 if (status && !startDate) {
357 throw new Error(
358 'getRemindersAsync must be called with a startDate (date) to search for reminders'
359 );
360 }
361 if (status && !endDate) {
362 throw new Error(
363 'getRemindersAsync must be called with an endDate (date) to search for reminders'
364 );
365 }
366 if (!calendarIds || !calendarIds.length) {
367 throw new Error(
368 'getRemindersAsync must be called with a non-empty array of calendarIds to search'
369 );
370 }
371 return NativeModules.ExponentCalendar.getRemindersAsync(
372 startDate || null,
373 endDate || null,
374 calendarIds,
375 status || null
376 );
377} // iOS
378
379export async function getReminderAsync(id: string): Promise<Reminder> {
380 if (Platform.OS === 'android') {
381 throw new Error('getReminderAsync is not available on Android');
382 }
383 if (!id) {
384 throw new Error('getReminderAsync must be called with an id (string) of the target reminder');
385 }
386 return NativeModules.ExponentCalendar.getReminderByIdAsync(id);
387} // iOS
388
389export async function createReminderAsync(
390 calendarId: string,
391 details: Reminder = {}
392): Promise<string> {
393 if (Platform.OS === 'android') {
394 throw new Error('createReminderAsync is not available on Android');
395 }
396 if (!calendarId) {
397 throw new Error(
398 'createReminderAsync must be called with an id (string) of the target calendar'
399 );
400 }
401 const newDetails = { ...details, id: undefined, calendarId };
402 return NativeModules.ExponentCalendar.saveReminderAsync(newDetails);
403} // iOS
404
405export async function updateReminderAsync(id: string, details: Reminder = {}): Promise<string> {
406 if (Platform.OS === 'android') {
407 throw new Error('updateReminderAsync is not available on Android');
408 }
409 if (!id) {
410 throw new Error(
411 'updateReminderAsync must be called with an id (string) of the target reminder'
412 );
413 }
414
415 if (details.hasOwnProperty('creationDate') || details.hasOwnProperty('lastModifiedDate')) {
416 console.warn(
417 'updateReminderAsync was called with one or more read-only properties, which will not be updated'
418 );
419 }
420
421 const newDetails = { ...details, id };
422 return NativeModules.ExponentCalendar.saveReminderAsync(newDetails);
423} // iOS
424
425export async function deleteReminderAsync(id: string): Promise<void> {
426 if (Platform.OS === 'android') {
427 throw new Error('deleteReminderAsync is not available on Android');
428 }
429 if (!id) {
430 throw new Error(
431 'deleteReminderAsync must be called with an id (string) of the target reminder'
432 );
433 }
434 return NativeModules.ExponentCalendar.deleteReminderAsync(id);
435} // iOS
436
437export async function getSourcesAsync(): Promise<Array<Source>> {
438 if (Platform.OS === 'android') {
439 throw new Error('getSourcesAsync is not available on Android');
440 }
441 return NativeModules.ExponentCalendar.getSourcesAsync();
442} // iOS
443
444export async function getSourceAsync(id: string): Promise<Source> {
445 if (Platform.OS === 'android') {
446 throw new Error('getSourceAsync is not available on Android');
447 }
448 if (!id) {
449 throw new Error('getSourceAsync must be called with an id (string) of the target source');
450 }
451 return NativeModules.ExponentCalendar.getSourceByIdAsync(id);
452} // iOS
453
454export function openEventInCalendar(id: string): void {
455 if (Platform.OS === 'ios') {
456 console.warn('openEventInCalendar is not available on iOS');
457 return;
458 }
459 if (!id) {
460 throw new Error('openEventInCalendar must be called with an id (string) of the target event');
461 }
462 return NativeModules.ExponentCalendar.openEventInCalendar(parseInt(id, 10));
463} // Android
464
465export const EntityTypes = {
466 EVENT: 'event',
467 REMINDER: 'reminder',
468};
469
470export const Frequency = {
471 DAILY: 'daily',
472 WEEKLY: 'weekly',
473 MONTHLY: 'monthly',
474 YEARLY: 'yearly',
475};
476
477export const Availability = {
478 NOT_SUPPORTED: 'notSupported', // iOS
479 BUSY: 'busy',
480 FREE: 'free',
481 TENTATIVE: 'tentative',
482 UNAVAILABLE: 'unavailable', // iOS
483};
484
485export const CalendarType = {
486 LOCAL: 'local',
487 CALDAV: 'caldav',
488 EXCHANGE: 'exchange',
489 SUBSCRIBED: 'subscribed',
490 BIRTHDAYS: 'birthdays',
491}; // iOS
492
493export const EventStatus = {
494 NONE: 'none',
495 CONFIRMED: 'confirmed',
496 TENTATIVE: 'tentative',
497 CANCELED: 'canceled',
498};
499
500export const SourceType = {
501 LOCAL: 'local',
502 EXCHANGE: 'exchange',
503 CALDAV: 'caldav',
504 MOBILEME: 'mobileme',
505 SUBSCRIBED: 'subscribed',
506 BIRTHDAYS: 'birthdays',
507};
508
509export const AttendeeRole = {
510 UNKNOWN: 'unknown', // iOS
511 REQUIRED: 'required', // iOS
512 OPTIONAL: 'optional', // iOS
513 CHAIR: 'chair', // iOS
514 NON_PARTICIPANT: 'nonParticipant', // iOS
515 ATTENDEE: 'attendee', // Android
516 ORGANIZER: 'organizer', // Android
517 PERFORMER: 'performer', // Android
518 SPEAKER: 'speaker', // Android
519 NONE: 'none', // Android
520};
521
522export const AttendeeStatus = {
523 UNKNOWN: 'unknown', // iOS
524 PENDING: 'pending', // iOS
525 ACCEPTED: 'accepted',
526 DECLINED: 'declined',
527 TENTATIVE: 'tentative',
528 DELEGATED: 'delegated', // iOS
529 COMPLETED: 'completed', // iOS
530 IN_PROCESS: 'inProcess', // iOS
531 INVITED: 'invited', // Android
532 NONE: 'none', // Android
533};
534
535export const AttendeeType = {
536 UNKNOWN: 'unknown', // iOS
537 PERSON: 'person', // iOS
538 ROOM: 'room', // iOS
539 GROUP: 'group', // iOS
540 RESOURCE: 'resource',
541 OPTIONAL: 'optional', // Android
542 REQUIRED: 'required', // Android
543 NONE: 'none', // Android
544};
545
546export const AlarmMethod = {
547 ALARM: 'alarm',
548 ALERT: 'alert',
549 EMAIL: 'email',
550 SMS: 'sms',
551 DEFAULT: 'default',
552};
553
554export const EventAccessLevel = {
555 CONFIDENTIAL: 'confidential',
556 PRIVATE: 'private',
557 PUBLIC: 'public',
558 DEFAULT: 'default',
559};
560
561export const CalendarAccessLevel = {
562 CONTRIBUTOR: 'contributor',
563 EDITOR: 'editor',
564 FREEBUSY: 'freebusy',
565 OVERRIDE: 'override',
566 OWNER: 'owner',
567 READ: 'read',
568 RESPOND: 'respond',
569 ROOT: 'root',
570 NONE: 'none',
571};
572
573export const ReminderStatus = {
574 COMPLETED: 'completed',
575 INCOMPLETE: 'incomplete',
576};