├── .gitignore ├── .prettierignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE.md ├── README.md ├── RNCalendarEvents.podspec ├── android ├── .npmignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── calendarevents │ ├── RNCalendarEvents.java │ └── RNCalendarEventsPackage.java ├── example ├── .buckconfig ├── .eslintrc.js ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .prettierrc.js ├── .watchmanconfig ├── App.js ├── Gemfile ├── Gemfile.lock ├── __tests__ │ └── App-test.js ├── android │ ├── app │ │ ├── _BUCK │ │ ├── build.gradle │ │ ├── build_defs.bzl │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── rncalendareventsexample │ │ │ │ └── ReactNativeFlipper.java │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── rncalendareventsexample │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── index.js ├── ios │ ├── Podfile │ ├── Podfile.lock │ ├── RNCalendarEventsExample-tvOS │ │ └── Info.plist │ ├── RNCalendarEventsExample-tvOSTests │ │ └── Info.plist │ ├── RNCalendarEventsExample.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── RNCalendarEventsExample-tvOS.xcscheme │ │ │ └── RNCalendarEventsExample.xcscheme │ ├── RNCalendarEventsExample.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── RNCalendarEventsExample │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ └── main.m │ └── RNCalendarEventsExampleTests │ │ ├── Info.plist │ │ └── RNCalendarEventsExampleTests.m ├── metro.config.js ├── package.json └── yarn.lock ├── ios ├── .npmignore ├── RNCalendarEvents.h ├── RNCalendarEvents.m └── RNCalendarEvents.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ ├── moox.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ ├── will.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── wmcmahan.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ ├── moox.xcuserdatad │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── will.xcuserdatad │ └── xcschemes │ │ ├── RNCalendarEvents.xcscheme │ │ └── xcschememanagement.plist │ └── wmcmahan.xcuserdatad │ └── xcschemes │ ├── RNCalendarEvents.xcscheme │ └── xcschememanagement.plist ├── package.json ├── src ├── index.android.js ├── index.d.ts └── index.ios.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .DS_Store 4 | android/build/* 5 | xcuserdata 6 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/android/app/build 2 | **/ios/Pods 3 | **/ios/**/*.xcassets 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog for `react-native-calendar-events` 2 | 3 | ## 2.2.0 - 2021-01-08 4 | 5 | - Fixed `findEventByID` on iOS - return null if event is not found (_for consistency with Android_) [#337](https://github.com/wmcmahan/react-native-calendar-events/pull/337) by [@dstop75](https://github.com/dstop75) 6 | 7 | - Fixed android calendar query to catch events that intersect date range but aren't entirely a subset (_for consistency with iOS_) [#333](https://github.com/wmcmahan/react-native-calendar-events/pull/333) by [@jenniferburch](https://github.com/jenniferburch) 8 | 9 | - Added ability to set timezone on events in iOS (necessary for recurrence expansion to work correctly across daylight savings time transitions) [#335](https://github.com/wmcmahan/react-native-calendar-events/pull/335) by [@LorienHW](https://github.com/LorienHW) and [@mcarlson](https://github.com/mcarlson) 10 | 11 | Also includes minor documentation tweaks. 12 | 13 | ## 2.1.2 - 2020-11-08 14 | 15 | - Fixed `exceptionDate` option being optional in TypeScript bindings [#329](https://github.com/wmcmahan/react-native-calendar-events/pull/329) by [@MoOx](https://github.com/MoOx) 16 | 17 | ## 2.1.1 - 2020-10-20 18 | 19 | - Fixed TypeScript declaration in `package.json` file [#328](https://github.com/wmcmahan/react-native-calendar-events/pull/328) by [@wmcmahan](https://github.com/wmcmahan) 20 | - Fixed Android import into the README manual linking section [#321](https://github.com/wmcmahan/react-native-calendar-events/pull/321) by [@chiformihai](https://github.com/chiformihai) 21 | 22 | ## 2.1.0 - 2020-08-11 23 | 24 | - Added ability to restrict to read-only permission on Android [#320](https://github.com/wmcmahan/react-native-calendar-events/pull/320) by [@mikehardy](https://github.com/mikehardy) 25 | - Added a _Troubleshooting_ section in README, to document the issue about saved event not being kept on device during sync [#317](https://github.com/wmcmahan/react-native-calendar-events/pull/317) by [@MoOx](https://github.com/MoOx) 26 | 27 | ## 2.0.1 - 2020-08-01 28 | 29 | - Fixed TypeScript definition for missing `requestPermissions` [#316](https://github.com/wmcmahan/react-native-calendar-events/pull/316) by [@wmcmahan](https://github.com/wmcmahan) 30 | 31 | ## 2.0.0 - 2020-08-01 32 | 33 | In addition to bugfixes, this release introduces some minor breaking changes: 34 | 35 | - Support for React Native 0.60+ only 36 | - AndroidX support! 37 | - Android & iOS package name have changed. If you rely on React Native autolinking, you don't have to change a thing, otherwise, please see README to update installation instruction. 38 | - Permissions method names have changed for more explicit `checkPermissions` & `requestPermissions`. 39 | - For iOS, we now avoid crashes at all cost, which means 40 | - if a native method fails, it should be recoverable from JavaScript (promise rejection) - we tried to cover most native code part in the bridge to be able to catch all kind of exception 41 | - An exception has been made for fetching event: if some part of the serialization fails, a NSLog is emitted & the specific problematic part is ommited (eg: an alarm or a structuredLocation could be missing) and the process continues on other events. 42 | We keep in mind the idea of adding an `error` field into calendar event so the information is explicitely available from JavaScript. 43 | This is to avoid receving a promise rejection if you fetch 2 months of events & have a single tiny information that we failed to serialize. In this cases, you will receive all fetched calendar events with just a tiny information missing, which offers a better UX. 44 | 45 | ### All platforms 46 | 47 | - Added `removeCalendar` method [#269](https://github.com/wmcmahan/react-native-calendar-events/pull/269) by [@hmcheu](https://github.com/hmcheu) 48 | 49 | ### Android 50 | 51 | - Package is now `com.calendarevents.RNCalendarEvents` [a39efe7](https://github.com/wmcmahan/react-native-calendar-events/commit/a39efe79c730c578abe8614986d63520005a8e59) by [@MoOx](https://github.com/MoOx) 52 | - Fixed `'boolean android.database.Cursor.moveToNext()' on a null object reference` error [e7c9680](https://github.com/wmcmahan/react-native-calendar-events/commit/e7c9680dd24a84229df234abf82277115d3f4f00) by [@MoOx](https://github.com/MoOx) 53 | - Fixed parsing allowed availability [#268](https://github.com/wmcmahan/react-native-calendar-events/pull/268) by [@saghul](https://github.com/saghul) 54 | - Added AndroidX support for react-native 0.60 [#263](https://github.com/wmcmahan/react-native-calendar-events/pull/263) by [@yfuks](https://github.com/yfuks) 55 | - Added: use PermissionListener to avoid Android manual steps [#252](https://github.com/wmcmahan/react-native-calendar-events/pull/252) by [@saghul](https://github.com/saghul) 56 | - Added "NEVER ASK ME AGAIN" status added in Android [#273](https://github.com/wmcmahan/react-native-calendar-events/pull/273) by [@webtaculars](https://github.com/webtaculars) 57 | - Added key to skip setting timezone on Android [#271](https://github.com/wmcmahan/react-native-calendar-events/pull/271) by [@eleddie](https://github.com/eleddie) 58 | 59 | ### iOS 60 | 61 | - Package is now `RNCalendarEvents` [5ea007c](https://github.com/wmcmahan/react-native-calendar-events/commit/5ea007c0cbb147f37b7c1b748e6acae0a9485b88) by [@MoOx](https://github.com/MoOx) 62 | - Fixed crashes related to structured location [#253](https://github.com/wmcmahan/react-native-calendar-events/pull/253) by [@eladgel](https://github.com/eladgel) & [4560a2f](https://github.com/wmcmahan/react-native-calendar-events/commit/4560a2ff883e1a8bad97ec16f3325d52ccccdff5) by [@MoOx](https://github.com/MoOx) 63 | - Fixed iOS 13 show bug [#279](https://github.com/wmcmahan/react-native-calendar-events/pull/279) by [@huang303513](https://github.com/huang303513) 64 | - Minimal version to iOS 9.0, like react-native 0.60 [5ea007c](https://github.com/wmcmahan/react-native-calendar-events/commit/5ea007c0cbb147f37b7c1b748e6acae0a9485b88) by [@MoOx](https://github.com/MoOx) 65 | - Avoid iOS crashes at all cost [314](https://github.com/wmcmahan/react-native-calendar-events/pull/314) by [@MoOx](https://github.com/MoOx) 66 | 67 | ### Docs 68 | 69 | - Various minor README update [92c3238](https://github.com/wmcmahan/react-native-calendar-events/commit/92c3238eead14eb9a7d36398c3b9d17df0c9e270) by [@MoOx](https://github.com/MoOx) 70 | - Updated docs with correct type for string dates [#250](https://github.com/wmcmahan/react-native-calendar-events/pull/250) by [@hugofelp](https://github.com/eladgel) 71 | 72 | ## Pre 2.0.0 73 | 74 | For 1.7.x & before, please refer to 75 | [git history](https://github.com/wmcmahan/react-native-calendar-events/commits/master). 76 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | - Using welcoming and inclusive language 12 | - Being respectful of differing viewpoints and experiences 13 | - Gracefully accepting constructive criticism 14 | - Focusing on what is best for the community 15 | - Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | - The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | - Trolling, insulting/derogatory comments, and personal or political attacks 21 | - Public or private harassment 22 | - Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | - Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at mcmahanwill@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for contributing! When contributing to this project, please first discuss the change you wish to make via issue or any other method with the owners of this repository before making a change. 4 | 5 | Please note we have a code of conduct; follow it in all your interactions with the project. 6 | 7 | ## Pull Request Process 8 | 9 | 1. Describe in detail the issue or feature and link to the issue that the pull request aims to resolve. 10 | 2. If the pull request is a new feature, please ensure that there is parity between iOS and Android. If not, please describe the reason. 11 | 3. Ensure that there are no compiler errors and that the changes are well vetted in the run-time environment for iOS and Android. 12 | 4. Remove any code that has been commented-out or used for debugging. 13 | 5. Update the README.md with details of changes to the api or install. 14 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### Environment 4 | 5 | 6 | 7 | ### Steps to Reproduce 8 | 9 | 10 | 11 | ### Expected Behavior 12 | 13 | 14 | 15 | ### Actual Behavior 16 | 17 | 18 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Will McMahan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native Calendar Events 2 | 3 | [![npm](https://img.shields.io/npm/v/react-native-calendar-events.svg?style=flat-square)](https://www.npmjs.com/package/react-native-calendar-events) 4 | [![npm](https://img.shields.io/npm/dm/react-native-calendar-events.svg?style=flat-square)](https://www.npmjs.com/package/react-native-calendar-events) 5 | [![npm](https://img.shields.io/npm/l/react-native-calendar-events.svg?style=flat-square)](https://github.com/wmcmahan/react-native-calendar-events/blob/master/LICENSE.md) 6 | 7 | A React Native module to help access and save events to iOS and Android calendars. 8 | 9 | ## Getting started 10 | 11 | This package assumes that you already have a React Native project or are familiar with React Native. If not, checkout the official documentation for more details about getting started with [React Native](https://facebook.github.io/react-native/docs/getting-started.html). 12 | 13 | ### Support 14 | 15 | | version | react-native version | 16 | | ---------- | -------------------- | 17 | | 2.0.0+ | 0.60.0+ | 18 | | pre 2.0.0+ | 0.40.0+ | 19 | 20 | For 0.59-, you should use [`jetify -r`](https://github.com/mikehardy/jetifier/blob/master/README.md#to-reverse-jetify--convert-node_modules-dependencies-to-support-libraries) 21 | 22 | ## Installation 23 | 24 | ```bash 25 | $ npm install --save react-native-calendar-events 26 | # --- or --- 27 | $ yarn add react-native-calendar-events 28 | ``` 29 | 30 | Don't forget going into the `ios` directory to execute a `pod install`. 31 | 32 | ## 🆘 Manual linking 33 | 34 | Because this package targets React Native 0.60.0+, you will probably don't need to link it manually. Otherwise if it's not the case, follow this additional instructions: 35 | 36 |
37 | 👀 See manual linking instructions 38 | 39 | ### iOS 40 | 41 | Add this line to your `ios/Podfile` file, then run `pod install`. 42 | 43 | ```bash 44 | target 'YourAwesomeProject' do 45 | # … 46 | pod 'RNCalendarEvents', :path => '../node_modules/react-native-calendar-events' 47 | end 48 | ``` 49 | 50 | ### Android 51 | 52 | 1 - Add the following lines to `android/settings.gradle`: 53 | 54 | ```gradle 55 | include ':react-native-calendar-events' 56 | project(':react-native-calendar-events').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-calendar-events/android') 57 | ``` 58 | 59 | 2 - Add the implementation line to the dependencies in `android/app/build.gradle`: 60 | 61 | ```gradle 62 | dependencies { 63 | // ... 64 | implementation project(':react-native-calendar-events') 65 | } 66 | ``` 67 | 68 | 3 - Add the import and link the package in `MainApplication.java`: 69 | 70 | ```java 71 | import com.calendarevents.RNCalendarEventsPackage; // <- add the RNCalendarEventsPackage import 72 | 73 | public class MainApplication extends Application implements ReactApplication { 74 | 75 | // … 76 | 77 | @Override 78 | protected List getPackages() { 79 | @SuppressWarnings("UnnecessaryLocalVariable") 80 | List packages = new PackageList(this).getPackages(); 81 | // … 82 | packages.add(new RNCalendarEventsPackage()); 83 | return packages; 84 | } 85 | 86 | // … 87 | } 88 | ``` 89 | 90 |
91 | 92 | ### iOS specific instructions 93 | 94 | Add `RNCalendarEvents`, as well as `EventKit.framework` to project libraries if not already done. 95 | 96 | Setting up privacy usage descriptions may also be required depending on which iOS version is supported. This involves updating the Property List, `Info.plist`, with the corresponding key for the EKEventStore api. [Info.plist reference](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html). 97 | 98 | For updating the `Info.plist` key/value via XCode, add a `Privacy - Calendars Usage Description` key with a usage description as the value. Resulting change to `Info.plist` should look something like: 99 | 100 | ```xml 101 | NSCalendarsUsageDescription 102 | This app requires access to the calendar 103 | ``` 104 | 105 | ## API 106 | 107 | The following API allows for interacting with both iOS and Android device calendars. See the full list of available [event fields](#event-fields). 108 | 109 | ```javascript 110 | import RNCalendarEvents from "react-native-calendar-events"; 111 | ``` 112 | 113 | ### `checkPermissions` 114 | 115 | Get calendar authorization status. 116 | You may check for the default read/write access with no argument, or read-only access on Android by passing boolean true. iOS is always read/write. 117 | 118 | ```javascript 119 | RNCalendarEvents.checkPermissions((readOnly = false)); 120 | ``` 121 | 122 | Returns: **Promise** 123 | 124 | - fulfilled: String - `denied`, `restricted`, `authorized` or `undetermined` 125 | - rejected: Error 126 | 127 | ### `requestPermissions` 128 | 129 | Request calendar authorization. Authorization must be granted before accessing calendar events. 130 | 131 | ```javascript 132 | RNCalendarEvents.requestPermissions((readOnly = false)); 133 | ``` 134 | 135 | (readOnly is for Android only, see below) 136 | 137 | > Android note: this is necessary for targeted SDK of >=23. 138 | > iOS note: This method will crash, if you didn't update `Info.plist`. Follow carefully installation instruction. 139 | 140 | Returns: **Promise** 141 | 142 | - fulfilled: String - `denied`, `restricted`, `authorized` or `undetermined` 143 | - rejected: Error 144 | 145 | ### Read-Only `requestPermissions` (_Android only_) 146 | 147 | ⚠️ Note that to restrict to read-only usage on Android (iOS is always read/write) you will need to alter the included Android permissions 148 | as the `AndroidManifest.xml` is merged during the Android build. 149 | 150 | You do that by altering your AndroidManifest.xml to "remove" the WRITE_CALENDAR permission with an entry like so: 151 | 152 | ```xml 153 | 156 | 157 | 158 | ``` 159 | 160 | ### `findCalendars` 161 | 162 | Finds all the calendars on the device. 163 | 164 | ```javascript 165 | RNCalendarEvents.findCalendars(); 166 | ``` 167 | 168 | Returns: **Promise** 169 | 170 | - fulfilled: Array - A list of known calendars on the device 171 | - rejected: Error 172 | 173 | ### `saveCalendar` 174 | 175 | Create a calendar. 176 | 177 | ```javascript 178 | RNCalendarEvents.saveCalendar(calendar); 179 | ``` 180 | 181 | ⚠️ When you want to save a calendar, you need to use a valid source (find using [`findCalendars`](#findcalendars)). 182 | 183 | Arguments: 184 | 185 | - [calendar](#Calendar-options): Object - Calendar to create. 186 | 187 | Returns: **Promise** 188 | 189 | - fulfilled: The id of the created calendar 190 | - rejected: Error 191 | 192 | ### `removeCalendar` 193 | 194 | Removes a calendar. 195 | 196 | ```javascript 197 | RNCalendarEvents.removeCalendar(id); 198 | ``` 199 | 200 | Arguments: 201 | 202 | - id: String - The id of the calendar to remove. 203 | 204 | Returns: **Promise** 205 | 206 | - fulfilled: Bool - Successful 207 | - rejected: Error 208 | 209 | ### `findEventById` 210 | 211 | Find calendar event by id. 212 | Returns a promise with fulfilled found events. 213 | 214 | ```javascript 215 | RNCalendarEvents.findEventById(id); 216 | ``` 217 | 218 | Arguments: 219 | 220 | - id: String - The events unique id. 221 | 222 | Returns: **Promise** 223 | 224 | - fulfilled: Object | null - Found event with unique id. 225 | - rejected: Error 226 | 227 | ### `fetchAllEvents` 228 | 229 | Fetch all calendar events. 230 | Returns a promise with fulfilled found events. 231 | 232 | ```javascript 233 | RNCalendarEvents.fetchAllEvents(startDate, endDate, calendars); 234 | ``` 235 | 236 | Arguments: 237 | 238 | - startDate: String - The start date of the range of events fetched. 239 | - endDate: String - The end date of the range of events fetched. 240 | - calendars: Array - List of calendar id strings to specify calendar events. Defaults to all calendars if empty. 241 | 242 | Returns: **Promise** 243 | 244 | - fulfilled: Array - Matched events within the specified date range. 245 | - rejected: Error 246 | 247 | ### `saveEvent` 248 | 249 | Creates or updates a calendar event. - [wiki guide](https://github.com/wmcmahan/react-native-calendar-events/wiki/Creating-basic-event) 250 | 251 | ```javascript 252 | RNCalendarEvents.saveEvent(title, details, options); 253 | ``` 254 | 255 | Arguments: 256 | 257 | - title: String - The title of the event. 258 | - [details](#event-fields): Object - The event's details. 259 | - [options](#options): Object - Options specific to the saved event. Note that on Android, `saveEvent` accepts an additional option `sync` (boolean) to prevent syncing issues. 260 | 261 | Returns: **Promise** 262 | 263 | - fulfilled: String - Created event's ID. 264 | - rejected: Error 265 | 266 | To update an event, the event `id` must be defined. - [wiki guide](https://github.com/wmcmahan/react-native-calendar-events/wiki/Updating-events) 267 | 268 | ```javascript 269 | RNCalendarEvents.saveEvent(title, { 270 | id: "FE6B128F-C0D8-4FB8-8FC6-D1D6BA015CDE", 271 | }); 272 | ``` 273 | 274 | #### Example for saveEvent 275 | 276 | Creating events is fairly straightforward. Hopefully the following explanation can help. 277 | 278 | ##### Basic `saveEvent` 279 | For both iOS and Android the pattern is simple; the event needs a `title` as well as a `startDate` and `endDate`. The `endDate` should also be a date later than the `startDate`. 280 | 281 | ```javascript 282 | RNCalendarEvents.saveEvent('Title of event', { 283 | startDate: '2016-08-19T19:26:00.000Z', 284 | endDate: '2017-08-19T19:26:00.000Z' 285 | }) 286 | ``` 287 | 288 | ##### Specify a calendar `saveEvent` 289 | 290 | The example above will simply save the event to your devices default calendar. If you wish to control which calendar the event is saved to, you must provide the `calendarId`. This will ensure your event is saved to an expected calendar. 291 | 292 | ```javascript 293 | RNCalendarEvents.saveEvent('Title of event', { 294 | calendarId: '141', 295 | startDate: '2016-08-19T19:26:00.000Z', 296 | endDate: '2017-08-19T19:26:00.000Z' 297 | }) 298 | ``` 299 | 300 | ##### Additional fields with `saveEvent` 301 | 302 | There are also other writable fields available. For example, you may wish to specify the location of the event or add additional notes for the event. Complete list of fields can be found [in the wiki](https://github.com/wmcmahan/react-native-calendar-events/wiki/Event-Fields#event-details). 303 | 304 | ```javascript 305 | RNCalendarEvents.saveEvent('Title of event', { 306 | calendarId: '141', 307 | startDate: '2016-08-19T19:26:00.000Z', 308 | endDate: '2017-08-19T19:26:00.000Z', 309 | location: 'Los Angeles, CA', 310 | notes: 'Bring sunglasses' 311 | }) 312 | ``` 313 | 314 | ### `removeEvent` 315 | 316 | Removes calendar event. 317 | 318 | ```javascript 319 | RNCalendarEvents.removeEvent(id, options); 320 | ``` 321 | 322 | Arguments: 323 | 324 | - id: String - The id of the event to remove. 325 | - [options](#options): Object - Options specific to event removal. 326 | 327 | Returns: **Promise** 328 | 329 | - fulfilled: Bool - Successful 330 | - rejected: Error 331 | 332 | ## Event fields 333 | 334 | | Property | Type | Description | iOS | Android | 335 | | :--------------------------------------------------- | :----- | :---------------------------------------------------------------------------------------------------- | :-: | :-----: | 336 | | **id\*** | String | Unique id for the calendar event. | ✓ | ✓ | 337 | | **calendarId\*\*** | String | Unique id for the calendar where the event will be saved. Defaults to the device's default calendar. | ✓ | ✓ | 338 | | **title** | String | The title for the calendar event. | ✓ | ✓ | 339 | | **startDate** | String | The start date of the calendar event in ISO format. | ✓ | ✓ | 340 | | **endDate** | String | The end date of the calendar event in ISO format. | ✓ | ✓ | 341 | | **allDay** | Bool | Indicates whether the event is an all-day | 342 | | event. | ✓ | ✓ | 343 | | **recurrence** | String | The simple recurrence frequency of the calendar event `daily`, `weekly`, `monthly`, `yearly` or none. | ✓ | ✓ | 344 | | [**recurrenceRule**](#recurrence-rule) \*\* | Object | The events recurrence settings. | ✓ | ✓ | 345 | | **occurrenceDate\*** | String | The original occurrence date of an event if it is part of a recurring series. | ✓ | | 346 | | **isDetached** | Bool | Indicates whether an event is a detached instance of a repeating event. | ✓ | | 347 | | **url** | String | The url associated with the calendar event. | ✓ | | 348 | | **location** | String | The location associated with the calendar event. | ✓ | ✓ | 349 | | [**structuredLocation**](#alarm-structuredlocation) | String | The structuredLocation associated with the calendar event. | ✓ | | 350 | | **notes** | String | The notes associated with the calendar event. | ✓ | | 351 | | **description** | String | The description associated with the calendar event. | | ✓ | 352 | | [**alarms**](#alarms) | Array | The alarms associated with the calendar event, as an array of alarm objects. | ✓ | ✓ | 353 | | [**attendees**](#attendees)\* | Array | The attendees of the event, including the organizer. | ✓ | ✓ | 354 | | [**calendar**](#calendar)\* | Object | The calendar containing the event. | ✓ | ✓ | 355 | | **skipAndroidTimezone** | Bool | Skip the process of setting automatic timezone on android | | ✓ | 356 | | **timeZone** | String | The time zone associated with the event | ✓ | | 357 | 358 | ### Calendar 359 | 360 | | Property | Type | Description | iOS | Android | 361 | | :-------------------------- | :----- | :------------------------------------------------------------------------- | :-: | :-----: | 362 | | **id** | String | Unique calendar ID. | ✓ | ✓ | 363 | | **title** | String | The calendar’s title. | ✓ | ✓ | 364 | | **type** | String | The calendar’s type. | ✓ | ✓ | 365 | | **source** | String | The source object representing the account to which this calendar belongs. | ✓ | ✓ | 366 | | **isPrimary\*** | Bool | Indicates if the calendar is assigned as primary. | ✓ | ✓ | 367 | | **allowsModifications\*** | Bool | Indicates if the calendar allows events to be written, edited or removed. | ✓ | ✓ | 368 | | **color\*** | String | The color assigned to the calendar represented as a hex value. | ✓ | ✓ | 369 | | **allowedAvailabilities\*** | Array | The event availability settings supported by the calendar. | ✓ | ✓ | 370 | 371 | ### Attendees 372 | 373 | | Property | Type | Description | iOS | Android | 374 | | :---------- | :----- | :--------------------------------- | :-: | :-----: | 375 | | **name** | String | The name of the attendee. | ✓ | ✓ | 376 | | **email\*** | String | The email address of the attendee. | ✓ | ✓ | 377 | | **phone\*** | String | The phone number of the attendee. | ✓ | | 378 | 379 | ### Recurrence rule 380 | 381 | | Property | Type | Description | iOS | Android | 382 | | :------------- | :----- | :------------------------------------------------------------------------------------ | :-: | :-----: | 383 | | **frequency** | String | Event recurring frequency. Allowed values are `daily`, `weekly`, `monthly`, `yearly`. | ✓ | ✓ | 384 | | **endDate** | String | Event recurring end date. This overrides occurrence. | ✓ | ✓ | 385 | | **occurrence** | Number | Number of event occurrences. | ✓ | ✓ | 386 | | **interval** | Number | The interval between events of this recurrence. | ✓ | ✓ | 387 | 388 | ### Alarms 389 | 390 | | Property | Type | Description | iOS | Android | 391 | | :-------------------------------------------------- | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-: | :-----: | 392 | | **date** | String or Number | If a String is given, an alarm will be set with an absolute date. If a Number is given, an alarm will be set with a relative offset (in minutes) from the start date. | ✓ | ✓ | 393 | | [**structuredLocation**](#alarm-structuredlocation) | Object | The location to trigger an alarm. | ✓ | | 394 | 395 | ### Alarm structuredLocation 396 | 397 | | Property | Type | Description | iOS | Android | 398 | | :------------ | :----- | :----------------------------------------------------------------------------------------------------- | :-: | :-----: | 399 | | **title** | String | The title of the location. | ✓ | | 400 | | **proximity** | String | A value indicating how a location-based alarm is triggered. Possible values: `enter`, `leave`, `none`. | ✓ | | 401 | | **radius** | Number | A minimum distance from the core location that would trigger the calendar event's alarm. | ✓ | | 402 | | **coords** | Object | The geolocation coordinates, as an object with latitude and longitude properties | ✓ | | 403 | 404 | ### Options 405 | 406 | | Property | Type | Description | iOS | Android | 407 | | :---------------- | :----- | :------------------------------------------------------------------------------------------------------------- | :-: | :-----: | 408 | | **exceptionDate** | String | The start date of a recurring event's exception instance. Used for updating single event in a recurring series | ✓ | ✓ | 409 | | **futureEvents** | Bool | If `true` the update will span all future events. If `false` it only update the single instance. | ✓ | | 410 | 411 | ### Calendar options 412 | 413 | | Property | Type | Description | iOS | Android | 414 | | :------------------------ | :----- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-: | :-----: | 415 | | **title** | String | The calendar title (required) | ✓ | ✓ | 416 | | **color** | String | The calendar color (required) | ✓ | ✓ | 417 | | **entityType** | String | 'event' or 'reminder' (required) | ✓ | | 418 | | **name** | String | The calendar name (required) | | ✓ | 419 | | **accessLevel** | String | Defines how the event shows up for others when the calendar is shared [doc](https://developer.android.com/reference/android/provider/CalendarContract.EventsColumns.html#ACCESS_LEVEL)(required) `'contributor', 'editor', 'freebusy', 'override', 'owner', 'read', 'respond', 'root'` | | ✓ | 420 | | **ownerAccount** | String | The owner account for this calendar, based on the calendar feed [doc](https://developer.android.com/reference/android/provider/CalendarContract.CalendarColumns#OWNER_ACCOUNT)(required) | | ✓ | 421 | | **source** | Object | The calendar Account source (required) | | ✓ | 422 | | **source.name** | String | The Account name (required) | | ✓ | 423 | | **source.type** | String | The Account type | | ✓ | 424 | | **source.isLocalAccount** | Bool | The source (required if **source.type** is not used) | | ✓ | 425 | 426 | \* _Read only_, \*\* \_Write only 427 | 428 | ## Troubleshooting 429 | 430 | These are some common issues you may run into while using `react-native-calendar-events` library. 431 | If you encounter something that is not listed here, try [searching in GitHub issues of `react-native-calendar-events`](https://github.com/wmcmahan/react-native-calendar-events/issues). 432 | 433 | ### After saving an event, it disappear form the calendar 434 | 435 | This might be related to a sync issue. 436 | You need to be sure that the event you saved is matching what your device will keep in sync. 437 | 438 | For iOS, you might have not all event synced. You might need to update this iOS settings in _Settings_ > _Calendar_ > _Sync_ > **All Events**. If that's not enough, it might be worth checking [iOS iCloud sync documentation](https://support.apple.com/en-us/HT203521). 439 | For Android, you can have a look to [Google Calendar sync problems documentation](https://support.google.com/calendar/answer/6261951). 440 | 441 | ### Duplicated events after editing and saving an event 442 | 443 | Another symptom of syncing issue. See the issue above. 444 | Note that on Android, `saveEvent` accepts an additional option `sync` (boolean) to prevent syncing issues. 445 | 446 | ## Wiki 447 | 448 | - [Create basic event](https://github.com/wmcmahan/react-native-calendar-events/wiki/Creating-basic-event) 449 | - [Create recurring event](https://github.com/wmcmahan/react-native-calendar-events/wiki/Create-recurring-event) 450 | - [Updating events](https://github.com/wmcmahan/react-native-calendar-events/wiki/Updating-events) 451 | - [Adding alarms](https://github.com/wmcmahan/react-native-calendar-events/wiki/Event-alarms) 452 | 453 | ## Authors 454 | 455 | - **Will McMahan** - Initial code - [github.com/wmcmahan](https://github.com/wmcmahan) 456 | 457 | See also the list of [contributors](https://github.com/wmcmahan/react-native-calendar-events/contributors) who participated in this project. 458 | 459 | ## License 460 | 461 | This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/wmcmahan/react-native-calendar-events/blob/master/LICENSE.md) file for details 462 | 463 | ## Acknowledgments 464 | 465 | Big thanks to all who have contributed, raised an issue or simply find use in this project. Cheers! 466 | -------------------------------------------------------------------------------- /RNCalendarEvents.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | package = JSON.parse(File.read('./package.json')) 3 | 4 | Pod::Spec.new do |s| 5 | s.name = 'RNCalendarEvents' 6 | s.dependency 'React-Core' 7 | 8 | s.version = package["version"] 9 | s.license = package["license"] 10 | s.summary = package["description"] 11 | s.authors = package["author"] 12 | s.homepage = package["homepage"] 13 | 14 | s.platform = :ios, '9.0' 15 | 16 | s.source = { :git => package["repository"]["url"], :tag => s.version } 17 | s.source_files = 'ios/*.{h,m}' 18 | 19 | end 20 | -------------------------------------------------------------------------------- /android/.npmignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .DS_Store 3 | .gradle/ 4 | .idea/ 5 | .npmignore 6 | build/ 7 | gradle/ 8 | gradlew 9 | gradlew.bat 10 | local.properties 11 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | def safeExtGet(prop, fallback) { 4 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 5 | } 6 | 7 | android { 8 | compileSdkVersion safeExtGet('compileSdkVersion', 28) 9 | buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3') 10 | 11 | defaultConfig { 12 | minSdkVersion safeExtGet('minSdkVersion', 16) 13 | targetSdkVersion safeExtGet('targetSdkVersion', 28) 14 | versionCode 1 15 | versionName "1.0" 16 | } 17 | 18 | lintOptions { 19 | warning 'InvalidPackage' 20 | } 21 | } 22 | 23 | dependencies { 24 | api 'com.facebook.react:react-native:+' 25 | } 26 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/src/main/java/com/calendarevents/RNCalendarEventsPackage.java: -------------------------------------------------------------------------------- 1 | package com.calendarevents; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.NativeModule; 5 | import com.facebook.react.bridge.ReactApplicationContext; 6 | import com.facebook.react.uimanager.ViewManager; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | public class RNCalendarEventsPackage implements ReactPackage { 13 | 14 | @Override 15 | public List createViewManagers(ReactApplicationContext reactContext) { 16 | return Collections.emptyList(); 17 | } 18 | 19 | @Override 20 | public List createNativeModules( 21 | ReactApplicationContext reactContext) { 22 | List modules = new ArrayList<>(); 23 | 24 | modules.add(new RNCalendarEvents(reactContext)); 25 | 26 | return modules; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /example/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /example/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | }; 5 | -------------------------------------------------------------------------------- /example/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore polyfills 9 | node_modules/react-native/Libraries/polyfills/.* 10 | 11 | ; These should not be required directly 12 | ; require from fbjs/lib instead: require('fbjs/lib/warning') 13 | node_modules/warning/.* 14 | 15 | ; Flow doesn't support platforms 16 | .*/Libraries/Utilities/LoadingView.js 17 | 18 | [untyped] 19 | .*/node_modules/@react-native-community/cli/.*/.* 20 | 21 | [include] 22 | 23 | [libs] 24 | node_modules/react-native/interface.js 25 | node_modules/react-native/flow/ 26 | 27 | [options] 28 | emoji=true 29 | 30 | esproposal.optional_chaining=enable 31 | esproposal.nullish_coalescing=enable 32 | 33 | module.file_ext=.js 34 | module.file_ext=.json 35 | module.file_ext=.ios.js 36 | 37 | munge_underscores=true 38 | 39 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 40 | module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' 41 | 42 | suppress_type=$FlowIssue 43 | suppress_type=$FlowFixMe 44 | suppress_type=$FlowFixMeProps 45 | suppress_type=$FlowFixMeState 46 | 47 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) 48 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ 49 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 50 | 51 | [lints] 52 | sketchy-null-number=warn 53 | sketchy-null-mixed=warn 54 | sketchy-number=warn 55 | untyped-type-import=warn 56 | nonstrict-import=warn 57 | deprecated-type=warn 58 | unsafe-getters-setters=warn 59 | unnecessary-invariant=warn 60 | signature-verification-failure=warn 61 | deprecated-utility=error 62 | 63 | [strict] 64 | deprecated-type 65 | nonstrict-import 66 | sketchy-null 67 | unclear-type 68 | unsafe-getters-setters 69 | untyped-import 70 | untyped-type-import 71 | 72 | [version] 73 | ^0.122.0 74 | -------------------------------------------------------------------------------- /example/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | 38 | # BUCK 39 | buck-out/ 40 | \.buckd/ 41 | *.keystore 42 | !debug.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://docs.fastlane.tools/best-practices/source-control/ 50 | 51 | */fastlane/report.xml 52 | */fastlane/Preview.html 53 | */fastlane/screenshots 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # CocoaPods 59 | /ios/Pods/ 60 | -------------------------------------------------------------------------------- /example/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | }; 7 | -------------------------------------------------------------------------------- /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /example/App.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | * @flow strict-local 4 | */ 5 | 6 | import React from 'react'; 7 | import { 8 | SafeAreaView, 9 | StyleSheet, 10 | ScrollView, 11 | View, 12 | Text, 13 | StatusBar, 14 | Button, 15 | Alert, 16 | Platform, 17 | } from 'react-native'; 18 | import {Header, Colors} from 'react-native/Libraries/NewAppScreen'; 19 | import RNCalendarEvents from 'react-native-calendar-events'; 20 | 21 | const App: () => React$Node = () => { 22 | return ( 23 | <> 24 | 25 | 26 | 29 |
30 | {global.HermesInternal == null ? null : ( 31 | 32 | Engine: Hermes 33 | 34 | )} 35 | 36 | 37 | Read/Write Auth 38 | 39 |