Merge lp:~threeve/ubuntuone-ios-files/background-processing into lp:ubuntuone-ios-files

Proposed by Jason Foreman
Status: Merged
Merged at revision: 37
Proposed branch: lp:~threeve/ubuntuone-ios-files/background-processing
Merge into: lp:ubuntuone-ios-files
Diff against target: 1483 lines (+478/-287)
23 files modified
Files.xcodeproj/project.pbxproj (+11/-11)
Files/Files-Prefix.pch (+4/-2)
Files/U1AssetRepresenationDataProvider.h (+4/-3)
Files/U1AssetRepresenationDataProvider.m (+47/-8)
Files/U1AutoUploadOperation.h (+8/-3)
Files/U1AutoUploadOperation.m (+21/-11)
Files/U1AutoUploadsManager.h (+1/-1)
Files/U1AutoUploadsManager.m (+195/-144)
Files/U1DataRepository.h (+4/-2)
Files/U1DataRepository.m (+27/-10)
Files/U1FilesClient.h (+1/-3)
Files/U1FilesClient.m (+32/-17)
Files/U1FilesService.h (+6/-1)
Files/U1FilesService.m (+43/-32)
Files/U1FolderItemCell.m (+16/-1)
Files/U1FolderItemCell.xib (+3/-1)
Files/U1FolderViewController.m (+4/-3)
Files/U1ReportingInputStream.h (+3/-2)
Files/U1ReportingInputStream.m (+6/-8)
Files/U1UploadOperation.m (+21/-4)
Files/U1UploadsPoolViewController.m (+1/-1)
Files/U1Volume.m (+1/-1)
Files/iPhone/en.lproj/MainWindow_iPhone.xib (+19/-18)
To merge this branch: bzr merge lp:~threeve/ubuntuone-ios-files/background-processing
Reviewer Review Type Date Requested Status
Zachery Bir Approve
Review via email: mp+85186@code.launchpad.net

Description of the change

Do node loading and parsing in the background to avoid UI blocking.

To post a comment you must log in.
32. By Jason Foreman

Merge lp:~urbanape/ubuntuone-ios-files/background-processing

Revision history for this message
Zachery Bir (urbanape) wrote :

