mirror of
https://github.com/drewmccormack/ensembles.git
synced 2026-03-03 18:23:18 +01:00
303 lines
9.0 KiB
Objective-C
303 lines
9.0 KiB
Objective-C
//
|
|
// CDEDropboxCloudFileSystem.m
|
|
// Test App iOS
|
|
//
|
|
// Created by Drew McCormack on 4/12/13.
|
|
// Copyright (c) 2013 The Mental Faculty B.V. All rights reserved.
|
|
//
|
|
|
|
#import "CDEDropboxCloudFileSystem.h"
|
|
#import "DBMetadata.h"
|
|
#import "CDEDefines.h"
|
|
#import "CDEAsynchronousTaskQueue.h"
|
|
#import "CDECloudFile.h"
|
|
#import "CDECloudDirectory.h"
|
|
|
|
typedef void (^CDEFileExistenceCallback)(BOOL exists, BOOL isDirectory, NSError *error);
|
|
typedef void (^CDEDirectoryContentsCallback)(NSArray *contents, NSError *error);
|
|
|
|
const NSUInteger kCDENumberOfRetriesForFailedAttempt = 5;
|
|
|
|
@implementation CDEDropboxCloudFileSystem {
|
|
DBRestClient *restClient;
|
|
NSCache *cache;
|
|
CDEDirectoryContentsCallback directoryContentsCallback;
|
|
CDECompletionBlock completionCallback;
|
|
CDEAsynchronousTaskCallbackBlock retryCallbackBlock;
|
|
CDEFileExistenceCallback fileExistenceCallback;
|
|
CDEAsynchronousTaskQueue *taskQueue;
|
|
BOOL fileExists, isDirectory;
|
|
NSDictionary *existingResults;
|
|
}
|
|
|
|
@synthesize session = session;
|
|
|
|
- (instancetype)initWithSession:(DBSession *)newSession
|
|
{
|
|
self = [super init];
|
|
if (self) {
|
|
session = newSession;
|
|
restClient = [[DBRestClient alloc] initWithSession:[DBSession sharedSession]];
|
|
restClient.delegate = self;
|
|
cache = [[NSCache alloc] init];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
[restClient cancelAllRequests];
|
|
}
|
|
|
|
#pragma mark Connecting
|
|
|
|
- (BOOL)isConnected
|
|
{
|
|
return self.session.isLinked;
|
|
}
|
|
|
|
- (void)connect:(CDECompletionBlock)completion
|
|
{
|
|
if (self.isConnected) {
|
|
if (completion) completion(nil);
|
|
}
|
|
else if ([self.delegate respondsToSelector:@selector(linkSessionForDropboxCloudFileSystem:completion:)]) {
|
|
[self.delegate linkSessionForDropboxCloudFileSystem:self completion:completion];
|
|
}
|
|
else {
|
|
NSError *error = [NSError errorWithDomain:CDEErrorDomain code:CDEErrorConnectionError userInfo:nil];
|
|
if (completion) completion(error);
|
|
}
|
|
}
|
|
|
|
#pragma mark - User Identity
|
|
|
|
- (id <NSObject, NSCoding, NSCopying>)identityToken
|
|
{
|
|
return self.session.userIds > 0 ? self.session.userIds[0] : nil;
|
|
}
|
|
|
|
#pragma mark Checking File Existence
|
|
|
|
- (void)fileExistsAtPath:(NSString *)path completion:(CDEFileExistenceCallback)block
|
|
{
|
|
fileExists = NO;
|
|
isDirectory = NO;
|
|
fileExistenceCallback = [block copy];
|
|
taskQueue = [[CDEAsynchronousTaskQueue alloc] initWithTask:^(CDEAsynchronousTaskCallbackBlock next) {
|
|
retryCallbackBlock = [next copy];
|
|
[restClient loadMetadata:path];
|
|
}
|
|
repeatCount:kCDENumberOfRetriesForFailedAttempt
|
|
terminationPolicy:CDETaskQueueTerminationPolicyStopOnSuccess
|
|
completion:^(NSError *error) {
|
|
fileExistenceCallback(fileExists, isDirectory, error);
|
|
retryCallbackBlock = NULL;
|
|
}
|
|
];
|
|
[taskQueue start];
|
|
}
|
|
|
|
#pragma mark Getting Directory Contents
|
|
|
|
- (void)contentsOfDirectoryAtPath:(NSString *)path completion:(void(^)(NSArray *contents, NSError *error))block
|
|
{
|
|
directoryContentsCallback = [block copy];
|
|
existingResults = [cache objectForKey:@"path"];
|
|
NSString *hash = existingResults[@"hash"];
|
|
if (hash) {
|
|
[restClient loadMetadata:path withHash:hash];
|
|
}
|
|
else {
|
|
[restClient loadMetadata:path];
|
|
}
|
|
}
|
|
|
|
#pragma mark Creating Directories
|
|
|
|
- (void)createDirectoryAtPath:(NSString *)path completion:(CDECompletionBlock)block
|
|
{
|
|
completionCallback = [block copy];
|
|
[restClient createFolder:path];
|
|
}
|
|
|
|
#pragma mark Moving and Copying
|
|
|
|
- (void)moveItemAtPath:(NSString *)fromPath toPath:(NSString *)toPath completion:(CDECompletionBlock)block
|
|
{
|
|
completionCallback = [block copy];
|
|
[restClient moveFrom:fromPath toPath:toPath];
|
|
}
|
|
|
|
- (void)copyItemAtPath:(NSString *)fromPath toPath:(NSString *)toPath completion:(CDECompletionBlock)block
|
|
{
|
|
completionCallback = [block copy];
|
|
[restClient copyFrom:fromPath toPath:toPath];
|
|
}
|
|
|
|
#pragma mark Deleting
|
|
|
|
- (void)removeItemAtPath:(NSString *)path completion:(CDECompletionBlock)block
|
|
{
|
|
completionCallback = [block copy];
|
|
[restClient deletePath:path];
|
|
}
|
|
|
|
#pragma mark Uploading and Downloading
|
|
|
|
- (void)uploadLocalFile:(NSString *)fromPath toPath:(NSString *)toPath completion:(CDECompletionBlock)block
|
|
{
|
|
completionCallback = [block copy];
|
|
[restClient uploadFile:[toPath lastPathComponent] toPath:[toPath stringByDeletingLastPathComponent] withParentRev:nil fromPath:fromPath];
|
|
}
|
|
|
|
- (void)downloadFromPath:(NSString *)fromPath toLocalFile:(NSString *)toPath completion:(CDECompletionBlock)block
|
|
{
|
|
completionCallback = [block copy];
|
|
[restClient loadFile:fromPath atRev:nil intoPath:toPath];
|
|
}
|
|
|
|
#pragma DBRestClientDelegate methods
|
|
|
|
- (void)restClient:(DBRestClient *)client loadedMetadata:(DBMetadata *)metadata
|
|
{
|
|
if (fileExistenceCallback) {
|
|
fileExists = !metadata.isDeleted;
|
|
isDirectory = metadata.isDirectory;
|
|
retryCallbackBlock(nil, YES);
|
|
}
|
|
else if (directoryContentsCallback) {
|
|
CDECloudDirectory *directory = [CDECloudDirectory new];
|
|
directory.path = metadata.path;
|
|
directory.name = metadata.filename;
|
|
|
|
NSMutableArray *contents = [[NSMutableArray alloc] initWithCapacity:metadata.contents.count];
|
|
for (DBMetadata *child in metadata.contents) {
|
|
if (child.isDirectory) {
|
|
CDECloudDirectory *dir = [CDECloudDirectory new];
|
|
dir.name = child.filename;
|
|
dir.path = child.path;
|
|
[contents addObject:dir];
|
|
}
|
|
else {
|
|
CDECloudFile *file = [CDECloudFile new];
|
|
file.name = child.filename;
|
|
file.path = child.path;
|
|
file.size = child.totalBytes;
|
|
[contents addObject:file];
|
|
}
|
|
}
|
|
directory.contents = contents;
|
|
|
|
NSDictionary *dict = @{@"hash":metadata.hash, @"directory":directory};
|
|
[cache setObject:dict forKey:directory.path];
|
|
|
|
[self performDirectoryContentsCallbackWithResults:directory.contents error:nil];
|
|
}
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client metadataUnchangedAtPath:(NSString *)path
|
|
{
|
|
if (directoryContentsCallback) {
|
|
CDECloudDirectory *directory = existingResults[@"directory"];
|
|
[self performDirectoryContentsCallbackWithResults:directory.contents error:nil];
|
|
}
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client loadMetadataFailedWithError:(NSError *)error
|
|
{
|
|
if (fileExistenceCallback) {
|
|
if (error.code == 404) {
|
|
fileExists = NO;
|
|
isDirectory = NO;
|
|
retryCallbackBlock(nil, YES);
|
|
}
|
|
else {
|
|
retryCallbackBlock(error, NO);
|
|
}
|
|
}
|
|
else if (directoryContentsCallback) {
|
|
[self performDirectoryContentsCallbackWithResults:nil error:error];
|
|
}
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client createdFolder:(DBMetadata *)folder
|
|
{
|
|
[self performCompletionCallbackWithError:nil];
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client createFolderFailedWithError:(NSError *)error
|
|
{
|
|
[self performCompletionCallbackWithError:error];
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client deletedPath:(NSString *)path
|
|
{
|
|
[self performCompletionCallbackWithError:nil];
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client deletePathFailedWithError:(NSError *)error
|
|
{
|
|
[self performCompletionCallbackWithError:error];
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client movedPath:(NSString *)from_path to:(DBMetadata *)result
|
|
{
|
|
[self performCompletionCallbackWithError:nil];
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client movePathFailedWithError:(NSError *)error
|
|
{
|
|
[self performCompletionCallbackWithError:error];
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client copiedPath:(NSString *)fromPath to:(DBMetadata *)to
|
|
{
|
|
[self performCompletionCallbackWithError:nil];
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client copyPathFailedWithError:(NSError *)error
|
|
{
|
|
[self performCompletionCallbackWithError:error];
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client uploadedFile:(NSString *)destPath from:(NSString *)srcPath
|
|
{
|
|
[self performCompletionCallbackWithError:nil];
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client uploadFileFailedWithError:(NSError *)error
|
|
{
|
|
[self performCompletionCallbackWithError:error];
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client loadedFile:(NSString *)destPath
|
|
{
|
|
[self performCompletionCallbackWithError:nil];
|
|
}
|
|
|
|
- (void)restClient:(DBRestClient *)client loadFileFailedWithError:(NSError *)error
|
|
{
|
|
[self performCompletionCallbackWithError:error];
|
|
}
|
|
|
|
- (void)performCompletionCallbackWithError:(NSError *)error
|
|
{
|
|
// Use a local, in case callback schedules another operation
|
|
// and causes completionCallback to be reassigned
|
|
CDECompletionBlock block = completionCallback;
|
|
completionCallback = NULL;
|
|
if (block) block(error);
|
|
}
|
|
|
|
- (void)performDirectoryContentsCallbackWithResults:(id)results error:(NSError *)error
|
|
{
|
|
// Use a local var to prevent premature release of block
|
|
CDEDirectoryContentsCallback block = directoryContentsCallback;
|
|
directoryContentsCallback = NULL;
|
|
if (block) block(results, error);
|
|
existingResults = nil;
|
|
}
|
|
|
|
@end
|