Quellcode durchsuchen

Merge branch 'master' of git://github.com/yonahforst/react-native-permissions into motion-permission-request

Peter Lau vor 7 Jahren
Ursprung
Commit
ad1c633a6e
95 geänderte Dateien mit 1719 neuen und 805 gelöschten Zeilen
  1. 9
    0
      .flowconfig
  2. 74
    0
      .github/CODE_OF_CONDUCT.md
  3. 26
    0
      .github/ISSUE_TEMPLATE.md
  4. 15
    10
      .gitignore
  5. 1
    1
      .npmignore
  6. 3
    0
      .prettierignore
  7. 5
    0
      .prettierrc
  8. 0
    46
      CODE_OF_CONDUCT.md
  9. 0
    12
      Example/__tests__/index.android.js
  10. 0
    12
      Example/__tests__/index.ios.js
  11. 0
    14
      Example/index.android.js
  12. 0
    14
      Example/index.ios.js
  13. 0
    38
      Example/ios/Example/Images.xcassets/AppIcon.appiconset/Contents.json
  14. 0
    23
      Example/package.json
  15. 239
    167
      README.md
  16. 14
    15
      ReactNativePermissions.podspec
  17. 0
    7
      ReactNativePermissions.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  18. 0
    80
      ReactNativePermissions.xcodeproj/xcuserdata/Yonah.xcuserdatad/xcschemes/ReactNativePermissions.xcscheme
  19. 0
    22
      ReactNativePermissions.xcodeproj/xcuserdata/Yonah.xcuserdatad/xcschemes/xcschememanagement.plist
  20. 0
    0
      example/.babelrc
  21. 0
    0
      example/.buckconfig
  22. 9
    6
      example/.flowconfig
  23. 0
    0
      example/.gitattributes
  24. 4
    4
      example/.gitignore
  25. 0
    0
      example/.watchmanconfig
  26. 51
    52
      example/App.js
  27. 10
    0
      example/__tests__/index.js
  28. 0
    0
      example/android/app/BUCK
  29. 5
    1
      example/android/app/build.gradle
  30. 0
    0
      example/android/app/proguard-rules.pro
  31. 6
    1
      example/android/app/src/main/AndroidManifest.xml
  32. 0
    0
      example/android/app/src/main/java/com/example/MainActivity.java
  33. 5
    0
      example/android/app/src/main/java/com/example/MainApplication.java
  34. 0
    0
      example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
  35. 0
    0
      example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
  36. 0
    0
      example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
  37. 0
    0
      example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  38. 0
    1
      example/android/app/src/main/res/values/strings.xml
  39. 0
    0
      example/android/app/src/main/res/values/styles.xml
  40. 1
    0
      example/android/build.gradle
  41. 0
    0
      example/android/gradle.properties
  42. 0
    0
      example/android/gradle/wrapper/gradle-wrapper.jar
  43. 1
    2
      example/android/gradle/wrapper/gradle-wrapper.properties
  44. 0
    0
      example/android/gradlew
  45. 0
    0
      example/android/gradlew.bat
  46. 0
    0
      example/android/keystores/BUCK
  47. 0
    0
      example/android/keystores/debug.keystore.properties
  48. 0
    0
      example/android/settings.gradle
  49. 4
    0
      example/app.json
  50. 4
    0
      example/index.js
  51. 0
    0
      example/ios/Example-tvOS/Info.plist
  52. 0
    0
      example/ios/Example-tvOSTests/Info.plist
  53. 217
    34
      example/ios/Example.xcodeproj/project.pbxproj
  54. 0
    0
      example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example-tvOS.xcscheme
  55. 1
    1
      example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme
  56. 0
    0
      example/ios/Example/AppDelegate.h
  57. 1
    1
      example/ios/Example/AppDelegate.m
  58. 0
    0
      example/ios/Example/Base.lproj/LaunchScreen.xib
  59. 38
    0
      example/ios/Example/Images.xcassets/AppIcon.appiconset/Contents.json
  60. 6
    0
      example/ios/Example/Images.xcassets/Contents.json
  61. 5
    1
      example/ios/Example/Info.plist
  62. 0
    0
      example/ios/Example/main.m
  63. 0
    0
      example/ios/ExampleTests/ExampleTests.m
  64. 0
    0
      example/ios/ExampleTests/Info.plist
  65. 23
    0
      example/package.json
  66. 0
    91
      index.android.js
  67. 0
    70
      index.ios.js
  68. 4
    0
      index.js
  69. 0
    0
      ios/Permissions/RNPAudioVideo.h
  70. 0
    0
      ios/Permissions/RNPAudioVideo.m
  71. 0
    0
      ios/Permissions/RNPBackgroundRefresh.h
  72. 0
    0
      ios/Permissions/RNPBackgroundRefresh.m
  73. 0
    0
      ios/Permissions/RNPBluetooth.h
  74. 0
    0
      ios/Permissions/RNPBluetooth.m
  75. 0
    0
      ios/Permissions/RNPContacts.h
  76. 0
    0
      ios/Permissions/RNPContacts.m
  77. 0
    0
      ios/Permissions/RNPEvent.h
  78. 0
    0
      ios/Permissions/RNPEvent.m
  79. 0
    0
      ios/Permissions/RNPLocation.h
  80. 0
    0
      ios/Permissions/RNPLocation.m
  81. 0
    0
      ios/Permissions/RNPNotification.h
  82. 0
    0
      ios/Permissions/RNPNotification.m
  83. 0
    0
      ios/Permissions/RNPPhoto.h
  84. 0
    0
      ios/Permissions/RNPPhoto.m
  85. 0
    0
      ios/Permissions/RNPSpeechRecognition.h
  86. 0
    0
      ios/Permissions/RNPSpeechRecognition.m
  87. 0
    0
      ios/RCTConvert+RNPStatus.h
  88. 0
    1
      ios/RCTConvert+RNPStatus.m
  89. 0
    1
      ios/ReactNativePermissions.h
  90. 5
    1
      ios/ReactNativePermissions.m
  91. 74
    64
      ios/ReactNativePermissions.xcodeproj/project.pbxproj
  92. 117
    0
      lib/permissions.android.js
  93. 107
    0
      lib/permissions.ios.js
  94. 21
    12
      package.json
  95. 614
    0
      yarn.lock

+ 9
- 0
.flowconfig Datei anzeigen

@@ -0,0 +1,9 @@
1
+[ignore]
2
+
3
+[include]
4
+
5
+[libs]
6
+
7
+[lints]
8
+
9
+[options]

+ 74
- 0
.github/CODE_OF_CONDUCT.md Datei anzeigen

@@ -0,0 +1,74 @@
1
+# Contributor Covenant Code of Conduct
2
+
3
+## Our Pledge
4
+
5
+In the interest of fostering an open and welcoming environment, we as
6
+contributors and maintainers pledge to making participation in our project and
7
+our community a harassment-free experience for everyone, regardless of age, body
8
+size, disability, ethnicity, gender identity and expression, level of
9
+experience, nationality, personal appearance, race, religion, or sexual identity
10
+and orientation.
11
+
12
+## Our Standards
13
+
14
+Examples of behavior that contributes to creating a positive environment
15
+include:
16
+
17
+* Using welcoming and inclusive language
18
+* Being respectful of differing viewpoints and experiences
19
+* Gracefully accepting constructive criticism
20
+* Focusing on what is best for the community
21
+* Showing empathy towards other community members
22
+
23
+Examples of unacceptable behavior by participants include:
24
+
25
+* The use of sexualized language or imagery and unwelcome sexual attention or
26
+  advances
27
+* Trolling, insulting/derogatory comments, and personal or political attacks
28
+* Public or private harassment
29
+* Publishing others' private information, such as a physical or electronic
30
+  address, without explicit permission
31
+* Other conduct which could reasonably be considered inappropriate in a
32
+  professional setting
33
+
34
+## Our Responsibilities
35
+
36
+Project maintainers are responsible for clarifying the standards of acceptable
37
+behavior and are expected to take appropriate and fair corrective action in
38
+response to any instances of unacceptable behavior.
39
+
40
+Project maintainers have the right and responsibility to remove, edit, or reject
41
+comments, commits, code, wiki edits, issues, and other contributions that are
42
+not aligned to this Code of Conduct, or to ban temporarily or permanently any
43
+contributor for other behaviors that they deem inappropriate, threatening,
44
+offensive, or harmful.
45
+
46
+## Scope
47
+
48
+This Code of Conduct applies both within project spaces and in public spaces
49
+when an individual is representing the project or its community. Examples of
50
+representing a project or community include using an official project e-mail
51
+address, posting via an official social media account, or acting as an appointed
52
+representative at an online or offline event. Representation of a project may be
53
+further defined and clarified by project maintainers.
54
+
55
+## Enforcement
56
+
57
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+reported by contacting the project team at yonaforst@hotmail.com. The project
59
+team will review and investigate all complaints, and will respond in a way that
60
+it deems appropriate to the circumstances. The project team is obligated to
61
+maintain confidentiality with regard to the reporter of an incident. Further
62
+details of specific enforcement policies may be posted separately.
63
+
64
+Project maintainers who do not follow or enforce the Code of Conduct in good
65
+faith may face temporary or permanent repercussions as determined by other
66
+members of the project's leadership.
67
+
68
+## Attribution
69
+
70
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
71
+version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+[homepage]: http://contributor-covenant.org
74
+[version]: http://contributor-covenant.org/version/1/4/

+ 26
- 0
.github/ISSUE_TEMPLATE.md Datei anzeigen

@@ -0,0 +1,26 @@
1
+Hello!
2
+
3
+Please read the following carefully before opening a new issue. Your issue may
4
+be closed if it doesn't provide the informations required.
5
+
6
+#### ⚠️ Delete everything above this line
7
+
8
+### Describe your environment
9
+
10
+* React-Native version
11
+* Platform: iOS, Android, both?
12
+* Device (which one?), simulator?
13
+* OS version
14
+* react-native-permissions version
15
+* Devtools: Xcode? Android Studio version?
16
+* (Android only: buildToolsVersion)
17
+
18
+### How to repeat issue and example
19
+
20
+Explain what you did, what you expected to happen, and what actually happens.
21
+Provide some code if needed.
22
+
23
+### Solution
24
+
25
+Do you know what needs to be done to address this issue? Ideally, provide a pull
26
+request with a fix.

+ 15
- 10
.gitignore Datei anzeigen

@@ -1,10 +1,15 @@
1
-android/react-native-permissions.iml
2
-android/build
3
-android/.idea
4
-npm-debug.log
5
-gradlew
6
-gradle-wrapper.properties
7
-gradle-wrapper.jar
8
-local.properties
9
-gradlew.bat
10
-android.iml
1
+*.xcworkspace
2
+xcuserdata
3
+
4
+npm-debug.log*
5
+yarn-debug.log*
6
+yarn-error.log*
7
+node_modules/
8
+
9
+*.DS_Store
10
+Thumbs.db
11
+Desktop.ini
12
+
13
+.vscode/
14
+
15
+android/build/

+ 1
- 1
.npmignore Datei anzeigen

@@ -1 +1 @@
1
-Example
1
+example/

+ 3
- 0
.prettierignore Datei anzeigen

@@ -0,0 +1,3 @@
1
+android/
2
+ios/
3
+example/node_modules/

+ 5
- 0
.prettierrc Datei anzeigen

@@ -0,0 +1,5 @@
1
+{
2
+  "singleQuote": true,
3
+  "trailingComma": "all",
4
+  "semi": false
5
+}

+ 0
- 46
CODE_OF_CONDUCT.md Datei anzeigen

@@ -1,46 +0,0 @@
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 yonaforst@hotmail.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/

+ 0
- 12
Example/__tests__/index.android.js Datei anzeigen

@@ -1,12 +0,0 @@
1
-import 'react-native';
2
-import React from 'react';
3
-import Index from '../index.android.js';
4
-
5
-// Note: test renderer must be required after react-native.
6
-import renderer from 'react-test-renderer';
7
-
8
-it('renders correctly', () => {
9
-  const tree = renderer.create(
10
-    <Index />
11
-  );
12
-});

+ 0
- 12
Example/__tests__/index.ios.js Datei anzeigen

@@ -1,12 +0,0 @@
1
-import 'react-native';
2
-import React from 'react';
3
-import Index from '../index.ios.js';
4
-
5
-// Note: test renderer must be required after react-native.
6
-import renderer from 'react-test-renderer';
7
-
8
-it('renders correctly', () => {
9
-  const tree = renderer.create(
10
-    <Index />
11
-  );
12
-});

+ 0
- 14
Example/index.android.js Datei anzeigen

@@ -1,14 +0,0 @@
1
-/**
2
- * Sample React Native App
3
- * https://github.com/facebook/react-native
4
- * @flow
5
- */
6
-
7
-import React, { Component } from 'react';
8
-import {
9
-  AppRegistry,
10
-} from 'react-native';
11
-
12
-import Example from './Example'
13
-
14
-AppRegistry.registerComponent('Example', () => Example);

+ 0
- 14
Example/index.ios.js Datei anzeigen

@@ -1,14 +0,0 @@
1
-/**
2
- * Sample React Native App
3
- * https://github.com/facebook/react-native
4
- * @flow
5
- */
6
-
7
-import React, { Component } from 'react';
8
-import {
9
-  AppRegistry,
10
-} from 'react-native';
11
-
12
-import Example from './Example'
13
-
14
-AppRegistry.registerComponent('Example', () => Example);

+ 0
- 38
Example/ios/Example/Images.xcassets/AppIcon.appiconset/Contents.json Datei anzeigen

@@ -1,38 +0,0 @@
1
-{
2
-  "images" : [
3
-    {
4
-      "idiom" : "iphone",
5
-      "size" : "29x29",
6
-      "scale" : "2x"
7
-    },
8
-    {
9
-      "idiom" : "iphone",
10
-      "size" : "29x29",
11
-      "scale" : "3x"
12
-    },
13
-    {
14
-      "idiom" : "iphone",
15
-      "size" : "40x40",
16
-      "scale" : "2x"
17
-    },
18
-    {
19
-      "idiom" : "iphone",
20
-      "size" : "40x40",
21
-      "scale" : "3x"
22
-    },
23
-    {
24
-      "idiom" : "iphone",
25
-      "size" : "60x60",
26
-      "scale" : "2x"
27
-    },
28
-    {
29
-      "idiom" : "iphone",
30
-      "size" : "60x60",
31
-      "scale" : "3x"
32
-    }
33
-  ],
34
-  "info" : {
35
-    "version" : 1,
36
-    "author" : "xcode"
37
-  }
38
-}

+ 0
- 23
Example/package.json Datei anzeigen

@@ -1,23 +0,0 @@
1
-{
2
-  "name": "Example",
3
-  "version": "0.0.1",
4
-  "private": true,
5
-  "scripts": {
6
-    "start": "react-native start",
7
-    "test": "jest"
8
-  },
9
-  "dependencies": {
10
-    "react": "^16.0.0-alpha.12",
11
-    "react-native": "^0.48.4",
12
-    "react-native-permissions": "../"
13
-  },
14
-  "devDependencies": {
15
-    "babel-jest": "18.0.0",
16
-    "babel-preset-react-native": "1.9.1",
17
-    "jest": "18.1.0",
18
-    "react-test-renderer": "15.4.2"
19
-  },
20
-  "jest": {
21
-    "preset": "react-native"
22
-  }
23
-}

+ 239
- 167
README.md Datei anzeigen

@@ -1,212 +1,230 @@
1
-# React Native Permissions
2
-Request user permissions from React Native, iOS + Android
1
+# ☝🏼 React Native Permissions
3 2
 
