Skip to content
This repository was archived by the owner on Jun 19, 2025. It is now read-only.
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
7 changes: 2 additions & 5 deletions Pod/Classes/WPMediaCollectionViewCell.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
@import UIKit;
#import "WPMediaCollectionDataSource.h"

@interface WPMediaCollectionViewCell : UICollectionViewCell

@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) id<WPMediaAsset> asset;
@property (nonatomic, assign) NSInteger position;

- (void)setCaption:(NSString *)caption;

- (void)setImage:(UIImage *)image animated:(BOOL)animated withAccessibilityLabel:(NSString*)accessibilityLabel;

@end
92 changes: 84 additions & 8 deletions Pod/Classes/WPMediaCollectionViewCell.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#import "WPMediaCollectionViewCell.h"

static const NSTimeInterval ThredsholdForAnimation = 0.03;
static const CGFloat TimeForFadeAnimation = 0.3;

@interface WPMediaCollectionViewCell ()

@property (nonatomic, strong) UILabel *positionLabel;
Expand Down Expand Up @@ -32,7 +35,11 @@ - (id)initWithCoder:(NSCoder *)aDecoder
- (void)prepareForReuse
{
[super prepareForReuse];
[self setImage:nil];
if (self.tag != 0) {
[self.asset cancelImageRequest:(WPMediaRequestID)self.tag];
}
self.tag = 0;
[self setImage:nil animated:NO];
[self setCaption:@""];
[self setPosition:NSNotFound];
[self setSelected:NO];
Expand Down Expand Up @@ -72,28 +79,97 @@ - (void)commonInit
[self.contentView addSubview:_captionLabel];
}

- (void)setImage:(UIImage *)image withAccessibilityLabel:(NSString*)accessibilityLabel
- (void)setAsset:(id<WPMediaAsset>)asset {
_asset = asset;
__block WPMediaRequestID requestKey = 0;
NSTimeInterval timestamp = [NSDate timeIntervalSinceReferenceDate];
requestKey = [_asset imageWithSize:self.frame.size completionHandler:^(UIImage *result, NSError *error) {
BOOL animated = ([NSDate timeIntervalSinceReferenceDate] - timestamp) > ThredsholdForAnimation;
if (error) {
self.image = nil;
NSLog(@"%@", [error localizedDescription]);
return;
}
// Did this request changed meanwhile
if (requestKey != self.tag) {
return;
}
if ([NSThread isMainThread]){
[self setImage:result
animated:animated];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self setImage:result
animated:animated];
});
}
}];
self.tag = requestKey;
NSString *label = @"";
NSString *caption = @"";
WPMediaType assetType = _asset.assetType;
switch (assetType) {
case WPMediaTypeImage:
label = [NSString stringWithFormat:NSLocalizedString(@"Image, %@", @"Accessibility label for image thumbnails in the media collection view. The parameter is the creation date of the image."),
[[[self class] dateFormatter] stringFromDate:_asset.date]];
break;
case WPMediaTypeVideo:
label = [NSString stringWithFormat:NSLocalizedString(@"Video, %@", @"Accessibility label for video thumbnails in the media collection view. The parameter is the creation date of the video."),
[[[self class] dateFormatter] stringFromDate:_asset.date]];
NSTimeInterval duration = [asset duration];
caption = [self stringFromTimeInterval:duration];
break;
default:
break;
}
self.imageView.accessibilityLabel = label;
[self setCaption:caption];
}

+ (NSDateFormatter *) dateFormatter {
static NSDateFormatter *_dateFormatter = nil;
static dispatch_once_t _onceToken;
dispatch_once(&_onceToken, ^{
_dateFormatter = [[NSDateFormatter alloc] init];
_dateFormatter.dateStyle = NSDateFormatterMediumStyle;
_dateFormatter.timeStyle = NSDateFormatterMediumStyle;
});

return _dateFormatter;
}

- (NSString *)stringFromTimeInterval:(NSTimeInterval)timeInterval
{
NSInteger roundedHours = floor(timeInterval / 3600);
NSInteger roundedMinutes = floor((timeInterval - (3600 * roundedHours)) / 60);
NSInteger roundedSeconds = round(timeInterval - (roundedHours * 60 * 60) - (roundedMinutes * 60));

if (roundedHours > 0)
return [NSString stringWithFormat:@"%ld:%02ld:%02ld", (long)roundedHours, (long)roundedMinutes, (long)roundedSeconds];

else
return [NSString stringWithFormat:@"%ld:%02ld", (long)roundedMinutes, (long)roundedSeconds];
}

- (void)setImage:(UIImage *)image
{
[self setImage:image animated:YES withAccessibilityLabel:accessibilityLabel];
[self setImage:image animated:YES];
}

