Skip to content
This repository was archived by the owner on Jun 19, 2025. It is now read-only.

Commit ce1e610

Browse files
authored
Merge pull request #383 from wordpress-mobile/issue/permission-check-adding-media
Add permission check when adding media
2 parents 4d9589b + 0b85071 commit ce1e610

File tree

7 files changed

+140
-68
lines changed

7 files changed

+140
-68
lines changed

Pod/Classes/UIViewController+MediaAdditions.m

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,11 @@
11
#import "UIViewController+MediaAdditions.h"
22
#import "WPMediaCollectionDataSource.h"
3+
#import "WPMediaPickerAlertHelper.h"
34

45
@implementation UIViewController (MediaAdditions)
56

67
- (void)wpm_showAlertWithError:(NSError *)error okActionHandler:(void (^ __nullable)(UIAlertAction *action))handler {
7-
NSString *title = NSLocalizedString(@"Media Library", @"Title for alert when a generic error happened when loading media");
8-
NSString *message = NSLocalizedString(@"There was a problem when trying to access your media. Please try again later.", @"Explaining to the user there was an generic error accesing media.");
9-
NSString *cancelText = NSLocalizedString(@"OK", "");
10-
NSString *otherButtonTitle = nil;
11-
if (error.domain == WPMediaPickerErrorDomain) {
12-
title = NSLocalizedString(@"Media Library", @"Title for alert when access to the media library is not granted by the user");
13-
if (error.code == WPMediaPickerErrorCodePermissionDenied) {
14-
otherButtonTitle = NSLocalizedString(@"Open Settings", @"Go to the settings app");
15-
message = NSLocalizedString(@"This app needs permission to access your device media library in order to add photos and/or video to your posts. Please change the privacy settings if you wish to allow this.",
16-
@"Explaining to the user why the app needs access to the device media library.");
17-
} else if (error.code == WPMediaPickerErrorCodeRestricted) {
18-
message = NSLocalizedString(@"Your app is not authorized to access media library due to active restrictions such as parental controls. Please check your parental control settings in this device.",
19-
@"Explaining to the user why the app needs access to the device media library.");
20-
}
21-
}
22-
23-
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title
24-
message:message
25-
preferredStyle:UIAlertControllerStyleAlert];
26-
UIAlertAction *okAction = [UIAlertAction actionWithTitle:cancelText
27-
style:UIAlertActionStyleCancel
28-
handler:handler];
29-
[alertController addAction:okAction];
30-
31-
if (otherButtonTitle) {
32-
UIAlertAction *otherAction = [UIAlertAction actionWithTitle:otherButtonTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
33-
NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
34-
[[UIApplication sharedApplication] openURL:settingsURL options:@{} completionHandler:nil];
35-
}];
36-
[alertController addAction:otherAction];
37-
}
8+
UIAlertController *alertController = [WPMediaPickerAlertHelper buildAlertControllerWithError:error okActionHandler:handler];
389
[self presentViewController:alertController animated:YES completion:nil];
3910
}
4011

Pod/Classes/WPMediaPicker.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@
1515
#import "WPMediaCapturePreviewCollectionView.h"
1616
#import "WPVideoPlayerView.h"
1717
#import "WPActionBar.h"
18+
#import "WPMediaPickerAlertHelper.h"
1819