4
-The current supported permissions are:
5
-- Location
6
-- Camera
7
-- Microphone
8
-- Photos
9
-- Contacts
10
-- Events
11
-- Reminders *(iOS only)*
12
-- Bluetooth *(iOS only)*
13
-- Push Notifications *(iOS only)*
14
-- Background Refresh *(iOS only)*
15
-- Speech Recognition *(iOS only)*
16
-- Core Motion *(iOS only)*
17
-- Call Phone *(Android Only)*
18
-- Read/Receive SMS *(Android only)*
3
+[![npm version](https://badge.fury.io/js/react-native-permissions.svg)](https://badge.fury.io/js/react-native-permissions)
4
+[![npm](https://img.shields.io/npm/dt/react-native-permissions.svg)](https://www.npmjs.org/package/react-native-permissions)
5
+![Platform - Android and iOS](https://img.shields.io/badge/platform-Android%20%7C%20iOS-yellow.svg)
6
+![MIT](https://img.shields.io/dub/l/vibe-d.svg)
7
+[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
19 8
 
9
+Request user permissions from React Native, iOS + Android
20 10
 
21 11
 | Version | React Native Support |
22
-|---|---|
23
-| 1.0.1 | 0.40.0 - 0.48.4 |
24
-| 0.2.7 | 0.40.0 - 0.41.0 |
25
-| 0.2.5 | 0.33.0 - 0.39.0 |
26
-*Complies with [react-native-version-support-table](https://github.com/dangnelson/react-native-version-support-table)*
27
-
28
-### Breaking changes in version 1.0.0
29
-  - Now using React Native's own JS PermissionsAndroid library on Android, which is great because now we no longer have to do any additional linking (on Android)
30
-  - Updated API to be closer to RN's PermissionsAndroid
31
-  - Removed `openSettings()` support on Android (to stay linking-free). There are several NPM modules available for this
32
-  - `restricted` status now supported on Android, although it means something different than iOS
33
-
34
-## General Usage
35
-```
12
+| ------- | -------------------- |
13
+| 1.0.6   | 0.40 - 0.51          |
14
+| 0.2.5   | 0.33 - 0.39          |
15
+
16
+_Complies with
17
+[react-native-version-support-table](https://github.com/dangnelson/react-native-version-support-table)_
18
+
19
+## ⚠️ Breaking changes in version 1.0.0
20
+
21
+* Now using React Native's own JS `PermissionsAndroid` module on Android, which
22
+  is great because we no longer have to do any additional linking on Android
23
+* Updated API to be closer to React Native's `PermissionsAndroid`
24
+* Removed `openSettings()` support on Android (to stay linking-free). There are
25
+  several NPM modules available for this
26
+* `restricted` status now supported on Android, although it means something
27
+  different than iOS
28
+
29
+## Setup
30
+
31
+```sh
36 32
 npm install --save react-native-permissions
37
-react-native link
33
+# --- or ---
34
+yarn add react-native-permissions
35
+```
36
+
37
+_📌 Don't forget to add permissions to `AndroidManifest.xml` for android and
38
+`Info.plist` for iOS (Xcode >= 8). See [iOS Notes](#ios-notes) or [Android Notes](#android-notes) for more details._
39
+
40
+### Additional iOS setup
41
+
42
+#### Using cocoaPods
43
+
44
+Update the following line with your path to `node_modules/` and add it to your
45
+podfile:
46
+
47
+```ruby
48
+pod 'ReactNativePermissions', :path => '../node_modules/react-native-permissions'
38 49
 ```
39 50
 
40
-Add permissions to manifest for android and info.plist for ios (xcode >=8). See notes below for more details.
51
+#### Using react-native link
52
+
53
+```sh
54
+react-native link react-native-permissions
55
+```
56
+
57
+#### Using manual linking
58
+
59
+1. In the XCode's "Project navigator", right click on your project's Libraries
60
+   folder ➜ `Add Files to <...>`
61
+2. Go to `node_modules` ➜ `react-native-permissions` ➜ select
62
+   `ReactNativePermissions.xcodeproj`
63
+3. Add `libReactNativePermissions.a` to `Build Phases` -> `Link Binary With
64
+   Libraries`
65
+
66
+## Using
41 67
 
42 68
 ```js
43
-const Permissions = require('react-native-permissions');
69
+import Permissions from 'react-native-permissions'
70
+// OR const Permissions = require('react-native-permissions').default
71
+// if you use CommonJS module system
44 72
 
45 73
 //...
46
-  //check the status of a single permission
74
+
75
+export default class extends React.Component {
76
+  //...
77
+
78
+  // Check the status of a single permission
47 79
   componentDidMount() {
48
-    Permissions.check('photo')
49
-      .then(response => {
50
-        //response is one of: 'authorized', 'denied', 'restricted', or 'undetermined'
51
-        this.setState({ photoPermission: response })
52
-      });
80
+    Permissions.check('photo').then(response => {
81
+      // Response is one of: 'authorized', 'denied', 'restricted', or 'undetermined'
82
+      this.setState({ photoPermission: response })
83
+    })
53 84
   }
54 85
 
55
-  //request permission to access photos
56
-  _requestPermission() {
57
-    Permissions.request('photo')
58
-      .then(response => {
59
-        //returns once the user has chosen to 'allow' or to 'not allow' access
60
-        //response is one of: 'authorized', 'denied', 'restricted', or 'undetermined'
61
-        this.setState({ photoPermission: response })
62
-      });
86
+  // Request permission to access photos
87
+  _requestPermission = () => {
88
+    Permissions.request('photo').then(response => {
89
+      // Returns once the user has chosen to 'allow' or to 'not allow' access
90
+      // Response is one of: 'authorized', 'denied', 'restricted', or 'undetermined'
91
+      this.setState({ photoPermission: response })
92
+    })
63 93
   }
64 94
 
65
-  //check the status of multiple permissions
66
-  _checkCameraAndPhotos() {
67
-    Permissions.checkMultiple(['camera', 'photo'])
68
-      .then(response => {
69
-        //response is an object mapping type to permission
70
-        this.setState({
71
-          cameraPermission: response.camera,
72
-          photoPermission: response.photo,
73
-        })
74
-      });
95
+  // Check the status of multiple permissions
96
+  _checkCameraAndPhotos = () => {
97
+    Permissions.checkMultiple(['camera', 'photo']).then(response => {
98
+      //response is an object mapping type to permission
99
+      this.setState({
100
+        cameraPermission: response.camera,
101
+        photoPermission: response.photo,
102
+      })
103
+    })
75 104
   }
76 105
 
77
-  // this is a common pattern when asking for permissions.
106
+  // This is a common pattern when asking for permissions.
78 107
   // iOS only gives you once chance to show the permission dialog,
79 108
   // after which the user needs to manually enable them from settings.
80
-  // the idea here is to explain why we need access and determine if
109
+  // The idea here is to explain why we need access and determine if
81 110
   // the user will say no, so that we don't blow our one chance.
82
-  // if the user already denied access, we can ask them to enable it from settings.
111
+  // If the user already denied access, we can ask them to enable it from settings.
83 112
   _alertForPhotosPermission() {
84 113
     Alert.alert(
85 114
       'Can we access your photos?',
86 115
       'We need access so you can set your profile pic',
87 116
       [
88
-        {text: 'No way', onPress: () => console.log('permission denied'), style: 'cancel'},
89
-        this.state.photoPermission == 'undetermined'?
90
-          {text: 'OK', onPress: this._requestPermission.bind(this)}
91
-          : {text: 'Open Settings', onPress: Permissions.openSettings}
92
-      ]
117
+        {
118
+          text: 'No way',
119
+          onPress: () => console.log('Permission denied'),
120
+          style: 'cancel',
121
+        },
122
+        this.state.photoPermission == 'undetermined'
123
+          ? { text: 'OK', onPress: this._requestPermission }
124
+          : { text: 'Open Settings', onPress: Permissions.openSettings },
125
+      ],
93 126
     )
94 127
   }
95
-//...
96
-```
97
-
98
-## API
99
-
100
-### Permission statuses
101
-Promises resolve into one of these statuses
102
-
103
-| Return value | Notes|
104
-|---|---|
105
-|`authorized`| user has authorized this permission |
106
-|`denied`| user has denied this permission at least once. On iOS this means that the user will not be prompted again. Android users can be promted multiple times until they select 'Never ask me again'|
107
-|`restricted`| **iOS** - this means user is not able to grant this permission, either because it's not supported by the device or because it has been blocked by parental controls. **Android** - this means that the user has selected 'Never ask me again' while denying permission |
108
-|`undetermined`| user has not yet been prompted with a permission dialog |
109
-
110
-### Supported permission types
111
-
112
-| Name | iOS | Android |
113
-|---|---|---|
114
-|`location`| ✔️ | ✔ |
115
-|`camera`| ✔️ | ✔ |
116
-|`microphone`| ✔️ | ✔ |
117
-|`photo`| ✔️ | ✔ |
118
-|`contacts`| ✔️ | ✔ |
119
-|`event`| ✔️ | ✔ |
120
-|`bluetooth`| ✔️ | ❌ |
121
-|`reminder`| ✔️ | ❌ |
122
-|`notification`| ✔️ | ❌ |
123
-|`backgroundRefresh`| ✔️ | ❌ |
124
-|`speechRecognition`| ✔️ | ❌ |
125
-|`motion`| ✔️ | ❌ |
126
-|`storage`| ❌️ | ✔ |
127
-|`callPhone`| ❌️ | ✔ |
128
-|`readSms`| ❌️ | ✔ |
129
-|`receiveSms`| ❌️ | ✔ |
130
-
131
-### Methods
132
-| Method Name | Arguments | Notes
133
-|---|---|---|
134
-| `check()` | `type` | - Returns a promise with the permission status. See iOS Notes for special cases |
135
-| `request()` | `type` | - Accepts any permission type except `backgroundRefresh`. If the current status is `undetermined`, shows the permission dialog and returns a promise with the resulting status. Otherwise, immediately return a promise with the current status. See iOS Notes for special cases|
136
-| `checkMultiple()` | `[types]` | - Accepts an array of permission types and returns a promise with an object mapping permission types to statuses |
137
-| `getTypes()` | *none* | - Returns an array of valid permission types  |
138
-| `openSettings()` | *none* | - *(iOS only - 8.0 and later)* Switches the user to the settings page of your app |
139
-| `canOpenSettings()` | *none* | - *(iOS only)* Returns a boolean indicating if the device supports switching to the settings page |
140
-
141
-### iOS Notes
142
-- Permission type `bluetooth` represents the status of the `CBPeripheralManager`. Don't use this if only need `CBCentralManager`
143
-- Permission type `location` accepts a second parameter for `request()` and `check()`;  the second parameter is a string, either `always` or `whenInUse`(default).
144 128
 
145
-- Permission type `notification` accepts a second parameter for `request()`. The second parameter is an array with the desired alert types. Any combination of `alert`, `badge` and `sound` (default requests all three)
146
-
147
-```js
148
-///example
149
-    Permissions.check('location', 'always')
150
-      .then(response => {
151
-        this.setState({ locationPermission: response })
152
-      })
153
-
154
-    Permissions.request('location', 'always')
155
-      .then(response => {
156
-        this.setState({ locationPermission: response })
157
-      })
158
-
159
-    Permissions.request('notification', ['alert', 'badge'])
160
-      .then(response => {
161
-        this.setState({ notificationPermission: response })
162
-      })
129
+  //...
130
+}
163 131
 ```
164 132
 
165
-You cannot request microphone permissions on the simulator.
133
+## API
166 134
 
167
-With Xcode 8, you now need to add usage descriptions for each permission you will request. Open Xcode > Info.plist > Add a key (starting with "Privacy - ...") with your kit specific permission.
135
+### Permissions statuses
168 136
 
169
-Example:
170
-If you need Contacts permission you have to add the key "Privacy - Contacts Usage Description".
171
-<img width="338" alt="3cde3b44-7ffd-11e6-918b-63888e33f983" src="https://cloud.githubusercontent.com/assets/1440796/18713019/271be540-8011-11e6-87fb-c3828c172dfc.png">
137
+Promises resolve into one of these statuses:
172 138
 
173
-### Android Notes
139
+| Return value   | Notes                                                                                                                                                                                                                                                                  |
140
+| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
141
+| `authorized`   | User has authorized this permission                                                                                                                                                                                                                                    |
142
+| `denied`       | User has denied this permission at least once. On iOS this means that the user will not be prompted again. Android users can be prompted multiple times until they select 'Never ask me again'                                                                          |
143
+| `restricted`   | **iOS** - this means user is not able to grant this permission, either because it's not supported by the device or because it has been blocked by parental controls. **Android** - this means that the user has selected 'Never ask me again' while denying permission |
144
+| `undetermined` | User has not yet been prompted with a permission dialog                                                                                                                                                                                                                |
174 145
 
175
-Requires RN >= 0.29.0
146
+### Supported permissions types
176 147
 
177
-Uses RN's own `PermissionsAndroid` JS api (http://facebook.github.io/react-native/releases/0.45/docs/permissionsandroid.html)
148
+The current supported permissions are:
178 149
 
179
-All required permissions also need to be included in the Manifest before they can be requested. Otherwise `request()` will immediately return `denied`.
150
+|                    | Type                | iOS | Android |
151
+| ------------------ | ------------------- | --- | ------- |
152
+| Location           | `location`          | ✔️  | ✔       |
153
+| Camera             | `camera`            | ✔️  | ✔       |
154
+| Microphone         | `microphone`        | ✔️  | ✔       |
155
+| Photos             | `photo`             | ✔️  | ✔       |
156
+| Contacts           | `contacts`          | ✔️  | ✔       |
157
+| Events             | `event`             | ✔️  | ✔       |
158
+| Bluetooth          | `bluetooth`         | ✔️  | ❌      |
159
+| Reminders          | `reminder`          | ✔️  | ❌      |
160
+| Push Notifications | `notification`      | ✔️  | ❌      |
161
+| Background Refresh | `backgroundRefresh` | ✔️  | ❌      |
162
+| Speech Recognition | `speechRecognition` | ✔️  | ❌      |
163
+| Motion Activity    | `motion`            | ✔️  | ❌      |
164
+| Storage            | `storage`           | ❌️ | ✔       |
165
+| Phone Call         | `callPhone`         | ❌️ | ✔       |
166
+| Read SMS           | `readSms`           | ❌️ | ✔       |
167
+| Receive SMS        | `receiveSms`        | ❌️ | ✔       |
180 168
 
181
-Permissions are automatically accepted for targetSdkVersion < 23 but you can still use `check()` to check if the user has disabled them from Settings.
169
+### Methods
182 170
 
183
-You can request write access to any of these types by also including the appropriate write permission in the Manifest. Read more here: https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous
171
+| Method Name         | Arguments | Notes                                                                                                                                                                                                                                                                            |
172
+| ------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
173
+| `check()`           | `type`    | - Returns a promise with the permission status. See iOS Notes for special cases                                                                                                                                                                                                  |
174
+| `request()`         | `type`    | - Accepts any permission type except `backgroundRefresh`. If the current status is `undetermined`, shows the permission dialog and returns a promise with the resulting status. Otherwise, immediately return a promise with the current status. See iOS Notes for special cases |
175
+| `checkMultiple()`   | `[types]` | - Accepts an array of permission types and returns a promise with an object mapping permission types to statuses                                                                                                                                                                 |
176
+| `getTypes()`        | _none_    | - Returns an array of valid permission types                                                                                                                                                                                                                                     |
177
+| `openSettings()`    | _none_    | - _(iOS only - 8.0 and later)_ Switches the user to the settings page of your app                                                                                                                                                                                                |
178
+| `canOpenSettings()` | _none_    | - _(iOS only)_ Returns a boolean indicating if the device supports switching to the settings page                                                                                                                                                                                |
184 179
 
185
-## Setup
180
+### iOS Notes
186 181
 
187
-````
188
-npm install --save react-native-permissions
189
-react-native link
190
-````
182
+* Permission type `bluetooth` represents the status of the
183
+  `CBPeripheralManager`. Don't use this if only need `CBCentralManager`
184
+* Permission type `location` accepts a second parameter for `request()` and
185
+  `check()`; the second parameter is a string, either `always` or `whenInUse`
186
+  (default).
187
+* Permission type `notification` accepts a second parameter for `request()`. The
188
+  second parameter is an array with the desired alert types. Any combination of
189
+  `alert`, `badge` and `sound` (default requests all three).
191 190
 
192
-### Or manually linking
191
+```js
192
+// example
193
+Permissions.check('location', { type: 'always' }).then(response => {
194
+  this.setState({ locationPermission: response })
195
+})
196
+
197
+Permissions.request('location', { type: 'always' }).then(response => {
198
+  this.setState({ locationPermission: response })
199
+})
200
+
201
+Permissions.request('notification', { type: ['alert', 'badge'] }).then(
202
+  response => {
203
+    this.setState({ notificationPermission: response })
204
+  },
205
+)
206
+```
193 207
 
194
-#### iOS
195
-* Run open node_modules/react-native-permissions
196
-* Drag ReactNativePermissions.xcodeproj into the Libraries group of your app's Xcode project
197
-* Add libReactNativePermissions.a to `Build Phases -> Link Binary With Libraries.
208
+* You cannot request microphone permissions on the simulator.
209
+* With Xcode 8, you now need to add usage descriptions for each permission you
210
+  will request. Open Xcode ➜ `Info.plist` ➜ Add a key (starting with "Privacy -
211
+  ...") with your kit specific permission.
198 212
 
199
-#### Android
200
-  No additional linking required
213
+Example: If you need Contacts permission you have to add the key `Privacy -
214
+Contacts Usage Description`.
201 215
 
202
-## AppStore submission disclaimer
216
+<img width="338" alt="3cde3b44-7ffd-11e6-918b-63888e33f983" src="https://cloud.githubusercontent.com/assets/1440796/18713019/271be540-8011-11e6-87fb-c3828c172dfc.png">
203 217
 
204
-If you need to submit you application to the AppStore, you need to add to your `Info.plist` all `*UsageDescription` keys with a string value explaining to the user how the app uses this data. **Even if you don't use them**.
218
+#### App Store submission disclaimer
205 219
 
206
-So before submitting your app to the `AppStore`, make sure that in your `Info.plist` you have the following keys:
220
+If you need to submit you application to the AppStore, you need to add to your
221
+`Info.plist` all `*UsageDescription` keys with a string value explaining to the
222
+user how the app uses this data. **Even if you don't use them**.
207 223
 
208
-```
224
+So before submitting your app to the App Store, make sure that in your
225
+`Info.plist` you have the following keys:
209 226
 
227
+```xml
210 228
 <key>NSBluetoothPeripheralUsageDescription</key>
211 229
 <string>Some description</string>
212 230
 <key>NSCalendarsUsageDescription</key>
@@ -215,25 +233,79 @@ So before submitting your app to the `AppStore`, make sure that in your `Info.pl
215 233
 <string>Some description</string>
216 234
 <key>NSLocationWhenInUseUsageDescription</key>
217 235
 <string>Some description</string>
236
+<key>NSPhotoLibraryAddUsageDescription</key>
237
+<string>Some description</string>
218 238
 <key>NSPhotoLibraryUsageDescription</key>
219 239
 <string>Some description</string>
220 240
 <key>NSSpeechRecognitionUsageDescription</key>
221 241
 <string>Some description</string>
222 242
 <key>NSMotionUsageDescription</key>
223 243
 <string>Some description</string>
244
+```
245
+
246
+This is required because during the phase of processing in the App Store
247
+submission, the system detects that you app contains code to request the
248
+permission `X` but don't have the `UsageDescription` key and then it rejects the
249
+build.
250
+
251
+> Please note that it will only be shown to the users the usage descriptions of
252
+> the permissions you really require in your app.
253
+
254
+You can find more information about this issue in #46.
255
+
256
+### Android Notes
257
+
258
+* Uses React Native's own
259
+  [`PermissionsAndroid` JS API](http://facebook.github.io/react-native/docs/permissionsandroid.html).
260
+* All required permissions also need to be included in the `AndroidManifest.xml`
261
+  file before they can be requested. Otherwise `request()` will immediately
262
+  return `denied`.
263
+* You can request write access to any of these types by also including the
264
+  appropriate write permission in the `AndroidManifest.xml` file. Read more
265
+  [here](https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous).
224 266
 
267
+* The optional rationale argument will show a dialog prompt.
268
+
269
+```js
270
+// example
271
+Permissions.request('camera', {
272
+  rationale: {
273
+    title: 'Cool Photo App Camera Permission',
274
+    message:
275
+      'Cool Photo App needs access to your camera ' +
276
+      'so you can take awesome pictures.',
277
+  },
278
+}).then(response => {
279
+  this.setState({ cameraPermission: response })
280
+})
225 281
 ```
226 282
 
227
-This is required because during the phase of `processing` in the `AppStore` submission, the system detects that you app contains code to request the permission `X` but don't have the `UsageDescription` key and rejects the build.
283
+* Permissions are automatically accepted for **targetSdkVersion < 23** but you
284
+  can still use `check()` to check if the user has disabled them from Settings.
228 285
 
229
-> Please note that it will only be shown to the users the usage descriptions of the permissions you really require in your app.
286
+You might need to elevate the **targetSdkVersion** version in your
287
+`build.gradle`:
230 288
 
231
-You can find more informations about this issue in #46.
289
+```groovy
290
+android {
291
+  compileSdkVersion 23 // ← set at least 23
292
+  buildToolsVersion "23.0.1"  // ← set at least 23.0.0
293
+
294
+  defaultConfig {
295
+    minSdkVersion 16
296
+    targetSdkVersion 23 // ← set at least 23
297
+    // ...
298
+```
232 299
 
233 300
 ## Troubleshooting
234 301
 
235
-#### Q: iOS - app crashes as soon as I request permission
236
-A: starting with xcode 8, you need to add permission descriptions. see iOS notes for more details. Thanks to @jesperlndk for discovering this.
302
+#### Q: iOS - App crashes as soon as I request permission
303
+
304
+> A: Starting with Xcode 8, you need to add permission descriptions. See iOS
305
+> notes for more details. Thanks to [@jesperlndk](https://github.com/jesperlndk)
306
+> for discovering this.
307
+
308
+#### Q: iOS - App crashes when I change permission from settings
237 309
 
238
-#### Q: iOS - app crashes when I change permissions from settings
239
-A: This is normal. iOS restarts your app when your privacy settings change. Just google "ios crash permission change"
310
+> A: This is normal. iOS restarts your app when your privacy settings change.
311
+> Just google "iOS crash permission change"

+ 14
- 15
ReactNativePermissions.podspec Datei anzeigen

@@ -3,21 +3,20 @@ require 'json'
3 3
 package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4 4
 
5 5
 Pod::Spec.new do |s|
6
-  s.name                = 'ReactNativePermissions'
7
-  s.version             = package['version']
8
-  s.summary             = package['description']
9
-  s.description         = package['description']
10
-  s.homepage            = package['homepage']
11
-  s.license             = package['license']
12
-  s.author              = package['author']
13
-  s.source              = { :git => 'https://github.com/yonahforst/react-native-permissions.git', :tag => s.version }
6
+  s.name                   = 'ReactNativePermissions'
7
+  s.version                = package['version']
8
+  s.summary                = package['description']
9
+  s.description            = package['description']
10
+  s.homepage               = package['homepage']
11
+  s.license                = package['license']
12
+  s.author                 = package['author']
13
+  s.source                 = { :git => 'https://github.com/yonahforst/react-native-permissions.git', :tag => s.version }
14 14
 
15
-  s.platform              = :ios, '9.0'
16
-  s.ios.deployment_target = '8.0'
15
+  s.platform               = :ios, '9.0'
16
+  s.ios.deployment_target  = '8.0'
17 17
 
18
-  s.dependency 'React'
19
-
20
-  s.preserve_paths      = 'docs', 'CHANGELOG.md', 'LICENSE', 'package.json', 'ReactNativePermissions.ios.js'
21
-  s.source_files        = '**/*.{h,m}'
22
-  s.exclude_files       = 'Example/**/*'
18
+  s.preserve_paths         = 'LICENSE', 'package.json'
19
+  s.source_files           = '**/*.{h,m}'
20
+  s.exclude_files          = 'example/**/*'
21
+  s.dependency               'React'
23 22
 end

+ 0
- 7
ReactNativePermissions.xcodeproj/project.xcworkspace/contents.xcworkspacedata Datei anzeigen

@@ -1,7 +0,0 @@
1
-<?xml version="1.0" encoding="UTF-8"?>
2
-<Workspace
3
-   version = "1.0">
4
-   <FileRef
5
-      location = "self:ReactNativePermissions.xcodeproj">
6
-   </FileRef>
7
-</Workspace>

+ 0
- 80
ReactNativePermissions.xcodeproj/xcuserdata/Yonah.xcuserdatad/xcschemes/ReactNativePermissions.xcscheme Datei anzeigen

@@ -1,80 +0,0 @@
1
-<?xml version="1.0" encoding="UTF-8"?>
2
-<Scheme
3
-   LastUpgradeVersion = "0710"
4
-   version = "1.3">
5
-   <BuildAction
6
-      parallelizeBuildables = "YES"
7
-      buildImplicitDependencies = "YES">
8
-      <BuildActionEntries>
9
-         <BuildActionEntry
10
-            buildForTesting = "YES"
11
-            buildForRunning = "YES"
12
-            buildForProfiling = "YES"
13
-            buildForArchiving = "YES"
14
-            buildForAnalyzing = "YES">
15
-            <BuildableReference
16
-               BuildableIdentifier = "primary"
17
-               BlueprintIdentifier = "9D23B34E1C767B80008B4819"
18
-               BuildableName = "libReactNativePermissions.a"
19
-               BlueprintName = "ReactNativePermissions"
20
-               ReferencedContainer = "container:ReactNativePermissions.xcodeproj">
21
-            </BuildableReference>
22
-         </BuildActionEntry>
23
-      </BuildActionEntries>
24
-   </BuildAction>
25
-   <TestAction
26
-      buildConfiguration = "Debug"
27
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29
-      shouldUseLaunchSchemeArgsEnv = "YES">
30
-      <Testables>
31
-      </Testables>
32
-      <AdditionalOptions>
33
-      </AdditionalOptions>
34
-   </TestAction>
35
-   <LaunchAction
36
-      buildConfiguration = "Debug"
37
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
38
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
39
-      launchStyle = "0"
40
-      useCustomWorkingDirectory = "NO"
41
-      ignoresPersistentStateOnLaunch = "NO"
42
-      debugDocumentVersioning = "YES"
43
-      debugServiceExtension = "internal"
44
-      allowLocationSimulation = "YES">
45
-      <MacroExpansion>
46
-         <BuildableReference
47
-            BuildableIdentifier = "primary"
48
-            BlueprintIdentifier = "9D23B34E1C767B80008B4819"
49
-            BuildableName = "libReactNativePermissions.a"
50
-            BlueprintName = "ReactNativePermissions"
51
-            ReferencedContainer = "container:ReactNativePermissions.xcodeproj">
52
-         </BuildableReference>
53
-      </MacroExpansion>
54
-      <AdditionalOptions>
55
-      </AdditionalOptions>
56
-   </LaunchAction>
57
-   <ProfileAction
58
-      buildConfiguration = "Release"
59
-      shouldUseLaunchSchemeArgsEnv = "YES"
60
-      savedToolIdentifier = ""
61
-      useCustomWorkingDirectory = "NO"
62
-      debugDocumentVersioning = "YES">
63
-      <MacroExpansion>
64
-         <BuildableReference
65
-            BuildableIdentifier = "primary"
66
-            BlueprintIdentifier = "9D23B34E1C767B80008B4819"
67
-            BuildableName = "libReactNativePermissions.a"
68
-            BlueprintName = "ReactNativePermissions"
69
-            ReferencedContainer = "container:ReactNativePermissions.xcodeproj">
70
-         </BuildableReference>
71
-      </MacroExpansion>
72
-   </ProfileAction>
73
-   <AnalyzeAction
74
-      buildConfiguration = "Debug">
75
-   </AnalyzeAction>
76
-   <ArchiveAction
77
-      buildConfiguration = "Release"
78
-      revealArchiveInOrganizer = "YES">
79
-   </ArchiveAction>
80
-</Scheme>

+ 0
- 22
ReactNativePermissions.xcodeproj/xcuserdata/Yonah.xcuserdatad/xcschemes/xcschememanagement.plist Datei anzeigen

@@ -1,22 +0,0 @@
1
-<?xml version="1.0" encoding="UTF-8"?>
2
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
-<plist version="1.0">
4
-<dict>
5
-	<key>SchemeUserState</key>
6
-	<dict>
7
-		<key>ReactNativePermissions.xcscheme</key>
8
-		<dict>
9
-			<key>orderHint</key>
10
-			<integer>0</integer>
11
-		</dict>
12
-	</dict>
13
-	<key>SuppressBuildableAutocreation</key>
14
-	<dict>
15
-		<key>9D23B34E1C767B80008B4819</key>
16
-		<dict>
17
-			<key>primary</key>
18
-			<true/>
19
-		</dict>
20
-	</dict>
21
-</dict>
22
-</plist>

Example/.babelrc → example/.babelrc Datei anzeigen


Example/.buckconfig → example/.buckconfig Datei anzeigen


Example/.flowconfig → example/.flowconfig Datei anzeigen

@@ -12,14 +12,15 @@
12 12
 ; For RN Apps installed via npm, "Libraries" folder is inside
13 13
 ; "node_modules/react-native" but in the source repo it is in the root
14 14
 .*/Libraries/react-native/React.js
15
-.*/Libraries/react-native/ReactNative.js
15
+
16
+; Ignore polyfills
17
+.*/Libraries/polyfills/.*
16 18
 
17 19
 [include]
18 20
 
19 21
 [libs]
20 22
 node_modules/react-native/Libraries/react-native/react-native-interface.js
21
-node_modules/react-native/flow
22
-flow/
23
+node_modules/react-native/flow/
23 24
 
24 25
 [options]
25 26
 emoji=true
@@ -32,14 +33,16 @@ module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|we
32 33
 
33 34
 suppress_type=$FlowIssue
34 35
 suppress_type=$FlowFixMe
36
+suppress_type=$FlowFixMeProps
37
+suppress_type=$FlowFixMeState
35 38
 suppress_type=$FixMe
36 39
 
37
-suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
38
-suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
40
+suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
41
+suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
39 42
 suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
40 43
 suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
41 44
 
42 45
 unsafe.enable_getters_and_setters=true
43 46
 
44 47
 [version]
45
-^0.49.1
48
+^0.56.0

Example/.gitattributes → example/.gitattributes Datei anzeigen


Example/.gitignore → example/.gitignore Datei anzeigen

@@ -46,8 +46,8 @@ buck-out/
46 46
 # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
47 47
 # screenshots whenever they are needed.
48 48
 # For more information about the recommended setup visit:
49
-# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
49
+# https://docs.fastlane.tools/best-practices/source-control/
50 50
 
51
-fastlane/report.xml
52
-fastlane/Preview.html
53
-fastlane/screenshots
51
+*/fastlane/report.xml
52
+*/fastlane/Preview.html
53
+*/fastlane/screenshots

Example/.watchmanconfig → example/.watchmanconfig Datei anzeigen


Example/Example.js → example/App.js Datei anzeigen

@@ -1,10 +1,6 @@
1
-/**
2
- * Sample React Native App
3
- * https://github.com/facebook/react-native
4
- * @flow
5
- */
1
+// @flow
6 2
 
7
-import React, { Component } from 'react';
3
+import React, { Component } from 'react'
8 4
 import {
9 5
   StyleSheet,
10 6
   TouchableHighlight,
@@ -13,11 +9,11 @@ import {
13 9
   Alert,
14 10
   AppState,
15 11
   Platform,
16
-} from 'react-native';
12
+} from 'react-native'
17 13
 
18 14
 import Permissions from 'react-native-permissions'
19 15
 
20
-export default class Example extends Component {
16
+export default class App extends Component {
21 17
   state = {
22 18
     types: [],
23 19
     status: {},
@@ -29,38 +25,38 @@ export default class Example extends Component {
29 25
 
30 26
     this.setState({ types, canOpenSettings })
31 27
     this._updatePermissions(types)
32
-    AppState.addEventListener('change', this._handleAppStateChange.bind(this));
28
+    AppState.addEventListener('change', this._handleAppStateChange)
33 29
   }
34 30
 
35 31
   componentWillUnmount() {
36
-    AppState.removeEventListener('change', this._handleAppStateChange.bind(this));
32
+    AppState.removeEventListener('change', this._handleAppStateChange)
37 33
   }
38 34
 
39 35
   //update permissions when app comes back from settings
40
-  _handleAppStateChange(appState) {
36
+  _handleAppStateChange = appState => {
41 37
     if (appState == 'active') {
42 38
       this._updatePermissions(this.state.types)
43 39
     }
44 40
   }
45 41
 
46
-  _openSettings() {
47
-    return Permissions.openSettings()
48
-      .then(() => alert('back to app!!'))
49
-  }
42
+  _openSettings = () =>
43
+    Permissions.openSettings().then(() => alert('back to app!!'))
50 44
 
51
-  _updatePermissions(types) {
45
+  _updatePermissions = types => {
52 46
     Permissions.checkMultiple(types)
53 47
       .then(status => {
54 48
         if (this.state.isAlways) {
55
-          return Permissions.check('location', 'always')
56
-            .then(location => ({...status, location}))
49
+          return Permissions.check('location', 'always').then(location => ({
50
+            ...status,
51
+            location,
52
+          }))
57 53
         }
58 54
         return status
59 55
       })
60 56
       .then(status => this.setState({ status }))
61 57
   }
62 58
 
63
-  _requestPermission(permission) {
59
+  _requestPermission = permission => {
64 60
     var options
65 61
 
66 62
     if (permission == 'location') {
@@ -70,22 +66,27 @@ export default class Example extends Component {
70 66
     Permissions.request(permission, options)
71 67
       .then(res => {
72 68
         this.setState({
73
-          status: {...this.state.status, [permission]: res}
69
+          status: { ...this.state.status, [permission]: res },
74 70
         })
75 71
         if (res != 'authorized') {
76 72
           var buttons = [{ text: 'Cancel', style: 'cancel' }]
77
-          if (this.state.canOpenSettings) buttons.push({ text: 'Open Settings', onPress: this._openSettings.bind(this) })
78
-          
73
+          if (this.state.canOpenSettings)
74
+            buttons.push({
75
+              text: 'Open Settings',
76
+              onPress: this._openSettings,
77
+            })
78
+
79 79
           Alert.alert(
80 80
             'Whoops!',
81
-            "There was a problem getting your permission. Please enable it from settings.",
82
-            buttons
81
+            'There was a problem getting your permission. Please enable it from settings.',
82
+            buttons,
83 83
           )
84 84
         }
85
-      }).catch(e => console.warn(e))
85
+      })
86
+      .catch(e => console.warn(e))
86 87
   }
87 88
 
88
-  _onLocationSwitchChange() {
89
+  _onLocationSwitchChange = () => {
89 90
     this.setState({ isAlways: !this.state.isAlways })
90 91
     this._updatePermissions(this.state.types)
91 92
   }
@@ -93,46 +94,44 @@ export default class Example extends Component {
93 94
   render() {
94 95
     return (
95 96
       <View style={styles.container}>
96
-
97 97
         {this.state.types.map(p => (
98
-          <TouchableHighlight 
98
+          <TouchableHighlight
99 99
             style={[styles.button, styles[this.state.status[p]]]}
100 100
             key={p}
101
-            onPress={this._requestPermission.bind(this, p)}>
101
+            onPress={() => this._requestPermission(p)}
102
+          >
102 103
             <View>
103 104
               <Text style={styles.text}>
104
-                {Platform.OS == 'ios' && p == 'location' ? `location ${this.state.isAlways ? 'always' : 'whenInUse'}` : p}
105
-              </Text>
106
-              <Text style={styles.subtext}>
107
-                {this.state.status[p]}
105
+                {Platform.OS == 'ios' && p == 'location'
106
+                  ? `location ${this.state.isAlways ? 'always' : 'whenInUse'}`
107
+                  : p}
108 108
               </Text>
109
+              <Text style={styles.subtext}>{this.state.status[p]}</Text>
109 110
             </View>
110 111
           </TouchableHighlight>
111
-          )
112
-        )}
112
+        ))}
113 113
         <View style={styles.footer}>
114
-          <TouchableHighlight 
115
-            style={styles['footer_'+Platform.OS]}
116
-            onPress={this._onLocationSwitchChange.bind(this)}>
114
+          <TouchableHighlight
115
+            style={styles['footer_' + Platform.OS]}
116
+            onPress={this._onLocationSwitchChange}
117
+          >
117 118
             <Text style={styles.text}>Toggle location type</Text>
118 119
           </TouchableHighlight>
119
-   
120
-          {
121
-            this.state.canOpenSettings &&
122
-            <TouchableHighlight 
123
-              onPress={this._openSettings.bind(this)}>
120
+
121
+          {this.state.canOpenSettings && (
122
+            <TouchableHighlight onPress={this._openSettings}>
124 123
               <Text style={styles.text}>Open settings</Text>
125 124
             </TouchableHighlight>
126
-          }
127
-
125
+          )}
128 126
         </View>
129 127
 
130
-
131
-        <Text style={styles['footer_'+Platform.OS]}>
132
-          Note: microphone permissions may not work on iOS simulator. Also, toggling permissions from the settings menu may cause the app to crash. This is normal on iOS. Google "ios crash permission change"
128
+        <Text style={styles['footer_' + Platform.OS]}>
129
+          Note: microphone permissions may not work on iOS simulator. Also,
130
+          toggling permissions from the settings menu may cause the app to
131
+          crash. This is normal on iOS. Google "ios crash permission change"
133 132
         </Text>
134 133
       </View>
135
-    );
134
+    )
136 135
   }
137 136
 }
138 137
 
@@ -169,7 +168,7 @@ const styles = StyleSheet.create({
169 168
     backgroundColor: '#ef9a9a',
170 169
   },
171 170
   restricted: {
172
-    backgroundColor: '#ef9a9a'
171
+    backgroundColor: '#ef9a9a',
173 172
   },
174 173
   footer: {
175 174
     padding: 10,
@@ -179,5 +178,5 @@ const styles = StyleSheet.create({
179 178
   footer_android: {
180 179
     height: 0,
181 180
     width: 0,
182
-  }
183
-})
181
+  },
182
+})

+ 10
- 0
example/__tests__/index.js Datei anzeigen

@@ -0,0 +1,10 @@
1
+import 'react-native'
2
+import React from 'react'
3
+import Index from '../index.js'
4
+
5
+// Note: test renderer must be required after react-native.
6
+import renderer from 'react-test-renderer'
7
+
8
+it('renders correctly', () => {
9
+  const tree = renderer.create(<Index />)
10
+})

Example/android/app/BUCK → example/android/app/BUCK Datei anzeigen


Example/android/app/build.gradle → example/android/app/build.gradle Datei anzeigen

@@ -72,6 +72,10 @@ import com.android.build.OutputFile
72 72
  * ]
73 73
  */
74 74
 
75
+project.ext.react = [
76
+    entryFile: "index.js"
77
+]
78
+
75 79
 apply from: "../../node_modules/react-native/react.gradle"
76 80
 
77 81
 /**
@@ -95,7 +99,7 @@ android {
95 99
 
96 100
     defaultConfig {
97 101
         applicationId "com.example"
98
-        minSdkVersion 21
102
+        minSdkVersion 16
99 103
         targetSdkVersion 23
100 104
         versionCode 1
101 105
         versionName "1.0"

Example/android/app/proguard-rules.pro → example/android/app/proguard-rules.pro Datei anzeigen


Example/android/app/src/main/AndroidManifest.xml → example/android/app/src/main/AndroidManifest.xml Datei anzeigen

@@ -8,6 +8,7 @@
8 8
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
9 9
     <uses-permission android:name="android.permission.CAMERA"/>
10 10
     <uses-permission android:name="android.permission.RECORD_AUDIO"/>
11
+    <uses-permission android:name="android.permission.CALL_PHONE"/>
11 12
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
12 13
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
13 14
     <uses-permission android:name="android.permission.READ_CONTACTS"/>
@@ -15,9 +16,13 @@
15 16
     <uses-permission android:name="android.permission.READ_SMS"/>
16 17
     <uses-permission android:name="android.permission.RECEIVE_SMS"/>
17 18
 
19
+    <uses-sdk
20
+        android:minSdkVersion="16"
21
+        android:targetSdkVersion="23" />
22
+
18 23
     <application
19 24
       android:name=".MainApplication"
20
-      android:allowBackup="true"
25
+      android:allowBackup="false"
21 26
       android:label="@string/app_name"
22 27
       android:icon="@mipmap/ic_launcher"
23 28
       android:theme="@style/AppTheme">

Example/android/app/src/main/java/com/example/MainActivity.java → example/android/app/src/main/java/com/example/MainActivity.java Datei anzeigen


Example/android/app/src/main/java/com/example/MainApplication.java → example/android/app/src/main/java/com/example/MainApplication.java Datei anzeigen

@@ -25,6 +25,11 @@ public class MainApplication extends Application implements ReactApplication {
25 25
           new MainReactPackage()
26 26
       );
27 27
     }
28
+
29
+    @Override
30
+    protected String getJSMainModuleName() {
31
+      return "index";
32
+    }
28 33
   };
29 34
 
30 35
   @Override

Example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png → example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png Datei anzeigen


Example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png → example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png Datei anzeigen


Example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png → example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png Datei anzeigen


Example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png → example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png Datei anzeigen


Example/android/app/src/main/res/values/strings.xml → example/android/app/src/main/res/values/strings.xml Datei anzeigen

@@ -1,4 +1,3 @@
1 1
 <resources>
2
-
3 2
     <string name="app_name">Example</string>
4 3
 </resources>

Example/android/app/src/main/res/values/styles.xml → example/android/app/src/main/res/values/styles.xml Datei anzeigen


Example/android/build.gradle → example/android/build.gradle Datei anzeigen

@@ -6,6 +6,7 @@ buildscript {
6 6
     }
7 7
     dependencies {
8 8
         classpath 'com.android.tools.build:gradle:2.2.3'
9
+
9 10
         // NOTE: Do not place your application dependencies here; they belong
10 11
         // in the individual module build.gradle files
11 12
     }

Example/android/gradle.properties → example/android/gradle.properties Datei anzeigen


Example/android/gradle/wrapper/gradle-wrapper.jar → example/android/gradle/wrapper/gradle-wrapper.jar Datei anzeigen


Example/android/gradle/wrapper/gradle-wrapper.properties → example/android/gradle/wrapper/gradle-wrapper.properties Datei anzeigen

@@ -1,6 +1,5 @@
1
-#Fri Feb 03 16:27:32 CET 2017
2 1
 distributionBase=GRADLE_USER_HOME
3 2
 distributionPath=wrapper/dists
4 3
 zipStoreBase=GRADLE_USER_HOME
5 4
 zipStorePath=wrapper/dists
6
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
5
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

Example/android/gradlew → example/android/gradlew Datei anzeigen


Example/android/gradlew.bat → example/android/gradlew.bat Datei anzeigen


Example/android/keystores/BUCK → example/android/keystores/BUCK Datei anzeigen


Example/android/keystores/debug.keystore.properties → example/android/keystores/debug.keystore.properties Datei anzeigen


Example/android/settings.gradle → example/android/settings.gradle Datei anzeigen


+ 4
- 0
example/app.json Datei anzeigen

@@ -0,0 +1,4 @@
1
+{
2
+  "name": "Example",
3
+  "displayName": "Example"
4
+}

+ 4
- 0
example/index.js Datei anzeigen

@@ -0,0 +1,4 @@
1
+import { AppRegistry } from 'react-native'
2
+import App from './App'
3
+
4
+AppRegistry.registerComponent('Example', () => App)

Example/ios/Example-tvOS/Info.plist → example/ios/Example-tvOS/Info.plist Datei anzeigen


Example/ios/Example-tvOSTests/Info.plist → example/ios/Example-tvOSTests/Info.plist Datei anzeigen


Example/ios/Example.xcodeproj/project.pbxproj → example/ios/Example.xcodeproj/project.pbxproj Datei anzeigen

@@ -25,7 +25,7 @@
25 25
 		2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
26 26
 		2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
27 27
 		2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
28
-		2D02E4C21E0B4AEC006451C7 /* libRCTAnimation-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */; };
28
+		2D02E4C21E0B4AEC006451C7 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */; };
29 29
 		2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */; };
30 30
 		2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */; };
31 31
 		2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */; };
@@ -35,7 +35,7 @@
35 35
 		2D02E4C91E0B4AEC006451C7 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3EA31DF850E9000B6D8A /* libReact.a */; };
36 36
 		2DCD954D1E0B4F2C00145EB5 /* ExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* ExampleTests.m */; };
37 37
 		5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; };
38
-		6D05A8F55CC4482AACFFC932 /* libReactNativePermissions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DF4131A2930454297EF564B /* libReactNativePermissions.a */; };
38
+		66AE23241FE44648000AEC3F /* libReactNativePermissions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 66AE23231FE44628000AEC3F /* libReactNativePermissions.a */; };
39 39
 		832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
40 40
 		ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */; };
41 41
 /* End PBXBuildFile section */
@@ -216,6 +216,76 @@
216 216
 			remoteGlobalIDString = 2D2A28201D9B03D100D4039D;
217 217
 			remoteInfo = "RCTAnimation-tvOS";
218 218
 		};
219
+		661E35331FD3107F00C328EA /* PBXContainerItemProxy */ = {
220
+			isa = PBXContainerItemProxy;
221
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
222
+			proxyType = 2;
223
+			remoteGlobalIDString = 139D7ECE1E25DB7D00323FB7;
224
+			remoteInfo = "third-party";
225
+		};
226
+		661E35351FD3107F00C328EA /* PBXContainerItemProxy */ = {
227
+			isa = PBXContainerItemProxy;
228
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
229
+			proxyType = 2;
230
+			remoteGlobalIDString = 3D383D3C1EBD27B6005632C8;
231
+			remoteInfo = "third-party-tvOS";
232
+		};
233
+		661E35371FD3107F00C328EA /* PBXContainerItemProxy */ = {
234
+			isa = PBXContainerItemProxy;
235
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
236
+			proxyType = 2;
237
+			remoteGlobalIDString = 139D7E881E25C6D100323FB7;
238
+			remoteInfo = "double-conversion";
239
+		};
240
+		661E35391FD3107F00C328EA /* PBXContainerItemProxy */ = {
241
+			isa = PBXContainerItemProxy;
242
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
243
+			proxyType = 2;
244
+			remoteGlobalIDString = 3D383D621EBD27B9005632C8;
245
+			remoteInfo = "double-conversion-tvOS";
246
+		};
247
+		661E353B1FD3107F00C328EA /* PBXContainerItemProxy */ = {
248
+			isa = PBXContainerItemProxy;
249
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
250
+			proxyType = 2;
251
+			remoteGlobalIDString = 9936F3131F5F2E4B0010BF04;
252
+			remoteInfo = privatedata;
253
+		};
254
+		661E353D1FD3107F00C328EA /* PBXContainerItemProxy */ = {
255
+			isa = PBXContainerItemProxy;
256
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
257
+			proxyType = 2;
258
+			remoteGlobalIDString = 9936F32F1F5F2E5B0010BF04;
259
+			remoteInfo = "privatedata-tvOS";
260
+		};
261
+		66AE23221FE44628000AEC3F /* PBXContainerItemProxy */ = {
262
+			isa = PBXContainerItemProxy;
263
+			containerPortal = 14B7951690F04106A4A8E60E /* ReactNativePermissions.xcodeproj */;
264
+			proxyType = 2;
265
+			remoteGlobalIDString = 9D23B34F1C767B80008B4819;
266
+			remoteInfo = ReactNativePermissions;
267
+		};
268
+		66F16BED1FC608A800E71FEB /* PBXContainerItemProxy */ = {
269
+			isa = PBXContainerItemProxy;
270
+			containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */;
271
+			proxyType = 2;
272
+			remoteGlobalIDString = ADD01A681E09402E00F6D226;
273
+			remoteInfo = "RCTBlob-tvOS";
274
+		};
275
+		66F16BFF1FC608A800E71FEB /* PBXContainerItemProxy */ = {
276
+			isa = PBXContainerItemProxy;
277
+			containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
278
+			proxyType = 2;
279
+			remoteGlobalIDString = 3DBE0D001F3B181A0099AA32;
280
+			remoteInfo = fishhook;
281
+		};
282
+		66F16C011FC608A800E71FEB /* PBXContainerItemProxy */ = {
283
+			isa = PBXContainerItemProxy;
284
+			containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
285
+			proxyType = 2;
286
+			remoteGlobalIDString = 3DBE0D0D1F3B181C0099AA32;
287
+			remoteInfo = "fishhook-tvOS";
288
+		};
219 289
 		78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
220 290
 			isa = PBXContainerItemProxy;
221 291
 			containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
@@ -259,10 +329,9 @@
259 329
 		13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Example/Info.plist; sourceTree = "<group>"; };
