Skip to content
This repository has been archived by the owner on Nov 29, 2022. It is now read-only.

Google Images integration. Fixes #111 #119

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion DZNPhotoPickerController.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Pod::Spec.new do |s|
ss.source_files = 'Source/Classes/Core/*.{h,m}'
ss.dependency 'DZNPhotoPickerController/Services'
ss.dependency 'DZNPhotoPickerController/Editor'
ss.dependency 'SDWebImage', '~> 3.7'
ss.dependency 'SDWebImage', '~> 4.0'
ss.dependency 'DZNEmptyDataSet', '~> 1.7'
end

Expand Down
1 change: 1 addition & 0 deletions Source/Classes/Core/DZNPhotoDisplayViewCell.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#import "DZNPhotoDisplayViewCell.h"
#import "UIImageView+WebCache.h"
#import "UIView+WebCache.h"

@implementation DZNPhotoDisplayViewCell
@synthesize imageView = _imageView;
Expand Down
2 changes: 1 addition & 1 deletion Source/Classes/Core/DZNPhotoDisplayViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
@interface DZNPhotoDisplayViewController : UICollectionViewController <UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating>

/** The nearest ancestor in the view controller hierarchy that is a photo picker controller. */
@property (nonatomic, readonly) DZNPhotoPickerController *navigationController;
@property (nonatomic, readonly) DZNPhotoPickerController *pickerController;
/** The view controller's search controller. */
@property (nonatomic, readonly) UISearchController *searchController;
/** The count number of rows of thumbs to be diplayed. */
Expand Down
72 changes: 44 additions & 28 deletions Source/Classes/Core/DZNPhotoDisplayViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ - (void)loadView
{
[super loadView];

_segmentedControlTitles = NSArrayFromServices(self.navigationController.supportedServices);
_segmentedControlTitles = NSArrayFromServices(self.pickerController.supportedServices);
NSAssert((_segmentedControlTitles.count <= 4), @"DZNPhotoPickerController doesn't support more than 4 photo service providers");

_selectedService = DZNFirstPhotoServiceFromPhotoServices(self.navigationController.supportedServices);
_selectedService = DZNFirstPhotoServiceFromPhotoServices(self.pickerController.supportedServices);
NSAssert((_selectedService > 0), @"DZNPhotoPickerController requieres at least 1 supported photo service provider");

self.extendedLayoutIncludesOpaqueBars = YES;
Expand Down Expand Up @@ -128,6 +128,17 @@ - (void)viewWillAppear:(BOOL)animated
}
}

- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];

if (([self.searchController.searchBar.text length] == 0) && (self.metadataList.count == 0)) {
// Calling becomeFirstResponder directly doesn't open the keybord for some reason
dispatch_async(dispatch_get_main_queue(), ^{
[self.searchController.searchBar becomeFirstResponder];
});
}
}

#pragma mark - Getter methods

Expand Down Expand Up @@ -159,10 +170,10 @@ + (UICollectionViewFlowLayout *)layoutFittingSize:(CGSize)size
return [[DZNPhotoServiceFactory defaultFactory] clientForService:self.selectedService];
}

/* Returns the navigation controller casted to DZNPhotoPickerController. */
- (DZNPhotoPickerController *)navigationController
///* Returns the navigation controller casted to DZNPhotoPickerController. */
- (DZNPhotoPickerController *)pickerController
{
return (DZNPhotoPickerController *)[super navigationController];
return (DZNPhotoPickerController *) self.parentViewController;
}

/* Returns the custom search display controller. */
Expand All @@ -176,12 +187,13 @@ - (UISearchController *)searchController
_searchController.searchResultsUpdater = self;
_searchController.delegate = self;
_searchController.dimsBackgroundDuringPresentation = YES;
_searchController.hidesNavigationBarDuringPresentation = YES;
_searchController.hidesNavigationBarDuringPresentation = NO;

