1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-02 09:27:55 +01:00
Telegram/Telegraph/TGLocationVenueIconDataSource.m
2015-10-01 19:19:52 +03:00

260 lines
8.6 KiB
Objective-C

#import "TGLocationVenueIconDataSource.h"
#import "ASQueue.h"
#import "TGWorkerPool.h"
#import "TGWorkerTask.h"
#import "TGMediaPreviewTask.h"
#import "TGMemoryImageCache.h"
#import "TGImageUtils.h"
#import "TGStringUtils.h"
#import "TGRemoteImageView.h"
#import "TGImageBlur.h"
#import "UIImage+TG.h"
#import "TGMediaStoreContext.h"
static TGWorkerPool *workerPool()
{
static TGWorkerPool *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
instance = [[TGWorkerPool alloc] init];
});
return instance;
}
static ASQueue *taskManagementQueue()
{
static ASQueue *queue = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
queue = [[ASQueue alloc] initWithName:"org.telegram.locationVenueIconTaskManagementQueue"];
});
return queue;
}
@implementation TGLocationVenueIconDataSource
+ (void)load
{
@autoreleasepool
{
[TGImageDataSource registerDataSource:[[self alloc] init]];
}
}
+ (NSString *)uriScheme
{
return @"location-venue-icon";
}
+ (NSString *)uriSchemeFull
{
return [NSString stringWithFormat:@"%@://", [self uriScheme]];
}
- (bool)canHandleUri:(NSString *)uri
{
return [uri hasPrefix:[TGLocationVenueIconDataSource uriSchemeFull]];
}
- (bool)canHandleAttributeUri:(NSString *)uri
{
return [uri hasPrefix:[TGLocationVenueIconDataSource uriSchemeFull]];
}
+ (NSString *)iconAddressForUri:(NSString *)uri size:(out CGSize *)size
{
NSDictionary *args = [TGStringUtils argumentDictionaryInUrlString:[uri substringFromIndex:[TGLocationVenueIconDataSource uriSchemeFull].length]];
CGSize imageSize = CGSizeMake([args[@"width"] intValue], [args[@"height"] intValue]);
if (size != NULL)
*size = imageSize;
return args[@"url"] == nil ? nil : [[NSString alloc] initWithFormat:@"%@", args[@"url"]];
}
- (id)loadDataAsyncWithUri:(NSString *)uri progress:(void (^)(float))progress partialCompletion:(void (^)(TGDataResource *resource))__unused partialCompletion completion:(void (^)(TGDataResource *))completion
{
TGMediaPreviewTask *previewTask = [[TGMediaPreviewTask alloc] init];
[taskManagementQueue() dispatchOnQueue:^
{
TGWorkerTask *workerTask = [[TGWorkerTask alloc] initWithBlock:^(bool (^isCancelled)())
{
TGDataResource *result = [TGLocationVenueIconDataSource _performLoad:uri isCancelled:isCancelled];
if (result != nil && progress != nil)
progress(1.0f);
if (isCancelled != nil && isCancelled())
return;
if (completion != nil)
completion(result != nil ? result : [TGLocationVenueIconDataSource resultForUnavailableImage]);
}];
if ([TGLocationVenueIconDataSource _isDataLocallyAvailableForUri:uri])
{
[previewTask executeWithWorkerTask:workerTask workerPool:workerPool()];
}
else
{
[previewTask executeWithTargetFilePath:nil uri:[TGLocationVenueIconDataSource iconAddressForUri:uri size:NULL] completion:^(bool success)
{
if (success)
{
[previewTask executeWithWorkerTask:workerTask workerPool:workerPool()];
}
else
{
if (completion != nil)
completion([TGLocationVenueIconDataSource resultForUnavailableImage]);
}
} workerTask:workerTask];
}
}];
return previewTask;
}
- (void)cancelTaskById:(id)taskId
{
[taskManagementQueue() dispatchOnQueue:^
{
if ([taskId isKindOfClass:[TGMediaPreviewTask class]])
{
TGMediaPreviewTask *previewTask = taskId;
[previewTask cancel];
}
}];
}
+ (TGDataResource *)resultForUnavailableImage
{
static TGDataResource *imageData = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
UIImage *image = nil;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(40, 40), false, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, UIColorRGB(0xededed).CGColor);
CGContextFillEllipseInRect(context, CGRectMake(0.0, 0.0f, 40.0f, 40.0f));
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageData = [[TGDataResource alloc] initWithImage:image decoded:true];
});
return imageData;
}
- (id)loadAttributeSyncForUri:(NSString *)__unused uri attribute:(NSString *)attribute
{
if ([attribute isEqualToString:@"placeholder"])
{
static NSMutableDictionary *placeholderBySize = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
placeholderBySize = [[NSMutableDictionary alloc] init];
});
CGSize size = CGSizeZero;
[TGLocationVenueIconDataSource iconAddressForUri:uri size:&size];
NSString *sizeString = NSStringFromCGSize(size);
UIImage *placeholder = placeholderBySize[sizeString];
if (placeholder != nil)
return placeholder;
//ededed
//f2f2f2
UIGraphicsBeginImageContextWithOptions(size, false, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, UIColorRGB(0xf2f2f2).CGColor);
CGContextFillEllipseInRect(context, CGRectMake(0.0, 0.0f, size.width, size.height));
placeholder = UIGraphicsGetImageFromCurrentImageContext();
if (placeholder != nil)
placeholderBySize[sizeString] = placeholder;
UIGraphicsEndImageContext();
return placeholder;
}
return nil;
}
- (TGDataResource *)loadDataSyncWithUri:(NSString *)uri canWait:(bool)canWait acceptPartialData:(bool)__unused acceptPartialData asyncTaskId:(__autoreleasing id *)__unused asyncTaskId progress:(void (^)(float))__unused progress partialCompletion:(void (^)(TGDataResource *))__unused partialCompletion completion:(void (^)(TGDataResource *))__unused completion
{
if (uri == nil)
return nil;
UIImage *cachedImage = [[TGMediaStoreContext instance] mediaImage:uri attributes:nil];
if (cachedImage != nil)
return [[TGDataResource alloc] initWithImage:cachedImage decoded:true];
if (!canWait)
return nil;
return [TGLocationVenueIconDataSource _performLoad:uri isCancelled:nil];
}
+ (bool)_isDataLocallyAvailableForUri:(NSString *)uri
{
NSString *iconAddress = [self iconAddressForUri:uri size:NULL];
return [[[TGMediaStoreContext instance] temporaryFilesCache] containsValueForKey:[iconAddress dataUsingEncoding:NSUTF8StringEncoding]];
}
+ (TGDataResource *)_performLoad:(NSString *)uri isCancelled:(bool (^)())isCancelled
{
if (isCancelled && isCancelled())
return nil;
CGSize size = CGSizeZero;
NSString *imageUrl = [TGLocationVenueIconDataSource iconAddressForUri:uri size:&size];
NSData *iconSourceData = [[[TGMediaStoreContext instance] temporaryFilesCache] getValueForKey:[imageUrl dataUsingEncoding:NSUTF8StringEncoding]];
UIImage *iconSourceImage = [[UIImage alloc] initWithData:iconSourceData];
UIGraphicsBeginImageContextWithOptions(iconSourceImage.size, false, iconSourceImage.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
[iconSourceImage drawAtPoint:CGPointZero];
CGContextSetBlendMode (context, kCGBlendModeSourceAtop);
CGContextSetFillColorWithColor(context, UIColorRGB(0xa0a0a0).CGColor);
CGContextFillRect(context, CGRectMake(0, 0, iconSourceImage.size.width, iconSourceImage.size.height));
UIImage *tintedIconImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIGraphicsBeginImageContextWithOptions(size, false, 0.0f);
context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, UIColorRGB(0xf2f2f2).CGColor);
CGContextFillEllipseInRect(context, CGRectMake(0.0, 0.0f, size.width, size.height));
CGRect imageRect = CGRectMake(4.0f, 4.0f, 32.0f, 32.0f);
[tintedIconImage drawInRect:imageRect];
UIImage *iconImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (iconImage != nil)
{
[[TGMediaStoreContext instance] setMediaImageForKey:uri image:iconImage attributes:@{}];
return [[TGDataResource alloc] initWithImage:iconImage decoded:true];
}
return nil;
}
@end