260 330
 		13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Example/main.m; sourceTree = "<group>"; };
261 331
 		146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
262
-		1CB53DB705894AAA8CB22783 /* ReactNativePermissions.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = ReactNativePermissions.xcodeproj; path = "../node_modules/react-native-permissions/ReactNativePermissions.xcodeproj"; sourceTree = "<group>"; };
332
+		14B7951690F04106A4A8E60E /* ReactNativePermissions.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = ReactNativePermissions.xcodeproj; path = "../node_modules/react-native-permissions/ios/ReactNativePermissions.xcodeproj"; sourceTree = "<group>"; };
263 333
 		2D02E47B1E0B4A5D006451C7 /* Example-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
264 334
 		2D02E4901E0B4A5D006451C7 /* Example-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Example-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
265
-		5DF4131A2930454297EF564B /* libReactNativePermissions.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libReactNativePermissions.a; sourceTree = "<group>"; };
266 335
 		5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = "<group>"; };
267 336
 		78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
268 337
 		832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
@@ -295,7 +364,7 @@
295 364
 				832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
296 365
 				00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
297 366
 				139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
298
-				6D05A8F55CC4482AACFFC932 /* libReactNativePermissions.a in Frameworks */,
367
+				66AE23241FE44648000AEC3F /* libReactNativePermissions.a in Frameworks */,
299 368
 			);