UISearchBar *searchBar = _searchController.searchBar;
[searchBar sizeToFit];
searchBar.placeholder = NSLocalizedString(@"Search", nil);
searchBar.text = self.navigationController.initialSearchTerm;
searchBar.scopeButtonTitles = self.segmentedControlTitles;
searchBar.text = self.pickerController.initialSearchTerm;
searchBar.scopeButtonTitles = [self segmentedControlTitles];
searchBar.searchBarStyle = UISearchBarStyleProminent;
searchBar.barStyle = UIBarStyleDefault;
searchBar.selectedScopeButtonIndex = 0;
Expand Down Expand Up @@ -418,16 +430,16 @@ - (void)resetPhotos
*/
- (void)selectedMetadata:(DZNPhotoMetadata *)metadata
{
if (!self.navigationController.enablePhotoDownload) {
if (!self.pickerController.enablePhotoDownload) {
[metadata postMetadataUpdate:nil];
}
else if (self.navigationController.allowsEditing) {
else if (self.pickerController.allowsEditing) {

UIImage *image = [[SDImageCache sharedImageCache] imageFromMemoryCacheForKey:metadata.sourceURL.absoluteString];

DZNPhotoEditorViewController *controller = [[DZNPhotoEditorViewController alloc] initWithImage:image];
controller.cropMode = self.navigationController.cropMode;
controller.cropSize = self.navigationController.cropSize;
controller.cropMode = self.pickerController.cropMode;
controller.cropSize = self.pickerController.cropSize;

[self.navigationController pushViewController:controller animated:YES];

Expand Down Expand Up @@ -464,28 +476,29 @@ - (void)selectedMetadata:(DZNPhotoMetadata *)metadata
}
}
else {
[self setActivityIndicatorsVisible:YES];

self.pickerController.activityBlock(self.pickerController, YES);
[[SDWebImageDownloader sharedDownloader] downloadImageWithURL:metadata.sourceURL
options:SDWebImageCacheMemoryOnly|SDWebImageRetryFailed
progress:NULL
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished){
if (image) {
NSDictionary *userInfo = @{UIImagePickerControllerOriginalImage: image};
[metadata postMetadataUpdate:userInfo];
}
else {
[self setLoadingError:error];
}

[self setActivityIndicatorsVisible:NO];
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
dispatch_async(dispatch_get_main_queue(), ^{
if (image) {
NSDictionary *userInfo = @{UIImagePickerControllerOriginalImage: image};
[metadata postMetadataUpdate:userInfo];
}
else {
[self setLoadingError:error];
}

self.pickerController.activityBlock(self.pickerController, NO);
});
}];
}
}

