1 |
|
2 |
|
3 | import { NativeModules, Platform, processColor } from 'react-native';
|
4 |
|
5 | type RecurringEventOptions = {
|
6 | futureEvents?: boolean,
|
7 | instanceStartDate?: string,
|
8 | };
|
9 |
|
10 | type Calendar = {
|
11 | id?: string,
|
12 | title?: string,
|
13 | sourceId?: string,
|
14 | source?: Source,
|
15 | type?: string,
|
16 | color?: string,
|
17 | entityType?: string,
|
18 | allowsModifications?: boolean,
|
19 | allowedAvailabilities?: boolean,
|
20 | isPrimary?: boolean,
|
21 | name?: string,
|
22 | ownerAccount?: string,
|
23 | timeZone?: string,
|
24 | allowedReminders?: Array<string>,
|
25 | allowedAttendeeTypes?: Array<string>,
|
26 | isVisible?: boolean,
|
27 | isSynced?: boolean,
|
28 | accessLevel?: string,
|
29 | };
|
30 |
|
31 | type Source = {
|
32 | id?: string,
|
33 | type?: string,
|
34 | name?: string,
|
35 | isLocalAccount?: boolean,
|
36 | };
|
37 |
|
38 | type Event = {
|
39 | id?: string,
|
40 | calendarId?: string,
|
41 | title?: string,
|
42 | location?: string,
|
43 | creationDate?: string,
|
44 | lastModifiedDate?: string,
|
45 | timeZone?: string,
|
46 | endTimeZone?: string,
|
47 | url?: string,
|
48 | notes?: string,
|
49 | alarms?: Array<Alarm>,
|
50 | recurrenceRule?: RecurrenceRule,
|
51 | startDate?: string,
|
52 | endDate?: string,
|
53 | originalStartDate?: string,
|
54 | isDetached?: boolean,
|
55 | allDay?: boolean,
|
56 | availability?: string,
|
57 | status?: string,
|
58 | organizer?: string,
|
59 | organizerEmail?: string,
|
60 | accessLevel?: string,
|
61 | guestsCanModify?: boolean,
|
62 | guestsCanInviteOthers?: boolean,
|
63 | guestsCanSeeGuests?: boolean,
|
64 | originalId?: string,
|
65 | instanceId?: string,
|
66 | };
|
67 |
|
68 | type 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 |
|
86 | type Attendee = {
|
87 | id?: string,
|
88 | isCurrentUser?: boolean,
|
89 | name?: string,
|
90 | role?: string,
|
91 | status?: string,
|
92 | type?: string,
|
93 | url?: string,
|
94 | email?: string,
|
95 | };
|
96 |
|
97 | type Alarm = {
|
98 | absoluteDate?: string,
|
99 | relativeOffset?: string,
|
100 | structuredLocation?: {
|
101 |
|
102 | title?: string,
|
103 | proximity?: string,
|
104 | radius?: number,
|
105 | coords?: {
|
106 | latitude?: number,
|
107 | longitude?: number,
|
108 | },
|
109 | },
|
110 | method?: string,
|
111 | };
|
112 |
|
113 | type RecurrenceRule = {
|
114 | frequency: string,
|
115 | interval?: number,
|
116 | endDate?: string,
|
117 | occurrence?: number,
|
118 | };
|
119 |
|
120 | export 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 |
|
127 | export 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 |
|
136 | export 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 |
|
182 | export 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 |
|
191 | export 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 |
|
210 | export 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 |
|
224 | export 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 |
|
245 | export 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 |
|
273 | export 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 |
|
286 | export 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 |
|
296 | const params = Platform.OS === 'ios' ? { id, instanceStartDate } : id;
|
297 | return NativeModules.ExponentCalendar.getAttendeesForEventAsync(params);
|
298 | }
|
299 |
|
300 | export 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 | }
|
325 |
|
326 | export 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 | }
|
336 |
|
337 | export 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 | }
|
346 |
|
347 | export 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 | }
|
378 |
|
379 | export 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 | }
|
388 |
|
389 | export 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 | }
|
404 |
|
405 | export 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 | }
|
424 |
|
425 | export 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 | }
|
436 |
|
437 | export 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 | }
|
443 |
|
444 | export 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 | }
|
453 |
|
454 | export 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 | }
|
464 |
|
465 | export const EntityTypes = {
|
466 | EVENT: 'event',
|
467 | REMINDER: 'reminder',
|
468 | };
|
469 |
|
470 | export const Frequency = {
|
471 | DAILY: 'daily',
|
472 | WEEKLY: 'weekly',
|
473 | MONTHLY: 'monthly',
|
474 | YEARLY: 'yearly',
|
475 | };
|
476 |
|
477 | export const Availability = {
|
478 | NOT_SUPPORTED: 'notSupported',
|
479 | BUSY: 'busy',
|
480 | FREE: 'free',
|
481 | TENTATIVE: 'tentative',
|
482 | UNAVAILABLE: 'unavailable',
|
483 | };
|
484 |
|
485 | export const CalendarType = {
|
486 | LOCAL: 'local',
|
487 | CALDAV: 'caldav',
|
488 | EXCHANGE: 'exchange',
|
489 | SUBSCRIBED: 'subscribed',
|
490 | BIRTHDAYS: 'birthdays',
|
491 | };
|
492 |
|
493 | export const EventStatus = {
|
494 | NONE: 'none',
|
495 | CONFIRMED: 'confirmed',
|
496 | TENTATIVE: 'tentative',
|
497 | CANCELED: 'canceled',
|
498 | };
|
499 |
|
500 | export const SourceType = {
|
501 | LOCAL: 'local',
|
502 | EXCHANGE: 'exchange',
|
503 | CALDAV: 'caldav',
|
504 | MOBILEME: 'mobileme',
|
505 | SUBSCRIBED: 'subscribed',
|
506 | BIRTHDAYS: 'birthdays',
|
507 | };
|
508 |
|
509 | export const AttendeeRole = {
|
510 | UNKNOWN: 'unknown',
|
511 | REQUIRED: 'required',
|
512 | OPTIONAL: 'optional',
|
513 | CHAIR: 'chair',
|
514 | NON_PARTICIPANT: 'nonParticipant',
|
515 | ATTENDEE: 'attendee',
|
516 | ORGANIZER: 'organizer',
|
517 | PERFORMER: 'performer',
|
518 | SPEAKER: 'speaker',
|
519 | NONE: 'none',
|
520 | };
|
521 |
|
522 | export const AttendeeStatus = {
|
523 | UNKNOWN: 'unknown',
|
524 | PENDING: 'pending',
|
525 | ACCEPTED: 'accepted',
|
526 | DECLINED: 'declined',
|
527 | TENTATIVE: 'tentative',
|
528 | DELEGATED: 'delegated',
|
529 | COMPLETED: 'completed',
|
530 | IN_PROCESS: 'inProcess',
|
531 | INVITED: 'invited',
|
532 | NONE: 'none',
|
533 | };
|
534 |
|
535 | export const AttendeeType = {
|
536 | UNKNOWN: 'unknown',
|
537 | PERSON: 'person',
|
538 | ROOM: 'room',
|
539 | GROUP: 'group',
|
540 | RESOURCE: 'resource',
|
541 | OPTIONAL: 'optional',
|
542 | REQUIRED: 'required',
|
543 | NONE: 'none',
|
544 | };
|
545 |
|
546 | export const AlarmMethod = {
|
547 | ALARM: 'alarm',
|
548 | ALERT: 'alert',
|
549 | EMAIL: 'email',
|
550 | SMS: 'sms',
|
551 | DEFAULT: 'default',
|
552 | };
|
553 |
|
554 | export const EventAccessLevel = {
|
555 | CONFIDENTIAL: 'confidential',
|
556 | PRIVATE: 'private',
|
557 | PUBLIC: 'public',
|
558 | DEFAULT: 'default',
|
559 | };
|
560 |
|
561 | export 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 |
|
573 | export const ReminderStatus = {
|
574 | COMPLETED: 'completed',
|
575 | INCOMPLETE: 'incomplete',
|
576 | };
|