300 369
 			runOnlyForDeploymentPostprocessing = 0;
301 370
 		};
@@ -304,7 +373,7 @@
304 373
 			buildActionMask = 2147483647;
305 374
 			files = (
306 375
 				2D02E4C91E0B4AEC006451C7 /* libReact.a in Frameworks */,
307
-				2D02E4C21E0B4AEC006451C7 /* libRCTAnimation-tvOS.a in Frameworks */,
376
+				2D02E4C21E0B4AEC006451C7 /* libRCTAnimation.a in Frameworks */,
308 377
 				2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */,
309 378
 				2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */,
310 379
 				2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */,
@@ -397,6 +466,8 @@
397 466
 			children = (
398 467
 				139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
399 468
 				3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */,
469
+				66F16C001FC608A800E71FEB /* libfishhook.a */,
470
+				66F16C021FC608A800E71FEB /* libfishhook-tvOS.a */,
400 471
 			);
401 472
 			name = Products;
402 473
 			sourceTree = "<group>";
@@ -426,7 +497,12 @@
426 497
 				3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */,
427 498
 				3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */,
428 499
 				3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */,
429
-				3DAD3EA31DF850E9000B6D8A /* libReact-tvOS.a */,
500
+				661E35341FD3107F00C328EA /* libthird-party.a */,
501
+				661E35361FD3107F00C328EA /* libthird-party.a */,
502
+				661E35381FD3107F00C328EA /* libdouble-conversion.a */,
503
+				661E353A1FD3107F00C328EA /* libdouble-conversion.a */,
504
+				661E353C1FD3107F00C328EA /* libprivatedata.a */,
505
+				661E353E1FD3107F00C328EA /* libprivatedata-tvOS.a */,
430 506
 			);
431 507
 			name = Products;
432 508
 			sourceTree = "<group>";
@@ -435,11 +511,26 @@
435 511
 			isa = PBXGroup;
436 512
 			children = (
437 513
 				5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */,
438
-				5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */,
514
+				5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */,
439 515
 			);
440 516
 			name = Products;
441 517
 			sourceTree = "<group>";
442 518
 		};
519
+		66AE22FC1FE44628000AEC3F /* Products */ = {
520
+			isa = PBXGroup;
521
+			children = (
522
+				66AE23231FE44628000AEC3F /* libReactNativePermissions.a */,
523
+			);
524
+			name = Products;
525
+			sourceTree = "<group>";
526
+		};
527
+		66F16C081FC608C600E71FEB /* Frameworks */ = {
528
+			isa = PBXGroup;
529
+			children = (
530
+			);
531
+			name = Frameworks;
532
+			sourceTree = "<group>";
533
+		};
443 534
 		78C398B11ACF4ADC00677621 /* Products */ = {
444 535
 			isa = PBXGroup;
445 536
 			children = (
@@ -464,7 +555,7 @@
464 555
 				832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
465 556
 				00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
466 557
 				139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
467
-				1CB53DB705894AAA8CB22783 /* ReactNativePermissions.xcodeproj */,
558
+				14B7951690F04106A4A8E60E /* ReactNativePermissions.xcodeproj */,
468 559
 			);
469 560
 			name = Libraries;
470 561
 			sourceTree = "<group>";
@@ -485,6 +576,7 @@
485 576
 				832341AE1AAA6A7D00B99B32 /* Libraries */,
486 577
 				00E356EF1AD99517003FC87E /* ExampleTests */,
487 578
 				83CBBA001A601CBA00E9B192 /* Products */,
579
+				66F16C081FC608C600E71FEB /* Frameworks */,
488 580
 			);
489 581
 			indentWidth = 2;
490 582
 			sourceTree = "<group>";
@@ -506,6 +598,7 @@
506 598
 			isa = PBXGroup;
507 599
 			children = (
508 600
 				ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */,
601
+				66F16BEE1FC608A800E71FEB /* libRCTBlob-tvOS.a */,
509 602
 			);
510 603
 			name = Products;
511 604
 			sourceTree = "<group>";