1920
#endif /* _WPMEDIAPICKER_ */
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#import <Foundation/Foundation.h>
2+
3+
@interface WPMediaPickerAlertHelper : NSObject
4+
5+
+ (nonnull UIAlertController *)buildAlertControllerWithError:(NSError * _Nullable)error
6+
okActionHandler:(void (^ __nullable)(UIAlertAction * _Nullable action))handler;
7+
8+
@end
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#import "WPMediaPickerAlertHelper.h"
2+
#import "WPMediaCollectionDataSource.h"
3+
4+
@implementation WPMediaPickerAlertHelper
5+
6+
+ (nonnull UIAlertController *)buildAlertControllerWithError:(NSError * _Nullable)error
7+
okActionHandler:(void (^ __nullable)(UIAlertAction * _Nullable action))handler {
8+
NSString *title = NSLocalizedString(@"Media Library", @"Title for alert when a generic error happened when loading media");
9+
NSString *message = NSLocalizedString(@"There was a problem when trying to access your media. Please try again later.", @"Explaining to the user there was an generic error accesing media.");
10+
NSString *cancelText = NSLocalizedString(@"OK", "");
11+
NSString *otherButtonTitle = nil;
12+
if (error.domain == WPMediaPickerErrorDomain) {
13+
title = NSLocalizedString(@"Media Library", @"Title for alert when access to the media library is not granted by the user");
14+
if (error.code == WPMediaPickerErrorCodePermissionDenied) {
15+
otherButtonTitle = NSLocalizedString(@"Open Settings", @"Go to the settings app");
16+
message = NSLocalizedString(@"This app needs permission to access your device media library in order to add photos and/or video to your posts. Please change the privacy settings if you wish to allow this.",
17+
@"Explaining to the user why the app needs access to the device media library.");
18+
} else if (error.code == WPMediaPickerErrorCodeRestricted) {
19+
message = NSLocalizedString(@"Your app is not authorized to access media library due to active restrictions such as parental controls. Please check your parental control settings in this device.",
20+
@"Explaining to the user why the app needs access to the device media library.");
21+
}
22+
}
23+
24+
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title
25+
message:message
26+
preferredStyle:UIAlertControllerStyleAlert];
27+
UIAlertAction *okAction = [UIAlertAction actionWithTitle:cancelText
28+
style:UIAlertActionStyleCancel
29+
handler:handler];
30+
[alertController addAction:okAction];
31+
32+
if (otherButtonTitle) {
33+
UIAlertAction *otherAction = [UIAlertAction actionWithTitle:otherButtonTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
34+
NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
35+
[[UIApplication sharedApplication] openURL:settingsURL options:@{} completionHandler:nil];
36+
}];
37+
[alertController addAction:otherAction];
38+
}
39+
40+
return alertController;
41+
}
42+
43+
@end

