This commit is contained in:
Yamozha
2021-04-02 02:24:13 +03:00
parent c23950b545
commit 7256d79e2c
31493 changed files with 3036630 additions and 0 deletions

View File

@ -0,0 +1,17 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface EXResumablesManager : NSObject
- (NSURLSessionDownloadTask * _Nullable)taskForId:(NSString *)uuid;
- (void)registerTask:(NSURLSessionDownloadTask *)task uuid:(NSString *)uuid;
- (void)unregisterTask:(NSString *)uuid;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,36 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <EXFileSystem/EXResumablesManager.h>
@interface EXResumablesManager ()
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSURLSessionDownloadTask *> *resumableDownloads;
@end
@implementation EXResumablesManager
- (instancetype)init
{
if (self = [super init]) {
_resumableDownloads = [NSMutableDictionary dictionary];
}
return self;
}
- (void)registerTask:(NSURLSessionDownloadTask *)task uuid:(NSString *)uuid
{
_resumableDownloads[uuid] = task;
}
- (NSURLSessionDownloadTask * _Nullable)taskForId:(NSString *)uuid
{
return _resumableDownloads[uuid];
}
- (void)unregisterTask:(NSString *)uuid
{
[_resumableDownloads removeObjectForKey:uuid];
}
@end

View File

@ -0,0 +1,13 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <EXFileSystem/EXSessionTaskDelegate.h>
@interface EXSessionDownloadTaskDelegate : EXSessionTaskDelegate
- (instancetype)initWithResolve:(UMPromiseResolveBlock)resolve
reject:(UMPromiseRejectBlock)reject
localUrl:(NSURL *)localUrl
shouldCalculateMd5:(BOOL)shouldCalculateMd5;
@end

View File

@ -0,0 +1,64 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <EXFileSystem/EXSessionDownloadTaskDelegate.h>
#import <EXFileSystem/NSData+EXFileSystem.h>
@interface EXSessionDownloadTaskDelegate ()
@property (strong, nonatomic) NSURL *localUrl;
@property (nonatomic) BOOL shouldCalculateMd5;
@end
@implementation EXSessionDownloadTaskDelegate
- (instancetype)initWithResolve:(UMPromiseResolveBlock)resolve
reject:(UMPromiseRejectBlock)reject
localUrl:(NSURL *)localUrl
shouldCalculateMd5:(BOOL)shouldCalculateMd5
{
if (self = [super initWithResolve:resolve reject:reject])
{
_localUrl = localUrl;
_shouldCalculateMd5 = shouldCalculateMd5;
}
return self;
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:_localUrl.path]) {
[fileManager removeItemAtURL:_localUrl error:&error];
if (error) {
self.reject(@"ERR_FILESYSTEM_CANNOT_REMOVE",
[NSString stringWithFormat:@"Unable to remove file from local URI: '%@'", error.description],
error);
return;
}
}
[fileManager moveItemAtURL:location toURL:_localUrl error:&error];
if (error) {
self.reject(@"ERR_FILESYSTEM_CANNOT_SAVE",
[NSString stringWithFormat:@"Unable to save file to local URI: '%@'", error.description],
error);
return;
}
self.resolve([self parseServerResponse:downloadTask.response]);
}
- (NSDictionary *)parseServerResponse:(NSURLResponse *)response
{
NSMutableDictionary *result = [[super parseServerResponse:response] mutableCopy];
result[@"uri"] = _localUrl.absoluteString;
if (_shouldCalculateMd5) {
NSData *data = [NSData dataWithContentsOfURL:_localUrl];
result[@"md5"] = [data md5String];
}
return result;
}
@end

View File

@ -0,0 +1,19 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <Foundation/Foundation.h>
#import <UMCore/UMSingletonModule.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@protocol EXSessionHandler
- (void)invokeCompletionHandlerForSessionIdentifier:(NSString *)identifier;
@end
@interface EXSessionHandler : UMSingletonModule <UIApplicationDelegate, EXSessionHandler>
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,49 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <EXFileSystem/EXSessionHandler.h>
#import <UMCore/UMDefines.h>
@interface EXSessionHandler ()
@property (nonatomic, strong) NSMutableDictionary<NSString *, void (^)(void)> *completionHandlers;
@end
@implementation EXSessionHandler
UM_REGISTER_SINGLETON_MODULE(SessionHandler);
- (instancetype)init
{
if (self = [super init]) {
_completionHandlers = [NSMutableDictionary dictionary];
}
return self;
}
- (void)invokeCompletionHandlerForSessionIdentifier:(NSString *)identifier
{
if (!identifier) {
return;
}
void (^completionHandler)(void) = _completionHandlers[identifier];
if (completionHandler) {
// We need to run completionHandler explicite on the main thread because is's part of UIKit
dispatch_async(dispatch_get_main_queue(), ^{
completionHandler();
});
[_completionHandlers removeObjectForKey:identifier];
}
}
#pragma mark - AppDelegate
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler
{
_completionHandlers[identifier] = completionHandler;
}
@end