@@ -591,16 +684,16 @@
591 684
 		83CBB9F71A601CBA00E9B192 /* Project object */ = {
592 685
 			isa = PBXProject;
593 686
 			attributes = {
594
-				LastUpgradeCheck = 820;
687
+				LastUpgradeCheck = 610;
595 688
 				ORGANIZATIONNAME = Facebook;
596 689
 				TargetAttributes = {
597 690
 					00E356ED1AD99517003FC87E = {
598 691
 						CreatedOnToolsVersion = 6.2;
599
-						DevelopmentTeam = 66SW7BQ2SM;
692
+						DevelopmentTeam = 745449BDR9;
600 693
 						TestTargetID = 13B07F861A680F5B00A75B9A;
601 694
 					};
602 695
 					13B07F861A680F5B00A75B9A = {
603
-						DevelopmentTeam = 66SW7BQ2SM;
696
+						DevelopmentTeam = 745449BDR9;
604 697
 						SystemCapabilities = {
605 698
 							com.apple.BackgroundModes = {
606 699
 								enabled = 1;
@@ -679,8 +772,8 @@
679 772
 					ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;
680 773
 				},
681 774
 				{
682
-					ProductGroup = 9D140C9F1F068EB400146F6C /* Products */;
683
-					ProjectRef = 1CB53DB705894AAA8CB22783 /* ReactNativePermissions.xcodeproj */;
775
+					ProductGroup = 66AE22FC1FE44628000AEC3F /* Products */;
776
+					ProjectRef = 14B7951690F04106A4A8E60E /* ReactNativePermissions.xcodeproj */;
684 777
 				},
685 778
 			);
686 779
 			projectRoot = "";
@@ -792,10 +885,10 @@
792 885
 			remoteRef = 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */;
793 886
 			sourceTree = BUILT_PRODUCTS_DIR;
794 887
 		};
795
-		3DAD3EA31DF850E9000B6D8A /* libReact-tvOS.a */ = {
888
+		3DAD3EA31DF850E9000B6D8A /* libReact.a */ = {
796 889
 			isa = PBXReferenceProxy;
797 890
 			fileType = archive.ar;
798
-			path = "libReact-tvOS.a";
891
+			path = libReact.a;
799 892
 			remoteRef = 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */;
800 893
 			sourceTree = BUILT_PRODUCTS_DIR;
801 894
 		};
@@ -848,13 +941,83 @@
848 941
 			remoteRef = 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */;
849 942
 			sourceTree = BUILT_PRODUCTS_DIR;
850 943
 		};
851
-		5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */ = {
944
+		5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */ = {
852 945
 			isa = PBXReferenceProxy;
853 946
 			fileType = archive.ar;
854
-			path = "libRCTAnimation-tvOS.a";
947
+			path = libRCTAnimation.a;
855 948
 			remoteRef = 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */;
856 949
 			sourceTree = BUILT_PRODUCTS_DIR;
857 950
 		};
951
+		661E35341FD3107F00C328EA /* libthird-party.a */ = {
952
+			isa = PBXReferenceProxy;
953
+			fileType = archive.ar;
954
+			path = "libthird-party.a";
955
+			remoteRef = 661E35331FD3107F00C328EA /* PBXContainerItemProxy */;
956
+			sourceTree = BUILT_PRODUCTS_DIR;
957
+		};
958
+		661E35361FD3107F00C328EA /* libthird-party.a */ = {
959
+			isa = PBXReferenceProxy;
960
+			fileType = archive.ar;
961
+			path = "libthird-party.a";
962
+			remoteRef = 661E35351FD3107F00C328EA /* PBXContainerItemProxy */;
963
+			sourceTree = BUILT_PRODUCTS_DIR;
964
+		};
965
+		661E35381FD3107F00C328EA /* libdouble-conversion.a */ = {
966
+			isa = PBXReferenceProxy;
967
+			fileType = archive.ar;
968
+			path = "libdouble-conversion.a";
969
+			remoteRef = 661E35371FD3107F00C328EA /* PBXContainerItemProxy */;
970
+			sourceTree = BUILT_PRODUCTS_DIR;
971
+		};
972
+		661E353A1FD3107F00C328EA /* libdouble-conversion.a */ = {
973
+			isa = PBXReferenceProxy;
974
+			fileType = archive.ar;
975
+			path = "libdouble-conversion.a";
976
+			remoteRef = 661E35391FD3107F00C328EA /* PBXContainerItemProxy */;
977
+			sourceTree = BUILT_PRODUCTS_DIR;
978
+		};
979
+		661E353C1FD3107F00C328EA /* libprivatedata.a */ = {
980
+			isa = PBXReferenceProxy;
981
+			fileType = archive.ar;
982
+			path = libprivatedata.a;
983
+			remoteRef = 661E353B1FD3107F00C328EA /* PBXContainerItemProxy */;
984
+			sourceTree = BUILT_PRODUCTS_DIR;
985
+		};
986
+		661E353E1FD3107F00C328EA /* libprivatedata-tvOS.a */ = {
987
+			isa = PBXReferenceProxy;
988
+			fileType = archive.ar;
989
+			path = "libprivatedata-tvOS.a";
990
+			remoteRef = 661E353D1FD3107F00C328EA /* PBXContainerItemProxy */;
991
+			sourceTree = BUILT_PRODUCTS_DIR;
992
+		};
993
+		66AE23231FE44628000AEC3F /* libReactNativePermissions.a */ = {
994
+			isa = PBXReferenceProxy;
995
+			fileType = archive.ar;
996
+			path = libReactNativePermissions.a;
997
+			remoteRef = 66AE23221FE44628000AEC3F /* PBXContainerItemProxy */;
998
+			sourceTree = BUILT_PRODUCTS_DIR;
999
+		};
1000
+		66F16BEE1FC608A800E71FEB /* libRCTBlob-tvOS.a */ = {
1001
+			isa = PBXReferenceProxy;
1002
+			fileType = archive.ar;
1003
+			path = "libRCTBlob-tvOS.a";
1004
+			remoteRef = 66F16BED1FC608A800E71FEB /* PBXContainerItemProxy */;
1005
+			sourceTree = BUILT_PRODUCTS_DIR;
1006
+		};
1007
+		66F16C001FC608A800E71FEB /* libfishhook.a */ = {
1008
+			isa = PBXReferenceProxy;
1009
+			fileType = archive.ar;
1010
+			path = libfishhook.a;
1011
+			remoteRef = 66F16BFF1FC608A800E71FEB /* PBXContainerItemProxy */;
1012
+			sourceTree = BUILT_PRODUCTS_DIR;
1013
+		};
1014
+		66F16C021FC608A800E71FEB /* libfishhook-tvOS.a */ = {
1015
+			isa = PBXReferenceProxy;
1016
+			fileType = archive.ar;
1017
+			path = "libfishhook-tvOS.a";
1018
+			remoteRef = 66F16C011FC608A800E71FEB /* PBXContainerItemProxy */;
1019
+			sourceTree = BUILT_PRODUCTS_DIR;
1020
+		};
858 1021
 		78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
859 1022
 			isa = PBXReferenceProxy;
860 1023
 			fileType = archive.ar;
@@ -1010,19 +1173,22 @@
1010 1173
 			isa = XCBuildConfiguration;
1011 1174
 			buildSettings = {
1012 1175
 				BUNDLE_LOADER = "$(TEST_HOST)";
1013
-				DEVELOPMENT_TEAM = 66SW7BQ2SM;
1176
+				DEVELOPMENT_TEAM = 745449BDR9;
1014 1177
 				GCC_PREPROCESSOR_DEFINITIONS = (
1015 1178
 					"DEBUG=1",
1016 1179
 					"$(inherited)",
1017 1180
 				);
1181
+				HEADER_SEARCH_PATHS = (
1182
+					"$(inherited)",
1183
+					"$(SRCROOT)/../node_modules/react-native-permissions",
1184
+					"$(SRCROOT)/../node_modules/react-native-permissions/ios/**",
1185
+				);
1018 1186
 				INFOPLIST_FILE = ExampleTests/Info.plist;
1019 1187
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
1020 1188
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
1021 1189
 				LIBRARY_SEARCH_PATHS = (
1022 1190
 					"$(inherited)",
1023 1191
 					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1024
-					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1025
-					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1026 1192
 				);
1027 1193
 				OTHER_LDFLAGS = (
1028 1194
 					"-ObjC",
@@ -1038,15 +1204,18 @@
1038 1204
 			buildSettings = {
1039 1205
 				BUNDLE_LOADER = "$(TEST_HOST)";
1040 1206
 				COPY_PHASE_STRIP = NO;
1041
-				DEVELOPMENT_TEAM = 66SW7BQ2SM;
1207
+				DEVELOPMENT_TEAM = 745449BDR9;
1208
+				HEADER_SEARCH_PATHS = (
1209
+					"$(inherited)",
1210
+					"$(SRCROOT)/../node_modules/react-native-permissions",
1211
+					"$(SRCROOT)/../node_modules/react-native-permissions/ios/**",
1212
+				);
1042 1213
 				INFOPLIST_FILE = ExampleTests/Info.plist;
1043 1214
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
1044 1215
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
1045 1216
 				LIBRARY_SEARCH_PATHS = (
1046 1217
 					"$(inherited)",
1047 1218
 					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1048
-					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1049
-					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1050 1219
 				);
1051 1220
 				OTHER_LDFLAGS = (
1052 1221
 					"-ObjC",
@@ -1063,7 +1232,12 @@
1063 1232
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
1064 1233
 				CURRENT_PROJECT_VERSION = 1;
1065 1234
 				DEAD_CODE_STRIPPING = NO;
1066
-				DEVELOPMENT_TEAM = 66SW7BQ2SM;
1235
+				DEVELOPMENT_TEAM = 745449BDR9;
1236
+				HEADER_SEARCH_PATHS = (
1237
+					"$(inherited)",
1238
+					"$(SRCROOT)/../node_modules/react-native-permissions",
1239
+					"$(SRCROOT)/../node_modules/react-native-permissions/ios/**",
1240
+				);
1067 1241
 				INFOPLIST_FILE = Example/Info.plist;
1068 1242
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
1069 1243
 				OTHER_LDFLAGS = (
@@ -1071,6 +1245,7 @@
1071 1245
 					"-ObjC",
1072 1246
 					"-lc++",
1073 1247
 				);
1248
+				PRODUCT_BUNDLE_IDENTIFIER = com.react.permissions;
1074 1249
 				PRODUCT_NAME = Example;
1075 1250
 				VERSIONING_SYSTEM = "apple-generic";
1076 1251
 			};
@@ -1081,7 +1256,12 @@
1081 1256
 			buildSettings = {
1082 1257
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
1083 1258
 				CURRENT_PROJECT_VERSION = 1;
1084
-				DEVELOPMENT_TEAM = 66SW7BQ2SM;
1259
+				DEVELOPMENT_TEAM = 745449BDR9;
1260
+				HEADER_SEARCH_PATHS = (
1261
+					"$(inherited)",
1262
+					"$(SRCROOT)/../node_modules/react-native-permissions",
1263
+					"$(SRCROOT)/../node_modules/react-native-permissions/ios/**",
1264
+				);
1085 1265
 				INFOPLIST_FILE = Example/Info.plist;
1086 1266
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
1087 1267
 				OTHER_LDFLAGS = (
@@ -1089,6 +1269,7 @@
1089 1269
 					"-ObjC",
1090 1270
 					"-lc++",
1091 1271
 				);
1272
+				PRODUCT_BUNDLE_IDENTIFIER = com.react.permissions;
1092 1273
 				PRODUCT_NAME = Example;
1093 1274
 				VERSIONING_SYSTEM = "apple-generic";
1094 1275
 			};
@@ -1106,13 +1287,16 @@
1106 1287
 				DEBUG_INFORMATION_FORMAT = dwarf;
1107 1288
 				ENABLE_TESTABILITY = YES;
1108 1289
 				GCC_NO_COMMON_BLOCKS = YES;
1290
+				HEADER_SEARCH_PATHS = (
1291
+					"$(inherited)",
1292
+					"$(SRCROOT)/../node_modules/react-native-permissions",
1293
+					"$(SRCROOT)/../node_modules/react-native-permissions/ios/**",
1294
+				);
1109 1295
 				INFOPLIST_FILE = "Example-tvOS/Info.plist";
1110 1296
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
1111 1297
 				LIBRARY_SEARCH_PATHS = (
1112 1298
 					"$(inherited)",
1113 1299
 					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1114
-					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1115
-					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1116 1300
 				);
1117 1301
 				OTHER_LDFLAGS = (
1118 1302
 					"-ObjC",
@@ -1138,13 +1322,16 @@
1138 1322
 				COPY_PHASE_STRIP = NO;
1139 1323
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
1140 1324
 				GCC_NO_COMMON_BLOCKS = YES;
1325
+				HEADER_SEARCH_PATHS = (
1326
+					"$(inherited)",
1327
+					"$(SRCROOT)/../node_modules/react-native-permissions",
1328
+					"$(SRCROOT)/../node_modules/react-native-permissions/ios/**",
1329
+				);
1141 1330
 				INFOPLIST_FILE = "Example-tvOS/Info.plist";
1142 1331
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
1143 1332
 				LIBRARY_SEARCH_PATHS = (
1144 1333
 					"$(inherited)",
1145 1334
 					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1146
-					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1147
-					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1148 1335
 				);
1149 1336
 				OTHER_LDFLAGS = (
1150 1337
 					"-ObjC",
@@ -1174,8 +1361,6 @@
1174 1361
 				LIBRARY_SEARCH_PATHS = (
1175 1362
 					"$(inherited)",
1176 1363
 					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1177
-					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1178
-					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1179 1364
 				);
1180 1365
 				PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.Example-tvOSTests";
1181 1366
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1201,8 +1386,6 @@
1201 1386
 				LIBRARY_SEARCH_PATHS = (
1202 1387
 					"$(inherited)",
1203 1388
 					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1204
-					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1205
-					"\"$(SRCROOT)/$(TARGET_NAME)\"",
1206 1389
 				);
1207 1390
 				PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.Example-tvOSTests";
1208 1391
 				PRODUCT_NAME = "$(TARGET_NAME)";

Example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example-tvOS.xcscheme → example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example-tvOS.xcscheme Datei anzeigen


Example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme → example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme Datei anzeigen

@@ -1,6 +1,6 @@
1 1
 <?xml version="1.0" encoding="UTF-8"?>
2 2
 <Scheme
3
-   LastUpgradeVersion = "0820"
3
+   LastUpgradeVersion = "0620"
4 4
    version = "1.3">
5 5
    <BuildAction
6 6
       parallelizeBuildables = "NO"

Example/ios/Example/AppDelegate.h → example/ios/Example/AppDelegate.h Datei anzeigen


Example/ios/Example/AppDelegate.m → example/ios/Example/AppDelegate.m Datei anzeigen

@@ -18,7 +18,7 @@
18 18
 {
19 19
   NSURL *jsCodeLocation;
20 20
 
21
-  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
21
+  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
22 22
 
23 23
   RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
24 24
                                                       moduleName:@"Example"

Example/ios/Example/Base.lproj/LaunchScreen.xib → example/ios/Example/Base.lproj/LaunchScreen.xib Datei anzeigen


+ 38
- 0
example/ios/Example/Images.xcassets/AppIcon.appiconset/Contents.json Datei anzeigen

@@ -0,0 +1,38 @@
1
+{
2
+  "images": [
3
+    {
4
+      "idiom": "iphone",
5
+      "size": "29x29",
6
+      "scale": "2x"
7
+    },
8
+    {
9
+      "idiom": "iphone",
10
+      "size": "29x29",
11
+      "scale": "3x"
12
+    },
13
+    {
14
+      "idiom": "iphone",
15
+      "size": "40x40",
16
+      "scale": "2x"
17
+    },
18
+    {
19
+      "idiom": "iphone",
20
+      "size": "40x40",
21
+      "scale": "3x"
22
+    },
23
+    {
24
+      "idiom": "iphone",
25
+      "size": "60x60",
26
+      "scale": "2x"
27
+    },
28
+    {
29
+      "idiom": "iphone",
30
+      "size": "60x60",
31
+      "scale": "3x"
32
+    }
33
+  ],
34
+  "info": {
35
+    "version": 1,
36
+    "author": "xcode"
37
+  }
38
+}

+ 6
- 0
example/ios/Example/Images.xcassets/Contents.json Datei anzeigen

@@ -0,0 +1,6 @@
1
+{
2
+  "info": {
3
+    "version": 1,
4
+    "author": "xcode"
5
+  }
6
+}

Example/ios/Example/Info.plist → example/ios/Example/Info.plist Datei anzeigen

@@ -4,10 +4,14 @@
4 4
 <dict>
5 5
 	<key>CFBundleDevelopmentRegion</key>
6 6
 	<string>en</string>
7
+	<key>CFBundleDisplayName</key>
8
+	<string>Example</string>
7 9
 	<key>CFBundleExecutable</key>
8 10
 	<string>$(EXECUTABLE_NAME)</string>
9 11
 	<key>CFBundleIdentifier</key>
10
-	<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
12
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13
+	<key>CFBundleInfoDictionaryVersion</key>
14
+	<string>6.0</string>
11 15
 	<key>CFBundleName</key>
12 16
 	<string>$(PRODUCT_NAME)</string>
13 17
 	<key>CFBundlePackageType</key>

Example/ios/Example/main.m → example/ios/Example/main.m Datei anzeigen


Example/ios/ExampleTests/ExampleTests.m → example/ios/ExampleTests/ExampleTests.m Datei anzeigen


Example/ios/ExampleTests/Info.plist → example/ios/ExampleTests/Info.plist Datei anzeigen


+ 23
- 0
example/package.json Datei anzeigen

@@ -0,0 +1,23 @@
1
+{
2
+  "name": "Example",
3
+  "version": "0.0.1",
4
+  "private": true,
5
+  "scripts": {
6
+    "start": "node node_modules/react-native/local-cli/cli.js start",
7
+    "test": "jest"
8
+  },
9
+  "dependencies": {
10
+    "react": "16.0.0",
11
+    "react-native": "0.50.3",
12
+    "react-native-permissions": "../"
13
+  },
14
+  "devDependencies": {
15
+    "babel-jest": "21.2.0",
16
+    "babel-preset-react-native": "4.0.0",
17
+    "jest": "21.2.1",
18
+    "react-test-renderer": "16.0.0"
19
+  },
20
+  "jest": {
21
+    "preset": "react-native"
22
+  }
23
+}

+ 0
- 91
index.android.js Datei anzeigen

@@ -1,91 +0,0 @@
1
-'use strict';
2
-
3
-const ReactNative = require('react-native')
4
-const RNPermissions = ReactNative.PermissionsAndroid;
5
-const AsyncStorage = ReactNative.AsyncStorage
6
-
7
-const RNPTypes = {
8
-	location: RNPermissions.PERMISSIONS.ACCESS_FINE_LOCATION,
9
-	camera: RNPermissions.PERMISSIONS.CAMERA,
10
-	microphone: RNPermissions.PERMISSIONS.RECORD_AUDIO,
11
-	contacts: RNPermissions.PERMISSIONS.READ_CONTACTS,
12
-	event: RNPermissions.PERMISSIONS.READ_CALENDAR,
13
-	storage: RNPermissions.PERMISSIONS.READ_EXTERNAL_STORAGE,
14
-	photo: RNPermissions.PERMISSIONS.READ_EXTERNAL_STORAGE,
15
-	callPhone: RNPermissions.PERMISSIONS.CALL_PHONE,
16
-	readSms: RNPermissions.PERMISSIONS.READ_SMS,
17
-	receiveSms: RNPermissions.PERMISSIONS.RECEIVE_SMS,
18
-}
19
-
20
-const RESULTS = {
21
-	[ RNPermissions.RESULTS.GRANTED ]: 'authorized',
22
-	[ RNPermissions.RESULTS.DENIED ]: 'denied',
23
-	[ RNPermissions.RESULTS.NEVER_ASK_AGAIN ]: 'restricted',
24
-}
25
-
26
-const STORAGE_KEY = '@RNPermissions:didAskPermission:'
27
-
28
-const setDidAskOnce = p => AsyncStorage.setItem(STORAGE_KEY + p, 'true')
29
-const getDidAskOnce = p =>  AsyncStorage.getItem(STORAGE_KEY + p).then(res => !!res)
30
-
31
-class ReactNativePermissions {
32
-	canOpenSettings() {
33
-		return false
34
-	}
35
-
36
-	openSettings() {
37
-		return Promise.reject('\'openSettings\' is Depricated on android')
38
-	}
39
-
40
-	getTypes() {
41
-		return Object.keys(RNPTypes);
42
-	}
43
-
44
-	check(permission) {
45
-		const androidPermission = RNPTypes[permission]
46
-  	if (!androidPermission) return Promise.reject(`ReactNativePermissions: ${permission} is not a valid permission type on Android`);
47
-		
48
-		const shouldShowRationale = ReactNative.NativeModules.PermissionsAndroid.shouldShowRequestPermissionRationale;
49
-
50
-		return RNPermissions.check(androidPermission)
51
-			.then(isAuthorized => {
52
-				if (isAuthorized) return 'authorized'
53
-
54
-				return getDidAskOnce(permission)
55
-					.then(didAsk => {
56
-						if (didAsk) {
57
-							return shouldShowRationale(androidPermission)
58
-								.then(shouldShow => shouldShow ? 'denied' : 'restricted')
59
-						}
60
-						return 'undetermined'
61
-					})
62
-			})
63
-	}
64
-
65
-
66
-	request(permission) {
67
-		const androidPermission = RNPTypes[permission]
68
-  	if (!androidPermission) return Promise.reject(`ReactNativePermissions: ${permission} is not a valid permission type on Android`);
69
-
70
-
71
-		return RNPermissions.request(androidPermission)
72
-			.then(res => {
73
-				// RNPermissions.request() to native module resolves to boolean
74
-				// rather than string if running on OS version prior to Android M 
75
-				if (typeof res === 'boolean') return res ? 'authorized' : 'denied';
76
-				return setDidAskOnce(permission)
77
-					.then(() => RESULTS[res])
78
-			});
79
-	}
80
-
81
-	checkMultiple(permissions) {
82
-		return Promise.all(permissions.map(this.check.bind(this)))
83
-			.then(res => res.reduce((pre, cur, i) => {
84
-				var name = permissions[i]
85
-				pre[name] = cur
86
-				return pre
87
-			}, {}))
88
-	}
89
-}
90
-
91
-module.exports = new ReactNativePermissions()

+ 0
- 70
index.ios.js Datei anzeigen

@@ -1,70 +0,0 @@
1
-'use strict';
2
-
3
-const ReactNative = require('react-native');
4
-const RNPermissions = ReactNative.NativeModules.ReactNativePermissions;
5
-
6
-const RNPTypes = [
7
-	'location',
8
-	'camera',
9
-	'microphone',
10
-	'photo',
11
-	'contacts',
12
-	'event',
13
-	'reminder',
14
-	'bluetooth',
15
-	'notification',
16
-	'backgroundRefresh',
17
-	'speechRecognition',
18
-]
19
-
20
-const DEFAULTS = {
21
-	'location' : 'whenInUse',
22
-	'notification': ['alert', 'badge', 'sound'],
23
-}
24
-
25
-class ReactNativePermissions {
26
-	canOpenSettings() {
27
-		return RNPermissions.canOpenSettings()
28
-	}
29
-
30
-	openSettings() {
31
-		return RNPermissions.openSettings()
32
-	}
33
-
34
-	getTypes() {
35
-		return RNPTypes;
36
-	}
37
-
38
-	check(permission, type) {
39
-  	if (!RNPTypes.includes(permission)) {
40
-			return Promise.reject(`ReactNativePermissions: ${permission} is not a valid permission type on iOS`);
41
-		}
42
-		
43
-		return RNPermissions.getPermissionStatus(permission, type);
44
-	}
45
-
46
-	request(permission, type) {
47
-		if (!RNPTypes.includes(permission)) {
48
-			return Promise.reject(`ReactNativePermissions: ${permission} is not a valid permission type on iOS`);
49
-		}
50
-
51
-		if (permission == 'backgroundRefresh') {
52
-			return Promise.reject('ReactNativePermissions: You cannot request backgroundRefresh')
53
-		}
54
-
55
-		type = type || DEFAULTS[permission]
56
-
57
-		return RNPermissions.requestPermission(permission, type)
58
-	}
59
-
60
-	checkMultiple(permissions) {
61
-		return Promise.all(permissions.map(permission => this.check(permission)))
62
-			.then(res => res.reduce((pre, cur, i) => {
63
-				var name = permissions[i]
64
-				pre[name] = cur
65
-				return pre
66
-			}, {}))
67
-	}
68
-}
69
-
70
-module.exports = new ReactNativePermissions()

+ 4
- 0
index.js Datei anzeigen

@@ -0,0 +1,4 @@
1
+// @flow
2
+
3
+import Permissions from './lib/permissions'
4
+export default Permissions

permissions/RNPAudioVideo.h → ios/Permissions/RNPAudioVideo.h Datei anzeigen


permissions/RNPAudioVideo.m → ios/Permissions/RNPAudioVideo.m Datei anzeigen


permissions/RNPBackgroundRefresh.h → ios/Permissions/RNPBackgroundRefresh.h Datei anzeigen


permissions/RNPBackgroundRefresh.m → ios/Permissions/RNPBackgroundRefresh.m Datei anzeigen


permissions/RNPBluetooth.h → ios/Permissions/RNPBluetooth.h Datei anzeigen


permissions/RNPBluetooth.m → ios/Permissions/RNPBluetooth.m Datei anzeigen


permissions/RNPContacts.h → ios/Permissions/RNPContacts.h Datei anzeigen


permissions/RNPContacts.m → ios/Permissions/RNPContacts.m Datei anzeigen


permissions/RNPEvent.h → ios/Permissions/RNPEvent.h Datei anzeigen


permissions/RNPEvent.m → ios/Permissions/RNPEvent.m Datei anzeigen


permissions/RNPLocation.h → ios/Permissions/RNPLocation.h Datei anzeigen


permissions/RNPLocation.m → ios/Permissions/RNPLocation.m Datei anzeigen


permissions/RNPNotification.h → ios/Permissions/RNPNotification.h Datei anzeigen


permissions/RNPNotification.m → ios/Permissions/RNPNotification.m Datei anzeigen


permissions/RNPPhoto.h → ios/Permissions/RNPPhoto.h Datei anzeigen


permissions/RNPPhoto.m → ios/Permissions/RNPPhoto.m Datei anzeigen


permissions/RNPSpeechRecognition.h → ios/Permissions/RNPSpeechRecognition.h Datei anzeigen


permissions/RNPSpeechRecognition.m → ios/Permissions/RNPSpeechRecognition.m Datei anzeigen


RCTConvert+RNPStatus.h → ios/RCTConvert+RNPStatus.h Datei anzeigen


RCTConvert+RNPStatus.m → ios/RCTConvert+RNPStatus.m Datei anzeigen

@@ -10,7 +10,6 @@
10 10
 
11 11
 @implementation RCTConvert (RNPStatus)
12 12
 
13
-
14 13
 RCT_ENUM_CONVERTER(RNPType, (@{ @"location" : @(RNPTypeLocation),
15 14
                                 @"camera" : @(RNPTypeCamera),
16 15
                                 @"microphone" : @(RNPTypeMicrophone),

ReactNativePermissions.h → ios/ReactNativePermissions.h Datei anzeigen

@@ -16,5 +16,4 @@
16 16
 
17 17
 @interface ReactNativePermissions : NSObject <RCTBridgeModule>
18 18
 
19
-
20 19
 @end

ReactNativePermissions.m → ios/ReactNativePermissions.m Datei anzeigen

@@ -18,7 +18,6 @@
18 18
   #import "RCTBridge.h"
19 19
 #endif
20 20
 
21
-
22 21
 #if __has_include(<React/RCTConvert.h>)
23 22
   #import <React/RCTConvert.h>
24 23
 #elif __has_include("React/RCTConvert.h")
@@ -58,6 +57,11 @@
58 57
 RCT_EXPORT_MODULE();
59 58
 @synthesize bridge = _bridge;
60 59
 
60
++ (BOOL)requiresMainQueueSetup
61
+{
62
+    return YES;
63
+}
64
+
61 65
 #pragma mark Initialization
62 66
 
63 67
 - (instancetype)init

ReactNativePermissions.xcodeproj/project.pbxproj → ios/ReactNativePermissions.xcodeproj/project.pbxproj Datei anzeigen

@@ -7,18 +7,18 @@
7 7
 	objects = {
8 8
 
9 9
 /* Begin PBXBuildFile section */
10
-		281CD5911E26B0C8003A72B2 /* RNPSpeechRecognition.m in Sources */ = {isa = PBXBuildFile; fileRef = 281CD5901E26B0C7003A72B2 /* RNPSpeechRecognition.m */; };
11 10
 		483383101FAB6115005D5777 /* RNPMotion.m in Sources */ = {isa = PBXBuildFile; fileRef = 4833830E1FAB6114005D5777 /* RNPMotion.m */; };
12
-		9D46283E1D34719100346A5B /* RNPAudioVideo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D46282F1D34719100346A5B /* RNPAudioVideo.m */; };
13
-		9D46283F1D34719100346A5B /* RNPBackgroundRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D4628311D34719100346A5B /* RNPBackgroundRefresh.m */; };
14
-		9D4628401D34719100346A5B /* RNPBluetooth.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D4628331D34719100346A5B /* RNPBluetooth.m */; };
15
-		9D4628411D34719100346A5B /* RNPContacts.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D4628351D34719100346A5B /* RNPContacts.m */; };
16
-		9D4628421D34719100346A5B /* RNPEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D4628371D34719100346A5B /* RNPEvent.m */; };
17
-		9D4628431D34719100346A5B /* RNPLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D4628391D34719100346A5B /* RNPLocation.m */; };
18
-		9D4628441D34719100346A5B /* RNPNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D46283B1D34719100346A5B /* RNPNotification.m */; };
19
-		9D4628451D34719100346A5B /* RNPPhoto.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D46283D1D34719100346A5B /* RNPPhoto.m */; };
20
-		9DE8D2821CA3188D009CE8CC /* ReactNativePermissions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DE8D2811CA3188D009CE8CC /* ReactNativePermissions.m */; };
21
-		9DE8D28B1CA31E95009CE8CC /* RCTConvert+RNPStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DE8D28A1CA31E95009CE8CC /* RCTConvert+RNPStatus.m */; };
11
+		669581F71FE4416B008596CD /* RCTConvert+RNPStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 669581F41FE4416B008596CD /* RCTConvert+RNPStatus.m */; };
12
+		669581F81FE4416B008596CD /* ReactNativePermissions.m in Sources */ = {isa = PBXBuildFile; fileRef = 669581F51FE4416B008596CD /* ReactNativePermissions.m */; };
13
+		6695820D1FE441A8008596CD /* RNPSpeechRecognition.m in Sources */ = {isa = PBXBuildFile; fileRef = 669581FD1FE441A7008596CD /* RNPSpeechRecognition.m */; };
14
+		6695820E1FE441A8008596CD /* RNPLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 669581FE1FE441A7008596CD /* RNPLocation.m */; };
15
+		6695820F1FE441A8008596CD /* RNPBluetooth.m in Sources */ = {isa = PBXBuildFile; fileRef = 669581FF1FE441A7008596CD /* RNPBluetooth.m */; };
16
+		669582101FE441A8008596CD /* RNPBackgroundRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 669582001FE441A7008596CD /* RNPBackgroundRefresh.m */; };
17
+		669582111FE441A8008596CD /* RNPNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 669582011FE441A7008596CD /* RNPNotification.m */; };
18
+		669582121FE441A8008596CD /* RNPPhoto.m in Sources */ = {isa = PBXBuildFile; fileRef = 669582031FE441A7008596CD /* RNPPhoto.m */; };
19
+		669582131FE441A8008596CD /* RNPAudioVideo.m in Sources */ = {isa = PBXBuildFile; fileRef = 669582071FE441A7008596CD /* RNPAudioVideo.m */; };
20
+		669582141FE441A8008596CD /* RNPContacts.m in Sources */ = {isa = PBXBuildFile; fileRef = 669582081FE441A8008596CD /* RNPContacts.m */; };
21
+		669582151FE441A8008596CD /* RNPEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 6695820A1FE441A8008596CD /* RNPEvent.m */; };
22 22
 /* End PBXBuildFile section */