LAND, LAND

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Files.xcodeproj/project.pbxproj'
--- Files.xcodeproj/project.pbxproj 2011-12-07 14:26:35 +0000
+++ Files.xcodeproj/project.pbxproj 2011-12-09 20:00:29 +0000
@@ -640,6 +640,13 @@
640 96CC17E414180C5F00EFC1BA /* U1FilesClient.m */,640 96CC17E414180C5F00EFC1BA /* U1FilesClient.m */,
641 91B3F2D7141FC9BE00939B3C /* U1AutoUploadsManager.h */,641 91B3F2D7141FC9BE00939B3C /* U1AutoUploadsManager.h */,
642 91A5E2DB142A70DF00EAAC2B /* U1AutoUploadsManager.m */,642 91A5E2DB142A70DF00EAAC2B /* U1AutoUploadsManager.m */,
643 910393E61475B118004DE69D /* U1AutoUploadOperation.h */,
644 910393E71475B118004DE69D /* U1AutoUploadOperation.m */,
645 91A007E8147559F200D0E5FF /* U1AssetRepresenationDataProvider.h */,
646 91A007E9147559F200D0E5FF /* U1AssetRepresenationDataProvider.m */,
647 916E0080143C9A390037F6D3 /* U1UploadsPoolViewController.h */,
648 916E0081143C9A390037F6D3 /* U1UploadsPoolViewController.m */,
649 9190AAF31444CA0A0063614A /* U1UploadsPoolViewController.xib */,
643 969EF22613F8C10C00CEF6CB /* U1VolumesViewController.h */,650 969EF22613F8C10C00CEF6CB /* U1VolumesViewController.h */,
644 969EF22713F8C10C00CEF6CB /* U1VolumesViewController.m */,651 969EF22713F8C10C00CEF6CB /* U1VolumesViewController.m */,
645 969EF22813F8C10C00CEF6CB /* U1VolumesViewController.xib */,652 969EF22813F8C10C00CEF6CB /* U1VolumesViewController.xib */,
@@ -654,20 +661,13 @@
654 960D4627140D8B4400B73177 /* U1FriendlyDateValueTransformer.m */,661 960D4627140D8B4400B73177 /* U1FriendlyDateValueTransformer.m */,
655 91A5E2DD142B727500EAAC2B /* U1UploadOperation.h */,662 91A5E2DD142B727500EAAC2B /* U1UploadOperation.h */,
656 91A5E2DE142B727500EAAC2B /* U1UploadOperation.m */,663 91A5E2DE142B727500EAAC2B /* U1UploadOperation.m */,
657 910393E61475B118004DE69D /* U1AutoUploadOperation.h */,
658 910393E71475B118004DE69D /* U1AutoUploadOperation.m */,
659 965D7EB71429690C00E4754F /* U1NavigationBar.h */,664 965D7EB71429690C00E4754F /* U1NavigationBar.h */,
660 965D7EB81429690C00E4754F /* U1NavigationBar.m */,665 965D7EB81429690C00E4754F /* U1NavigationBar.m */,
661 96A169A21430D53600E4C990 /* U1LocalFileInfo.h */,666 96A169A21430D53600E4C990 /* U1LocalFileInfo.h */,
662 96A169A31430D53600E4C990 /* U1LocalFileInfo.m */,667 96A169A31430D53600E4C990 /* U1LocalFileInfo.m */,
663 916E0080143C9A390037F6D3 /* U1UploadsPoolViewController.h */,
664 916E0081143C9A390037F6D3 /* U1UploadsPoolViewController.m */,
665 9190AAF31444CA0A0063614A /* U1UploadsPoolViewController.xib */,
666 91EC184B145B8E3A00DF31F4 /* U1SettingsViewController.h */,668 91EC184B145B8E3A00DF31F4 /* U1SettingsViewController.h */,
667 91EC184C145B8E3A00DF31F4 /* U1SettingsViewController.m */,669 91EC184C145B8E3A00DF31F4 /* U1SettingsViewController.m */,
668 91EC184D145B8E3B00DF31F4 /* U1SettingsViewController.xib */,670 91EC184D145B8E3B00DF31F4 /* U1SettingsViewController.xib */,
669 91A007E8147559F200D0E5FF /* U1AssetRepresenationDataProvider.h */,
670 91A007E9147559F200D0E5FF /* U1AssetRepresenationDataProvider.m */,
671 9623AE6014868F7000ACDF1C /* U1ReportingInputStream.h */,671 9623AE6014868F7000ACDF1C /* U1ReportingInputStream.h */,
672 9623AE6114868F7000ACDF1C /* U1ReportingInputStream.m */,672 9623AE6114868F7000ACDF1C /* U1ReportingInputStream.m */,
673 9172C86E148FA4F600FC7737 /* U1TopPinningLabel.h */,673 9172C86E148FA4F600FC7737 /* U1TopPinningLabel.h */,
@@ -1198,8 +1198,8 @@
1198 armv6,1198 armv6,
1199 armv7,1199 armv7,
1200 );1200 );
1201 CODE_SIGN_IDENTITY = "iPhone Distribution: Canonical Group Limited";1201 CODE_SIGN_IDENTITY = "iPhone Distribution";
1202 "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Canonical Group Limited";1202 "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
1203 FRAMEWORK_SEARCH_PATHS = (1203 FRAMEWORK_SEARCH_PATHS = (
1204 "$(inherited)",1204 "$(inherited)",
1205 "\"$(SRCROOT)\"",1205 "\"$(SRCROOT)\"",
@@ -1214,8 +1214,8 @@
1214 "\"$(SRCROOT)/Dependencies/TestFlightSDK\"",1214 "\"$(SRCROOT)/Dependencies/TestFlightSDK\"",
1215 );1215 );
1216 PRODUCT_NAME = "$(TARGET_NAME)";1216 PRODUCT_NAME = "$(TARGET_NAME)";
1217 PROVISIONING_PROFILE = "AC4373DF-1FF8-4EA3-A098-888460CA563B";1217 PROVISIONING_PROFILE = "";
1218 "PROVISIONING_PROFILE[sdk=iphoneos*]" = "AC4373DF-1FF8-4EA3-A098-888460CA563B";1218 "PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
1219 TARGETED_DEVICE_FAMILY = 1;1219 TARGETED_DEVICE_FAMILY = 1;
1220 VALID_ARCHS = "arm6 armv7";1220 VALID_ARCHS = "arm6 armv7";
1221 WRAPPER_EXTENSION = app;1221 WRAPPER_EXTENSION = app;
12221222
=== modified file 'Files/Files-Prefix.pch'
--- Files/Files-Prefix.pch 2011-10-26 03:39:52 +0000
+++ Files/Files-Prefix.pch 2011-12-09 20:00:29 +0000
@@ -15,14 +15,16 @@
1515
16#import <Availability.h>16#import <Availability.h>
1717
18#ifndef __IPHONE_3_018#ifndef __IPHONE_4_0
19#warning "This project uses features only available in iPhone SDK 3.0 and later."19#warning "This project uses features only available in iPhone SDK 4.0 and later."
20#endif20#endif
2121
22#ifdef __OBJC__22#ifdef __OBJC__
2323
24#import <UIKit/UIKit.h>24#import <UIKit/UIKit.h>
25#import <Foundation/Foundation.h>25#import <Foundation/Foundation.h>
26#import <CoreData/CoreData.h>
27
26#import "TestFlight.h"28#import "TestFlight.h"
27#import "NSDictionary+U1Additions.h"29#import "NSDictionary+U1Additions.h"
2830
2931
=== modified file 'Files/U1AssetRepresenationDataProvider.h'
--- Files/U1AssetRepresenationDataProvider.h 2011-11-18 16:27:59 +0000
+++ Files/U1AssetRepresenationDataProvider.h 2011-12-09 20:00:29 +0000
@@ -14,9 +14,10 @@
14// along with this program. If not, see <http://www.gnu.org/licenses/>.14// along with this program. If not, see <http://www.gnu.org/licenses/>.
1515
16#import <Foundation/Foundation.h>16#import <Foundation/Foundation.h>
17#import <AssetsLibrary/AssetsLibrary.h>17
18#import "U1FilesClient.h"18#import "U1FilesService.h"
19
1920
20@interface U1AssetRepresenationDataProvider : NSObject <U1UploadDataProvider>21@interface U1AssetRepresenationDataProvider : NSObject <U1UploadDataProvider>
21@property (retain) ALAssetRepresentation *representation;22@property (retain) NSURL *assetURL;
22@end23@end
2324
=== modified file 'Files/U1AssetRepresenationDataProvider.m'
--- Files/U1AssetRepresenationDataProvider.m 2011-11-18 16:27:59 +0000
+++ Files/U1AssetRepresenationDataProvider.m 2011-12-09 20:00:29 +0000
@@ -15,22 +15,61 @@
1515
16#import "U1AssetRepresenationDataProvider.h"16#import "U1AssetRepresenationDataProvider.h"
1717
18#import <AssetsLibrary/AssetsLibrary.h>
19#import <MobileCoreServices/MobileCoreServices.h>
20
21
18@implementation U1AssetRepresenationDataProvider22@implementation U1AssetRepresenationDataProvider
1923{
20@synthesize representation;24 ALAssetsLibrary *library;
25}
26
27@synthesize assetURL;
28
29- (id)init;
30{
31 self = [super init];
32 if (self == nil)
33 return nil;
34 library = [[ALAssetsLibrary alloc] init];
35 return self;
36}
2137
22- (void)dealloc;38- (void)dealloc;
23{39{
24 [representation release];40 [assetURL release];
41 [library release];
25 [super dealloc];42 [super dealloc];
26}43}
2744
28- (NSData *)serializeData;45- (void)prepareDataStreamWithBlock:(void(^)(NSInputStream *dataStream, NSString *mimeType, NSUInteger length, NSError *error))block;
29{46{
30 Byte *buffer = (Byte*)malloc(self.representation.size);47 [library assetForURL:self.assetURL resultBlock:^(ALAsset *asset) {
31 NSUInteger length = [self.representation getBytes:buffer fromOffset:0 length:self.representation.size error:nil];48
32 NSData *assetData = [NSData dataWithBytesNoCopy:buffer length:length freeWhenDone:YES];49 if (asset == nil)
33 return assetData;50 {
51 if (block)
52 {
53 NSError *error = [NSError errorWithDomain:@"nonexistentAsset" code:1 userInfo:nil];
54 block(nil, nil, nil, error);
55 }
56 }
57 else
58 {
59 ALAssetRepresentation *representation = [asset defaultRepresentation];
60 uint8_t *buffer = (uint8_t*)malloc(representation.size);
61 NSUInteger length = [representation getBytes:buffer fromOffset:0 length:representation.size error:nil];
62 NSData *imageData = [NSData dataWithBytesNoCopy:buffer length:length freeWhenDone:YES];
63 NSString *mimeType = (id)UTTypeCopyPreferredTagWithClass((CFStringRef)[representation UTI], kUTTagClassMIMEType);
64 NSInputStream *dataStream = [NSInputStream inputStreamWithData:imageData];
65 if (block)
66 block(dataStream, mimeType, length, nil);
67 }
68
69 } failureBlock:^(NSError *error) {
70 if (block)
71 block(nil, nil, 0, error);
72 }];
34}73}
3574
36@end75@end
3776
=== modified file 'Files/U1AutoUploadOperation.h'
--- Files/U1AutoUploadOperation.h 2011-11-18 16:28:43 +0000
+++ Files/U1AutoUploadOperation.h 2011-12-09 20:00:29 +0000
@@ -14,17 +14,22 @@
14// along with this program. If not, see <http://www.gnu.org/licenses/>.14// along with this program. If not, see <http://www.gnu.org/licenses/>.
1515
16#import <Foundation/Foundation.h>16#import <Foundation/Foundation.h>
17#import "U1FilesClient.h"17#import <CoreData/CoreData.h>
1818
19@protocol U1UploadDataProvider;
19@class U1Asset;20@class U1Asset;
20@class U1FolderNode;21@class U1FolderNode;
2122
23
22@interface U1AutoUploadOperation : NSOperation24@interface U1AutoUploadOperation : NSOperation
2325
24@property (retain) id<U1UploadDataProvider> dataProvider;26@property (retain) id<U1UploadDataProvider> dataProvider;
25@property (retain) U1Asset *u1asset;27
26@property (retain) U1FolderNode *folder;28@property (retain) NSManagedObjectID *assetID;
29@property (retain) NSManagedObjectID *folderID;
30
27@property (retain) NSString *filename;31@property (retain) NSString *filename;
28@property (retain) NSString *contentType;32@property (retain) NSString *contentType;
29@property (atomic) NSOperationQueuePriority priority;33@property (atomic) NSOperationQueuePriority priority;
34
30@end35@end
3136
=== modified file 'Files/U1AutoUploadOperation.m'
--- Files/U1AutoUploadOperation.m 2011-12-06 20:53:05 +0000
+++ Files/U1AutoUploadOperation.m 2011-12-09 20:00:29 +0000
@@ -13,11 +13,14 @@
13// You should have received a copy of the GNU Affero General Public License13// You should have received a copy of the GNU Affero General Public License
14// along with this program. If not, see <http://www.gnu.org/licenses/>.14// along with this program. If not, see <http://www.gnu.org/licenses/>.
1515
16#import "U1AutoUploadOperation.h"
17
16#import "U1Asset.h"18#import "U1Asset.h"
17#import "U1AutoUploadOperation.h"
18#import "U1DataRepository.h"19#import "U1DataRepository.h"
19#import "U1FileNode.h"20#import "U1FileNode.h"
20#import "U1FilesClient.h"21#import "U1FilesClient.h"
22#import "U1FilesService.h"
23
2124
22@interface U1AutoUploadOperation ()25@interface U1AutoUploadOperation ()
23@property (getter=isExecuting) BOOL executing;26@property (getter=isExecuting) BOOL executing;
@@ -26,9 +29,10 @@
26- (void)beginUpload;29- (void)beginUpload;
27@end30@end
2831
32
29@implementation U1AutoUploadOperation33@implementation U1AutoUploadOperation
3034
31@synthesize executing, finished, dataProvider, u1asset, folder, filename, contentType, priority;35@synthesize executing, finished, dataProvider, assetID, folderID, filename, contentType, priority;
3236
33- (BOOL)isConcurrent;37- (BOOL)isConcurrent;
34{38{
@@ -64,32 +68,38 @@
64- (void)dealloc68- (void)dealloc
65{69{
66 [dataProvider release];70 [dataProvider release];
67 [u1asset release];
68 [folder release];
69 [filename release];71 [filename release];
70 [contentType release];72 [contentType release];
73 [assetID release];
74 [folderID release];
71 [super dealloc];75 [super dealloc];
72}76}
7377
74- (void)beginUpload;78- (void)beginUpload;
75{79{
76 dispatch_async(dispatch_get_main_queue(), ^(void) {80 U1DataRepository *dataRepository = [U1DataRepository sharedDataRepository];
77 [[U1FilesClient sharedFilesClient] uploadContentDataProvider:dataProvider toFolder:self.folder withResourceName:self.filename withContentType:self.contentType withPriority:self.priority progressBlock:^(long long bytesUploaded, long long totalBytes) {81 [dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) {
78 82
83 U1Asset *asset = (id)[context objectWithID:self.assetID];
84 U1FolderNode *folder = (id)[context objectWithID:self.folderID];
85
86 [[U1FilesClient sharedFilesClient] uploadContentDataProvider:dataProvider toFolder:folder withResourceName:self.filename withContentType:self.contentType withPriority:self.priority progressBlock:^(long long bytesUploaded, long long totalBytes) {
87
79 } completionBlock:^(U1FileNode *fileNode, NSError *error) {88 } completionBlock:^(U1FileNode *fileNode, NSError *error) {
80 if (error)89 if (error)
81 {90 {
82 NSLog(@"auto-upload failed: %@", error);91 NSLog(@"auto-upload failed: %@", error);
83 } 92 }
8493
85 dispatch_async(dispatch_get_main_queue(), ^(void) {94 dispatch_async(dispatch_get_main_queue(), ^(void) {
86 95
87 self.u1asset.generation = self.u1asset.fileNode.generation;96 asset.generation = asset.fileNode.generation;
88 [[U1DataRepository sharedDataRepository] save:NULL];97 [dataRepository save:NULL];
89 [self finishExecuting];98 [self finishExecuting];
90 });99 });
91 }];100 }];
92 });101
102 }];
93}103}
94104
95@end105@end
96106
=== modified file 'Files/U1AutoUploadsManager.h'
--- Files/U1AutoUploadsManager.h 2011-12-06 18:03:30 +0000
+++ Files/U1AutoUploadsManager.h 2011-12-09 20:00:29 +0000
@@ -29,8 +29,8 @@
29+ (U1AutoUploadsManager *)sharedAutoUploadsManager;29+ (U1AutoUploadsManager *)sharedAutoUploadsManager;
30- (int)numberOfAssets;30- (int)numberOfAssets;
31- (void)checkForNewAssets;31- (void)checkForNewAssets;
32- (U1Asset *)createU1AssetWithAsset:(ALAsset *)asset group:(ALAssetsGroup *)group URLString:(NSString *)urlString fileName:(NSString *)filename inFolder:(U1FolderNode *)folderNode;
33- (void)thumbnailForNode:(U1FileNode *)fileNode completionBlock:(void(^)(CGImageRef thumbnail))completionBlock;32- (void)thumbnailForNode:(U1FileNode *)fileNode completionBlock:(void(^)(CGImageRef thumbnail))completionBlock;
34- (NSOperation*)queueAutoUploadForAsset:(U1Asset *)assetToUpload andRepresentation:(ALAssetRepresentation *)representation;33- (NSOperation*)queueAutoUploadForAsset:(U1Asset *)assetToUpload andRepresentation:(ALAssetRepresentation *)representation;
35- (int)pendingCount;34- (int)pendingCount;
35- (U1Asset *)createU1AssetWithAsset:(ALAsset *)asset group:(ALAssetsGroup *)group URLString:(NSString *)urlString fileName:(NSString *)filename inFolder:(U1FolderNode *)folderNode context:(NSManagedObjectContext*)context;
36@end36@end
3737
=== modified file 'Files/U1AutoUploadsManager.m'
--- Files/U1AutoUploadsManager.m 2011-12-07 20:42:55 +0000
+++ Files/U1AutoUploadsManager.m 2011-12-09 20:00:29 +0000
@@ -29,9 +29,11 @@
29#import "U1FolderNode.h"29#import "U1FolderNode.h"
30#import "U1Volume.h"30#import "U1Volume.h"
3131
32
32@interface U1AutoUploadsManager ()33@interface U1AutoUploadsManager ()
33@property (retain) U1FilesClient *filesClient;34@property (retain) U1FilesClient *filesClient;
34@property (retain) NSOperationQueue *autoUploadPreparationQueue;35@property (retain) NSOperationQueue *autoUploadPreparationQueue;
36@property (retain) NSManagedObjectID *autoUploadsFolderID;
35- (void)walkAssetsInLibrary;37- (void)walkAssetsInLibrary;
36- (NSString *)generateFilenameForAsset:(ALAsset *)asset;38- (NSString *)generateFilenameForAsset:(ALAsset *)asset;
37- (void)processAssetBatch:(NSArray*)batch inGroup:(ALAssetsGroup *)group toArray:(NSMutableArray*)ops;39- (void)processAssetBatch:(NSArray*)batch inGroup:(ALAssetsGroup *)group toArray:(NSMutableArray*)ops;
@@ -43,16 +45,16 @@
43- (void)volumesFetched:(NSNotification *)notification;45- (void)volumesFetched:(NSNotification *)notification;
44@end46@end
4547
46static U1AutoUploadsManager *sharedAutoUploadsManager = nil;
4748
48@implementation U1AutoUploadsManager49@implementation U1AutoUploadsManager
4950
50@synthesize filesClient, dataRepository, assetsLibrary;51@synthesize filesClient, dataRepository, assetsLibrary;
51@synthesize autoUploadPreparationQueue;52@synthesize autoUploadPreparationQueue, autoUploadsFolderID;
52@synthesize remoteUploadFolder;53@synthesize remoteUploadFolder;
5354
54+ (U1AutoUploadsManager *)sharedAutoUploadsManager;55+ (U1AutoUploadsManager *)sharedAutoUploadsManager;
55{56{
57 static U1AutoUploadsManager *sharedAutoUploadsManager = nil;
56 if (sharedAutoUploadsManager == nil)58 if (sharedAutoUploadsManager == nil)
57 {59 {
58 sharedAutoUploadsManager = [[U1AutoUploadsManager alloc] init];60 sharedAutoUploadsManager = [[U1AutoUploadsManager alloc] init];
@@ -86,6 +88,7 @@
86 [assetsLibrary release];88 [assetsLibrary release];
87 [autoUploadPreparationQueue release];89 [autoUploadPreparationQueue release];
88 [remoteUploadFolder release];90 [remoteUploadFolder release];
91 [autoUploadsFolderID release];
89 [super dealloc];92 [super dealloc];
90}93}
9194
@@ -169,6 +172,7 @@
169 if (error == nil)172 if (error == nil)
170 {173 {
171 self.remoteUploadFolder = volume.rootFolder;174 self.remoteUploadFolder = volume.rootFolder;
175 self.autoUploadsFolderID = [volume.rootFolder objectID];
172 [self fetchRemoteUploadFolderContents];176 [self fetchRemoteUploadFolderContents];
173 }177 }
174 else178 else
@@ -180,6 +184,7 @@
180 else184 else
181 {185 {
182 self.remoteUploadFolder = volume.rootFolder;186 self.remoteUploadFolder = volume.rootFolder;
187 self.autoUploadsFolderID = [volume.rootFolder objectID];
183 [self fetchRemoteUploadFolderContents];188 [self fetchRemoteUploadFolderContents];
184 }189 }
185 }190 }
@@ -200,6 +205,7 @@
200 if (resultsDataSourceType == U1DataSourceRemote)205 if (resultsDataSourceType == U1DataSourceRemote)
201 {206 {
202 [childrenResultsController performFetch:NULL];207 [childrenResultsController performFetch:NULL];
208 // TODO: this
203 [self queuePreviousUploads];209 [self queuePreviousUploads];
204 [self checkForNewAssets];210 [self checkForNewAssets];
205 }211 }
@@ -218,49 +224,56 @@
218 224
219 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];225 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
220 226
221 if ([defaults boolForKey:@"auto_upload"]) {227 if ([defaults boolForKey:@"auto_upload"])
222 [self.assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos228 {
223 usingBlock:^(ALAssetsGroup *group, BOOL *stop) {229 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
224 NSMutableArray *ops = [NSMutableArray array];
225 __block NSMutableArray *batch = [[NSMutableArray alloc] initWithCapacity:50];
226 [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop) {
227 if (asset == nil)
228 {
229 return;
230 }
231
232 [batch addObject:asset];
233230
234 if ([batch count] >= 50)231 [self.assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
235 {232
236 NSSortDescriptor *sortBy = [NSSortDescriptor sortDescriptorWithKey:@"defaultRepresentation.url.absoluteString" ascending:YES];233 NSMutableArray *ops = [NSMutableArray array];
237 [batch sortUsingDescriptors:[NSArray arrayWithObject:sortBy]];234 __block NSMutableArray *batch = [[NSMutableArray alloc] initWithCapacity:50];
238 [self processAssetBatch:batch inGroup:group toArray:ops];235 [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop) {
239 [batch release];236
240 batch = [[NSMutableArray alloc] initWithCapacity:50];237 if (asset == nil)
241 }238 {
242 }];239 return;
243 if ([batch count] > 0) // Deal with last partial batch240 }
244 {241
245 NSSortDescriptor *sortBy = [NSSortDescriptor sortDescriptorWithKey:@"defaultRepresentation.url.absoluteString" ascending:YES];242 [batch addObject:asset];
246 [batch sortUsingDescriptors:[NSArray arrayWithObject:sortBy]];243
247 [self processAssetBatch:batch inGroup:group toArray:ops];244 if ([batch count] >= 50)
248 }245 {
249 [batch release];246 NSSortDescriptor *sortBy = [NSSortDescriptor sortDescriptorWithKey:@"defaultRepresentation.url.absoluteString" ascending:YES];
250 batch = nil;247 [batch sortUsingDescriptors:[NSArray arrayWithObject:sortBy]];
251 NSArray *sortedOps = [ops sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"filename" ascending:YES]]];248 [self processAssetBatch:batch inGroup:group toArray:ops];
252 [sortedOps enumerateObjectsUsingBlock:^(U1AutoUploadOperation *operation, NSUInteger idx, BOOL *stop) {249 [batch release];
253 [self.autoUploadPreparationQueue addOperation:operation];250 batch = [[NSMutableArray alloc] initWithCapacity:50];
254 [[NSNotificationCenter defaultCenter] postNotificationName:@"uploadQueued" object:nil];251 }
255 }];252 }];
256 [ops removeAllObjects];253 if ([batch count] > 0) // Deal with last partial batch
257 alreadyWalking = NO;254 {
258 }255 NSSortDescriptor *sortBy = [NSSortDescriptor sortDescriptorWithKey:@"defaultRepresentation.url.absoluteString" ascending:YES];
259 failureBlock:^(NSError *error) {256 [batch sortUsingDescriptors:[NSArray arrayWithObject:sortBy]];
260 NSLog(@"Some error happened: %@", error);257 [self processAssetBatch:batch inGroup:group toArray:ops];
261 }];258 }
259 [batch release];
260 batch = nil;
261
262 NSArray *sortedOps = [ops sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"filename" ascending:YES]]];
263 [sortedOps enumerateObjectsUsingBlock:^(U1AutoUploadOperation *operation, NSUInteger idx, BOOL *stop) {
264 [self.autoUploadPreparationQueue addOperation:operation];
265 [[NSNotificationCenter defaultCenter] postNotificationName:@"uploadQueued" object:nil];
266 }];
267 [ops removeAllObjects];
268 alreadyWalking = NO;
269 } failureBlock:^(NSError *error) {
270 NSLog(@"Some error happened: %@", error);
271 }];
272
273 });
262 274
263 }275 }
276
264}277}
265278
266- (void)processAssetBatch:(NSArray*)batch inGroup:(ALAssetsGroup *)group toArray:(NSMutableArray*)ops;279- (void)processAssetBatch:(NSArray*)batch inGroup:(ALAssetsGroup *)group toArray:(NSMutableArray*)ops;
@@ -270,16 +283,19 @@
270 // instead of dealing with a single asset, loop over our batch283 // instead of dealing with a single asset, loop over our batch
271 NSMutableArray *URLs = [batch valueForKeyPath:@"defaultRepresentation.url.absoluteString"];284 NSMutableArray *URLs = [batch valueForKeyPath:@"defaultRepresentation.url.absoluteString"];
272285
273
274 [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {286 [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {
275 NSPredicate *p = [NSPredicate predicateWithFormat:@"url in %@ and (fileNode.parent = %@ OR fileNode = nil)", URLs, self.remoteUploadFolder];287
288 U1FolderNode *autoUploadsFolder = (id)[context objectWithID:self.autoUploadsFolderID];
289 NSMutableSet *assetsToUpload = [NSMutableSet set];
290
291 NSPredicate *p = [NSPredicate predicateWithFormat:@"url in %@ and (fileNode.parent = %@ OR fileNode = nil)", URLs, autoUploadsFolder];
276 NSError *error = nil;292 NSError *error = nil;
277 NSSortDescriptor *sortBy = [NSSortDescriptor sortDescriptorWithKey:@"url" ascending:YES];293 NSSortDescriptor *sortBy = [NSSortDescriptor sortDescriptorWithKey:@"url" ascending:YES];
278 NSArray *existingU1Assets = [[self.dataRepository resultsForEntityClass:[U1Asset class]294 NSArray *existingU1Assets = [self.dataRepository resultsForEntityClass:[U1Asset class]
279 matchingPredicate:p295 inContext:context
280 withSortDescriptors:[NSArray arrayWithObject:sortBy]296 withPredicate:p
281 error:&error] retain];297 sortDescriptors:[NSArray arrayWithObject:sortBy]
282298 error:&error];
283 299
284 // If batch's asset isn't in existingU1Assets or existingU1Asset's generation is nil, we upload it.300 // If batch's asset isn't in existingU1Assets or existingU1Asset's generation is nil, we upload it.
285 301
@@ -320,22 +336,25 @@
320 336
321 if (canUpload) {337 if (canUpload) {
322 shouldUpload = YES;338 shouldUpload = YES;
323 assetToUpload = [self createU1AssetWithAsset:asset group:group URLString:url fileName:nil inFolder:self.remoteUploadFolder];339 assetToUpload = [self createU1AssetWithAsset:asset group:group URLString:url fileName:nil inFolder:autoUploadsFolder context:context];
324 }340 }
325 }341 }
326 // Check shouldUpload flag
327 if (shouldUpload)342 if (shouldUpload)
328 {343 {
329 NSOperation *op = [self queueAutoUploadForAsset:assetToUpload andRepresentation:[asset defaultRepresentation]];344 [assetsToUpload addObject:assetToUpload];
330 if (op)345 }
331 [ops addObject:op];346 }];
332347
333 }348 [context save:NULL];
334 }];349
335350 [assetsToUpload enumerateObjectsUsingBlock:^(U1Asset *u1asset, BOOL *stop) {
336 [self.dataRepository save:NULL];351
337 352 NSOperation *op = [self queueAutoUploadForAsset:u1asset andRepresentation:nil];
338 353 if (op)
354 {
355 [ops addObject:op];
356 }
357 }];
339 }];358 }];
340359
341 360
@@ -344,54 +363,91 @@
344- (void)queuePreviousUploads;363- (void)queuePreviousUploads;
345{364{
346 // We should poll our data repository for all U1Assets which have generation=nil. They *should* all have U1FileNodes associated with them. If the U1FileNode's parent equals our autoUploadsManager's remoteUploadFolder, then it's an auto-upload, and we let the LAM handle it. Otherwise, kick it off immediately to the FilesClient and get it back in the queue.365 // We should poll our data repository for all U1Assets which have generation=nil. They *should* all have U1FileNodes associated with them. If the U1FileNode's parent equals our autoUploadsManager's remoteUploadFolder, then it's an auto-upload, and we let the LAM handle it. Otherwise, kick it off immediately to the FilesClient and get it back in the queue.
347 NSPredicate *p = [NSPredicate predicateWithFormat:@"generation = %@", nil];366 NSPredicate *p = [NSPredicate predicateWithFormat:@"generation = %@", nil];
348 NSError *error = nil;367 NSError *error = nil;
349 NSSortDescriptor *sortBy = [NSSortDescriptor sortDescriptorWithKey:@"filename" ascending:YES];368 NSSortDescriptor *sortBy = [NSSortDescriptor sortDescriptorWithKey:@"filename" ascending:YES];
350 NSArray *previouslyQueuedU1Assets = [self.dataRepository resultsForEntityClass:[U1Asset class]369 NSArray *previouslyQueuedU1Assets = [self.dataRepository resultsForEntityClass:[U1Asset class]
351 matchingPredicate:p370 matchingPredicate:p
352 withSortDescriptors:[NSArray arrayWithObject:sortBy]371 withSortDescriptors:[NSArray arrayWithObject:sortBy]
353 error:&error];372 error:&error];
354 [previouslyQueuedU1Assets enumerateObjectsUsingBlock:^(U1Asset *u1asset, NSUInteger idx, BOOL *stop) {373 __block NSMutableArray *assetsDeletedFromLibrary = [NSMutableArray array];
355 if (u1asset.fileNode.parent == self.remoteUploadFolder)374
356 {375 [previouslyQueuedU1Assets enumerateObjectsUsingBlock:^(U1Asset *u1asset, NSUInteger idx, BOOL *stop) {
357 [self.assetsLibrary assetForURL:[NSURL URLWithString:u1asset.url]376 if (u1asset.fileNode.parent == self.remoteUploadFolder)
358 resultBlock:^(ALAsset *asset) {377 {
378 [self.assetsLibrary assetForURL:[NSURL URLWithString:u1asset.url]
379 resultBlock:^(ALAsset *asset) {
380 if (asset == nil)
381 {
382 NSLog(@"In the results block, but asset is nil!");
383 [assetsDeletedFromLibrary addObject:u1asset];
384 }
385 else
386 {
359 ALAssetRepresentation *rep = [asset defaultRepresentation];387 ALAssetRepresentation *rep = [asset defaultRepresentation];
360 // Belongs to LAM, could punt and let it get picked up by checkForNewAssets388 // Belongs to LAM, could punt and let it get picked up by checkForNewAssets
361 NSOperation *op = [self queueAutoUploadForAsset:u1asset andRepresentation:rep];389 NSOperation *op = [self queueAutoUploadForAsset:u1asset andRepresentation:rep];
362 if (op)390 if (op)
391 {
363 [self.autoUploadPreparationQueue addOperation:op];392 [self.autoUploadPreparationQueue addOperation:op];
364 } failureBlock:^(NSError *error) {393 }
365 NSLog(@"Error: %@", error);394 }
366 // TODO: delete asset395 } failureBlock:^(NSError *error) {
367 }];396 NSLog(@"Error: %@", error);
368 }397 [assetsDeletedFromLibrary addObject:u1asset];
369 else398 }];
399 }
400 else
401 {
402 NSURL *imageURL = [NSURL URLWithString:u1asset.url];
403
404 [self.assetsLibrary assetForURL:imageURL
405 resultBlock:^(ALAsset *asset) {
406 if (asset == nil)
407 {
408 NSLog(@"In the results block, but asset is nil!");
409 [assetsDeletedFromLibrary addObject:u1asset];
410 }
411 else
412 {
413 ALAssetRepresentation *representation = [asset defaultRepresentation];
414 NSString *mimetype = (id)UTTypeCopyPreferredTagWithClass((CFStringRef)[representation UTI], kUTTagClassMIMEType);
415
416 U1AssetRepresenationDataProvider *provider = [[U1AssetRepresenationDataProvider alloc] init];
417 provider.assetURL = imageURL;
418
419 [self.filesClient uploadContentDataProvider:provider
420 toFolder:u1asset.fileNode.parent
421 withResourceName:u1asset.filename
422 withContentType:mimetype
423 withPriority:NSOperationQueuePriorityVeryHigh
424 progressBlock:^(long long bytesUploaded, long long totalBytes) {}
425 completionBlock:^(U1FileNode *updatedNode, NSError *error) {
426 u1asset.generation = updatedNode.generation;
427 }];
428 }
429 } failureBlock:^(NSError *error) {
430 NSLog(@"Error: %@", error);
431 [assetsDeletedFromLibrary addObject:u1asset];
432 }];
433 }
434 }];
435
436 // Iterate over the assetsDeletedFromLibrary, and clean them up.
437 [self.dataRepository dispatchAsyncBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {
438 for (int i = 0; i < [assetsDeletedFromLibrary count]; i++)
439 {
440 U1Asset *assetToBeDeleted = [assetsDeletedFromLibrary objectAtIndex:i];
441 U1FileNode *placeholderNode = assetToBeDeleted.fileNode;
442 [context deleteObject:assetToBeDeleted];
443 if (placeholderNode.generation == nil)
370 {444 {
371 NSURL *imageURL = [NSURL URLWithString:u1asset.url];445 [context deleteObject:placeholderNode];
372
373 [self.assetsLibrary assetForURL:imageURL
374 resultBlock:^(ALAsset *asset) {
375 ALAssetRepresentation *representation = [asset defaultRepresentation];
376 NSString *mimetype = (id)UTTypeCopyPreferredTagWithClass((CFStringRef)[representation UTI], kUTTagClassMIMEType);
377
378 U1AssetRepresenationDataProvider *provider = [[U1AssetRepresenationDataProvider alloc] init];
379 provider.representation = representation;
380
381 [self.filesClient uploadContentDataProvider:provider
382 toFolder:u1asset.fileNode.parent
383 withResourceName:u1asset.filename
384 withContentType:mimetype
385 withPriority:NSOperationQueuePriorityVeryHigh
386 progressBlock:^(long long bytesUploaded, long long totalBytes) {}
387 completionBlock:^(U1FileNode *updatedNode, NSError *error) {
388 u1asset.generation = updatedNode.generation;
389 }];
390 } failureBlock:^(NSError *error) {
391 NSLog(@"Error: %@", error);
392 }];
393 }446 }
394 }];447 [self.dataRepository save:NULL];
448 }
449 [assetsDeletedFromLibrary release];
450 }];
395}451}
396452
397- (NSString *)remoteUploadFolderPath;453- (NSString *)remoteUploadFolderPath;
@@ -421,47 +477,41 @@
421 return filename;477 return filename;
422}478}
423479
424- (U1Asset *)createU1AssetWithAsset:(ALAsset *)asset group:(ALAssetsGroup *)group URLString:(NSString *)urlString fileName:(NSString *)filename inFolder:(U1FolderNode *)folderNode;480- (U1Asset *)createU1AssetWithAsset:(ALAsset *)asset group:(ALAssetsGroup *)group URLString:(NSString *)urlString fileName:(NSString *)filename inFolder:(U1FolderNode *)folderNode context:(NSManagedObjectContext*)context;
425{481{
426 __block U1Asset *newAsset = nil;482 U1Asset *newAsset = [U1Asset insertInManagedObjectContext:context];
427 __block NSString *newFilename = filename;483 newAsset.groupId = [group valueForProperty: ALAssetsGroupPropertyPersistentID];
428 484 newAsset.url = urlString;
429 // TODO: temporary, create node if doesn't exist485 if (filename == nil)
430 [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {486 {
431 newAsset = [U1Asset insertInManagedObjectContext:context];487 filename = [self generateFilenameForAsset:asset];
432 newAsset.groupId = [group valueForProperty: ALAssetsGroupPropertyPersistentID];488 }
433 newAsset.url = urlString;489 newAsset.filename = filename;
434 if (filename == nil)490 NSString *resourcePath = [folderNode.resourcePath stringByAppendingPathComponent:filename];
435 {491 NSString *contentPath = [folderNode.contentPath stringByAppendingPathComponent:filename];
436 newFilename = [self generateFilenameForAsset:asset];492
437 }493 __block BOOL found = NO;
438 newAsset.filename = newFilename;494 __block U1FileNode *node = nil;
439 NSString *resourcePath = [folderNode.resourcePath stringByAppendingPathComponent:newFilename];495
440 NSString *contentPath = [folderNode.contentPath stringByAppendingPathComponent:newFilename];496 [folderNode.children enumerateObjectsUsingBlock:^(U1FileNode *childNode, BOOL *stop) {
441497 if ([childNode.name isEqualToString:filename]) {
442 __block BOOL found = NO;498 found = YES;
443 __block U1FileNode *node = nil;499 newAsset.generation = childNode.generation;
444500 newAsset.fileNode = childNode;
445 [folderNode.children enumerateObjectsUsingBlock:^(U1FileNode *childNode, BOOL *stop) {501 *stop = YES;
446 if ([childNode.name isEqualToString:newFilename]) {
447 found = YES;
448 newAsset.generation = childNode.generation;
449 newAsset.fileNode = childNode;
450 *stop = YES;
451 }
452 }];
453 // Now we have an asset. We need to check to see if a corresponding FileNode is in our remoteUploadFolderChildren, and use it if it is.
454 if (!found)
455 {
456 node = [U1FileNode insertInManagedObjectContext:context];
457 node.resourcePath = resourcePath;
458 node.kind = @"file";
459 node.parent = folderNode;
460 node.contentPath = contentPath;
461 node.asset = newAsset;
462 }502 }
463 }];503 }];
464504 // Now we have an asset. We need to check to see if a corresponding FileNode is in our remoteUploadFolderChildren, and use it if it is.
505 if (!found)
506 {
507 node = [U1FileNode insertInManagedObjectContext:context];
508 node.resourcePath = resourcePath;
509 node.kind = @"file";
510 node.parent = folderNode;
511 node.contentPath = contentPath;
512 node.asset = newAsset;
513 }
514
465 return newAsset;515 return newAsset;
466}516}
467517
@@ -477,15 +527,16 @@
477 if ((![self isPending:assetToUpload.filename]) && (assetToUpload.generation == nil))527 if ((![self isPending:assetToUpload.filename]) && (assetToUpload.generation == nil))
478 {528 {
479 U1AssetRepresenationDataProvider *provider = [[U1AssetRepresenationDataProvider alloc] init];529 U1AssetRepresenationDataProvider *provider = [[U1AssetRepresenationDataProvider alloc] init];
480 provider.representation = representation;530 provider.assetURL = [NSURL URLWithString:assetToUpload.url];
481 531
482 // Let's create an operation!532 // Let's create an operation!
483 U1AutoUploadOperation *operation = [[U1AutoUploadOperation alloc] init];533 U1AutoUploadOperation *operation = [[U1AutoUploadOperation alloc] init];
484 operation.dataProvider = provider;534 operation.dataProvider = provider;
485 operation.u1asset = assetToUpload;535 operation.assetID = [assetToUpload objectID];
486 operation.folder = self.remoteUploadFolder;536 operation.folderID = [self.remoteUploadFolder objectID];
487 operation.filename = assetToUpload.filename;537 operation.filename = assetToUpload.filename;
488 operation.contentType = (id)UTTypeCopyPreferredTagWithClass((CFStringRef)[provider.representation UTI], kUTTagClassMIMEType);538 // TODO:
539// operation.contentType = (id)UTTypeCopyPreferredTagWithClass((CFStringRef)[provider.representation UTI], kUTTagClassMIMEType);
489 operation.priority = NSOperationQueuePriorityNormal;540 operation.priority = NSOperationQueuePriorityNormal;
490 return [operation autorelease];541 return [operation autorelease];
491 }542 }
492543
=== modified file 'Files/U1DataRepository.h'
--- Files/U1DataRepository.h 2011-09-23 18:35:34 +0000
+++ Files/U1DataRepository.h 2011-12-09 20:00:29 +0000
@@ -26,10 +26,12 @@
2626
27- (U1Node*)nodeWithResourcePath:(NSString*)resourcePath;27- (U1Node*)nodeWithResourcePath:(NSString*)resourcePath;
2828
29//- (void)fetchResultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors completionBlock:(void(^)(NSArray *results, NSError *error))completionBlock;
30
31- (NSArray*)resultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error;29- (NSArray*)resultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error;
3230
31- (NSArray*)resultsForEntityClass:(Class)class inContext:(NSManagedObjectContext*)context withPredicate:(NSPredicate*)predicate sortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error;
32
33- (void)dispatchBlockWithMainContext:(void(^)(NSManagedObjectContext *context))block;
34
33- (void)dispatchBlockWithManagedObjectContext:(void(^)(NSManagedObjectContext *context))block;35- (void)dispatchBlockWithManagedObjectContext:(void(^)(NSManagedObjectContext *context))block;
3436
35- (void)dispatchAsyncBlockWithManagedObjectContext:(void(^)(NSManagedObjectContext *context))block;37- (void)dispatchAsyncBlockWithManagedObjectContext:(void(^)(NSManagedObjectContext *context))block;
3638
=== modified file 'Files/U1DataRepository.m'
--- Files/U1DataRepository.m 2011-10-25 23:36:04 +0000
+++ Files/U1DataRepository.m 2011-12-09 20:00:29 +0000
@@ -27,7 +27,7 @@
27@property (nonatomic, retain) NSManagedObjectContext *mainContext;27@property (nonatomic, retain) NSManagedObjectContext *mainContext;
28@property (nonatomic, retain) NSPersistentStoreCoordinator *storeCoordinator;28@property (nonatomic, retain) NSPersistentStoreCoordinator *storeCoordinator;
2929
30- (NSArray*)fetchEntitiesForClass:(Class)class inContext:(NSManagedObjectContext*)context withPredicate:(NSPredicate*)predicate sortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error;30- (NSArray*)resultsForEntityClass:(Class)class inContext:(NSManagedObjectContext*)context withPredicate:(NSPredicate*)predicate sortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error;
3131
32@end32@end
3333
@@ -101,22 +101,17 @@
101 NSParameterAssert(resourcePath);101 NSParameterAssert(resourcePath);
102102
103 NSPredicate *p = [NSPredicate predicateWithFormat:@"resourcePath = %@", resourcePath];103 NSPredicate *p = [NSPredicate predicateWithFormat:@"resourcePath = %@", resourcePath];
104 NSArray *nodes = [self fetchEntitiesForClass:[U1Node class] inContext:self.mainContext withPredicate:p sortDescriptors:nil error:NULL];104 NSArray *nodes = [self resultsForEntityClass:[U1Node class] inContext:self.mainContext withPredicate:p sortDescriptors:nil error:NULL];
105 U1Node *node = [nodes lastObject];105 U1Node *node = [nodes lastObject];
106 return node;106 return node;
107}107}
108108
109//- (void)fetchResultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors completionBlock:(void(^)(NSArray *results, NSError *error))completionBlock;
110//{
111//
112//}
113
114- (NSArray*)resultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error;109- (NSArray*)resultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error;
115{110{
116 return [self fetchEntitiesForClass:entityClass inContext:self.mainContext withPredicate:predicate sortDescriptors:sortDescriptors error:error];111 return [self resultsForEntityClass:entityClass inContext:self.mainContext withPredicate:predicate sortDescriptors:sortDescriptors error:error];
117}112}
118113
119- (NSArray*)fetchEntitiesForClass:(Class)class inContext:(NSManagedObjectContext*)context withPredicate:(NSPredicate*)predicate sortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error;114- (NSArray*)resultsForEntityClass:(Class)class inContext:(NSManagedObjectContext*)context withPredicate:(NSPredicate*)predicate sortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error;
120{115{
121 NSParameterAssert(class != nil);116 NSParameterAssert(class != nil);
122 NSParameterAssert(context != nil);117 NSParameterAssert(context != nil);
@@ -129,7 +124,7 @@
129 return results;124 return results;
130}125}
131126
132- (void)dispatchBlockWithManagedObjectContext:(void(^)(NSManagedObjectContext *context))block;127- (void)dispatchBlockWithMainContext:(void(^)(NSManagedObjectContext *context))block;
133{128{
134 NSParameterAssert(block != NULL);129 NSParameterAssert(block != NULL);
135 if (![NSThread isMainThread])130 if (![NSThread isMainThread])
@@ -146,6 +141,22 @@
146 }141 }
147}142}
148143
144- (void)dispatchBlockWithManagedObjectContext:(void(^)(NSManagedObjectContext *context))block;
145{
146 NSParameterAssert(block != NULL);
147
148 NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
149 id observation = [[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:context queue:nil usingBlock:^(NSNotification *note) {
150 dispatch_async(dispatch_get_main_queue(), ^{
151 [self.mainContext mergeChangesFromContextDidSaveNotification:note];
152 });
153 }] retain];
154 [context setPersistentStoreCoordinator:self.storeCoordinator];
155 block(context);
156 [context release];
157 [observation release];
158}
159
149- (void)dispatchAsyncBlockWithManagedObjectContext:(void(^)(NSManagedObjectContext *context))block;160- (void)dispatchAsyncBlockWithManagedObjectContext:(void(^)(NSManagedObjectContext *context))block;
150{161{
151 NSParameterAssert(block != NULL);162 NSParameterAssert(block != NULL);
@@ -153,10 +164,16 @@
153 typeof(block) contextBlock = [block copy];164 typeof(block) contextBlock = [block copy];
154 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {165 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
155 NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];166 NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
167 id observation = [[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:context queue:nil usingBlock:^(NSNotification *note) {
168 dispatch_async(dispatch_get_main_queue(), ^{
169 [self.mainContext mergeChangesFromContextDidSaveNotification:note];
170 });
171 }] retain];
156 [context setPersistentStoreCoordinator:self.storeCoordinator];172 [context setPersistentStoreCoordinator:self.storeCoordinator];
157 contextBlock(context);173 contextBlock(context);
158 [contextBlock release];174 [contextBlock release];
159 [context release];175 [context release];
176 [observation release];
160 });177 });
161}178}
162179
163180
=== modified file 'Files/U1FilesClient.h'
--- Files/U1FilesClient.h 2011-12-01 17:37:53 +0000
+++ Files/U1FilesClient.h 2011-12-09 20:00:29 +0000
@@ -22,10 +22,8 @@
2222
23extern NSString * const U1FilesClientNodeStatusChangedNotification;23extern NSString * const U1FilesClientNodeStatusChangedNotification;
2424
25@protocol U1UploadDataProvider;
2526
26@protocol U1UploadDataProvider <NSObject>
27- (NSData *)serializeData;
28@end
2927
30typedef enum U1DataSourceType {28typedef enum U1DataSourceType {
31 U1DataSourceLocal,29 U1DataSourceLocal,
3230
=== modified file 'Files/U1FilesClient.m'
--- Files/U1FilesClient.m 2011-12-06 20:53:05 +0000
+++ Files/U1FilesClient.m 2011-12-09 20:00:29 +0000
@@ -117,7 +117,7 @@
117 __block NSFetchedResultsController *cloudFoldersResultsController = nil;117 __block NSFetchedResultsController *cloudFoldersResultsController = nil;
118 __block U1Volume *rootVolume = nil; // vestigial118 __block U1Volume *rootVolume = nil; // vestigial
119 119
120 [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {120 [self.dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) {
121 121
122 NSFetchRequest *request = [[NSFetchRequest alloc] init];122 NSFetchRequest *request = [[NSFetchRequest alloc] init];
123 [request setEntity:[U1Volume entityInManagedObjectContext:context]];123 [request setEntity:[U1Volume entityInManagedObjectContext:context]];
@@ -142,7 +142,7 @@
142 142
143 [self.filesService volumeInfoWithCompletionBlock:^(NSArray *volumeInfos, NSError *error) {143 [self.filesService volumeInfoWithCompletionBlock:^(NSArray *volumeInfos, NSError *error) {
144 144
145 [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {145 [self.dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) {
146 146
147 NSMutableArray *fetchedVolumes = [NSMutableArray array];147 NSMutableArray *fetchedVolumes = [NSMutableArray array];
148 for (NSDictionary *volumeInfo in volumeInfos)148 for (NSDictionary *volumeInfo in volumeInfos)
@@ -193,7 +193,7 @@
193 __block U1FolderNode *node = [(id)[self.dataRepository nodeWithResourcePath:nodePath] retain];193 __block U1FolderNode *node = [(id)[self.dataRepository nodeWithResourcePath:nodePath] retain];
194 __block NSFetchedResultsController *resultsController = nil;194 __block NSFetchedResultsController *resultsController = nil;
195195
196 [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {196 [self.dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) {
197197
198 if (!node)198 if (!node)
199 {199 {
@@ -237,17 +237,24 @@
237 237
238 [node updatePropertiesFromJSONDictionary:nodeInfo];238 [node updatePropertiesFromJSONDictionary:nodeInfo];
239 239
240 NSManagedObjectID *nodeID = [node objectID];
241
240 NSArray *childInfos = [nodeInfo objectForKey:@"children"];242 NSArray *childInfos = [nodeInfo objectForKey:@"children"];
241 [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {243 [self.dataRepository dispatchAsyncBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {
242 244
245 U1FolderNode *folderNode = (id)[context objectWithID:nodeID];
243 NSMutableSet *orphans = [NSMutableSet set];246 NSMutableSet *orphans = [NSMutableSet set];
244 [orphans unionSet:node.children];247 [orphans unionSet:folderNode.children];
245 248
249 NSUInteger batchCounter = 0;
246 for (NSDictionary *childInfo in childInfos)250 for (NSDictionary *childInfo in childInfos)
247 {251 {
248 NSString *childResourcePath = [childInfo objectForKey:@"resource_path"];252 NSString *childResourcePath = [childInfo objectForKey:@"resource_path"];
249 NSString *kind = [childInfo objectForKey:@"kind"];253 NSString *kind = [childInfo objectForKey:@"kind"];
250 U1Node *childNode = [self.dataRepository nodeWithResourcePath:childResourcePath];254 NSError *error = nil;
255 NSPredicate *p = [NSPredicate predicateWithFormat:@"resourcePath = %@", childResourcePath];
256 NSArray *results = [self.dataRepository resultsForEntityClass:[U1Node class] inContext:context withPredicate:p sortDescriptors:nil error:&error];
257 U1Node *childNode = [results lastObject];
251 if (!childNode)258 if (!childNode)
252 {259 {
253 if ([@"file" isEqualToString:kind])260 if ([@"file" isEqualToString:kind])
@@ -257,8 +264,14 @@
257 }264 }
258 265
259 [childNode updatePropertiesFromJSONDictionary:childInfo];266 [childNode updatePropertiesFromJSONDictionary:childInfo];
260 childNode.parent = node;267 childNode.parent = folderNode;
261 [orphans removeObject:childNode];268 [orphans removeObject:childNode];
269
270 if (++batchCounter > 100)
271 {
272 [context save:NULL];
273 batchCounter = 0;
274 }
262 }275 }
263 276
264 for (U1Node *orphan in orphans)277 for (U1Node *orphan in orphans)
@@ -270,13 +283,15 @@
270 }283 }
271 284
272 [context save:NULL];285 [context save:NULL];
286
287 dispatch_async(dispatch_get_main_queue(), ^(void) {
288 resultsBlock(node, resultsController, U1DataSourceRemote);
289 [resultsController release];
290 [node release];
291 });
292
273 }];293 }];
274294
275 dispatch_async(dispatch_get_main_queue(), ^(void) {
276 resultsBlock(node, resultsController, U1DataSourceRemote);
277 [resultsController release];
278 [node release];
279 });
280 295
281 }];296 }];
282 return nil;297 return nil;
@@ -288,7 +303,7 @@
288 303
289 if (!node)304 if (!node)
290 {305 {
291 [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {306 [self.dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) {
292 node = [[U1FileNode insertInManagedObjectContext:context] retain];307 node = [[U1FileNode insertInManagedObjectContext:context] retain];
293 node.resourcePath = nodePath;308 node.resourcePath = nodePath;
294 [context save:NULL];309 [context save:NULL];
@@ -333,7 +348,7 @@
333 return [self.filesService deleteNodeAtResourcePath:node.resourcePath completionBlock:^(NSError *error) {348 return [self.filesService deleteNodeAtResourcePath:node.resourcePath completionBlock:^(NSError *error) {
334 if (!error)349 if (!error)
335 {350 {
336 [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {351 [self.dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) {
337 [context deleteObject:node];352 [context deleteObject:node];
338 [context save:NULL];353 [context save:NULL];
339 }];354 }];
@@ -348,7 +363,7 @@
348 U1FileNode *node = (id)[self.dataRepository nodeWithResourcePath:resourcePath];363 U1FileNode *node = (id)[self.dataRepository nodeWithResourcePath:resourcePath];
349 if (!node)364 if (!node)
350 {365 {
351 [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {366 [self.dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) {
352 U1FileNode *newNode = [U1FileNode insertInManagedObjectContext:context];367 U1FileNode *newNode = [U1FileNode insertInManagedObjectContext:context];
353 newNode.resourcePath = resourcePath;368 newNode.resourcePath = resourcePath;
354 newNode.kind = @"file";369 newNode.kind = @"file";
@@ -429,7 +444,7 @@
429 U1FolderNode *node = (id)[self.dataRepository nodeWithResourcePath:resourcePath];444 U1FolderNode *node = (id)[self.dataRepository nodeWithResourcePath:resourcePath];
430 if (!node)445 if (!node)
431 {446 {
432 [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {447 [self.dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) {
433 U1FolderNode *newNode = [U1FolderNode insertInManagedObjectContext:context];448 U1FolderNode *newNode = [U1FolderNode insertInManagedObjectContext:context];
434 newNode.resourcePath = resourcePath;449 newNode.resourcePath = resourcePath;
435 newNode.kind = @"directory";450 newNode.kind = @"directory";
@@ -452,7 +467,7 @@
452- (id)createVolumeAtPath:(NSString*)folderPath completionBlock:(void(^)(U1Volume *volume, NSError *error))completionBlock;467- (id)createVolumeAtPath:(NSString*)folderPath completionBlock:(void(^)(U1Volume *volume, NSError *error))completionBlock;
453{468{
454 return [self.filesService createVolumeAtPath:folderPath completionBlock:^(NSDictionary *volumeInfo, NSError *error) {469 return [self.filesService createVolumeAtPath:folderPath completionBlock:^(NSDictionary *volumeInfo, NSError *error) {
455 [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {470 [self.dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) {
456 U1Volume *volume = [U1Volume insertInManagedObjectContext:context];471 U1Volume *volume = [U1Volume insertInManagedObjectContext:context];
457 if (!error)472 if (!error)
458 {473 {
459474
=== modified file 'Files/U1FilesService.h'
--- Files/U1FilesService.h 2011-11-01 01:17:53 +0000
+++ Files/U1FilesService.h 2011-12-09 20:00:29 +0000
@@ -18,6 +18,11 @@
18@class U1Node, U1FileNode, U1FolderNode;18@class U1Node, U1FileNode, U1FolderNode;
1919
2020
21@protocol U1UploadDataProvider <NSObject>
22- (void)prepareDataStreamWithBlock:(void(^)(NSInputStream *dataStream, NSString *mimeType, NSUInteger length, NSError *error))block;
23@end
24
25
21@interface U1FilesService : NSObject26@interface U1FilesService : NSObject
2227
23+ (U1FilesService *)sharedFilesService;28+ (U1FilesService *)sharedFilesService;
@@ -28,7 +33,7 @@
28- (id)infoForNode:(U1Node*)node includeChildren:(BOOL)includeChildren completionBlock:(void(^)(NSDictionary *node, NSError *error))completionBlock;33- (id)infoForNode:(U1Node*)node includeChildren:(BOOL)includeChildren completionBlock:(void(^)(NSDictionary *node, NSError *error))completionBlock;
29- (id)contentForNode:(U1FileNode*)node progressBlock:(void(^)(long long bytesReceived, long long bytesExpected))progressBlock completionBlock:(void(^)(NSURL *contentURL))completionBlock;34- (id)contentForNode:(U1FileNode*)node progressBlock:(void(^)(long long bytesReceived, long long bytesExpected))progressBlock completionBlock:(void(^)(NSURL *contentURL))completionBlock;
30- (id)uploadContentAtURL:(NSURL*)contentURL forNode:(U1FileNode*)node progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(U1FileNode *updatedNode, NSError *error))completionBlock;35- (id)uploadContentAtURL:(NSURL*)contentURL forNode:(U1FileNode*)node progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(U1FileNode *updatedNode, NSError *error))completionBlock;
31- (id)uploadContentData:(NSData*)contentData forNode:(U1FileNode*)node withContentType:(NSString*)contentType progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(NSDictionary *updatedNodeInfo, NSError *error))completionBlock;36- (id)uploadContentData:(id<U1UploadDataProvider>)contentData forNode:(U1FileNode*)node withContentType:(NSString*)contentType progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(NSDictionary *updatedNodeInfo, NSError *error))completionBlock;
32- (id)moveNodeAtResourcePath:(NSString*)resourcePath toPath:(NSString*)newPath withCompletionBlock:(void(^)(NSDictionary *nodeInfo, NSError *error))completionBlock;37- (id)moveNodeAtResourcePath:(NSString*)resourcePath toPath:(NSString*)newPath withCompletionBlock:(void(^)(NSDictionary *nodeInfo, NSError *error))completionBlock;
33- (id)deleteNodeAtResourcePath:(NSString*)resourcePath completionBlock:(void(^)(NSError *error))completionBlock;38- (id)deleteNodeAtResourcePath:(NSString*)resourcePath completionBlock:(void(^)(NSError *error))completionBlock;
34- (id)publishNode:(U1FileNode*)node completionBlock:(void(^)(U1FileNode *node, NSError *error))completionBlock;39- (id)publishNode:(U1FileNode*)node completionBlock:(void(^)(U1FileNode *node, NSError *error))completionBlock;
3540
=== modified file 'Files/U1FilesService.m'
--- Files/U1FilesService.m 2011-12-06 18:38:47 +0000
+++ Files/U1FilesService.m 2011-12-09 20:00:29 +0000
@@ -196,20 +196,28 @@
196 return nil;196 return nil;
197}197}
198198
199- (id)uploadContentData:(NSData*)contentData forNode:(U1FileNode*)node withContentType:(NSString*)contentType progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(NSDictionary *updatedNodeInfo, NSError *error))completionBlock;199- (id)uploadContentData:(id<U1UploadDataProvider>)contentData forNode:(U1FileNode*)node withContentType:(NSString*)contentType progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(NSDictionary *updatedNodeInfo, NSError *error))completionBlock;
200{200{
201 NSString *contentPath = node.contentPath;201 NSString *contentPath = node.contentPath;
202 NSURL *requestURL = [NSURL URLWithString:[[U1FilesServiceAPIContentRoot stringByAppendingPathComponent:contentPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];202 NSURL *requestURL = [NSURL URLWithString:[[U1FilesServiceAPIContentRoot stringByAppendingPathComponent:contentPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
203 203
204 204 [contentData prepareDataStreamWithBlock:^(NSInputStream *dataStream, NSString *mimeType, NSUInteger length, NSError *error) {
205 U1ReportingInputStream *stream = [[U1ReportingInputStream alloc] initWithData:contentData];205
206 stream.progressBlock = progressBlock;206 if (error)
207 207 {
208 [self execute:@"PUT" toURL:requestURL withParameters:nil requestBody:stream contentType:contentType contentLength:[contentData length] parseResponseBody:YES completionBlock:^(id results, NSError *error) {208 completionBlock(nil, error);
209 209 return;
210 completionBlock(results, error);210 }
211
212 U1ReportingInputStream *stream = [U1ReportingInputStream inputStreamWithSourceStream:dataStream];
213 stream.progressBlock = progressBlock;
214 stream.dataLength = length;
215 [self execute:@"PUT" toURL:requestURL withParameters:nil requestBody:stream contentType:mimeType contentLength:length parseResponseBody:YES completionBlock:^(id results, NSError *error) {
216
217 completionBlock(results, error);
218 }];
211 }];219 }];
212 220
213 return nil;221 return nil;
214}222}
215223
@@ -350,30 +358,33 @@
350 [request release];358 [request release];
351 359
352 [httpOperation setCompletionBlock:^(void) {360 [httpOperation setCompletionBlock:^(void) {
361
362 id result = nil;
363 NSHTTPURLResponse *response = httpOperation.response;
364 NSError *error = httpOperation.error;
365
366 if ([response statusCode] == 401)
367 {
368 dispatch_async(dispatch_get_main_queue(), ^(void) {
369 [[U1AccountManager sharedAccountManager] removeCredentials];
370 });
371 return;
372 }
373
374 if (!error &&
375 ![[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)] containsIndex:[response statusCode]])
376 {
377 // TODO: semantic error messages
378 error = [NSError errorWithDomain:@"U1FilesServiceErrorDomain" code:[response statusCode] userInfo:nil];
379 }
380 if (!error && parseResponseBody)
381 {
382 NSData *data = [collector data];
383 result = [data objectFromJSONDataWithParseOptions:JKParseOptionNone error:&error];
384 }
385
353 dispatch_async(dispatch_get_main_queue(), ^(void) {386 dispatch_async(dispatch_get_main_queue(), ^(void) {
354 387
355 id result = nil;
356 NSHTTPURLResponse *response = httpOperation.response;
357 NSError *error = httpOperation.error;
358
359 if ([response statusCode] == 401)
360 {
361 [[U1AccountManager sharedAccountManager] removeCredentials];
362 return;
363 }
364
365 if (!error &&
366 ![[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)] containsIndex:[response statusCode]])
367 {
368 // TODO: semantic error messages
369 error = [NSError errorWithDomain:@"U1FilesServiceErrorDomain" code:[response statusCode] userInfo:nil];
370 }
371 if (!error && parseResponseBody)
372 {
373 NSData *data = [collector data];
374 result = [data objectFromJSONDataWithParseOptions:JKParseOptionNone error:&error];
375 }
376
377 if (completionBlock)388 if (completionBlock)
378 completionBlock(result, error);389 completionBlock(result, error);
379 390
380391
=== modified file 'Files/U1FolderItemCell.m'
--- Files/U1FolderItemCell.m 2011-12-01 17:37:53 +0000
+++ Files/U1FolderItemCell.m 2011-12-09 20:00:29 +0000
@@ -19,6 +19,11 @@
19#import "U1ViewNibLoader.h"19#import "U1ViewNibLoader.h"
2020
2121
22@interface U1FolderItemCell ()
23+ (UINib*)cellNib;
24@end
25
26
22@implementation U1FolderItemCell27@implementation U1FolderItemCell
2328
24@synthesize iconImageView, nameLabel, detailLabel, uploadIndicator, uploadProgressView;29@synthesize iconImageView, nameLabel, detailLabel, uploadIndicator, uploadProgressView;
@@ -29,11 +34,21 @@
29 U1FolderItemCell *cell = (id)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass(self)];34 U1FolderItemCell *cell = (id)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass(self)];
30 if (!cell)35 if (!cell)
31 {36 {
32 cell = [U1ViewNibLoader viewFromNib:NSStringFromClass(self)];37 cell = [U1ViewNibLoader viewFromUINib:[U1FolderItemCell cellNib]];
33 }38 }
34 return cell;39 return cell;
35}40}
3641
42+ (UINib*)cellNib;
43{
44 static UINib *cellNib;
45 static dispatch_once_t onceToken;
46 dispatch_once(&onceToken, ^{
47 cellNib = [[UINib nibWithNibName:NSStringFromClass(self) bundle:nil] retain];
48 });
49 return cellNib;
50}
51
37- (void)dealloc52- (void)dealloc
38{53{
39 [iconImageView release];54 [iconImageView release];
4055
=== modified file 'Files/U1FolderItemCell.xib'
--- Files/U1FolderItemCell.xib 2011-12-01 17:37:53 +0000
+++ Files/U1FolderItemCell.xib 2011-12-09 20:00:29 +0000
@@ -101,7 +101,7 @@
101 <string key="NSFrame">{{52, 28}, {234, 17}}</string>101 <string key="NSFrame">{{52, 28}, {234, 17}}</string>
102 <reference key="NSSuperview" ref="604950473"/>102 <reference key="NSSuperview" ref="604950473"/>
103 <reference key="NSWindow"/>103 <reference key="NSWindow"/>
104 <reference key="NSNextKeyView"/>104 <reference key="NSNextKeyView" ref="23474122"/>
105 <bool key="IBUIOpaque">NO</bool>105 <bool key="IBUIOpaque">NO</bool>
106 <bool key="IBUIClipsSubviews">YES</bool>106 <bool key="IBUIClipsSubviews">YES</bool>
107 <int key="IBUIContentMode">7</int>107 <int key="IBUIContentMode">7</int>
@@ -134,6 +134,7 @@
134 <string key="NSFrame">{{293, 17}, {20, 20}}</string>134 <string key="NSFrame">{{293, 17}, {20, 20}}</string>
135 <reference key="NSSuperview" ref="604950473"/>135 <reference key="NSSuperview" ref="604950473"/>
136 <reference key="NSWindow"/>136 <reference key="NSWindow"/>
137 <reference key="NSNextKeyView"/>
137 <bool key="IBUIOpaque">NO</bool>138 <bool key="IBUIOpaque">NO</bool>
138 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>139 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
139 <bool key="IBUIHidesWhenStopped">NO</bool>140 <bool key="IBUIHidesWhenStopped">NO</bool>
@@ -145,6 +146,7 @@
145 <string key="NSFrame">{{52, 32}, {234, 9}}</string>146 <string key="NSFrame">{{52, 32}, {234, 9}}</string>
146 <reference key="NSSuperview" ref="604950473"/>147 <reference key="NSSuperview" ref="604950473"/>
147 <reference key="NSWindow"/>148 <reference key="NSWindow"/>
149 <reference key="NSNextKeyView" ref="587955385"/>
148 <bool key="IBUIOpaque">NO</bool>150 <bool key="IBUIOpaque">NO</bool>
149 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>151 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
150 <object class="NSColor" key="IBUIProgressTintColor">152 <object class="NSColor" key="IBUIProgressTintColor">
151153
=== modified file 'Files/U1FolderViewController.m'
--- Files/U1FolderViewController.m 2011-12-07 18:23:32 +0000
+++ Files/U1FolderViewController.m 2011-12-09 20:00:29 +0000
@@ -253,12 +253,13 @@
253 NSString *filename = [NSString stringWithFormat:@"%@ %@.%@", assetType, [dateFormatter stringFromDate:assetDate], ext];253 NSString *filename = [NSString stringWithFormat:@"%@ %@.%@", assetType, [dateFormatter stringFromDate:assetDate], ext];
254 [dateFormatter release];254 [dateFormatter release];
255 255
256 U1Asset *u1asset = [autoUploadsManager createU1AssetWithAsset:asset group:nil URLString:[imageURL absoluteString] fileName:filename inFolder:self.node];256 // TODO: fix!
257 U1Asset *u1asset = [autoUploadsManager createU1AssetWithAsset:asset group:nil URLString:[imageURL absoluteString] fileName:filename inFolder:self.node context:nil];
257 258
258 if (u1asset.generation == nil) // Prevent duplicate uploading to the same folder259 if (u1asset.generation == nil) // Prevent duplicate uploading to the same folder
259 {260 {
260 U1AssetRepresenationDataProvider *provider = [[U1AssetRepresenationDataProvider alloc] init];261 U1AssetRepresenationDataProvider *provider = [[U1AssetRepresenationDataProvider alloc] init];
261 provider.representation = representation;262 provider.assetURL = [NSURL URLWithString:[u1asset url]];
262 dispatch_async(dispatch_get_main_queue(), ^(void) {263 dispatch_async(dispatch_get_main_queue(), ^(void) {
263 [self.filesClient uploadContentDataProvider:provider264 [self.filesClient uploadContentDataProvider:provider
264 toFolder:self.node265 toFolder:self.node
@@ -271,7 +272,7 @@
271 if (error)272 if (error)
272 {273 {
273 // TODO: remove direct access to data repository274 // TODO: remove direct access to data repository
274 [[U1DataRepository sharedDataRepository] dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {275 [[U1DataRepository sharedDataRepository] dispatchBlockWithMainContext:^(NSManagedObjectContext *context) {
275 [context deleteObject:u1asset.fileNode];276 [context deleteObject:u1asset.fileNode];
276 }];277 }];
277 }278 }
278279
=== modified file 'Files/U1ReportingInputStream.h'
--- Files/U1ReportingInputStream.h 2011-11-30 21:42:52 +0000
+++ Files/U1ReportingInputStream.h 2011-12-09 20:00:29 +0000
@@ -19,8 +19,9 @@
19@interface U1ReportingInputStream : NSProxy19@interface U1ReportingInputStream : NSProxy
2020
21@property (copy) void (^progressBlock)(long long, long long);21@property (copy) void (^progressBlock)(long long, long long);
22@property long long dataLength;
2223
23+ (NSInputStream*)inputStreamWithData:(NSData*)data;24+ (U1ReportingInputStream*)inputStreamWithSourceStream:(NSInputStream*)sourceStream;
24- (id)initWithData:(NSData*)data;25- (id)initWithSourceStream:(NSInputStream*)sourceStream;
2526
26@end27@end
2728
=== modified file 'Files/U1ReportingInputStream.m'
--- Files/U1ReportingInputStream.m 2011-11-30 21:42:52 +0000
+++ Files/U1ReportingInputStream.m 2011-12-09 20:00:29 +0000
@@ -23,22 +23,20 @@
2323
24@implementation U1ReportingInputStream24@implementation U1ReportingInputStream
25{25{
26 NSUInteger contentLength;
27 NSUInteger readSoFar;26 NSUInteger readSoFar;
28}27}
2928
30@synthesize progressBlock;29@synthesize progressBlock, dataLength;
31@synthesize targetStream;30@synthesize targetStream;
3231
33+ (NSInputStream *)inputStreamWithData:(NSData *)data;32+ (U1ReportingInputStream *)inputStreamWithSourceStream:(NSInputStream*)sourceStream;
34{33{
35 return [[[self alloc] initWithData:data] autorelease];34 return [[[self alloc] initWithSourceStream:sourceStream] autorelease];
36}35}
3736
38- (id)initWithData:(NSData *)theData;37- (id)initWithSourceStream:(NSInputStream*)sourceStream;
39{38{
40 targetStream = [[NSInputStream alloc] initWithData:theData];39 targetStream = [sourceStream retain];
41 contentLength = [theData length];
42 return self;40 return self;
43}41}
4442
@@ -54,7 +52,7 @@
54 NSInteger read = [self.targetStream read:buffer maxLength:len];52 NSInteger read = [self.targetStream read:buffer maxLength:len];
55 readSoFar += read;53 readSoFar += read;
56 if (self.progressBlock)54 if (self.progressBlock)
57 self.progressBlock(readSoFar, contentLength); 55 self.progressBlock(readSoFar, self.dataLength);
58 return read;56 return read;
59}57}
6058
6159
=== modified file 'Files/U1UploadOperation.m'
--- Files/U1UploadOperation.m 2011-12-06 20:53:05 +0000
+++ Files/U1UploadOperation.m 2011-12-09 20:00:29 +0000
@@ -85,9 +85,7 @@
8585
86 U1FilesService *filesService = [U1FilesService sharedFilesService];86 U1FilesService *filesService = [U1FilesService sharedFilesService];
87 fileInfo.uploading = YES;87 fileInfo.uploading = YES;
88 NSData *uploadData = [self.dataProvider serializeData];88 [filesService uploadContentData:self.dataProvider forNode:self.fileNode withContentType:self.mimetype progressBlock:^(long long uploaded, long long totalLength) {
89
90 [filesService uploadContentData:uploadData forNode:self.fileNode withContentType:self.mimetype progressBlock:^(long long uploaded, long long totalLength) {
91 89
92 dispatch_async(dispatch_get_main_queue(), ^{90 dispatch_async(dispatch_get_main_queue(), ^{
93 [self.fileInfo setUploadPercentage:((double)uploaded / (double)totalLength)];91 [self.fileInfo setUploadPercentage:((double)uploaded / (double)totalLength)];
@@ -107,7 +105,26 @@
107 if (filesServiceError != nil)105 if (filesServiceError != nil)
108 {106 {
109 self.error = filesServiceError;107 self.error = filesServiceError;
110 [self beginUpload];108 if ([filesServiceError.domain isEqualToString:@"nonexistentAsset"])
109 {
110 // Asset is gone, delete U1Asset and potentially the Node, and stop running
111 U1DataRepository *dataRepository = [U1DataRepository sharedDataRepository];
112 [dataRepository dispatchAsyncBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {
113 U1Asset *assetToBeDeleted = self.fileNode.asset;
114 [context deleteObject:assetToBeDeleted];
115 if (self.fileNode.generation == nil)
116 {
117 [context deleteObject:self.fileNode];
118 }
119 [dataRepository save:NULL];
120 }];
121 [self finishExecuting];
122 }
123 else
124 {
125 // File upload timed out or something else, so reschedule
126 [self beginUpload];
127 }
111 }128 }
112 else129 else
113 {130 {
114131
=== modified file 'Files/U1UploadsPoolViewController.m'
--- Files/U1UploadsPoolViewController.m 2011-12-06 18:36:40 +0000
+++ Files/U1UploadsPoolViewController.m 2011-12-09 20:00:29 +0000
@@ -275,7 +275,7 @@
275275
276- (void)loadCurrentUploads;276- (void)loadCurrentUploads;
277{277{
278 [[U1DataRepository sharedDataRepository] dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {278 [[U1DataRepository sharedDataRepository] dispatchBlockWithMainContext:^(NSManagedObjectContext *context) {
279 279
280 NSFetchRequest *request = [[NSFetchRequest alloc] init];280 NSFetchRequest *request = [[NSFetchRequest alloc] init];
281 [request setEntity:[U1Asset entityInManagedObjectContext:context]];281 [request setEntity:[U1Asset entityInManagedObjectContext:context]];
282282
=== modified file 'Files/U1Volume.m'
--- Files/U1Volume.m 2011-10-26 04:40:14 +0000
+++ Files/U1Volume.m 2011-12-09 20:00:29 +0000
@@ -41,7 +41,7 @@
41 if (rootFolder == nil)41 if (rootFolder == nil)
42 {42 {
43 // Upload43 // Upload
44 [dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) {44 [dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) {
45 45
46 U1FolderNode *rootFolder = [U1FolderNode insertInManagedObjectContext:context];46 U1FolderNode *rootFolder = [U1FolderNode insertInManagedObjectContext:context];
47 rootFolder.resourcePath = self.nodePath;47 rootFolder.resourcePath = self.nodePath;
4848
=== modified file 'Files/iPhone/en.lproj/MainWindow_iPhone.xib'
--- Files/iPhone/en.lproj/MainWindow_iPhone.xib 2011-11-18 17:53:03 +0000
+++ Files/iPhone/en.lproj/MainWindow_iPhone.xib 2011-12-09 20:00:29 +0000
@@ -45,10 +45,11 @@
45 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>45 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
46 </object>46 </object>
47 <object class="IBUIWindow" id="380026005">47 <object class="IBUIWindow" id="380026005">
48 <nil key="NSNextResponder"/>48 <reference key="NSNextResponder"/>
49 <int key="NSvFlags">1316</int>49 <int key="NSvFlags">1316</int>
50 <object class="NSPSMatrix" key="NSFrameMatrix"/>50 <object class="NSPSMatrix" key="NSFrameMatrix"/>
51 <string key="NSFrameSize">{320, 480}</string>51 <string key="NSFrameSize">{320, 480}</string>
52 <reference key="NSSuperview"/>
52 <object class="NSColor" key="IBUIBackgroundColor">53 <object class="NSColor" key="IBUIBackgroundColor">
53 <int key="NSColorSpace">1</int>54 <int key="NSColorSpace">1</int>
54 <bytes key="NSRGB">MSAxIDEAA</bytes>55 <bytes key="NSRGB">MSAxIDEAA</bytes>
@@ -68,12 +69,12 @@
68 </object>69 </object>
69 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>70 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
70 <bool key="IBUIHorizontal">NO</bool>71 <bool key="IBUIHorizontal">NO</bool>
71 <object class="IBUINavigationController" key="IBUISelectedViewController" id="941272465">72 <object class="IBUINavigationController" key="IBUISelectedViewController" id="175250829">
72 <object class="IBUITabBarItem" key="IBUITabBarItem" id="463875161">73 <object class="IBUITabBarItem" key="IBUITabBarItem" id="1047769425">
73 <string key="IBUITitle">Uploads</string>74 <string key="IBUITitle">Files</string>
74 <object class="NSCustomResource" key="IBUIImage">75 <object class="NSCustomResource" key="IBUIImage">
75 <string key="NSClassName">NSImage</string>76 <string key="NSClassName">NSImage</string>
76 <string key="NSResourceName">upload.png</string>77 <string key="NSResourceName">folder.png</string>
77 </object>78 </object>
78 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>79 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
79 </object>80 </object>
@@ -85,7 +86,7 @@
85 </object>86 </object>
86 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>87 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
87 <bool key="IBUIHorizontal">NO</bool>88 <bool key="IBUIHorizontal">NO</bool>
88 <object class="IBUINavigationBar" key="IBUINavigationBar" id="499706903">89 <object class="IBUINavigationBar" key="IBUINavigationBar" id="131246382">
89 <nil key="NSNextResponder"/>90 <nil key="NSNextResponder"/>
90 <int key="NSvFlags">256</int>91 <int key="NSvFlags">256</int>
91 <string key="NSFrameSize">{0, 0}</string>92 <string key="NSFrameSize">{0, 0}</string>
@@ -100,12 +101,12 @@
100 </object>101 </object>
101 <object class="NSMutableArray" key="IBUIViewControllers">102 <object class="NSMutableArray" key="IBUIViewControllers">
102 <bool key="EncodedWithXMLCoder">YES</bool>103 <bool key="EncodedWithXMLCoder">YES</bool>
103 <object class="IBUIViewController" id="743143347">104 <object class="IBUIViewController" id="852027692">
104 <object class="IBUINavigationItem" key="IBUINavigationItem" id="374575231">105 <object class="IBUINavigationItem" key="IBUINavigationItem" id="570921376">
105 <string key="IBUITitle">Root View Controller</string>106 <string key="IBUITitle">Root View Controller</string>
106 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>107 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
107 </object>108 </object>
108 <reference key="IBUIParentViewController" ref="941272465"/>109 <reference key="IBUIParentViewController" ref="175250829"/>
109 <object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">110 <object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">
110 <int key="IBUIInterfaceOrientation">1</int>111 <int key="IBUIInterfaceOrientation">1</int>
111 <int key="interfaceOrientation">1</int>112 <int key="interfaceOrientation">1</int>
@@ -117,12 +118,13 @@
117 </object>118 </object>
118 <object class="NSMutableArray" key="IBUIViewControllers">119 <object class="NSMutableArray" key="IBUIViewControllers">
119 <bool key="EncodedWithXMLCoder">YES</bool>120 <bool key="EncodedWithXMLCoder">YES</bool>
120 <object class="IBUINavigationController" id="175250829">121 <reference ref="175250829"/>
121 <object class="IBUITabBarItem" key="IBUITabBarItem" id="1047769425">122 <object class="IBUINavigationController" id="941272465">
122 <string key="IBUITitle">Files</string>123 <object class="IBUITabBarItem" key="IBUITabBarItem" id="463875161">
124 <string key="IBUITitle">Uploads</string>
123 <object class="NSCustomResource" key="IBUIImage">125 <object class="NSCustomResource" key="IBUIImage">
124 <string key="NSClassName">NSImage</string>126 <string key="NSClassName">NSImage</string>
125 <string key="NSResourceName">folder.png</string>127 <string key="NSResourceName">upload.png</string>
126 </object>128 </object>
127 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>129 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
128 </object>130 </object>
@@ -134,7 +136,7 @@
134 </object>136 </object>
135 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>137 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
136 <bool key="IBUIHorizontal">NO</bool>138 <bool key="IBUIHorizontal">NO</bool>
137 <object class="IBUINavigationBar" key="IBUINavigationBar" id="131246382">139 <object class="IBUINavigationBar" key="IBUINavigationBar" id="499706903">
138 <nil key="NSNextResponder"/>140 <nil key="NSNextResponder"/>
139 <int key="NSvFlags">256</int>141 <int key="NSvFlags">256</int>
140 <string key="NSFrameSize">{0, 0}</string>142 <string key="NSFrameSize">{0, 0}</string>
@@ -149,12 +151,12 @@
149 </object>151 </object>
150 <object class="NSMutableArray" key="IBUIViewControllers">152 <object class="NSMutableArray" key="IBUIViewControllers">
151 <bool key="EncodedWithXMLCoder">YES</bool>153 <bool key="EncodedWithXMLCoder">YES</bool>
152 <object class="IBUIViewController" id="852027692">154 <object class="IBUIViewController" id="743143347">
153 <object class="IBUINavigationItem" key="IBUINavigationItem" id="570921376">155 <object class="IBUINavigationItem" key="IBUINavigationItem" id="374575231">
154 <string key="IBUITitle">Root View Controller</string>156 <string key="IBUITitle">Root View Controller</string>
155 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>157 <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
156 </object>158 </object>
157 <reference key="IBUIParentViewController" ref="175250829"/>159 <reference key="IBUIParentViewController" ref="941272465"/>
158 <object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">160 <object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">
159 <int key="IBUIInterfaceOrientation">1</int>161 <int key="IBUIInterfaceOrientation">1</int>
160 <int key="interfaceOrientation">1</int>162 <int key="interfaceOrientation">1</int>
@@ -164,7 +166,6 @@
164 </object>166 </object>
165 </object>167 </object>
166 </object>168 </object>
167 <reference ref="941272465"/>
168 <object class="IBUINavigationController" id="631281359">169 <object class="IBUINavigationController" id="631281359">
169 <object class="IBUITabBarItem" key="IBUITabBarItem" id="460599548">170 <object class="IBUITabBarItem" key="IBUITabBarItem" id="460599548">
170 <string key="IBUITitle">Settings</string>171 <string key="IBUITitle">Settings</string>

Subscribers

People subscribed via source and target branches