Pod/Classes/WPMediaPickerViewController.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,7 @@ - (void)processMediaCaptured:(NSDictionary *)info
11931193
WPMediaAddedBlock completionBlock = ^(id<WPMediaAsset> media, NSError *error) {
11941194
if (error || !media) {
11951195
NSLog(@"Adding media failed: %@", [error localizedDescription]);
1196+
[self showError:error];
11961197
return;
11971198
}
11981199
[self addMedia:media animated:YES];

Pod/Classes/WPPHAssetDataSource.m

Lines changed: 84 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,7 @@ - (void)loadDataWithOptions:(WPMediaLoadOptions)options
131131
{
132132
[self checkPermissionStatus:^(PHAuthorizationStatus status) {
133133

134-
/// Starting from iOS 15.2 we should do the registration
135-
/// after asking user for permission
136-
/// Solution proposed here - https://developer.apple.com/forums/thread/696804
137-
///
138-
[[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];
134+
[self registerPHChangeObserver];
139135

140136
switch (status) {
141137
case PHAuthorizationStatusRestricted:
@@ -450,40 +446,82 @@ - (void)addAssetWithChangeRequest:(PHAssetChangeRequest *(^)(void))changeRequest
450446
{
451447
NSParameterAssert(changeRequestBlock);
452448
__block NSString * assetIdentifier = nil;
453-
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
454-
// Request creating an asset from the image.
455-
PHAssetChangeRequest *createAssetRequest = changeRequestBlock();
456-
PHObjectPlaceholder *assetPlaceholder = [createAssetRequest placeholderForCreatedAsset];
457-
assetIdentifier = [assetPlaceholder localIdentifier];
458-
if ([self.activeAssetsCollection canPerformEditOperation:PHCollectionEditOperationAddContent]) {
459-
// Request editing the album.
460-
PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:self.activeAssetsCollection];
461-
[albumChangeRequest addAssets:@[ assetPlaceholder ]];
462-
}
463-
} completionHandler:^(BOOL success, NSError *error) {
464-
if (!success) {
465-
if (completionBlock){
466-
dispatch_async(dispatch_get_main_queue(), ^{
467-
completionBlock(nil, error);
468-
});
449+
450+
[self checkPermissionStatus:^(PHAuthorizationStatus status) {
451+
452+
[self registerPHChangeObserver];
453+
454+
switch (status) {
455+
case PHAuthorizationStatusRestricted:
456+
{
457+
if (completionBlock) {
458+
dispatch_async(dispatch_get_main_queue(), ^{
459+
NSError *error = [NSError errorWithDomain:WPMediaPickerErrorDomain code:WPMediaPickerErrorCodeRestricted userInfo:nil];
460+
completionBlock(nil, error);
461+
});
462+
}
463+
return;
469464
}
470-
return;
471-
}
472-
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
473-
fetchOptions.predicate = [NSPredicate predicateWithFormat:@"(localIdentifier == %@)", assetIdentifier];
474-
PHFetchResult * result = [PHAsset fetchAssetsWithOptions:fetchOptions];
475-
if (result.count < 1){
476-
if (completionBlock){
477-
dispatch_async(dispatch_get_main_queue(), ^{
478-
completionBlock(nil, error);
465+
case PHAuthorizationStatusDenied:
466+
case PHAuthorizationStatusLimited:
467+
{
468+
if (completionBlock) {
469+
dispatch_async(dispatch_get_main_queue(), ^{
470+
NSError *error = [NSError errorWithDomain:WPMediaPickerErrorDomain code:WPMediaPickerErrorCodePermissionDenied userInfo:nil];
471+
completionBlock(nil, error);
472+
});
473+
}
474+
return;
475+
}
476+
case PHAuthorizationStatusNotDetermined:
477+
{
478+
[self checkPermissionStatus:^(PHAuthorizationStatus status) {
479+
[self addAssetWithChangeRequest:changeRequestBlock completionBlock:completionBlock];
480+
}];
481+
return;
482+
}
483+
case PHAuthorizationStatusAuthorized:
484+
{
485+
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
486+
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
487+
// Request creating an asset from the image.
488+
PHAssetChangeRequest *createAssetRequest = changeRequestBlock();
489+
PHObjectPlaceholder *assetPlaceholder = [createAssetRequest placeholderForCreatedAsset];
490+
assetIdentifier = [assetPlaceholder localIdentifier];
491+
if ([self.activeAssetsCollection canPerformEditOperation:PHCollectionEditOperationAddContent]) {
492+
// Request editing the album.
493+
PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:self.activeAssetsCollection];
494+
[albumChangeRequest addAssets:@[ assetPlaceholder ]];
495+
}
496+
} completionHandler:^(BOOL success, NSError *error) {
497+
if (!success) {
498+
if (completionBlock){
499+
dispatch_async(dispatch_get_main_queue(), ^{
500+
completionBlock(nil, error);
501+
});
502+
}
503+
return;
504+
}
505+
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
506+
fetchOptions.predicate = [NSPredicate predicateWithFormat:@"(localIdentifier == %@)", assetIdentifier];
507+
PHFetchResult * result = [PHAsset fetchAssetsWithOptions:fetchOptions];
508+
if (result.count < 1){
509+
if (completionBlock){
510+
dispatch_async(dispatch_get_main_queue(), ^{
511+
completionBlock(nil, error);
512+
});
513+
}
514+
return;
515+
}
516+
if (completionBlock) {
517+
dispatch_async(dispatch_get_main_queue(), ^{
518+
completionBlock([result firstObject], nil);
519+
});
520+
}
521+
}];
479522
});
523+
return;
480524
}
481-
return;
482-
}
483-
if (completionBlock) {
484-
dispatch_async(dispatch_get_main_queue(), ^{
485-
completionBlock([result firstObject], nil);
486-
});
487525
}
488526
}];
489527
}
@@ -495,6 +533,16 @@ - (void)setMediaTypeFilter:(WPMediaType)filter
495533
_refreshGroups = YES;
496534
}
497535

536+
- (void)registerPHChangeObserver
537+
{
538+
539+
/// Starting from iOS 15.2 we should do the registration
540+
/// after asking user for permission
541+
/// Solution proposed here - https://developer.apple.com/forums/thread/696804
542+
///
543+
[[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];
544+
}
545+
498546
@end
499547

500548
#pragma mark - WPPHAssetMedia

WPMediaPicker.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Pod::Spec.new do |s|
44
s.name = 'WPMediaPicker'
5-
s.version = '1.8.2'
5+
s.version = '1.8.3-beta.1'
66

77
s.summary = 'WPMediaPicker is an iOS controller that allows capture and picking of media assets.'
88
s.description = <<-DESC

0 commit comments

Comments
 (0)