//Copyright (c) 2015 Katsuma Tanaka //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to //deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or //sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS //IN THE SOFTWARE. #import "UGCKitAlbumsViewController.h" #import // Views #import "UGCKitAlbumCell.h" // ViewControllers #import "UGCKitMediaPickerViewControllerPrivate.h" #import "UGCKitAssetsViewController.h" static CGSize CGSizeScale(CGSize size, CGFloat scale) { return CGSizeMake(size.width * scale, size.height * scale); } @interface UGCKitMediaPickerViewController (Private) @property (nonatomic, strong) NSBundle *assetBundle; @end @interface UGCKitAlbumsViewController () @property (nonatomic, strong) IBOutlet UIBarButtonItem *doneButton; @property (nonatomic, copy) NSArray *fetchResults; @end @implementation UGCKitAlbumsViewController - (void)viewDidLoad { [super viewDidLoad]; [self setUpToolbarItems]; /* // Fetch user albums and smart albums __weak __typeof(self) weakSelf = self; void (^doFetch)(void) = ^{ __strong __typeof(weakSelf) self = weakSelf; PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAny options:nil]; PHFetchResult *userAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAny options:nil]; self.fetchResults = @[smartAlbums, userAlbums]; [self updateAssetCollections]; [self.tableView reloadData]; }; // Register observer [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self]; if (PHAuthorizationStatusAuthorized != [PHPhotoLibrary authorizationStatus]) { [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { if (PHAuthorizationStatusAuthorized == status) { dispatch_async(dispatch_get_main_queue(), doFetch); } }]; } else { doFetch(); } */ } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // Configure navigation item self.navigationItem.title = [_theme localizedString:@"UGCKit.MediaPicker.Title"]; self.navigationItem.prompt = self.imagePickerController.config.prompt; // Show/hide 'Done' button if (self.imagePickerController.allowsMultipleSelection) { [self.navigationItem setRightBarButtonItem:self.doneButton animated:NO]; } else { [self.navigationItem setRightBarButtonItem:nil animated:NO]; } [self updateControlState]; [self updateSelectionInfo]; } - (void)dealloc { // Deregister observer [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self]; } #pragma mark - Storyboard - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { UGCKitAssetsViewController *assetsViewController = segue.destinationViewController; assetsViewController.theme = _theme; assetsViewController.imagePickerController = self.imagePickerController; assetsViewController.assetCollection = self.assetCollections[self.tableView.indexPathForSelectedRow.row]; } #pragma mark - Actions - (IBAction)cancel:(id)sender { [self dismissViewControllerAnimated:YES completion:nil]; } - (IBAction)done:(id)sender { } #pragma mark - Toolbar - (void)setUpToolbarItems { // Space UIBarButtonItem *leftSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL]; UIBarButtonItem *rightSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL]; // Info label NSDictionary *attributes = @{ NSForegroundColorAttributeName: [UIColor blackColor] }; UIBarButtonItem *infoButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:NULL]; infoButtonItem.enabled = NO; [infoButtonItem setTitleTextAttributes:attributes forState:UIControlStateNormal]; [infoButtonItem setTitleTextAttributes:attributes forState:UIControlStateDisabled]; self.toolbarItems = @[leftSpace, infoButtonItem, rightSpace]; } - (void)updateSelectionInfo { NSMutableOrderedSet *selectedAssets = self.imagePickerController.selectedAssets; if (selectedAssets.count > 0) { NSString *format; if (selectedAssets.count > 1) { format = [_theme localizedString:@"UGCKit.MediaPicker.Toolbar.ItemsSelected"]; } else { format = [_theme localizedString:@"UGCKit.MediaPicker.Toolbar.ItemSelected"]; } NSString *title = [NSString stringWithFormat:format, selectedAssets.count]; [(UIBarButtonItem *)self.toolbarItems[1] setTitle:title]; } else { [(UIBarButtonItem *)self.toolbarItems[1] setTitle:@""]; } } #pragma mark - Fetching Asset Collections - (void)updateAssetCollections { // Filter albums NSArray *assetCollectionSubtypes = self.imagePickerController.assetCollectionSubtypes; NSMutableDictionary *smartAlbums = [NSMutableDictionary dictionaryWithCapacity:assetCollectionSubtypes.count]; NSMutableArray *userAlbums = [NSMutableArray array]; for (PHFetchResult *fetchResult in self.fetchResults) { [fetchResult enumerateObjectsUsingBlock:^(PHAssetCollection *assetCollection, NSUInteger index, BOOL *stop) { PHAssetCollectionSubtype subtype = assetCollection.assetCollectionSubtype; if (subtype == PHAssetCollectionSubtypeAlbumRegular) { [userAlbums addObject:assetCollection]; } else if ([assetCollectionSubtypes containsObject:@(subtype)]) { if (!smartAlbums[@(subtype)]) { smartAlbums[@(subtype)] = [NSMutableArray array]; } [smartAlbums[@(subtype)] addObject:assetCollection]; } }]; } NSMutableArray *assetCollections = [NSMutableArray array]; // Fetch smart albums for (NSNumber *assetCollectionSubtype in assetCollectionSubtypes) { NSArray *collections = smartAlbums[assetCollectionSubtype]; if (collections) { [assetCollections addObjectsFromArray:collections]; } } // Fetch user albums [userAlbums enumerateObjectsUsingBlock:^(PHAssetCollection *assetCollection, NSUInteger index, BOOL *stop) { [assetCollections addObject:assetCollection]; }]; self.assetCollections = assetCollections; } - (UIImage *)placeholderImageWithSize:(CGSize)size { UIGraphicsBeginImageContext(size); CGContextRef context = UIGraphicsGetCurrentContext(); UIColor *backgroundColor = [UIColor colorWithRed:(239.0 / 255.0) green:(239.0 / 255.0) blue:(244.0 / 255.0) alpha:1.0]; UIColor *iconColor = [UIColor colorWithRed:(179.0 / 255.0) green:(179.0 / 255.0) blue:(182.0 / 255.0) alpha:1.0]; // Background CGContextSetFillColorWithColor(context, [backgroundColor CGColor]); CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height)); // Icon (back) CGRect backIconRect = CGRectMake(size.width * (16.0 / 68.0), size.height * (20.0 / 68.0), size.width * (32.0 / 68.0), size.height * (24.0 / 68.0)); CGContextSetFillColorWithColor(context, [iconColor CGColor]); CGContextFillRect(context, backIconRect); CGContextSetFillColorWithColor(context, [backgroundColor CGColor]); CGContextFillRect(context, CGRectInset(backIconRect, 1.0, 1.0)); // Icon (front) CGRect frontIconRect = CGRectMake(size.width * (20.0 / 68.0), size.height * (24.0 / 68.0), size.width * (32.0 / 68.0), size.height * (24.0 / 68.0)); CGContextSetFillColorWithColor(context, [backgroundColor CGColor]); CGContextFillRect(context, CGRectInset(frontIconRect, -1.0, -1.0)); CGContextSetFillColorWithColor(context, [iconColor CGColor]); CGContextFillRect(context, frontIconRect); CGContextSetFillColorWithColor(context, [backgroundColor CGColor]); CGContextFillRect(context, CGRectInset(frontIconRect, 1.0, 1.0)); UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } #pragma mark - Checking for Selection Limit - (BOOL)isMinimumSelectionLimitFulfilled { return (self.imagePickerController.minimumNumberOfSelection <= self.imagePickerController.selectedAssets.count); } - (BOOL)isMaximumSelectionLimitReached { NSUInteger minimumNumberOfSelection = MAX(1, self.imagePickerController.minimumNumberOfSelection); if (minimumNumberOfSelection <= self.imagePickerController.maximumNumberOfSelection) { return (self.imagePickerController.maximumNumberOfSelection <= self.imagePickerController.selectedAssets.count); } return NO; } - (void)updateControlState { self.doneButton.enabled = [self isMinimumSelectionLimitFulfilled]; } #pragma mark - UITableViewDataSource - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.assetCollections.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UGCKitAlbumCell *cell = [tableView dequeueReusableCellWithIdentifier:@"AlbumCell" forIndexPath:indexPath]; cell.accessoryView = [[UIImageView alloc] initWithImage:_theme.rightArrowIcon]; cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.backgroundColor = [UIColor whiteColor]; cell.tag = indexPath.row; cell.borderWidth = 1.0 / self.traitCollection.displayScale; // Thumbnail PHAssetCollection *assetCollection = self.assetCollections[indexPath.row]; PHFetchOptions *options = [PHFetchOptions new]; switch (self.imagePickerController.mediaType) { case UGCKitMediaTypePhoto: options.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage]; break; case UGCKitMediaTypeVideo: options.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeVideo]; break; default: break; } PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:options]; PHImageManager *imageManager = [PHImageManager defaultManager]; if (fetchResult.count >= 3) { cell.imageView3.hidden = NO; [imageManager requestImageForAsset:fetchResult[fetchResult.count - 3] targetSize:CGSizeScale(cell.imageView3.frame.size, self.traitCollection.displayScale) contentMode:PHImageContentModeAspectFill options:nil resultHandler:^(UIImage *result, NSDictionary *info) { if (cell.tag == indexPath.row) { cell.imageView3.image = result; } }]; } else { cell.imageView3.hidden = YES; } if (fetchResult.count >= 2) { cell.imageView2.hidden = NO; [imageManager requestImageForAsset:fetchResult[fetchResult.count - 2] targetSize:CGSizeScale(cell.imageView2.frame.size, self.traitCollection.displayScale) contentMode:PHImageContentModeAspectFill options:nil resultHandler:^(UIImage *result, NSDictionary *info) { if (cell.tag == indexPath.row) { cell.imageView2.image = result; } }]; } else { cell.imageView2.hidden = YES; } if (fetchResult.count >= 1) { [imageManager requestImageForAsset:fetchResult[fetchResult.count - 1] targetSize:CGSizeScale(cell.imageView1.frame.size, self.traitCollection.displayScale) contentMode:PHImageContentModeAspectFill options:nil resultHandler:^(UIImage *result, NSDictionary *info) { if (cell.tag == indexPath.row) { cell.imageView1.image = result; } }]; } if (fetchResult.count == 0) { cell.imageView3.hidden = NO; cell.imageView2.hidden = NO; // Set placeholder image UIImage *placeholderImage = [self placeholderImageWithSize:cell.imageView1.frame.size]; cell.imageView1.image = placeholderImage; cell.imageView2.image = placeholderImage; cell.imageView3.image = placeholderImage; } // Album title cell.titleLabel.text = assetCollection.localizedTitle; // Number of photos cell.countLabel.text = [NSString stringWithFormat:@"%lu", (long)fetchResult.count]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { PHAssetCollection *collection = self.assetCollections[indexPath.row]; if (self.onPickAssetCollection) { self.onPickAssetCollection(collection); } } #pragma mark - PHPhotoLibraryChangeObserver - (void)photoLibraryDidChange:(PHChange *)changeInstance { dispatch_async(dispatch_get_main_queue(), ^{ // Update fetch results NSMutableArray *fetchResults = [self.fetchResults mutableCopy]; [self.fetchResults enumerateObjectsUsingBlock:^(PHFetchResult *fetchResult, NSUInteger index, BOOL *stop) { PHFetchResultChangeDetails *changeDetails = [changeInstance changeDetailsForFetchResult:fetchResult]; if (changeDetails) { [fetchResults replaceObjectAtIndex:index withObject:changeDetails.fetchResultAfterChanges]; } }]; if (![self.fetchResults isEqualToArray:fetchResults]) { self.fetchResults = fetchResults; // Reload albums [self updateAssetCollections]; [self.tableView reloadData]; } }); } @end