View File

@ -0,0 +1,18 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <EXFileSystem/EXSessionDownloadTaskDelegate.h>
#import <EXFileSystem/EXResumablesManager.h>
typedef void (^EXDownloadDelegateOnWriteCallback)(NSURLSessionDownloadTask *task, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite);
@interface EXSessionResumableDownloadTaskDelegate : EXSessionDownloadTaskDelegate
- (instancetype)initWithResolve:(UMPromiseResolveBlock)resolve
reject:(UMPromiseRejectBlock)reject
localUrl:(NSURL *)localUrl
shouldCalculateMd5:(BOOL)shouldCalculateMd5
onWriteCallback:(EXDownloadDelegateOnWriteCallback)onWriteCallback
resumableManager:(EXResumablesManager *)manager
uuid:(NSString *)uuid;
@end

View File

@ -0,0 +1,60 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <EXFileSystem/EXSessionResumableDownloadTaskDelegate.h>
@interface EXSessionResumableDownloadTaskDelegate ()
@property (strong, nonatomic, readonly) EXDownloadDelegateOnWriteCallback onWriteCallback;
@property (weak, nonatomic) EXResumablesManager *manager;
@property (strong, nonatomic) NSString *uuid;
@end
@implementation EXSessionResumableDownloadTaskDelegate
- (instancetype)initWithResolve:(UMPromiseResolveBlock)resolve
reject:(UMPromiseRejectBlock)reject
localUrl:(NSURL *)localUrl
shouldCalculateMd5:(BOOL)shouldCalculateMd5
onWriteCallback:(EXDownloadDelegateOnWriteCallback)onWriteCallback
resumableManager:(EXResumablesManager *)manager
uuid:(NSString *)uuid;
{
if (self = [super initWithResolve:resolve
reject:reject
localUrl:localUrl
shouldCalculateMd5:shouldCalculateMd5]) {
_onWriteCallback = onWriteCallback;
_manager = manager;
_uuid = uuid;
}
return self;
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
if (error) {
// The task was paused by us. So, we shouldn't throw.
if (error.code == NSURLErrorCancelled) {
self.resolve([NSNull null]);
} else {
self.reject(@"ERR_FILESYSTEM_CANNOT_DOWNLOAD",
[NSString stringWithFormat:@"Unable to download file: %@", error.description],
error);
}
}
[_manager unregisterTask:_uuid];
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
if (_onWriteCallback && bytesWritten > 0) {
_onWriteCallback(downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
}
}
@end

View File

@ -0,0 +1,27 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <Foundation/Foundation.h>
#import <UMCore/UMDefines.h>
@interface EXSessionTaskDelegate : NSObject
@property (nonatomic, strong, readonly) UMPromiseResolveBlock resolve;
@property (nonatomic, strong, readonly) UMPromiseRejectBlock reject;
- (instancetype)initWithResolve:(UMPromiseResolveBlock)resolve
reject:(UMPromiseRejectBlock)reject;
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location;
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error;
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data;
- (NSDictionary *)parseServerResponse:(NSURLResponse *)response;
@end

View File

@ -0,0 +1,51 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <EXFileSystem/EXSessionTaskDelegate.h>
@implementation EXSessionTaskDelegate
- (instancetype)initWithResolve:(UMPromiseResolveBlock)resolve
reject:(UMPromiseRejectBlock)reject
{
if (self = [super init]) {
_resolve = resolve;
_reject = reject;
}
return self;
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
if (error) {
self.reject(@"ERR_FILESYSTEM_CANNOT_DOWNLOAD",
[NSString stringWithFormat:@"Unable to download file: %@", error.description],
error);
}
}
- (NSDictionary *)parseServerResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
return @{
@"status": @([httpResponse statusCode]),
@"headers": [httpResponse allHeaderFields],
@"mimeType": UMNullIfNil([httpResponse MIMEType])
};
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
}
@end

