Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support iOS 14 photo permission API changes #510

Merged
merged 6 commits into from
Oct 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ target 'YourAwesomeProject' do
pod 'Permission-Motion', :path => "#{permissions_path}/Motion.podspec"
pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications.podspec"
pod 'Permission-PhotoLibrary', :path => "#{permissions_path}/PhotoLibrary.podspec"
pod 'Permission-PhotoLibraryAddOnly', :path => "#{permissions_path}/PhotoLibraryAddOnly.podspec"
pod 'Permission-Reminders', :path => "#{permissions_path}/Reminders.podspec"
pod 'Permission-Siri', :path => "#{permissions_path}/Siri.podspec"
pod 'Permission-SpeechRecognition', :path => "#{permissions_path}/SpeechRecognition.podspec"
Expand Down Expand Up @@ -93,6 +94,8 @@ Then update your `Info.plist` with wanted permissions usage descriptions:
<string>YOUR TEXT</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSRemindersUsageDescription</key>
<string>YOUR TEXT</string>
<key>NSSpeechRecognitionUsageDescription</key>
Expand Down Expand Up @@ -391,6 +394,7 @@ PERMISSIONS.IOS.MEDIA_LIBRARY;
PERMISSIONS.IOS.MICROPHONE;
PERMISSIONS.IOS.MOTION;
PERMISSIONS.IOS.PHOTO_LIBRARY;
PERMISSIONS.IOS.PHOTO_LIBRARY_ADD_ONLY;
PERMISSIONS.IOS.REMINDERS;
PERMISSIONS.IOS.SIRI;
PERMISSIONS.IOS.SPEECH_RECOGNITION;
Expand All @@ -407,12 +411,18 @@ Permission checks and requests resolve into one of these statuses:
| `RESULTS.DENIED` | The permission has not been requested / is denied but requestable |
| `RESULTS.GRANTED` | The permission is granted |
| `RESULTS.BLOCKED` | The permission is denied and not requestable anymore |
| `RESULTS.LIMITED` | The permission is granted but with limitations |

### Methods

```ts
// type used in usage examples
type PermissionStatus = 'unavailable' | 'denied' | 'blocked' | 'granted';
type PermissionStatus =
| 'unavailable'
| 'denied'
| 'blocked'
| 'granted'
| 'limited';
```

#### check
Expand Down Expand Up @@ -620,6 +630,24 @@ import {openSettings} from 'react-native-permissions';
openSettings().catch(() => console.warn('cannot open settings'));
```

---

#### presentLimitedLibraryPicker

On iOS, open a picker to update the photo selection when limited permissions are given. This is a no-op on Android, and when full permissions are given.

```ts
function presentLimitedLibraryPicker(): Promise<void>;
```

```js
import {presentLimitedLibraryPicker} from 'react-native-permissions';

