mirror of
https://github.com/status-im/react-native-camera-roll.git
synced 2026-08-30 21:01:10 +00:00
Fixes fix(ci): fixed android release build as a CI test step fix(android): Fix MediaStore issues and support scopped storage #322 #244 fix(android): Fix saveImageToCameraRoll #248 #254 fix(android): remove JCenter #340 #401 fix(ios): Fix performance issues #276 fix(ios): add method to get file Path from internal PH ID #135 fix(react-native): Bump used dependencies #393 ... Fixes #322 Fixes #244 Fixes #248 Fixes #254 Fixes #340 Fixes #401 Fixes #276 Fixes #135 Fixes #393 new Features feat(ios): now it's possible to listen to library selection changes `useEffect(() => { let subscription: EmitterSubscription; if (isAboveIOS14) { subscription = cameraRollEventEmitter.addListener('onLibrarySelectionChange', (_event) => { getUnloadedPictures(); }); } return () => { if (isAboveIOS14 && subscription) { subscription.remove(); } };` feat(ios): possibility to open native modal to update selection when authorization is limited iosRefreshGallerySelection() feat(ios): Convert HEIC images on demand to upload to server BREAKING CHANGE: root import changed! ``` import { CameraRoll } from @react-native-community/cameraroll instead of import CameraRoll from @react-native-community/cameraroll ``` Co-authored-by: idrissakhi <85105624+idrissakhi@users.noreply.github.com>
193 lines
6.3 KiB
Objective-C
193 lines
6.3 KiB
Objective-C
//
|
|
// CameraRollPermissionModule.m
|
|
// RNCCameraRoll
|
|
//
|
|
// Created by sakhi idris on 16/08/2022.
|
|
// Copyright © 2022 Facebook. All rights reserved.
|
|
//
|
|
#import "RNCCameraRollPermissionModule.h"
|
|
#import <React/RCTUtils.h>
|
|
#import <React/RCTConvert.h>
|
|
|
|
@import Photos;
|
|
@import PhotosUI;
|
|
|
|
@implementation RNCCameraRollPermissionModule
|
|
|
|
{
|
|
bool hasListeners;
|
|
}
|
|
|
|
#pragma mark - Access Levels
|
|
static NSString * const ADD_ONLY = @"addOnly";
|
|
static NSString * const READ_WRITE = @"readWrite";
|
|
|
|
// Will be called when this module's first listener is added.
|
|
-(void)startObserving {
|
|
hasListeners = YES;
|
|
[[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];
|
|
}
|
|
|
|
// Will be called when this module's last listener is removed, or on dealloc.
|
|
-(void)stopObserving {
|
|
hasListeners = NO;
|
|
[[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];
|
|
}
|
|
|
|
RCT_EXPORT_MODULE()
|
|
|
|
- (dispatch_queue_t)methodQueue
|
|
{
|
|
return dispatch_get_main_queue();
|
|
}
|
|
|
|
- (NSArray<NSString *> *)supportedEvents {
|
|
return @[@"onLibrarySelectionChange"];
|
|
}
|
|
|
|
- (NSString *)stringForStatus:(RNPermissionStatus)status {
|
|
switch (status) {
|
|
case RNPermissionStatusRestricted:
|
|
return @"unavailable";
|
|
case RNPermissionStatusNotDetermined:
|
|
return @"not-determined";
|
|
case RNPermissionStatusDenied:
|
|
return @"denied";
|
|
case RNPermissionStatusLimited:
|
|
return @"limited";
|
|
case RNPermissionStatusAuthorized:
|
|
return @"granted";
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- (void)checkCameraRollPermission:(NSString *) accessLevel
|
|
resolver:(void (^ _Nonnull)(RNPermissionStatus))resolve
|
|
rejecter:(void (^ _Nonnull)(NSString *code, NSString *message))reject {
|
|
PHAuthorizationStatus status;
|
|
|
|
if (@available(iOS 14.0, *)) {
|
|
PHAccessLevel requestedAccessLevel;
|
|
if ([accessLevel isEqualToString: ADD_ONLY]) {
|
|
requestedAccessLevel = PHAccessLevelAddOnly;
|
|
} else if ([accessLevel isEqualToString: READ_WRITE]) {
|
|
requestedAccessLevel = PHAccessLevelReadWrite;
|
|
} else {
|
|
return reject(@"incorrect_access_level", @"The requested access level does not exist");
|
|
}
|
|
status = [PHPhotoLibrary authorizationStatusForAccessLevel:requestedAccessLevel];
|
|
} else {
|
|
status = [PHPhotoLibrary authorizationStatus];
|
|
}
|
|
|
|
switch (status) {
|
|
case PHAuthorizationStatusNotDetermined:
|
|
return resolve(RNPermissionStatusNotDetermined);
|
|
case PHAuthorizationStatusRestricted:
|
|
return resolve(RNPermissionStatusRestricted);
|
|
case PHAuthorizationStatusDenied:
|
|
return resolve(RNPermissionStatusDenied);
|
|
case PHAuthorizationStatusLimited:
|
|
return resolve(RNPermissionStatusLimited);
|
|
case PHAuthorizationStatusAuthorized:
|
|
return resolve(RNPermissionStatusAuthorized);
|
|
}
|
|
|
|
}
|
|
|
|
- (void)requestCameraRollReadWritePermission:(void (^ _Nonnull)(RNPermissionStatus))resolve
|
|
rejecter:(void (^ _Nonnull)(NSString *code, NSString *message))reject {
|
|
if (@available(iOS 14.0, *)) {
|
|
[PHPhotoLibrary requestAuthorizationForAccessLevel:PHAccessLevelReadWrite handler:^(__unused PHAuthorizationStatus status) {
|
|
[self checkCameraRollPermission: READ_WRITE resolver: resolve rejecter:reject];
|
|
}];
|
|
} else {
|
|
[PHPhotoLibrary requestAuthorization:^(__unused PHAuthorizationStatus status) {
|
|
[self checkCameraRollPermission: READ_WRITE resolver: resolve rejecter:reject];
|
|
}];
|
|
}
|
|
}
|
|
|
|
- (void)requestCameraRollAddOnlyPermission:(void (^ _Nonnull)(RNPermissionStatus))resolve
|
|
rejecter:(void (^ _Nonnull)(NSString *code, NSString *message))reject {
|
|
if (@available(iOS 14.0, *)) {
|
|
[PHPhotoLibrary requestAuthorizationForAccessLevel:PHAccessLevelAddOnly handler:^(__unused PHAuthorizationStatus status) {
|
|
[self checkCameraRollPermission: ADD_ONLY resolver: resolve rejecter:reject];
|
|
}];
|
|
} else {
|
|
[PHPhotoLibrary requestAuthorization:^(__unused PHAuthorizationStatus status) {
|
|
[self checkCameraRollPermission: ADD_ONLY resolver: resolve rejecter:reject];
|
|
}];
|
|
}
|
|
}
|
|
|
|
|
|
- (void)refreshLimitedPhotoselection:(RCTPromiseResolveBlock _Nonnull)resolve
|
|
rejecter:(RCTPromiseRejectBlock _Nonnull)reject {
|
|
if (@available(iOS 14, *)) {
|
|
if ([PHPhotoLibrary authorizationStatusForAccessLevel:PHAccessLevelReadWrite] != PHAuthorizationStatusLimited) {
|
|
return reject(@"cannot_open_limited_picker", @"Photo library permission isn't limited", nil);
|
|
}
|
|
|
|
UIViewController *presentedViewController = RCTPresentedViewController();
|
|
[[PHPhotoLibrary sharedPhotoLibrary] presentLimitedLibraryPickerFromViewController:presentedViewController];
|
|
|
|
resolve(@(true));
|
|
} else {
|
|
reject(@"cannot_open_limited_picker", @"Available on iOS 14 or higher", nil);
|
|
}
|
|
}
|
|
|
|
- (void)photoLibraryDidChange:(PHChange *)changeInstance
|
|
{
|
|
if (hasListeners && changeInstance != nil) {
|
|
[self sendEventWithName:@"onLibrarySelectionChange" body:@"Changes occured"];
|
|
}
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(checkPermission:
|
|
(NSString *) accessLevel
|
|
resolve: (RCTPromiseResolveBlock)resolve
|
|
reject: (RCTPromiseRejectBlock)reject) {
|
|
|
|
[self checkCameraRollPermission:accessLevel resolver:^(RNPermissionStatus status) {
|
|
resolve([self stringForStatus:status]);
|
|
} rejecter:^(NSString *code, NSString *message) {
|
|
reject(code, message, nil);
|
|
}];
|
|
}
|
|
|
|
|
|
RCT_EXPORT_METHOD(requestReadWritePermission:
|
|
(RCTPromiseResolveBlock)resolve
|
|
reject:(RCTPromiseRejectBlock)reject) {
|
|
|
|
[self requestCameraRollReadWritePermission:^(RNPermissionStatus status) {
|
|
resolve([self stringForStatus:status]);
|
|
} rejecter:^(NSString *code, NSString *message) {
|
|
reject(code, message, nil);
|
|
}];
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(requestAddOnlyPermission:
|
|
(RCTPromiseResolveBlock)resolve
|
|
reject:(RCTPromiseRejectBlock)reject) {
|
|
|
|
[self requestCameraRollAddOnlyPermission:^(RNPermissionStatus status) {
|
|
resolve([self stringForStatus:status]);
|
|
} rejecter:^(NSString *code, NSString *message) {
|
|
reject(code, message, nil);
|
|
}];
|
|
}
|
|
|
|
|
|
RCT_REMAP_METHOD(refreshPhotoSelection,
|
|
refreshLimitedPhotoselectionWithResolver:(RCTPromiseResolveBlock)resolve
|
|
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
[self refreshLimitedPhotoselection:resolve rejecter:reject];
|
|
}
|
|
|
|
@end
|
|
|