View File

@ -0,0 +1,19 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <Foundation/Foundation.h>
#import <EXFileSystem/EXSessionTaskDelegate.h>
#import <EXFileSystem/EXSessionHandler.h>
NS_ASSUME_NONNULL_BEGIN
@interface EXSessionTaskDispatcher : NSObject <NSURLSessionDelegate>
- (instancetype)initWithSessionHandler:(id<EXSessionHandler>)sessionHandler;
- (void)registerTaskDelegate:(EXSessionTaskDelegate *)delegate forTask:(NSURLSessionTask *)task;
- (void)deactivate;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,85 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <EXFileSystem/EXSessionTaskDispatcher.h>
#import <EXFileSystem/EXSessionResumableDownloadTaskDelegate.h>
@interface EXSessionTaskDispatcher ()
@property (nonatomic, strong) NSMutableDictionary<NSURLSessionTask *, EXSessionTaskDelegate *> *tasks;
@property (nonatomic) BOOL isActive;
@property (nonatomic, weak) id<EXSessionHandler> sessionHandler;
@end
@implementation EXSessionTaskDispatcher
- (instancetype)initWithSessionHandler:(id<EXSessionHandler>)sessionHandler;
{
if (self = [super init]) {
_tasks = [NSMutableDictionary dictionary];
_isActive = true;
_sessionHandler = sessionHandler;
}
return self;
}
#pragma mark - public methods
- (void)registerTaskDelegate:(EXSessionTaskDelegate *)delegate forTask:(NSURLSessionTask *)task
{
_tasks[task] = delegate;
}
- (void)deactivate
{
_isActive = false;
}
#pragma mark - dispatcher
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
if (_isActive) {
EXSessionTaskDelegate *exTask = _tasks[downloadTask];
if (exTask) {
[exTask URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location];
[_tasks removeObjectForKey:downloadTask];
}
}
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
if (_isActive) {
EXSessionTaskDelegate *exTask = _tasks[task];
if (exTask) {
[exTask URLSession:session task:task didCompleteWithError:error];
[_tasks removeObjectForKey:task];
}
}
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
if (_isActive) {
EXSessionTaskDelegate *exTask = _tasks[downloadTask];
[exTask URLSession:session downloadTask:downloadTask didWriteData:bytesWritten totalBytesWritten:totalBytesWritten totalBytesExpectedToWrite:totalBytesExpectedToWrite];
}
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
if (_isActive) {
EXSessionTaskDelegate *exTask = _tasks[dataTask];
[exTask URLSession:session dataTask:dataTask didReceiveData:data];
}
}
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
[_sessionHandler invokeCompletionHandlerForSessionIdentifier:session.configuration.identifier];
}
@end

View File

@ -0,0 +1,8 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <EXFileSystem/EXSessionTaskDelegate.h>
@interface EXSessionUploadTaskDelegate : EXSessionTaskDelegate
@end

View File

@ -0,0 +1,52 @@
// Copyright 2015-present 650 Industries. All rights reserved.
#import <EXFileSystem/EXSessionUploadTaskDelegate.h>
@interface EXSessionUploadTaskDelegate ()
@property (strong, nonatomic) NSMutableData *responseData;
@end
@implementation EXSessionUploadTaskDelegate
- (instancetype)initWithResolve:(UMPromiseResolveBlock)resolve reject:(UMPromiseRejectBlock)reject
{
if (self = [super initWithResolve:resolve reject:reject]) {
_responseData = [NSMutableData new];
}
return self;
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
if (!data.length) {
return;
}
[_responseData appendData:data];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
if (error) {
self.reject(@"ERR_FILESYSTEM_CANNOT_UPLOAD",
[NSString stringWithFormat:@"Unable to upload the file: '%@'", error.description],
error);
return;
}
// We only set EXSessionUploadTaskDelegates as delegates of upload tasks
// so it should be safe to assume that this is what we will receive here.
NSURLSessionUploadTask *uploadTask = (NSURLSessionUploadTask *)task;
self.resolve([self parseServerResponse:uploadTask.response]);
}
- (NSDictionary *)parseServerResponse:(NSURLResponse *)response
{
NSMutableDictionary *result = [[super parseServerResponse:response] mutableCopy];
// TODO: add support for others response types (different encodings, files)
result[@"body"] = UMNullIfNil([[NSString alloc] initWithData:_responseData encoding:NSUTF8StringEncoding]);
return result;
}
@end