presentLimitedLibraryPicker().catch(() =>
console.warn('cannot open presentLimitedLibraryPicker'),
);
```

## Migrating from v1.x.x

If you are currently using the version `1.x.x` and would like to switch to `v2.x.x`, the only thing you really need to know is that it's now required to select the wanted permission **per platform**.
Expand Down
8 changes: 8 additions & 0 deletions example/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ const colors: {[key: string]: string} = {
denied: '#ff9800',
granted: '#43a047',
blocked: '#e53935',
limited: '#ffdd00',
};

const icons: {[key: string]: string} = {
unavailable: 'circle',
denied: 'alert-circle',
granted: 'check-circle',
blocked: 'close-circle',
limited: 'check-circle-outline',
};

const PermissionRow = ({
Expand Down Expand Up @@ -117,6 +119,12 @@ export default class App extends React.Component<{}, State> {
RNPermissions.openSettings();
}}
/>
<Appbar.Action
icon="image-multiple"
onPress={() => {
RNPermissions.presentLimitedLibraryPicker();
}}
/>
</Appbar.Header>

<FlatList
Expand Down
1 change: 1 addition & 0 deletions example/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ target 'RNPermissionsExample' do
pod 'Permission-Motion', :path => "#{permissions_path}/Motion.podspec"
pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications.podspec"
pod 'Permission-PhotoLibrary', :path => "#{permissions_path}/PhotoLibrary.podspec"
pod 'Permission-PhotoLibraryAddOnly', :path => "#{permissions_path}/PhotoLibraryAddOnly.podspec"
pod 'Permission-Reminders', :path => "#{permissions_path}/Reminders.podspec"
# pod 'Permission-Siri', :path => "#{permissions_path}/Siri.podspec"
pod 'Permission-SpeechRecognition', :path => "#{permissions_path}/SpeechRecognition.podspec"
Expand Down
10 changes: 8 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ PODS:
- RNPermissions
- Permission-PhotoLibrary (2.2.0):
- RNPermissions
- Permission-PhotoLibraryAddOnly (2.2.0):
- RNPermissions
- Permission-Reminders (2.2.0):
- RNPermissions
- Permission-SpeechRecognition (2.2.0):
Expand Down Expand Up @@ -370,6 +372,7 @@ DEPENDENCIES:
- Permission-Motion (from `../node_modules/react-native-permissions/ios/Motion.podspec`)
- Permission-Notifications (from `../node_modules/react-native-permissions/ios/Notifications.podspec`)
- Permission-PhotoLibrary (from `../node_modules/react-native-permissions/ios/PhotoLibrary.podspec`)
- Permission-PhotoLibraryAddOnly (from `../node_modules/react-native-permissions/ios/PhotoLibraryAddOnly.podspec`)
- Permission-Reminders (from `../node_modules/react-native-permissions/ios/Reminders.podspec`)
- Permission-SpeechRecognition (from `../node_modules/react-native-permissions/ios/SpeechRecognition.podspec`)
- Permission-StoreKit (from `../node_modules/react-native-permissions/ios/StoreKit.podspec`)
Expand Down Expand Up @@ -451,6 +454,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-permissions/ios/Notifications.podspec"
Permission-PhotoLibrary:
:path: "../node_modules/react-native-permissions/ios/PhotoLibrary.podspec"
Permission-PhotoLibraryAddOnly:
:path: "../node_modules/react-native-permissions/ios/PhotoLibraryAddOnly.podspec"
Permission-Reminders:
:path: "../node_modules/react-native-permissions/ios/Reminders.podspec"
Permission-SpeechRecognition:
Expand Down Expand Up @@ -531,7 +536,8 @@ SPEC CHECKSUMS:
Permission-Microphone: 06462b9d979ada12095bcff8d5ee1aeeeaf20b5d
Permission-Motion: b8f1f0e7baf8fb136fc54aabf6a8669e95265d16
Permission-Notifications: 572d4e94121e57dbecc71a0933abd8ed61108e92
Permission-PhotoLibrary: e3ff899f87a3eda29427c142ca93837e8802d228
Permission-PhotoLibrary: e7419100010711b9c1cf002c1483653d66e6c246
Permission-PhotoLibraryAddOnly: a8f8e696158be0d7652dc14a3ce8f1d9d738e7ab
Permission-Reminders: 82dfcc66d1afdaef20a0084350753c3ff2691e4a
Permission-SpeechRecognition: 0dc3e7a65fa38beb9d249cd37ef1b1565f72a494
Permission-StoreKit: 0fc596a9c7d2c3fbebfd4b1c89222db3ce94eba2
Expand Down Expand Up @@ -559,6 +565,6 @@ SPEC CHECKSUMS:
Yoga: 3ebccbdd559724312790e7742142d062476b698e
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a

PODFILE CHECKSUM: 33d4013cd5154539040dffe614d959a536bc61f4
PODFILE CHECKSUM: 8f91a3a16ccf05cf62965b5febfce149cb72da42

COCOAPODS: 1.9.3
2 changes: 2 additions & 0 deletions example/ios/RNPermissionsExample/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
<string>Let me use the microphone</string>
<key>NSMotionUsageDescription</key>
<string>Let me use your motion data</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Let me add photos</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Let me use your photo library</string>
<key>NSRemindersUsageDescription</key>
Expand Down
1 change: 1 addition & 0 deletions ios/PhotoLibrary.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ Pod::Spec.new do |s|

s.source = { :git => package["repository"]["url"], :tag => s.version }
s.source_files = "PhotoLibrary/*.{h,m}"
s.frameworks = "PhotosUI"
end
2 changes: 2 additions & 0 deletions ios/PhotoLibrary/RNPermissionHandlerPhotoLibrary.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

@interface RNPermissionHandlerPhotoLibrary : NSObject<RNPermissionHandler>

- (void)presentLimitedLibraryPickerFromViewController API_AVAILABLE(ios(14));

@end
26 changes: 25 additions & 1 deletion ios/PhotoLibrary/RNPermissionHandlerPhotoLibrary.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "RNPermissionHandlerPhotoLibrary.h"

@import Photos;
@import PhotosUI;

@implementation RNPermissionHandlerPhotoLibrary

Expand All @@ -14,7 +15,14 @@ + (NSString * _Nonnull)handlerUniqueId {

- (void)checkWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve
rejecter:(void (__unused ^ _Nonnull)(NSError * _Nonnull))reject {
switch ([PHPhotoLibrary authorizationStatus]) {
PHAuthorizationStatus status;
if (@available(iOS 14.0, *)) {
status = [PHPhotoLibrary authorizationStatusForAccessLevel:PHAccessLevelReadWrite];
} else {
status = [PHPhotoLibrary authorizationStatus];
}

switch (status) {
case PHAuthorizationStatusNotDetermined:
return resolve(RNPermissionStatusNotDetermined);
case PHAuthorizationStatusRestricted:
Expand All @@ -23,14 +31,30 @@ - (void)checkWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve
return resolve(RNPermissionStatusDenied);
case PHAuthorizationStatusAuthorized:
return resolve(RNPermissionStatusAuthorized);
case PHAuthorizationStatusLimited:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PHAuthorizationStatusLimited is not available on iOS < 14, no?

Copy link

@FRizzonelli FRizzonelli Sep 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested it on simulator and works on both iOS 14 and iOS 13 without problems!

Copy link
Owner

@zoontek zoontek Sep 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The simulator might not work correctly on iOS because, unlike Android, it's not a proper emulator. Have you tested it on a real device?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return resolve(RNPermissionStatusLimited);
}
}

- (void)requestWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve
rejecter:(void (^ _Nonnull)(NSError * _Nonnull))reject {

if (@available(iOS 14.0, *)) {
[PHPhotoLibrary requestAuthorizationForAccessLevel:PHAccessLevelReadWrite handler:^(__unused PHAuthorizationStatus status) {
[self checkWithResolver:resolve rejecter:reject];
}];
return;
}

[PHPhotoLibrary requestAuthorization:^(__unused PHAuthorizationStatus status) {
[self checkWithResolver:resolve rejecter:reject];
}];
}

- (void)presentLimitedLibraryPickerFromViewController {
UIViewController* rootViewController = [[UIApplication sharedApplication].keyWindow rootViewController];

[[PHPhotoLibrary sharedPhotoLibrary] presentLimitedLibraryPickerFromViewController:rootViewController];
}

@end
21 changes: 21 additions & 0 deletions ios/PhotoLibraryAddOnly.podspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'json'
package = JSON.parse(File.read('../package.json'))

Pod::Spec.new do |s|
s.name = "Permission-PhotoLibraryAddOnly"
s.dependency "RNPermissions"

s.version = package["version"]
s.license = package["license"]
s.summary = package["description"]
s.authors = package["author"]
s.homepage = package["homepage"]

s.platform = :ios, "9.0"
s.ios.deployment_target = "9.0"
s.tvos.deployment_target = "11.0"
s.requires_arc = true

s.source = { :git => package["repository"]["url"], :tag => s.version }
s.source_files = "PhotoLibraryAddOnly/*.{h,m}"
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#import "RNPermissions.h"

@interface RNPermissionHandlerPhotoLibraryAddOnly : NSObject<RNPermissionHandler>

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#import "RNPermissionHandlerPhotoLibraryAddOnly.h"

@import Photos;

@implementation RNPermissionHandlerPhotoLibraryAddOnly

+ (NSArray<NSString *> * _Nonnull)usageDescriptionKeys {
return @[@"NSPhotoLibraryUsageDescription"];
}

+ (NSString * _Nonnull)handlerUniqueId {
return @"ios.permission.PHOTO_LIBRARY_ADD_ONLY";
}

- (void)checkWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve
rejecter:(void (__unused ^ _Nonnull)(NSError * _Nonnull))reject {
PHAuthorizationStatus status;
if (@available(iOS 14.0, *)) {
status = [PHPhotoLibrary authorizationStatusForAccessLevel:PHAccessLevelAddOnly];
} else {
status = [PHPhotoLibrary authorizationStatus];
}

switch (status) {
case PHAuthorizationStatusNotDetermined:
return resolve(RNPermissionStatusNotDetermined);
case PHAuthorizationStatusRestricted:
return resolve(RNPermissionStatusRestricted);
case PHAuthorizationStatusDenied:
return resolve(RNPermissionStatusDenied);
case PHAuthorizationStatusAuthorized:
return resolve(RNPermissionStatusAuthorized);
case PHAuthorizationStatusLimited:
return resolve(RNPermissionStatusLimited);
}
}

- (void)requestWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve
rejecter:(void (^ _Nonnull)(NSError * _Nonnull))reject {

if (@available(iOS 14.0, *)) {
[PHPhotoLibrary requestAuthorizationForAccessLevel:PHAccessLevelAddOnly handler:^(__unused PHAuthorizationStatus status) {
[self checkWithResolver:resolve rejecter:reject];
}];
return;
}

[PHPhotoLibrary requestAuthorization:^(__unused PHAuthorizationStatus status) {
[self checkWithResolver:resolve rejecter:reject];
}];
}

@end
4 changes: 4 additions & 0 deletions ios/RNPermissions.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ typedef NS_ENUM(NSInteger, RNPermission) {
#if __has_include("RNPermissionHandlerAppTrackingTransparency.h")
RNPermissionAppTrackingTransparency = 16,
#endif
#if __has_include("RNPermissionHandlerPhotoLibraryAddOnly.h")
RNPermissionAppPhotoLibraryAddOnly = 17,
#endif
};

@interface RCTConvert (RNPermission)
Expand All @@ -62,6 +65,7 @@ typedef enum {
RNPermissionStatusRestricted = 2,
RNPermissionStatusDenied = 3,
RNPermissionStatusAuthorized = 4,
RNPermissionStatusLimited = 5,
} RNPermissionStatus;

@protocol RNPermissionHandler <NSObject>
Expand Down
Loading