Merge lp:~urbanape/ubuntuone-ios-files/auto-uploads-view into lp:ubuntuone-ios-files
- auto-uploads-view
- Merge into trunk
Status: | Merged |
---|---|
Merge reported by: | Zachery Bir |
Merged at revision: | not available |
Proposed branch: | lp:~urbanape/ubuntuone-ios-files/auto-uploads-view |
Merge into: | lp:ubuntuone-ios-files |
Diff against target: |
7414 lines (+5251/-436) 67 files modified
.bzrignore (+1/-0) Dependencies/RIButtonItem.h (+23/-0) Dependencies/RIButtonItem.m (+28/-0) Dependencies/Reachability/Reachability.h (+88/-0) Dependencies/Reachability/Reachability.m (+274/-0) Dependencies/TestFlightSDK/README.txt (+167/-0) Dependencies/TestFlightSDK/TestFlight.h (+44/-0) Dependencies/TestFlightSDK/release_notes.txt (+41/-0) Dependencies/UIActionSheet+Blocks.h (+16/-0) Dependencies/UIActionSheet+Blocks.m (+71/-0) Dependencies/UIAlertView+Blocks.h (+16/-0) Dependencies/UIAlertView+Blocks.m (+61/-0) Dependencies/oauthconsumer/Crypto/sha1.c (+2/-0) Dependencies/oauthconsumer/OAMutableURLRequest.m (+2/-2) Dependencies/oauthconsumer/OAToken.m (+1/-1) Dependencies/oauthconsumer/OATokenManager.m (+3/-1) Files.xcodeproj/project.pbxproj (+210/-9) Files/Entitlements.plist (+14/-0) Files/Files-Info.plist (+22/-6) Files/Files-Prefix.pch (+6/-2) Files/FilesAppDelegate.h (+5/-2) Files/FilesAppDelegate.m (+147/-68) Files/Generated/_U1Asset.h (+111/-0) Files/Generated/_U1Asset.m (+98/-0) Files/Generated/_U1FileNode.h (+13/-0) Files/Generated/_U1FileNode.m (+4/-0) Files/Generated/_U1Volume.h (+16/-1) Files/Generated/_U1Volume.m (+7/-0) Files/NSDictionary+U1Additions.h (+23/-0) Files/NSDictionary+U1Additions.m (+29/-0) Files/U1Asset.h (+5/-0) Files/U1Asset.m (+7/-0) Files/U1AssetUploadOperation.h (+32/-0) Files/U1AssetUploadOperation.m (+103/-0) Files/U1ByteSizeValueTransformer.m (+1/-1) Files/U1DataRepository.h (+5/-1) Files/U1DataRepository.m (+23/-0) Files/U1FileNode.m (+3/-5) Files/U1FilePreviewViewController.h (+2/-1) Files/U1FilePreviewViewController.m (+78/-2) Files/U1FilePreviewViewController.xib (+120/-35) Files/U1Files.xcdatamodeld/.xccurrentversion (+1/-1) Files/U1FilesClient.h (+11/-3) Files/U1FilesClient.m (+207/-45) Files/U1FilesService.h (+8/-3) Files/U1FilesService.m (+86/-7) Files/U1FolderNode.m (+1/-1) Files/U1FolderViewController.m (+44/-16) Files/U1LocalAssetsManager.h (+33/-0) Files/U1LocalAssetsManager.m (+354/-0) Files/U1LocalAssetsViewController.h (+43/-0) Files/U1LocalAssetsViewController.m (+420/-0) Files/U1LocalAssetsViewController.xib (+391/-0) Files/U1Node.m (+10/-10) Files/U1SettingsViewController.h (+38/-0) Files/U1SettingsViewController.m (+264/-0) Files/U1SettingsViewController.xib (+632/-0) Files/U1UTIMapper.h (+22/-0) Files/U1UTIMapper.m (+63/-0) Files/U1Volume.h (+19/-1) Files/U1Volume.m (+58/-1) Files/U1VolumesViewController.h (+5/-3) Files/U1VolumesViewController.m (+186/-41) Files/U1VolumesViewController.xib (+45/-33) Files/default-settings.plist (+14/-0) Files/iPhone/en.lproj/MainWindow_iPhone.xib (+340/-134) Files/uti-mappings.plist (+34/-0) |
To merge this branch: | bzr merge lp:~urbanape/ubuntuone-ios-files/auto-uploads-view |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jason Foreman (community) | Approve | ||
Review via email: mp+80647@code.launchpad.net |
Commit message
Description of the change
Big branch that magically got bigger.
This branch handles auto-uploading of the iOS camera roll.
It also splits out the management view for this auto-upload behavior from the main folder browsing view, and incorporates a Settings view (TBD).
The default (and configurable) settings we *want* are:
- Auto Upload [ Off ( On ) ]
- Wifi Only [ Off ( On ) ]
- Include Video [ ( Off ) On ]
Which we don't actually have yet.
- 94. By Zachery Bir
-
Stupid Xcode
- 95. By Zachery Bir
-
Added so our apps can share Keychain access
- 96. By Zachery Bir
-
Up the build to 15, and fix the Bundle name
- 97. By Zachery Bir
-
Fix some crasher, redo how we handle the tab bar view controllers.
- 98. By Zachery Bir
-
Change "fetchNodeWithR
esourcePath" to "fetchFolderWit hResourcePath" and add "fetchFileWithR esourcePath" since the web returns a 403 (!?) for GETs on files with "?include_ children= True" in the query string. - 99. By Zachery Bir
-
Fix a crasher.
- 100. By Zachery Bir
-
Remove the class method that returns a UINavigationCon
troller, and use the new filesClient method - 101. By Zachery Bir
-
Remove the class method that returns a UINavigationCon
troller - 102. By Zachery Bir
-
Remove the class method that returns a UINavigationCon
troller, and use the new filesClient method - 103. By Zachery Bir
-
Xcode kookiness.
- 104. By Zachery Bir
-
Handle uploads in batches of 50 assets at a time, and ditch all the debugging logging.
- 105. By Zachery Bir
-
Get rid of the commented out code.
When uploading a file, first try to fetch it. If there's something there at the same path, let's just skip it now. We can try to compare byte length later.
Properly handle the rest of the upload inside the ALAssetsLibrary assetForURL resultBlock.
- 106. By Zachery Bir
-
Added some dependency code for action sheets with blocks.
- 107. By Zachery Bir
-
Default preferences:
asked_
auto_upload_ on_first_ launch - whether we should display the alert view asking whether we should upload camera roll contents automatically (defaults to NO, obviously) auto_upload - whether we should upload camera roll contents automatically (defaults to NO)
wifi_only - whether we should upload camera roll contents over 3G (defaults to YES)
include_video - whether video files should be uploaded as well (defaults to NO)
- 108. By Zachery Bir
-
Interface layout for the settings view.
- 109. By Zachery Bir
-
Modified the Settings view to be owned by a nav controller
- 110. By Zachery Bir
-
Wire up the Settings view, and ask the user if she wants to enable automatically uploading camera roll contents.
- 111. By Zachery Bir
-
Use user preferences to determine whether we should upload the camera contents and whether we should include video
- 112. By Zachery Bir
-
Wire up the settings and make them clever enough that the wifi_only and include_video settings are disabled if auto_upload is disabled in the first place.
- 113. By Zachery Bir
-
New files.
- 114. By Zachery Bir
-
Write out preferences when we aren't the foreground app.
- 115. By Zachery Bir
-
Subscribe to user defaults changing. If we turn off auto_upload, suspend the queue. If it is turned on subsequently, resume the queue, and re-walk the library.
Also, avoid re-adding an operation to the queue, if the resource path is already in teh queue.
- 116. By Zachery Bir
-
Release mah bits.
- 117. By Zachery Bir
-
Merged Jason's touchup branch
- 118. By Zachery Bir
-
Merged Jason's account settings branch
- 119. By Zachery Bir
-
Merged Jason's preview additions branch
- 120. By Zachery Bir
-
Merged Jason's reachability branch
- 121. By Zachery Bir
-
Upped the build number to 16
- 122. By Zachery Bir
-
Updated the copyright headers
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2011-07-18 16:25:02 +0000 |
3 | +++ .bzrignore 2011-11-01 14:25:30 +0000 |
4 | @@ -5,3 +5,4 @@ |
5 | Files.xcodeproj/*.mode1v3 |
6 | Files.xcodeproj/xcuserdata |
7 | Files.xcodeproj/project.xcworkspace/ |
8 | +U1TestFlightTeamToken.txt |
9 | |
10 | === added file 'Assets/218-trash2.png' |
11 | Binary files Assets/218-trash2.png 1970-01-01 00:00:00 +0000 and Assets/218-trash2.png 2011-11-01 14:25:30 +0000 differ |
12 | === added file 'Assets/218-trash2@2x.png' |
13 | Binary files Assets/218-trash2@2x.png 1970-01-01 00:00:00 +0000 and Assets/218-trash2@2x.png 2011-11-01 14:25:30 +0000 differ |
14 | === added file 'Assets/progress_view_background.png' |
15 | Binary files Assets/progress_view_background.png 1970-01-01 00:00:00 +0000 and Assets/progress_view_background.png 2011-11-01 14:25:30 +0000 differ |
16 | === added file 'Assets/progress_view_background@2x.png' |
17 | Binary files Assets/progress_view_background@2x.png 1970-01-01 00:00:00 +0000 and Assets/progress_view_background@2x.png 2011-11-01 14:25:30 +0000 differ |
18 | === added file 'Assets/settings.png' |
19 | Binary files Assets/settings.png 1970-01-01 00:00:00 +0000 and Assets/settings.png 2011-11-01 14:25:30 +0000 differ |
20 | === added file 'Assets/settings@2x.png' |
21 | Binary files Assets/settings@2x.png 1970-01-01 00:00:00 +0000 and Assets/settings@2x.png 2011-11-01 14:25:30 +0000 differ |
22 | === added file 'Dependencies/RIButtonItem.h' |
23 | --- Dependencies/RIButtonItem.h 1970-01-01 00:00:00 +0000 |
24 | +++ Dependencies/RIButtonItem.h 2011-11-01 14:25:30 +0000 |
25 | @@ -0,0 +1,23 @@ |
26 | +// |
27 | +// RIButtonItem.h |
28 | +// Shibui |
29 | +// |
30 | +// Created by Jiva DeVoe on 1/12/11. |
31 | +// Copyright 2011 Random Ideas, LLC. All rights reserved. |
32 | +// |
33 | + |
34 | +#import <Foundation/Foundation.h> |
35 | + |
36 | +typedef void (^RISimpleAction)(); |
37 | + |
38 | +@interface RIButtonItem : NSObject |
39 | +{ |
40 | + NSString *label; |
41 | + RISimpleAction action; |
42 | +} |
43 | +@property (retain, nonatomic) NSString *label; |
44 | +@property (copy, nonatomic) RISimpleAction action; |
45 | ++(id)item; |
46 | ++(id)itemWithLabel:(NSString *)inLabel; |
47 | +@end |
48 | + |
49 | |
50 | === added file 'Dependencies/RIButtonItem.m' |
51 | --- Dependencies/RIButtonItem.m 1970-01-01 00:00:00 +0000 |
52 | +++ Dependencies/RIButtonItem.m 2011-11-01 14:25:30 +0000 |
53 | @@ -0,0 +1,28 @@ |
54 | +// |
55 | +// RIButtonItem.m |
56 | +// Shibui |
57 | +// |
58 | +// Created by Jiva DeVoe on 1/12/11. |
59 | +// Copyright 2011 Random Ideas, LLC. All rights reserved. |
60 | +// |
61 | + |
62 | +#import "RIButtonItem.h" |
63 | + |
64 | +@implementation RIButtonItem |
65 | +@synthesize label; |
66 | +@synthesize action; |
67 | + |
68 | ++(id)item |
69 | +{ |
70 | + return [[self new] autorelease]; |
71 | +} |
72 | + |
73 | ++(id)itemWithLabel:(NSString *)inLabel |
74 | +{ |
75 | + id newItem = [self item]; |
76 | + [newItem setLabel:inLabel]; |
77 | + return newItem; |
78 | +} |
79 | + |
80 | +@end |
81 | + |
82 | |
83 | === added directory 'Dependencies/Reachability' |
84 | === added file 'Dependencies/Reachability/Reachability.h' |
85 | --- Dependencies/Reachability/Reachability.h 1970-01-01 00:00:00 +0000 |
86 | +++ Dependencies/Reachability/Reachability.h 2011-11-01 14:25:30 +0000 |
87 | @@ -0,0 +1,88 @@ |
88 | +/* |
89 | + |
90 | + File: Reachability.h |
91 | + Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. |
92 | + |
93 | + Version: 2.0 |
94 | + |
95 | + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. |
96 | + ("Apple") in consideration of your agreement to the following terms, and your |
97 | + use, installation, modification or redistribution of this Apple software |
98 | + constitutes acceptance of these terms. If you do not agree with these terms, |
99 | + please do not use, install, modify or redistribute this Apple software. |
100 | + |
101 | + In consideration of your agreement to abide by the following terms, and subject |
102 | + to these terms, Apple grants you a personal, non-exclusive license, under |
103 | + Apple's copyrights in this original Apple software (the "Apple Software"), to |
104 | + use, reproduce, modify and redistribute the Apple Software, with or without |
105 | + modifications, in source and/or binary forms; provided that if you redistribute |
106 | + the Apple Software in its entirety and without modifications, you must retain |
107 | + this notice and the following text and disclaimers in all such redistributions |
108 | + of the Apple Software. |
109 | + Neither the name, trademarks, service marks or logos of Apple Inc. may be used |
110 | + to endorse or promote products derived from the Apple Software without specific |
111 | + prior written permission from Apple. Except as expressly stated in this notice, |
112 | + no other rights or licenses, express or implied, are granted by Apple herein, |
113 | + including but not limited to any patent rights that may be infringed by your |
114 | + derivative works or by other works in which the Apple Software may be |
115 | + incorporated. |
116 | + |
117 | + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
118 | + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
119 | + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
120 | + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
121 | + COMBINATION WITH YOUR PRODUCTS. |
122 | + |
123 | + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
124 | + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
125 | + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
126 | + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR |
127 | + DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF |
128 | + CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF |
129 | + APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
130 | + |
131 | + Copyright (C) 2009 Apple Inc. All Rights Reserved. |
132 | + |
133 | +*/ |
134 | + |
135 | + |
136 | +#import <Foundation/Foundation.h> |
137 | +#import <SystemConfiguration/SystemConfiguration.h> |
138 | + |
139 | +typedef enum { |
140 | + NotReachable = 0, |
141 | + ReachableViaWiFi, |
142 | + ReachableViaWWAN |
143 | +} NetworkStatus; |
144 | +#define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification" |
145 | + |
146 | +@interface Reachability: NSObject |
147 | +{ |
148 | + BOOL localWiFiRef; |
149 | + SCNetworkReachabilityRef reachabilityRef; |
150 | +} |
151 | + |
152 | +//reachabilityWithHostName- Use to check the reachability of a particular host name. |
153 | ++ (Reachability*) reachabilityWithHostName: (NSString*) hostName; |
154 | + |
155 | +//reachabilityWithAddress- Use to check the reachability of a particular IP address. |
156 | +//+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; |
157 | + |
158 | +//reachabilityForInternetConnection- checks whether the default route is available. |
159 | +// Should be used by applications that do not connect to a particular host |
160 | ++ (Reachability*) reachabilityForInternetConnection; |
161 | + |
162 | +//reachabilityForLocalWiFi- checks whether a local wifi connection is available. |
163 | ++ (Reachability*) reachabilityForLocalWiFi; |
164 | + |
165 | +//Start listening for reachability notifications on the current run loop |
166 | +- (BOOL) startNotifer; |
167 | +- (void) stopNotifer; |
168 | + |
169 | +- (NetworkStatus) currentReachabilityStatus; |
170 | +//WWAN may be available, but not active until a connection has been established. |
171 | +//WiFi may require a connection for VPN on Demand. |
172 | +- (BOOL) connectionRequired; |
173 | +@end |
174 | + |
175 | + |
176 | |
177 | === added file 'Dependencies/Reachability/Reachability.m' |
178 | --- Dependencies/Reachability/Reachability.m 1970-01-01 00:00:00 +0000 |
179 | +++ Dependencies/Reachability/Reachability.m 2011-11-01 14:25:30 +0000 |
180 | @@ -0,0 +1,274 @@ |
181 | +/* |
182 | + |
183 | + File: Reachability.m |
184 | + Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. |
185 | + |
186 | + Version: 2.0 |
187 | + |
188 | + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. |
189 | + ("Apple") in consideration of your agreement to the following terms, and your |
190 | + use, installation, modification or redistribution of this Apple software |
191 | + constitutes acceptance of these terms. If you do not agree with these terms, |
192 | + please do not use, install, modify or redistribute this Apple software. |
193 | + |
194 | + In consideration of your agreement to abide by the following terms, and subject |
195 | + to these terms, Apple grants you a personal, non-exclusive license, under |
196 | + Apple's copyrights in this original Apple software (the "Apple Software"), to |
197 | + use, reproduce, modify and redistribute the Apple Software, with or without |
198 | + modifications, in source and/or binary forms; provided that if you redistribute |
199 | + the Apple Software in its entirety and without modifications, you must retain |
200 | + this notice and the following text and disclaimers in all such redistributions |
201 | + of the Apple Software. |
202 | + Neither the name, trademarks, service marks or logos of Apple Inc. may be used |
203 | + to endorse or promote products derived from the Apple Software without specific |
204 | + prior written permission from Apple. Except as expressly stated in this notice, |
205 | + no other rights or licenses, express or implied, are granted by Apple herein, |
206 | + including but not limited to any patent rights that may be infringed by your |
207 | + derivative works or by other works in which the Apple Software may be |
208 | + incorporated. |
209 | + |
210 | + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
211 | + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
212 | + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
213 | + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
214 | + COMBINATION WITH YOUR PRODUCTS. |
215 | + |
216 | + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
217 | + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
218 | + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
219 | + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR |
220 | + DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF |
221 | + CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF |
222 | + APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
223 | + |
224 | + Copyright (C) 2009 Apple Inc. All Rights Reserved. |
225 | + |
226 | +*/ |
227 | + |
228 | +#import <sys/socket.h> |
229 | +#import <netinet/in.h> |
230 | +#import <netinet6/in6.h> |
231 | +#import <arpa/inet.h> |
232 | +#import <ifaddrs.h> |
233 | +#import <netdb.h> |
234 | + |
235 | +#import <CoreFoundation/CoreFoundation.h> |
236 | + |
237 | +#import "Reachability.h" |
238 | + |
239 | +#define kShouldPrintReachabilityFlags 0 |
240 | + |
241 | +static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment) |
242 | +{ |
243 | +#if kShouldPrintReachabilityFlags |
244 | + |
245 | + NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n", |
246 | + (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', |
247 | + (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', |
248 | + |
249 | + (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', |
250 | + (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', |
251 | + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', |
252 | + (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', |
253 | + (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', |
254 | + (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', |
255 | + (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-', |
256 | + comment |
257 | + ); |
258 | +#endif |
259 | +} |
260 | + |
261 | + |
262 | +@implementation Reachability |
263 | +static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) |
264 | +{ |
265 | + #pragma unused (target, flags) |
266 | + NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback"); |
267 | + NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback"); |
268 | + |
269 | + //We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively |
270 | + // in case someon uses the Reachablity object in a different thread. |
271 | + NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init]; |
272 | + |
273 | + Reachability* noteObject = (Reachability*) info; |
274 | + // Post a notification to notify the client that the network reachability changed. |
275 | + [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject]; |
276 | + |
277 | + [myPool release]; |
278 | +} |
279 | + |
280 | +- (BOOL) startNotifer |
281 | +{ |
282 | + BOOL retVal = NO; |
283 | + SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL}; |
284 | + if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)) |
285 | + { |
286 | + if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) |
287 | + { |
288 | + retVal = YES; |
289 | + } |
290 | + } |
291 | + return retVal; |
292 | +} |
293 | + |
294 | +- (void) stopNotifer |
295 | +{ |
296 | + if(reachabilityRef!= NULL) |
297 | + { |
298 | + SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); |
299 | + } |
300 | +} |
301 | + |
302 | +- (void) dealloc |
303 | +{ |
304 | + [self stopNotifer]; |
305 | + if(reachabilityRef!= NULL) |
306 | + { |
307 | + CFRelease(reachabilityRef); |
308 | + } |
309 | + [super dealloc]; |
310 | +} |
311 | + |
312 | ++ (Reachability*) reachabilityWithHostName: (NSString*) hostName; |
313 | +{ |
314 | + Reachability* retVal = NULL; |
315 | + SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]); |
316 | + if(reachability!= NULL) |
317 | + { |
318 | + retVal= [[[self alloc] init] autorelease]; |
319 | + if(retVal!= NULL) |
320 | + { |
321 | + retVal->reachabilityRef = reachability; |
322 | + retVal->localWiFiRef = NO; |
323 | + } |
324 | + } |
325 | + return retVal; |
326 | +} |
327 | + |
328 | ++ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; |
329 | +{ |
330 | + SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); |
331 | + Reachability* retVal = NULL; |
332 | + if(reachability!= NULL) |
333 | + { |
334 | + retVal= [[[self alloc] init] autorelease]; |
335 | + if(retVal!= NULL) |
336 | + { |
337 | + retVal->reachabilityRef = reachability; |
338 | + retVal->localWiFiRef = NO; |
339 | + } |
340 | + } |
341 | + return retVal; |
342 | +} |
343 | + |
344 | ++ (Reachability*) reachabilityForInternetConnection; |
345 | +{ |
346 | + struct sockaddr_in zeroAddress; |
347 | + bzero(&zeroAddress, sizeof(zeroAddress)); |
348 | + zeroAddress.sin_len = sizeof(zeroAddress); |
349 | + zeroAddress.sin_family = AF_INET; |
350 | + return [self reachabilityWithAddress: &zeroAddress]; |
351 | +} |
352 | + |
353 | ++ (Reachability*) reachabilityForLocalWiFi; |
354 | +{ |
355 | + //[super init]; |
356 | + struct sockaddr_in localWifiAddress; |
357 | + bzero(&localWifiAddress, sizeof(localWifiAddress)); |
358 | + localWifiAddress.sin_len = sizeof(localWifiAddress); |
359 | + localWifiAddress.sin_family = AF_INET; |
360 | + // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0 |
361 | + localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); |
362 | + Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress]; |
363 | + if(retVal!= NULL) |
364 | + { |
365 | + retVal->localWiFiRef = YES; |
366 | + } |
367 | + return retVal; |
368 | +} |
369 | + |
370 | +#pragma mark Network Flag Handling |
371 | + |
372 | +- (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags |
373 | +{ |
374 | + PrintReachabilityFlags(flags, "localWiFiStatusForFlags"); |
375 | + |
376 | + BOOL retVal = NotReachable; |
377 | + if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect)) |
378 | + { |
379 | + retVal = ReachableViaWiFi; |
380 | + } |
381 | + return retVal; |
382 | +} |
383 | + |
384 | +- (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags |
385 | +{ |
386 | + PrintReachabilityFlags(flags, "networkStatusForFlags"); |
387 | + if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) |
388 | + { |
389 | + // if target host is not reachable |
390 | + return NotReachable; |
391 | + } |
392 | + |
393 | + BOOL retVal = NotReachable; |
394 | + |
395 | + if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) |
396 | + { |
397 | + // if target host is reachable and no connection is required |
398 | + // then we'll assume (for now) that your on Wi-Fi |
399 | + retVal = ReachableViaWiFi; |
400 | + } |
401 | + |
402 | + |
403 | + if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || |
404 | + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) |
405 | + { |
406 | + // ... and the connection is on-demand (or on-traffic) if the |
407 | + // calling application is using the CFSocketStream or higher APIs |
408 | + |
409 | + if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) |
410 | + { |
411 | + // ... and no [user] intervention is needed |
412 | + retVal = ReachableViaWiFi; |
413 | + } |
414 | + } |
415 | + |
416 | + if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) |
417 | + { |
418 | + // ... but WWAN connections are OK if the calling application |
419 | + // is using the CFNetwork (CFSocketStream?) APIs. |
420 | + retVal = ReachableViaWWAN; |
421 | + } |
422 | + return retVal; |
423 | +} |
424 | + |
425 | +- (BOOL) connectionRequired; |
426 | +{ |
427 | + NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef"); |
428 | + SCNetworkReachabilityFlags flags; |
429 | + if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) |
430 | + { |
431 | + return (flags & kSCNetworkReachabilityFlagsConnectionRequired); |
432 | + } |
433 | + return NO; |
434 | +} |
435 | + |
436 | +- (NetworkStatus) currentReachabilityStatus |
437 | +{ |
438 | + NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef"); |
439 | + NetworkStatus retVal = NotReachable; |
440 | + SCNetworkReachabilityFlags flags; |
441 | + if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) |
442 | + { |
443 | + if(localWiFiRef) |
444 | + { |
445 | + retVal = [self localWiFiStatusForFlags: flags]; |
446 | + } |
447 | + else |
448 | + { |
449 | + retVal = [self networkStatusForFlags: flags]; |
450 | + } |
451 | + } |
452 | + return retVal; |
453 | +} |
454 | +@end |
455 | |
456 | === added directory 'Dependencies/TestFlightSDK' |
457 | === added file 'Dependencies/TestFlightSDK/README.txt' |
458 | --- Dependencies/TestFlightSDK/README.txt 1970-01-01 00:00:00 +0000 |
459 | +++ Dependencies/TestFlightSDK/README.txt 2011-11-01 14:25:30 +0000 |
460 | @@ -0,0 +1,167 @@ |
461 | +Thanks for downloading the TestFlight SDK 0.7! |
462 | + |
463 | +This document is also available on the web at https://www.testflightapp.com/sdk/doc |
464 | + |
465 | +1. Why use the TestFlight SDK? |
466 | +2. Considerations |
467 | +3. How do I integrate the SDK into my project? |
468 | +4. Using the Checkpoint API |
469 | +5. Using the Feedback API |
470 | +6. Upload your build |
471 | +7. Questions API |
472 | +8. View your results |
473 | +9. Advanced Exception Handling |
474 | + |
475 | +START |
476 | + |
477 | + |
478 | +1. Why use the TestFlight SDK? |
479 | + |
480 | +The TestFlight SDK allows you to track how beta testers are testing your application. Out of the box we track simple usage information, such as which tester is using your application, their device model/OS, how long they used the application, logs of their test session, and automatic recording of any crashes they encounter. |
481 | + |
482 | +To get the most out of the SDK we have provided the Checkpoint API. |
483 | + |
484 | +The Checkpoint API is used to help you track exactly how your testers are using your application. Curious about which users passed level 5 in your game, or posted their high score to Twitter, or found that obscure feature? With a single line of code you can finally gather all this information. Wondering how many times your app has crashed? Wondering who your power testers are? We've got you covered. See more information on the Checkpoint API in section 4. |
485 | + |
486 | +Alongside the Checkpoint API is the Questions interface. The Questions interface is managed on a per build basis on the TestFlight website. Find out more about the Questions Interface in section 6. |
487 | + |
488 | +2. Considerations |
489 | + |
490 | + |
491 | +Information gathered by the SDK is sent to the website in real time. When an application is put into the background (iOS 4.x) or terminated (iOS 3.x) we try to send the finalizing information for the session during the time allowed for finalizing the application. Should all of the data not get sent the remaining data will be sent the next time the application is launched. As such, to get the most out of the SDK we recommend your application support iOS 4.0 and higher. |
492 | + |
493 | +This SDK can be run from both the iPhone Simulator and Device and has been tested using Xcode 4.0. |
494 | + |
495 | +3. How do I integrate the SDK into my project? |
496 | + |
497 | + |
498 | +1. Add the files to your project: Project -> Add to Project -> TestFlightSDK |
499 | + |
500 | + 1. Copy items into destination folder (if needed): Checked |
501 | + 2. Reference Type: Default |
502 | + 3. Recursively create groups for added folders |
503 | + |
504 | +2. Verify that libTestFlight.a has been added to the Link Binary With Libraries Build Phase for the targets you want to use the SDK with |
505 | + |
506 | + 1. Select your Project in the Project Navigator |
507 | + 2. Select the target you want to enable the SDK for |
508 | + 3. Select the Build Phases tab |
509 | + 4. Open the Link Binary With Libraries Phase |
510 | + 5. If libTestFlight.a is not listed, drag and drop the library from your Project Navigator to the Link Binary With Libraries area |
511 | + 6. Repeat Steps 2 - 5 until all targets you want to use the SDK with have the SDK linked |
512 | + |
513 | +3. In your Application Delegate: |
514 | + |
515 | + 1. Import TestFlight: `#import "TestFlight.h"` |
516 | + NOTE: If you do not want to import TestFlight.h in every file you may add the above line into you pre-compiled header (`<projectname>_Prefix.pch`) file inside of the |
517 | + |
518 | + #ifdef __OBJC__ section. |
519 | + This will give you access to the SDK across all files. |
520 | + |
521 | + 2. Get your Team Token which you can find at [http://testflightapp.com/dashboard/team/](http://testflightapp.com/dashboard/team/) select the team you are using from the team selection drop down list on the top of the page and then select edit. |
522 | + |
523 | + |
524 | + 3. Launch TestFlight with your Team Token |
525 | + |
526 | + -(BOOL)application:(UIApplication *)application |
527 | + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { |
528 | + // start of your application:didFinishLaunchingWithOptions |
529 | + // ... |
530 | + [TestFlight takeOff:@"Insert your Team Token here"]; |
531 | + // The rest of your application:didFinishLaunchingWithOptions method |
532 | + // ... |
533 | + } |
534 | + |
535 | + 4. To report crashes to you we install our own uncaught exception handler. If you are not currently using an exception handler of your own then all you need to do is go to the next step. If you currently use an Exception Handler, or you use another framework that does please go to the section on advanced exception handling. |
536 | + |
537 | +4. To enable the best crash reporting possible we recommend setting the following project build settings in Xcode to NO for all targets that you want to have live crash reporting for You can find build settings by opening the Project Navigator (default command+1 or command+shift+j) then clicking on the project you are configuring (usually the first selection in the list). From there you can choose to either change the global project settings or settings on an individual project basis. All settings below are in the Deployment Section. |
538 | + |
539 | + 1. Deployment Post Processing |
540 | + 2. Strip Debug Symbols During Copy |
541 | + 3. Strip Linked Product |
542 | + |
543 | +4. Use the Checkpoint API to create important checkpoints throughout your application. |
544 | + |
545 | +When a tester passes a level, or adds a new todo item, you can pass a checkpoint. The checkpoint progress is used to provide insight into how your testers are testing your apps. The passed checkpoints are also attached to crashes, which can help when creating steps to replicate. |
546 | + |
547 | +`[TestFlight passCheckpoint:@"CHECKPOINT_NAME"];` |
548 | +Use `passCheckpoint:` to track when a user performs certain tasks in your application. This can be useful for making sure testers are hitting all parts of your application, as well as tracking which testers are being thorough. |
549 | + |
550 | +5. Using the Feedback API |
551 | + |
552 | +To launch unguided feedback call the `openFeedbackView` method. We recommend that you call this from a GUI element. |
553 | + |
554 | + -(IBAction)launchFeedback { |
555 | + [TestFlight openFeedbackView]; |
556 | + } |
557 | + |
558 | +Once users have submitted feedback from inside of the application you can view it in the feedback area of your build page. |
559 | + |
560 | +6. Upload your build. |
561 | + |
562 | +After you have integrated the SDK into your application you need to upload your build to TestFlight. You can upload from your dashboard or or using the Upload API, full documentation at <https://testflightapp.com/api/doc/> |
563 | + |
564 | +7. Add Questions to Checkpoints |
565 | + |
566 | +In order to ask a question, you'll need to associate it with a checkpoint. Make sure your checkpoints are initialized by running your app and hitting them all yourself before you start adding questions. |
567 | + |
568 | +There are three question types available: Yes/No, Multiple Choice, and Long Answer. |
569 | + |
570 | +To create questions, visit your builds Questions page and click on 'Add Question'. If you choose Multiple Choice, you'll need to enter a list of possible answers for your testers to choose from — otherwise, you'll only need to enter your question's, well, question. If your build has no questions, you can also choose to migrate questions from another build (because seriously — who wants to do all that typing again)? |
571 | + |
572 | +After restarting your application on an approved device, when you pass the checkpoint associated with your questions a Test Flight modal question form will appear on the screen asking the beta tester to answer your question. |
573 | + |
574 | +After you upload a new build to TestFlight you will need to associate questions once again. However if your checkpoints and questions have remained the same you can choose "copy questions from an older build" and choose which build to copy the questions from. |
575 | + |
576 | +8. View your results. |
577 | + |
578 | +As testers install your build and start to test it you will see their session data on the web on the build report page for the build you've uploaded. |
579 | + |
580 | +9. Advanced Exception Handling |
581 | + |
582 | +An uncaught exception means that your application is in an unknown state and there is not much that you can do but try and exit gracefully. Our SDK does its best to get the data we collect in this situation to you while it is crashing, but it is designed in such a way that the important act of saving the data occurs in as safe way a way as possible before trying to send anything. If you do use uncaught exception or signal handlers install your handlers before calling `takeOff`. Our SDK will then call your handler while ours is running. For example: |
583 | + |
584 | + /* |
585 | + My Apps Custom uncaught exception catcher, we do special stuff here, and TestFlight takes care of the rest |
586 | + **/ |
587 | + void HandleExceptions(NSException *exception) { |
588 | + NSLog(@"This is where we save the application data during a exception"); |
589 | + // Save application data on crash |
590 | + } |
591 | + /* |
592 | + My Apps Custom signal catcher, we do special stuff here, and TestFlight takes care of the rest |
593 | + **/ |
594 | + void SignalHandler(int sig) { |
595 | + NSLog(@"This is where we save the application data during a signal"); |
596 | + // Save application data on crash |
597 | + } |
598 | + |
599 | + -(BOOL)application:(UIApplication *)application |
600 | + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { |
601 | + // installs HandleExceptions as the Uncaught Exception Handler |
602 | + NSSetUncaughtExceptionHandler(&HandleExceptions); |
603 | + // create the signal action structure |
604 | + struct sigaction newSignalAction; |
605 | + // initialize the signal action structure |
606 | + memset(&newSignalAction, 0, sizeof(newSignalAction)); |
607 | + // set SignalHandler as the handler in the signal action structure |
608 | + newSignalAction.sa_handler = &SignalHandler; |
609 | + // set SignalHandler as the handlers for SIGABRT, SIGILL and SIGBUS |
610 | + sigaction(SIGABRT, &newSignalAction, NULL); |
611 | + sigaction(SIGILL, &newSignalAction, NULL); |
612 | + sigaction(SIGBUS, &newSignalAction, NULL); |
613 | + // Call takeOff after install your own unhandled exception and signal handlers |
614 | + [TestFlight takeOff:@"Insert your Team Token here"]; |
615 | + // continue with your application initialization |
616 | + } |
617 | + |
618 | +You do not need to add the above code if your application does not use exception handling already. |
619 | + |
620 | +END |
621 | + |
622 | +Please contact us if you have any questions. |
623 | + |
624 | +The TestFlight Team |
625 | + |
626 | +w. http://www.testflightapp.com |
627 | +e. beta@testflightapp.com |
628 | |
629 | === added file 'Dependencies/TestFlightSDK/TestFlight.h' |
630 | --- Dependencies/TestFlightSDK/TestFlight.h 1970-01-01 00:00:00 +0000 |
631 | +++ Dependencies/TestFlightSDK/TestFlight.h 2011-11-01 14:25:30 +0000 |
632 | @@ -0,0 +1,44 @@ |
633 | +// |
634 | +// TestFlight.h |
635 | +// libTestFlight |
636 | +// |
637 | +// Created by Jonathan Janzen on 06/11/11. |
638 | +// Copyright 2011 TestFlight. All rights reserved. |
639 | + |
640 | +#import <Foundation/Foundation.h> |
641 | +#define TESTFLIGHT_SDK_VERSION @"0.7.2" |
642 | + |
643 | +@interface TestFlight : NSObject { |
644 | + |
645 | +} |
646 | + |
647 | +/** |
648 | + Add custom environment information |
649 | + If you want to track a user name from your application you can add it here |
650 | + */ |
651 | ++ (void)addCustomEnvironmentInformation:(NSString *)information forKey:(NSString*)key; |
652 | + |
653 | +/** |
654 | + Starts a TestFlight session |
655 | + */ |
656 | ++ (void)takeOff:(NSString *)teamToken; |
657 | + |
658 | +/** |
659 | + Sets custom options |
660 | + Option Accepted Values Description |
661 | + reinstallCrashHandlers [NSNumber numberWithBool:YES] Reinstalls crash handlers, to be used if a third party |
662 | + library installs crash handlers overtop of the TestFlight Crash Handlers |
663 | + */ |
664 | ++ (void)setOptions:(NSDictionary*)options; |
665 | + |
666 | +/** |
667 | + Track when a user has passed a checkpoint after the flight has taken off. Eg. passed level 1, posted high score |
668 | + */ |
669 | ++ (void)passCheckpoint:(NSString *)checkpointName; |
670 | + |
671 | +/** |
672 | + Opens a feeback window that is not attached to a checkpoint |
673 | + */ |
674 | ++ (void)openFeedbackView; |
675 | + |
676 | +@end |
677 | |
678 | === added file 'Dependencies/TestFlightSDK/release_notes.txt' |
679 | --- Dependencies/TestFlightSDK/release_notes.txt 1970-01-01 00:00:00 +0000 |
680 | +++ Dependencies/TestFlightSDK/release_notes.txt 2011-11-01 14:25:30 +0000 |
681 | @@ -0,0 +1,41 @@ |
682 | +0.7.2 - September 29, 2011 |
683 | +Changed TESTFLIGHT_SDK_VERSION string to be an NSString |
684 | +Fixed an issue where exiting an application while the SDK is active caused modal views to be dismissed |
685 | +0.7.1 - September 22, 2011 |
686 | +Internal release |
687 | +Refactoring |
688 | +0.7 - September 21, 2011 |
689 | +Moved TestFlight images and data to the Library/Caches folder |
690 | +Resolved an issue where sometimes the rootViewController could not be found and feedback, questions and upgrade views would not be displayed |
691 | +In application upgrade changed to allow skipping until the next version is installed and allows upgrades to be forced |
692 | +Fixed a memory leak when launching questions |
693 | +0.6 - September 2, 2011 |
694 | +Renamed base64_encode to testflight_base64_encode to remove a conflict with other third party libraries |
695 | +Added ability to reinstall crash handlers when they are overwritten using the setOptions API |
696 | +Fixed an issue where crash reports might not get sent under certain circumstances |
697 | +Fixed a deadlock when the application is put in the background and then resumed before all information can be sent |
698 | +Fixed an issue when attempting to un-install all signal handlers during a signal |
699 | +Added support for landscape mode on the iPad to the Questions and Feedback views |
700 | +Crash reporting now works in versions of Xcode earlier than 4.2 |
701 | +Fixed a memory leak during handshake |
702 | +0.5 - August 19, 2011 |
703 | +Feedback that is not attached to a checkpoint [TestFlight openFeedbackView] |
704 | +Usability changes to question views |
705 | +Removed pause and resume sessions, replaced with sessions being stopped and started |
706 | +Added text auto correction to the Long Answer question type |
707 | +Crash reports now send on crash instead of next launch |
708 | +0.4 - August 15, 2011 |
709 | +In Application Feedback with Questions |
710 | +In application updates |
711 | +Custom Environment Information added |
712 | +Networking stack reimplementation |
713 | +Exception handling fixes |
714 | +0.3 - June 15, 2011 |
715 | +Removed all mention of JSONKit from the README |
716 | +Added support for using both the Bundle Version and the Bundle Short Version string |
717 | +0.2 - June 14, 2011 |
718 | +Removed all categories this allows users to use the SDK without having to set -ObjC and -load_all |
719 | +Prefixed JSONKit for use in TestFlight to remove reported issues where some users were already using JSONKit |
720 | +Added support for armv6 again |
721 | +0.1 - June 11, 2011 |
722 | +Initial Version |
723 | \ No newline at end of file |
724 | |
725 | === added file 'Dependencies/UIActionSheet+Blocks.h' |
726 | --- Dependencies/UIActionSheet+Blocks.h 1970-01-01 00:00:00 +0000 |
727 | +++ Dependencies/UIActionSheet+Blocks.h 2011-11-01 14:25:30 +0000 |
728 | @@ -0,0 +1,16 @@ |
729 | +// |
730 | +// UIActionSheet+Blocks.h |
731 | +// Shibui |
732 | +// |
733 | +// Created by Jiva DeVoe on 1/5/11. |
734 | +// Copyright 2011 Random Ideas, LLC. All rights reserved. |
735 | +// |
736 | + |
737 | +#import <Foundation/Foundation.h> |
738 | +#import "RIButtonItem.h" |
739 | + |
740 | +@interface UIActionSheet (Blocks) <UIActionSheetDelegate> |
741 | + |
742 | +-(id)initWithTitle:(NSString *)inTitle cancelButtonItem:(RIButtonItem *)inCancelButtonItem destructiveButtonItem:(RIButtonItem *)inDestructiveItem otherButtonItems:(RIButtonItem *)inOtherButtonItems, ... NS_REQUIRES_NIL_TERMINATION; |
743 | + |
744 | +@end |
745 | |
746 | === added file 'Dependencies/UIActionSheet+Blocks.m' |
747 | --- Dependencies/UIActionSheet+Blocks.m 1970-01-01 00:00:00 +0000 |
748 | +++ Dependencies/UIActionSheet+Blocks.m 2011-11-01 14:25:30 +0000 |
749 | @@ -0,0 +1,71 @@ |
750 | +// |
751 | +// UIActionSheet+Blocks.m |
752 | +// Shibui |
753 | +// |
754 | +// Created by Jiva DeVoe on 1/5/11. |
755 | +// Copyright 2011 Random Ideas, LLC. All rights reserved. |
756 | +// |
757 | + |
758 | +#import "UIActionSheet+Blocks.h" |
759 | +#import <objc/runtime.h> |
760 | + |
761 | +static NSString *RI_BUTTON_ASS_KEY = @"com.random-ideas.BUTTONS"; |
762 | + |
763 | +@implementation UIActionSheet (Blocks) |
764 | + |
765 | +-(id)initWithTitle:(NSString *)inTitle cancelButtonItem:(RIButtonItem *)inCancelButtonItem destructiveButtonItem:(RIButtonItem *)inDestructiveItem otherButtonItems:(RIButtonItem *)inOtherButtonItems, ... |
766 | +{ |
767 | + if((self = [self initWithTitle:inTitle delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil])) |
768 | + { |
769 | + NSMutableArray *buttonsArray = [NSMutableArray array]; |
770 | + |
771 | + RIButtonItem *eachItem; |
772 | + va_list argumentList; |
773 | + if (inOtherButtonItems) |
774 | + { |
775 | + [buttonsArray addObject: inOtherButtonItems]; |
776 | + va_start(argumentList, inOtherButtonItems); |
777 | + while((eachItem = va_arg(argumentList, RIButtonItem *))) |
778 | + { |
779 | + [buttonsArray addObject: eachItem]; |
780 | + } |
781 | + va_end(argumentList); |
782 | + } |
783 | + |
784 | + for(RIButtonItem *item in buttonsArray) |
785 | + { |
786 | + [self addButtonWithTitle:item.label]; |
787 | + } |
788 | + |
789 | + if(inDestructiveItem) |
790 | + { |
791 | + [buttonsArray addObject:inDestructiveItem]; |
792 | + NSInteger destIndex = [self addButtonWithTitle:inDestructiveItem.label]; |
793 | + [self setDestructiveButtonIndex:destIndex]; |
794 | + } |
795 | + if(inCancelButtonItem) |
796 | + { |
797 | + [buttonsArray addObject:inCancelButtonItem]; |
798 | + NSInteger cancelIndex = [self addButtonWithTitle:inCancelButtonItem.label]; |
799 | + [self setCancelButtonIndex:cancelIndex]; |
800 | + } |
801 | + |
802 | + objc_setAssociatedObject(self, RI_BUTTON_ASS_KEY, buttonsArray, OBJC_ASSOCIATION_RETAIN_NONATOMIC); |
803 | + |
804 | + [self retain]; // keep yourself around! |
805 | + } |
806 | + return self; |
807 | +} |
808 | + |
809 | +- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex |
810 | +{ |
811 | + NSArray *buttonsArray = objc_getAssociatedObject(self, RI_BUTTON_ASS_KEY); |
812 | + RIButtonItem *item = [buttonsArray objectAtIndex:buttonIndex]; |
813 | + if(item.action) |
814 | + item.action(); |
815 | + objc_setAssociatedObject(self, RI_BUTTON_ASS_KEY, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); |
816 | + [self release]; // and release yourself! |
817 | +} |
818 | + |
819 | + |
820 | +@end |
821 | |
822 | === added file 'Dependencies/UIAlertView+Blocks.h' |
823 | --- Dependencies/UIAlertView+Blocks.h 1970-01-01 00:00:00 +0000 |
824 | +++ Dependencies/UIAlertView+Blocks.h 2011-11-01 14:25:30 +0000 |
825 | @@ -0,0 +1,16 @@ |
826 | +// |
827 | +// UIAlertView+Blocks.h |
828 | +// Shibui |
829 | +// |
830 | +// Created by Jiva DeVoe on 12/28/10. |
831 | +// Copyright 2010 Random Ideas, LLC. All rights reserved. |
832 | +// |
833 | + |
834 | +#import <Foundation/Foundation.h> |
835 | +#import "RIButtonItem.h" |
836 | + |
837 | +@interface UIAlertView (Blocks) |
838 | + |
839 | +-(id)initWithTitle:(NSString *)inTitle message:(NSString *)inMessage cancelButtonItem:(RIButtonItem *)inCancelButtonItem otherButtonItems:(RIButtonItem *)inOtherButtonItems, ... NS_REQUIRES_NIL_TERMINATION; |
840 | + |
841 | +@end |
842 | |
843 | === added file 'Dependencies/UIAlertView+Blocks.m' |
844 | --- Dependencies/UIAlertView+Blocks.m 1970-01-01 00:00:00 +0000 |
845 | +++ Dependencies/UIAlertView+Blocks.m 2011-11-01 14:25:30 +0000 |
846 | @@ -0,0 +1,61 @@ |
847 | +// |
848 | +// UIAlertView+Blocks.m |
849 | +// Shibui |
850 | +// |
851 | +// Created by Jiva DeVoe on 12/28/10. |
852 | +// Copyright 2010 Random Ideas, LLC. All rights reserved. |
853 | +// |
854 | + |
855 | +#import "UIAlertView+Blocks.h" |
856 | +#import <objc/runtime.h> |
857 | + |
858 | +static NSString *RI_BUTTON_ASS_KEY = @"com.random-ideas.BUTTONS"; |
859 | + |
860 | +@implementation UIAlertView (Blocks) |
861 | + |
862 | +-(id)initWithTitle:(NSString *)inTitle message:(NSString *)inMessage cancelButtonItem:(RIButtonItem *)inCancelButtonItem otherButtonItems:(RIButtonItem *)inOtherButtonItems, ... |
863 | +{ |
864 | + if((self = [self initWithTitle:inTitle message:inMessage delegate:self cancelButtonTitle:inCancelButtonItem.label otherButtonTitles:nil])) |
865 | + { |
866 | + NSMutableArray *buttonsArray = [NSMutableArray array]; |
867 | + |
868 | + RIButtonItem *eachItem; |
869 | + va_list argumentList; |
870 | + if (inOtherButtonItems) |
871 | + { |
872 | + [buttonsArray addObject: inOtherButtonItems]; |
873 | + va_start(argumentList, inOtherButtonItems); |
874 | + while((eachItem = va_arg(argumentList, RIButtonItem *))) |
875 | + { |
876 | + [buttonsArray addObject: eachItem]; |
877 | + } |
878 | + va_end(argumentList); |
879 | + } |
880 | + |
881 | + for(RIButtonItem *item in buttonsArray) |
882 | + { |
883 | + [self addButtonWithTitle:item.label]; |
884 | + } |
885 | + |
886 | + if(inCancelButtonItem) |
887 | + [buttonsArray insertObject:inCancelButtonItem atIndex:0]; |
888 | + |
889 | + objc_setAssociatedObject(self, RI_BUTTON_ASS_KEY, buttonsArray, OBJC_ASSOCIATION_RETAIN_NONATOMIC); |
890 | + |
891 | + [self setDelegate:self]; |
892 | + [self retain]; // keep yourself around! |
893 | + } |
894 | + return self; |
895 | +} |
896 | + |
897 | +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex |
898 | +{ |
899 | + NSArray *buttonsArray = objc_getAssociatedObject(self, RI_BUTTON_ASS_KEY); |
900 | + RIButtonItem *item = [buttonsArray objectAtIndex:buttonIndex]; |
901 | + if(item.action) |
902 | + item.action(); |
903 | + objc_setAssociatedObject(self, RI_BUTTON_ASS_KEY, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); |
904 | + [self release]; // and release yourself! |
905 | +} |
906 | + |
907 | +@end |
908 | |
909 | === modified file 'Dependencies/oauthconsumer/Crypto/sha1.c' |
910 | --- Dependencies/oauthconsumer/Crypto/sha1.c 2011-08-31 14:56:30 +0000 |
911 | +++ Dependencies/oauthconsumer/Crypto/sha1.c 2011-11-01 14:25:30 +0000 |
912 | @@ -98,6 +98,7 @@ |
913 | state[4] += e; |
914 | /* Wipe variables */ |
915 | a = b = c = d = e = 0; |
916 | + (void)a; // shut up the static analyzer |
917 | } |
918 | |
919 | |
920 | @@ -159,6 +160,7 @@ |
921 | } |
922 | /* Wipe variables */ |
923 | i = j = 0; |
924 | + (void)i; // shut up the static analyzer |
925 | memset(context->buffer, 0, 64); |
926 | memset(context->state, 0, 20); |
927 | memset(context->count, 0, 8); |
928 | |
929 | === modified file 'Dependencies/oauthconsumer/OAMutableURLRequest.m' |
930 | --- Dependencies/oauthconsumer/OAMutableURLRequest.m 2011-08-31 14:56:30 +0000 |
931 | +++ Dependencies/oauthconsumer/OAMutableURLRequest.m 2011-11-01 14:25:30 +0000 |
932 | @@ -85,7 +85,7 @@ |
933 | signatureProvider:(id<OASignatureProviding>)aProvider |
934 | nonce:(NSString *)aNonce |
935 | timestamp:(NSString *)aTimestamp { |
936 | - [self initWithURL:aUrl |
937 | + self = [self initWithURL:aUrl |
938 | consumer:aConsumer |
939 | token:aToken |
940 | realm:aRealm |
941 | @@ -135,7 +135,7 @@ |
942 | - (void)_generateNonce { |
943 | CFUUIDRef theUUID = CFUUIDCreate(NULL); |
944 | CFStringRef string = CFUUIDCreateString(NULL, theUUID); |
945 | - NSMakeCollectable(theUUID); |
946 | + [NSMakeCollectable(theUUID) autorelease]; |
947 | if (nonce) { |
948 | CFRelease(nonce); |
949 | } |
950 | |
951 | === modified file 'Dependencies/oauthconsumer/OAToken.m' |
952 | --- Dependencies/oauthconsumer/OAToken.m 2011-08-31 14:56:30 +0000 |
953 | +++ Dependencies/oauthconsumer/OAToken.m 2011-11-01 14:25:30 +0000 |
954 | @@ -117,7 +117,7 @@ |
955 | } |
956 | |
957 | - (id)initWithUserDefaultsUsingServiceProviderName:(const NSString *)provider prefix:(const NSString *)prefix { |
958 | - [super init]; |
959 | + self = [super init]; |
960 | self.key = [OAToken loadSetting:@"key" provider:provider prefix:prefix]; |
961 | self.secret = [OAToken loadSetting:@"secret" provider:provider prefix:prefix]; |
962 | self.session = [OAToken loadSetting:@"session" provider:provider prefix:prefix]; |
963 | |
964 | === modified file 'Dependencies/oauthconsumer/OATokenManager.m' |
965 | --- Dependencies/oauthconsumer/OATokenManager.m 2011-08-31 14:56:30 +0000 |
966 | +++ Dependencies/oauthconsumer/OATokenManager.m 2011-11-01 14:25:30 +0000 |
967 | @@ -93,7 +93,7 @@ |
968 | [self exchangeToken]; |
969 | } else { |
970 | [authorizedTokenKey release]; |
971 | - authorizedTokenKey = [aKey retain]; |
972 | + authorizedTokenKey = (NSString*)[aKey retain]; |
973 | } |
974 | } |
975 | |
976 | @@ -284,6 +284,7 @@ |
977 | { |
978 | OAToken *token = [[OAToken alloc] initWithHTTPResponseBody:body]; |
979 | [self setAccessToken:token]; |
980 | + [token release]; |
981 | } |
982 | |
983 | - (void)renewToken { |
984 | @@ -371,6 +372,7 @@ |
985 | [delegates setObject:aDelegate forKey:[NSString stringWithFormat:@"%p", call]]; |
986 | } |
987 | [self dispatch]; |
988 | + [call release]; |
989 | } |
990 | |
991 | - (void)fetchData:(NSString *)aURL method:(NSString *)aMethod parameters:(NSArray *)theParameters |
992 | |
993 | === modified file 'Files.xcodeproj/project.pbxproj' |
994 | --- Files.xcodeproj/project.pbxproj 2011-09-27 14:36:00 +0000 |
995 | +++ Files.xcodeproj/project.pbxproj 2011-11-01 14:25:30 +0000 |
996 | @@ -7,6 +7,28 @@ |
997 | objects = { |
998 | |
999 | /* Begin PBXBuildFile section */ |
1000 | + 913A54AF1451EFE70081FD67 /* progress_view_background.png in Resources */ = {isa = PBXBuildFile; fileRef = 913A54AD1451EFE70081FD67 /* progress_view_background.png */; }; |
1001 | + 913A54B01451EFE70081FD67 /* progress_view_background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 913A54AE1451EFE70081FD67 /* progress_view_background@2x.png */; }; |
1002 | + 916BF7611459EF9C00D4FE06 /* U1UTIMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 916BF7601459EF9C00D4FE06 /* U1UTIMapper.m */; }; |
1003 | + 916BF7641459F66A00D4FE06 /* uti-mappings.plist in Resources */ = {isa = PBXBuildFile; fileRef = 916BF7631459F66A00D4FE06 /* uti-mappings.plist */; }; |
1004 | + 916BF76B145A464E00D4FE06 /* settings.png in Resources */ = {isa = PBXBuildFile; fileRef = 916BF769145A464E00D4FE06 /* settings.png */; }; |
1005 | + 916BF76C145A464E00D4FE06 /* settings@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 916BF76A145A464E00D4FE06 /* settings@2x.png */; }; |
1006 | + 916BF77A145AF6B900D4FE06 /* Entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = 916BF779145AF6B900D4FE06 /* Entitlements.plist */; }; |
1007 | + 916E0082143C9A3A0037F6D3 /* U1LocalAssetsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 916E0081143C9A390037F6D3 /* U1LocalAssetsViewController.m */; }; |
1008 | + 917ADEC71458954E00980FD4 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 917ADEC51458954E00980FD4 /* Icon.png */; }; |
1009 | + 917ADEC81458954E00980FD4 /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 917ADEC61458954E00980FD4 /* Icon@2x.png */; }; |
1010 | + 9190AAF41444CA0A0063614A /* U1LocalAssetsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9190AAF31444CA0A0063614A /* U1LocalAssetsViewController.xib */; }; |
1011 | + 91A5E2DC142A70DF00EAAC2B /* U1LocalAssetsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 91A5E2DB142A70DF00EAAC2B /* U1LocalAssetsManager.m */; }; |
1012 | + 91A5E2DF142B727600EAAC2B /* U1AssetUploadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 91A5E2DE142B727500EAAC2B /* U1AssetUploadOperation.m */; }; |
1013 | + 91B3F2D5141E87F900939B3C /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91B3F2D4141E87F900939B3C /* AssetsLibrary.framework */; }; |
1014 | + 91B3F2DC141FDFAB00939B3C /* _U1Asset.m in Sources */ = {isa = PBXBuildFile; fileRef = 91B3F2DB141FDFAB00939B3C /* _U1Asset.m */; }; |
1015 | + 91B3F2DF141FDFBE00939B3C /* U1Asset.m in Sources */ = {isa = PBXBuildFile; fileRef = 91B3F2DE141FDFBE00939B3C /* U1Asset.m */; }; |
1016 | + 91EC184E145B8E3B00DF31F4 /* U1SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 91EC184C145B8E3A00DF31F4 /* U1SettingsViewController.m */; }; |
1017 | + 91EC184F145B8E3B00DF31F4 /* U1SettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 91EC184D145B8E3B00DF31F4 /* U1SettingsViewController.xib */; }; |
1018 | + 91EC1851145F0A8F00DF31F4 /* default-settings.plist in Resources */ = {isa = PBXBuildFile; fileRef = 91EC1850145F0A8F00DF31F4 /* default-settings.plist */; }; |
1019 | + 91EC1858145F0C1600DF31F4 /* RIButtonItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 91EC1857145F0C1600DF31F4 /* RIButtonItem.m */; }; |
1020 | + 91EC185D145F0C3000DF31F4 /* UIActionSheet+Blocks.m in Sources */ = {isa = PBXBuildFile; fileRef = 91EC185A145F0C3000DF31F4 /* UIActionSheet+Blocks.m */; }; |
1021 | + 91EC185E145F0C3000DF31F4 /* UIAlertView+Blocks.m in Sources */ = {isa = PBXBuildFile; fileRef = 91EC185C145F0C3000DF31F4 /* UIAlertView+Blocks.m */; }; |
1022 | 960D46131409E0E100B73177 /* PullRefreshTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 960D46001409E09F00B73177 /* PullRefreshTableViewController.m */; }; |
1023 | 960D46141409E0F000B73177 /* arrow.png in Resources */ = {isa = PBXBuildFile; fileRef = 960D45FB1409E09F00B73177 /* arrow.png */; }; |
1024 | 960D46161409E10200B73177 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 960D46151409E10200B73177 /* QuartzCore.framework */; }; |
1025 | @@ -21,6 +43,7 @@ |
1026 | 960D462E140DD22800B73177 /* U1FileNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 960D462D140DD22600B73177 /* U1FileNode.m */; }; |
1027 | 960D4631140DD23600B73177 /* U1FolderNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 960D4630140DD23400B73177 /* U1FolderNode.m */; }; |
1028 | 960D4635140DDBE400B73177 /* U1NodeChildrenResultSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 960D4634140DDBE400B73177 /* U1NodeChildrenResultSet.m */; }; |
1029 | + 963C16D0144346CC007A51D0 /* libTestFlight.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 963C16CB144346A6007A51D0 /* libTestFlight.a */; }; |
1030 | 965D7EA814293B6700E4754F /* ic_act_publish_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 965D7EA214293B6700E4754F /* ic_act_publish_file.png */; }; |
1031 | 965D7EA914293B6700E4754F /* ic_act_publish_file@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 965D7EA314293B6700E4754F /* ic_act_publish_file@2x.png */; }; |
1032 | 965D7EAA14293B6700E4754F /* ic_act_unpublish_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 965D7EA414293B6700E4754F /* ic_act_unpublish_file.png */; }; |
1033 | @@ -52,6 +75,11 @@ |
1034 | 96A169A01430C9C900E4C990 /* 265-download.png in Resources */ = {isa = PBXBuildFile; fileRef = 96A1699E1430C9C900E4C990 /* 265-download.png */; }; |
1035 | 96A169A11430C9C900E4C990 /* 265-download@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 96A1699F1430C9C900E4C990 /* 265-download@2x.png */; }; |
1036 | 96A169A41430D53700E4C990 /* U1LocalFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 96A169A31430D53600E4C990 /* U1LocalFileInfo.m */; }; |
1037 | + 96B20E6D145F6AAE00D8ED69 /* 218-trash2.png in Resources */ = {isa = PBXBuildFile; fileRef = 96B20E6B145F6AAE00D8ED69 /* 218-trash2.png */; }; |
1038 | + 96B20E6E145F6AAE00D8ED69 /* 218-trash2@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 96B20E6C145F6AAE00D8ED69 /* 218-trash2@2x.png */; }; |
1039 | + 96B20E78145F815500D8ED69 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 96B20E77145F815500D8ED69 /* Reachability.m */; }; |
1040 | + 96B20E7A145F819300D8ED69 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96B20E79145F819200D8ED69 /* SystemConfiguration.framework */; }; |
1041 | + 96CAD3C71457823B007A496C /* NSDictionary+U1Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 96CAD3C61457823B007A496C /* NSDictionary+U1Additions.m */; }; |
1042 | 96CC17C81417E5E400EFC1BA /* U1Files.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 96CC17C61417E5E400EFC1BA /* U1Files.xcdatamodeld */; }; |
1043 | 96CC17D31417EA0700EFC1BA /* _U1FileNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 96CC17CC1417EA0700EFC1BA /* _U1FileNode.m */; }; |
1044 | 96CC17D41417EA0700EFC1BA /* _U1FolderNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 96CC17CE1417EA0700EFC1BA /* _U1FolderNode.m */; }; |
1045 | @@ -116,6 +144,39 @@ |
1046 | /* End PBXContainerItemProxy section */ |
1047 | |
1048 | /* Begin PBXFileReference section */ |
1049 | + 913A54AD1451EFE70081FD67 /* progress_view_background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = progress_view_background.png; path = Assets/progress_view_background.png; sourceTree = "<group>"; }; |
1050 | + 913A54AE1451EFE70081FD67 /* progress_view_background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "progress_view_background@2x.png"; path = "Assets/progress_view_background@2x.png"; sourceTree = "<group>"; }; |
1051 | + 916BF75F1459EF9C00D4FE06 /* U1UTIMapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1UTIMapper.h; sourceTree = "<group>"; }; |
1052 | + 916BF7601459EF9C00D4FE06 /* U1UTIMapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1UTIMapper.m; sourceTree = "<group>"; }; |
1053 | + 916BF7631459F66A00D4FE06 /* uti-mappings.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "uti-mappings.plist"; sourceTree = "<group>"; }; |
1054 | + 916BF769145A464E00D4FE06 /* settings.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = settings.png; path = Assets/settings.png; sourceTree = "<group>"; }; |
1055 | + 916BF76A145A464E00D4FE06 /* settings@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "settings@2x.png"; path = "Assets/settings@2x.png"; sourceTree = "<group>"; }; |
1056 | + 916BF779145AF6B900D4FE06 /* Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Entitlements.plist; sourceTree = "<group>"; }; |
1057 | + 916E0080143C9A390037F6D3 /* U1LocalAssetsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1LocalAssetsViewController.h; sourceTree = "<group>"; }; |
1058 | + 916E0081143C9A390037F6D3 /* U1LocalAssetsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1LocalAssetsViewController.m; sourceTree = "<group>"; }; |
1059 | + 917ADEC014585DC800980FD4 /* U1Files 1.0-9.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "U1Files 1.0-9.xcdatamodel"; sourceTree = "<group>"; }; |
1060 | + 917ADEC51458954E00980FD4 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = "<group>"; }; |
1061 | + 917ADEC61458954E00980FD4 /* Icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon@2x.png"; sourceTree = "<group>"; }; |
1062 | + 9190AAF31444CA0A0063614A /* U1LocalAssetsViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = U1LocalAssetsViewController.xib; sourceTree = "<group>"; }; |
1063 | + 91A5E2DB142A70DF00EAAC2B /* U1LocalAssetsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1LocalAssetsManager.m; sourceTree = "<group>"; }; |
1064 | + 91A5E2DD142B727500EAAC2B /* U1AssetUploadOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1AssetUploadOperation.h; sourceTree = "<group>"; }; |
1065 | + 91A5E2DE142B727500EAAC2B /* U1AssetUploadOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1AssetUploadOperation.m; sourceTree = "<group>"; }; |
1066 | + 91B3F2D4141E87F900939B3C /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; |
1067 | + 91B3F2D7141FC9BE00939B3C /* U1LocalAssetsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1LocalAssetsManager.h; sourceTree = "<group>"; }; |
1068 | + 91B3F2DA141FDFAB00939B3C /* _U1Asset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _U1Asset.h; sourceTree = "<group>"; }; |
1069 | + 91B3F2DB141FDFAB00939B3C /* _U1Asset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _U1Asset.m; sourceTree = "<group>"; }; |
1070 | + 91B3F2DD141FDFBE00939B3C /* U1Asset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1Asset.h; sourceTree = "<group>"; }; |
1071 | + 91B3F2DE141FDFBE00939B3C /* U1Asset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1Asset.m; sourceTree = "<group>"; }; |
1072 | + 91EC184B145B8E3A00DF31F4 /* U1SettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1SettingsViewController.h; sourceTree = "<group>"; }; |
1073 | + 91EC184C145B8E3A00DF31F4 /* U1SettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1SettingsViewController.m; sourceTree = "<group>"; }; |
1074 | + 91EC184D145B8E3B00DF31F4 /* U1SettingsViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = U1SettingsViewController.xib; sourceTree = "<group>"; }; |
1075 | + 91EC1850145F0A8F00DF31F4 /* default-settings.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "default-settings.plist"; sourceTree = "<group>"; }; |
1076 | + 91EC1856145F0C1600DF31F4 /* RIButtonItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RIButtonItem.h; sourceTree = "<group>"; }; |
1077 | + 91EC1857145F0C1600DF31F4 /* RIButtonItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RIButtonItem.m; sourceTree = "<group>"; }; |
1078 | + 91EC1859145F0C3000DF31F4 /* UIActionSheet+Blocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIActionSheet+Blocks.h"; sourceTree = "<group>"; }; |
1079 | + 91EC185A145F0C3000DF31F4 /* UIActionSheet+Blocks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIActionSheet+Blocks.m"; sourceTree = "<group>"; }; |
1080 | + 91EC185B145F0C3000DF31F4 /* UIAlertView+Blocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIAlertView+Blocks.h"; sourceTree = "<group>"; }; |
1081 | + 91EC185C145F0C3000DF31F4 /* UIAlertView+Blocks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIAlertView+Blocks.m"; sourceTree = "<group>"; }; |
1082 | 960D45FA1409E09F00B73177 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = "<group>"; }; |
1083 | 960D45FB1409E09F00B73177 /* arrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = arrow.png; sourceTree = "<group>"; }; |
1084 | 960D45FD1409E09F00B73177 /* DemoTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoTableViewController.h; sourceTree = "<group>"; }; |
1085 | @@ -149,6 +210,10 @@ |
1086 | 960D4630140DD23400B73177 /* U1FolderNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1FolderNode.m; sourceTree = "<group>"; }; |
1087 | 960D4633140DDBE400B73177 /* U1NodeChildrenResultSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1NodeChildrenResultSet.h; sourceTree = "<group>"; }; |
1088 | 960D4634140DDBE400B73177 /* U1NodeChildrenResultSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1NodeChildrenResultSet.m; sourceTree = "<group>"; }; |
1089 | + 963C16CB144346A6007A51D0 /* libTestFlight.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libTestFlight.a; sourceTree = "<group>"; }; |
1090 | + 963C16CC144346A6007A51D0 /* README.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.txt; sourceTree = "<group>"; }; |
1091 | + 963C16CD144346A6007A51D0 /* release_notes.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = release_notes.txt; sourceTree = "<group>"; }; |
1092 | + 963C16CE144346A6007A51D0 /* TestFlight.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestFlight.h; sourceTree = "<group>"; }; |
1093 | 965D7EA214293B6700E4754F /* ic_act_publish_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_act_publish_file.png; path = Assets/ic_act_publish_file.png; sourceTree = "<group>"; }; |
1094 | 965D7EA314293B6700E4754F /* ic_act_publish_file@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "ic_act_publish_file@2x.png"; path = "Assets/ic_act_publish_file@2x.png"; sourceTree = "<group>"; }; |
1095 | 965D7EA414293B6700E4754F /* ic_act_unpublish_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_act_unpublish_file.png; path = Assets/ic_act_unpublish_file.png; sourceTree = "<group>"; }; |
1096 | @@ -194,6 +259,14 @@ |
1097 | 96A1699F1430C9C900E4C990 /* 265-download@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "265-download@2x.png"; path = "Assets/265-download@2x.png"; sourceTree = "<group>"; }; |
1098 | 96A169A21430D53600E4C990 /* U1LocalFileInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1LocalFileInfo.h; sourceTree = "<group>"; }; |
1099 | 96A169A31430D53600E4C990 /* U1LocalFileInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1LocalFileInfo.m; sourceTree = "<group>"; }; |
1100 | + 96A56430143265B4007A1A93 /* U1Files 1.0-3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "U1Files 1.0-3.xcdatamodel"; sourceTree = "<group>"; }; |
1101 | + 96B20E6B145F6AAE00D8ED69 /* 218-trash2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "218-trash2.png"; path = "Assets/218-trash2.png"; sourceTree = "<group>"; }; |
1102 | + 96B20E6C145F6AAE00D8ED69 /* 218-trash2@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "218-trash2@2x.png"; path = "Assets/218-trash2@2x.png"; sourceTree = "<group>"; }; |
1103 | + 96B20E76145F815500D8ED69 /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = "<group>"; }; |
1104 | + 96B20E77145F815500D8ED69 /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = "<group>"; }; |
1105 | + 96B20E79145F819200D8ED69 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; |
1106 | + 96CAD3C51457823B007A496C /* NSDictionary+U1Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+U1Additions.h"; sourceTree = "<group>"; }; |
1107 | + 96CAD3C61457823B007A496C /* NSDictionary+U1Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+U1Additions.m"; sourceTree = "<group>"; }; |
1108 | 96CC17C71417E5E400EFC1BA /* U1Files.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = U1Files.xcdatamodel; sourceTree = "<group>"; }; |
1109 | 96CC17CB1417EA0700EFC1BA /* _U1FileNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _U1FileNode.h; sourceTree = "<group>"; }; |
1110 | 96CC17CC1417EA0700EFC1BA /* _U1FileNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _U1FileNode.m; sourceTree = "<group>"; }; |
1111 | @@ -292,6 +365,8 @@ |
1112 | isa = PBXFrameworksBuildPhase; |
1113 | buildActionMask = 2147483647; |
1114 | files = ( |
1115 | + 96B20E7A145F819300D8ED69 /* SystemConfiguration.framework in Frameworks */, |
1116 | + 91B3F2D5141E87F900939B3C /* AssetsLibrary.framework in Frameworks */, |
1117 | 96CC17D81417EA2B00EFC1BA /* CoreData.framework in Frameworks */, |
1118 | 96733B12140DFD6D0074D545 /* Security.framework in Frameworks */, |
1119 | 960D46161409E10200B73177 /* QuartzCore.framework in Frameworks */, |
1120 | @@ -299,6 +374,7 @@ |
1121 | 96E860B613F7251D0026783D /* UIKit.framework in Frameworks */, |
1122 | 96E860B813F7251D0026783D /* Foundation.framework in Frameworks */, |
1123 | 96E860BA13F7251D0026783D /* CoreGraphics.framework in Frameworks */, |
1124 | + 963C16D0144346CC007A51D0 /* libTestFlight.a in Frameworks */, |
1125 | ); |
1126 | runOnlyForDeploymentPostprocessing = 0; |
1127 | }; |
1128 | @@ -350,6 +426,8 @@ |
1129 | 96CC17CA1417E9E500EFC1BA /* Generated */, |
1130 | 96CC17DF1418091100EFC1BA /* Parsers */, |
1131 | 96CC17C61417E5E400EFC1BA /* U1Files.xcdatamodeld */, |
1132 | + 91B3F2DD141FDFBE00939B3C /* U1Asset.h */, |
1133 | + 91B3F2DE141FDFBE00939B3C /* U1Asset.m */, |
1134 | 96CC17D91417EBF500EFC1BA /* U1Volume.h */, |
1135 | 96CC17DA1417EBF500EFC1BA /* U1Volume.m */, |
1136 | 960D4629140D99DB00B73177 /* U1Node.h */, |
1137 | @@ -366,6 +444,17 @@ |
1138 | name = Model; |
1139 | sourceTree = "<group>"; |
1140 | }; |
1141 | + 963C16CA144346A6007A51D0 /* TestFlightSDK */ = { |
1142 | + isa = PBXGroup; |
1143 | + children = ( |
1144 | + 963C16CB144346A6007A51D0 /* libTestFlight.a */, |
1145 | + 963C16CC144346A6007A51D0 /* README.txt */, |
1146 | + 963C16CD144346A6007A51D0 /* release_notes.txt */, |
1147 | + 963C16CE144346A6007A51D0 /* TestFlight.h */, |
1148 | + ); |
1149 | + path = TestFlightSDK; |
1150 | + sourceTree = "<group>"; |
1151 | + }; |
1152 | 96733AEC140DFABB0074D545 /* SSO */ = { |
1153 | isa = PBXGroup; |
1154 | children = ( |
1155 | @@ -383,14 +472,12 @@ |
1156 | 96783E6513F8ABC70092C6A1 /* Assets */ = { |
1157 | isa = PBXGroup; |
1158 | children = ( |
1159 | + 96A1699A1430C95E00E4C990 /* 04-eye.png */, |
1160 | + 96A1699B1430C95E00E4C990 /* 04-eye@2x.png */, |
1161 | + 96B20E6B145F6AAE00D8ED69 /* 218-trash2.png */, |
1162 | + 96B20E6C145F6AAE00D8ED69 /* 218-trash2@2x.png */, |
1163 | 96A1699E1430C9C900E4C990 /* 265-download.png */, |
1164 | 96A1699F1430C9C900E4C990 /* 265-download@2x.png */, |
1165 | - 96A1699A1430C95E00E4C990 /* 04-eye.png */, |
1166 | - 96A1699B1430C95E00E4C990 /* 04-eye@2x.png */, |
1167 | - 965D7EAF1429663A00E4754F /* logo_4_white.png */, |
1168 | - 965D7EB01429663A00E4754F /* logo_4_white@2x.png */, |
1169 | - 965D7EB11429663A00E4754F /* white_tile.png */, |
1170 | - 965D7EB21429663A00E4754F /* white_tile@2x.png */, |
1171 | 965D7EA214293B6700E4754F /* ic_act_publish_file.png */, |
1172 | 965D7EA314293B6700E4754F /* ic_act_publish_file@2x.png */, |
1173 | 965D7EA414293B6700E4754F /* ic_act_unpublish_file.png */, |
1174 | @@ -399,14 +486,35 @@ |
1175 | 965D7EA714293B6700E4754F /* ic_act_upload_photo@2x.png */, |
1176 | 960D461F1409ECC500B73177 /* ic_folder.png */, |
1177 | 960D46201409ECC500B73177 /* ic_folder@2x.png */, |
1178 | + 917ADEC51458954E00980FD4 /* Icon.png */, |
1179 | + 917ADEC61458954E00980FD4 /* Icon@2x.png */, |
1180 | + 965D7EAF1429663A00E4754F /* logo_4_white.png */, |
1181 | + 965D7EB01429663A00E4754F /* logo_4_white@2x.png */, |
1182 | + 913A54AD1451EFE70081FD67 /* progress_view_background.png */, |
1183 | + 913A54AE1451EFE70081FD67 /* progress_view_background@2x.png */, |
1184 | + 916BF769145A464E00D4FE06 /* settings.png */, |
1185 | + 916BF76A145A464E00D4FE06 /* settings@2x.png */, |
1186 | + 965D7EB11429663A00E4754F /* white_tile.png */, |
1187 | + 965D7EB21429663A00E4754F /* white_tile@2x.png */, |
1188 | ); |
1189 | name = Assets; |
1190 | path = ..; |
1191 | sourceTree = "<group>"; |
1192 | }; |
1193 | + 96B20E75145F815500D8ED69 /* Reachability */ = { |
1194 | + isa = PBXGroup; |
1195 | + children = ( |
1196 | + 96B20E76145F815500D8ED69 /* Reachability.h */, |
1197 | + 96B20E77145F815500D8ED69 /* Reachability.m */, |
1198 | + ); |
1199 | + path = Reachability; |
1200 | + sourceTree = "<group>"; |
1201 | + }; |
1202 | 96CC17CA1417E9E500EFC1BA /* Generated */ = { |
1203 | isa = PBXGroup; |
1204 | children = ( |
1205 | + 91B3F2DA141FDFAB00939B3C /* _U1Asset.h */, |
1206 | + 91B3F2DB141FDFAB00939B3C /* _U1Asset.m */, |
1207 | 96CC17CB1417EA0700EFC1BA /* _U1FileNode.h */, |
1208 | 96CC17CC1417EA0700EFC1BA /* _U1FileNode.m */, |
1209 | 96CC17CD1417EA0700EFC1BA /* _U1FolderNode.h */, |
1210 | @@ -451,6 +559,8 @@ |
1211 | 96E860B413F7251D0026783D /* Frameworks */ = { |
1212 | isa = PBXGroup; |
1213 | children = ( |
1214 | + 96B20E79145F819200D8ED69 /* SystemConfiguration.framework */, |
1215 | + 91B3F2D4141E87F900939B3C /* AssetsLibrary.framework */, |
1216 | 96CC17D71417EA2B00EFC1BA /* CoreData.framework */, |
1217 | 96733B11140DFD6D0074D545 /* Security.framework */, |
1218 | 960D46151409E10200B73177 /* QuartzCore.framework */, |
1219 | @@ -486,6 +596,8 @@ |
1220 | 96E8614213F728380026783D /* U1FilesService.m */, |
1221 | 96CC17E314180C5F00EFC1BA /* U1FilesClient.h */, |
1222 | 96CC17E414180C5F00EFC1BA /* U1FilesClient.m */, |
1223 | + 91B3F2D7141FC9BE00939B3C /* U1LocalAssetsManager.h */, |
1224 | + 91A5E2DB142A70DF00EAAC2B /* U1LocalAssetsManager.m */, |
1225 | 969EF22613F8C10C00CEF6CB /* U1VolumesViewController.h */, |
1226 | 969EF22713F8C10C00CEF6CB /* U1VolumesViewController.m */, |
1227 | 969EF22813F8C10C00CEF6CB /* U1VolumesViewController.xib */, |
1228 | @@ -498,10 +610,20 @@ |
1229 | 960D4624140D8AF200B73177 /* U1ByteSizeValueTransformer.m */, |
1230 | 960D4626140D8B4400B73177 /* U1FriendlyDateValueTransformer.h */, |
1231 | 960D4627140D8B4400B73177 /* U1FriendlyDateValueTransformer.m */, |
1232 | + 91A5E2DD142B727500EAAC2B /* U1AssetUploadOperation.h */, |
1233 | + 91A5E2DE142B727500EAAC2B /* U1AssetUploadOperation.m */, |
1234 | 965D7EB71429690C00E4754F /* U1NavigationBar.h */, |
1235 | 965D7EB81429690C00E4754F /* U1NavigationBar.m */, |
1236 | 96A169A21430D53600E4C990 /* U1LocalFileInfo.h */, |
1237 | 96A169A31430D53600E4C990 /* U1LocalFileInfo.m */, |
1238 | + 916E0080143C9A390037F6D3 /* U1LocalAssetsViewController.h */, |
1239 | + 916E0081143C9A390037F6D3 /* U1LocalAssetsViewController.m */, |
1240 | + 9190AAF31444CA0A0063614A /* U1LocalAssetsViewController.xib */, |
1241 | + 916BF75F1459EF9C00D4FE06 /* U1UTIMapper.h */, |
1242 | + 916BF7601459EF9C00D4FE06 /* U1UTIMapper.m */, |
1243 | + 91EC184B145B8E3A00DF31F4 /* U1SettingsViewController.h */, |
1244 | + 91EC184C145B8E3A00DF31F4 /* U1SettingsViewController.m */, |
1245 | + 91EC184D145B8E3B00DF31F4 /* U1SettingsViewController.xib */, |
1246 | ); |
1247 | path = Files; |
1248 | sourceTree = "<group>"; |
1249 | @@ -509,6 +631,7 @@ |
1250 | 96E860BC13F7251D0026783D /* Supporting Files */ = { |
1251 | isa = PBXGroup; |
1252 | children = ( |
1253 | + 916BF779145AF6B900D4FE06 /* Entitlements.plist */, |
1254 | 96733B0E140DFD510074D545 /* SFHFKeychainUtils.h */, |
1255 | 96733B0F140DFD510074D545 /* SFHFKeychainUtils.m */, |
1256 | 96733B08140DFBB60074D545 /* URLQueryStringParser.h */, |
1257 | @@ -529,6 +652,10 @@ |
1258 | 96E860C313F7251D0026783D /* Files-Prefix.pch */, |
1259 | 96733B13140E04940074D545 /* UIActionSheet+U1Additions.h */, |
1260 | 96733B14140E04940074D545 /* UIActionSheet+U1Additions.m */, |
1261 | + 96CAD3C51457823B007A496C /* NSDictionary+U1Additions.h */, |
1262 | + 96CAD3C61457823B007A496C /* NSDictionary+U1Additions.m */, |
1263 | + 916BF7631459F66A00D4FE06 /* uti-mappings.plist */, |
1264 | + 91EC1850145F0A8F00DF31F4 /* default-settings.plist */, |
1265 | ); |
1266 | name = "Supporting Files"; |
1267 | sourceTree = "<group>"; |
1268 | @@ -555,6 +682,14 @@ |
1269 | 96E860F413F726250026783D /* Dependencies */ = { |
1270 | isa = PBXGroup; |
1271 | children = ( |
1272 | + 96B20E75145F815500D8ED69 /* Reachability */, |
1273 | + 91EC1859145F0C3000DF31F4 /* UIActionSheet+Blocks.h */, |
1274 | + 91EC185A145F0C3000DF31F4 /* UIActionSheet+Blocks.m */, |
1275 | + 91EC185B145F0C3000DF31F4 /* UIAlertView+Blocks.h */, |
1276 | + 91EC185C145F0C3000DF31F4 /* UIAlertView+Blocks.m */, |
1277 | + 91EC1856145F0C1600DF31F4 /* RIButtonItem.h */, |
1278 | + 91EC1857145F0C1600DF31F4 /* RIButtonItem.m */, |
1279 | + 963C16CA144346A6007A51D0 /* TestFlightSDK */, |
1280 | 96E8614713F740E20026783D /* JSONKit */, |
1281 | 96E860F513F7265B0026783D /* oauthconsumer */, |
1282 | 960D45F91409E09F00B73177 /* PullToRefresh */, |
1283 | @@ -645,6 +780,7 @@ |
1284 | buildPhases = ( |
1285 | 96E860AD13F7251D0026783D /* Sources */, |
1286 | 96E860AE13F7251D0026783D /* Frameworks */, |
1287 | + 963C16D614437CF4007A51D0 /* ShellScript */, |
1288 | 96E860AF13F7251D0026783D /* Resources */, |
1289 | ); |
1290 | buildRules = ( |
1291 | @@ -728,6 +864,19 @@ |
1292 | 96A1699D1430C95E00E4C990 /* 04-eye@2x.png in Resources */, |
1293 | 96A169A01430C9C900E4C990 /* 265-download.png in Resources */, |
1294 | 96A169A11430C9C900E4C990 /* 265-download@2x.png in Resources */, |
1295 | + 9190AAF41444CA0A0063614A /* U1LocalAssetsViewController.xib in Resources */, |
1296 | + 913A54AF1451EFE70081FD67 /* progress_view_background.png in Resources */, |
1297 | + 913A54B01451EFE70081FD67 /* progress_view_background@2x.png in Resources */, |
1298 | + 917ADEC71458954E00980FD4 /* Icon.png in Resources */, |
1299 | + 917ADEC81458954E00980FD4 /* Icon@2x.png in Resources */, |
1300 | + 916BF7641459F66A00D4FE06 /* uti-mappings.plist in Resources */, |
1301 | + 916BF76B145A464E00D4FE06 /* settings.png in Resources */, |
1302 | + 916BF76C145A464E00D4FE06 /* settings@2x.png in Resources */, |
1303 | + 916BF77A145AF6B900D4FE06 /* Entitlements.plist in Resources */, |
1304 | + 91EC184F145B8E3B00DF31F4 /* U1SettingsViewController.xib in Resources */, |
1305 | + 91EC1851145F0A8F00DF31F4 /* default-settings.plist in Resources */, |
1306 | + 96B20E6D145F6AAE00D8ED69 /* 218-trash2.png in Resources */, |
1307 | + 96B20E6E145F6AAE00D8ED69 /* 218-trash2@2x.png in Resources */, |
1308 | ); |
1309 | runOnlyForDeploymentPostprocessing = 0; |
1310 | }; |
1311 | @@ -743,6 +892,20 @@ |
1312 | /* End PBXResourcesBuildPhase section */ |
1313 | |
1314 | /* Begin PBXShellScriptBuildPhase section */ |
1315 | + 963C16D614437CF4007A51D0 /* ShellScript */ = { |
1316 | + isa = PBXShellScriptBuildPhase; |
1317 | + buildActionMask = 2147483647; |
1318 | + files = ( |
1319 | + ); |
1320 | + inputPaths = ( |
1321 | + ); |
1322 | + outputPaths = ( |
1323 | + ); |
1324 | + runOnlyForDeploymentPostprocessing = 0; |
1325 | + shellPath = /bin/bash; |
1326 | + shellScript = "\nif [ -f ${SRCROOT}/U1TestFlightTeamToken.txt ]\nthen\n\ncp ${SRCROOT}/U1TestFlightTeamToken.txt ${CODESIGNING_FOLDER_PATH}\n\nelse \n\necho \"warning: ${SRCROOT}/U1TestFlightTeamToken.txt does not exist. Create this file and paste the Ubuntu One TestFlight team token into it to enable TestFlight SDK analytics.\"\n\nfi\n\n\n#echo \"foo\" > ${CODESIGNING_FOLDER_PATH}/foo.plist\n"; |
1327 | + showEnvVarsInLog = 0; |
1328 | + }; |
1329 | 96E860D813F7251D0026783D /* ShellScript */ = { |
1330 | isa = PBXShellScriptBuildPhase; |
1331 | buildActionMask = 2147483647; |
1332 | @@ -818,8 +981,20 @@ |
1333 | 96CC17DE1417EF7200EFC1BA /* U1DataRepository.m in Sources */, |
1334 | 96CC17E21418094800EFC1BA /* U1NodeJSONParser.m in Sources */, |
1335 | 96CC17E514180C6000EFC1BA /* U1FilesClient.m in Sources */, |
1336 | + 91B3F2DC141FDFAB00939B3C /* _U1Asset.m in Sources */, |
1337 | + 91B3F2DF141FDFBE00939B3C /* U1Asset.m in Sources */, |
1338 | + 91A5E2DC142A70DF00EAAC2B /* U1LocalAssetsManager.m in Sources */, |
1339 | + 91A5E2DF142B727600EAAC2B /* U1AssetUploadOperation.m in Sources */, |
1340 | 965D7EB91429690C00E4754F /* U1NavigationBar.m in Sources */, |
1341 | 96A169A41430D53700E4C990 /* U1LocalFileInfo.m in Sources */, |
1342 | + 916E0082143C9A3A0037F6D3 /* U1LocalAssetsViewController.m in Sources */, |
1343 | + 96CAD3C71457823B007A496C /* NSDictionary+U1Additions.m in Sources */, |
1344 | + 916BF7611459EF9C00D4FE06 /* U1UTIMapper.m in Sources */, |
1345 | + 91EC184E145B8E3B00DF31F4 /* U1SettingsViewController.m in Sources */, |
1346 | + 91EC1858145F0C1600DF31F4 /* RIButtonItem.m in Sources */, |
1347 | + 91EC185D145F0C3000DF31F4 /* UIActionSheet+Blocks.m in Sources */, |
1348 | + 91EC185E145F0C3000DF31F4 /* UIAlertView+Blocks.m in Sources */, |
1349 | + 96B20E78145F815500D8ED69 /* Reachability.m in Sources */, |
1350 | ); |
1351 | runOnlyForDeploymentPostprocessing = 0; |
1352 | }; |
1353 | @@ -925,13 +1100,26 @@ |
1354 | 96E860EF13F7251D0026783D /* Debug */ = { |
1355 | isa = XCBuildConfiguration; |
1356 | buildSettings = { |
1357 | + ARCHS = ( |
1358 | + armv6, |
1359 | + armv7, |
1360 | + ); |
1361 | + CODE_SIGN_IDENTITY = "iPhone Developer: Zachery Bir (P7WDPDEFHU)"; |
1362 | + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Zachery Bir (P7WDPDEFHU)"; |
1363 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
1364 | GCC_PREFIX_HEADER = "Files/Files-Prefix.pch"; |
1365 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; |
1366 | INFOPLIST_FILE = "Files/Files-Info.plist"; |
1367 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; |
1368 | + LIBRARY_SEARCH_PATHS = ( |
1369 | + "$(inherited)", |
1370 | + "\"$(SRCROOT)/Dependencies/TestFlightSDK\"", |
1371 | + ); |
1372 | PRODUCT_NAME = "$(TARGET_NAME)"; |
1373 | + PROVISIONING_PROFILE = "9D31E6D0-194D-4310-9E89-CB404D06C116"; |
1374 | + "PROVISIONING_PROFILE[sdk=iphoneos*]" = "3D867106-3B81-4625-A9C8-1E9BD85B7E75"; |
1375 | TARGETED_DEVICE_FAMILY = 1; |
1376 | + VALID_ARCHS = "arm6 armv7"; |
1377 | WRAPPER_EXTENSION = app; |
1378 | }; |
1379 | name = Debug; |
1380 | @@ -939,15 +1127,26 @@ |
1381 | 96E860F013F7251D0026783D /* Release */ = { |
1382 | isa = XCBuildConfiguration; |
1383 | buildSettings = { |
1384 | - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; |
1385 | + ARCHS = ( |
1386 | + armv6, |
1387 | + armv7, |
1388 | + ); |
1389 | + CODE_SIGN_IDENTITY = "iPhone Distribution: Canonical Group Limited"; |
1390 | + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Canonical Group Limited"; |
1391 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
1392 | GCC_PREFIX_HEADER = "Files/Files-Prefix.pch"; |
1393 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; |
1394 | INFOPLIST_FILE = "Files/Files-Info.plist"; |
1395 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; |
1396 | + LIBRARY_SEARCH_PATHS = ( |
1397 | + "$(inherited)", |
1398 | + "\"$(SRCROOT)/Dependencies/TestFlightSDK\"", |
1399 | + ); |
1400 | PRODUCT_NAME = "$(TARGET_NAME)"; |
1401 | - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; |
1402 | + PROVISIONING_PROFILE = "B93E008E-7980-4B68-961E-44E81643E70F"; |
1403 | + "PROVISIONING_PROFILE[sdk=iphoneos*]" = "B93E008E-7980-4B68-961E-44E81643E70F"; |
1404 | TARGETED_DEVICE_FAMILY = 1; |
1405 | + VALID_ARCHS = "arm6 armv7"; |
1406 | WRAPPER_EXTENSION = app; |
1407 | }; |
1408 | name = Release; |
1409 | @@ -1022,9 +1221,11 @@ |
1410 | 96CC17C61417E5E400EFC1BA /* U1Files.xcdatamodeld */ = { |
1411 | isa = XCVersionGroup; |
1412 | children = ( |
1413 | + 917ADEC014585DC800980FD4 /* U1Files 1.0-9.xcdatamodel */, |
1414 | + 96A56430143265B4007A1A93 /* U1Files 1.0-3.xcdatamodel */, |
1415 | 96CC17C71417E5E400EFC1BA /* U1Files.xcdatamodel */, |
1416 | ); |
1417 | - currentVersion = 96CC17C71417E5E400EFC1BA /* U1Files.xcdatamodel */; |
1418 | + currentVersion = 917ADEC014585DC800980FD4 /* U1Files 1.0-9.xcdatamodel */; |
1419 | path = U1Files.xcdatamodeld; |
1420 | sourceTree = "<group>"; |
1421 | versionGroupType = wrapper.xcdatamodel; |
1422 | |
1423 | === added file 'Files/Entitlements.plist' |
1424 | --- Files/Entitlements.plist 1970-01-01 00:00:00 +0000 |
1425 | +++ Files/Entitlements.plist 2011-11-01 14:25:30 +0000 |
1426 | @@ -0,0 +1,14 @@ |
1427 | +<?xml version="1.0" encoding="UTF-8"?> |
1428 | +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
1429 | +<plist version="1.0"> |
1430 | +<dict> |
1431 | + <key>application-identifier</key> |
1432 | + <string>UD653J2ZMP.com.ubuntu.one.files</string> |
1433 | + <key>get-task-allow</key> |
1434 | + <false/> |
1435 | + <key>keychain-access-groups</key> |
1436 | + <array> |
1437 | + <string>UD653J2ZMP.com.ubuntu.one</string> |
1438 | + </array> |
1439 | +</dict> |
1440 | +</plist> |
1441 | |
1442 | === modified file 'Files/Files-Info.plist' |
1443 | --- Files/Files-Info.plist 2011-09-27 14:42:09 +0000 |
1444 | +++ Files/Files-Info.plist 2011-11-01 14:25:30 +0000 |
1445 | @@ -9,13 +9,31 @@ |
1446 | <key>CFBundleExecutable</key> |
1447 | <string>${EXECUTABLE_NAME}</string> |
1448 | <key>CFBundleIconFile</key> |
1449 | - <string></string> |
1450 | + <string>Icon.png</string> |
1451 | + <key>CFBundleIconFiles</key> |
1452 | + <array> |
1453 | + <string>Icon.png</string> |
1454 | + <string>Icon@2x.png</string> |
1455 | + </array> |
1456 | + <key>CFBundleIcons</key> |
1457 | + <dict> |
1458 | + <key>CFBundlePrimaryIcon</key> |
1459 | + <dict> |
1460 | + <key>CFBundleIconFiles</key> |
1461 | + <array> |
1462 | + <string>Icon.png</string> |
1463 | + <string>Icon@2x.png</string> |
1464 | + </array> |
1465 | + <key>UIPrerenderedIcon</key> |
1466 | + <true/> |
1467 | + </dict> |
1468 | + </dict> |
1469 | <key>CFBundleIdentifier</key> |
1470 | - <string>com.ubuntu.one.${PRODUCT_NAME:rfc1034identifier}</string> |
1471 | + <string>com.ubuntu.one.files</string> |
1472 | <key>CFBundleInfoDictionaryVersion</key> |
1473 | <string>6.0</string> |
1474 | <key>CFBundleName</key> |
1475 | - <string>${PRODUCT_NAME}</string> |
1476 | + <string>com.ubuntu.one.${PRODUCT_NAME:rfc1034identifier}</string> |
1477 | <key>CFBundlePackageType</key> |
1478 | <string>APPL</string> |
1479 | <key>CFBundleShortVersionString</key> |
1480 | @@ -23,13 +41,11 @@ |
1481 | <key>CFBundleSignature</key> |
1482 | <string>????</string> |
1483 | <key>CFBundleVersion</key> |
1484 | - <string>2</string> |
1485 | + <string>16</string> |
1486 | <key>LSRequiresIPhoneOS</key> |
1487 | <true/> |
1488 | <key>NSMainNibFile</key> |
1489 | <string>MainWindow_iPhone</string> |
1490 | - <key>NSMainNibFile~ipad</key> |
1491 | - <string>MainWindow_iPad</string> |
1492 | <key>UISupportedInterfaceOrientations</key> |
1493 | <array> |
1494 | <string>UIInterfaceOrientationPortrait</string> |
1495 | |
1496 | === modified file 'Files/Files-Prefix.pch' |
1497 | --- Files/Files-Prefix.pch 2011-08-31 14:56:30 +0000 |
1498 | +++ Files/Files-Prefix.pch 2011-11-01 14:25:30 +0000 |
1499 | @@ -20,6 +20,10 @@ |
1500 | #endif |
1501 | |
1502 | #ifdef __OBJC__ |
1503 | - #import <UIKit/UIKit.h> |
1504 | - #import <Foundation/Foundation.h> |
1505 | + |
1506 | +#import <UIKit/UIKit.h> |
1507 | +#import <Foundation/Foundation.h> |
1508 | +#import "TestFlight.h" |
1509 | +#import "NSDictionary+U1Additions.h" |
1510 | + |
1511 | #endif |
1512 | |
1513 | === modified file 'Files/FilesAppDelegate.h' |
1514 | --- Files/FilesAppDelegate.h 2011-09-27 14:36:00 +0000 |
1515 | +++ Files/FilesAppDelegate.h 2011-11-01 14:25:30 +0000 |
1516 | @@ -18,7 +18,10 @@ |
1517 | |
1518 | @interface FilesAppDelegate : NSObject <UIApplicationDelegate> |
1519 | |
1520 | -@property (nonatomic, retain, readonly) IBOutlet UIWindow *window; |
1521 | -@property (nonatomic, retain) IBOutlet UINavigationController *navController; |
1522 | +@property (nonatomic, retain) IBOutlet UIWindow *window; |
1523 | +@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController; |
1524 | +@property (nonatomic, retain) IBOutlet UINavigationController *volumesNavController; |
1525 | +@property (nonatomic, retain) IBOutlet UINavigationController *cameraNavController; |
1526 | +@property (nonatomic, retain) IBOutlet UINavigationController *settingsNavController; |
1527 | |
1528 | @end |
1529 | |
1530 | === modified file 'Files/FilesAppDelegate.m' |
1531 | --- Files/FilesAppDelegate.m 2011-09-27 14:36:00 +0000 |
1532 | +++ Files/FilesAppDelegate.m 2011-11-01 14:25:30 +0000 |
1533 | @@ -13,6 +13,10 @@ |
1534 | // You should have received a copy of the GNU Affero General Public License |
1535 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
1536 | |
1537 | +#import <AssetsLibrary/ALAssetsLibrary.h> |
1538 | +#import <AssetsLibrary/ALAssetsGroup.h> |
1539 | +#import <AssetsLibrary/ALAsset.h> |
1540 | + |
1541 | #import "FilesAppDelegate.h" |
1542 | |
1543 | #import "U1AccountManager.h" |
1544 | @@ -20,36 +24,47 @@ |
1545 | #import "U1FileNode.h" |
1546 | #import "U1FilePreviewViewController.h" |
1547 | #import "U1FilesClient.h" |
1548 | -#import "U1FilesService.h" |
1549 | +#import "U1LocalAssetsManager.h" |
1550 | +#import "U1LocalAssetsViewController.h" |
1551 | #import "U1FolderNode.h" |
1552 | #import "U1FolderViewController.h" |
1553 | #import "U1LoginController.h" |
1554 | #import "U1Node.h" |
1555 | +#import "U1SettingsViewController.h" |
1556 | #import "U1VolumesViewController.h" |
1557 | - |
1558 | - |
1559 | -@interface FilesAppDelegate () <U1FolderViewControllerDelegate, U1VolumesViewControllerDelegate, U1LoginControllerDelegate> |
1560 | -@property (retain) U1FilesService *filesService; |
1561 | +#import "U1Volume.h" |
1562 | +#import "UIAlertView+Blocks.h" |
1563 | +#import "RIButtonItem.h" |
1564 | + |
1565 | + |
1566 | +@interface FilesAppDelegate () <U1LoginControllerDelegate> |
1567 | @property (retain) U1FilesClient *filesClient; |
1568 | +@property (retain) U1LocalAssetsManager *localAssetsManager; |
1569 | @property (retain) U1LoginController *loginController; |
1570 | @property (retain) U1DataRepository *dataRepository; |
1571 | -- (NSURL*)dataStoreURL; |
1572 | - (void)showVolumes; |
1573 | - (void)showLoginController; |
1574 | +- (void)ensureUploadFolder; |
1575 | +- (NSString*)remoteUploadFolderPath; |
1576 | +- (NSString*)localUploadQueuePath; |
1577 | +- (void)prepareTestFlight; |
1578 | @end |
1579 | |
1580 | |
1581 | @implementation FilesAppDelegate |
1582 | |
1583 | -@synthesize window; |
1584 | -@synthesize filesService, filesClient, navController, loginController, dataRepository; |
1585 | +@synthesize window, volumesNavController, cameraNavController; |
1586 | +@synthesize filesClient, localAssetsManager, tabBarController, settingsNavController, loginController, dataRepository; |
1587 | |
1588 | - (void)dealloc |
1589 | { |
1590 | [window release]; |
1591 | - [filesService release]; |
1592 | + [volumesNavController release]; |
1593 | + [cameraNavController release]; |
1594 | + [settingsNavController release]; |
1595 | [filesClient release]; |
1596 | - [navController release]; |
1597 | + [localAssetsManager release]; |
1598 | + [tabBarController release]; |
1599 | [loginController release]; |
1600 | [dataRepository release]; |
1601 | [super dealloc]; |
1602 | @@ -57,8 +72,17 @@ |
1603 | |
1604 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions |
1605 | { |
1606 | + [self prepareTestFlight]; |
1607 | + |
1608 | + [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithContentsOfFile: |
1609 | + [[NSBundle mainBundle] pathForResource:@"default-settings" ofType:@"plist"]]]; |
1610 | + |
1611 | + self.localAssetsManager = [U1LocalAssetsManager sharedLocalAssetsManager]; |
1612 | + self.filesClient = [U1FilesClient sharedFilesClient]; |
1613 | + |
1614 | + [window addSubview:[tabBarController view]]; |
1615 | [self.window makeKeyAndVisible]; |
1616 | - |
1617 | + |
1618 | if (![[U1AccountManager sharedAccountManager] hasCredentials]) |
1619 | { |
1620 | [self showLoginController]; |
1621 | @@ -71,87 +95,142 @@ |
1622 | return YES; |
1623 | } |
1624 | |
1625 | +- (void)applicationDidBecomeActive:(UIApplication *)application; |
1626 | +{ |
1627 | + if ([[U1AccountManager sharedAccountManager] hasCredentials]) |
1628 | + { |
1629 | + [self ensureUploadFolder]; |
1630 | + } |
1631 | +} |
1632 | + |
1633 | +- (void)ensureUploadFolder; |
1634 | +{ |
1635 | + |
1636 | + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; |
1637 | + |
1638 | + if (![defaults boolForKey:@"asked_auto_upload_on_first_launch"]) |
1639 | + { |
1640 | + RIButtonItem *cancelButton = [RIButtonItem item]; |
1641 | + cancelButton.label = NSLocalizedString(@"No", @""); |
1642 | + cancelButton.action = ^ |
1643 | + { |
1644 | + [defaults setBool:YES forKey:@"asked_auto_upload_on_first_launch"]; |
1645 | + }; |
1646 | + |
1647 | + RIButtonItem *dismissButton = [RIButtonItem item]; |
1648 | + dismissButton.label = NSLocalizedString(@"Yes", @""); |
1649 | + dismissButton.action = ^ |
1650 | + { |
1651 | + [defaults setBool:YES forKey:@"auto_uploads"]; |
1652 | + [defaults setBool:YES forKey:@"asked_auto_upload_on_first_launch"]; |
1653 | + }; |
1654 | + |
1655 | + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Auto-Upload", @"") |
1656 | + message:NSLocalizedString(@"Shall I automatically upload all items in your camera roll?", @"") |
1657 | + cancelButtonItem:cancelButton otherButtonItems:dismissButton, nil]; |
1658 | + [alertView show]; |
1659 | + [alertView release]; |
1660 | + } |
1661 | + |
1662 | + [self.filesClient volumesWithCompletionBlock:^(U1Volume *rootVolume, NSFetchedResultsController *cloudFoldersResultsController, NSError *error) { |
1663 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
1664 | + // iterate over volumeInfos. If there isn't one there called "Pictures - <device name>", create it. |
1665 | + BOOL found = NO; |
1666 | + for (U1Volume *volume in [cloudFoldersResultsController fetchedObjects]) { |
1667 | + if ([volume.nodePath isEqualToString:[self remoteUploadFolderPath]]) |
1668 | + { |
1669 | + found = YES; |
1670 | + self.localAssetsManager.remoteUploadFolder = [volume rootFolder]; |
1671 | + break; |
1672 | + } |
1673 | + } |
1674 | + if (!found) |
1675 | + { |
1676 | + [self.filesClient createVolumeAtPath:[self remoteUploadFolderPath] |
1677 | + completionBlock:^(U1Volume *volume, NSError *error) { |
1678 | + self.localAssetsManager.remoteUploadFolder = [volume rootFolder]; |
1679 | + [self.localAssetsManager checkForNewAssets]; |
1680 | + if (error) |
1681 | + { |
1682 | + NSLog(@"Error: %@", error); |
1683 | + } |
1684 | + }]; |
1685 | + } else |
1686 | + { |
1687 | + [self.localAssetsManager checkForNewAssets]; |
1688 | + } |
1689 | + }); |
1690 | + }]; |
1691 | +} |
1692 | + |
1693 | +- (NSString *)remoteUploadFolderPath; |
1694 | +{ |
1695 | + return [NSString stringWithFormat:@"/~/Pictures - %@", [[UIDevice currentDevice] name]]; |
1696 | +} |
1697 | + |
1698 | +- (NSString*)localUploadQueuePath; |
1699 | +{ |
1700 | + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); |
1701 | + return [[paths objectAtIndex:0] stringByAppendingPathComponent:@"localAssetsToUpload.array"]; |
1702 | +} |
1703 | + |
1704 | - (void)applicationWillResignActive:(UIApplication *)application; |
1705 | { |
1706 | [self.dataRepository save:NULL]; |
1707 | + [[NSUserDefaults standardUserDefaults] synchronize]; |
1708 | } |
1709 | |
1710 | - (void)applicationWillTerminate:(UIApplication *)application; |
1711 | { |
1712 | // TODO: check error |
1713 | [self.dataRepository save:NULL]; |
1714 | -} |
1715 | - |
1716 | -- (NSURL*)dataStoreURL; |
1717 | -{ |
1718 | - NSURL *cachesDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject]; |
1719 | - NSURL *storeURL = [NSURL URLWithString:@"U1Files.sqlite" relativeToURL:cachesDirectory]; |
1720 | - return storeURL; |
1721 | + [[NSUserDefaults standardUserDefaults] synchronize]; |
1722 | } |
1723 | |
1724 | - (void)showVolumes; |
1725 | { |
1726 | - filesService = [U1FilesService new]; |
1727 | - |
1728 | - NSURL *storeURL = [self dataStoreURL]; |
1729 | - self.dataRepository = [[U1DataRepository alloc] initWithStoreURL:storeURL]; |
1730 | - [dataRepository release]; |
1731 | - |
1732 | - filesClient = [[U1FilesClient alloc] init]; |
1733 | - [self.filesClient setFilesService:filesService]; |
1734 | - [self.filesClient setDataRepository:self.dataRepository]; |
1735 | - |
1736 | - U1VolumesViewController *rootController = [U1VolumesViewController new]; |
1737 | - rootController.delegate = self; |
1738 | - rootController.filesService = self.filesService; |
1739 | - |
1740 | - [self.navController setViewControllers:[NSArray arrayWithObject:rootController] animated:NO]; |
1741 | + U1VolumesViewController *volumesViewController = [[[U1VolumesViewController alloc] init] autorelease]; |
1742 | + [self.volumesNavController setViewControllers:[NSArray arrayWithObject:volumesViewController]]; |
1743 | + U1LocalAssetsViewController *assetsViewController = [[[U1LocalAssetsViewController alloc] initWithNodeResourcePath:[self remoteUploadFolderPath]] autorelease]; |
1744 | + [self.cameraNavController setViewControllers:[NSArray arrayWithObject:assetsViewController]]; |
1745 | + U1SettingsViewController *settingsViewController = [[U1SettingsViewController alloc] initWithNibName:@"U1SettingsViewController" bundle:nil]; |
1746 | + [self.settingsNavController setViewControllers:[NSArray arrayWithObject:settingsViewController]]; |
1747 | } |
1748 | |
1749 | - (void)showLoginController; |
1750 | { |
1751 | self.loginController = [[[U1LoginController alloc] init] autorelease]; |
1752 | self.loginController.delegate = self; |
1753 | - [self.navController presentModalViewController:self.loginController.loginViewController animated:YES]; |
1754 | + [self.tabBarController presentModalViewController:self.loginController.loginViewController animated:YES]; |
1755 | } |
1756 | |
1757 | - (void)loginControllerDidLogin; |
1758 | { |
1759 | - [self.navController dismissModalViewControllerAnimated:YES]; |
1760 | + [self.tabBarController dismissModalViewControllerAnimated:YES]; |
1761 | self.loginController = nil; |
1762 | [self showVolumes]; |
1763 | -} |
1764 | - |
1765 | - |
1766 | -#pragma mark U1FolderViewControllerDelegate Methods |
1767 | - |
1768 | -- (void)folderController:(U1FolderViewController*)folderController didSelectNode:(U1Node*)node; |
1769 | -{ |
1770 | - if ([node isFolder]) |
1771 | - { |
1772 | - U1FolderViewController *nextFolderController = [[U1FolderViewController alloc] initWithNodeResourcePath:node.resourcePath]; |
1773 | - nextFolderController.filesClient = self.filesClient; |
1774 | - nextFolderController.delegate = self; |
1775 | - [self.navController pushViewController:nextFolderController animated:YES]; |
1776 | - } |
1777 | - else if ([node isFile]) |
1778 | - { |
1779 | - U1FilePreviewViewController *fileController = [[U1FilePreviewViewController alloc] initWithNode:(id)node]; |
1780 | - fileController.filesClient = self.filesClient; |
1781 | - [self.navController pushViewController:fileController animated:YES]; |
1782 | - } |
1783 | -} |
1784 | - |
1785 | - |
1786 | -#pragma mark U1VolumesControllerDelegate Methods |
1787 | - |
1788 | -- (void)volumesController:(U1VolumesViewController *)volumesController didSelectVolume:(NSDictionary *)volume; |
1789 | -{ |
1790 | - NSString *nodePath = [volume objectForKey:@"node_path"]; |
1791 | - U1FolderViewController *folderController = [[U1FolderViewController alloc] initWithNodeResourcePath:nodePath]; |
1792 | - folderController.filesClient = self.filesClient; |
1793 | - folderController.delegate = self; |
1794 | - [self.navController pushViewController:folderController animated:YES]; |
1795 | -} |
1796 | + [self ensureUploadFolder]; |
1797 | +} |
1798 | + |
1799 | +- (void)prepareTestFlight; |
1800 | +{ |
1801 | + NSString *tokenFilePath = [[NSBundle mainBundle] pathForResource:@"U1TestFlightTeamToken" ofType:@"txt"]; |
1802 | + if (!tokenFilePath) |
1803 | + return; |
1804 | + |
1805 | + NSError *error = nil; |
1806 | + NSString *teamToken = [NSString stringWithContentsOfFile:tokenFilePath usedEncoding:NULL error:&error]; |
1807 | + |
1808 | + if (teamToken) |
1809 | + { |
1810 | + teamToken = [teamToken stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; |
1811 | + [TestFlight takeOff:teamToken]; |
1812 | + } |
1813 | + else |
1814 | + { |
1815 | + NSLog(@"error loading TestFlight team token: %@", error); |
1816 | + } |
1817 | +} |
1818 | + |
1819 | |
1820 | @end |
1821 | |
1822 | === added file 'Files/Generated/_U1Asset.h' |
1823 | --- Files/Generated/_U1Asset.h 1970-01-01 00:00:00 +0000 |
1824 | +++ Files/Generated/_U1Asset.h 2011-11-01 14:25:30 +0000 |
1825 | @@ -0,0 +1,111 @@ |
1826 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
1827 | +// Make changes to U1Asset.h instead. |
1828 | + |
1829 | +#import <CoreData/CoreData.h> |
1830 | + |
1831 | + |
1832 | +@class U1FileNode; |
1833 | + |
1834 | + |
1835 | + |
1836 | + |
1837 | + |
1838 | + |
1839 | +@interface U1AssetID : NSManagedObjectID {} |
1840 | +@end |
1841 | + |
1842 | +@interface _U1Asset : NSManagedObject {} |
1843 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_; |
1844 | ++ (NSString*)entityName; |
1845 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_; |
1846 | +- (U1AssetID*)objectID; |
1847 | + |
1848 | + |
1849 | + |
1850 | + |
1851 | +@property (nonatomic, retain) NSString *filename; |
1852 | + |
1853 | + |
1854 | +//- (BOOL)validateFilename:(id*)value_ error:(NSError**)error_; |
1855 | + |
1856 | + |
1857 | + |
1858 | + |
1859 | +@property (nonatomic, retain) NSNumber *generation; |
1860 | + |
1861 | + |
1862 | +@property int generationValue; |
1863 | +- (int)generationValue; |
1864 | +- (void)setGenerationValue:(int)value_; |
1865 | + |
1866 | +//- (BOOL)validateGeneration:(id*)value_ error:(NSError**)error_; |
1867 | + |
1868 | + |
1869 | + |
1870 | + |
1871 | +@property (nonatomic, retain) NSString *groupId; |
1872 | + |
1873 | + |
1874 | +//- (BOOL)validateGroupId:(id*)value_ error:(NSError**)error_; |
1875 | + |
1876 | + |
1877 | + |
1878 | + |
1879 | +@property (nonatomic, retain) NSString *url; |
1880 | + |
1881 | + |
1882 | +//- (BOOL)validateUrl:(id*)value_ error:(NSError**)error_; |
1883 | + |
1884 | + |
1885 | + |
1886 | + |
1887 | + |
1888 | +@property (nonatomic, retain) U1FileNode* fileNode; |
1889 | + |
1890 | +//- (BOOL)validateFileNode:(id*)value_ error:(NSError**)error_; |
1891 | + |
1892 | + |
1893 | + |
1894 | + |
1895 | +@end |
1896 | + |
1897 | +@interface _U1Asset (CoreDataGeneratedAccessors) |
1898 | + |
1899 | +@end |
1900 | + |
1901 | +@interface _U1Asset (CoreDataGeneratedPrimitiveAccessors) |
1902 | + |
1903 | + |
1904 | +- (NSString*)primitiveFilename; |
1905 | +- (void)setPrimitiveFilename:(NSString*)value; |
1906 | + |
1907 | + |
1908 | + |
1909 | + |
1910 | +- (NSNumber*)primitiveGeneration; |
1911 | +- (void)setPrimitiveGeneration:(NSNumber*)value; |
1912 | + |
1913 | +- (int)primitiveGenerationValue; |
1914 | +- (void)setPrimitiveGenerationValue:(int)value_; |
1915 | + |
1916 | + |
1917 | + |
1918 | + |
1919 | +- (NSString*)primitiveGroupId; |
1920 | +- (void)setPrimitiveGroupId:(NSString*)value; |
1921 | + |
1922 | + |
1923 | + |
1924 | + |
1925 | +- (NSString*)primitiveUrl; |
1926 | +- (void)setPrimitiveUrl:(NSString*)value; |
1927 | + |
1928 | + |
1929 | + |
1930 | + |
1931 | + |
1932 | +- (U1FileNode*)primitiveFileNode; |
1933 | +- (void)setPrimitiveFileNode:(U1FileNode*)value; |
1934 | + |
1935 | + |
1936 | +@end |
1937 | |
1938 | === added file 'Files/Generated/_U1Asset.m' |
1939 | --- Files/Generated/_U1Asset.m 1970-01-01 00:00:00 +0000 |
1940 | +++ Files/Generated/_U1Asset.m 2011-11-01 14:25:30 +0000 |
1941 | @@ -0,0 +1,98 @@ |
1942 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
1943 | +// Make changes to U1Asset.m instead. |
1944 | + |
1945 | +#import "_U1Asset.h" |
1946 | + |
1947 | +@implementation U1AssetID |
1948 | +@end |
1949 | + |
1950 | +@implementation _U1Asset |
1951 | + |
1952 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
1953 | + NSParameterAssert(moc_); |
1954 | + return [NSEntityDescription insertNewObjectForEntityForName:@"Asset" inManagedObjectContext:moc_]; |
1955 | +} |
1956 | + |
1957 | ++ (NSString*)entityName { |
1958 | + return @"Asset"; |
1959 | +} |
1960 | + |
1961 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
1962 | + NSParameterAssert(moc_); |
1963 | + return [NSEntityDescription entityForName:@"Asset" inManagedObjectContext:moc_]; |
1964 | +} |
1965 | + |
1966 | +- (U1AssetID*)objectID { |
1967 | + return (U1AssetID*)[super objectID]; |
1968 | +} |
1969 | + |
1970 | ++ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { |
1971 | + NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; |
1972 | + |
1973 | + if ([key isEqualToString:@"generationValue"]) { |
1974 | + NSSet *affectingKey = [NSSet setWithObject:@"generation"]; |
1975 | + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; |
1976 | + } |
1977 | + |
1978 | + return keyPaths; |
1979 | +} |
1980 | + |
1981 | + |
1982 | + |
1983 | + |
1984 | +@dynamic filename; |
1985 | + |
1986 | + |
1987 | + |
1988 | + |
1989 | + |
1990 | + |
1991 | +@dynamic generation; |
1992 | + |
1993 | + |
1994 | + |
1995 | +- (int)generationValue { |
1996 | + NSNumber *result = [self generation]; |
1997 | + return [result intValue]; |
1998 | +} |
1999 | + |
2000 | +- (void)setGenerationValue:(int)value_ { |
2001 | + [self setGeneration:[NSNumber numberWithInt:value_]]; |
2002 | +} |
2003 | + |
2004 | +- (int)primitiveGenerationValue { |
2005 | + NSNumber *result = [self primitiveGeneration]; |
2006 | + return [result intValue]; |
2007 | +} |
2008 | + |
2009 | +- (void)setPrimitiveGenerationValue:(int)value_ { |
2010 | + [self setPrimitiveGeneration:[NSNumber numberWithInt:value_]]; |
2011 | +} |
2012 | + |
2013 | + |
2014 | + |
2015 | + |
2016 | + |
2017 | +@dynamic groupId; |
2018 | + |
2019 | + |
2020 | + |
2021 | + |
2022 | + |
2023 | + |
2024 | +@dynamic url; |
2025 | + |
2026 | + |
2027 | + |
2028 | + |
2029 | + |
2030 | + |
2031 | +@dynamic fileNode; |
2032 | + |
2033 | + |
2034 | + |
2035 | + |
2036 | + |
2037 | + |
2038 | + |
2039 | +@end |
2040 | |
2041 | === modified file 'Files/Generated/_U1FileNode.h' |
2042 | --- Files/Generated/_U1FileNode.h 2011-09-08 16:59:34 +0000 |
2043 | +++ Files/Generated/_U1FileNode.h 2011-11-01 14:25:30 +0000 |
2044 | @@ -4,6 +4,7 @@ |
2045 | #import <CoreData/CoreData.h> |
2046 | #import "U1Node.h" |
2047 | |
2048 | +@class U1Asset; |
2049 | |
2050 | |
2051 | |
2052 | @@ -54,6 +55,13 @@ |
2053 | |
2054 | |
2055 | |
2056 | +@property (nonatomic, retain) U1Asset* asset; |
2057 | + |
2058 | +//- (BOOL)validateAsset:(id*)value_ error:(NSError**)error_; |
2059 | + |
2060 | + |
2061 | + |
2062 | + |
2063 | @end |
2064 | |
2065 | @interface _U1FileNode (CoreDataGeneratedAccessors) |
2066 | @@ -87,4 +95,9 @@ |
2067 | |
2068 | |
2069 | |
2070 | + |
2071 | +- (U1Asset*)primitiveAsset; |
2072 | +- (void)setPrimitiveAsset:(U1Asset*)value; |
2073 | + |
2074 | + |
2075 | @end |
2076 | |
2077 | === modified file 'Files/Generated/_U1FileNode.m' |
2078 | --- Files/Generated/_U1FileNode.m 2011-09-08 16:59:34 +0000 |
2079 | +++ Files/Generated/_U1FileNode.m 2011-11-01 14:25:30 +0000 |
2080 | @@ -103,6 +103,10 @@ |
2081 | |
2082 | |
2083 | |
2084 | +@dynamic asset; |
2085 | + |
2086 | + |
2087 | + |
2088 | |
2089 | |
2090 | |
2091 | |
2092 | === modified file 'Files/Generated/_U1Volume.h' |
2093 | --- Files/Generated/_U1Volume.h 2011-09-08 16:59:34 +0000 |
2094 | +++ Files/Generated/_U1Volume.h 2011-11-01 14:25:30 +0000 |
2095 | @@ -2,6 +2,7 @@ |
2096 | // Make changes to U1Volume.h instead. |
2097 | |
2098 | #import <CoreData/CoreData.h> |
2099 | +#import "U1Node.h" |
2100 | |
2101 | |
2102 | |
2103 | @@ -9,7 +10,7 @@ |
2104 | @interface U1VolumeID : NSManagedObjectID {} |
2105 | @end |
2106 | |
2107 | -@interface _U1Volume : NSManagedObject {} |
2108 | +@interface _U1Volume : U1Node {} |
2109 | + (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_; |
2110 | + (NSString*)entityName; |
2111 | + (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_; |
2112 | @@ -18,6 +19,14 @@ |
2113 | |
2114 | |
2115 | |
2116 | +@property (nonatomic, retain) NSString *nodePath; |
2117 | + |
2118 | + |
2119 | +//- (BOOL)validateNodePath:(id*)value_ error:(NSError**)error_; |
2120 | + |
2121 | + |
2122 | + |
2123 | + |
2124 | |
2125 | @end |
2126 | |
2127 | @@ -28,4 +37,10 @@ |
2128 | @interface _U1Volume (CoreDataGeneratedPrimitiveAccessors) |
2129 | |
2130 | |
2131 | +- (NSString*)primitiveNodePath; |
2132 | +- (void)setPrimitiveNodePath:(NSString*)value; |
2133 | + |
2134 | + |
2135 | + |
2136 | + |
2137 | @end |
2138 | |
2139 | === modified file 'Files/Generated/_U1Volume.m' |
2140 | --- Files/Generated/_U1Volume.m 2011-09-08 16:59:34 +0000 |
2141 | +++ Files/Generated/_U1Volume.m 2011-11-01 14:25:30 +0000 |
2142 | @@ -36,6 +36,13 @@ |
2143 | |
2144 | |
2145 | |
2146 | +@dynamic nodePath; |
2147 | + |
2148 | + |
2149 | + |
2150 | + |
2151 | + |
2152 | + |
2153 | |
2154 | |
2155 | |
2156 | |
2157 | === added file 'Files/NSDictionary+U1Additions.h' |
2158 | --- Files/NSDictionary+U1Additions.h 1970-01-01 00:00:00 +0000 |
2159 | +++ Files/NSDictionary+U1Additions.h 2011-11-01 14:25:30 +0000 |
2160 | @@ -0,0 +1,23 @@ |
2161 | +// |
2162 | +// Copyright 2011 Canonical Ltd. |
2163 | +// |
2164 | +// This program is free software: you can redistribute it and/or modify it |
2165 | +// under the terms of the GNU Affero General Public License version 3, |
2166 | +// as published by the Free Software Foundation. |
2167 | +// |
2168 | +// This program is distributed in the hope that it will be useful, but |
2169 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
2170 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2171 | +// PURPOSE. See the GNU Affero General Public License for more details. |
2172 | +// |
2173 | +// You should have received a copy of the GNU Affero General Public License |
2174 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
2175 | + |
2176 | +#import <Foundation/Foundation.h> |
2177 | + |
2178 | + |
2179 | +@interface NSDictionary (U1Additions) |
2180 | + |
2181 | +- (id)nonNullValueForKey:(NSString*)key; |
2182 | + |
2183 | +@end |
2184 | |
2185 | === added file 'Files/NSDictionary+U1Additions.m' |
2186 | --- Files/NSDictionary+U1Additions.m 1970-01-01 00:00:00 +0000 |
2187 | +++ Files/NSDictionary+U1Additions.m 2011-11-01 14:25:30 +0000 |
2188 | @@ -0,0 +1,29 @@ |
2189 | +// |
2190 | +// Copyright 2011 Canonical Ltd. |
2191 | +// |
2192 | +// This program is free software: you can redistribute it and/or modify it |
2193 | +// under the terms of the GNU Affero General Public License version 3, |
2194 | +// as published by the Free Software Foundation. |
2195 | +// |
2196 | +// This program is distributed in the hope that it will be useful, but |
2197 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
2198 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2199 | +// PURPOSE. See the GNU Affero General Public License for more details. |
2200 | +// |
2201 | +// You should have received a copy of the GNU Affero General Public License |
2202 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
2203 | + |
2204 | +#import "NSDictionary+U1Additions.h" |
2205 | + |
2206 | + |
2207 | +@implementation NSDictionary (U1Additions) |
2208 | + |
2209 | +- (id)nonNullValueForKey:(NSString*)key; |
2210 | +{ |
2211 | + id value = [self valueForKey:key]; |
2212 | + if (value == [NSNull null]) |
2213 | + return nil; |
2214 | + return value; |
2215 | +} |
2216 | + |
2217 | +@end |
2218 | |
2219 | === added file 'Files/U1Asset.h' |
2220 | --- Files/U1Asset.h 1970-01-01 00:00:00 +0000 |
2221 | +++ Files/U1Asset.h 2011-11-01 14:25:30 +0000 |
2222 | @@ -0,0 +1,5 @@ |
2223 | +#import "_U1Asset.h" |
2224 | + |
2225 | +@interface U1Asset : _U1Asset {} |
2226 | +// Custom logic goes here. |
2227 | +@end |
2228 | |
2229 | === added file 'Files/U1Asset.m' |
2230 | --- Files/U1Asset.m 1970-01-01 00:00:00 +0000 |
2231 | +++ Files/U1Asset.m 2011-11-01 14:25:30 +0000 |
2232 | @@ -0,0 +1,7 @@ |
2233 | +#import "U1Asset.h" |
2234 | + |
2235 | +@implementation U1Asset |
2236 | + |
2237 | +// Custom logic goes here. |
2238 | + |
2239 | +@end |
2240 | |
2241 | === added file 'Files/U1AssetUploadOperation.h' |
2242 | --- Files/U1AssetUploadOperation.h 1970-01-01 00:00:00 +0000 |
2243 | +++ Files/U1AssetUploadOperation.h 2011-11-01 14:25:30 +0000 |
2244 | @@ -0,0 +1,32 @@ |
2245 | +// |
2246 | +// Copyright 2011 Canonical Ltd. |
2247 | +// |
2248 | +// This program is free software: you can redistribute it and/or modify it |
2249 | +// under the terms of the GNU Affero General Public License version 3, |
2250 | +// as published by the Free Software Foundation. |
2251 | +// |
2252 | +// This program is distributed in the hope that it will be useful, but |
2253 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
2254 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2255 | +// PURPOSE. See the GNU Affero General Public License for more details. |
2256 | +// |
2257 | +// You should have received a copy of the GNU Affero General Public License |
2258 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
2259 | + |
2260 | +#import <Foundation/Foundation.h> |
2261 | +#import <AssetsLibrary/AssetsLibrary.h> |
2262 | + |
2263 | +@class U1Asset; |
2264 | +@class U1FolderNode; |
2265 | + |
2266 | +@interface U1AssetUploadOperation : NSOperation { |
2267 | +@private |
2268 | + |
2269 | +} |
2270 | +@property (retain) ALAssetRepresentation *representation; |
2271 | +@property (retain) U1Asset *asset; |
2272 | +@property (retain) U1FolderNode *folder; |
2273 | +@property (retain) NSString *filename; |
2274 | +@property (retain) NSString *mimetype; |
2275 | +@property (retain) NSError *error; |
2276 | +@end |
2277 | |
2278 | === added file 'Files/U1AssetUploadOperation.m' |
2279 | --- Files/U1AssetUploadOperation.m 1970-01-01 00:00:00 +0000 |
2280 | +++ Files/U1AssetUploadOperation.m 2011-11-01 14:25:30 +0000 |
2281 | @@ -0,0 +1,103 @@ |
2282 | +// |
2283 | +// Copyright 2011 Canonical Ltd. |
2284 | +// |
2285 | +// This program is free software: you can redistribute it and/or modify it |
2286 | +// under the terms of the GNU Affero General Public License version 3, |
2287 | +// as published by the Free Software Foundation. |
2288 | +// |
2289 | +// This program is distributed in the hope that it will be useful, but |
2290 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
2291 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2292 | +// PURPOSE. See the GNU Affero General Public License for more details. |
2293 | +// |
2294 | +// You should have received a copy of the GNU Affero General Public License |
2295 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
2296 | + |
2297 | +#import "U1AssetUploadOperation.h" |
2298 | +#import "U1Asset.h" |
2299 | +#import "U1FilesClient.h" |
2300 | +#import "U1FileNode.h" |
2301 | +#import "U1FolderNode.h" |
2302 | + |
2303 | +@interface U1AssetUploadOperation () |
2304 | +@property (getter=isExecuting) BOOL executing; |
2305 | +@property (getter=isFinished) BOOL finished; |
2306 | +- (void)finishExecuting; |
2307 | +@end |
2308 | + |
2309 | +@implementation U1AssetUploadOperation |
2310 | + |
2311 | +@synthesize executing, finished, asset, representation, folder, filename, mimetype, error; |
2312 | + |
2313 | +- (id)init |
2314 | +{ |
2315 | + self = [super init]; |
2316 | + if (self) { |
2317 | + // Initialization code here. |
2318 | + } |
2319 | + |
2320 | + return self; |
2321 | +} |
2322 | + |
2323 | +- (BOOL)isConcurrent; |
2324 | +{ |
2325 | + return YES; |
2326 | +} |
2327 | + |
2328 | +- (void)finishExecuting; |
2329 | +{ |
2330 | + [self willChangeValueForKey:@"isExecuting"]; |
2331 | + [self willChangeValueForKey:@"isFinished"]; |
2332 | + self.finished = YES; |
2333 | + self.executing = NO; |
2334 | + [self didChangeValueForKey:@"isFinished"]; |
2335 | + [self didChangeValueForKey:@"isExecuting"]; |
2336 | +// [UONetworkStatusCoordinator removeNetworkActivity]; |
2337 | +} |
2338 | + |
2339 | +- (void)start; |
2340 | +{ |
2341 | + [self willChangeValueForKey:@"isExecuting"]; |
2342 | + self.executing = YES; |
2343 | + [self didChangeValueForKey:@"isExecuting"]; |
2344 | + |
2345 | + U1FilesClient *filesClient = [U1FilesClient sharedFilesClient]; |
2346 | + |
2347 | + // if the file already exists at that resourcePath, skip it. In the future, we should do stuff like test that the remote resource's size is the same as our size, and do the right thing accordingly, but I'm not sure what that is right now. |
2348 | + |
2349 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
2350 | + [filesClient fetchFileWithResourcePath:[[self.folder resourcePath] stringByAppendingPathComponent:self.filename] completionBlock:^(U1Node *node, NSError *error) { |
2351 | + if (node.generation == nil) |
2352 | + { |
2353 | + Byte *buffer = (Byte*)malloc(self.representation.size); |
2354 | + NSUInteger length = [self.representation getBytes:buffer fromOffset:0 length:self.representation.size error:nil]; |
2355 | + NSData *assetData = [NSData dataWithBytesNoCopy:buffer length:length freeWhenDone:YES]; |
2356 | + |
2357 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
2358 | + [filesClient uploadContentData:assetData |
2359 | + toFolder:self.folder |
2360 | + withResourceName:self.filename |
2361 | + withContentType:self.mimetype |
2362 | + progressBlock:^(long long bytesUploaded, long long totalBytes) { |
2363 | + // dispatch_async(dispatch_get_main_queue(), ^(void){ |
2364 | + // NSLog(@"Uploaded %lld of %lld for %@", bytesUploaded, totalBytes, self.filename); |
2365 | + // }); |
2366 | + } completionBlock:^(U1FileNode *updatedNode, NSError *uploadError) { |
2367 | + self.error = uploadError; |
2368 | + [self finishExecuting]; |
2369 | + }]; |
2370 | + }); |
2371 | + } |
2372 | + else { |
2373 | + [self finishExecuting]; |
2374 | + } |
2375 | + }]; |
2376 | + }); |
2377 | +} |
2378 | + |
2379 | +- (void)dealloc |
2380 | +{ |
2381 | + [super dealloc]; |
2382 | +} |
2383 | + |
2384 | +@end |
2385 | |
2386 | === modified file 'Files/U1ByteSizeValueTransformer.m' |
2387 | --- Files/U1ByteSizeValueTransformer.m 2011-08-31 14:56:30 +0000 |
2388 | +++ Files/U1ByteSizeValueTransformer.m 2011-11-01 14:25:30 +0000 |
2389 | @@ -29,7 +29,7 @@ |
2390 | if (![value isKindOfClass:[NSNumber class]]) |
2391 | return nil; |
2392 | |
2393 | - CGFloat size = (CGFloat)[value unsignedIntValue]; |
2394 | + double size = [value doubleValue]; |
2395 | NSUInteger suffixIndex = 0; |
2396 | while (size > 1024.f && ++suffixIndex < sizeof(suffixes)) |
2397 | { |
2398 | |
2399 | === modified file 'Files/U1DataRepository.h' |
2400 | --- Files/U1DataRepository.h 2011-09-08 16:59:34 +0000 |
2401 | +++ Files/U1DataRepository.h 2011-11-01 14:25:30 +0000 |
2402 | @@ -20,12 +20,16 @@ |
2403 | |
2404 | |
2405 | @interface U1DataRepository : NSObject |
2406 | - |
2407 | ++ (U1DataRepository*)sharedDataRepository; |
2408 | - (id)initWithStoreURL:(NSURL*)storeURL; |
2409 | - (BOOL)save:(NSError**)error; |
2410 | |
2411 | - (U1Node*)nodeWithResourcePath:(NSString*)resourcePath; |
2412 | |
2413 | +//- (void)fetchResultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors completionBlock:(void(^)(NSArray *results, NSError *error))completionBlock; |
2414 | + |
2415 | +- (NSArray*)resultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error; |
2416 | + |
2417 | - (void)dispatchBlockWithManagedObjectContext:(void(^)(NSManagedObjectContext *context))block; |
2418 | |
2419 | - (void)dispatchAsyncBlockWithManagedObjectContext:(void(^)(NSManagedObjectContext *context))block; |
2420 | |
2421 | === modified file 'Files/U1DataRepository.m' |
2422 | --- Files/U1DataRepository.m 2011-09-08 16:59:34 +0000 |
2423 | +++ Files/U1DataRepository.m 2011-11-01 14:25:30 +0000 |
2424 | @@ -19,6 +19,7 @@ |
2425 | |
2426 | #import "U1Node.h" |
2427 | |
2428 | +static U1DataRepository *sharedDataRepository = nil; |
2429 | |
2430 | @interface U1DataRepository () |
2431 | |
2432 | @@ -35,6 +36,18 @@ |
2433 | |
2434 | @synthesize model, mainContext, storeCoordinator; |
2435 | |
2436 | ++ (U1DataRepository*)sharedDataRepository; |
2437 | +{ |
2438 | + if (sharedDataRepository == nil) |
2439 | + { |
2440 | + NSURL *cachesDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory |
2441 | + inDomains:NSUserDomainMask] lastObject]; |
2442 | + NSURL *storeURL = [NSURL URLWithString:@"U1Files.sqlite" relativeToURL:cachesDirectory]; |
2443 | + sharedDataRepository = [[self alloc] initWithStoreURL:storeURL]; |
2444 | + } |
2445 | + return sharedDataRepository; |
2446 | +} |
2447 | + |
2448 | - (id)initWithStoreURL:(NSURL*)storeURL; |
2449 | { |
2450 | if (!(self = [super init])) |
2451 | @@ -93,6 +106,16 @@ |
2452 | return node; |
2453 | } |
2454 | |
2455 | +//- (void)fetchResultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors completionBlock:(void(^)(NSArray *results, NSError *error))completionBlock; |
2456 | +//{ |
2457 | +// |
2458 | +//} |
2459 | + |
2460 | +- (NSArray*)resultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error; |
2461 | +{ |
2462 | + return [self fetchEntitiesForClass:entityClass inContext:self.mainContext withPredicate:predicate sortDescriptors:sortDescriptors error:error]; |
2463 | +} |
2464 | + |
2465 | - (NSArray*)fetchEntitiesForClass:(Class)class inContext:(NSManagedObjectContext*)context withPredicate:(NSPredicate*)predicate sortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error; |
2466 | { |
2467 | NSParameterAssert(class != nil); |
2468 | |
2469 | === modified file 'Files/U1FileNode.m' |
2470 | --- Files/U1FileNode.m 2011-09-08 16:59:34 +0000 |
2471 | +++ Files/U1FileNode.m 2011-11-01 14:25:30 +0000 |
2472 | @@ -21,11 +21,9 @@ |
2473 | - (void)updatePropertiesFromJSONDictionary:(NSDictionary*)jsonDictionary; |
2474 | { |
2475 | [super updatePropertiesFromJSONDictionary:jsonDictionary]; |
2476 | - self.size = [[jsonDictionary objectForKey:@"size"] copy]; |
2477 | - self.isPublic = [[jsonDictionary objectForKey:@"is_public"] copy]; |
2478 | - NSString *url = [jsonDictionary objectForKey:@"public_url"]; |
2479 | - if (url != (id)[NSNull null]) |
2480 | - self.publicURLString = [url copy]; |
2481 | + self.size = [jsonDictionary nonNullValueForKey:@"size"]; |
2482 | + self.isPublic = [jsonDictionary nonNullValueForKey:@"is_public"]; |
2483 | + self.publicURLString = [jsonDictionary nonNullValueForKey:@"public_url"]; |
2484 | } |
2485 | |
2486 | - (BOOL)isFile; |
2487 | |
2488 | === modified file 'Files/U1FilePreviewViewController.h' |
2489 | --- Files/U1FilePreviewViewController.h 2011-09-27 14:36:00 +0000 |
2490 | +++ Files/U1FilePreviewViewController.h 2011-11-01 14:25:30 +0000 |
2491 | @@ -18,7 +18,7 @@ |
2492 | @class U1FilesClient, U1FileNode; |
2493 | |
2494 | |
2495 | -@interface U1FilePreviewViewController : UIViewController |
2496 | +@interface U1FilePreviewViewController : UIViewController <UITextFieldDelegate> |
2497 | |
2498 | @property (nonatomic, retain, readonly) IBOutlet UIView *loadingContainerView; |
2499 | @property (nonatomic, retain, readonly) IBOutlet UIImageView *iconImageView; |
2500 | @@ -29,6 +29,7 @@ |
2501 | @property (nonatomic, retain, readonly) IBOutlet UILabel *modifiedLabel; |
2502 | @property (nonatomic, retain, readonly) IBOutlet UIToolbar *toolbar; |
2503 | @property (nonatomic, retain, readonly) IBOutlet UITextView *publicURLLabel; |
2504 | +@property (nonatomic, retain, readonly) IBOutlet UITextField *renameTextField; |
2505 | |
2506 | @property (readonly, retain) U1FileNode *node; |
2507 | @property (retain) U1FilesClient *filesClient; |
2508 | |
2509 | === modified file 'Files/U1FilePreviewViewController.m' |
2510 | --- Files/U1FilePreviewViewController.m 2011-09-27 14:36:00 +0000 |
2511 | +++ Files/U1FilePreviewViewController.m 2011-11-01 14:25:30 +0000 |
2512 | @@ -31,6 +31,8 @@ |
2513 | @property (nonatomic, retain) U1LocalFileInfo *fileInfo; |
2514 | |
2515 | @property (retain) UIBarButtonItem *publishItem; |
2516 | +@property (retain) UIBarButtonItem *renameItem; |
2517 | +@property (retain) UIBarButtonItem *deleteItem; |
2518 | @property (retain) UIBarButtonItem *downloadItem; |
2519 | @property (retain) UIBarButtonItem *previewItem; |
2520 | @property (retain) UIBarButtonItem *openInItem; |
2521 | @@ -48,8 +50,8 @@ |
2522 | |
2523 | @implementation U1FilePreviewViewController |
2524 | |
2525 | -@synthesize loadingContainerView, iconImageView, nameLabel, loadingActivityView, sizeLabel, createdLabel, modifiedLabel, toolbar, publicURLLabel; |
2526 | -@synthesize node, docController, filesClient, contentURL, fileInfo, publishItem, downloadItem, previewItem, openInItem, downloadProgressItem, downloadProgressView; |
2527 | +@synthesize loadingContainerView, iconImageView, nameLabel, loadingActivityView, sizeLabel, createdLabel, modifiedLabel, toolbar, publicURLLabel, renameTextField; |
2528 | +@synthesize node, docController, filesClient, contentURL, fileInfo, publishItem, renameItem, deleteItem, downloadItem, previewItem, openInItem, downloadProgressItem, downloadProgressView; |
2529 | |
2530 | NSDateFormatter *modificationDateFormatter(void) |
2531 | { |
2532 | @@ -78,6 +80,7 @@ |
2533 | self = [super initWithNibName:@"U1FilePreviewViewController" bundle:nil]; |
2534 | if (self == nil) |
2535 | return nil; |
2536 | + filesClient = [U1FilesClient sharedFilesClient]; |
2537 | self.node = theNode; |
2538 | self.title = [node.path lastPathComponent]; |
2539 | |
2540 | @@ -95,6 +98,8 @@ |
2541 | [titleLabel release]; |
2542 | |
2543 | publishItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"ic_act_publish_file"] style:UIBarButtonItemStylePlain target:self action:@selector(publishItem:)]; |
2544 | + renameItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemOrganize target:self action:@selector(renameItem:)]; |
2545 | + deleteItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"218-trash2"] style:UIBarButtonItemStylePlain target:self action:@selector(deleteItem:)]; |
2546 | downloadItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"265-download"] style:UIBarButtonItemStylePlain target:self action:@selector(downloadItem:)]; |
2547 | previewItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"04-eye"] style:UIBarButtonItemStylePlain target:self action:@selector(showPreview:)]; |
2548 | openInItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(openIn:)]; |
2549 | @@ -121,7 +126,10 @@ |
2550 | [filesClient release]; |
2551 | [toolbar release]; |
2552 | [publicURLLabel release]; |
2553 | + [renameTextField release]; |
2554 | [publishItem release]; |
2555 | + [renameItem release]; |
2556 | + [deleteItem release]; |
2557 | [downloadItem release]; |
2558 | [previewItem release]; |
2559 | [openInItem release]; |
2560 | @@ -170,6 +178,10 @@ |
2561 | [self flexibleSpaceItem], |
2562 | self.publishItem, |
2563 | [self fixedSpaceItemWithWidth:32.f], |
2564 | + self.renameItem, |
2565 | + [self fixedSpaceItemWithWidth:32.f], |
2566 | + self.deleteItem, |
2567 | + [self fixedSpaceItemWithWidth:32.f], |
2568 | self.previewItem, |
2569 | [self fixedSpaceItemWithWidth:32.f], |
2570 | self.openInItem, |
2571 | @@ -182,6 +194,10 @@ |
2572 | [self flexibleSpaceItem], |
2573 | self.publishItem, |
2574 | [self fixedSpaceItemWithWidth:32.f], |
2575 | + self.renameItem, |
2576 | + [self fixedSpaceItemWithWidth:32.f], |
2577 | + self.deleteItem, |
2578 | + [self fixedSpaceItemWithWidth:32.f], |
2579 | self.downloadItem, |
2580 | [self flexibleSpaceItem], |
2581 | nil]; |
2582 | @@ -200,9 +216,27 @@ |
2583 | [modifiedLabel release], modifiedLabel = nil; |
2584 | [toolbar release], toolbar = nil; |
2585 | [publicURLLabel release], publicURLLabel = nil; |
2586 | + [renameTextField release], renameTextField = nil; |
2587 | [super viewDidUnload]; |
2588 | } |
2589 | |
2590 | +- (void)setEditing:(BOOL)editing animated:(BOOL)animated; |
2591 | +{ |
2592 | + [super setEditing:editing animated:animated]; |
2593 | + if (editing) |
2594 | + { |
2595 | + [self.renameTextField setText:self.title]; |
2596 | + [self.renameTextField setHidden:NO]; |
2597 | + [self.nameLabel setHidden:YES]; |
2598 | + [self.renameTextField becomeFirstResponder]; |
2599 | + } |
2600 | + else |
2601 | + { |
2602 | + [self.renameTextField setHidden:YES]; |
2603 | + [self.nameLabel setHidden:NO]; |
2604 | + } |
2605 | +} |
2606 | + |
2607 | - (IBAction)publishItem:(UIBarButtonItem*)sender; |
2608 | { |
2609 | if ([self.node isPublicValue]) |
2610 | @@ -225,6 +259,19 @@ |
2611 | } |
2612 | } |
2613 | |
2614 | +- (IBAction)renameItem:(UIBarButtonItem*)sender; |
2615 | +{ |
2616 | + [self setEditing:YES animated:YES]; |
2617 | +} |
2618 | + |
2619 | +- (IBAction)deleteItem:(UIBarButtonItem*)sender; |
2620 | +{ |
2621 | + [self.filesClient deleteNode:self.node completionBlock:^(NSError *error) { |
2622 | + |
2623 | + }]; |
2624 | + [self.navigationController popViewControllerAnimated:YES]; |
2625 | +} |
2626 | + |
2627 | - (IBAction)downloadItem:(UIBarButtonItem*)sender; |
2628 | { |
2629 | self.fileInfo = [self.filesClient downloadFileForNode:self.node completionBlock:^(NSError *error) { |
2630 | @@ -337,4 +384,33 @@ |
2631 | return [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease]; |
2632 | } |
2633 | |
2634 | +- (BOOL)textFieldShouldReturn:(UITextField *)textField; |
2635 | +{ |
2636 | + [textField endEditing:NO]; |
2637 | +// [textField resignFirstResponder]; |
2638 | + return YES; |
2639 | +} |
2640 | + |
2641 | +- (void)textFieldDidEndEditing:(UITextField *)textField; |
2642 | +{ |
2643 | + NSString *newName = [self.renameTextField text]; |
2644 | + |
2645 | + [self setEditing:NO animated:YES]; |
2646 | + |
2647 | + if (!newName) |
2648 | + return; |
2649 | + |
2650 | + [[U1FilesClient sharedFilesClient] renameNode:self.node toName:newName completionBlock:^(U1Node *newNode, NSError *error) { |
2651 | + |
2652 | + if (!error) |
2653 | + { |
2654 | + self.title = [node.path lastPathComponent]; |
2655 | + UILabel *titleLabel = (UILabel*)[self.navigationItem titleView]; |
2656 | + [titleLabel setText:self.title]; |
2657 | + [titleLabel sizeToFit]; |
2658 | + [self.nameLabel setText:self.title]; |
2659 | + } |
2660 | + }]; |
2661 | +} |
2662 | + |
2663 | @end |
2664 | |
2665 | === modified file 'Files/U1FilePreviewViewController.xib' |
2666 | --- Files/U1FilePreviewViewController.xib 2011-09-27 14:36:00 +0000 |
2667 | +++ Files/U1FilePreviewViewController.xib 2011-11-01 14:25:30 +0000 |
2668 | @@ -1,34 +1,32 @@ |
2669 | <?xml version="1.0" encoding="UTF-8"?> |
2670 | <archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10"> |
2671 | <data> |
2672 | - <int key="IBDocument.SystemTarget">1056</int> |
2673 | + <int key="IBDocument.SystemTarget">1280</int> |
2674 | <string key="IBDocument.SystemVersion">10K549</string> |
2675 | - <string key="IBDocument.InterfaceBuilderVersion">1306</string> |
2676 | + <string key="IBDocument.InterfaceBuilderVersion">1938</string> |
2677 | <string key="IBDocument.AppKitVersion">1038.36</string> |
2678 | <string key="IBDocument.HIToolboxVersion">461.00</string> |
2679 | <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> |
2680 | <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
2681 | - <string key="NS.object.0">301</string> |
2682 | + <string key="NS.object.0">933</string> |
2683 | </object> |
2684 | <object class="NSArray" key="IBDocument.IntegratedClassDependencies"> |
2685 | <bool key="EncodedWithXMLCoder">YES</bool> |
2686 | + <string>IBProxyObject</string> |
2687 | + <string>IBUIImageView</string> |
2688 | + <string>IBUILabel</string> |
2689 | + <string>IBUIToolbar</string> |
2690 | + <string>IBUITextField</string> |
2691 | <string>IBUITextView</string> |
2692 | - <string>IBUIToolbar</string> |
2693 | - <string>IBUIImageView</string> |
2694 | <string>IBUIView</string> |
2695 | - <string>IBUILabel</string> |
2696 | - <string>IBProxyObject</string> |
2697 | </object> |
2698 | <object class="NSArray" key="IBDocument.PluginDependencies"> |
2699 | <bool key="EncodedWithXMLCoder">YES</bool> |
2700 | <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
2701 | </object> |
2702 | <object class="NSMutableDictionary" key="IBDocument.Metadata"> |
2703 | - <bool key="EncodedWithXMLCoder">YES</bool> |
2704 | - <object class="NSArray" key="dict.sortedKeys" id="0"> |
2705 | - <bool key="EncodedWithXMLCoder">YES</bool> |
2706 | - </object> |
2707 | - <reference key="dict.values" ref="0"/> |
2708 | + <string key="NS.key.0">PluginDependencyRecalculationVersion</string> |
2709 | + <integer value="1" key="NS.object.0"/> |
2710 | </object> |
2711 | <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000"> |
2712 | <bool key="EncodedWithXMLCoder">YES</bool> |
2713 | @@ -83,18 +81,13 @@ |
2714 | <string key="NSFrame">{{118, 20}, {182, 78}}</string> |
2715 | <reference key="NSSuperview" ref="959604046"/> |
2716 | <reference key="NSWindow"/> |
2717 | - <reference key="NSNextKeyView" ref="526184231"/> |
2718 | + <reference key="NSNextKeyView" ref="1038751454"/> |
2719 | <bool key="IBUIOpaque">NO</bool> |
2720 | <bool key="IBUIClipsSubviews">YES</bool> |
2721 | <int key="IBUIContentMode">7</int> |
2722 | <bool key="IBUIUserInteractionEnabled">NO</bool> |
2723 | <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
2724 | <string key="IBUIText"/> |
2725 | - <object class="NSFont" key="IBUIFont"> |
2726 | - <string key="NSName">HelveticaNeue-Bold</string> |
2727 | - <double key="NSSize">17</double> |
2728 | - <int key="NSfFlags">16</int> |
2729 | - </object> |
2730 | <object class="NSColor" key="IBUITextColor" id="995516164"> |
2731 | <int key="NSColorSpace">1</int> |
2732 | <bytes key="NSRGB">MCAwIDAAA</bytes> |
2733 | @@ -104,6 +97,17 @@ |
2734 | <bool key="IBUIAdjustsFontSizeToFit">NO</bool> |
2735 | <float key="IBUIMinimumFontSize">10</float> |
2736 | <int key="IBUINumberOfLines">2</int> |
2737 | + <object class="IBUIFontDescription" key="IBUIFontDescription"> |
2738 | + <string key="name">HelveticaNeue-Bold</string> |
2739 | + <string key="family">Helvetica Neue</string> |
2740 | + <int key="traits">2</int> |
2741 | + <double key="pointSize">17</double> |
2742 | + </object> |
2743 | + <object class="NSFont" key="IBUIFont"> |
2744 | + <string key="NSName">HelveticaNeue-Bold</string> |
2745 | + <double key="NSSize">17</double> |
2746 | + <int key="NSfFlags">16</int> |
2747 | + </object> |
2748 | </object> |
2749 | <object class="IBUILabel" id="526184231"> |
2750 | <reference key="NSNextResponder" ref="959604046"/> |
2751 | @@ -118,11 +122,6 @@ |
2752 | <bool key="IBUIUserInteractionEnabled">NO</bool> |
2753 | <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
2754 | <string key="IBUIText">size</string> |
2755 | - <object class="NSFont" key="IBUIFont" id="1064584347"> |
2756 | - <string key="NSName">HelveticaNeue</string> |
2757 | - <double key="NSSize">14</double> |
2758 | - <int key="NSfFlags">16</int> |
2759 | - </object> |
2760 | <object class="NSColor" key="IBUITextColor" id="994737462"> |
2761 | <int key="NSColorSpace">3</int> |
2762 | <bytes key="NSWhite">MC4zMzMzMzMzMzMzAA</bytes> |
2763 | @@ -131,6 +130,17 @@ |
2764 | <int key="IBUIBaselineAdjustment">1</int> |
2765 | <float key="IBUIMinimumFontSize">10</float> |
2766 | <int key="IBUITextAlignment">2</int> |
2767 | + <object class="IBUIFontDescription" key="IBUIFontDescription" id="823461873"> |
2768 | + <string key="name">HelveticaNeue</string> |
2769 | + <string key="family">Helvetica Neue</string> |
2770 | + <int key="traits">0</int> |
2771 | + <double key="pointSize">14</double> |
2772 | + </object> |
2773 | + <object class="NSFont" key="IBUIFont" id="754417662"> |
2774 | + <string key="NSName">HelveticaNeue-Medium</string> |
2775 | + <double key="NSSize">14</double> |
2776 | + <int key="NSfFlags">16</int> |
2777 | + </object> |
2778 | </object> |
2779 | <object class="IBUILabel" id="383512508"> |
2780 | <reference key="NSNextResponder" ref="959604046"/> |
2781 | @@ -145,12 +155,13 @@ |
2782 | <bool key="IBUIUserInteractionEnabled">NO</bool> |
2783 | <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
2784 | <string key="IBUIText">created</string> |
2785 | - <reference key="IBUIFont" ref="1064584347"/> |
2786 | <reference key="IBUITextColor" ref="994737462"/> |
2787 | <nil key="IBUIHighlightedColor"/> |
2788 | <int key="IBUIBaselineAdjustment">1</int> |
2789 | <float key="IBUIMinimumFontSize">10</float> |
2790 | <int key="IBUITextAlignment">2</int> |
2791 | + <reference key="IBUIFontDescription" ref="823461873"/> |
2792 | + <reference key="IBUIFont" ref="754417662"/> |
2793 | </object> |
2794 | <object class="IBUILabel" id="426088224"> |
2795 | <reference key="NSNextResponder" ref="959604046"/> |
2796 | @@ -165,12 +176,13 @@ |
2797 | <bool key="IBUIUserInteractionEnabled">NO</bool> |
2798 | <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
2799 | <string key="IBUIText"/> |
2800 | - <reference key="IBUIFont" ref="1064584347"/> |
2801 | <reference key="IBUITextColor" ref="995516164"/> |
2802 | <nil key="IBUIHighlightedColor"/> |
2803 | <int key="IBUIBaselineAdjustment">1</int> |
2804 | <bool key="IBUIAdjustsFontSizeToFit">NO</bool> |
2805 | <float key="IBUIMinimumFontSize">10</float> |
2806 | + <reference key="IBUIFontDescription" ref="823461873"/> |
2807 | + <reference key="IBUIFont" ref="754417662"/> |
2808 | </object> |
2809 | <object class="IBUILabel" id="546780773"> |
2810 | <reference key="NSNextResponder" ref="959604046"/> |
2811 | @@ -185,12 +197,13 @@ |
2812 | <bool key="IBUIUserInteractionEnabled">NO</bool> |
2813 | <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
2814 | <string key="IBUIText"/> |
2815 | - <reference key="IBUIFont" ref="1064584347"/> |
2816 | <reference key="IBUITextColor" ref="995516164"/> |
2817 | <nil key="IBUIHighlightedColor"/> |
2818 | <int key="IBUIBaselineAdjustment">1</int> |
2819 | <bool key="IBUIAdjustsFontSizeToFit">NO</bool> |
2820 | <float key="IBUIMinimumFontSize">10</float> |
2821 | + <reference key="IBUIFontDescription" ref="823461873"/> |
2822 | + <reference key="IBUIFont" ref="754417662"/> |
2823 | </object> |
2824 | <object class="IBUILabel" id="256323477"> |
2825 | <reference key="NSNextResponder" ref="959604046"/> |
2826 | @@ -205,12 +218,13 @@ |
2827 | <bool key="IBUIUserInteractionEnabled">NO</bool> |
2828 | <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
2829 | <string key="IBUIText">modified</string> |
2830 | - <reference key="IBUIFont" ref="1064584347"/> |
2831 | <reference key="IBUITextColor" ref="994737462"/> |
2832 | <nil key="IBUIHighlightedColor"/> |
2833 | <int key="IBUIBaselineAdjustment">1</int> |
2834 | <float key="IBUIMinimumFontSize">10</float> |
2835 | <int key="IBUITextAlignment">2</int> |
2836 | + <reference key="IBUIFontDescription" ref="823461873"/> |
2837 | + <reference key="IBUIFont" ref="754417662"/> |
2838 | </object> |
2839 | <object class="IBUILabel" id="968704124"> |
2840 | <reference key="NSNextResponder" ref="959604046"/> |
2841 | @@ -225,12 +239,13 @@ |
2842 | <bool key="IBUIUserInteractionEnabled">NO</bool> |
2843 | <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
2844 | <string key="IBUIText"/> |
2845 | - <reference key="IBUIFont" ref="1064584347"/> |
2846 | <reference key="IBUITextColor" ref="995516164"/> |
2847 | <nil key="IBUIHighlightedColor"/> |
2848 | <int key="IBUIBaselineAdjustment">1</int> |
2849 | <bool key="IBUIAdjustsFontSizeToFit">NO</bool> |
2850 | <float key="IBUIMinimumFontSize">10</float> |
2851 | + <reference key="IBUIFontDescription" ref="823461873"/> |
2852 | + <reference key="IBUIFont" ref="754417662"/> |
2853 | </object> |
2854 | <object class="IBUILabel" id="221780367"> |
2855 | <reference key="NSNextResponder" ref="959604046"/> |
2856 | @@ -245,12 +260,13 @@ |
2857 | <bool key="IBUIUserInteractionEnabled">NO</bool> |
2858 | <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
2859 | <string key="IBUIText">public URL</string> |
2860 | - <reference key="IBUIFont" ref="1064584347"/> |
2861 | <reference key="IBUITextColor" ref="994737462"/> |
2862 | <nil key="IBUIHighlightedColor"/> |
2863 | <int key="IBUIBaselineAdjustment">1</int> |
2864 | <float key="IBUIMinimumFontSize">10</float> |
2865 | <int key="IBUITextAlignment">2</int> |
2866 | + <reference key="IBUIFontDescription" ref="823461873"/> |
2867 | + <reference key="IBUIFont" ref="754417662"/> |
2868 | </object> |
2869 | <object class="IBUITextView" id="395268767"> |
2870 | <reference key="NSNextResponder" ref="959604046"/> |
2871 | @@ -272,12 +288,46 @@ |
2872 | <bool key="IBUIShowsVerticalScrollIndicator">NO</bool> |
2873 | <bool key="IBUIEditable">NO</bool> |
2874 | <string key="IBUIText"/> |
2875 | - <reference key="IBUIFont" ref="1064584347"/> |
2876 | <object class="IBUITextInputTraits" key="IBUITextInputTraits"> |
2877 | <int key="IBUIAutocapitalizationType">2</int> |
2878 | <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
2879 | </object> |
2880 | <int key="IBUIDataDetectorTypes">2</int> |
2881 | + <reference key="IBUIFontDescription" ref="823461873"/> |
2882 | + <reference key="IBUIFont" ref="754417662"/> |
2883 | + </object> |
2884 | + <object class="IBUITextField" id="1038751454"> |
2885 | + <reference key="NSNextResponder" ref="959604046"/> |
2886 | + <int key="NSvFlags">-2147483356</int> |
2887 | + <string key="NSFrame">{{118, 20}, {182, 78}}</string> |
2888 | + <reference key="NSSuperview" ref="959604046"/> |
2889 | + <reference key="NSWindow"/> |
2890 | + <reference key="NSNextKeyView" ref="526184231"/> |
2891 | + <bool key="IBUIOpaque">NO</bool> |
2892 | + <bool key="IBUIClipsSubviews">YES</bool> |
2893 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
2894 | + <int key="IBUIContentVerticalAlignment">0</int> |
2895 | + <string key="IBUIText"/> |
2896 | + <object class="NSColor" key="IBUITextColor"> |
2897 | + <int key="NSColorSpace">3</int> |
2898 | + <bytes key="NSWhite">MAA</bytes> |
2899 | + <reference key="NSCustomColorSpace" ref="838192903"/> |
2900 | + </object> |
2901 | + <bool key="IBUIAdjustsFontSizeToFit">YES</bool> |
2902 | + <float key="IBUIMinimumFontSize">17</float> |
2903 | + <object class="IBUITextInputTraits" key="IBUITextInputTraits"> |
2904 | + <int key="IBUIReturnKeyType">9</int> |
2905 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
2906 | + </object> |
2907 | + <object class="IBUIFontDescription" key="IBUIFontDescription"> |
2908 | + <int key="type">2</int> |
2909 | + <double key="pointSize">17</double> |
2910 | + </object> |
2911 | + <object class="NSFont" key="IBUIFont"> |
2912 | + <string key="NSName">Helvetica-Bold</string> |
2913 | + <double key="NSSize">17</double> |
2914 | + <int key="NSfFlags">16</int> |
2915 | + </object> |
2916 | </object> |
2917 | </object> |
2918 | <string key="NSFrameSize">{320, 372}</string> |
2919 | @@ -401,13 +451,31 @@ |
2920 | </object> |
2921 | <int key="connectionID">46</int> |
2922 | </object> |
2923 | + <object class="IBConnectionRecord"> |
2924 | + <object class="IBCocoaTouchOutletConnection" key="connection"> |
2925 | + <string key="label">renameTextField</string> |
2926 | + <reference key="source" ref="372490531"/> |
2927 | + <reference key="destination" ref="1038751454"/> |
2928 | + </object> |
2929 | + <int key="connectionID">48</int> |
2930 | + </object> |
2931 | + <object class="IBConnectionRecord"> |
2932 | + <object class="IBCocoaTouchOutletConnection" key="connection"> |
2933 | + <string key="label">delegate</string> |
2934 | + <reference key="source" ref="1038751454"/> |
2935 | + <reference key="destination" ref="372490531"/> |
2936 | + </object> |
2937 | + <int key="connectionID">49</int> |
2938 | + </object> |
2939 | </object> |
2940 | <object class="IBMutableOrderedSet" key="objectRecords"> |
2941 | <object class="NSArray" key="orderedObjects"> |
2942 | <bool key="EncodedWithXMLCoder">YES</bool> |
2943 | <object class="IBObjectRecord"> |
2944 | <int key="objectID">0</int> |
2945 | - <reference key="object" ref="0"/> |
2946 | + <object class="NSArray" key="object" id="0"> |
2947 | + <bool key="EncodedWithXMLCoder">YES</bool> |
2948 | + </object> |
2949 | <reference key="children" ref="1000"/> |
2950 | <nil key="parent"/> |
2951 | </object> |
2952 | @@ -448,6 +516,7 @@ |
2953 | <reference ref="221780367"/> |
2954 | <reference ref="749932571"/> |
2955 | <reference ref="395268767"/> |
2956 | + <reference ref="1038751454"/> |
2957 | </object> |
2958 | <reference key="parent" ref="191373211"/> |
2959 | <string key="objectName">Info View</string> |
2960 | @@ -524,6 +593,11 @@ |
2961 | <reference key="object" ref="395268767"/> |
2962 | <reference key="parent" ref="959604046"/> |
2963 | </object> |
2964 | + <object class="IBObjectRecord"> |
2965 | + <int key="objectID">47</int> |
2966 | + <reference key="object" ref="1038751454"/> |
2967 | + <reference key="parent" ref="959604046"/> |
2968 | + </object> |
2969 | </object> |
2970 | </object> |
2971 | <object class="NSMutableDictionary" key="flattenedProperties"> |
2972 | @@ -531,8 +605,9 @@ |
2973 | <object class="NSArray" key="dict.sortedKeys"> |
2974 | <bool key="EncodedWithXMLCoder">YES</bool> |
2975 | <string>-1.CustomClassName</string> |
2976 | + <string>-1.IBPluginDependency</string> |
2977 | <string>-2.CustomClassName</string> |
2978 | - <string>1.IBEditorWindowLastContentRect</string> |
2979 | + <string>-2.IBPluginDependency</string> |
2980 | <string>1.IBPluginDependency</string> |
2981 | <string>17.IBPluginDependency</string> |
2982 | <string>21.IBPluginDependency</string> |
2983 | @@ -546,13 +621,16 @@ |
2984 | <string>40.IBPluginDependency</string> |
2985 | <string>41.IBPluginDependency</string> |
2986 | <string>45.IBPluginDependency</string> |
2987 | + <string>47.IBPluginDependency</string> |
2988 | <string>5.IBPluginDependency</string> |
2989 | </object> |
2990 | <object class="NSMutableArray" key="dict.values"> |
2991 | <bool key="EncodedWithXMLCoder">YES</bool> |
2992 | <string>U1FilePreviewViewController</string> |
2993 | + <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
2994 | <string>UIResponder</string> |
2995 | - <string>{{556, 412}, {320, 480}}</string> |
2996 | + <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
2997 | + <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
2998 | <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
2999 | <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
3000 | <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
3001 | @@ -581,7 +659,7 @@ |
3002 | <reference key="dict.values" ref="0"/> |
3003 | </object> |
3004 | <nil key="sourceID"/> |
3005 | - <int key="maxID">46</int> |
3006 | + <int key="maxID">49</int> |
3007 | </object> |
3008 | <object class="IBClassDescriber" key="IBDocument.Classes"> |
3009 | <object class="NSMutableArray" key="referencedPartialClassDescriptions"> |
3010 | @@ -600,6 +678,7 @@ |
3011 | <string>modifiedLabel</string> |
3012 | <string>nameLabel</string> |
3013 | <string>publicURLLabel</string> |
3014 | + <string>renameTextField</string> |
3015 | <string>sizeLabel</string> |
3016 | <string>toolbar</string> |
3017 | </object> |
3018 | @@ -612,6 +691,7 @@ |
3019 | <string>UILabel</string> |
3020 | <string>UILabel</string> |
3021 | <string>UITextView</string> |
3022 | + <string>UITextField</string> |
3023 | <string>UILabel</string> |
3024 | <string>UIToolbar</string> |
3025 | </object> |
3026 | @@ -627,6 +707,7 @@ |
3027 | <string>modifiedLabel</string> |
3028 | <string>nameLabel</string> |
3029 | <string>publicURLLabel</string> |
3030 | + <string>renameTextField</string> |
3031 | <string>sizeLabel</string> |
3032 | <string>toolbar</string> |
3033 | </object> |
3034 | @@ -661,6 +742,10 @@ |
3035 | <string key="candidateClassName">UITextView</string> |
3036 | </object> |
3037 | <object class="IBToOneOutletInfo"> |
3038 | + <string key="name">renameTextField</string> |
3039 | + <string key="candidateClassName">UITextField</string> |
3040 | + </object> |
3041 | + <object class="IBToOneOutletInfo"> |
3042 | <string key="name">sizeLabel</string> |
3043 | <string key="candidateClassName">UILabel</string> |
3044 | </object> |
3045 | @@ -685,6 +770,6 @@ |
3046 | </object> |
3047 | <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> |
3048 | <int key="IBDocument.defaultPropertyAccessControl">3</int> |
3049 | - <string key="IBCocoaTouchPluginVersion">301</string> |
3050 | + <string key="IBCocoaTouchPluginVersion">933</string> |
3051 | </data> |
3052 | </archive> |
3053 | |
3054 | === modified file 'Files/U1Files.xcdatamodeld/.xccurrentversion' |
3055 | --- Files/U1Files.xcdatamodeld/.xccurrentversion 2011-09-08 16:59:34 +0000 |
3056 | +++ Files/U1Files.xcdatamodeld/.xccurrentversion 2011-11-01 14:25:30 +0000 |
3057 | @@ -3,6 +3,6 @@ |
3058 | <plist version="1.0"> |
3059 | <dict> |
3060 | <key>_XCCurrentVersionName</key> |
3061 | - <string>U1Files.xcdatamodel</string> |
3062 | + <string>U1Files 1.0-9.xcdatamodel</string> |
3063 | </dict> |
3064 | </plist> |
3065 | |
3066 | === added directory 'Files/U1Files.xcdatamodeld/U1Files 1.0-3.xcdatamodel' |
3067 | === added file 'Files/U1Files.xcdatamodeld/U1Files 1.0-3.xcdatamodel/elements' |
3068 | Binary files Files/U1Files.xcdatamodeld/U1Files 1.0-3.xcdatamodel/elements 1970-01-01 00:00:00 +0000 and Files/U1Files.xcdatamodeld/U1Files 1.0-3.xcdatamodel/elements 2011-11-01 14:25:30 +0000 differ |
3069 | === added file 'Files/U1Files.xcdatamodeld/U1Files 1.0-3.xcdatamodel/layout' |
3070 | Binary files Files/U1Files.xcdatamodeld/U1Files 1.0-3.xcdatamodel/layout 1970-01-01 00:00:00 +0000 and Files/U1Files.xcdatamodeld/U1Files 1.0-3.xcdatamodel/layout 2011-11-01 14:25:30 +0000 differ |
3071 | === added directory 'Files/U1Files.xcdatamodeld/U1Files 1.0-9.xcdatamodel' |
3072 | === added file 'Files/U1Files.xcdatamodeld/U1Files 1.0-9.xcdatamodel/elements' |
3073 | Binary files Files/U1Files.xcdatamodeld/U1Files 1.0-9.xcdatamodel/elements 1970-01-01 00:00:00 +0000 and Files/U1Files.xcdatamodeld/U1Files 1.0-9.xcdatamodel/elements 2011-11-01 14:25:30 +0000 differ |
3074 | === added file 'Files/U1Files.xcdatamodeld/U1Files 1.0-9.xcdatamodel/layout' |
3075 | Binary files Files/U1Files.xcdatamodeld/U1Files 1.0-9.xcdatamodel/layout 1970-01-01 00:00:00 +0000 and Files/U1Files.xcdatamodeld/U1Files 1.0-9.xcdatamodel/layout 2011-11-01 14:25:30 +0000 differ |
3076 | === modified file 'Files/U1Files.xcdatamodeld/U1Files.xcdatamodel/elements' |
3077 | Binary files Files/U1Files.xcdatamodeld/U1Files.xcdatamodel/elements 2011-09-08 16:59:34 +0000 and Files/U1Files.xcdatamodeld/U1Files.xcdatamodel/elements 2011-11-01 14:25:30 +0000 differ |
3078 | === modified file 'Files/U1Files.xcdatamodeld/U1Files.xcdatamodel/layout' |
3079 | Binary files Files/U1Files.xcdatamodeld/U1Files.xcdatamodel/layout 2011-09-08 16:59:34 +0000 and Files/U1Files.xcdatamodeld/U1Files.xcdatamodel/layout 2011-11-01 14:25:30 +0000 differ |
3080 | === modified file 'Files/U1FilesClient.h' |
3081 | --- Files/U1FilesClient.h 2011-09-27 14:36:00 +0000 |
3082 | +++ Files/U1FilesClient.h 2011-11-01 14:25:30 +0000 |
3083 | @@ -16,7 +16,7 @@ |
3084 | #import <Foundation/Foundation.h> |
3085 | |
3086 | @class NSFetchedResultsController; |
3087 | -@class U1Node, U1FileNode, U1FolderNode, U1NodeChildrenResultSet, U1LocalFileInfo; |
3088 | +@class U1Node, U1FileNode, U1FolderNode, U1NodeChildrenResultSet, U1Volume, U1LocalFileInfo; |
3089 | @class U1DataRepository, U1FilesService; |
3090 | |
3091 | |
3092 | @@ -25,11 +25,19 @@ |
3093 | @property (retain) U1DataRepository *dataRepository; |
3094 | @property (retain) U1FilesService *filesService; |
3095 | |
3096 | -- (id)fetchNodeWithResourcePath:(NSString*)nodePath completionBlock:(void(^)(U1Node *node, NSFetchedResultsController *childrenResultsController, NSError *error))completionBlock; |
3097 | ++ (U1FilesClient *)sharedFilesClient; |
3098 | + |
3099 | +- (id)accountInfoWithCompletionBlock:(void(^)(NSDictionary *accountInfo, NSError *error))completionBlock; |
3100 | +- (id)volumesWithCompletionBlock:(void(^)(U1Volume *rootVolume, NSFetchedResultsController *cloudFoldersResultsController, NSError *error))completionBlock; |
3101 | +- (id)fetchFolderWithResourcePath:(NSString*)nodePath completionBlock:(void(^)(U1Node *node, NSFetchedResultsController *childrenResultsController, NSError *error))completionBlock; |
3102 | +- (id)fetchFileWithResourcePath:(NSString*)nodePath completionBlock:(void(^)(U1Node *node, NSError *error))completionBlock; |
3103 | +- (id)renameNode:(U1Node*)node toName:(NSString*)newName completionBlock:(void(^)(U1Node *node, NSError *error))completionBlock; |
3104 | - (id)deleteNode:(U1Node*)node completionBlock:(void(^)(NSError *error))completionBlock; |
3105 | -- (id)uploadContentData:(NSData*)contentData toFolder:(U1FolderNode*)folderNode withResourceName:(NSString*)resourceName progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(U1FileNode *updatedNode, NSError *error))completionBlock; |
3106 | +- (id)uploadContentData:(NSData*)contentData toFolder:(U1FolderNode*)folderNode withResourceName:(NSString*)resourceName withContentType:(NSString*)contentType progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(U1FileNode *updatedNode, NSError *error))completionBlock; |
3107 | - (id)publishNode:(U1FileNode*)node completionBlock:(void(^)(U1FileNode *node, NSError *error))completionBlock; |
3108 | - (id)unpublishNode:(U1FileNode*)node completionBlock:(void(^)(U1FileNode *node, NSError *error))completionBlock; |
3109 | +- (id)createFolderNamed:(NSString*)name inFolder:(U1FolderNode*)folderNode completionBlock:(void(^)(U1FolderNode *newFolderNode, NSError *error))completionBlock; |
3110 | +- (id)createVolumeAtPath:(NSString*)folderPath completionBlock:(void(^)(U1Volume *volume, NSError *error))completionBlock; |
3111 | - (BOOL)isNodeSavedLocally:(U1FileNode*)node; |
3112 | - (U1LocalFileInfo*)localInfoForNode:(U1FileNode*)node; |
3113 | |
3114 | |
3115 | === modified file 'Files/U1FilesClient.m' |
3116 | --- Files/U1FilesClient.m 2011-09-27 14:36:00 +0000 |
3117 | +++ Files/U1FilesClient.m 2011-11-01 14:25:30 +0000 |
3118 | @@ -23,66 +23,136 @@ |
3119 | #import "U1FolderNode.h" |
3120 | #import "U1LocalFileInfo.h" |
3121 | #import "U1Node.h" |
3122 | +#import "U1Volume.h" |
3123 | |
3124 | |
3125 | @interface U1FilesClient () |
3126 | - (NSURL*)fileURLForNode:(U1FileNode*)node; |
3127 | @end |
3128 | |
3129 | +static U1FilesClient *sharedFilesClient = nil; |
3130 | |
3131 | @implementation U1FilesClient |
3132 | |
3133 | @synthesize dataRepository, filesService; |
3134 | |
3135 | -- (void)dealloc; |
3136 | -{ |
3137 | - [dataRepository release]; |
3138 | - [filesService release]; |
3139 | - [super dealloc]; |
3140 | -} |
3141 | - |
3142 | -- (id)fetchNodeWithResourcePath:(NSString*)nodePath completionBlock:(void(^)(U1Node *node, NSFetchedResultsController *childrenResultsController, NSError *error))completionBlock; |
3143 | -{ |
3144 | - |
3145 | - U1FolderNode *node = (id)[self.dataRepository nodeWithResourcePath:nodePath]; |
3146 | - |
3147 | - // TODO: temporary, create node if doesn't exist |
3148 | ++ (U1FilesClient*)sharedFilesClient; |
3149 | +{ |
3150 | + if (sharedFilesClient == nil) |
3151 | + { |
3152 | + sharedFilesClient = [[self alloc] init]; |
3153 | + } |
3154 | + return sharedFilesClient; |
3155 | +} |
3156 | + |
3157 | +- (id)init; |
3158 | +{ |
3159 | + self = [super init]; |
3160 | + if (self == nil) |
3161 | + return nil; |
3162 | + dataRepository = [U1DataRepository sharedDataRepository]; |
3163 | + filesService = [U1FilesService sharedFilesService]; |
3164 | + return self; |
3165 | +} |
3166 | + |
3167 | +- (id)accountInfoWithCompletionBlock:(void(^)(NSDictionary *accountInfo, NSError *error))completionBlock; |
3168 | +{ |
3169 | + return [self.filesService accountInfoWithCompletionBlock:completionBlock]; |
3170 | +} |
3171 | + |
3172 | +- (id)volumesWithCompletionBlock:(void(^)(U1Volume *rootVolume, NSFetchedResultsController *cloudFoldersResultsController, NSError *error))completionBlock; |
3173 | +{ |
3174 | + NSParameterAssert(completionBlock != NULL); |
3175 | + |
3176 | + [self.filesService volumeInfoWithCompletionBlock:^(NSArray *volumeInfos, NSError *error) { |
3177 | + |
3178 | + __block U1Volume *rootVolume = nil; |
3179 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
3180 | + for (NSDictionary *volumeInfo in volumeInfos) |
3181 | + { |
3182 | + NSString *path = [volumeInfo objectForKey:@"path"]; |
3183 | + NSPredicate *p = [NSPredicate predicateWithFormat:@"path = %@", path]; |
3184 | + U1Volume *volume = [[self.dataRepository resultsForEntityClass:[U1Volume class] matchingPredicate:p withSortDescriptors:nil error:NULL] lastObject]; |
3185 | + if (!volume) |
3186 | + { |
3187 | + volume = [U1Volume insertInManagedObjectContext:context]; |
3188 | + } |
3189 | + [volume updatePropertiesFromJSONDictionary:volumeInfo]; |
3190 | + if ([volume.kind isEqualToString:@"root"]) |
3191 | + { |
3192 | + rootVolume = [volume retain]; |
3193 | + } |
3194 | + } |
3195 | + [context save:NULL]; |
3196 | + }]; |
3197 | + |
3198 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
3199 | + |
3200 | + NSFetchRequest *request = [[NSFetchRequest alloc] init]; |
3201 | + [request setEntity:[U1Volume entityInManagedObjectContext:context]]; |
3202 | + NSPredicate *p = [NSPredicate predicateWithFormat:@"kind = 'udf'"]; |
3203 | + [request setPredicate:p]; |
3204 | + NSArray *sortDescriptors = [NSArray arrayWithObjects: |
3205 | + [NSSortDescriptor sortDescriptorWithKey:@"resourcePath" ascending:YES selector:@selector(localizedStandardCompare:)], |
3206 | + nil]; |
3207 | + [request setSortDescriptors:sortDescriptors]; |
3208 | + NSFetchedResultsController *cloudFoldersResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:context sectionNameKeyPath:nil cacheName:nil]; |
3209 | + [request release]; |
3210 | + |
3211 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
3212 | + NSError *error = nil; |
3213 | + [cloudFoldersResultsController performFetch:&error]; |
3214 | + completionBlock(rootVolume, cloudFoldersResultsController, error); |
3215 | + [cloudFoldersResultsController release]; |
3216 | + [rootVolume release]; |
3217 | + }); |
3218 | + }]; |
3219 | + }]; |
3220 | + return nil; |
3221 | +} |
3222 | + |
3223 | +- (id)fetchFolderWithResourcePath:(NSString*)nodePath completionBlock:(void(^)(U1Node *node, NSFetchedResultsController *childrenResultsController, NSError *error))completionBlock; |
3224 | +{ |
3225 | + |
3226 | + __block U1FolderNode *node = [(id)[self.dataRepository nodeWithResourcePath:nodePath] retain]; |
3227 | + |
3228 | if (!node) |
3229 | { |
3230 | [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
3231 | - U1Node *newNode = [U1FolderNode insertInManagedObjectContext:context]; |
3232 | - newNode.resourcePath = nodePath; |
3233 | + node = [[U1FolderNode insertInManagedObjectContext:context] retain]; |
3234 | + node.resourcePath = nodePath; |
3235 | [context save:NULL]; |
3236 | }]; |
3237 | } |
3238 | - |
3239 | - node = (id)[self.dataRepository nodeWithResourcePath:nodePath]; |
3240 | |
3241 | [self.filesService infoForNodeAtResourcePath:node.resourcePath includeChildren:YES completionBlock:^(NSDictionary *nodeInfo, NSError *error) { |
3242 | - |
3243 | - [node updatePropertiesFromJSONDictionary:nodeInfo]; |
3244 | - |
3245 | - NSArray *childInfos = [nodeInfo objectForKey:@"children"]; |
3246 | - [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
3247 | |
3248 | - for (NSDictionary *childInfo in childInfos) |
3249 | - { |
3250 | - NSString *childResourcePath = [childInfo objectForKey:@"resource_path"]; |
3251 | - NSString *kind = [childInfo objectForKey:@"kind"]; |
3252 | - U1Node *childNode = [self.dataRepository nodeWithResourcePath:childResourcePath]; |
3253 | - if (!childNode) |
3254 | - { |
3255 | - if ([@"file" isEqualToString:kind]) |
3256 | - childNode = [U1FileNode insertInManagedObjectContext:context]; |
3257 | - else |
3258 | - childNode = [U1FolderNode insertInManagedObjectContext:context]; |
3259 | - } |
3260 | + if (error == nil) |
3261 | + { |
3262 | + [node updatePropertiesFromJSONDictionary:nodeInfo]; |
3263 | + |
3264 | + NSArray *childInfos = [nodeInfo objectForKey:@"children"]; |
3265 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
3266 | |
3267 | - [childNode updatePropertiesFromJSONDictionary:childInfo]; |
3268 | - childNode.parent = node; |
3269 | - } |
3270 | - [context save:NULL]; |
3271 | - }]; |
3272 | + for (NSDictionary *childInfo in childInfos) |
3273 | + { |
3274 | + NSString *childResourcePath = [childInfo objectForKey:@"resource_path"]; |
3275 | + NSString *kind = [childInfo objectForKey:@"kind"]; |
3276 | + U1Node *childNode = [self.dataRepository nodeWithResourcePath:childResourcePath]; |
3277 | + if (!childNode) |
3278 | + { |
3279 | + if ([@"file" isEqualToString:kind]) |
3280 | + childNode = [U1FileNode insertInManagedObjectContext:context]; |
3281 | + else |
3282 | + childNode = [U1FolderNode insertInManagedObjectContext:context]; |
3283 | + } |
3284 | + |
3285 | + [childNode updatePropertiesFromJSONDictionary:childInfo]; |
3286 | + childNode.parent = node; |
3287 | + } |
3288 | + [context save:NULL]; |
3289 | + }]; |
3290 | + } |
3291 | |
3292 | __block NSFetchedResultsController *resultsController = nil; |
3293 | [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
3294 | @@ -93,7 +163,7 @@ |
3295 | [request setPredicate:p]; |
3296 | NSArray *sortDescriptors = [NSArray arrayWithObjects: |
3297 | [NSSortDescriptor sortDescriptorWithKey:@"kind" ascending:YES], |
3298 | - [NSSortDescriptor sortDescriptorWithKey:@"resourcePath" ascending:YES selector:@selector(caseInsensitiveCompare:)], |
3299 | + [NSSortDescriptor sortDescriptorWithKey:@"resourcePath" ascending:YES selector:@selector(localizedStandardCompare:)], |
3300 | nil]; |
3301 | [request setSortDescriptors:sortDescriptors]; |
3302 | resultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:context sectionNameKeyPath:nil cacheName:nil]; |
3303 | @@ -106,12 +176,59 @@ |
3304 | [resultsController performFetch:&error]; |
3305 | completionBlock(node, resultsController, error); |
3306 | [resultsController release]; |
3307 | + [node release]; |
3308 | }); |
3309 | |
3310 | }]; |
3311 | return nil; |
3312 | } |
3313 | |
3314 | +- (id)fetchFileWithResourcePath:(NSString *)nodePath completionBlock:(void (^)(U1Node *, NSError *))completionBlock; |
3315 | +{ |
3316 | + __block U1FileNode *node = [(id)[self.dataRepository nodeWithResourcePath:nodePath] retain]; |
3317 | + |
3318 | + if (!node) |
3319 | + { |
3320 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
3321 | + node = [[U1FileNode insertInManagedObjectContext:context] retain]; |
3322 | + node.resourcePath = nodePath; |
3323 | + [context save:NULL]; |
3324 | + }]; |
3325 | + } |
3326 | + |
3327 | + |
3328 | + [self.filesService infoForNodeAtResourcePath:node.resourcePath includeChildren:NO completionBlock:^(NSDictionary *nodeInfo, NSError *error) { |
3329 | + if (error == nil) |
3330 | + { |
3331 | + [node updatePropertiesFromJSONDictionary:nodeInfo]; |
3332 | + } |
3333 | + }]; |
3334 | + |
3335 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
3336 | + NSError *error = nil; |
3337 | + completionBlock(node, error); |
3338 | + [node release]; |
3339 | + }); |
3340 | + |
3341 | + return nil; |
3342 | +} |
3343 | + |
3344 | +- (id)renameNode:(U1Node*)node toName:(NSString*)newName completionBlock:(void(^)(U1Node *node, NSError *error))completionBlock; |
3345 | +{ |
3346 | + NSParameterAssert(node != nil); |
3347 | + NSParameterAssert(newName != nil); |
3348 | + NSParameterAssert(completionBlock != NULL); |
3349 | + |
3350 | + NSString *newPath = [[node.path stringByDeletingLastPathComponent] stringByAppendingPathComponent:newName]; |
3351 | + return [self.filesService moveNodeAtResourcePath:node.resourcePath toPath:newPath withCompletionBlock:^(NSDictionary *nodeInfo, NSError *error) { |
3352 | + if (!error) |
3353 | + { |
3354 | + [node updatePropertiesFromJSONDictionary:nodeInfo]; |
3355 | + } |
3356 | + completionBlock(node, error); |
3357 | + }]; |
3358 | +} |
3359 | + |
3360 | - (id)deleteNode:(U1Node*)node completionBlock:(void(^)(NSError *error))completionBlock; |
3361 | { |
3362 | return [self.filesService deleteNodeAtResourcePath:node.resourcePath completionBlock:^(NSError *error) { |
3363 | @@ -126,7 +243,7 @@ |
3364 | }]; |
3365 | } |
3366 | |
3367 | -- (id)uploadContentData:(NSData*)contentData toFolder:(U1FolderNode*)folderNode withResourceName:(NSString*)resourceName progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(U1FileNode *updatedNode, NSError *error))completionBlock; |
3368 | +- (id)uploadContentData:(NSData*)contentData toFolder:(U1FolderNode*)folderNode withResourceName:(NSString*)resourceName withContentType:(NSString*)contentType progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(U1FileNode *updatedNode, NSError *error))completionBlock; |
3369 | { |
3370 | NSString *resourcePath = [folderNode.resourcePath stringByAppendingPathComponent:resourceName]; |
3371 | U1FileNode *node = (id)[self.dataRepository nodeWithResourcePath:resourcePath]; |
3372 | @@ -143,10 +260,19 @@ |
3373 | node = (id)[self.dataRepository nodeWithResourcePath:resourcePath]; |
3374 | } |
3375 | |
3376 | - return [self.filesService uploadContentData:contentData forNode:node progressBlock:progressBlock completionBlock:^(NSDictionary *updatedNodeInfo, NSError *error) { |
3377 | - |
3378 | - [node updatePropertiesFromJSONDictionary:updatedNodeInfo]; |
3379 | - completionBlock(node, error); |
3380 | + return [self.filesService uploadContentData:contentData forNode:node withContentType:contentType progressBlock:progressBlock completionBlock:^(NSDictionary *updatedNodeInfo, NSError *error) { |
3381 | + if (error != nil) |
3382 | + { |
3383 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
3384 | + [context deleteObject:node]; |
3385 | + }]; |
3386 | + completionBlock(nil, error); |
3387 | + } |
3388 | + else |
3389 | + { |
3390 | + [node updatePropertiesFromJSONDictionary:updatedNodeInfo]; |
3391 | + completionBlock(node, error); |
3392 | + } |
3393 | }]; |
3394 | } |
3395 | |
3396 | @@ -160,6 +286,42 @@ |
3397 | return [self.filesService unpublishNode:node completionBlock:completionBlock]; |
3398 | } |
3399 | |
3400 | +- (id)createFolderNamed:(NSString*)name inFolder:(U1FolderNode*)folderNode completionBlock:(void(^)(U1FolderNode *newFolderNode, NSError *error))completionBlock; |
3401 | +{ |
3402 | + NSString *resourcePath = folderNode.resourcePath; |
3403 | + resourcePath = [resourcePath stringByAppendingPathComponent:name]; |
3404 | + |
3405 | + U1FolderNode *node = (id)[self.dataRepository nodeWithResourcePath:resourcePath]; |
3406 | + if (!node) |
3407 | + { |
3408 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
3409 | + U1FolderNode *newNode = [U1FolderNode insertInManagedObjectContext:context]; |
3410 | + newNode.resourcePath = resourcePath; |
3411 | + newNode.kind = @"directory"; |
3412 | + newNode.contentPath = [folderNode.contentPath stringByAppendingPathComponent:name]; |
3413 | + newNode.parent = folderNode; |
3414 | + [context save:NULL]; |
3415 | + }]; |
3416 | + node = (id)[self.dataRepository nodeWithResourcePath:resourcePath]; |
3417 | + } |
3418 | + |
3419 | + return [self.filesService createFolderAtPath:resourcePath completionBlock:^(NSDictionary *nodeInfo, NSError *error) { |
3420 | + [node updatePropertiesFromJSONDictionary:nodeInfo]; |
3421 | + completionBlock(node, error); |
3422 | + }]; |
3423 | +} |
3424 | + |
3425 | +- (id)createVolumeAtPath:(NSString*)folderPath completionBlock:(void(^)(U1Volume *volume, NSError *error))completionBlock; |
3426 | +{ |
3427 | + return [self.filesService createVolumeAtPath:folderPath completionBlock:^(NSDictionary *volumeInfo, NSError *error) { |
3428 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
3429 | + U1Volume *volume = [U1Volume insertInManagedObjectContext:context]; |
3430 | + [volume updatePropertiesFromJSONDictionary:volumeInfo]; |
3431 | + completionBlock(volume, error); |
3432 | + }]; |
3433 | + }]; |
3434 | +} |
3435 | + |
3436 | - (BOOL)isNodeSavedLocally:(U1FileNode*)node; |
3437 | { |
3438 | NSString *contentPath = node.contentPath; |
3439 | |
3440 | === modified file 'Files/U1FilesService.h' |
3441 | --- Files/U1FilesService.h 2011-09-08 16:59:34 +0000 |
3442 | +++ Files/U1FilesService.h 2011-11-01 14:25:30 +0000 |
3443 | @@ -15,20 +15,25 @@ |
3444 | |
3445 | #import <Foundation/Foundation.h> |
3446 | |
3447 | -@class U1Node, U1FileNode; |
3448 | +@class U1Node, U1FileNode, U1FolderNode; |
3449 | |
3450 | |
3451 | @interface U1FilesService : NSObject |
3452 | |
3453 | -- (id)volumeInfoWithCompletionBlock:(void(^)(NSArray *volumeInfo, NSError *error))completionBlock; |
3454 | ++ (U1FilesService *)sharedFilesService; |
3455 | |
3456 | +- (id)accountInfoWithCompletionBlock:(void(^)(NSDictionary *accountInfo, NSError *error))completionBlock; |
3457 | +- (id)volumeInfoWithCompletionBlock:(void(^)(NSArray *volumeInfos, NSError *error))completionBlock; |
3458 | - (id)infoForNodeAtResourcePath:(NSString*)resourcePath includeChildren:(BOOL)includeChildren completionBlock:(void(^)(NSDictionary *node, NSError *error))completionBlock; |
3459 | - (id)infoForNode:(U1Node*)node includeChildren:(BOOL)includeChildren completionBlock:(void(^)(NSDictionary *node, NSError *error))completionBlock; |
3460 | - (id)contentForNode:(U1FileNode*)node progressBlock:(void(^)(long long bytesReceived, long long bytesExpected))progressBlock completionBlock:(void(^)(NSURL *contentURL))completionBlock; |
3461 | - (id)uploadContentAtURL:(NSURL*)contentURL forNode:(U1FileNode*)node progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(U1FileNode *updatedNode, NSError *error))completionBlock; |
3462 | -- (id)uploadContentData:(NSData*)contentData forNode:(U1FileNode*)node progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(NSDictionary *updatedNodeInfo, NSError *error))completionBlock; |
3463 | +- (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; |
3464 | +- (id)moveNodeAtResourcePath:(NSString*)resourcePath toPath:(NSString*)newPath withCompletionBlock:(void(^)(NSDictionary *nodeInfo, NSError *error))completionBlock; |
3465 | - (id)deleteNodeAtResourcePath:(NSString*)resourcePath completionBlock:(void(^)(NSError *error))completionBlock; |
3466 | - (id)publishNode:(U1FileNode*)node completionBlock:(void(^)(U1FileNode *node, NSError *error))completionBlock; |
3467 | - (id)unpublishNode:(U1FileNode*)node completionBlock:(void(^)(U1FileNode *node, NSError *error))completionBlock; |
3468 | +- (id)createFolderAtPath:(NSString*)folderPath completionBlock:(void(^)(NSDictionary *nodeInfo, NSError *error))completionBlock; |
3469 | +- (id)createVolumeAtPath:(NSString*)folderPath completionBlock:(void(^)(NSDictionary *volumeInfo, NSError *error))completionBlock; |
3470 | |
3471 | @end |
3472 | |
3473 | === modified file 'Files/U1FilesService.m' |
3474 | --- Files/U1FilesService.m 2011-09-27 14:36:00 +0000 |
3475 | +++ Files/U1FilesService.m 2011-11-01 14:25:30 +0000 |
3476 | @@ -17,17 +17,21 @@ |
3477 | |
3478 | #import "JSONKit.h" |
3479 | #import "OAuthConsumer.h" |
3480 | +#import "Reachability.h" |
3481 | |
3482 | #import "U1AccountManager.h" |
3483 | #import "U1HTTPRequestOperation.h" |
3484 | #import "U1Node.h" |
3485 | #import "U1FileNode.h" |
3486 | |
3487 | +static U1FilesService *sharedFilesService = nil; |
3488 | |
3489 | @interface U1FilesService () |
3490 | |
3491 | @property (retain) NSOperationQueue *networkQueue; |
3492 | +@property (retain) Reachability *reachability; |
3493 | |
3494 | +- (NSURL*)URLForVolumeWithPath:(NSString*)volumePath; |
3495 | - (NSURL*)URLForNode:(NSString*)nodePath includeChildren:(BOOL)includeChildren; |
3496 | - (id)execute:(NSString*)method toURL:(NSURL*)url withParameters:(NSDictionary*)parameters requestBody:(NSString*)body parseResponseBody:(BOOL)parseResponseBody completionBlock:(void(^)(id results, NSError *error))completionBlock; |
3497 | - (id)execute:(NSString*)method toURL:(NSURL*)url withParameters:(NSDictionary*)parameters requestData:(NSData*)bodyData contentType:(NSString*)contentType parseResponseBody:(BOOL)parseResponseBody completionBlock:(void(^)(id results, NSError *error))completionBlock; |
3498 | @@ -42,7 +46,16 @@ |
3499 | static NSString *const U1FilesServiceAPIVersion1 = @"/v1"; |
3500 | static NSString *const U1FilesServiceAPIContentRoot = @"https://files.one.ubuntu.com"; |
3501 | |
3502 | -@synthesize networkQueue; |
3503 | +@synthesize networkQueue, reachability; |
3504 | + |
3505 | ++ (U1FilesService*)sharedFilesService; |
3506 | +{ |
3507 | + if (sharedFilesService == nil) |
3508 | + { |
3509 | + sharedFilesService = [[self alloc] init]; |
3510 | + } |
3511 | + return sharedFilesService; |
3512 | +} |
3513 | |
3514 | - (id)init; |
3515 | { |
3516 | @@ -50,16 +63,31 @@ |
3517 | if (self == nil) |
3518 | return nil; |
3519 | networkQueue = [[NSOperationQueue alloc] init]; |
3520 | + reachability = [[Reachability reachabilityWithHostName:U1FilesServiceAPIContentRoot] retain]; |
3521 | + [reachability startNotifer]; |
3522 | return self; |
3523 | } |
3524 | |
3525 | - (void)dealloc; |
3526 | { |
3527 | [networkQueue release]; |
3528 | + [reachability stopNotifer]; |
3529 | + [reachability release]; |
3530 | [super dealloc]; |
3531 | } |
3532 | |
3533 | -- (id)volumeInfoWithCompletionBlock:(void(^)(NSArray *volumeInfo, NSError *error))completionBlock; |
3534 | +- (id)accountInfoWithCompletionBlock:(void(^)(NSDictionary *accountInfo, NSError *error))completionBlock; |
3535 | +{ |
3536 | + NSMutableString *urlString = [NSMutableString stringWithString:U1FilesServiceAPIBase]; |
3537 | + [urlString appendString:U1FilesServiceAPIPath]; |
3538 | + [urlString appendString:U1FilesServiceAPIVersion1]; |
3539 | + NSURL *rootURL = [NSURL URLWithString:urlString]; |
3540 | + return [self execute:@"GET" toURL:rootURL withParameters:nil requestBody:nil parseResponseBody:YES completionBlock:^(id results, NSError *error) { |
3541 | + completionBlock(results, error); |
3542 | + }]; |
3543 | +} |
3544 | + |
3545 | +- (id)volumeInfoWithCompletionBlock:(void(^)(NSArray *volumeInfos, NSError *error))completionBlock; |
3546 | { |
3547 | NSURL *volumesURL = [self URLForNode:@"/volumes" includeChildren:NO]; |
3548 | return [self execute:@"GET" toURL:volumesURL withParameters:nil requestBody:nil parseResponseBody:YES completionBlock:^(id results, NSError *error) { |
3549 | @@ -129,7 +157,9 @@ |
3550 | if (completionBlock) |
3551 | completionBlock(fileURL); |
3552 | }]; |
3553 | + [request release]; |
3554 | [self.networkQueue addOperation:httpOperation]; |
3555 | + [httpOperation release]; |
3556 | return nil; |
3557 | } |
3558 | |
3559 | @@ -144,10 +174,11 @@ |
3560 | [signatureProvider release]; |
3561 | |
3562 | [request setHTTPMethod:@"PUT"]; |
3563 | - [request setValue:@"application/octet-stream" forHTTPHeaderField:@"Content-Type"]; |
3564 | + [request setValue:@"image/jpeg" forHTTPHeaderField:@"Content-Type"]; |
3565 | [request prepare]; |
3566 | NSInputStream *contentStream = [[NSInputStream alloc] initWithURL:contentURL]; |
3567 | [request setHTTPBodyStream:contentStream]; |
3568 | + [contentStream release]; |
3569 | |
3570 | U1HTTPRequestOperationInMemoryDataCollector *collector = [U1HTTPRequestOperationInMemoryDataCollector new]; |
3571 | U1HTTPRequestOperation *httpOperation = [[U1HTTPRequestOperation alloc] initWithRequest:request dataCollector:collector]; |
3572 | @@ -158,16 +189,16 @@ |
3573 | // completionBlock(fileURL); |
3574 | }]; |
3575 | [self.networkQueue addOperation:httpOperation]; |
3576 | - |
3577 | + [httpOperation release]; |
3578 | return nil; |
3579 | } |
3580 | |
3581 | -- (id)uploadContentData:(NSData*)contentData forNode:(U1FileNode*)node progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlock:(void(^)(NSDictionary *updatedNodeInfo, NSError *error))completionBlock; |
3582 | +- (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; |
3583 | { |
3584 | NSString *contentPath = node.contentPath; |
3585 | NSURL *requestURL = [NSURL URLWithString:[[U1FilesServiceAPIContentRoot stringByAppendingPathComponent:contentPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; |
3586 | |
3587 | - [self execute:@"PUT" toURL:requestURL withParameters:nil requestData:contentData contentType:@"application/octet-stream" parseResponseBody:YES completionBlock:^(id results, NSError *error) { |
3588 | + [self execute:@"PUT" toURL:requestURL withParameters:nil requestData:contentData contentType:contentType parseResponseBody:YES completionBlock:^(id results, NSError *error) { |
3589 | |
3590 | completionBlock(results, error); |
3591 | }]; |
3592 | @@ -175,6 +206,19 @@ |
3593 | return nil; |
3594 | } |
3595 | |
3596 | +- (id)moveNodeAtResourcePath:(NSString*)resourcePath toPath:(NSString*)newPath withCompletionBlock:(void(^)(NSDictionary *nodeInfo, NSError *error))completionBlock; |
3597 | +{ |
3598 | + NSParameterAssert(resourcePath != nil); |
3599 | + NSParameterAssert(newPath != nil); |
3600 | + NSParameterAssert(completionBlock != NULL); |
3601 | + |
3602 | + NSURL *nodeURL = [self URLForNode:resourcePath includeChildren:NO]; |
3603 | + NSString *body = [NSString stringWithFormat:@"{\"path\": \"%@\"}", newPath]; |
3604 | + return [self execute:@"PUT" toURL:nodeURL withParameters:nil requestBody:body parseResponseBody:YES completionBlock:^(id results, NSError *error) { |
3605 | + completionBlock(results, error); |
3606 | + }]; |
3607 | +} |
3608 | + |
3609 | - (id)deleteNodeAtResourcePath:(NSString*)resourcePath completionBlock:(void(^)(NSError *error))completionBlock; |
3610 | { |
3611 | NSURL *nodeURL = [self URLForNode:resourcePath includeChildren:NO]; |
3612 | @@ -205,9 +249,44 @@ |
3613 | }]; |
3614 | } |
3615 | |
3616 | +- (id)createFolderAtPath:(NSString*)folderPath completionBlock:(void(^)(NSDictionary *nodeInfo, NSError *error))completionBlock; |
3617 | +{ |
3618 | + NSParameterAssert(folderPath != nil); |
3619 | + NSParameterAssert(completionBlock != NULL); |
3620 | + |
3621 | + NSURL *nodeURL = [self URLForNode:folderPath includeChildren:NO]; |
3622 | + return [self execute:@"PUT" toURL:nodeURL withParameters:nil requestBody:@"{\"kind\": \"directory\"}" parseResponseBody:YES completionBlock:^(id results, NSError *error) { |
3623 | + completionBlock(results, error); |
3624 | + }]; |
3625 | +} |
3626 | + |
3627 | +- (id)createVolumeAtPath:(NSString*)volumePath completionBlock:(void(^)(NSDictionary *volumeInfo, NSError *error))completionBlock; |
3628 | +{ |
3629 | + NSParameterAssert(volumePath != nil); |
3630 | + NSParameterAssert(completionBlock != NULL); |
3631 | + |
3632 | + NSURL *volumeURL = [self URLForVolumeWithPath:volumePath]; |
3633 | + return [self execute:@"PUT" toURL:volumeURL withParameters:nil requestBody:@"" parseResponseBody:YES completionBlock:^(id results, NSError *error) { |
3634 | + completionBlock(results, error); |
3635 | + }]; |
3636 | +} |
3637 | + |
3638 | |
3639 | #pragma mark Private Methods |
3640 | |
3641 | +- (NSURL*)URLForVolumeWithPath:(NSString*)volumePath; |
3642 | +{ |
3643 | + NSParameterAssert(volumePath != nil); |
3644 | + NSParameterAssert([volumePath hasPrefix:@"/"]); |
3645 | + |
3646 | + NSMutableString *urlString = [NSMutableString stringWithString:U1FilesServiceAPIBase]; |
3647 | + [urlString appendString:U1FilesServiceAPIPath]; |
3648 | + [urlString appendString:U1FilesServiceAPIVersion1]; |
3649 | + [urlString appendString:@"/volumes"]; |
3650 | + [urlString appendString:volumePath]; |
3651 | + return [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; |
3652 | +} |
3653 | + |
3654 | - (NSURL*)URLForNode:(NSString*)nodePath includeChildren:(BOOL)includeChildren; |
3655 | { |
3656 | NSMutableString *urlString = [NSMutableString stringWithString:U1FilesServiceAPIBase]; |
3657 | @@ -255,7 +334,7 @@ |
3658 | ![[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)] containsIndex:[response statusCode]]) |
3659 | { |
3660 | // TODO: semantic error messages |
3661 | - error = [NSError errorWithDomain:@"U1FilesServiceErrorDomain" code:0 userInfo:nil]; |
3662 | + error = [NSError errorWithDomain:@"U1FilesServiceErrorDomain" code:[response statusCode] userInfo:nil]; |
3663 | } |
3664 | if (!error && parseResponseBody) |
3665 | { |
3666 | |
3667 | === modified file 'Files/U1FolderNode.m' |
3668 | --- Files/U1FolderNode.m 2011-09-08 16:59:34 +0000 |
3669 | +++ Files/U1FolderNode.m 2011-11-01 14:25:30 +0000 |
3670 | @@ -21,7 +21,7 @@ |
3671 | - (void)updatePropertiesFromJSONDictionary:(NSDictionary*)jsonDictionary; |
3672 | { |
3673 | [super updatePropertiesFromJSONDictionary:jsonDictionary]; |
3674 | - self.hasChildren = [jsonDictionary objectForKey:@"has_children"]; |
3675 | + self.hasChildren = [jsonDictionary nonNullValueForKey:@"has_children"]; |
3676 | } |
3677 | |
3678 | - (BOOL)isFolder; |
3679 | |
3680 | === modified file 'Files/U1FolderViewController.m' |
3681 | --- Files/U1FolderViewController.m 2011-09-27 14:36:00 +0000 |
3682 | +++ Files/U1FolderViewController.m 2011-11-01 14:25:30 +0000 |
3683 | @@ -15,12 +15,14 @@ |
3684 | |
3685 | #import "U1FolderViewController.h" |
3686 | |
3687 | +#import <AssetsLibrary/AssetsLibrary.h> |
3688 | #import "U1ByteSizeValueTransformer.h" |
3689 | #import "U1FileNode.h" |
3690 | #import "U1FilesClient.h" |
3691 | #import "U1FolderItemCell.h" |
3692 | #import "U1FolderNode.h" |
3693 | #import "U1Node.h" |
3694 | +#import "U1UTIMapper.h" |
3695 | #import "UIActionSheet+U1Additions.h" |
3696 | |
3697 | |
3698 | @@ -48,8 +50,9 @@ |
3699 | if (!self) |
3700 | return nil; |
3701 | self.title = [theResourcePath lastPathComponent]; |
3702 | - self.resourcePath = [theResourcePath copy]; |
3703 | + self.resourcePath = theResourcePath; |
3704 | self.byteSizeTransformer = [[U1ByteSizeValueTransformer new] autorelease]; |
3705 | + filesClient = [U1FilesClient sharedFilesClient]; |
3706 | |
3707 | UIBarButtonItem *uploadItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(uploadImage:)]; |
3708 | [self.navigationItem setRightBarButtonItem:uploadItem]; |
3709 | @@ -74,7 +77,6 @@ |
3710 | - (void)dealloc; |
3711 | { |
3712 | [loadingCell release]; |
3713 | - [filesClient release]; |
3714 | [resourcePath release]; |
3715 | [node release]; |
3716 | [byteSizeTransformer release]; |
3717 | @@ -119,7 +121,7 @@ |
3718 | |
3719 | [actionSheet setTitle:[[childNode path] lastPathComponent]]; |
3720 | [actionSheet setDestructiveButtonIndex:[actionSheet addButtonWithTitle:@"Delete"]]; |
3721 | - // TODO: rename |
3722 | + NSInteger renameButtonIndex = [actionSheet addButtonWithTitle:@"Rename"]; |
3723 | NSInteger publishButtonIndex = -1; |
3724 | NSInteger copyURLButtonIndex = -1; |
3725 | if ([childNode isFile]) |
3726 | @@ -143,6 +145,10 @@ |
3727 | { |
3728 | [self deleteNodeAtIndexPath:self.pendingIndexPath]; |
3729 | } |
3730 | + else if (buttonIndex == renameButtonIndex) |
3731 | + { |
3732 | + NSLog(@"rename!"); // TODO: |
3733 | + } |
3734 | else if (buttonIndex == publishButtonIndex) |
3735 | { |
3736 | U1FileNode *fileNode = (id)childNode; |
3737 | @@ -182,20 +188,42 @@ |
3738 | |
3739 | [picker dismissModalViewControllerAnimated:YES]; |
3740 | |
3741 | -// NSURL *imageURL = [info objectForKey:UIImagePickerControllerReferenceURL]; |
3742 | - UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; |
3743 | + NSURL *imageURL = [info objectForKey:UIImagePickerControllerReferenceURL]; |
3744 | + ALAssetsLibrary *assetsLibrary = [[[ALAssetsLibrary alloc] init] autorelease]; |
3745 | + U1UTIMapper *utiMapper = [U1UTIMapper sharedU1UTIMapper]; |
3746 | |
3747 | - // TODO: pull date from ALAsset metadata |
3748 | - NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; |
3749 | - [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; |
3750 | - [dateFormatter setTimeStyle:NSDateFormatterMediumStyle]; |
3751 | - NSString *filename = [NSString stringWithFormat:@"Photo %@.png", [dateFormatter stringFromDate:[NSDate date]]]; |
3752 | + [assetsLibrary assetForURL:imageURL |
3753 | + resultBlock:^(ALAsset *asset) { |
3754 | + ALAssetRepresentation *representation = [asset defaultRepresentation]; |
3755 | + NSString *mimetype = [utiMapper MIMETypeForUTI:[representation UTI]]; |
3756 | + NSString *assetType = [asset valueForProperty:ALAssetPropertyType]; |
3757 | + NSDate *assetDate = [asset valueForProperty:ALAssetPropertyDate]; |
3758 | |
3759 | - [self.filesClient uploadContentData:UIImagePNGRepresentation(image) toFolder:self.node withResourceName:filename progressBlock:^(long long bytesUploaded, long long totalBytes) { |
3760 | - |
3761 | - } completionBlock:^(U1FileNode *updatedNode, NSError *error) { |
3762 | - |
3763 | - }]; |
3764 | + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; |
3765 | + [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; |
3766 | + [dateFormatter setTimeStyle:NSDateFormatterMediumStyle]; |
3767 | + |
3768 | + NSString *ext = [utiMapper extensionForUTI:[representation UTI]]; |
3769 | + NSString *filename = [NSString stringWithFormat:@"%@ %@.%@", assetType, [dateFormatter stringFromDate:assetDate], ext]; |
3770 | + [dateFormatter release]; |
3771 | + |
3772 | + Byte *buffer = (Byte*)malloc(representation.size); |
3773 | + NSUInteger length = [representation getBytes:buffer fromOffset:0 length:representation.size error:nil]; |
3774 | + NSData *assetData = [NSData dataWithBytesNoCopy:buffer length:length freeWhenDone:YES]; |
3775 | + |
3776 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
3777 | + [self.filesClient uploadContentData:assetData |
3778 | + toFolder:self.node |
3779 | + withResourceName:filename |
3780 | + withContentType:mimetype |
3781 | + progressBlock:^(long long bytesUploaded, long long totalBytes) {} |
3782 | + completionBlock:^(U1FileNode *updatedNode, NSError *uploadError) {} |
3783 | + ]; |
3784 | + }); |
3785 | + } failureBlock:^(NSError *error) { |
3786 | + NSLog(@"Error: %@", error); |
3787 | + }]; |
3788 | + |
3789 | } |
3790 | |
3791 | |
3792 | @@ -286,7 +314,7 @@ |
3793 | { |
3794 | NSParameterAssert(self.resourcePath != nil); |
3795 | |
3796 | - [self.filesClient fetchNodeWithResourcePath:self.resourcePath completionBlock:^(U1Node *theNode, NSFetchedResultsController *childrenResultsController, NSError *error) { |
3797 | + [self.filesClient fetchFolderWithResourcePath:self.resourcePath completionBlock:^(U1Node *theNode, NSFetchedResultsController *childrenResultsController, NSError *error) { |
3798 | |
3799 | self.node = (id)theNode; |
3800 | self.resultsController = childrenResultsController; |
3801 | |
3802 | === added file 'Files/U1LocalAssetsManager.h' |
3803 | --- Files/U1LocalAssetsManager.h 1970-01-01 00:00:00 +0000 |
3804 | +++ Files/U1LocalAssetsManager.h 2011-11-01 14:25:30 +0000 |
3805 | @@ -0,0 +1,33 @@ |
3806 | +// |
3807 | +// Copyright 2011 Canonical Ltd. |
3808 | +// |
3809 | +// This program is free software: you can redistribute it and/or modify it |
3810 | +// under the terms of the GNU Affero General Public License version 3, |
3811 | +// as published by the Free Software Foundation. |
3812 | +// |
3813 | +// This program is distributed in the hope that it will be useful, but |
3814 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
3815 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3816 | +// PURPOSE. See the GNU Affero General Public License for more details. |
3817 | +// |
3818 | +// You should have received a copy of the GNU Affero General Public License |
3819 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
3820 | + |
3821 | +#import <Foundation/Foundation.h> |
3822 | + |
3823 | +@class U1DataRepository; |
3824 | +@class U1Volume; |
3825 | +@class U1FileNode; |
3826 | + |
3827 | + |
3828 | +@interface U1LocalAssetsManager : NSObject |
3829 | +@property (retain) U1DataRepository *dataRepository; |
3830 | +@property (retain) NSMutableSet *localAssetsToUpload; |
3831 | +@property (retain) U1FolderNode *remoteUploadFolder; |
3832 | ++ (U1LocalAssetsManager *)sharedLocalAssetsManager; |
3833 | +- (int)numberOfAssets; |
3834 | +- (int)numberOfAssetsUploaded; |
3835 | +- (void)checkForNewAssets; |
3836 | +- (BOOL)isResourceUploading:(NSString *)resourcePath; |
3837 | +- (void)thumbnailForNode:(U1FileNode *)fileNode completionBlock:(void(^)(CGImageRef thumbnail))completionBlock; |
3838 | +@end |
3839 | |
3840 | === added file 'Files/U1LocalAssetsManager.m' |
3841 | --- Files/U1LocalAssetsManager.m 1970-01-01 00:00:00 +0000 |
3842 | +++ Files/U1LocalAssetsManager.m 2011-11-01 14:25:30 +0000 |
3843 | @@ -0,0 +1,354 @@ |
3844 | +// |
3845 | +// Copyright 2011 Canonical Ltd. |
3846 | +// |
3847 | +// This program is free software: you can redistribute it and/or modify it |
3848 | +// under the terms of the GNU Affero General Public License version 3, |
3849 | +// as published by the Free Software Foundation. |
3850 | +// |
3851 | +// This program is distributed in the hope that it will be useful, but |
3852 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
3853 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3854 | +// PURPOSE. See the GNU Affero General Public License for more details. |
3855 | +// |
3856 | +// You should have received a copy of the GNU Affero General Public License |
3857 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
3858 | + |
3859 | +#import <AssetsLibrary/AssetsLibrary.h> |
3860 | + |
3861 | +#import "Reachability.h" |
3862 | + |
3863 | +#import "U1Asset.h" |
3864 | +#import "U1DataRepository.h" |
3865 | +#import "U1LocalAssetsManager.h" |
3866 | +#import "U1AssetUploadOperation.h" |
3867 | +#import "U1FileNode.h" |
3868 | +#import "U1FilesClient.h" |
3869 | +#import "U1Volume.h" |
3870 | +#import "U1UTIMapper.h" |
3871 | + |
3872 | + |
3873 | +@interface U1LocalAssetsManager () |
3874 | +@property (retain) ALAssetsLibrary *assetsLibrary; |
3875 | +@property (retain) NSOperationQueue *uploadQueue; |
3876 | +- (void)walkAssetsInLibrary; |
3877 | +- (void)uploadRepresentation:(ALAssetRepresentation*)rep forAsset:(U1Asset*)asset withPriority:(NSOperationQueuePriority)priority; |
3878 | +- (NSString *)generateFilenameForAsset:(ALAsset *)asset; |
3879 | +- (U1FileNode *)createPendingFileNodeForResourcePath:(NSString *)resourcePath asset:(U1Asset *)asset; |
3880 | +- (void)processAssetBatch:(NSArray*)batch inGroup:(ALAssetsGroup *)group; |
3881 | +- (void)autoUploadSettingsChanged:(NSNotification*)notification; |
3882 | +@end |
3883 | + |
3884 | +static U1LocalAssetsManager *sharedLocalAssetsManager = nil; |
3885 | + |
3886 | +@implementation U1LocalAssetsManager |
3887 | + |
3888 | +@synthesize dataRepository, uploadQueue, localAssetsToUpload, remoteUploadFolder; |
3889 | +@synthesize assetsLibrary; |
3890 | + |
3891 | ++ (U1LocalAssetsManager *)sharedLocalAssetsManager; |
3892 | +{ |
3893 | + if (sharedLocalAssetsManager == nil) |
3894 | + { |
3895 | + sharedLocalAssetsManager = [[self alloc] init]; |
3896 | + } |
3897 | + return sharedLocalAssetsManager; |
3898 | +} |
3899 | + |
3900 | +- (id)init |
3901 | +{ |
3902 | + if (!(self = [super init])) |
3903 | + return nil; |
3904 | + |
3905 | + NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter]; |
3906 | + |
3907 | + assetsLibrary = [[ALAssetsLibrary alloc] init]; |
3908 | + [defaultCenter addObserver:self selector:@selector(libraryChanged:) name:ALAssetsLibraryChangedNotification object:assetsLibrary]; |
3909 | + [defaultCenter addObserver:self selector:@selector(autoUploadSettingsChanged:) name:NSUserDefaultsDidChangeNotification object:[NSUserDefaults standardUserDefaults]]; |
3910 | + dataRepository = [U1DataRepository sharedDataRepository]; |
3911 | + uploadQueue = [[NSOperationQueue alloc] init]; |
3912 | + [uploadQueue setMaxConcurrentOperationCount:4]; |
3913 | + self.localAssetsToUpload = [NSMutableSet set]; |
3914 | + [defaultCenter addObserver:self selector:@selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil]; |
3915 | + return self; |
3916 | + |
3917 | +} |
3918 | + |
3919 | +- (void)dealloc |
3920 | +{ |
3921 | + [[NSNotificationCenter defaultCenter] removeObserver:self]; |
3922 | + [assetsLibrary release]; |
3923 | + [super dealloc]; |
3924 | +} |
3925 | + |
3926 | +- (void)checkForNewAssets; |
3927 | +{ |
3928 | + [self walkAssetsInLibrary]; |
3929 | +} |
3930 | + |
3931 | +- (void)libraryChanged:(NSNotification*)notification; |
3932 | +{ |
3933 | + [self walkAssetsInLibrary]; |
3934 | +} |
3935 | + |
3936 | +- (void)autoUploadSettingsChanged:(NSNotification *)notification; |
3937 | +{ |
3938 | + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; |
3939 | + |
3940 | + if ([defaults boolForKey:@"auto_upload"]) |
3941 | + { |
3942 | + // Turned it on, start your engines |
3943 | + [self.uploadQueue setSuspended:NO]; |
3944 | + [self walkAssetsInLibrary]; |
3945 | + } |
3946 | + else |
3947 | + { |
3948 | + // Turned it off, cancel all operations |
3949 | + [self.uploadQueue setSuspended:YES]; |
3950 | + } |
3951 | +} |
3952 | + |
3953 | +- (void)reachabilityChanged:(NSNotification*)notification; |
3954 | +{ |
3955 | + Reachability *reachability = [notification object]; |
3956 | + NetworkStatus status = [reachability currentReachabilityStatus]; |
3957 | + switch (status) |
3958 | + { |
3959 | + case ReachableViaWiFi: |
3960 | + [self.uploadQueue setSuspended:NO]; |
3961 | + break; |
3962 | + case ReachableViaWWAN: |
3963 | + { |
3964 | + BOOL shouldSuspend = [[NSUserDefaults standardUserDefaults] boolForKey:@"wifi_only"]; |
3965 | + [self.uploadQueue setSuspended:shouldSuspend]; |
3966 | + break; |
3967 | + } |
3968 | + case NotReachable: |
3969 | + [self.uploadQueue setSuspended:YES]; |
3970 | + break; |
3971 | + } |
3972 | +} |
3973 | + |
3974 | +- (void)walkAssetsInLibrary; |
3975 | +{ |
3976 | + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; |
3977 | + if ([defaults boolForKey:@"auto_upload"]) { |
3978 | + [self.assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos |
3979 | + usingBlock:^(ALAssetsGroup *group, BOOL *stop) { |
3980 | + __block NSMutableArray *batch = [[NSMutableArray alloc] initWithCapacity:50]; |
3981 | + [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop) { |
3982 | + if (asset == nil) |
3983 | + { |
3984 | + return; |
3985 | + } |
3986 | + |
3987 | + [batch addObject:asset]; |
3988 | + |
3989 | + if ([batch count] >= 50) |
3990 | + { |
3991 | + NSSortDescriptor *sortBy = [NSSortDescriptor sortDescriptorWithKey:@"defaultRepresentation.url.absoluteString" ascending:YES]; |
3992 | + [batch sortUsingDescriptors:[NSArray arrayWithObject:sortBy]]; |
3993 | + [self processAssetBatch:batch inGroup:group]; |
3994 | + [batch release]; |
3995 | + batch = [[NSMutableArray alloc] initWithCapacity:50]; |
3996 | + } |
3997 | + }]; |
3998 | + if ([batch count] > 0) // Deal with last partial batch |
3999 | + { |
4000 | + NSSortDescriptor *sortBy = [NSSortDescriptor sortDescriptorWithKey:@"defaultRepresentation.url.absoluteString" ascending:YES]; |
4001 | + [batch sortUsingDescriptors:[NSArray arrayWithObject:sortBy]]; |
4002 | + [self processAssetBatch:batch inGroup:group]; |
4003 | + } |
4004 | + [batch release]; |
4005 | + batch = nil; |
4006 | + } |
4007 | + failureBlock:^(NSError *error) { |
4008 | + NSLog(@"Some error happened: %@", error); |
4009 | + }]; |
4010 | + } |
4011 | +} |
4012 | + |
4013 | +- (void)processAssetBatch:(NSArray*)batch inGroup:(ALAssetsGroup *)group; |
4014 | +{ |
4015 | + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; |
4016 | + |
4017 | + // instead of dealing with a single asset, loop over our batch |
4018 | + NSMutableArray *URLs = [batch valueForKeyPath:@"defaultRepresentation.url.absoluteString"]; |
4019 | + |
4020 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
4021 | + |
4022 | + NSPredicate *p = [NSPredicate predicateWithFormat:@"url in %@", URLs]; |
4023 | + NSError *error = nil; |
4024 | + NSSortDescriptor *sortBy = [NSSortDescriptor sortDescriptorWithKey:@"url" ascending:YES]; |
4025 | + NSArray *existingU1Assets = [self.dataRepository resultsForEntityClass:[U1Asset class] matchingPredicate:p withSortDescriptors:[NSArray arrayWithObject:sortBy] error:&error]; |
4026 | + |
4027 | + // If batch's asset isn't in existingU1Assets or existingU1Asset's generation is nil, we upload it. |
4028 | + |
4029 | + // walk batch, looking for |
4030 | + NSEnumerator *assetEnumerator = [existingU1Assets objectEnumerator]; |
4031 | + __block U1Asset *nextU1Asset = [assetEnumerator nextObject]; |
4032 | + [batch enumerateObjectsUsingBlock:^(ALAsset *asset, NSUInteger idx, BOOL *stop) { |
4033 | + BOOL shouldUpload = NO; |
4034 | + U1Asset *assetToUpload = nil; |
4035 | + |
4036 | + NSString *url = [[[asset defaultRepresentation] url] absoluteString]; |
4037 | + while (nextU1Asset && [nextU1Asset.url compare:url] == NSOrderedAscending) |
4038 | + nextU1Asset = [assetEnumerator nextObject]; |
4039 | + |
4040 | + if ([nextU1Asset.url isEqualToString:url]) |
4041 | + { |
4042 | + // matched... if the generation is nil, still need to upload it, but don't need to create it |
4043 | + if (nextU1Asset.generation == nil) |
4044 | + { |
4045 | + shouldUpload = YES; |
4046 | + assetToUpload = nextU1Asset; |
4047 | + } |
4048 | + } |
4049 | + else |
4050 | + { |
4051 | + // no U1asset, need to create/upload |
4052 | + NSString *assetType = [asset valueForProperty:ALAssetPropertyType]; |
4053 | + BOOL canUpload = NO; |
4054 | + if ([defaults boolForKey:@"include_video"]) |
4055 | + { |
4056 | + canUpload = ([assetType isEqualToString:ALAssetTypePhoto] || |
4057 | + [assetType isEqualToString:ALAssetTypeVideo]); |
4058 | + } |
4059 | + else |
4060 | + { |
4061 | + canUpload = [assetType isEqualToString:ALAssetTypePhoto]; |
4062 | + } |
4063 | + |
4064 | + if (canUpload) { |
4065 | + __block U1Asset *newAsset = nil; |
4066 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
4067 | + |
4068 | + newAsset = [U1Asset insertInManagedObjectContext:context]; |
4069 | + newAsset.groupId = [group valueForProperty: ALAssetsGroupPropertyPersistentID]; |
4070 | + newAsset.url = url; |
4071 | + newAsset.filename = [self generateFilenameForAsset:asset]; |
4072 | + NSString *resourcePath = [self.remoteUploadFolder.resourcePath stringByAppendingPathComponent:newAsset.filename]; |
4073 | + [self createPendingFileNodeForResourcePath:resourcePath asset:newAsset]; |
4074 | + }]; |
4075 | + |
4076 | + shouldUpload = YES; |
4077 | + assetToUpload = newAsset; |
4078 | + } |
4079 | + } |
4080 | + // Check shouldUpload flag |
4081 | + if (shouldUpload && ![self.localAssetsToUpload member:assetToUpload]) |
4082 | + { |
4083 | + [self uploadRepresentation:[asset defaultRepresentation] forAsset:assetToUpload withPriority:NSOperationQueuePriorityNormal]; |
4084 | + } |
4085 | + }]; |
4086 | + }); |
4087 | + |
4088 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
4089 | + [self.dataRepository save:NULL]; |
4090 | + }); |
4091 | +} |
4092 | + |
4093 | +- (NSString *)generateFilenameForAsset:(ALAsset *)asset; |
4094 | +{ |
4095 | + // get the type of the asset |
4096 | + U1UTIMapper *utiMapper = [U1UTIMapper sharedU1UTIMapper]; |
4097 | + |
4098 | + NSString *ext = [utiMapper extensionForUTI:[asset.defaultRepresentation UTI]]; |
4099 | + |
4100 | + int idx = (int)[self numberOfAssets]; |
4101 | + |
4102 | + return [NSString stringWithFormat:@"IMG_%d.%@", idx, ext]; |
4103 | +} |
4104 | + |
4105 | +- (void)uploadRepresentation:(ALAssetRepresentation *)rep forAsset:(U1Asset *)asset withPriority:(NSOperationQueuePriority)priority; |
4106 | +{ |
4107 | + NSString *resourcePath = [self.remoteUploadFolder.resourcePath stringByAppendingPathComponent:asset.filename]; |
4108 | + |
4109 | + if (![self isResourceUploading:resourcePath]) |
4110 | + { |
4111 | + [self.localAssetsToUpload addObject:asset]; |
4112 | + |
4113 | + U1AssetUploadOperation *operation = [[U1AssetUploadOperation alloc] init]; |
4114 | + operation.asset = asset; |
4115 | + operation.folder = self.remoteUploadFolder; |
4116 | + operation.filename = asset.filename; |
4117 | + operation.mimetype = [[U1UTIMapper sharedU1UTIMapper] MIMETypeForUTI:[rep UTI]]; |
4118 | + operation.representation = rep; |
4119 | + [operation setCompletionBlock:^{ |
4120 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
4121 | + if (operation.error == nil) // or the error is somehow unrecoverable (e.g., over quota) |
4122 | + { |
4123 | + asset.generation = asset.fileNode.generation; |
4124 | + [self.dataRepository save:NULL]; |
4125 | + [self.localAssetsToUpload removeObject:asset]; |
4126 | + [[NSNotificationCenter defaultCenter] postNotificationName:@"imageUploaded" object:nil]; |
4127 | + // Fire a notification that our U1LocalAssetsViewController can subscribe to |
4128 | + } |
4129 | + else |
4130 | + { |
4131 | + NSLog(@"Error trying to upload %@: %@", operation.filename, operation.error); |
4132 | + // Try it again (this is brittle if the error isn't recoverable (e.g. over quota) |
4133 | + [self uploadRepresentation:rep forAsset:asset withPriority:NSOperationQueuePriorityHigh]; |
4134 | + } |
4135 | + }); |
4136 | + }]; |
4137 | + [self.uploadQueue addOperation:operation]; |
4138 | + } |
4139 | +} |
4140 | + |
4141 | +- (U1FileNode *)createPendingFileNodeForResourcePath:(NSString *)resourcePath asset:(U1Asset *)asset; |
4142 | +{ |
4143 | + __block U1FileNode *node = nil; |
4144 | + |
4145 | + // TODO: temporary, create node if doesn't exist |
4146 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
4147 | + node = [U1FileNode insertInManagedObjectContext:context]; |
4148 | + node.resourcePath = resourcePath; |
4149 | + node.kind = @"file"; |
4150 | + node.parent = self.remoteUploadFolder; |
4151 | + node.contentPath = [self.remoteUploadFolder.contentPath stringByAppendingPathComponent:[resourcePath lastPathComponent]]; |
4152 | + node.asset = asset; |
4153 | + }]; |
4154 | + |
4155 | + return node; |
4156 | +} |
4157 | + |
4158 | +- (int)numberOfAssets; |
4159 | +{ |
4160 | + NSError *error = nil; |
4161 | + return [[self.dataRepository resultsForEntityClass:[U1Asset class] |
4162 | + matchingPredicate:nil |
4163 | + withSortDescriptors:nil |
4164 | + error:&error] count]; |
4165 | +} |
4166 | + |
4167 | +- (int)numberOfAssetsUploaded; |
4168 | +{ |
4169 | + return [self numberOfAssets] - [self.localAssetsToUpload count]; |
4170 | +} |
4171 | + |
4172 | +- (BOOL)isResourceUploading:(NSString *)resourcePath; |
4173 | +{ |
4174 | + __block BOOL isUploading = NO; |
4175 | + |
4176 | + [[self.uploadQueue operations] enumerateObjectsUsingBlock:^(U1AssetUploadOperation *operation, NSUInteger idx, BOOL *stop) { |
4177 | + if ([operation.filename isEqualToString:[resourcePath lastPathComponent]] && [operation isExecuting]) |
4178 | + { |
4179 | + isUploading = YES; |
4180 | + *stop = YES; |
4181 | + } |
4182 | + }]; |
4183 | + |
4184 | + return isUploading; |
4185 | +} |
4186 | + |
4187 | +- (void)thumbnailForNode:(U1FileNode *)fileNode completionBlock:(void(^)(CGImageRef thumbnail))completionBlock; |
4188 | +{ |
4189 | + [self.assetsLibrary assetForURL:[NSURL URLWithString:fileNode.asset.url] |
4190 | + resultBlock:^(ALAsset *asset) { |
4191 | + completionBlock(asset.thumbnail); |
4192 | + } failureBlock:^(NSError *error) { |
4193 | + NSLog(@"Couldn't find the asset to get a thumbnail: %@", error); |
4194 | + }]; |
4195 | +} |
4196 | + |
4197 | +@end |
4198 | |
4199 | === added file 'Files/U1LocalAssetsViewController.h' |
4200 | --- Files/U1LocalAssetsViewController.h 1970-01-01 00:00:00 +0000 |
4201 | +++ Files/U1LocalAssetsViewController.h 2011-11-01 14:25:30 +0000 |
4202 | @@ -0,0 +1,43 @@ |
4203 | +// |
4204 | +// Copyright 2011 Canonical Ltd. |
4205 | +// |
4206 | +// This program is free software: you can redistribute it and/or modify it |
4207 | +// under the terms of the GNU Affero General Public License version 3, |
4208 | +// as published by the Free Software Foundation. |
4209 | +// |
4210 | +// This program is distributed in the hope that it will be useful, but |
4211 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
4212 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
4213 | +// PURPOSE. See the GNU Affero General Public License for more details. |
4214 | +// |
4215 | +// You should have received a copy of the GNU Affero General Public License |
4216 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
4217 | + |
4218 | +#import <UIKit/UIKit.h> |
4219 | + |
4220 | +#import "PullRefreshTableViewController.h" |
4221 | + |
4222 | +@class U1FilesClient, U1Node; |
4223 | + |
4224 | +@protocol U1LocalAssetsViewControllerDelegate; |
4225 | + |
4226 | + |
4227 | +@interface U1LocalAssetsViewController : PullRefreshTableViewController |
4228 | + |
4229 | +@property (nonatomic, retain, readonly) IBOutlet UITableViewCell *loadingCell; |
4230 | +@property (nonatomic, retain) IBOutlet UIView *progressView; |
4231 | +@property (nonatomic, retain) IBOutlet UIProgressView *progressBar; |
4232 | +@property (nonatomic, retain) IBOutlet UILabel *progressLabel; |
4233 | + |
4234 | +@property (assign) id<U1LocalAssetsViewControllerDelegate> delegate; |
4235 | +@property (retain) U1FilesClient *filesClient; |
4236 | + |
4237 | +- (id)initWithNodeResourcePath:(NSString*)resourcePath; |
4238 | + |
4239 | +@end |
4240 | + |
4241 | + |
4242 | +@protocol U1LocalAssetsViewControllerDelegate <NSObject> |
4243 | +@required |
4244 | +- (void)localAssetsController:(U1LocalAssetsViewController*)localAssetsController didSelectNode:(U1Node*)node; |
4245 | +@end |
4246 | |
4247 | === added file 'Files/U1LocalAssetsViewController.m' |
4248 | --- Files/U1LocalAssetsViewController.m 1970-01-01 00:00:00 +0000 |
4249 | +++ Files/U1LocalAssetsViewController.m 2011-11-01 14:25:30 +0000 |
4250 | @@ -0,0 +1,420 @@ |
4251 | +// |
4252 | +// Copyright 2011 Canonical Ltd. |
4253 | +// |
4254 | +// This program is free software: you can redistribute it and/or modify it |
4255 | +// under the terms of the GNU Affero General Public License version 3, |
4256 | +// as published by the Free Software Foundation. |
4257 | +// |
4258 | +// This program is distributed in the hope that it will be useful, but |
4259 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
4260 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
4261 | +// PURPOSE. See the GNU Affero General Public License for more details. |
4262 | +// |
4263 | +// You should have received a copy of the GNU Affero General Public License |
4264 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
4265 | + |
4266 | +#import "U1LocalAssetsViewController.h" |
4267 | + |
4268 | +#import "U1ByteSizeValueTransformer.h" |
4269 | +#import "U1FileNode.h" |
4270 | +#import "U1FilePreviewViewController.h" |
4271 | +#import "U1FilesClient.h" |
4272 | +#import "U1FolderItemCell.h" |
4273 | +#import "U1FolderNode.h" |
4274 | +#import "U1Node.h" |
4275 | +#import "UIActionSheet+U1Additions.h" |
4276 | +#import "U1LocalAssetsManager.h" |
4277 | +#import "U1DataRepository.h" |
4278 | + |
4279 | +@interface U1LocalAssetsViewController () <U1LocalAssetsViewControllerDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, NSFetchedResultsControllerDelegate> |
4280 | +@property (copy) NSString *resourcePath; |
4281 | +@property (retain) U1ByteSizeValueTransformer *byteSizeTransformer; |
4282 | +@property (retain) NSIndexPath *pendingIndexPath; |
4283 | +@property (retain) U1FolderNode *node; |
4284 | +@property (retain) NSMutableArray *nodes; |
4285 | +@property (retain) NSFetchedResultsController *resultsController; |
4286 | +@property (retain) U1LocalAssetsManager *localAssetsManager; |
4287 | +- (void)updateFeedback:(id)sender; |
4288 | +- (void)loadInfoForNode; |
4289 | +@end |
4290 | + |
4291 | + |
4292 | +@implementation U1LocalAssetsViewController |
4293 | + |
4294 | +@synthesize loadingCell, progressView, progressBar, progressLabel; |
4295 | +@synthesize delegate, filesClient, node, resourcePath; |
4296 | +@synthesize byteSizeTransformer, pendingIndexPath, nodes, resultsController, localAssetsManager; |
4297 | + |
4298 | +- (id)initWithNodeResourcePath:(NSString*)theResourcePath; |
4299 | +{ |
4300 | + self = [super initWithNibName:@"U1LocalAssetsViewController" bundle:nil]; |
4301 | + if (!self) |
4302 | + return nil; |
4303 | + self.title = NSLocalizedString(@"Camera Roll", @""); |
4304 | + self.resourcePath = theResourcePath; |
4305 | + self.byteSizeTransformer = [[U1ByteSizeValueTransformer new] autorelease]; |
4306 | + self.delegate = self; // ??? |
4307 | + filesClient = [U1FilesClient sharedFilesClient]; |
4308 | + localAssetsManager = [U1LocalAssetsManager sharedLocalAssetsManager]; |
4309 | + |
4310 | + // This button should use a camera icon and go to the image picker to take a new photo. |
4311 | + UIBarButtonItem *cameraButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(takePicture:)]; |
4312 | + [self.navigationItem setRightBarButtonItem:cameraButton]; |
4313 | + [cameraButton release]; |
4314 | + |
4315 | + UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 20)]; |
4316 | + // TODO: Ubuntu font |
4317 | + [titleLabel setFont:[UIFont boldSystemFontOfSize:18.f]]; |
4318 | + [titleLabel setTextColor:[UIColor blackColor]]; |
4319 | + [titleLabel setShadowColor:[UIColor whiteColor]]; |
4320 | + [titleLabel setShadowOffset:CGSizeMake(-1, -1)]; |
4321 | + [titleLabel setText:self.title]; |
4322 | + [titleLabel sizeToFit]; |
4323 | + [titleLabel setOpaque:NO]; |
4324 | + [titleLabel setBackgroundColor:[UIColor clearColor]]; |
4325 | + [self.navigationItem setTitleView:titleLabel]; |
4326 | + [titleLabel release]; |
4327 | + // [uploadItem release]; |
4328 | + |
4329 | + return self; |
4330 | +} |
4331 | + |
4332 | +- (void)dealloc; |
4333 | +{ |
4334 | + [loadingCell release]; |
4335 | + [resourcePath release]; |
4336 | + [node release]; |
4337 | + [byteSizeTransformer release]; |
4338 | + [pendingIndexPath release]; |
4339 | + [nodes release]; |
4340 | + [resultsController release]; |
4341 | + [super dealloc]; |
4342 | +} |
4343 | + |
4344 | +- (void)viewDidLoad; |
4345 | +{ |
4346 | + [super viewDidLoad]; |
4347 | + [self updateFeedback:nil]; |
4348 | + [self refresh]; |
4349 | + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateFeedback:) name:@"imageUploaded" object:nil]; |
4350 | + UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)]; |
4351 | + [longPress setMinimumPressDuration:1.f]; |
4352 | + [self.tableView addGestureRecognizer:longPress]; |
4353 | + [longPress release]; |
4354 | +} |
4355 | + |
4356 | +- (void)viewDidUnload; |
4357 | +{ |
4358 | + [loadingCell release], loadingCell = nil; |
4359 | + [[NSNotificationCenter defaultCenter] removeObserver:self]; |
4360 | + [super viewDidUnload]; |
4361 | +} |
4362 | + |
4363 | +- (void)viewDidAppear:(BOOL)animated; |
4364 | +{ |
4365 | + [super viewDidAppear:animated]; |
4366 | + [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES]; |
4367 | +} |
4368 | + |
4369 | +- (void)longPress:(UILongPressGestureRecognizer*)longPress; |
4370 | +{ |
4371 | + if (longPress.state == UIGestureRecognizerStateBegan) |
4372 | + { |
4373 | + CGPoint p = [longPress locationInView:self.tableView]; |
4374 | + NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p]; |
4375 | + U1Node *childNode = [self.nodes objectAtIndex:indexPath.row]; |
4376 | + |
4377 | + UIActionSheet *actionSheet = [UIActionSheet new]; |
4378 | + |
4379 | + [actionSheet setTitle:[[childNode path] lastPathComponent]]; |
4380 | + // TODO: rename |
4381 | + NSInteger publishButtonIndex = -1; |
4382 | + NSInteger copyURLButtonIndex = -1; |
4383 | + if ([childNode isFile]) |
4384 | + { |
4385 | + U1FileNode *fileNode = (id)childNode; |
4386 | + if ([[fileNode isPublic] boolValue]) |
4387 | + { |
4388 | + publishButtonIndex = [actionSheet addButtonWithTitle:@"Unpublish"]; |
4389 | + copyURLButtonIndex = [actionSheet addButtonWithTitle:@"Copy Public URL"]; |
4390 | + } |
4391 | + else |
4392 | + { |
4393 | + publishButtonIndex = [actionSheet addButtonWithTitle:@"Publish"]; |
4394 | + } |
4395 | + } |
4396 | + [actionSheet setCancelButtonIndex:[actionSheet addButtonWithTitle:@"Cancel"]]; |
4397 | + |
4398 | + self.pendingIndexPath = indexPath; |
4399 | + [actionSheet showInView:self.view withCompletionBlock:^(NSInteger buttonIndex) { |
4400 | + if (buttonIndex == publishButtonIndex) |
4401 | + { |
4402 | + U1FileNode *fileNode = (id)childNode; |
4403 | + if ([[fileNode isPublic] boolValue]) |
4404 | + [self.filesClient unpublishNode:fileNode completionBlock:^(U1FileNode *updatedNode, NSError *error) { |
4405 | + }]; |
4406 | + else |
4407 | + [self.filesClient publishNode:fileNode completionBlock:^(U1FileNode *updatedNode, NSError *error) { |
4408 | + }]; |
4409 | + } |
4410 | + else if (buttonIndex == copyURLButtonIndex) |
4411 | + { |
4412 | + U1FileNode *fileNode = (id)childNode; |
4413 | + NSArray *types = UIPasteboardTypeListString; |
4414 | + [[UIPasteboard generalPasteboard] setValue:[fileNode publicURLString] forPasteboardType:[types lastObject]]; |
4415 | + } |
4416 | + else if (buttonIndex == [actionSheet cancelButtonIndex]) |
4417 | + { |
4418 | + // NSLog(@"cancel"); |
4419 | + } |
4420 | + self.pendingIndexPath = nil; |
4421 | + }]; |
4422 | + } |
4423 | +} |
4424 | + |
4425 | +- (void)takePicture:(id)sender; |
4426 | +{ |
4427 | + UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; |
4428 | + imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; |
4429 | + imagePicker.delegate = self; |
4430 | + [self presentModalViewController:imagePicker animated:YES]; |
4431 | +} |
4432 | + |
4433 | +- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info; |
4434 | +{ |
4435 | + // TODO: check for jpg/png |
4436 | + // TODO: handle videos (stream) |
4437 | + |
4438 | + [picker dismissModalViewControllerAnimated:YES]; |
4439 | + |
4440 | + // NSURL *imageURL = [info objectForKey:UIImagePickerControllerReferenceURL]; |
4441 | + UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; |
4442 | + |
4443 | + UIImageWriteToSavedPhotosAlbum(image, self, nil, nil); |
4444 | +} |
4445 | + |
4446 | +- (void)updateFeedback:(id)sender; |
4447 | +{ |
4448 | + // Update the label and the progress bar |
4449 | + // progressLabel = (numberOfAssets - assetsPendingUpload) / numberOfAssets |
4450 | + dispatch_async(dispatch_get_main_queue(), ^{ |
4451 | + U1LocalAssetsManager *localAssets = [U1LocalAssetsManager sharedLocalAssetsManager]; |
4452 | + int totalAssets = [localAssets numberOfAssets]; |
4453 | + int assetsUploaded = [localAssets numberOfAssetsUploaded]; |
4454 | + float percentDone = (float)assetsUploaded / (float)totalAssets; |
4455 | + self.progressLabel.text = [NSString stringWithFormat:@"%d of %d uploaded", assetsUploaded, totalAssets]; |
4456 | + self.progressBar.progress = percentDone; |
4457 | + [self.tableView reloadData]; |
4458 | + }); |
4459 | +} |
4460 | + |
4461 | +#pragma mark UITableViewDataSource Methods |
4462 | + |
4463 | +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; |
4464 | +{ |
4465 | + if (!self.resultsController) |
4466 | + return 1; |
4467 | + |
4468 | + return [[[self.resultsController sections] objectAtIndex:section] numberOfObjects]; |
4469 | +} |
4470 | + |
4471 | +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section; |
4472 | +{ |
4473 | + if (section == 0 && [self.localAssetsManager.localAssetsToUpload count] > 0) |
4474 | + { |
4475 | + return 66.0f; |
4476 | + } |
4477 | + |
4478 | + return [tableView sectionHeaderHeight]; |
4479 | +} |
4480 | + |
4481 | +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; |
4482 | +{ |
4483 | + if (section == 0 && [self.localAssetsManager.localAssetsToUpload count] > 0) |
4484 | + { |
4485 | + return self.progressView; |
4486 | + } |
4487 | + |
4488 | + return nil; |
4489 | +} |
4490 | + |
4491 | +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; |
4492 | +{ |
4493 | + if (!self.resultsController) |
4494 | + { |
4495 | + return self.loadingCell; |
4496 | + } |
4497 | + |
4498 | + U1FolderItemCell *cell = [U1FolderItemCell cellForTableView:tableView]; |
4499 | + |
4500 | + U1Node *childNode = [self.resultsController objectAtIndexPath:indexPath]; |
4501 | + cell.nameLabel.text = [childNode.resourcePath lastPathComponent]; |
4502 | + NSString *detailString = @"Pending"; |
4503 | +// TODO: get this thumbnail loading happening inside an operation queue, tied to visible rows |
4504 | +// [self.localAssetsManager thumbnailForNode:childNode completionBlock:^(CGImageRef thumbnail) { |
4505 | +// cell.iconImageView.image = [UIImage imageWithCGImage:thumbnail]; |
4506 | +// }]; |
4507 | + |
4508 | + BOOL hasChildren = [[childNode hasChildren] boolValue]; |
4509 | + [cell setAccessoryType:(hasChildren ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone)]; |
4510 | + |
4511 | + if (childNode.generation == nil) |
4512 | + { |
4513 | + cell.nameLabel.textColor = [UIColor grayColor]; |
4514 | + // query the local assets manager to see if this childNode's corresponding asset is actually in the upload operation queue |
4515 | + BOOL isUploading = [self.localAssetsManager isResourceUploading:childNode.resourcePath]; |
4516 | + if (isUploading) |
4517 | + { |
4518 | + [cell.uploadIndicator setHidden:NO]; |
4519 | + [cell.uploadIndicator startAnimating]; |
4520 | + detailString = @"Uploading"; |
4521 | + } |
4522 | + else { |
4523 | + [cell.uploadIndicator setHidden:YES]; |
4524 | + [cell.uploadIndicator stopAnimating]; |
4525 | + } |
4526 | + } |
4527 | + else |
4528 | + { |
4529 | + cell.nameLabel.textColor = [UIColor blackColor]; |
4530 | + [cell.detailLabel setHidden:NO]; |
4531 | + [cell.uploadIndicator setHidden:YES]; |
4532 | + [cell.uploadIndicator stopAnimating]; |
4533 | + } |
4534 | + |
4535 | + [cell.imageView setImage:nil]; |
4536 | + if ([childNode isFolder]) |
4537 | + { |
4538 | + [cell.imageView setImage:[UIImage imageNamed:@"ic_folder"]]; |
4539 | + detailString = [childNode.modificationDate description]; |
4540 | + } |
4541 | + else |
4542 | + { |
4543 | + NSString *contentPath = childNode.contentPath; |
4544 | + NSURL *contentURL = [NSURL fileURLWithPath:contentPath]; |
4545 | + UIDocumentInteractionController *docController = [UIDocumentInteractionController interactionControllerWithURL:contentURL]; |
4546 | + [cell.imageView setImage:[docController.icons objectAtIndex:0]]; |
4547 | + NSNumber *size = [childNode valueForKey:@"size"]; |
4548 | + NSString *sizeString = [self.byteSizeTransformer transformedValue:size]; |
4549 | + if (childNode.generation != nil) |
4550 | + { |
4551 | + detailString = [sizeString stringByAppendingFormat:@", modified %@", childNode.modificationDate]; |
4552 | + } |
4553 | + } |
4554 | + |
4555 | + [cell.detailLabel setText:detailString]; |
4556 | + return cell; |
4557 | +} |
4558 | + |
4559 | + |
4560 | +#pragma mark UITableViewDelegate Methods |
4561 | + |
4562 | +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; |
4563 | +{ |
4564 | + U1Node *childNode = [self.resultsController objectAtIndexPath:indexPath]; |
4565 | + [self.delegate localAssetsController:self didSelectNode:childNode]; |
4566 | +} |
4567 | + |
4568 | +- (void)refresh; |
4569 | +{ |
4570 | + [self loadInfoForNode]; |
4571 | +} |
4572 | + |
4573 | + |
4574 | +#pragma mark Private Methods |
4575 | + |
4576 | +- (void)loadInfoForNode; |
4577 | +{ |
4578 | + NSParameterAssert(self.resourcePath != nil); |
4579 | + |
4580 | + [self.filesClient fetchFolderWithResourcePath:self.resourcePath completionBlock:^(U1Node *theNode, NSFetchedResultsController *childrenResultsController, NSError *error) { |
4581 | + |
4582 | + self.node = (id)theNode; |
4583 | + self.resultsController = childrenResultsController; |
4584 | + [self.resultsController setDelegate:self]; |
4585 | + [self stopLoading]; |
4586 | + [self.tableView reloadData]; |
4587 | + }]; |
4588 | +} |
4589 | + |
4590 | +#pragma mark NSFetchedResultsControllerDelegate Methods |
4591 | + |
4592 | + |
4593 | +- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller; |
4594 | +{ |
4595 | + [self.tableView beginUpdates]; |
4596 | +} |
4597 | + |
4598 | + |
4599 | +- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo |
4600 | + atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type; |
4601 | +{ |
4602 | + switch (type) |
4603 | + { |
4604 | + case NSFetchedResultsChangeInsert: |
4605 | + [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] |
4606 | + withRowAnimation:UITableViewRowAnimationFade]; |
4607 | + break; |
4608 | + |
4609 | + case NSFetchedResultsChangeDelete: |
4610 | + [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] |
4611 | + withRowAnimation:UITableViewRowAnimationFade]; |
4612 | + break; |
4613 | + } |
4614 | +} |
4615 | + |
4616 | +- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject |
4617 | + atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type |
4618 | + newIndexPath:(NSIndexPath *)newIndexPath; |
4619 | +{ |
4620 | + |
4621 | + UITableView *tableView = self.tableView; |
4622 | + |
4623 | + switch (type) |
4624 | + { |
4625 | + |
4626 | + case NSFetchedResultsChangeInsert: |
4627 | + [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] |
4628 | + withRowAnimation:UITableViewRowAnimationFade]; |
4629 | + break; |
4630 | + |
4631 | + case NSFetchedResultsChangeDelete: |
4632 | + [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] |
4633 | + withRowAnimation:UITableViewRowAnimationFade]; |
4634 | + break; |
4635 | + |
4636 | + case NSFetchedResultsChangeUpdate: |
4637 | + // TODO: |
4638 | + // [self configureCell:[tableView cellForRowAtIndexPath:indexPath] |
4639 | + // atIndexPath:indexPath]; |
4640 | + [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] |
4641 | + withRowAnimation:UITableViewRowAnimationNone]; |
4642 | + break; |
4643 | + |
4644 | + case NSFetchedResultsChangeMove: |
4645 | + [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] |
4646 | + withRowAnimation:UITableViewRowAnimationFade]; |
4647 | + [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] |
4648 | + withRowAnimation:UITableViewRowAnimationFade]; |
4649 | + break; |
4650 | + } |
4651 | +} |
4652 | + |
4653 | +- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller; |
4654 | +{ |
4655 | + [self.tableView endUpdates]; |
4656 | +} |
4657 | + |
4658 | +#pragma mark U1LocalAssetsViewControllerDelegate Methods |
4659 | + |
4660 | +- (void)localAssetsController:(U1LocalAssetsViewController *)localAssetsController didSelectNode:(U1Node *)aNode |
4661 | +{ |
4662 | + if ([aNode isFile]) |
4663 | + { |
4664 | + U1FilePreviewViewController *fileController = [[U1FilePreviewViewController alloc] initWithNode:(id)node]; |
4665 | + [self.navigationController pushViewController:fileController animated:YES]; |
4666 | + [fileController release]; |
4667 | + } |
4668 | +} |
4669 | + |
4670 | +@end |
4671 | |
4672 | === added file 'Files/U1LocalAssetsViewController.xib' |
4673 | --- Files/U1LocalAssetsViewController.xib 1970-01-01 00:00:00 +0000 |
4674 | +++ Files/U1LocalAssetsViewController.xib 2011-11-01 14:25:30 +0000 |
4675 | @@ -0,0 +1,391 @@ |
4676 | +<?xml version="1.0" encoding="UTF-8"?> |
4677 | +<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00"> |
4678 | + <data> |
4679 | + <int key="IBDocument.SystemTarget">1280</int> |
4680 | + <string key="IBDocument.SystemVersion">10K549</string> |
4681 | + <string key="IBDocument.InterfaceBuilderVersion">1938</string> |
4682 | + <string key="IBDocument.AppKitVersion">1038.36</string> |
4683 | + <string key="IBDocument.HIToolboxVersion">461.00</string> |
4684 | + <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> |
4685 | + <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
4686 | + <string key="NS.object.0">933</string> |
4687 | + </object> |
4688 | + <array key="IBDocument.IntegratedClassDependencies"> |
4689 | + <string>IBProxyObject</string> |
4690 | + <string>IBUIProgressView</string> |
4691 | + <string>IBUILabel</string> |
4692 | + <string>IBUIImageView</string> |
4693 | + <string>IBUIActivityIndicatorView</string> |
4694 | + <string>IBUITableView</string> |
4695 | + <string>IBUITableViewCell</string> |
4696 | + <string>IBUIView</string> |
4697 | + </array> |
4698 | + <array key="IBDocument.PluginDependencies"> |
4699 | + <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
4700 | + </array> |
4701 | + <object class="NSMutableDictionary" key="IBDocument.Metadata"> |
4702 | + <string key="NS.key.0">PluginDependencyRecalculationVersion</string> |
4703 | + <integer value="1" key="NS.object.0"/> |
4704 | + </object> |
4705 | + <array class="NSMutableArray" key="IBDocument.RootObjects" id="1000"> |
4706 | + <object class="IBProxyObject" id="372490531"> |
4707 | + <string key="IBProxiedObjectIdentifier">IBFilesOwner</string> |
4708 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
4709 | + </object> |
4710 | + <object class="IBProxyObject" id="975951072"> |
4711 | + <string key="IBProxiedObjectIdentifier">IBFirstResponder</string> |
4712 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
4713 | + </object> |
4714 | + <object class="IBUIView" id="824354941"> |
4715 | + <reference key="NSNextResponder"/> |
4716 | + <int key="NSvFlags">292</int> |
4717 | + <array class="NSMutableArray" key="NSSubviews"> |
4718 | + <object class="IBUIImageView" id="135648369"> |
4719 | + <reference key="NSNextResponder" ref="824354941"/> |
4720 | + <int key="NSvFlags">292</int> |
4721 | + <string key="NSFrameSize">{320, 66}</string> |
4722 | + <reference key="NSSuperview" ref="824354941"/> |
4723 | + <reference key="NSWindow"/> |
4724 | + <reference key="NSNextKeyView" ref="129966493"/> |
4725 | + <bool key="IBUIUserInteractionEnabled">NO</bool> |
4726 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
4727 | + <object class="NSCustomResource" key="IBUIImage"> |
4728 | + <string key="NSClassName">NSImage</string> |
4729 | + <string key="NSResourceName">progress_view_background.png</string> |
4730 | + </object> |
4731 | + </object> |
4732 | + <object class="IBUIProgressView" id="129966493"> |
4733 | + <reference key="NSNextResponder" ref="824354941"/> |
4734 | + <int key="NSvFlags">292</int> |
4735 | + <string key="NSFrame">{{60, 20}, {200, 9}}</string> |
4736 | + <reference key="NSSuperview" ref="824354941"/> |
4737 | + <reference key="NSWindow"/> |
4738 | + <reference key="NSNextKeyView" ref="54616486"/> |
4739 | + <bool key="IBUIOpaque">NO</bool> |
4740 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
4741 | + <float key="IBUIProgress">0.5</float> |
4742 | + </object> |
4743 | + <object class="IBUILabel" id="54616486"> |
4744 | + <reference key="NSNextResponder" ref="824354941"/> |
4745 | + <int key="NSvFlags">292</int> |
4746 | + <string key="NSFrame">{{60, 37}, {200, 16}}</string> |
4747 | + <reference key="NSSuperview" ref="824354941"/> |
4748 | + <reference key="NSWindow"/> |
4749 | + <bool key="IBUIOpaque">NO</bool> |
4750 | + <bool key="IBUIClipsSubviews">YES</bool> |
4751 | + <int key="IBUIContentMode">7</int> |
4752 | + <bool key="IBUIUserInteractionEnabled">NO</bool> |
4753 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
4754 | + <string key="IBUIText">Label</string> |
4755 | + <object class="NSColor" key="IBUITextColor" id="943202549"> |
4756 | + <int key="NSColorSpace">1</int> |
4757 | + <bytes key="NSRGB">MCAwIDAAA</bytes> |
4758 | + </object> |
4759 | + <nil key="IBUIHighlightedColor"/> |
4760 | + <int key="IBUIBaselineAdjustment">1</int> |
4761 | + <float key="IBUIMinimumFontSize">10</float> |
4762 | + <int key="IBUITextAlignment">1</int> |
4763 | + <object class="IBUIFontDescription" key="IBUIFontDescription"> |
4764 | + <int key="type">1</int> |
4765 | + <double key="pointSize">12</double> |
4766 | + </object> |
4767 | + <object class="NSFont" key="IBUIFont"> |
4768 | + <string key="NSName">Helvetica</string> |
4769 | + <double key="NSSize">12</double> |
4770 | + <int key="NSfFlags">16</int> |
4771 | + </object> |
4772 | + </object> |
4773 | + </array> |
4774 | + <string key="NSFrameSize">{320, 66}</string> |
4775 | + <reference key="NSSuperview"/> |
4776 | + <reference key="NSWindow"/> |
4777 | + <reference key="NSNextKeyView" ref="135648369"/> |
4778 | + <object class="NSColor" key="IBUIBackgroundColor" id="590472223"> |
4779 | + <int key="NSColorSpace">3</int> |
4780 | + <bytes key="NSWhite">MCAwAA</bytes> |
4781 | + </object> |
4782 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
4783 | + </object> |
4784 | + <object class="IBUITableView" id="95160719"> |
4785 | + <reference key="NSNextResponder"/> |
4786 | + <int key="NSvFlags">274</int> |
4787 | + <string key="NSFrameSize">{320, 480}</string> |
4788 | + <reference key="NSSuperview"/> |
4789 | + <reference key="NSWindow"/> |
4790 | + <object class="NSColor" key="IBUIBackgroundColor"> |
4791 | + <int key="NSColorSpace">3</int> |
4792 | + <bytes key="NSWhite">MQA</bytes> |
4793 | + </object> |
4794 | + <bool key="IBUIClipsSubviews">YES</bool> |
4795 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
4796 | + <bool key="IBUIAlwaysBounceVertical">YES</bool> |
4797 | + <int key="IBUISeparatorStyle">1</int> |
4798 | + <int key="IBUISectionIndexMinimumDisplayRowCount">0</int> |
4799 | + <bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool> |
4800 | + <float key="IBUIRowHeight">54</float> |
4801 | + <float key="IBUISectionHeaderHeight">22</float> |
4802 | + <float key="IBUISectionFooterHeight">22</float> |
4803 | + </object> |
4804 | + <object class="IBUITableViewCell" id="1003077660"> |
4805 | + <reference key="NSNextResponder"/> |
4806 | + <int key="NSvFlags">292</int> |
4807 | + <array class="NSMutableArray" key="NSSubviews"> |
4808 | + <object class="IBUIView" id="783165177"> |
4809 | + <reference key="NSNextResponder" ref="1003077660"/> |
4810 | + <int key="NSvFlags">256</int> |
4811 | + <array class="NSMutableArray" key="NSSubviews"> |
4812 | + <object class="IBUILabel" id="131881887"> |
4813 | + <reference key="NSNextResponder" ref="783165177"/> |
4814 | + <int key="NSvFlags">292</int> |
4815 | + <string key="NSFrame">{{136, 17}, {75, 21}}</string> |
4816 | + <reference key="NSSuperview" ref="783165177"/> |
4817 | + <reference key="NSWindow"/> |
4818 | + <bool key="IBUIOpaque">NO</bool> |
4819 | + <bool key="IBUIClipsSubviews">YES</bool> |
4820 | + <int key="IBUIContentMode">7</int> |
4821 | + <bool key="IBUIUserInteractionEnabled">NO</bool> |
4822 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
4823 | + <string key="IBUIText">Loading...</string> |
4824 | + <reference key="IBUITextColor" ref="943202549"/> |
4825 | + <nil key="IBUIHighlightedColor"/> |
4826 | + <int key="IBUIBaselineAdjustment">1</int> |
4827 | + <float key="IBUIMinimumFontSize">10</float> |
4828 | + <object class="IBUIFontDescription" key="IBUIFontDescription"> |
4829 | + <string key="name">Helvetica</string> |
4830 | + <string key="family">Helvetica</string> |
4831 | + <int key="traits">0</int> |
4832 | + <double key="pointSize">17</double> |
4833 | + </object> |
4834 | + <object class="NSFont" key="IBUIFont"> |
4835 | + <string key="NSName">Helvetica</string> |
4836 | + <double key="NSSize">17</double> |
4837 | + <int key="NSfFlags">16</int> |
4838 | + </object> |
4839 | + </object> |
4840 | + <object class="IBUIActivityIndicatorView" id="1037320153"> |
4841 | + <reference key="NSNextResponder" ref="783165177"/> |
4842 | + <int key="NSvFlags">292</int> |
4843 | + <string key="NSFrame">{{108, 18}, {20, 20}}</string> |
4844 | + <reference key="NSSuperview" ref="783165177"/> |
4845 | + <reference key="NSWindow"/> |
4846 | + <reference key="NSNextKeyView" ref="131881887"/> |
4847 | + <bool key="IBUIOpaque">NO</bool> |
4848 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
4849 | + <bool key="IBUIHidesWhenStopped">NO</bool> |
4850 | + <bool key="IBUIAnimating">YES</bool> |
4851 | + <int key="IBUIStyle">2</int> |
4852 | + </object> |
4853 | + </array> |
4854 | + <string key="NSFrameSize">{320, 53}</string> |
4855 | + <reference key="NSSuperview" ref="1003077660"/> |
4856 | + <reference key="NSWindow"/> |
4857 | + <reference key="NSNextKeyView" ref="1037320153"/> |
4858 | + <reference key="IBUIBackgroundColor" ref="590472223"/> |
4859 | + <bool key="IBUIOpaque">NO</bool> |
4860 | + <bool key="IBUIClipsSubviews">YES</bool> |
4861 | + <int key="IBUIContentMode">4</int> |
4862 | + <bool key="IBUIMultipleTouchEnabled">YES</bool> |
4863 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
4864 | + </object> |
4865 | + </array> |
4866 | + <string key="NSFrameSize">{320, 54}</string> |
4867 | + <reference key="NSSuperview"/> |
4868 | + <reference key="NSWindow"/> |
4869 | + <reference key="NSNextKeyView" ref="783165177"/> |
4870 | + <object class="NSColor" key="IBUIBackgroundColor"> |
4871 | + <int key="NSColorSpace">1</int> |
4872 | + <bytes key="NSRGB">MSAxIDEAA</bytes> |
4873 | + </object> |
4874 | + <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> |
4875 | + <reference key="IBUIContentView" ref="783165177"/> |
4876 | + </object> |
4877 | + </array> |
4878 | + <object class="IBObjectContainer" key="IBDocument.Objects"> |
4879 | + <array class="NSMutableArray" key="connectionRecords"> |
4880 | + <object class="IBConnectionRecord"> |
4881 | + <object class="IBCocoaTouchOutletConnection" key="connection"> |
4882 | + <string key="label">loadingCell</string> |
4883 | + <reference key="source" ref="372490531"/> |
4884 | + <reference key="destination" ref="1003077660"/> |
4885 | + </object> |
4886 | + <int key="connectionID">12</int> |
4887 | + </object> |
4888 | + <object class="IBConnectionRecord"> |
4889 | + <object class="IBCocoaTouchOutletConnection" key="connection"> |
4890 | + <string key="label">view</string> |
4891 | + <reference key="source" ref="372490531"/> |
4892 | + <reference key="destination" ref="95160719"/> |
4893 | + </object> |
4894 | + <int key="connectionID">13</int> |
4895 | + </object> |
4896 | + <object class="IBConnectionRecord"> |
4897 | + <object class="IBCocoaTouchOutletConnection" key="connection"> |
4898 | + <string key="label">progressLabel</string> |
4899 | + <reference key="source" ref="372490531"/> |
4900 | + <reference key="destination" ref="54616486"/> |
4901 | + </object> |
4902 | + <int key="connectionID">15</int> |
4903 | + </object> |
4904 | + <object class="IBConnectionRecord"> |
4905 | + <object class="IBCocoaTouchOutletConnection" key="connection"> |
4906 | + <string key="label">progressView</string> |
4907 | + <reference key="source" ref="372490531"/> |
4908 | + <reference key="destination" ref="824354941"/> |
4909 | + </object> |
4910 | + <int key="connectionID">17</int> |
4911 | + </object> |
4912 | + <object class="IBConnectionRecord"> |
4913 | + <object class="IBCocoaTouchOutletConnection" key="connection"> |
4914 | + <string key="label">progressBar</string> |
4915 | + <reference key="source" ref="372490531"/> |
4916 | + <reference key="destination" ref="129966493"/> |
4917 | + </object> |
4918 | + <int key="connectionID">18</int> |
4919 | + </object> |
4920 | + </array> |
4921 | + <object class="IBMutableOrderedSet" key="objectRecords"> |
4922 | + <array key="orderedObjects"> |
4923 | + <object class="IBObjectRecord"> |
4924 | + <int key="objectID">0</int> |
4925 | + <array key="object" id="0"/> |
4926 | + <reference key="children" ref="1000"/> |
4927 | + <nil key="parent"/> |
4928 | + </object> |
4929 | + <object class="IBObjectRecord"> |
4930 | + <int key="objectID">-1</int> |
4931 | + <reference key="object" ref="372490531"/> |
4932 | + <reference key="parent" ref="0"/> |
4933 | + <string key="objectName">File's Owner</string> |
4934 | + </object> |
4935 | + <object class="IBObjectRecord"> |
4936 | + <int key="objectID">-2</int> |
4937 | + <reference key="object" ref="975951072"/> |
4938 | + <reference key="parent" ref="0"/> |
4939 | + </object> |
4940 | + <object class="IBObjectRecord"> |
4941 | + <int key="objectID">4</int> |
4942 | + <reference key="object" ref="95160719"/> |
4943 | + <array class="NSMutableArray" key="children"/> |
4944 | + <reference key="parent" ref="0"/> |
4945 | + </object> |
4946 | + <object class="IBObjectRecord"> |
4947 | + <int key="objectID">9</int> |
4948 | + <reference key="object" ref="1003077660"/> |
4949 | + <array class="NSMutableArray" key="children"> |
4950 | + <reference ref="131881887"/> |
4951 | + <reference ref="1037320153"/> |
4952 | + </array> |
4953 | + <reference key="parent" ref="0"/> |
4954 | + </object> |
4955 | + <object class="IBObjectRecord"> |
4956 | + <int key="objectID">10</int> |
4957 | + <reference key="object" ref="131881887"/> |
4958 | + <reference key="parent" ref="1003077660"/> |
4959 | + </object> |
4960 | + <object class="IBObjectRecord"> |
4961 | + <int key="objectID">11</int> |
4962 | + <reference key="object" ref="1037320153"/> |
4963 | + <reference key="parent" ref="1003077660"/> |
4964 | + </object> |
4965 | + <object class="IBObjectRecord"> |
4966 | + <int key="objectID">5</int> |
4967 | + <reference key="object" ref="824354941"/> |
4968 | + <array class="NSMutableArray" key="children"> |
4969 | + <reference ref="54616486"/> |
4970 | + <reference ref="129966493"/> |
4971 | + <reference ref="135648369"/> |
4972 | + </array> |
4973 | + <reference key="parent" ref="0"/> |
4974 | + </object> |
4975 | + <object class="IBObjectRecord"> |
4976 | + <int key="objectID">8</int> |
4977 | + <reference key="object" ref="54616486"/> |
4978 | + <reference key="parent" ref="824354941"/> |
4979 | + </object> |
4980 | + <object class="IBObjectRecord"> |
4981 | + <int key="objectID">6</int> |
4982 | + <reference key="object" ref="129966493"/> |
4983 | + <reference key="parent" ref="824354941"/> |
4984 | + </object> |
4985 | + <object class="IBObjectRecord"> |
4986 | + <int key="objectID">19</int> |
4987 | + <reference key="object" ref="135648369"/> |
4988 | + <reference key="parent" ref="824354941"/> |
4989 | + </object> |
4990 | + </array> |
4991 | + </object> |
4992 | + <dictionary class="NSMutableDictionary" key="flattenedProperties"> |
4993 | + <string key="-1.CustomClassName">U1LocalAssetsViewController</string> |
4994 | + <string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
4995 | + <string key="-2.CustomClassName">UIResponder</string> |
4996 | + <string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
4997 | + <string key="10.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
4998 | + <string key="11.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
4999 | + <string key="19.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
5000 | + <string key="4.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> |
+1, let's do this!