- (void)setImage:(UIImage *)image animated:(BOOL)animated withAccessibilityLabel:(NSString*)accessibilityLabel
- (void)setImage:(UIImage *)image animated:(BOOL)animated
{
if (!image){
self.imageView.alpha = 0;
self.imageView.image = nil;
self.imageView.accessibilityLabel = nil;
} else {
if (animated) {
[UIView animateWithDuration:0.3 animations:^{
[UIView animateWithDuration:TimeForFadeAnimation animations:^{
self.imageView.alpha = 1.0;
self.imageView.image = image;
self.imageView.accessibilityLabel = accessibilityLabel;
}];
} else {
self.imageView.alpha = 1.0;
self.imageView.image = image;
self.imageView.accessibilityLabel = accessibilityLabel;
}
}
}
Expand Down
74 changes: 2 additions & 72 deletions Pod/Classes/WPMediaCollectionViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -380,24 +380,6 @@ - (BOOL)isCaptureCellIndexPath:(NSIndexPath *)indexPath
return asset;
}

- (NSString *)accessibilityLabelForType:(WPMediaType)assetType atIndexPath:(NSInteger)index
{
NSString *accessibilityLabelFormat;
switch (assetType) {
case WPMediaTypeImage:
accessibilityLabelFormat = NSLocalizedString(@"Asset %d, image.", @"Accessibility label for image thumbnails in the media collection view. The parameter is the index of the image in the collection view.");
break;
case WPMediaTypeVideo:
accessibilityLabelFormat = NSLocalizedString(@"Asset %d, video", @"Accessibility label for video thumbnails in the media collection view. The parameter is the index of the video in the collection view.");
break;
default:
accessibilityLabelFormat = NSLocalizedString(@"Asset %d", @"Accessibility label for asset (of unknown type) thumbnails in the media collection view. The parameter is the index of the asset in the collection view.");
break;
}

return [NSString stringWithFormat:accessibilityLabelFormat, index];
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
if ([self isCaptureCellIndexPath:indexPath]) {
Expand All @@ -408,40 +390,9 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell

id<WPMediaAsset> asset = [self assetForPosition:indexPath];
WPMediaCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([WPMediaCollectionViewCell class]) forIndexPath:indexPath];
if (cell.tag != 0) {
[asset cancelImageRequest:(WPMediaRequestID)cell.tag];
cell.tag = 0;
}

// Configure the cell
__block WPMediaRequestID requestKey = 0;
NSTimeInterval timestamp = [NSDate timeIntervalSinceReferenceDate];
NSInteger itemIndex = indexPath.item + 1; // Asset position + 1 to avoid starting at "Asset 0"
WPMediaType assetType = asset.assetType;
requestKey = [asset imageWithSize:cell.frame.size completionHandler:^(UIImage *result, NSError *error) {
BOOL animated = ([NSDate timeIntervalSinceReferenceDate] - timestamp) > 0.03;
if (error) {
cell.image = nil;
NSLog(@"%@", [error localizedDescription]);
return;
}
void (^setImage)() = ^{
if (requestKey == cell.tag){
NSString *accessibilityLabel = [self accessibilityLabelForType:assetType
atIndexPath:itemIndex];
[cell setImage:result
animated:animated
withAccessibilityLabel:accessibilityLabel];
}
};
if ([NSThread isMainThread]){
setImage();
} else {
dispatch_async(dispatch_get_main_queue(), ^{
setImage();
});
}
}];
cell.tag = requestKey;
cell.asset = asset;
NSUInteger position = [self positionOfAssetInSelection:asset];
if (position != NSNotFound) {
[self.collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
Expand All @@ -456,30 +407,9 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell
cell.selected = NO;
}

if ([asset assetType] == WPMediaTypeVideo) {
NSTimeInterval duration = [asset duration];
NSString *caption = [self stringFromTimeInterval:duration];
[cell setCaption:caption];
} else {
[cell setCaption:@""];
}

return cell;
}

- (NSString *)stringFromTimeInterval:(NSTimeInterval)timeInterval
{
NSInteger roundedHours = floor(timeInterval / 3600);
NSInteger roundedMinutes = floor((timeInterval - (3600 * roundedHours)) / 60);
NSInteger roundedSeconds = round(timeInterval - (roundedHours * 60 * 60) - (roundedMinutes * 60));

if (roundedHours > 0)
return [NSString stringWithFormat:@"%ld:%02ld:%02ld", (long)roundedHours, (long)roundedMinutes, (long)roundedSeconds];

else
return [NSString stringWithFormat:@"%ld:%02ld", (long)roundedMinutes, (long)roundedSeconds];
}

- (NSUInteger)positionOfAssetInSelection:(id<WPMediaAsset>)asset
{
NSUInteger position = [self.selectedAssets indexOfObjectPassingTest:^BOOL(id<WPMediaAsset> loopAsset, NSUInteger idx, BOOL *stop) {
Expand Down
2 changes: 1 addition & 1 deletion WPMediaPicker.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "WPMediaPicker"
s.version = "0.7.1"
s.version = "0.7.2"
s.summary = "WPMediaPicker is an iOS controller that allows capture and picking of media assets."
s.description = <<-DESC
WPMediaPicker is an iOS controller that allows capture and picking of media assets.
Expand Down