1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-02 09:27:55 +01:00
Telegram/Telegraph/TGMediaAssetsUtils.m
2016-02-25 01:03:51 +01:00

180 lines
6.0 KiB
Objective-C

#import "TGMediaAssetsUtils.h"
#import "UICollectionView+Utils.h"
#import "TGMediaSelectionContext.h"
@interface TGMediaAssetsPreheatMixin ()
{
UICollectionView *_collectionView;
UICollectionViewScrollDirection _scrollDirection;
CGRect _previousPreheatRect;
}
@end
@implementation TGMediaAssetsPreheatMixin
- (instancetype)initWithCollectionView:(UICollectionView *)collectionView scrollDirection:(UICollectionViewScrollDirection)scrollDirection
{
self = [super init];
if (self != nil)
{
_collectionView = collectionView;
_scrollDirection = scrollDirection;
}
return self;
}
- (void)update
{
CGRect preheatRect = _collectionView.bounds;
CGFloat delta = 0.0f;
CGFloat threshold = 0.0f;
switch (_scrollDirection)
{
case UICollectionViewScrollDirectionHorizontal:
preheatRect = CGRectInset(preheatRect, -0.5f * preheatRect.size.width, 0.0f);
delta = fabs(CGRectGetMidX(preheatRect) - CGRectGetMidX(_previousPreheatRect));
threshold = _collectionView.bounds.size.width / 3.0f;
break;
case UICollectionViewScrollDirectionVertical:
preheatRect = CGRectInset(preheatRect, 0.0f, -0.5f * preheatRect.size.height);
delta = fabs(CGRectGetMidY(preheatRect) - CGRectGetMidY(_previousPreheatRect));
threshold = _collectionView.bounds.size.height / 3.0f;
break;
}
if (delta > threshold)
{
NSMutableArray *addedIndexPaths = [[NSMutableArray alloc] init];
NSMutableArray *removedIndexPaths = [[NSMutableArray alloc] init];
__weak TGMediaAssetsPreheatMixin *weakSelf = self;
[_collectionView computeDifferenceBetweenRect:_previousPreheatRect andRect:preheatRect direction:_scrollDirection removedHandler:^(CGRect removedRect)
{
__strong TGMediaAssetsPreheatMixin *strongSelf = weakSelf;
if (strongSelf == nil)
return;
NSArray *indexPaths = [strongSelf->_collectionView indexPathsForElementsInRect:removedRect];
[removedIndexPaths addObjectsFromArray:indexPaths];
} addedHandler:^(CGRect addedRect)
{
__strong TGMediaAssetsPreheatMixin *strongSelf = weakSelf;
if (strongSelf == nil)
return;
NSArray *indexPaths = [strongSelf->_collectionView indexPathsForElementsInRect:addedRect];
[addedIndexPaths addObjectsFromArray:indexPaths];
}];
NSArray *assetsToCache = [self _assetsAtIndexPaths:addedIndexPaths];
NSArray *assetsToInvalidate = [self _assetsAtIndexPaths:removedIndexPaths];
CGSize imageSize = self.imageSize;
[TGMediaAssetImageSignals startCachingImagesForAssets:assetsToCache imageType:self.imageType size:imageSize];
[TGMediaAssetImageSignals stopCachingImagesForAssets:assetsToInvalidate imageType:self.imageType size:imageSize];
_previousPreheatRect = preheatRect;
}
}
- (void)stop
{
[TGMediaAssetImageSignals stopCachingImagesForAllAssets];
_previousPreheatRect = CGRectZero;
}
- (NSArray *)_assetsAtIndexPaths:(NSArray *)indexPaths
{
if (indexPaths.count == 0)
return nil;
NSInteger assetCount = self.assetCount();
NSMutableArray *assets = [NSMutableArray arrayWithCapacity:indexPaths.count];
for (NSIndexPath *indexPath in indexPaths)
{
NSInteger index = indexPath.row;
if (index < assetCount)
[assets addObject:self.assetAtIndex(index)];
}
return assets;
}
@end
@implementation TGMediaAssetsCollectionViewIncrementalUpdater
+ (void)updateCollectionView:(UICollectionView *)collectionView withChange:(TGMediaAssetFetchResultChange *)change completion:(void (^)(bool incremental))completion
{
[collectionView reloadData];
if (completion != nil)
completion(false);
return;
if (!change.hasIncrementalChanges)
{
[collectionView reloadData];
if (completion != nil)
completion(false);
return;
}
NSMutableArray *removedIndexPaths = [[NSMutableArray alloc] init];
[change.removedIndexes enumerateIndexesUsingBlock:^(NSUInteger index, __unused BOOL *stop)
{
[removedIndexPaths addObject:[NSIndexPath indexPathForRow:index inSection:0]];
}];
NSMutableArray *insertedIndexPaths = [[NSMutableArray alloc] init];
[change.insertedIndexes enumerateIndexesUsingBlock:^(NSUInteger index, __unused BOOL *stop)
{
[insertedIndexPaths addObject:[NSIndexPath indexPathForRow:index inSection:0]];
}];
NSMutableArray *updatedIndexPaths = [[NSMutableArray alloc] init];
[change.updatedIndexes enumerateIndexesUsingBlock:^(NSUInteger index, __unused BOOL *stop)
{
[updatedIndexPaths addObject:[NSIndexPath indexPathForRow:index inSection:0]];
}];
[collectionView performBatchUpdates:^
{
[collectionView deleteItemsAtIndexPaths:removedIndexPaths];
[collectionView insertItemsAtIndexPaths:insertedIndexPaths];
} completion:^(__unused BOOL finished)
{
if (updatedIndexPaths.count > 0 || change.hasMoves)
{
[collectionView performBatchUpdates:^
{
[collectionView reloadItemsAtIndexPaths:updatedIndexPaths];
[change enumerateMovesWithBlock:^(NSUInteger fromIndex, NSUInteger toIndex)
{
NSIndexPath *fromIndexPath = [NSIndexPath indexPathForRow:fromIndex inSection:0];
NSIndexPath *toIndexPath = [NSIndexPath indexPathForRow:toIndex inSection:0];
[collectionView moveItemAtIndexPath:fromIndexPath toIndexPath:toIndexPath];
}];
} completion:^(__unused BOOL finished)
{
if (completion != nil)
completion(true);
}];
}
else if (completion != nil)
{
completion(true);
}
}];
}
@end