23 23
 
24 24
 /* Begin PBXCopyFilesBuildPhase section */
@@ -34,31 +34,31 @@
34 34
 /* End PBXCopyFilesBuildPhase section */
35 35
 
36 36
 /* Begin PBXFileReference section */
37
-		281CD5901E26B0C7003A72B2 /* RNPSpeechRecognition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPSpeechRecognition.m; path = permissions/RNPSpeechRecognition.m; sourceTree = SOURCE_ROOT; };
38
-		281CD5921E26B266003A72B2 /* RNPSpeechRecognition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPSpeechRecognition.h; path = permissions/RNPSpeechRecognition.h; sourceTree = SOURCE_ROOT; };
39 37
 		4833830E1FAB6114005D5777 /* RNPMotion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPMotion.m; path = permissions/RNPMotion.m; sourceTree = SOURCE_ROOT; };
40 38
 		4833830F1FAB6115005D5777 /* RNPMotion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPMotion.h; path = permissions/RNPMotion.h; sourceTree = SOURCE_ROOT; };
39
+		669581F31FE4416B008596CD /* ReactNativePermissions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReactNativePermissions.h; sourceTree = "<group>"; };
40
+		669581F41FE4416B008596CD /* RCTConvert+RNPStatus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+RNPStatus.m"; sourceTree = "<group>"; };
41
+		669581F51FE4416B008596CD /* ReactNativePermissions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReactNativePermissions.m; sourceTree = "<group>"; };
42
+		669581F61FE4416B008596CD /* RCTConvert+RNPStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+RNPStatus.h"; sourceTree = "<group>"; };
43
+		669581FB1FE441A7008596CD /* RNPContacts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPContacts.h; sourceTree = "<group>"; };
44
+		669581FC1FE441A7008596CD /* RNPPhoto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPPhoto.h; sourceTree = "<group>"; };
45
+		669581FD1FE441A7008596CD /* RNPSpeechRecognition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPSpeechRecognition.m; sourceTree = "<group>"; };
46
+		669581FE1FE441A7008596CD /* RNPLocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPLocation.m; sourceTree = "<group>"; };
47
+		669581FF1FE441A7008596CD /* RNPBluetooth.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPBluetooth.m; sourceTree = "<group>"; };
48
+		669582001FE441A7008596CD /* RNPBackgroundRefresh.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPBackgroundRefresh.m; sourceTree = "<group>"; };
49
+		669582011FE441A7008596CD /* RNPNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPNotification.m; sourceTree = "<group>"; };
50
+		669582021FE441A7008596CD /* RNPLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPLocation.h; sourceTree = "<group>"; };
51
+		669582031FE441A7008596CD /* RNPPhoto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPPhoto.m; sourceTree = "<group>"; };
52
+		669582041FE441A7008596CD /* RNPAudioVideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPAudioVideo.h; sourceTree = "<group>"; };
53
+		669582051FE441A7008596CD /* RNPBackgroundRefresh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPBackgroundRefresh.h; sourceTree = "<group>"; };
54
+		669582061FE441A7008596CD /* RNPEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPEvent.h; sourceTree = "<group>"; };
55
+		669582071FE441A7008596CD /* RNPAudioVideo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPAudioVideo.m; sourceTree = "<group>"; };
56
+		669582081FE441A8008596CD /* RNPContacts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPContacts.m; sourceTree = "<group>"; };
57
+		669582091FE441A8008596CD /* RNPBluetooth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPBluetooth.h; sourceTree = "<group>"; };
58
+		6695820A1FE441A8008596CD /* RNPEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPEvent.m; sourceTree = "<group>"; };
59
+		6695820B1FE441A8008596CD /* RNPSpeechRecognition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPSpeechRecognition.h; sourceTree = "<group>"; };
60
+		6695820C1FE441A8008596CD /* RNPNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPNotification.h; sourceTree = "<group>"; };
41 61
 		9D23B34F1C767B80008B4819 /* libReactNativePermissions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactNativePermissions.a; sourceTree = BUILT_PRODUCTS_DIR; };
42
-		9D46282E1D34719100346A5B /* RNPAudioVideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPAudioVideo.h; path = permissions/RNPAudioVideo.h; sourceTree = SOURCE_ROOT; };
43
-		9D46282F1D34719100346A5B /* RNPAudioVideo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPAudioVideo.m; path = permissions/RNPAudioVideo.m; sourceTree = SOURCE_ROOT; };
44
-		9D4628301D34719100346A5B /* RNPBackgroundRefresh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPBackgroundRefresh.h; path = permissions/RNPBackgroundRefresh.h; sourceTree = SOURCE_ROOT; };
45
-		9D4628311D34719100346A5B /* RNPBackgroundRefresh.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPBackgroundRefresh.m; path = permissions/RNPBackgroundRefresh.m; sourceTree = SOURCE_ROOT; };
46
-		9D4628321D34719100346A5B /* RNPBluetooth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPBluetooth.h; path = permissions/RNPBluetooth.h; sourceTree = SOURCE_ROOT; };
47
-		9D4628331D34719100346A5B /* RNPBluetooth.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPBluetooth.m; path = permissions/RNPBluetooth.m; sourceTree = SOURCE_ROOT; };
48
-		9D4628341D34719100346A5B /* RNPContacts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPContacts.h; path = permissions/RNPContacts.h; sourceTree = SOURCE_ROOT; };
49
-		9D4628351D34719100346A5B /* RNPContacts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPContacts.m; path = permissions/RNPContacts.m; sourceTree = SOURCE_ROOT; };
50
-		9D4628361D34719100346A5B /* RNPEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPEvent.h; path = permissions/RNPEvent.h; sourceTree = SOURCE_ROOT; };
51
-		9D4628371D34719100346A5B /* RNPEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPEvent.m; path = permissions/RNPEvent.m; sourceTree = SOURCE_ROOT; };
52
-		9D4628381D34719100346A5B /* RNPLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPLocation.h; path = permissions/RNPLocation.h; sourceTree = SOURCE_ROOT; };
53
-		9D4628391D34719100346A5B /* RNPLocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPLocation.m; path = permissions/RNPLocation.m; sourceTree = SOURCE_ROOT; };
54
-		9D46283A1D34719100346A5B /* RNPNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPNotification.h; path = permissions/RNPNotification.h; sourceTree = SOURCE_ROOT; };
55
-		9D46283B1D34719100346A5B /* RNPNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPNotification.m; path = permissions/RNPNotification.m; sourceTree = SOURCE_ROOT; };
56
-		9D46283C1D34719100346A5B /* RNPPhoto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPPhoto.h; path = permissions/RNPPhoto.h; sourceTree = SOURCE_ROOT; };
57
-		9D46283D1D34719100346A5B /* RNPPhoto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPPhoto.m; path = permissions/RNPPhoto.m; sourceTree = SOURCE_ROOT; };
58
-		9DE8D2801CA31888009CE8CC /* ReactNativePermissions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactNativePermissions.h; sourceTree = SOURCE_ROOT; };
59
-		9DE8D2811CA3188D009CE8CC /* ReactNativePermissions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ReactNativePermissions.m; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
60
-		9DE8D2891CA31E95009CE8CC /* RCTConvert+RNPStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "RCTConvert+RNPStatus.h"; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
61
-		9DE8D28A1CA31E95009CE8CC /* RCTConvert+RNPStatus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = "RCTConvert+RNPStatus.m"; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
62 62
 /* End PBXFileReference section */