- (BOOL)canSearchTags
{
if (!self.navigationController.allowAutoCompletedSearch) {
if (!self.pickerController.allowAutoCompletedSearch) {
return NO;
}

Expand Down Expand Up @@ -643,7 +656,7 @@ - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
UIView *subview = nil;

if ([self canDisplayFooterView]) {
if (self.isLoading || self.navigationController.infiniteScrollingEnabled) {
if (self.isLoading || self.pickerController.infiniteScrollingEnabled) {
subview = self.activityIndicator;
}
else {
Expand Down Expand Up @@ -685,7 +698,7 @@ - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
{
if ([elementKind isEqualToString:UICollectionElementKindSectionFooter]) {
if (self.navigationController.infiniteScrollingEnabled && [self canDisplayFooterView] && !self.isLoading) {
if (self.pickerController.infiniteScrollingEnabled && [self canDisplayFooterView] && !self.isLoading) {

// It is important to schedule this call on the next run loop so it doesn't
// interfere with the current scroll's run loop.
Expand Down Expand Up @@ -900,7 +913,10 @@ - (NSAttributedString *)descriptionForEmptyDataSet:(UIScrollView *)scrollView
text = localizedDescription;
}
else if (!self.loading) {
text = NSLocalizedString(@"Make sure that all words are\nspelled correctly.", nil);
if (self.pickerController.initialSearchTerm)
text = NSLocalizedString(@"Make sure that all words are\nspelled correctly.", nil);
else
text = nil;
}

if (text) {
Expand Down
6 changes: 5 additions & 1 deletion Source/Classes/Core/DZNPhotoPickerController.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@

@discussion Due to Terms of Use of some photo services, the images can only be cached in memory, but not the device's hard drive.
*/
@interface DZNPhotoPickerController : UINavigationController
@interface DZNPhotoPickerController : UIViewController

typedef void (^DZNPhotoPickerControllerActivityBlock)(DZNPhotoPickerController *picker, BOOL show);
typedef void (^DZNPhotoPickerControllerFinalizationBlock)(DZNPhotoPickerController *picker, NSDictionary *info);
typedef void (^DZNPhotoPickerControllerFailureBlock)(DZNPhotoPickerController *picker, NSError *error);
typedef void (^DZNPhotoPickerControllerCancellationBlock)(DZNPhotoPickerController *picker);
Expand All @@ -41,6 +42,9 @@ typedef void (^DZNPhotoPickerControllerCancellationBlock)(DZNPhotoPickerControll
@property (nonatomic) DZNPhotoPickerControllerCCLicenses supportedLicenses;
/** YES if the picker should download the full size photo after selecting its thumbnail, when allowsEditing is NO. Default is YES. */
@property (nonatomic) BOOL enablePhotoDownload;

@property (nonatomic, strong) DZNPhotoPickerControllerActivityBlock activityBlock;

/** A block to be executed whenever the user pickes a new photo. Use this block to replace delegate method photoPickerController:didFinishPickingPhotoWithInfo: */
@property (nonatomic, strong) DZNPhotoPickerControllerFinalizationBlock finalizationBlock;
/** A block to be executed whenever an error occurs while picking a photo. Use this block to replace delegate method photoPickerController:didFailedPickingPhotoWithError: */
Expand Down
21 changes: 16 additions & 5 deletions Source/Classes/Core/DZNPhotoPickerController.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

@interface DZNPhotoPickerController ()
@property (nonatomic, getter=isEditModeEnabled) BOOL editModeEnabled;
@property (nonatomic, assign) BOOL firstAppear;
@end

@implementation DZNPhotoPickerController
Expand All @@ -33,8 +34,9 @@ - (id)init
self.allowsEditing = NO;
self.enablePhotoDownload = YES;
self.allowAutoCompletedSearch = YES;
self.firstAppear = YES;

self.supportedServices = DZNPhotoPickerControllerService500px | DZNPhotoPickerControllerServiceFlickr;
self.supportedServices = DZNPhotoPickerControllerServiceGoogleImages | DZNPhotoPickerControllerServiceFlickr | DZNPhotoPickerControllerServiceBingImages;
self.supportedLicenses = DZNPhotoPickerControllerCCLicenseBY_ALL;
self.cropMode = DZNPhotoEditorViewControllerCropModeSquare;
}
Expand All @@ -58,7 +60,8 @@ - (void)viewWillAppear:(BOOL)animated
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didFinishPickingPhoto:) name:DZNPhotoPickerDidFinishPickingNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didFailPickingPhoto:) name:DZNPhotoPickerDidFailPickingNotification object:nil];

if (!self.isEditModeEnabled) {
if (!self.isEditModeEnabled && self.firstAppear) {
self.firstAppear = NO;
[self showPhotoDisplayController];
}
}
Expand Down Expand Up @@ -120,7 +123,6 @@ + (void)registerService:(DZNPhotoPickerControllerServices)service consumerKey:(N
/* Shows the photo display controller. */
- (void)showPhotoDisplayController
{
[self setViewControllers:@[]];

DZNPhotoDisplayViewController *controller = [[DZNPhotoDisplayViewController alloc] initWithPreferredContentSize:self.view.frame.size];
if (self.title) controller.title = self.title;
Expand All @@ -130,7 +132,16 @@ - (void)showPhotoDisplayController
[controller.navigationItem setRightBarButtonItem:cancel];
}

[self setViewControllers:@[controller]];
[self addChildViewController:controller];
[self.view addSubview:controller.view];

controller.view.translatesAutoresizingMaskIntoConstraints = false;
[NSLayoutConstraint activateConstraints:@[[controller.view.topAnchor constraintEqualToAnchor:self.view.topAnchor],
[controller.view.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[controller.view.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
[controller.view.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor]]];

[controller didMoveToParentViewController:self];
}

/* Called by a notification whenever the user picks a photo. */
Expand Down Expand Up @@ -158,7 +169,7 @@ - (void)didFailPickingPhoto:(NSNotification *)notification
/* Called whenever the user cancels the picker. */
- (void)cancelPicker:(id)sender
{
DZNPhotoDisplayViewController *controller = (DZNPhotoDisplayViewController *)[self.viewControllers firstObject];
DZNPhotoDisplayViewController *controller = (DZNPhotoDisplayViewController *)[self.childViewControllers firstObject];
if ([controller respondsToSelector:@selector(stopLoadingRequest)]) {
[controller stopLoadingRequest];
}
Expand Down
31 changes: 26 additions & 5 deletions Source/Classes/Services/DZNPhotoServiceClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -150,17 +150,16 @@ - (NSDictionary *)photosParamsWithKeyword:(NSString *)keyword page:(NSInteger)pa
[params setObject:[self consumerSecret] forKey:keyForAPIConsumerSecret(self.service)];
[params setObject:@"image" forKey:@"searchType"];
[params setObject:@"medium" forKey:@"safe"];

if (page > 1) {
[params setObject:@((page - 1) * resultPerPage + 1) forKey:@"start"];
}
[params setObject:@(10) forKey:@"num"];
[params setObject:@(page ? page * resultPerPage + 1 : 1) forKey:@"start"];
}
else if (self.service == DZNPhotoPickerControllerServiceBingImages)
{
[params setObject:@"'Moderate'" forKey:@"Adult"];

// Default to size medium. Size Large causes some buggy behavior with download times.
[params setObject:@"'Size:Medium'" forKey:@"ImageFilters"];
[params setObject:@"Image" forKey:@"Source"];

// Top and skip are like limit and offset
[params setObject:@(resultPerPage) forKey:@"$top"];
Expand Down Expand Up @@ -244,7 +243,29 @@ - (void)searchPhotosWithKeyword:(NSString *)keyword page:(NSInteger)page resultP
NSString *path = photoSearchUrlPathForService(self.service);

NSDictionary *params = [self photosParamsWithKeyword:keyword page:page resultPerPage:resultPerPage];
[self getObject:[DZNPhotoMetadata class] path:path params:params completion:completion];
__block NSMutableArray * aggregate = [NSMutableArray arrayWithCapacity:resultPerPage];
__block NSInteger currentPage = [[params objectForKey:keyForSearchPage(self.service)] integerValue];
NSLog(@"starting with currentPage %ul", currentPage);
__block DZNHTTPRequestCompletion recursive = ^(NSArray *list, NSError *error) {
if (error)
completion(nil, error);

[aggregate addObjectsFromArray:list];
currentPage = currentPage + list.count;
if ((aggregate.count < resultPerPage) && list.count) {
NSLog(@"asking for more at %ul after receiving %ul", currentPage, list.count);
[params setValue:@(currentPage) forKey:keyForSearchPage(self.service)];
[params setValue:MIN(@(resultPerPage - aggregate.count),[params objectForKey:keyForSearchResultPerPage(self.service)]) forKey:keyForSearchResultPerPage(self.service)];
[self getObject:[DZNPhotoMetadata class] path:path params:params completion:recursive];
} else {
NSLog(@"received all items %ul",aggregate.count);
completion(aggregate, nil);
}
};

[self getObject:[DZNPhotoMetadata class] path:path params:params completion:recursive];


}

- (void)getObject:(Class)class path:(NSString *)path params:(NSDictionary *)params completion:(DZNHTTPRequestCompletion)completion
Expand Down
1 change: 1 addition & 0 deletions Source/Classes/Services/DZNPhotoServiceConstants.m
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
NSString *keyForSearchPage(DZNPhotoPickerControllerServices service)
{
switch (service) {
case DZNPhotoPickerControllerServiceGoogleImages: return @"start";
case DZNPhotoPickerControllerServiceBingImages: return nil;
default: return @"page";
}
Expand Down

This file was deleted.

Loading