63 63
 
64 64
 /* Begin PBXFrameworksBuildPhase section */
@@ -72,35 +72,44 @@
72 72
 /* End PBXFrameworksBuildPhase section */
73 73
 
74 74
 /* Begin PBXGroup section */
75
-		9D23B3461C767B80008B4819 = {
75
+		669581FA1FE44191008596CD /* Permissions */ = {
76 76
 			isa = PBXGroup;
77 77
 			children = (
78
-				9D23B3511C767B80008B4819 /* ReactNativePermissions */,
79
-				9D23B3501C767B80008B4819 /* Products */,
78
+				669582041FE441A7008596CD /* RNPAudioVideo.h */,
79
+				669582071FE441A7008596CD /* RNPAudioVideo.m */,
80
+				669582051FE441A7008596CD /* RNPBackgroundRefresh.h */,
81
+				669582001FE441A7008596CD /* RNPBackgroundRefresh.m */,
82
+				669582091FE441A8008596CD /* RNPBluetooth.h */,
83
+				669581FF1FE441A7008596CD /* RNPBluetooth.m */,
84
+				669581FB1FE441A7008596CD /* RNPContacts.h */,
85
+				669582081FE441A8008596CD /* RNPContacts.m */,
86
+				669582061FE441A7008596CD /* RNPEvent.h */,
87
+				6695820A1FE441A8008596CD /* RNPEvent.m */,
88
+				669582021FE441A7008596CD /* RNPLocation.h */,
89
+				669581FE1FE441A7008596CD /* RNPLocation.m */,
90
+				6695820C1FE441A8008596CD /* RNPNotification.h */,
91
+				669582011FE441A7008596CD /* RNPNotification.m */,
92
+				669581FC1FE441A7008596CD /* RNPPhoto.h */,
93
+				669582031FE441A7008596CD /* RNPPhoto.m */,
94
+				6695820B1FE441A8008596CD /* RNPSpeechRecognition.h */,
95
+				669581FD1FE441A7008596CD /* RNPSpeechRecognition.m */,
80 96
 			);
97
+			path = Permissions;
81 98
 			sourceTree = "<group>";
82 99
 		};
83
-		9D23B3501C767B80008B4819 /* Products */ = {
84
-			isa = PBXGroup;
85
-			children = (
86
-				9D23B34F1C767B80008B4819 /* libReactNativePermissions.a */,
87
-			);
88
-			name = Products;
89
-			sourceTree = "<group>";
90
-		};
91
-		9D23B3511C767B80008B4819 /* ReactNativePermissions */ = {
100
+		9D23B3461C767B80008B4819 = {
92 101
 			isa = PBXGroup;
93 102
 			children = (
94
-				9D4628091D33C1EC00346A5B /* permissions */,
95
-				9DE8D2891CA31E95009CE8CC /* RCTConvert+RNPStatus.h */,
96
-				9DE8D28A1CA31E95009CE8CC /* RCTConvert+RNPStatus.m */,
97
-				9DE8D2801CA31888009CE8CC /* ReactNativePermissions.h */,
98
-				9DE8D2811CA3188D009CE8CC /* ReactNativePermissions.m */,
103
+				669581FA1FE44191008596CD /* Permissions */,
104
+				669581F61FE4416B008596CD /* RCTConvert+RNPStatus.h */,
105
+				669581F41FE4416B008596CD /* RCTConvert+RNPStatus.m */,
106
+				669581F31FE4416B008596CD /* ReactNativePermissions.h */,
107
+				669581F51FE4416B008596CD /* ReactNativePermissions.m */,
108
+				9D23B3501C767B80008B4819 /* Products */,
99 109
 			);
100
-			path = ReactNativePermissions;
101 110
 			sourceTree = "<group>";
102 111
 		};
103
-		9D4628091D33C1EC00346A5B /* permissions */ = {
112
+		9D23B3501C767B80008B4819 /* Products */ = {
104 113
 			isa = PBXGroup;
105 114
 			children = (
106 115
 				4833830F1FAB6115005D5777 /* RNPMotion.h */,
@@ -123,8 +132,9 @@
123 132
 				9D46283D1D34719100346A5B /* RNPPhoto.m */,
124 133
 				281CD5921E26B266003A72B2 /* RNPSpeechRecognition.h */,
125 134
 				281CD5901E26B0C7003A72B2 /* RNPSpeechRecognition.m */,
135
+				9D23B34F1C767B80008B4819 /* libReactNativePermissions.a */,
126 136
 			);
127
-			name = permissions;
137
+			name = Products;
128 138
 			sourceTree = "<group>";
129 139
 		};
130 140
 /* End PBXGroup section */
@@ -183,18 +193,18 @@
183 193
 			isa = PBXSourcesBuildPhase;
184 194
 			buildActionMask = 2147483647;
185 195
 			files = (
186
-				9D46283F1D34719100346A5B /* RNPBackgroundRefresh.m in Sources */,
187
-				9D4628451D34719100346A5B /* RNPPhoto.m in Sources */,
188
-				281CD5911E26B0C8003A72B2 /* RNPSpeechRecognition.m in Sources */,
189
-				9D4628431D34719100346A5B /* RNPLocation.m in Sources */,
190
-				9D46283E1D34719100346A5B /* RNPAudioVideo.m in Sources */,
191
-				9D4628401D34719100346A5B /* RNPBluetooth.m in Sources */,
192
-				9DE8D28B1CA31E95009CE8CC /* RCTConvert+RNPStatus.m in Sources */,
193
-				9D4628421D34719100346A5B /* RNPEvent.m in Sources */,
194 196
 				483383101FAB6115005D5777 /* RNPMotion.m in Sources */,
195
-				9DE8D2821CA3188D009CE8CC /* ReactNativePermissions.m in Sources */,
196
-				9D4628411D34719100346A5B /* RNPContacts.m in Sources */,
197
-				9D4628441D34719100346A5B /* RNPNotification.m in Sources */,
197
+				669582111FE441A8008596CD /* RNPNotification.m in Sources */,
198
+				669582151FE441A8008596CD /* RNPEvent.m in Sources */,
199
+				669582101FE441A8008596CD /* RNPBackgroundRefresh.m in Sources */,
200
+				669581F71FE4416B008596CD /* RCTConvert+RNPStatus.m in Sources */,
201
+				6695820E1FE441A8008596CD /* RNPLocation.m in Sources */,
202
+				6695820F1FE441A8008596CD /* RNPBluetooth.m in Sources */,
203
+				669582141FE441A8008596CD /* RNPContacts.m in Sources */,
204
+				6695820D1FE441A8008596CD /* RNPSpeechRecognition.m in Sources */,
205
+				669582131FE441A8008596CD /* RNPAudioVideo.m in Sources */,
206
+				669581F81FE4416B008596CD /* ReactNativePermissions.m in Sources */,
207
+				669582121FE441A8008596CD /* RNPPhoto.m in Sources */,
198 208
 			);
199 209
 			runOnlyForDeploymentPostprocessing = 0;
200 210
 		};

+ 117
- 0
lib/permissions.android.js Datei anzeigen

@@ -0,0 +1,117 @@
1
+// @flow
2
+
3
+import { AsyncStorage, NativeModules, PermissionsAndroid } from 'react-native'
4
+
5
+type Status = 'authorized' | 'denied' | 'restricted' | 'undetermined'
6
+type Rationale = { title: string, message: string }
7
+type CheckOptions = string | { type: string }
8
+type RequestOptions = string | { type: string, rationale?: Rationale }
9
+
10
+const permissionTypes = {
11
+  location: PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
12
+  camera: PermissionsAndroid.PERMISSIONS.CAMERA,
13
+  microphone: PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
14
+  contacts: PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
15
+  event: PermissionsAndroid.PERMISSIONS.READ_CALENDAR,
16
+  storage: PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
17
+  photo: PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
18
+  callPhone: PermissionsAndroid.PERMISSIONS.CALL_PHONE,
19
+  readSms: PermissionsAndroid.PERMISSIONS.READ_SMS,
20
+  receiveSms: PermissionsAndroid.PERMISSIONS.RECEIVE_SMS,
21
+}
22
+
23
+const RESULTS = {
24
+  [PermissionsAndroid.RESULTS.GRANTED]: 'authorized',
25
+  [PermissionsAndroid.RESULTS.DENIED]: 'denied',
26
+  [PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN]: 'restricted',
27
+}
28
+
29
+const STORAGE_KEY = '@RNPermissions:didAskPermission:'
30
+
31
+const setDidAskOnce = (permission: string) =>
32
+  AsyncStorage.setItem(STORAGE_KEY + permission, 'true')
33
+
34
+const getDidAskOnce = (permission: string) =>
35
+  AsyncStorage.getItem(STORAGE_KEY + permission).then(item => !!item)
36
+
37
+class ReactNativePermissions {
38
+  canOpenSettings: () => Promise<boolean> = () => Promise.resolve(false)
39
+
40
+  openSettings: () => Promise<*> = () =>
41
+    Promise.reject(new Error("'openSettings' is deprecated on android"))
42
+
43
+  getTypes: () => Array<string> = () => Object.keys(permissionTypes)
44
+
45
+  check = (permission: string, options?: CheckOptions): Promise<Status> => {
46
+    if (!permissionTypes[permission]) {
47
+      const error = new Error(
48
+        `ReactNativePermissions: ${
49
+          permission
50
+        } is not a valid permission type on Android`,
51
+      )
52
+
53
+      return Promise.reject(error)
54
+    }
55
+
56
+    return PermissionsAndroid.check(permissionTypes[permission]).then(
57
+      isAuthorized => {
58
+        if (isAuthorized) {
59
+          return 'authorized'
60
+        }
61
+
62
+        return getDidAskOnce(permission).then(didAsk => {
63
+          if (didAsk) {
64
+            return NativeModules.PermissionsAndroid.shouldShowRequestPermissionRationale(
65
+              permissionTypes[permission],
66
+            ).then(shouldShow => (shouldShow ? 'denied' : 'restricted'))
67
+          }
68
+
69
+          return 'undetermined'
70
+        })
71
+      },
72
+    )
73
+  }
74
+
75
+  request = (permission: string, options?: RequestOptions): Promise<Status> => {
76
+    if (!permissionTypes[permission]) {
77
+      const error = new Error(
78
+        `ReactNativePermissions: ${
79
+          permission
80
+        } is not a valid permission type on Android`,
81
+      )
82
+
83
+      return Promise.reject(error)
84
+    }
85
+
86
+    let rationale
87
+
88
+    if (options && options.rationale) {
89
+      rationale = options.rationale
90
+    }
91
+
92
+    return PermissionsAndroid.request(
93
+      permissionTypes[permission],
94
+      rationale,
95
+    ).then(result => {
96
+      // PermissionsAndroid.request() to native module resolves to boolean
97
+      // rather than string if running on OS version prior to Android M
98
+      if (typeof result === 'boolean') {
99
+        return result ? 'authorized' : 'denied'
100
+      }
101
+
102
+      return setDidAskOnce(permission).then(() => RESULTS[result])
103
+    })
104
+  }
105
+
106
+  checkMultiple = (permissions: Array<string>): Promise<{ [string]: string }> =>
107
+    Promise.all(permissions.map(permission => this.check(permission))).then(
108
+      result =>
109
+        result.reduce((acc, value, index) => {
110
+          const name = permissions[index]
111
+          acc[name] = value
112
+          return acc
113
+        }, {}),
114
+    )
115
+}
116
+
117
+export default new ReactNativePermissions()

+ 107
- 0
lib/permissions.ios.js Datei anzeigen

@@ -0,0 +1,107 @@
1
+// @flow
2
+
3
+import { NativeModules } from 'react-native'
4
+const PermissionsIOS = NativeModules.ReactNativePermissions
5
+
6
+type Status = 'authorized' | 'denied' | 'restricted' | 'undetermined'
7
+type Rationale = { title: string, message: string }
8
+type CheckOptions = string | { type: string }
9
+type RequestOptions = string | { type: string, rationale?: Rationale }
10
+
11
+const permissionTypes = [
12
+  'location',
13
+  'camera',
14
+  'microphone',
15
+  'photo',
16
+  'contacts',
17
+  'event',
18
+  'reminder',
19
+  'bluetooth',
20
+  'notification',
21
+  'backgroundRefresh',
22
+  'speechRecognition',
23
+]
24
+
25
+const DEFAULTS = {
26
+  location: 'whenInUse',
27
+  notification: ['alert', 'badge', 'sound'],
28
+}
29
+
30
+class ReactNativePermissions {
31
+  canOpenSettings: () => Promise<boolean> = () =>
32
+    PermissionsIOS.canOpenSettings()
33
+
34
+  openSettings: () => Promise<*> = () => PermissionsIOS.openSettings()
35
+
36
+  getTypes: () => Array<string> = () => permissionTypes
37
+
38
+  check = (permission: string, options?: CheckOptions): Promise<Status> => {
39
+    if (!permissionTypes.includes(permission)) {
40
+      const error = new Error(
41
+        `ReactNativePermissions: ${
42
+          permission
43
+        } is not a valid permission type on iOS`,
44
+      )
45
+
46
+      return Promise.reject(error)
47
+    }
48
+
49
+    let type
50
+
51
+    if (typeof options === 'string') {
52
+      type = options
53
+    } else if (options && options.type) {
54
+      type = options.type
55
+    }
56
+
57
+    return PermissionsIOS.getPermissionStatus(
58
+      permission,
59
+      type || DEFAULTS[permission],
60
+    )
61
+  }
62
+
63
+  request = (permission: string, options?: RequestOptions): Promise<Status> => {
64
+    if (!permissionTypes.includes(permission)) {
65
+      const error = new Error(
66
+        `ReactNativePermissions: ${
67
+          permission
68
+        } is not a valid permission type on iOS`,
69
+      )
70
+
71
+      return Promise.reject(error)
72
+    }
73
+
74
+    if (permission == 'backgroundRefresh') {
75
+      const error = new Error(
76
+        'ReactNativePermissions: You cannot request backgroundRefresh',
77
+      )
78
+
79
+      return Promise.reject(error)
80
+    }
81
+
82
+    let type
83
+
84
+    if (typeof options === 'string') {
85
+      type = options
86
+    } else if (options && options.type) {
87
+      type = options.type
88
+    }
89
+
90
+    return PermissionsIOS.requestPermission(
91
+      permission,
92
+      type || DEFAULTS[permission],
93
+    )
94
+  }
95
+
96
+  checkMultiple = (permissions: Array<string>): Promise<{ [string]: string }> =>
97
+    Promise.all(permissions.map(permission => this.check(permission))).then(
98
+      result =>
99
+        result.reduce((acc, value, index) => {
100
+          const name = permissions[index]
101
+          acc[name] = value
102
+          return acc
103
+        }, {}),
104
+    )
105
+}
106
+
107
+export default new ReactNativePermissions()

+ 21
- 12
package.json Datei anzeigen

@@ -1,18 +1,27 @@
1 1
 {
2 2
   "name": "react-native-permissions",
3
-  "version": "1.0.1",
3
+  "version": "1.0.6",
4
+  "description": "Check user permissions in React Native",
5
+  "author": "Yonah Forst <yonaforst@hotmail.com>",
6
+  "homepage": "https://github.com/yonahforst/react-native-permissions",
7
+  "keywords": ["react-native", "react-permissions", "permissions"],
8
+  "main": "index.js",
9
+  "license": "MIT",
4 10
   "repository": {
5 11
     "type": "git",
6
-    "url": "https://github.com/joshblour/react-native-permissions.git"
12
+    "url": "https://github.com/yonahforst/react-native-permissions.git"
7 13
   },
8
-  "main": "index",
9
-  "license": "MIT",
10
-  "keywords": [
11
-    "react-native",
12
-    "react-permissions",
13
-    "permissions"
14
-  ],
15
-  "author": "Yonah Forst <yonaforst@hotmail.com>",
16
-  "homepage": "https://github.com/joshblour/react-native-permissions",
17
-  "description": "Check user permissions in React Native"
14
+  "scripts": {
15
+    "precommit": "lint-staged",
16
+    "prettier": "prettier --write '**/*.{js,json,md}'"
17
+  },
18
+  "lint-staged": {
19
+    "**/*.{js,json,md}": ["prettier --write", "git add"]
20
+  },
21
+  "devDependencies": {
22
+    "flow-bin": "^0.57.3",
23
+    "husky": "^0.14.3",
24
+    "lint-staged": "^6.0.0",
25
+    "prettier": "^1.9.2"
26
+  }
18 27
 }

+ 614
- 0
yarn.lock Datei anzeigen

@@ -0,0 +1,614 @@
1
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2
+# yarn lockfile v1
3
+
4
+
5
+ansi-escapes@^1.0.0:
6
+  version "1.4.0"
7
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
8
+
9
+ansi-regex@^2.0.0:
10
+  version "2.1.1"
11
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
12
+
13
+ansi-regex@^3.0.0:
14
+  version "3.0.0"
15
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
16
+
17
+ansi-styles@^2.2.1:
18
+  version "2.2.1"
19
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
20
+
21
+ansi-styles@^3.1.0, ansi-styles@^3.2.0:
22
+  version "3.2.0"
23
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88"
24
+  dependencies:
25
+    color-convert "^1.9.0"
26
+
27
+any-observable@^0.2.0:
28
+  version "0.2.0"
29
+  resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.2.0.tgz#c67870058003579009083f54ac0abafb5c33d242"
30
+
31
+app-root-path@^2.0.0:
32
+  version "2.0.1"
33
+  resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.0.1.tgz#cd62dcf8e4fd5a417efc664d2e5b10653c651b46"
34
+
35
+argparse@^1.0.7:
36
+  version "1.0.9"
37
+  resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
38
+  dependencies:
39
+    sprintf-js "~1.0.2"
40
+
41
+balanced-match@^1.0.0:
42
+  version "1.0.0"
43
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
44
+
45
+brace-expansion@^1.1.7:
46
+  version "1.1.8"
47
+  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
48
+  dependencies:
49
+    balanced-match "^1.0.0"
50
+    concat-map "0.0.1"
51
+
52
+chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
53
+  version "1.1.3"
54
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
55
+  dependencies:
56
+    ansi-styles "^2.2.1"
57
+    escape-string-regexp "^1.0.2"
58
+    has-ansi "^2.0.0"
59
+    strip-ansi "^3.0.0"
60
+    supports-color "^2.0.0"
61
+
62
+chalk@^2.0.1, chalk@^2.1.0:
63
+  version "2.3.0"
64
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba"
65
+  dependencies:
66
+    ansi-styles "^3.1.0"
67
+    escape-string-regexp "^1.0.5"
68
+    supports-color "^4.0.0"
69
+
70
+ci-info@^1.0.0:
71
+  version "1.1.2"
72
+  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.2.tgz#03561259db48d0474c8bdc90f5b47b068b6bbfb4"
73
+
74
+cli-cursor@^1.0.2:
75
+  version "1.0.2"
76
+  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
77
+  dependencies:
78
+    restore-cursor "^1.0.1"
79
+
80
+cli-spinners@^0.1.2:
81
+  version "0.1.2"
82
+  resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c"
83
+
84
+cli-truncate@^0.2.1:
85
+  version "0.2.1"
86
+  resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574"
87
+  dependencies:
88
+    slice-ansi "0.0.4"
89
+    string-width "^1.0.1"
90
+
91
+code-point-at@^1.0.0:
92
+  version "1.1.0"
93
+  resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
94
+
95
+color-convert@^1.9.0:
96
+  version "1.9.1"
97
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed"
98
+  dependencies:
99
+    color-name "^1.1.1"
100
+
101
+color-name@^1.1.1:
102
+  version "1.1.3"
103
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
104
+
105
+commander@^2.11.0, commander@^2.9.0:
106
+  version "2.12.2"
107
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555"
108
+
109
+concat-map@0.0.1:
110
+  version "0.0.1"
111
+  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
112
+
113
+cosmiconfig@^3.1.0:
114
+  version "3.1.0"
115
+  resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-3.1.0.tgz#640a94bf9847f321800403cd273af60665c73397"
116
+  dependencies:
117
+    is-directory "^0.3.1"
118
+    js-yaml "^3.9.0"
119
+    parse-json "^3.0.0"
120
+    require-from-string "^2.0.1"
121
+
122
+cross-spawn@^5.0.1:
123
+  version "5.1.0"
124
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
125
+  dependencies:
126
+    lru-cache "^4.0.1"
127
+    shebang-command "^1.2.0"
128
+    which "^1.2.9"
129
+
130
+date-fns@^1.27.2:
131
+  version "1.29.0"
132
+  resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6"
133
+
134
+dedent@^0.7.0:
135
+  version "0.7.0"
136
+  resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
137
+
138
+elegant-spinner@^1.0.1:
139
+  version "1.0.1"
140
+  resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
141
+
142
+error-ex@^1.3.1:
143
+  version "1.3.1"
144
+  resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
145
+  dependencies:
146
+    is-arrayish "^0.2.1"
147
+
148
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
149
+  version "1.0.5"
150
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
151
+
152
+esprima@^4.0.0:
153
+  version "4.0.0"
154
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
155
+
156
+execa@^0.8.0:
157
+  version "0.8.0"
158
+  resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da"
159
+  dependencies:
160
+    cross-spawn "^5.0.1"
161
+    get-stream "^3.0.0"
162
+    is-stream "^1.1.0"
163
+    npm-run-path "^2.0.0"
164
+    p-finally "^1.0.0"
165
+    signal-exit "^3.0.0"
166
+    strip-eof "^1.0.0"
167
+
168
+exit-hook@^1.0.0:
169
+  version "1.1.1"
170
+  resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
171
+
172
+figures@^1.7.0:
173
+  version "1.7.0"
174
+  resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
175
+  dependencies:
176
+    escape-string-regexp "^1.0.5"
177
+    object-assign "^4.1.0"
178
+
179
+find-parent-dir@^0.3.0:
180
+  version "0.3.0"
181
+  resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54"
182
+
183
+flow-bin@^0.57.3:
184
+  version "0.57.3"
185
+  resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.57.3.tgz#843fb80a821b6d0c5847f7bb3f42365ffe53b27b"
186
+
187
+get-own-enumerable-property-symbols@^2.0.1:
188
+  version "2.0.1"
189
+  resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz#5c4ad87f2834c4b9b4e84549dc1e0650fb38c24b"
190
+
191
+get-stream@^3.0.0:
192
+  version "3.0.0"
193
+  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
194
+
195
+has-ansi@^2.0.0:
196
+  version "2.0.0"
197
+  resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
198
+  dependencies:
199
+    ansi-regex "^2.0.0"
200
+
201
+has-flag@^2.0.0:
202
+  version "2.0.0"
203
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
204
+
205
+husky@^0.14.3:
206
+  version "0.14.3"
207
+  resolved "https://registry.yarnpkg.com/husky/-/husky-0.14.3.tgz#c69ed74e2d2779769a17ba8399b54ce0b63c12c3"
208
+  dependencies:
209
+    is-ci "^1.0.10"
210
+    normalize-path "^1.0.0"
211
+    strip-indent "^2.0.0"
212
+
213
+indent-string@^2.1.0:
214
+  version "2.1.0"
215
+  resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
216
+  dependencies:
217
+    repeating "^2.0.0"
218
+
219
+indent-string@^3.0.0:
220
+  version "3.2.0"
221
+  resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
222
+
223
+is-arrayish@^0.2.1:
224
+  version "0.2.1"
225
+  resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
226
+
227
+is-ci@^1.0.10:
228
+  version "1.0.10"
229
+  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e"
230
+  dependencies:
231
+    ci-info "^1.0.0"
232
+
233
+is-directory@^0.3.1:
234
+  version "0.3.1"
235
+  resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
236
+
237
+is-extglob@^2.1.1:
238
+  version "2.1.1"
239
+  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
240
+
241
+is-finite@^1.0.0:
242
+  version "1.0.2"
243
+  resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
244
+  dependencies:
245
+    number-is-nan "^1.0.0"
246
+
247
+is-fullwidth-code-point@^1.0.0:
248
+  version "1.0.0"
249
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
250
+  dependencies:
251
+    number-is-nan "^1.0.0"
252
+
253
+is-glob@^4.0.0:
254
+  version "4.0.0"
255
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0"
256
+  dependencies:
257
+    is-extglob "^2.1.1"
258
+
259
+is-obj@^1.0.1:
260
+  version "1.0.1"
261
+  resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
262
+
263
+is-observable@^0.2.0:
264
+  version "0.2.0"
265
+  resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-0.2.0.tgz#b361311d83c6e5d726cabf5e250b0237106f5ae2"
266
+  dependencies:
267
+    symbol-observable "^0.2.2"
268
+
269
+is-promise@^2.1.0:
270
+  version "2.1.0"
271
+  resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
272
+
273
+is-regexp@^1.0.0:
274
+  version "1.0.0"
275
+  resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
276
+
277
+is-stream@^1.1.0:
278
+  version "1.1.0"
279
+  resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
280
+
281
+isexe@^2.0.0:
282
+  version "2.0.0"
283
+  resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
284
+
285
+jest-get-type@^21.2.0:
286
+  version "21.2.0"
287
+  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.2.0.tgz#f6376ab9db4b60d81e39f30749c6c466f40d4a23"
288
+
289
+jest-validate@^21.1.0:
290
+  version "21.2.1"
291
+  resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.2.1.tgz#cc0cbca653cd54937ba4f2a111796774530dd3c7"
292
+  dependencies:
293
+    chalk "^2.0.1"
294
+    jest-get-type "^21.2.0"
295
+    leven "^2.1.0"
296
+    pretty-format "^21.2.1"
297
+
298
+js-yaml@^3.9.0:
299
+  version "3.10.0"
300
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
301
+  dependencies:
302
+    argparse "^1.0.7"
303
+    esprima "^4.0.0"
304
+
305
+leven@^2.1.0:
306
+  version "2.1.0"
307
+  resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
308
+
309
+lint-staged@^5.0.0:
310
+  version "5.0.0"
311
+  resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-5.0.0.tgz#f1c670e03e2fdf3f3d0eb81f72d3bcf658770e54"
312
+  dependencies:
313
+    app-root-path "^2.0.0"
314
+    chalk "^2.1.0"
315
+    commander "^2.11.0"
316
+    cosmiconfig "^3.1.0"
317
+    dedent "^0.7.0"
318
+    execa "^0.8.0"
319
+    find-parent-dir "^0.3.0"
320
+    is-glob "^4.0.0"
321
+    jest-validate "^21.1.0"
322
+    listr "^0.13.0"
323
+    lodash "^4.17.4"
324
+    log-symbols "^2.0.0"
325
+    minimatch "^3.0.0"
326
+    npm-which "^3.0.1"
327
+    p-map "^1.1.1"
328
+    path-is-inside "^1.0.2"
329
+    pify "^3.0.0"
330
+    staged-git-files "0.0.4"
331
+    stringify-object "^3.2.0"
332
+
333
+listr-silent-renderer@^1.1.1:
334
+  version "1.1.1"
335
+  resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e"
336
+
337
+listr-update-renderer@^0.4.0:
338
+  version "0.4.0"
339
+  resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz#344d980da2ca2e8b145ba305908f32ae3f4cc8a7"
340
+  dependencies:
341
+    chalk "^1.1.3"
342
+    cli-truncate "^0.2.1"
343
+    elegant-spinner "^1.0.1"
344
+    figures "^1.7.0"
345
+    indent-string "^3.0.0"
346
+    log-symbols "^1.0.2"
347
+    log-update "^1.0.2"
348
+    strip-ansi "^3.0.1"
349
+
350
+listr-verbose-renderer@^0.4.0:
351
+  version "0.4.1"
352
+  resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35"
353
+  dependencies:
354
+    chalk "^1.1.3"
355
+    cli-cursor "^1.0.2"
356
+    date-fns "^1.27.2"
357
+    figures "^1.7.0"
358
+
359
+listr@^0.13.0:
360
+  version "0.13.0"
361
+  resolved "https://registry.yarnpkg.com/listr/-/listr-0.13.0.tgz#20bb0ba30bae660ee84cc0503df4be3d5623887d"
362
+  dependencies:
363
+    chalk "^1.1.3"
364
+    cli-truncate "^0.2.1"
365
+    figures "^1.7.0"
366
+    indent-string "^2.1.0"
367
+    is-observable "^0.2.0"
368
+    is-promise "^2.1.0"
369
+    is-stream "^1.1.0"
370
+    listr-silent-renderer "^1.1.1"
371
+    listr-update-renderer "^0.4.0"
372
+    listr-verbose-renderer "^0.4.0"
373
+    log-symbols "^1.0.2"
374
+    log-update "^1.0.2"
375
+    ora "^0.2.3"
376
+    p-map "^1.1.1"
377
+    rxjs "^5.4.2"
378
+    stream-to-observable "^0.2.0"
379
+    strip-ansi "^3.0.1"
380
+
381
+lodash@^4.17.4:
382
+  version "4.17.4"
383
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
384
+
385
+log-symbols@^1.0.2:
386
+  version "1.0.2"
387
+  resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
388
+  dependencies:
389
+    chalk "^1.0.0"
390
+
391
+log-symbols@^2.0.0:
392
+  version "2.1.0"
393
+  resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.1.0.tgz#f35fa60e278832b538dc4dddcbb478a45d3e3be6"
394
+  dependencies:
395
+    chalk "^2.0.1"
396
+
397
+log-update@^1.0.2:
398
+  version "1.0.2"
399
+  resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1"
400
+  dependencies:
401
+    ansi-escapes "^1.0.0"
402
+    cli-cursor "^1.0.2"
403
+
404
+lru-cache@^4.0.1:
405
+  version "4.1.1"
406
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55"
407
+  dependencies:
408
+    pseudomap "^1.0.2"
409
+    yallist "^2.1.2"
410
+
411
+minimatch@^3.0.0:
412
+  version "3.0.4"
413
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
414
+  dependencies:
415
+    brace-expansion "^1.1.7"
416
+
417
+normalize-path@^1.0.0:
418
+  version "1.0.0"
419
+  resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379"
420
+
421
+npm-path@^2.0.2:
422
+  version "2.0.3"
423
+  resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.3.tgz#15cff4e1c89a38da77f56f6055b24f975dfb2bbe"
424
+  dependencies:
425
+    which "^1.2.10"
426
+
427
+npm-run-path@^2.0.0:
428
+  version "2.0.2"
429
+  resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
430
+  dependencies:
431
+    path-key "^2.0.0"
432
+
433
+npm-which@^3.0.1:
434
+  version "3.0.1"
435
+  resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa"
436
+  dependencies:
437
+    commander "^2.9.0"
438
+    npm-path "^2.0.2"
439
+    which "^1.2.10"
440
+
441
+number-is-nan@^1.0.0:
442
+  version "1.0.1"
443
+  resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
444
+
445
+object-assign@^4.0.1, object-assign@^4.1.0:
446
+  version "4.1.1"
447
+  resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
448
+
449
+onetime@^1.0.0:
450
+  version "1.1.0"
451
+  resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
452
+
453
+ora@^0.2.3:
454
+  version "0.2.3"
455
+  resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4"
456
+  dependencies:
457
+    chalk "^1.1.1"
458
+    cli-cursor "^1.0.2"
459
+    cli-spinners "^0.1.2"
460
+    object-assign "^4.0.1"
461
+
462
+p-finally@^1.0.0:
463
+  version "1.0.0"
464
+  resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
465
+
466
+p-map@^1.1.1:
467
+  version "1.2.0"
468
+  resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b"
469
+
470
+parse-json@^3.0.0:
471
+  version "3.0.0"
472
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-3.0.0.tgz#fa6f47b18e23826ead32f263e744d0e1e847fb13"
473
+  dependencies:
474
+    error-ex "^1.3.1"
475
+
476
+path-is-inside@^1.0.2:
477
+  version "1.0.2"
478
+  resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
479
+
480
+path-key@^2.0.0:
481
+  version "2.0.1"
482
+  resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
483
+
484
+pify@^3.0.0:
485
+  version "3.0.0"
486
+  resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
487
+
488
+prettier@^1.8.2:
489
+  version "1.8.2"
490
+  resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.8.2.tgz#bff83e7fd573933c607875e5ba3abbdffb96aeb8"
491
+
492
+pretty-format@^21.2.1:
493
+  version "21.2.1"
494
+  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.2.1.tgz#ae5407f3cf21066cd011aa1ba5fce7b6a2eddb36"
495
+  dependencies:
496
+    ansi-regex "^3.0.0"
497
+    ansi-styles "^3.2.0"
498
+
499
+pseudomap@^1.0.2:
500
+  version "1.0.2"
501
+  resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
502
+
503
+repeating@^2.0.0:
504
+  version "2.0.1"
505
+  resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
506
+  dependencies:
507
+    is-finite "^1.0.0"
508
+
509
+require-from-string@^2.0.1:
510
+  version "2.0.1"
511
+  resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.1.tgz#c545233e9d7da6616e9d59adfb39fc9f588676ff"
512
+
513
+restore-cursor@^1.0.1:
514
+  version "1.0.1"
515
+  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
516
+  dependencies:
517
+    exit-hook "^1.0.0"
518
+    onetime "^1.0.0"
519
+
520
+rxjs@^5.4.2:
521
+  version "5.5.3"
522
+  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.3.tgz#b62227e74b84f4e77bdf440e50b5ee01a1bc7dcd"
523
+  dependencies:
524
+    symbol-observable "^1.0.1"
525
+
526
+shebang-command@^1.2.0:
527
+  version "1.2.0"
528
+  resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
529
+  dependencies:
530
+    shebang-regex "^1.0.0"
531
+
532
+shebang-regex@^1.0.0:
533
+  version "1.0.0"
534
+  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
535
+
536
+signal-exit@^3.0.0:
537
+  version "3.0.2"
538
+  resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
539
+
540
+slice-ansi@0.0.4:
541
+  version "0.0.4"
542
+  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
543
+
544
+sprintf-js@~1.0.2:
545
+  version "1.0.3"
546
+  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
547
+
548
+staged-git-files@0.0.4:
549
+  version "0.0.4"
550
+  resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-0.0.4.tgz#d797e1b551ca7a639dec0237dc6eb4bb9be17d35"
551
+
552
+stream-to-observable@^0.2.0:
553
+  version "0.2.0"
554
+  resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.2.0.tgz#59d6ea393d87c2c0ddac10aa0d561bc6ba6f0e10"
555
+  dependencies:
556
+    any-observable "^0.2.0"
557
+
558
+string-width@^1.0.1:
559
+  version "1.0.2"
560
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
561
+  dependencies:
562
+    code-point-at "^1.0.0"
563
+    is-fullwidth-code-point "^1.0.0"
564
+    strip-ansi "^3.0.0"
565
+
566
+stringify-object@^3.2.0:
567
+  version "3.2.1"
568
+  resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.2.1.tgz#2720c2eff940854c819f6ee252aaeb581f30624d"
569
+  dependencies:
570
+    get-own-enumerable-property-symbols "^2.0.1"
571
+    is-obj "^1.0.1"
572
+    is-regexp "^1.0.0"
573
+
574
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
575
+  version "3.0.1"
576
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
577
+  dependencies:
578
+    ansi-regex "^2.0.0"
579
+
580
+strip-eof@^1.0.0:
581
+  version "1.0.0"
582
+  resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
583
+
584
+strip-indent@^2.0.0:
585
+  version "2.0.0"
586
+  resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
587
+
588
+supports-color@^2.0.0:
589
+  version "2.0.0"
590
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
591
+
592
+supports-color@^4.0.0:
593
+  version "4.5.0"
594
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b"
595
+  dependencies:
596
+    has-flag "^2.0.0"
597
+
598
+symbol-observable@^0.2.2:
599
+  version "0.2.4"
600
+  resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-0.2.4.tgz#95a83db26186d6af7e7a18dbd9760a2f86d08f40"
601
+
602
+symbol-observable@^1.0.1:
603
+  version "1.1.0"
604
+  resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.1.0.tgz#5c68fd8d54115d9dfb72a84720549222e8db9b32"
605
+
606
+which@^1.2.10, which@^1.2.9:
607
+  version "1.3.0"
608
+  resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
609
+  dependencies:
610
+    isexe "^2.0.0"
611
+
612
+yallist@^2.1.2:
613
+  version "2.1.2"
614
+  resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"