Merge lp:~urbanape/ubuntuone-ios-files/auto-upload-pics into lp:ubuntuone-ios-files
- auto-upload-pics
- Merge into trunk
Proposed by
Zachery Bir
Status: | Merged |
---|---|
Merge reported by: | Zachery Bir |
Merged at revision: | not available |
Proposed branch: | lp:~urbanape/ubuntuone-ios-files/auto-upload-pics |
Merge into: | lp:ubuntuone-ios-files |
Diff against target: |
1698 lines (+1018/-63) 26 files modified
Files.xcodeproj/project.pbxproj (+33/-3) Files/Files-Info.plist (+9/-1) Files/FilesAppDelegate.m (+89/-29) Files/Generated/_U1Asset.h (+76/-0) Files/Generated/_U1Asset.m (+64/-0) Files/Generated/_U1Volume.h (+16/-1) Files/Generated/_U1Volume.m (+7/-0) Files/U1Asset.h (+5/-0) Files/U1Asset.m (+7/-0) Files/U1AssetUploadOperation.h (+25/-0) Files/U1AssetUploadOperation.m (+74/-0) Files/U1DataRepository.h (+5/-1) Files/U1DataRepository.m (+53/-0) Files/U1FilePreviewViewController.m (+1/-0) Files/U1Files.xcdatamodeld/.xccurrentversion (+1/-1) Files/U1FilesClient.h (+6/-1) Files/U1FilesClient.m (+124/-8) Files/U1FilesService.h (+5/-3) Files/U1FilesService.m (+77/-1) Files/U1FolderViewController.m (+1/-1) Files/U1LocalAssetsManager.h (+29/-0) Files/U1LocalAssetsManager.m (+209/-0) Files/U1Volume.h (+18/-1) Files/U1Volume.m (+53/-1) Files/U1VolumesViewController.h (+4/-3) Files/U1VolumesViewController.m (+27/-8) |
To merge this branch: | bzr merge lp:~urbanape/ubuntuone-ios-files/auto-upload-pics |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jason Foreman (community) | Approve | ||
Review via email: mp+77757@code.launchpad.net |
Commit message
Description of the change
This branch adds rough auto-upload of the user's photo library (only photos, no video).
It provides no feedback or controls to cancel the operation yet, and is very, very chatty.
To post a comment you must log in.
Revision history for this message
Zachery Bir (urbanape) wrote : | # |
- 36. By Zachery Bir
-
Renamed to match the new bundle version
- 37. By Zachery Bir
-
Renamed data model
- 38. By Zachery Bir
-
Updated bundle version
- 39. By Zachery Bir
-
No longer a private property
- 40. By Zachery Bir
-
Using a FilesClient, rather than the bare FilesService
- 41. By Zachery Bir
-
Move the static variable outside the implementation, and close an errant code block
- 42. By Zachery Bir
-
Uncomment the icon block
- 43. By Zachery Bir
-
Updates to make build more better good.
Revision history for this message
Jason Foreman (threeve) wrote : | # |
I've ended up un-singletonizing (just the bits about overriding retain/release) in a later changeset, but otherwise looks good.
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'Files.xcodeproj/project.pbxproj' |
2 | --- Files.xcodeproj/project.pbxproj 2011-09-27 14:36:00 +0000 |
3 | +++ Files.xcodeproj/project.pbxproj 2011-10-04 14:38:28 +0000 |
4 | @@ -7,6 +7,11 @@ |
5 | objects = { |
6 | |
7 | /* Begin PBXBuildFile section */ |
8 | + 91A5E2DC142A70DF00EAAC2B /* U1LocalAssetsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 91A5E2DB142A70DF00EAAC2B /* U1LocalAssetsManager.m */; }; |
9 | + 91A5E2DF142B727600EAAC2B /* U1AssetUploadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 91A5E2DE142B727500EAAC2B /* U1AssetUploadOperation.m */; }; |
10 | + 91B3F2D5141E87F900939B3C /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91B3F2D4141E87F900939B3C /* AssetsLibrary.framework */; }; |
11 | + 91B3F2DC141FDFAB00939B3C /* _U1Asset.m in Sources */ = {isa = PBXBuildFile; fileRef = 91B3F2DB141FDFAB00939B3C /* _U1Asset.m */; }; |
12 | + 91B3F2DF141FDFBE00939B3C /* U1Asset.m in Sources */ = {isa = PBXBuildFile; fileRef = 91B3F2DE141FDFBE00939B3C /* U1Asset.m */; }; |
13 | 960D46131409E0E100B73177 /* PullRefreshTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 960D46001409E09F00B73177 /* PullRefreshTableViewController.m */; }; |
14 | 960D46141409E0F000B73177 /* arrow.png in Resources */ = {isa = PBXBuildFile; fileRef = 960D45FB1409E09F00B73177 /* arrow.png */; }; |
15 | 960D46161409E10200B73177 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 960D46151409E10200B73177 /* QuartzCore.framework */; }; |
16 | @@ -116,6 +121,15 @@ |
17 | /* End PBXContainerItemProxy section */ |
18 | |
19 | /* Begin PBXFileReference section */ |
20 | + 91A5E2DB142A70DF00EAAC2B /* U1LocalAssetsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1LocalAssetsManager.m; sourceTree = "<group>"; }; |
21 | + 91A5E2DD142B727500EAAC2B /* U1AssetUploadOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1AssetUploadOperation.h; sourceTree = "<group>"; }; |
22 | + 91A5E2DE142B727500EAAC2B /* U1AssetUploadOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1AssetUploadOperation.m; sourceTree = "<group>"; }; |
23 | + 91B3F2D4141E87F900939B3C /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; |
24 | + 91B3F2D7141FC9BE00939B3C /* U1LocalAssetsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1LocalAssetsManager.h; sourceTree = "<group>"; }; |
25 | + 91B3F2DA141FDFAB00939B3C /* _U1Asset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _U1Asset.h; sourceTree = "<group>"; }; |
26 | + 91B3F2DB141FDFAB00939B3C /* _U1Asset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _U1Asset.m; sourceTree = "<group>"; }; |
27 | + 91B3F2DD141FDFBE00939B3C /* U1Asset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1Asset.h; sourceTree = "<group>"; }; |
28 | + 91B3F2DE141FDFBE00939B3C /* U1Asset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1Asset.m; sourceTree = "<group>"; }; |
29 | 960D45FA1409E09F00B73177 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = "<group>"; }; |
30 | 960D45FB1409E09F00B73177 /* arrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = arrow.png; sourceTree = "<group>"; }; |
31 | 960D45FD1409E09F00B73177 /* DemoTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoTableViewController.h; sourceTree = "<group>"; }; |
32 | @@ -194,6 +208,7 @@ |
33 | 96A1699F1430C9C900E4C990 /* 265-download@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "265-download@2x.png"; path = "Assets/265-download@2x.png"; sourceTree = "<group>"; }; |
34 | 96A169A21430D53600E4C990 /* U1LocalFileInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = U1LocalFileInfo.h; sourceTree = "<group>"; }; |
35 | 96A169A31430D53600E4C990 /* U1LocalFileInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = U1LocalFileInfo.m; sourceTree = "<group>"; }; |
36 | + 96A56430143265B4007A1A93 /* U1Files 1.0-3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "U1Files 1.0-3.xcdatamodel"; sourceTree = "<group>"; }; |
37 | 96CC17C71417E5E400EFC1BA /* U1Files.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = U1Files.xcdatamodel; sourceTree = "<group>"; }; |
38 | 96CC17CB1417EA0700EFC1BA /* _U1FileNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _U1FileNode.h; sourceTree = "<group>"; }; |
39 | 96CC17CC1417EA0700EFC1BA /* _U1FileNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _U1FileNode.m; sourceTree = "<group>"; }; |
40 | @@ -292,6 +307,7 @@ |
41 | isa = PBXFrameworksBuildPhase; |
42 | buildActionMask = 2147483647; |
43 | files = ( |
44 | + 91B3F2D5141E87F900939B3C /* AssetsLibrary.framework in Frameworks */, |
45 | 96CC17D81417EA2B00EFC1BA /* CoreData.framework in Frameworks */, |
46 | 96733B12140DFD6D0074D545 /* Security.framework in Frameworks */, |
47 | 960D46161409E10200B73177 /* QuartzCore.framework in Frameworks */, |
48 | @@ -350,6 +366,8 @@ |
49 | 96CC17CA1417E9E500EFC1BA /* Generated */, |
50 | 96CC17DF1418091100EFC1BA /* Parsers */, |
51 | 96CC17C61417E5E400EFC1BA /* U1Files.xcdatamodeld */, |
52 | + 91B3F2DD141FDFBE00939B3C /* U1Asset.h */, |
53 | + 91B3F2DE141FDFBE00939B3C /* U1Asset.m */, |
54 | 96CC17D91417EBF500EFC1BA /* U1Volume.h */, |
55 | 96CC17DA1417EBF500EFC1BA /* U1Volume.m */, |
56 | 960D4629140D99DB00B73177 /* U1Node.h */, |
57 | @@ -407,6 +425,8 @@ |
58 | 96CC17CA1417E9E500EFC1BA /* Generated */ = { |
59 | isa = PBXGroup; |
60 | children = ( |
61 | + 91B3F2DA141FDFAB00939B3C /* _U1Asset.h */, |
62 | + 91B3F2DB141FDFAB00939B3C /* _U1Asset.m */, |
63 | 96CC17CB1417EA0700EFC1BA /* _U1FileNode.h */, |
64 | 96CC17CC1417EA0700EFC1BA /* _U1FileNode.m */, |
65 | 96CC17CD1417EA0700EFC1BA /* _U1FolderNode.h */, |
66 | @@ -451,6 +471,7 @@ |
67 | 96E860B413F7251D0026783D /* Frameworks */ = { |
68 | isa = PBXGroup; |
69 | children = ( |
70 | + 91B3F2D4141E87F900939B3C /* AssetsLibrary.framework */, |
71 | 96CC17D71417EA2B00EFC1BA /* CoreData.framework */, |
72 | 96733B11140DFD6D0074D545 /* Security.framework */, |
73 | 960D46151409E10200B73177 /* QuartzCore.framework */, |
74 | @@ -486,6 +507,8 @@ |
75 | 96E8614213F728380026783D /* U1FilesService.m */, |
76 | 96CC17E314180C5F00EFC1BA /* U1FilesClient.h */, |
77 | 96CC17E414180C5F00EFC1BA /* U1FilesClient.m */, |
78 | + 91B3F2D7141FC9BE00939B3C /* U1LocalAssetsManager.h */, |
79 | + 91A5E2DB142A70DF00EAAC2B /* U1LocalAssetsManager.m */, |
80 | 969EF22613F8C10C00CEF6CB /* U1VolumesViewController.h */, |
81 | 969EF22713F8C10C00CEF6CB /* U1VolumesViewController.m */, |
82 | 969EF22813F8C10C00CEF6CB /* U1VolumesViewController.xib */, |
83 | @@ -498,6 +521,8 @@ |
84 | 960D4624140D8AF200B73177 /* U1ByteSizeValueTransformer.m */, |
85 | 960D4626140D8B4400B73177 /* U1FriendlyDateValueTransformer.h */, |
86 | 960D4627140D8B4400B73177 /* U1FriendlyDateValueTransformer.m */, |
87 | + 91A5E2DD142B727500EAAC2B /* U1AssetUploadOperation.h */, |
88 | + 91A5E2DE142B727500EAAC2B /* U1AssetUploadOperation.m */, |
89 | 965D7EB71429690C00E4754F /* U1NavigationBar.h */, |
90 | 965D7EB81429690C00E4754F /* U1NavigationBar.m */, |
91 | 96A169A21430D53600E4C990 /* U1LocalFileInfo.h */, |
92 | @@ -818,6 +843,10 @@ |
93 | 96CC17DE1417EF7200EFC1BA /* U1DataRepository.m in Sources */, |
94 | 96CC17E21418094800EFC1BA /* U1NodeJSONParser.m in Sources */, |
95 | 96CC17E514180C6000EFC1BA /* U1FilesClient.m in Sources */, |
96 | + 91B3F2DC141FDFAB00939B3C /* _U1Asset.m in Sources */, |
97 | + 91B3F2DF141FDFBE00939B3C /* U1Asset.m in Sources */, |
98 | + 91A5E2DC142A70DF00EAAC2B /* U1LocalAssetsManager.m in Sources */, |
99 | + 91A5E2DF142B727600EAAC2B /* U1AssetUploadOperation.m in Sources */, |
100 | 965D7EB91429690C00E4754F /* U1NavigationBar.m in Sources */, |
101 | 96A169A41430D53700E4C990 /* U1LocalFileInfo.m in Sources */, |
102 | ); |
103 | @@ -939,14 +968,14 @@ |
104 | 96E860F013F7251D0026783D /* Release */ = { |
105 | isa = XCBuildConfiguration; |
106 | buildSettings = { |
107 | - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; |
108 | + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Zachery Bir (P7WDPDEFHU)"; |
109 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
110 | GCC_PREFIX_HEADER = "Files/Files-Prefix.pch"; |
111 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; |
112 | INFOPLIST_FILE = "Files/Files-Info.plist"; |
113 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; |
114 | PRODUCT_NAME = "$(TARGET_NAME)"; |
115 | - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; |
116 | + "PROVISIONING_PROFILE[sdk=iphoneos*]" = "84E0B7E6-02A2-46EF-9C76-AA80C48130A7"; |
117 | TARGETED_DEVICE_FAMILY = 1; |
118 | WRAPPER_EXTENSION = app; |
119 | }; |
120 | @@ -1022,9 +1051,10 @@ |
121 | 96CC17C61417E5E400EFC1BA /* U1Files.xcdatamodeld */ = { |
122 | isa = XCVersionGroup; |
123 | children = ( |
124 | + 96A56430143265B4007A1A93 /* U1Files 1.0-3.xcdatamodel */, |
125 | 96CC17C71417E5E400EFC1BA /* U1Files.xcdatamodel */, |
126 | ); |
127 | - currentVersion = 96CC17C71417E5E400EFC1BA /* U1Files.xcdatamodel */; |
128 | + currentVersion = 96A56430143265B4007A1A93 /* U1Files 1.0-3.xcdatamodel */; |
129 | path = U1Files.xcdatamodeld; |
130 | sourceTree = "<group>"; |
131 | versionGroupType = wrapper.xcdatamodel; |
132 | |
133 | === modified file 'Files/Files-Info.plist' |
134 | --- Files/Files-Info.plist 2011-09-27 14:42:09 +0000 |
135 | +++ Files/Files-Info.plist 2011-10-04 14:38:28 +0000 |
136 | @@ -6,6 +6,8 @@ |
137 | <string>en</string> |
138 | <key>CFBundleDisplayName</key> |
139 | <string>${PRODUCT_NAME}</string> |
140 | + <key>CFBundleDocumentTypes</key> |
141 | + <array/> |
142 | <key>CFBundleExecutable</key> |
143 | <string>${EXECUTABLE_NAME}</string> |
144 | <key>CFBundleIconFile</key> |
145 | @@ -22,8 +24,10 @@ |
146 | <string>1.0</string> |
147 | <key>CFBundleSignature</key> |
148 | <string>????</string> |
149 | + <key>CFBundleURLTypes</key> |
150 | + <array/> |
151 | <key>CFBundleVersion</key> |
152 | - <string>2</string> |
153 | + <string>3</string> |
154 | <key>LSRequiresIPhoneOS</key> |
155 | <true/> |
156 | <key>NSMainNibFile</key> |
157 | @@ -43,5 +47,9 @@ |
158 | <string>UIInterfaceOrientationLandscapeLeft</string> |
159 | <string>UIInterfaceOrientationLandscapeRight</string> |
160 | </array> |
161 | + <key>UTExportedTypeDeclarations</key> |
162 | + <array/> |
163 | + <key>UTImportedTypeDeclarations</key> |
164 | + <array/> |
165 | </dict> |
166 | </plist> |
167 | |
168 | === modified file 'Files/FilesAppDelegate.m' |
169 | --- Files/FilesAppDelegate.m 2011-09-27 14:36:00 +0000 |
170 | +++ Files/FilesAppDelegate.m 2011-10-04 14:38:28 +0000 |
171 | @@ -13,6 +13,10 @@ |
172 | // You should have received a copy of the GNU Affero General Public License |
173 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
174 | |
175 | +#import <AssetsLibrary/ALAssetsLibrary.h> |
176 | +#import <AssetsLibrary/ALAssetsGroup.h> |
177 | +#import <AssetsLibrary/ALAsset.h> |
178 | + |
179 | #import "FilesAppDelegate.h" |
180 | |
181 | #import "U1AccountManager.h" |
182 | @@ -20,35 +24,41 @@ |
183 | #import "U1FileNode.h" |
184 | #import "U1FilePreviewViewController.h" |
185 | #import "U1FilesClient.h" |
186 | +#import "U1LocalAssetsManager.h" |
187 | #import "U1FilesService.h" |
188 | #import "U1FolderNode.h" |
189 | #import "U1FolderViewController.h" |
190 | #import "U1LoginController.h" |
191 | #import "U1Node.h" |
192 | #import "U1VolumesViewController.h" |
193 | +#import "U1Volume.h" |
194 | |
195 | |
196 | @interface FilesAppDelegate () <U1FolderViewControllerDelegate, U1VolumesViewControllerDelegate, U1LoginControllerDelegate> |
197 | @property (retain) U1FilesService *filesService; |
198 | @property (retain) U1FilesClient *filesClient; |
199 | +@property (retain) U1LocalAssetsManager *localAssetsManager; |
200 | @property (retain) U1LoginController *loginController; |
201 | @property (retain) U1DataRepository *dataRepository; |
202 | -- (NSURL*)dataStoreURL; |
203 | - (void)showVolumes; |
204 | - (void)showLoginController; |
205 | +- (void)ensureUploadFolder; |
206 | +- (NSString*)remoteUploadFolderPath; |
207 | +- (NSString*)localUploadQueuePath; |
208 | @end |
209 | |
210 | |
211 | @implementation FilesAppDelegate |
212 | |
213 | @synthesize window; |
214 | -@synthesize filesService, filesClient, navController, loginController, dataRepository; |
215 | +@synthesize filesService, filesClient, localAssetsManager, navController, loginController, dataRepository; |
216 | |
217 | - (void)dealloc |
218 | { |
219 | [window release]; |
220 | [filesService release]; |
221 | [filesClient release]; |
222 | + [localAssetsManager release]; |
223 | [navController release]; |
224 | [loginController release]; |
225 | [dataRepository release]; |
226 | @@ -59,51 +69,104 @@ |
227 | { |
228 | [self.window makeKeyAndVisible]; |
229 | |
230 | + return YES; |
231 | +} |
232 | + |
233 | +- (void)applicationDidBecomeActive:(UIApplication *)application; |
234 | +{ |
235 | if (![[U1AccountManager sharedAccountManager] hasCredentials]) |
236 | { |
237 | [self showLoginController]; |
238 | } |
239 | else |
240 | { |
241 | - [self showVolumes]; |
242 | + self.filesService = [U1FilesService sharedFilesService]; |
243 | + self.filesClient = [U1FilesClient sharedFilesClient]; |
244 | + |
245 | + self.localAssetsManager = [U1LocalAssetsManager sharedFilesManager]; |
246 | + NSLog(@"Showing Volumes: Reading localAssetsToUpload from filesystem."); |
247 | + NSMutableArray *uploadQueue = [NSMutableArray arrayWithContentsOfFile:[self localUploadQueuePath]]; |
248 | + if (uploadQueue != nil) { |
249 | + NSLog(@"Retrieved the upload queue from the filesystem."); |
250 | + NSLog(@"Length of the array on filesystem: %d", [uploadQueue count]); |
251 | + self.localAssetsManager.localAssetsToUpload = uploadQueue; |
252 | + NSLog(@"Read in the file, now we delete it."); |
253 | + NSError *error = nil; |
254 | + [[NSFileManager defaultManager] removeItemAtPath:[self localUploadQueuePath] error:&error]; |
255 | + } |
256 | + |
257 | + [self ensureUploadFolder]; |
258 | } |
259 | - |
260 | - return YES; |
261 | +} |
262 | + |
263 | +- (void)ensureUploadFolder; |
264 | +{ |
265 | + [self.filesClient volumesWithCompletionBlock:^(NSArray *volumeInfos, NSError *error) { |
266 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
267 | + // iterate over volumeInfos. If there isn't one there called "Pictures - <device name>", create it. |
268 | + BOOL found = NO; |
269 | + NSLog(@"Walking the volumes, to see if it has been created already."); |
270 | + for (U1Volume *volume in volumeInfos) { |
271 | + if ([volume.path isEqualToString:[self remoteUploadFolderPath]]) |
272 | + { |
273 | + NSLog(@"Found the volume. No need to try to create it."); |
274 | + found = YES; |
275 | + self.localAssetsManager.remoteUploadVolume = volume; |
276 | + break; |
277 | + } |
278 | + } |
279 | + if (!found) |
280 | + { |
281 | + NSLog(@"Didn't find the volume. Creating it."); |
282 | + [self.filesClient createVolumeAtPath:[self remoteUploadFolderPath] |
283 | + completionBlock:^(U1Volume *volume, NSError *error) { |
284 | + self.localAssetsManager.remoteUploadVolume = volume; |
285 | + [self.localAssetsManager uploadPendingAssets]; |
286 | + [self.localAssetsManager checkForNewAssets]; |
287 | + NSLog(@"Error: %@", error); |
288 | + }]; |
289 | + } else |
290 | + { |
291 | + [self.localAssetsManager uploadPendingAssets]; |
292 | + [self.localAssetsManager checkForNewAssets]; |
293 | + } |
294 | + [self showVolumes]; |
295 | + }); |
296 | + }]; |
297 | +} |
298 | + |
299 | +- (NSString *)remoteUploadFolderPath; |
300 | +{ |
301 | + return [NSString stringWithFormat:@"/~/Pictures - %@", [[UIDevice currentDevice] name]]; |
302 | +} |
303 | + |
304 | +- (NSString*)localUploadQueuePath; |
305 | +{ |
306 | + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); |
307 | + return [[paths objectAtIndex:0] stringByAppendingPathComponent:@"localAssetsToUpload.array"]; |
308 | } |
309 | |
310 | - (void)applicationWillResignActive:(UIApplication *)application; |
311 | { |
312 | [self.dataRepository save:NULL]; |
313 | + NSLog(@"Application Resigning: Writing localAssetsToUpload (%d items) to the filesystem.", [self.localAssetsManager.localAssetsToUpload count]); |
314 | + [self.localAssetsManager.localAssetsToUpload writeToFile:[self localUploadQueuePath] atomically:YES]; |
315 | + // serialize self.filesManager's localAssetsToUpload to the filesystem |
316 | } |
317 | |
318 | - (void)applicationWillTerminate:(UIApplication *)application; |
319 | { |
320 | // TODO: check error |
321 | [self.dataRepository save:NULL]; |
322 | -} |
323 | - |
324 | -- (NSURL*)dataStoreURL; |
325 | -{ |
326 | - NSURL *cachesDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject]; |
327 | - NSURL *storeURL = [NSURL URLWithString:@"U1Files.sqlite" relativeToURL:cachesDirectory]; |
328 | - return storeURL; |
329 | + NSLog(@"Application Terminating: Writing localAssetsToUpload (%d items) to the filesystem.", [self.localAssetsManager.localAssetsToUpload count]); |
330 | + [self.localAssetsManager.localAssetsToUpload writeToFile:[self localUploadQueuePath] atomically:YES]; |
331 | + // serialize self.filesManager's localAssetsToUpload to the filesystem |
332 | } |
333 | |
334 | - (void)showVolumes; |
335 | { |
336 | - filesService = [U1FilesService new]; |
337 | - |
338 | - NSURL *storeURL = [self dataStoreURL]; |
339 | - self.dataRepository = [[U1DataRepository alloc] initWithStoreURL:storeURL]; |
340 | - [dataRepository release]; |
341 | - |
342 | - filesClient = [[U1FilesClient alloc] init]; |
343 | - [self.filesClient setFilesService:filesService]; |
344 | - [self.filesClient setDataRepository:self.dataRepository]; |
345 | - |
346 | U1VolumesViewController *rootController = [U1VolumesViewController new]; |
347 | rootController.delegate = self; |
348 | - rootController.filesService = self.filesService; |
349 | |
350 | [self.navController setViewControllers:[NSArray arrayWithObject:rootController] animated:NO]; |
351 | } |
352 | @@ -119,7 +182,7 @@ |
353 | { |
354 | [self.navController dismissModalViewControllerAnimated:YES]; |
355 | self.loginController = nil; |
356 | - [self showVolumes]; |
357 | + [self applicationDidBecomeActive:nil]; |
358 | } |
359 | |
360 | |
361 | @@ -130,14 +193,12 @@ |
362 | if ([node isFolder]) |
363 | { |
364 | U1FolderViewController *nextFolderController = [[U1FolderViewController alloc] initWithNodeResourcePath:node.resourcePath]; |
365 | - nextFolderController.filesClient = self.filesClient; |
366 | nextFolderController.delegate = self; |
367 | [self.navController pushViewController:nextFolderController animated:YES]; |
368 | } |
369 | else if ([node isFile]) |
370 | { |
371 | U1FilePreviewViewController *fileController = [[U1FilePreviewViewController alloc] initWithNode:(id)node]; |
372 | - fileController.filesClient = self.filesClient; |
373 | [self.navController pushViewController:fileController animated:YES]; |
374 | } |
375 | } |
376 | @@ -145,11 +206,10 @@ |
377 | |
378 | #pragma mark U1VolumesControllerDelegate Methods |
379 | |
380 | -- (void)volumesController:(U1VolumesViewController *)volumesController didSelectVolume:(NSDictionary *)volume; |
381 | +- (void)volumesController:(U1VolumesViewController *)volumesController didSelectVolume:(U1Volume *)volume; |
382 | { |
383 | - NSString *nodePath = [volume objectForKey:@"node_path"]; |
384 | + NSString *nodePath = volume.nodePath; |
385 | U1FolderViewController *folderController = [[U1FolderViewController alloc] initWithNodeResourcePath:nodePath]; |
386 | - folderController.filesClient = self.filesClient; |
387 | folderController.delegate = self; |
388 | [self.navController pushViewController:folderController animated:YES]; |
389 | } |
390 | |
391 | === added file 'Files/Generated/_U1Asset.h' |
392 | --- Files/Generated/_U1Asset.h 1970-01-01 00:00:00 +0000 |
393 | +++ Files/Generated/_U1Asset.h 2011-10-04 14:38:28 +0000 |
394 | @@ -0,0 +1,76 @@ |
395 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
396 | +// Make changes to U1Asset.h instead. |
397 | + |
398 | +#import <CoreData/CoreData.h> |
399 | + |
400 | + |
401 | + |
402 | + |
403 | + |
404 | + |
405 | + |
406 | +@interface U1AssetID : NSManagedObjectID {} |
407 | +@end |
408 | + |
409 | +@interface _U1Asset : NSManagedObject {} |
410 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_; |
411 | ++ (NSString*)entityName; |
412 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_; |
413 | +- (U1AssetID*)objectID; |
414 | + |
415 | + |
416 | + |
417 | + |
418 | +@property (nonatomic, retain) NSString *filename; |
419 | + |
420 | + |
421 | +//- (BOOL)validateFilename:(id*)value_ error:(NSError**)error_; |
422 | + |
423 | + |
424 | + |
425 | + |
426 | +@property (nonatomic, retain) NSString *groupId; |
427 | + |
428 | + |
429 | +//- (BOOL)validateGroupId:(id*)value_ error:(NSError**)error_; |
430 | + |
431 | + |
432 | + |
433 | + |
434 | +@property (nonatomic, retain) NSString *url; |
435 | + |
436 | + |
437 | +//- (BOOL)validateUrl:(id*)value_ error:(NSError**)error_; |
438 | + |
439 | + |
440 | + |
441 | + |
442 | + |
443 | +@end |
444 | + |
445 | +@interface _U1Asset (CoreDataGeneratedAccessors) |
446 | + |
447 | +@end |
448 | + |
449 | +@interface _U1Asset (CoreDataGeneratedPrimitiveAccessors) |
450 | + |
451 | + |
452 | +- (NSString*)primitiveFilename; |
453 | +- (void)setPrimitiveFilename:(NSString*)value; |
454 | + |
455 | + |
456 | + |
457 | + |
458 | +- (NSString*)primitiveGroupId; |
459 | +- (void)setPrimitiveGroupId:(NSString*)value; |
460 | + |
461 | + |
462 | + |
463 | + |
464 | +- (NSString*)primitiveUrl; |
465 | +- (void)setPrimitiveUrl:(NSString*)value; |
466 | + |
467 | + |
468 | + |
469 | + |
470 | +@end |
471 | |
472 | === added file 'Files/Generated/_U1Asset.m' |
473 | --- Files/Generated/_U1Asset.m 1970-01-01 00:00:00 +0000 |
474 | +++ Files/Generated/_U1Asset.m 2011-10-04 14:38:28 +0000 |
475 | @@ -0,0 +1,64 @@ |
476 | +// DO NOT EDIT. This file is machine-generated and constantly overwritten. |
477 | +// Make changes to U1Asset.m instead. |
478 | + |
479 | +#import "_U1Asset.h" |
480 | + |
481 | +@implementation U1AssetID |
482 | +@end |
483 | + |
484 | +@implementation _U1Asset |
485 | + |
486 | ++ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
487 | + NSParameterAssert(moc_); |
488 | + return [NSEntityDescription insertNewObjectForEntityForName:@"Asset" inManagedObjectContext:moc_]; |
489 | +} |
490 | + |
491 | ++ (NSString*)entityName { |
492 | + return @"Asset"; |
493 | +} |
494 | + |
495 | ++ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_ { |
496 | + NSParameterAssert(moc_); |
497 | + return [NSEntityDescription entityForName:@"Asset" inManagedObjectContext:moc_]; |
498 | +} |
499 | + |
500 | +- (U1AssetID*)objectID { |
501 | + return (U1AssetID*)[super objectID]; |
502 | +} |
503 | + |
504 | ++ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { |
505 | + NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; |
506 | + |
507 | + |
508 | + return keyPaths; |
509 | +} |
510 | + |
511 | + |
512 | + |
513 | + |
514 | +@dynamic filename; |
515 | + |
516 | + |
517 | + |
518 | + |
519 | + |
520 | + |
521 | +@dynamic groupId; |
522 | + |
523 | + |
524 | + |
525 | + |
526 | + |
527 | + |
528 | +@dynamic url; |
529 | + |
530 | + |
531 | + |
532 | + |
533 | + |
534 | + |
535 | + |
536 | + |
537 | + |
538 | + |
539 | +@end |
540 | |
541 | === modified file 'Files/Generated/_U1Volume.h' |
542 | --- Files/Generated/_U1Volume.h 2011-09-08 16:59:34 +0000 |
543 | +++ Files/Generated/_U1Volume.h 2011-10-04 14:38:28 +0000 |
544 | @@ -2,6 +2,7 @@ |
545 | // Make changes to U1Volume.h instead. |
546 | |
547 | #import <CoreData/CoreData.h> |
548 | +#import "U1Node.h" |
549 | |
550 | |
551 | |
552 | @@ -9,7 +10,7 @@ |
553 | @interface U1VolumeID : NSManagedObjectID {} |
554 | @end |
555 | |
556 | -@interface _U1Volume : NSManagedObject {} |
557 | +@interface _U1Volume : U1Node {} |
558 | + (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_; |
559 | + (NSString*)entityName; |
560 | + (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_; |
561 | @@ -18,6 +19,14 @@ |
562 | |
563 | |
564 | |
565 | +@property (nonatomic, retain) NSString *nodePath; |
566 | + |
567 | + |
568 | +//- (BOOL)validateNodePath:(id*)value_ error:(NSError**)error_; |
569 | + |
570 | + |
571 | + |
572 | + |
573 | |
574 | @end |
575 | |
576 | @@ -28,4 +37,10 @@ |
577 | @interface _U1Volume (CoreDataGeneratedPrimitiveAccessors) |
578 | |
579 | |
580 | +- (NSString*)primitiveNodePath; |
581 | +- (void)setPrimitiveNodePath:(NSString*)value; |
582 | + |
583 | + |
584 | + |
585 | + |
586 | @end |
587 | |
588 | === modified file 'Files/Generated/_U1Volume.m' |
589 | --- Files/Generated/_U1Volume.m 2011-09-08 16:59:34 +0000 |
590 | +++ Files/Generated/_U1Volume.m 2011-10-04 14:38:28 +0000 |
591 | @@ -36,6 +36,13 @@ |
592 | |
593 | |
594 | |
595 | +@dynamic nodePath; |
596 | + |
597 | + |
598 | + |
599 | + |
600 | + |
601 | + |
602 | |
603 | |
604 | |
605 | |
606 | === added file 'Files/U1Asset.h' |
607 | --- Files/U1Asset.h 1970-01-01 00:00:00 +0000 |
608 | +++ Files/U1Asset.h 2011-10-04 14:38:28 +0000 |
609 | @@ -0,0 +1,5 @@ |
610 | +#import "_U1Asset.h" |
611 | + |
612 | +@interface U1Asset : _U1Asset {} |
613 | +// Custom logic goes here. |
614 | +@end |
615 | |
616 | === added file 'Files/U1Asset.m' |
617 | --- Files/U1Asset.m 1970-01-01 00:00:00 +0000 |
618 | +++ Files/U1Asset.m 2011-10-04 14:38:28 +0000 |
619 | @@ -0,0 +1,7 @@ |
620 | +#import "U1Asset.h" |
621 | + |
622 | +@implementation U1Asset |
623 | + |
624 | +// Custom logic goes here. |
625 | + |
626 | +@end |
627 | |
628 | === added file 'Files/U1AssetUploadOperation.h' |
629 | --- Files/U1AssetUploadOperation.h 1970-01-01 00:00:00 +0000 |
630 | +++ Files/U1AssetUploadOperation.h 2011-10-04 14:38:28 +0000 |
631 | @@ -0,0 +1,25 @@ |
632 | +// |
633 | +// U1AssetUploadOperation.h |
634 | +// Files |
635 | +// |
636 | +// Created by Zachery Bir on 9/22/11. |
637 | +// Copyright 2011 __MyCompanyName__. All rights reserved. |
638 | +// |
639 | + |
640 | +#import <Foundation/Foundation.h> |
641 | +#import <AssetsLibrary/AssetsLibrary.h> |
642 | + |
643 | +@class U1Asset; |
644 | +@class U1FolderNode; |
645 | + |
646 | +@interface U1AssetUploadOperation : NSOperation { |
647 | +@private |
648 | + |
649 | +} |
650 | +@property (retain) ALAssetRepresentation *representation; |
651 | +@property (retain) NSData *assetData; |
652 | +@property (retain) U1Asset *asset; |
653 | +@property (retain) U1FolderNode *folder; |
654 | +@property (retain) NSString *filename; |
655 | +@property (retain) NSError *error; |
656 | +@end |
657 | |
658 | === added file 'Files/U1AssetUploadOperation.m' |
659 | --- Files/U1AssetUploadOperation.m 1970-01-01 00:00:00 +0000 |
660 | +++ Files/U1AssetUploadOperation.m 2011-10-04 14:38:28 +0000 |
661 | @@ -0,0 +1,74 @@ |
662 | +// |
663 | +// U1AssetUploadOperation.m |
664 | +// Files |
665 | +// |
666 | +// Created by Zachery Bir on 9/22/11. |
667 | +// Copyright 2011 __MyCompanyName__. All rights reserved. |
668 | +// |
669 | + |
670 | +#import "U1AssetUploadOperation.h" |
671 | +#import "U1Asset.h" |
672 | +#import "U1FilesClient.h" |
673 | + |
674 | +@interface U1AssetUploadOperation () |
675 | +@property (getter=isExecuting) BOOL executing; |
676 | +@property (getter=isFinished) BOOL finished; |
677 | +- (void)finishExecuting; |
678 | +@end |
679 | + |
680 | +@implementation U1AssetUploadOperation |
681 | + |
682 | +@synthesize executing, finished, asset, assetData, representation, folder, filename, error; |
683 | + |
684 | +- (id)init |
685 | +{ |
686 | + self = [super init]; |
687 | + if (self) { |
688 | + // Initialization code here. |
689 | + } |
690 | + |
691 | + return self; |
692 | +} |
693 | + |
694 | +- (BOOL)isConcurrent; |
695 | +{ |
696 | + return YES; |
697 | +} |
698 | + |
699 | +- (void)finishExecuting; |
700 | +{ |
701 | + [self willChangeValueForKey:@"isExecuting"]; |
702 | + [self willChangeValueForKey:@"isFinished"]; |
703 | + self.finished = YES; |
704 | + self.executing = NO; |
705 | + [self didChangeValueForKey:@"isFinished"]; |
706 | + [self didChangeValueForKey:@"isExecuting"]; |
707 | +// [UONetworkStatusCoordinator removeNetworkActivity]; |
708 | +} |
709 | + |
710 | +- (void)start; |
711 | +{ |
712 | + // Trigger the filesClient to upload our asset, setting the completion block to marking ourself completed. |
713 | + [self willChangeValueForKey:@"isExecuting"]; |
714 | + self.executing = YES; |
715 | + [self didChangeValueForKey:@"isExecuting"]; |
716 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
717 | + U1FilesClient *filesClient = [U1FilesClient sharedFilesClient]; |
718 | + [filesClient uploadContentData:self.assetData |
719 | + toFolder:self.folder withResourceName:self.filename progressBlock:^(long long bytesUploaded, long long totalBytes) { |
720 | + dispatch_async(dispatch_get_main_queue(), ^(void){ |
721 | + NSLog(@"Uploaded %lld of %lld for %@", bytesUploaded, totalBytes, self.filename); |
722 | + }); |
723 | + } completionBlock:^(U1FileNode *updatedNode, NSError *uploadError) { |
724 | + self.error = uploadError; |
725 | + [self finishExecuting]; |
726 | + }]; |
727 | + }); |
728 | +} |
729 | + |
730 | +- (void)dealloc |
731 | +{ |
732 | + [super dealloc]; |
733 | +} |
734 | + |
735 | +@end |
736 | |
737 | === modified file 'Files/U1DataRepository.h' |
738 | --- Files/U1DataRepository.h 2011-09-08 16:59:34 +0000 |
739 | +++ Files/U1DataRepository.h 2011-10-04 14:38:28 +0000 |
740 | @@ -20,12 +20,16 @@ |
741 | |
742 | |
743 | @interface U1DataRepository : NSObject |
744 | - |
745 | ++ (U1DataRepository*)sharedDataRepository; |
746 | - (id)initWithStoreURL:(NSURL*)storeURL; |
747 | - (BOOL)save:(NSError**)error; |
748 | |
749 | - (U1Node*)nodeWithResourcePath:(NSString*)resourcePath; |
750 | |
751 | +//- (void)fetchResultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors completionBlock:(void(^)(NSArray *results, NSError *error))completionBlock; |
752 | + |
753 | +- (NSArray*)resultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error; |
754 | + |
755 | - (void)dispatchBlockWithManagedObjectContext:(void(^)(NSManagedObjectContext *context))block; |
756 | |
757 | - (void)dispatchAsyncBlockWithManagedObjectContext:(void(^)(NSManagedObjectContext *context))block; |
758 | |
759 | === modified file 'Files/U1DataRepository.m' |
760 | --- Files/U1DataRepository.m 2011-09-08 16:59:34 +0000 |
761 | +++ Files/U1DataRepository.m 2011-10-04 14:38:28 +0000 |
762 | @@ -19,6 +19,7 @@ |
763 | |
764 | #import "U1Node.h" |
765 | |
766 | +static U1DataRepository *sharedDataRepository = nil; |
767 | |
768 | @interface U1DataRepository () |
769 | |
770 | @@ -35,6 +36,48 @@ |
771 | |
772 | @synthesize model, mainContext, storeCoordinator; |
773 | |
774 | ++ (U1DataRepository*)sharedDataRepository; |
775 | +{ |
776 | + if (sharedDataRepository == nil) |
777 | + { |
778 | + NSURL *cachesDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory |
779 | + inDomains:NSUserDomainMask] lastObject]; |
780 | + NSURL *storeURL = [NSURL URLWithString:@"U1Files.sqlite" relativeToURL:cachesDirectory]; |
781 | + sharedDataRepository = [[super allocWithZone:NULL] initWithStoreURL:storeURL]; |
782 | + } |
783 | + return sharedDataRepository; |
784 | +} |
785 | + |
786 | ++ (id)allocWithZone:(NSZone *)zone; |
787 | +{ |
788 | + return [[self sharedDataRepository] retain]; |
789 | +} |
790 | + |
791 | +- (id)copyWithZone:(NSZone *)zone; |
792 | +{ |
793 | + return self; |
794 | +} |
795 | + |
796 | +- (id)retain; |
797 | +{ |
798 | + return self; |
799 | +} |
800 | + |
801 | +- (NSUInteger)retainCount; |
802 | +{ |
803 | + return NSUIntegerMax; |
804 | +} |
805 | + |
806 | +- (void)release; |
807 | +{ |
808 | + |
809 | +} |
810 | + |
811 | +- (id)autorelease; |
812 | +{ |
813 | + return self; |
814 | +} |
815 | + |
816 | - (id)initWithStoreURL:(NSURL*)storeURL; |
817 | { |
818 | if (!(self = [super init])) |
819 | @@ -93,6 +136,16 @@ |
820 | return node; |
821 | } |
822 | |
823 | +//- (void)fetchResultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors completionBlock:(void(^)(NSArray *results, NSError *error))completionBlock; |
824 | +//{ |
825 | +// |
826 | +//} |
827 | + |
828 | +- (NSArray*)resultsForEntityClass:(Class)entityClass matchingPredicate:(NSPredicate*)predicate withSortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error; |
829 | +{ |
830 | + return [self fetchEntitiesForClass:entityClass inContext:self.mainContext withPredicate:predicate sortDescriptors:sortDescriptors error:error]; |
831 | +} |
832 | + |
833 | - (NSArray*)fetchEntitiesForClass:(Class)class inContext:(NSManagedObjectContext*)context withPredicate:(NSPredicate*)predicate sortDescriptors:(NSArray*)sortDescriptors error:(NSError**)error; |
834 | { |
835 | NSParameterAssert(class != nil); |
836 | |
837 | === modified file 'Files/U1FilePreviewViewController.m' |
838 | --- Files/U1FilePreviewViewController.m 2011-09-27 14:36:00 +0000 |
839 | +++ Files/U1FilePreviewViewController.m 2011-10-04 14:38:28 +0000 |
840 | @@ -78,6 +78,7 @@ |
841 | self = [super initWithNibName:@"U1FilePreviewViewController" bundle:nil]; |
842 | if (self == nil) |
843 | return nil; |
844 | + filesClient = [U1FilesClient sharedFilesClient]; |
845 | self.node = theNode; |
846 | self.title = [node.path lastPathComponent]; |
847 | |
848 | |
849 | === modified file 'Files/U1Files.xcdatamodeld/.xccurrentversion' |
850 | --- Files/U1Files.xcdatamodeld/.xccurrentversion 2011-09-08 16:59:34 +0000 |
851 | +++ Files/U1Files.xcdatamodeld/.xccurrentversion 2011-10-04 14:38:28 +0000 |
852 | @@ -3,6 +3,6 @@ |
853 | <plist version="1.0"> |
854 | <dict> |
855 | <key>_XCCurrentVersionName</key> |
856 | - <string>U1Files.xcdatamodel</string> |
857 | + <string>U1Files 1.0-3.xcdatamodel</string> |
858 | </dict> |
859 | </plist> |
860 | |
861 | === added directory 'Files/U1Files.xcdatamodeld/U1Files 1.0-3.xcdatamodel' |
862 | === added file 'Files/U1Files.xcdatamodeld/U1Files 1.0-3.xcdatamodel/elements' |
863 | 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-10-04 14:38:28 +0000 differ |
864 | === added file 'Files/U1Files.xcdatamodeld/U1Files 1.0-3.xcdatamodel/layout' |
865 | 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-10-04 14:38:28 +0000 differ |
866 | === modified file 'Files/U1Files.xcdatamodeld/U1Files.xcdatamodel/elements' |
867 | Binary files Files/U1Files.xcdatamodeld/U1Files.xcdatamodel/elements 2011-09-08 16:59:34 +0000 and Files/U1Files.xcdatamodeld/U1Files.xcdatamodel/elements 2011-10-04 14:38:28 +0000 differ |
868 | === modified file 'Files/U1Files.xcdatamodeld/U1Files.xcdatamodel/layout' |
869 | Binary files Files/U1Files.xcdatamodeld/U1Files.xcdatamodel/layout 2011-09-08 16:59:34 +0000 and Files/U1Files.xcdatamodeld/U1Files.xcdatamodel/layout 2011-10-04 14:38:28 +0000 differ |
870 | === modified file 'Files/U1FilesClient.h' |
871 | --- Files/U1FilesClient.h 2011-09-27 14:36:00 +0000 |
872 | +++ Files/U1FilesClient.h 2011-10-04 14:38:28 +0000 |
873 | @@ -16,7 +16,7 @@ |
874 | #import <Foundation/Foundation.h> |
875 | |
876 | @class NSFetchedResultsController; |
877 | -@class U1Node, U1FileNode, U1FolderNode, U1NodeChildrenResultSet, U1LocalFileInfo; |
878 | +@class U1Node, U1FileNode, U1FolderNode, U1NodeChildrenResultSet, U1Volume, U1LocalFileInfo; |
879 | @class U1DataRepository, U1FilesService; |
880 | |
881 | |
882 | @@ -25,11 +25,16 @@ |
883 | @property (retain) U1DataRepository *dataRepository; |
884 | @property (retain) U1FilesService *filesService; |
885 | |
886 | ++ (U1FilesClient *)sharedFilesClient; |
887 | + |
888 | +- (id)volumesWithCompletionBlock:(void(^)(NSArray *volumes, NSError *error))completionBlock; |
889 | - (id)fetchNodeWithResourcePath:(NSString*)nodePath completionBlock:(void(^)(U1Node *node, NSFetchedResultsController *childrenResultsController, NSError *error))completionBlock; |
890 | - (id)deleteNode:(U1Node*)node completionBlock:(void(^)(NSError *error))completionBlock; |
891 | - (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; |
892 | - (id)publishNode:(U1FileNode*)node completionBlock:(void(^)(U1FileNode *node, NSError *error))completionBlock; |
893 | - (id)unpublishNode:(U1FileNode*)node completionBlock:(void(^)(U1FileNode *node, NSError *error))completionBlock; |
894 | +- (id)createFolderNamed:(NSString*)name inFolder:(U1FolderNode*)folderNode completionBlock:(void(^)(U1FolderNode *newFolderNode, NSError *error))completionBlock; |
895 | +- (id)createVolumeAtPath:(NSString*)folderPath completionBlock:(void(^)(U1Volume *volume, NSError *error))completionBlock; |
896 | - (BOOL)isNodeSavedLocally:(U1FileNode*)node; |
897 | - (U1LocalFileInfo*)localInfoForNode:(U1FileNode*)node; |
898 | |
899 | |
900 | === modified file 'Files/U1FilesClient.m' |
901 | --- Files/U1FilesClient.m 2011-09-27 14:36:00 +0000 |
902 | +++ Files/U1FilesClient.m 2011-10-04 14:38:28 +0000 |
903 | @@ -23,22 +23,93 @@ |
904 | #import "U1FolderNode.h" |
905 | #import "U1LocalFileInfo.h" |
906 | #import "U1Node.h" |
907 | +#import "U1Volume.h" |
908 | |
909 | |
910 | @interface U1FilesClient () |
911 | - (NSURL*)fileURLForNode:(U1FileNode*)node; |
912 | @end |
913 | |
914 | +static U1FilesClient *sharedFilesClient = nil; |
915 | |
916 | @implementation U1FilesClient |
917 | |
918 | @synthesize dataRepository, filesService; |
919 | |
920 | -- (void)dealloc; |
921 | -{ |
922 | - [dataRepository release]; |
923 | - [filesService release]; |
924 | - [super dealloc]; |
925 | ++ (U1FilesClient*)sharedFilesClient; |
926 | +{ |
927 | + if (sharedFilesClient == nil) |
928 | + { |
929 | + sharedFilesClient = [[super allocWithZone:NULL] init]; |
930 | + } |
931 | + return sharedFilesClient; |
932 | +} |
933 | + |
934 | ++ (id)allocWithZone:(NSZone *)zone; |
935 | +{ |
936 | + return [[self sharedFilesClient] retain]; |
937 | +} |
938 | + |
939 | +- (id)copyWithZone:(NSZone *)zone; |
940 | +{ |
941 | + return self; |
942 | +} |
943 | + |
944 | +- (id)retain; |
945 | +{ |
946 | + return self; |
947 | +} |
948 | + |
949 | +- (NSUInteger)retainCount; |
950 | +{ |
951 | + return NSUIntegerMax; |
952 | +} |
953 | + |
954 | +- (void)release; |
955 | +{ |
956 | + |
957 | +} |
958 | + |
959 | +- (id)autorelease; |
960 | +{ |
961 | + return self; |
962 | +} |
963 | + |
964 | +- (id)init; |
965 | +{ |
966 | + self = [super init]; |
967 | + if (self == nil) |
968 | + return nil; |
969 | + dataRepository = [U1DataRepository sharedDataRepository]; |
970 | + filesService = [U1FilesService sharedFilesService]; |
971 | + return self; |
972 | +} |
973 | + |
974 | +- (id)volumesWithCompletionBlock:(void(^)(NSArray *volumes, NSError *error))completionBlock; |
975 | +{ |
976 | + NSParameterAssert(completionBlock != NULL); |
977 | + |
978 | + [self.filesService volumeInfoWithCompletionBlock:^(NSArray *volumeInfos, NSError *error) { |
979 | + |
980 | + NSMutableArray *volumes = [NSMutableArray array]; |
981 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
982 | + for (NSDictionary *volumeInfo in volumeInfos) |
983 | + { |
984 | + NSString *path = [volumeInfo objectForKey:@"path"]; |
985 | + NSPredicate *p = [NSPredicate predicateWithFormat:@"path = %@", path]; |
986 | + U1Volume *volume = [[self.dataRepository resultsForEntityClass:[U1Volume class] matchingPredicate:p withSortDescriptors:nil error:NULL] lastObject]; |
987 | + if (!volume) |
988 | + { |
989 | + volume = [U1Volume insertInManagedObjectContext:context]; |
990 | + } |
991 | + [volume updatePropertiesFromJSONDictionary:volumeInfo]; |
992 | + [volumes addObject:volume]; |
993 | + } |
994 | + [context save:NULL]; |
995 | + }]; |
996 | + completionBlock(volumes, error); |
997 | + }]; |
998 | + return nil; |
999 | } |
1000 | |
1001 | - (id)fetchNodeWithResourcePath:(NSString*)nodePath completionBlock:(void(^)(U1Node *node, NSFetchedResultsController *childrenResultsController, NSError *error))completionBlock; |
1002 | @@ -144,9 +215,18 @@ |
1003 | } |
1004 | |
1005 | return [self.filesService uploadContentData:contentData forNode:node progressBlock:progressBlock completionBlock:^(NSDictionary *updatedNodeInfo, NSError *error) { |
1006 | - |
1007 | - [node updatePropertiesFromJSONDictionary:updatedNodeInfo]; |
1008 | - completionBlock(node, error); |
1009 | + if (error != nil) |
1010 | + { |
1011 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
1012 | + [context deleteObject:node]; |
1013 | + }]; |
1014 | + completionBlock(nil, error); |
1015 | + } |
1016 | + else |
1017 | + { |
1018 | + [node updatePropertiesFromJSONDictionary:updatedNodeInfo]; |
1019 | + completionBlock(node, error); |
1020 | + } |
1021 | }]; |
1022 | } |
1023 | |
1024 | @@ -160,6 +240,42 @@ |
1025 | return [self.filesService unpublishNode:node completionBlock:completionBlock]; |
1026 | } |
1027 | |
1028 | +- (id)createFolderNamed:(NSString*)name inFolder:(U1FolderNode*)folderNode completionBlock:(void(^)(U1FolderNode *newFolderNode, NSError *error))completionBlock; |
1029 | +{ |
1030 | + NSString *resourcePath = folderNode.resourcePath; |
1031 | + resourcePath = [resourcePath stringByAppendingPathComponent:name]; |
1032 | + |
1033 | + U1FolderNode *node = (id)[self.dataRepository nodeWithResourcePath:resourcePath]; |
1034 | + if (!node) |
1035 | + { |
1036 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
1037 | + U1FolderNode *newNode = [U1FolderNode insertInManagedObjectContext:context]; |
1038 | + newNode.resourcePath = resourcePath; |
1039 | + newNode.kind = @"directory"; |
1040 | + newNode.contentPath = [folderNode.contentPath stringByAppendingPathComponent:name]; |
1041 | + newNode.parent = folderNode; |
1042 | + [context save:NULL]; |
1043 | + }]; |
1044 | + node = (id)[self.dataRepository nodeWithResourcePath:resourcePath]; |
1045 | + } |
1046 | + |
1047 | + return [self.filesService createFolderAtPath:resourcePath completionBlock:^(NSDictionary *nodeInfo, NSError *error) { |
1048 | + [node updatePropertiesFromJSONDictionary:nodeInfo]; |
1049 | + completionBlock(node, error); |
1050 | + }]; |
1051 | +} |
1052 | + |
1053 | +- (id)createVolumeAtPath:(NSString*)folderPath completionBlock:(void(^)(U1Volume *volume, NSError *error))completionBlock; |
1054 | +{ |
1055 | + return [self.filesService createVolumeAtPath:folderPath completionBlock:^(NSDictionary *volumeInfo, NSError *error) { |
1056 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
1057 | + U1Volume *volume = [U1Volume insertInManagedObjectContext:context]; |
1058 | + [volume updatePropertiesFromJSONDictionary:volumeInfo]; |
1059 | + completionBlock(volume, error); |
1060 | + }]; |
1061 | + }]; |
1062 | +} |
1063 | + |
1064 | - (BOOL)isNodeSavedLocally:(U1FileNode*)node; |
1065 | { |
1066 | NSString *contentPath = node.contentPath; |
1067 | |
1068 | === modified file 'Files/U1FilesService.h' |
1069 | --- Files/U1FilesService.h 2011-09-08 16:59:34 +0000 |
1070 | +++ Files/U1FilesService.h 2011-10-04 14:38:28 +0000 |
1071 | @@ -15,12 +15,12 @@ |
1072 | |
1073 | #import <Foundation/Foundation.h> |
1074 | |
1075 | -@class U1Node, U1FileNode; |
1076 | +@class U1Node, U1FileNode, U1FolderNode; |
1077 | |
1078 | |
1079 | @interface U1FilesService : NSObject |
1080 | - |
1081 | -- (id)volumeInfoWithCompletionBlock:(void(^)(NSArray *volumeInfo, NSError *error))completionBlock; |
1082 | ++ (U1FilesService *)sharedFilesService; |
1083 | +- (id)volumeInfoWithCompletionBlock:(void(^)(NSArray *volumeInfos, NSError *error))completionBlock; |
1084 | |
1085 | - (id)infoForNodeAtResourcePath:(NSString*)resourcePath includeChildren:(BOOL)includeChildren completionBlock:(void(^)(NSDictionary *node, NSError *error))completionBlock; |
1086 | - (id)infoForNode:(U1Node*)node includeChildren:(BOOL)includeChildren completionBlock:(void(^)(NSDictionary *node, NSError *error))completionBlock; |
1087 | @@ -30,5 +30,7 @@ |
1088 | - (id)deleteNodeAtResourcePath:(NSString*)resourcePath completionBlock:(void(^)(NSError *error))completionBlock; |
1089 | - (id)publishNode:(U1FileNode*)node completionBlock:(void(^)(U1FileNode *node, NSError *error))completionBlock; |
1090 | - (id)unpublishNode:(U1FileNode*)node completionBlock:(void(^)(U1FileNode *node, NSError *error))completionBlock; |
1091 | +- (id)createFolderAtPath:(NSString*)folderPath completionBlock:(void(^)(NSDictionary *nodeInfo, NSError *error))completionBlock; |
1092 | +- (id)createVolumeAtPath:(NSString*)folderPath completionBlock:(void(^)(NSDictionary *volumeInfo, NSError *error))completionBlock; |
1093 | |
1094 | @end |
1095 | |
1096 | === modified file 'Files/U1FilesService.m' |
1097 | --- Files/U1FilesService.m 2011-09-27 14:36:00 +0000 |
1098 | +++ Files/U1FilesService.m 2011-10-04 14:38:28 +0000 |
1099 | @@ -23,11 +23,13 @@ |
1100 | #import "U1Node.h" |
1101 | #import "U1FileNode.h" |
1102 | |
1103 | +static U1FilesService *sharedFilesService = nil; |
1104 | |
1105 | @interface U1FilesService () |
1106 | |
1107 | @property (retain) NSOperationQueue *networkQueue; |
1108 | |
1109 | +- (NSURL*)URLForVolumeWithPath:(NSString*)volumePath; |
1110 | - (NSURL*)URLForNode:(NSString*)nodePath includeChildren:(BOOL)includeChildren; |
1111 | - (id)execute:(NSString*)method toURL:(NSURL*)url withParameters:(NSDictionary*)parameters requestBody:(NSString*)body parseResponseBody:(BOOL)parseResponseBody completionBlock:(void(^)(id results, NSError *error))completionBlock; |
1112 | - (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; |
1113 | @@ -44,6 +46,45 @@ |
1114 | |
1115 | @synthesize networkQueue; |
1116 | |
1117 | ++ (U1FilesService*)sharedFilesService; |
1118 | +{ |
1119 | + if (sharedFilesService == nil) |
1120 | + { |
1121 | + sharedFilesService = [[super allocWithZone:NULL] init]; |
1122 | + } |
1123 | + return sharedFilesService; |
1124 | +} |
1125 | + |
1126 | ++ (id)allocWithZone:(NSZone *)zone; |
1127 | +{ |
1128 | + return [[self sharedFilesService] retain]; |
1129 | +} |
1130 | + |
1131 | +- (id)copyWithZone:(NSZone *)zone; |
1132 | +{ |
1133 | + return self; |
1134 | +} |
1135 | + |
1136 | +- (id)retain; |
1137 | +{ |
1138 | + return self; |
1139 | +} |
1140 | + |
1141 | +- (NSUInteger)retainCount; |
1142 | +{ |
1143 | + return NSUIntegerMax; |
1144 | +} |
1145 | + |
1146 | +- (void)release; |
1147 | +{ |
1148 | + |
1149 | +} |
1150 | + |
1151 | +- (id)autorelease; |
1152 | +{ |
1153 | + return self; |
1154 | +} |
1155 | + |
1156 | - (id)init; |
1157 | { |
1158 | self = [super init]; |
1159 | @@ -59,7 +100,7 @@ |
1160 | [super dealloc]; |
1161 | } |
1162 | |
1163 | -- (id)volumeInfoWithCompletionBlock:(void(^)(NSArray *volumeInfo, NSError *error))completionBlock; |
1164 | +- (id)volumeInfoWithCompletionBlock:(void(^)(NSArray *volumeInfos, NSError *error))completionBlock; |
1165 | { |
1166 | NSURL *volumesURL = [self URLForNode:@"/volumes" includeChildren:NO]; |
1167 | return [self execute:@"GET" toURL:volumesURL withParameters:nil requestBody:nil parseResponseBody:YES completionBlock:^(id results, NSError *error) { |
1168 | @@ -205,9 +246,44 @@ |
1169 | }]; |
1170 | } |
1171 | |
1172 | +- (id)createFolderAtPath:(NSString*)folderPath completionBlock:(void(^)(NSDictionary *nodeInfo, NSError *error))completionBlock; |
1173 | +{ |
1174 | + NSParameterAssert(folderPath != nil); |
1175 | + NSParameterAssert(completionBlock != NULL); |
1176 | + |
1177 | + NSURL *nodeURL = [self URLForNode:folderPath includeChildren:NO]; |
1178 | + return [self execute:@"PUT" toURL:nodeURL withParameters:nil requestBody:@"{\"kind\": \"directory\"}" parseResponseBody:YES completionBlock:^(id results, NSError *error) { |
1179 | + completionBlock(results, error); |
1180 | + }]; |
1181 | +} |
1182 | + |
1183 | +- (id)createVolumeAtPath:(NSString*)volumePath completionBlock:(void(^)(NSDictionary *volumeInfo, NSError *error))completionBlock; |
1184 | +{ |
1185 | + NSParameterAssert(volumePath != nil); |
1186 | + NSParameterAssert(completionBlock != NULL); |
1187 | + |
1188 | + NSURL *volumeURL = [self URLForVolumeWithPath:volumePath]; |
1189 | + return [self execute:@"PUT" toURL:volumeURL withParameters:nil requestBody:@"" parseResponseBody:YES completionBlock:^(id results, NSError *error) { |
1190 | + completionBlock(results, error); |
1191 | + }]; |
1192 | +} |
1193 | + |
1194 | |
1195 | #pragma mark Private Methods |
1196 | |
1197 | +- (NSURL*)URLForVolumeWithPath:(NSString*)volumePath; |
1198 | +{ |
1199 | + NSParameterAssert(volumePath != nil); |
1200 | + NSParameterAssert([volumePath hasPrefix:@"/"]); |
1201 | + |
1202 | + NSMutableString *urlString = [NSMutableString stringWithString:U1FilesServiceAPIBase]; |
1203 | + [urlString appendString:U1FilesServiceAPIPath]; |
1204 | + [urlString appendString:U1FilesServiceAPIVersion1]; |
1205 | + [urlString appendString:@"/volumes"]; |
1206 | + [urlString appendString:volumePath]; |
1207 | + return [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; |
1208 | +} |
1209 | + |
1210 | - (NSURL*)URLForNode:(NSString*)nodePath includeChildren:(BOOL)includeChildren; |
1211 | { |
1212 | NSMutableString *urlString = [NSMutableString stringWithString:U1FilesServiceAPIBase]; |
1213 | |
1214 | === modified file 'Files/U1FolderViewController.m' |
1215 | --- Files/U1FolderViewController.m 2011-09-27 14:36:00 +0000 |
1216 | +++ Files/U1FolderViewController.m 2011-10-04 14:38:28 +0000 |
1217 | @@ -50,6 +50,7 @@ |
1218 | self.title = [theResourcePath lastPathComponent]; |
1219 | self.resourcePath = [theResourcePath copy]; |
1220 | self.byteSizeTransformer = [[U1ByteSizeValueTransformer new] autorelease]; |
1221 | + filesClient = [U1FilesClient sharedFilesClient]; |
1222 | |
1223 | UIBarButtonItem *uploadItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(uploadImage:)]; |
1224 | [self.navigationItem setRightBarButtonItem:uploadItem]; |
1225 | @@ -74,7 +75,6 @@ |
1226 | - (void)dealloc; |
1227 | { |
1228 | [loadingCell release]; |
1229 | - [filesClient release]; |
1230 | [resourcePath release]; |
1231 | [node release]; |
1232 | [byteSizeTransformer release]; |
1233 | |
1234 | === added file 'Files/U1LocalAssetsManager.h' |
1235 | --- Files/U1LocalAssetsManager.h 1970-01-01 00:00:00 +0000 |
1236 | +++ Files/U1LocalAssetsManager.h 2011-10-04 14:38:28 +0000 |
1237 | @@ -0,0 +1,29 @@ |
1238 | +// |
1239 | +// Copyright 2011 Canonical Ltd. |
1240 | +// |
1241 | +// This program is free software: you can redistribute it and/or modify it |
1242 | +// under the terms of the GNU Affero General Public License version 3, |
1243 | +// as published by the Free Software Foundation. |
1244 | +// |
1245 | +// This program is distributed in the hope that it will be useful, but |
1246 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
1247 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1248 | +// PURPOSE. See the GNU Affero General Public License for more details. |
1249 | +// |
1250 | +// You should have received a copy of the GNU Affero General Public License |
1251 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1252 | + |
1253 | +#import <Foundation/Foundation.h> |
1254 | + |
1255 | +@class U1DataRepository; |
1256 | +@class U1Volume; |
1257 | + |
1258 | + |
1259 | +@interface U1LocalAssetsManager : NSObject |
1260 | +@property (retain) U1DataRepository *dataRepository; |
1261 | +@property (retain) NSMutableArray *localAssetsToUpload; |
1262 | +@property (retain) U1Volume *remoteUploadVolume; |
1263 | ++ (U1LocalAssetsManager *)sharedFilesManager; |
1264 | +- (void)checkForNewAssets; |
1265 | +- (void)uploadPendingAssets; |
1266 | +@end |
1267 | |
1268 | === added file 'Files/U1LocalAssetsManager.m' |
1269 | --- Files/U1LocalAssetsManager.m 1970-01-01 00:00:00 +0000 |
1270 | +++ Files/U1LocalAssetsManager.m 2011-10-04 14:38:28 +0000 |
1271 | @@ -0,0 +1,209 @@ |
1272 | +// |
1273 | +// Copyright 2011 Canonical Ltd. |
1274 | +// |
1275 | +// This program is free software: you can redistribute it and/or modify it |
1276 | +// under the terms of the GNU Affero General Public License version 3, |
1277 | +// as published by the Free Software Foundation. |
1278 | +// |
1279 | +// This program is distributed in the hope that it will be useful, but |
1280 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
1281 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1282 | +// PURPOSE. See the GNU Affero General Public License for more details. |
1283 | +// |
1284 | +// You should have received a copy of the GNU Affero General Public License |
1285 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1286 | + |
1287 | +#import <AssetsLibrary/AssetsLibrary.h> |
1288 | + |
1289 | +#import "U1Asset.h" |
1290 | +#import "U1DataRepository.h" |
1291 | +#import "U1LocalAssetsManager.h" |
1292 | +#import "U1AssetUploadOperation.h" |
1293 | +#import "U1FilesClient.h" |
1294 | +#import "U1Volume.h" |
1295 | + |
1296 | +@interface U1LocalAssetsManager () |
1297 | +@property (retain) ALAssetsLibrary *assetsLibrary; |
1298 | +@property (retain) NSOperationQueue *uploadQueue; |
1299 | +- (void)walkAssetsInLibrary; |
1300 | +- (void)uploadRepresentation:(ALAssetRepresentation*)rep forAsset:(U1Asset*)asset; |
1301 | +- (NSString *)generateFilenameForAsset:(ALAsset *)asset; |
1302 | +@end |
1303 | + |
1304 | +static U1LocalAssetsManager *sharedFilesManager = nil; |
1305 | + |
1306 | +@implementation U1LocalAssetsManager |
1307 | + |
1308 | +@synthesize dataRepository, uploadQueue, localAssetsToUpload, remoteUploadVolume; |
1309 | +@synthesize assetsLibrary; |
1310 | + |
1311 | ++ (U1LocalAssetsManager *)sharedFilesManager; |
1312 | +{ |
1313 | + if (sharedFilesManager == nil) |
1314 | + { |
1315 | + sharedFilesManager = [[super allocWithZone:NULL] init]; |
1316 | + } |
1317 | + return sharedFilesManager; |
1318 | +} |
1319 | + |
1320 | ++ (id)allocWithZone:(NSZone *)zone; |
1321 | +{ |
1322 | + return [[self sharedFilesManager] retain]; |
1323 | +} |
1324 | + |
1325 | +- (id)copyWithZone:(NSZone *)zone; |
1326 | +{ |
1327 | + return self; |
1328 | +} |
1329 | + |
1330 | +- (id)retain; |
1331 | +{ |
1332 | + return self; |
1333 | +} |
1334 | + |
1335 | +- (NSUInteger)retainCount; |
1336 | +{ |
1337 | + return NSUIntegerMax; |
1338 | +} |
1339 | + |
1340 | +- (void)release; |
1341 | +{ |
1342 | + |
1343 | +} |
1344 | + |
1345 | +- (id)autorelease; |
1346 | +{ |
1347 | + return self; |
1348 | +} |
1349 | + |
1350 | +- (id)init |
1351 | +{ |
1352 | + if (!(self = [super init])) |
1353 | + return nil; |
1354 | + |
1355 | + assetsLibrary = [[ALAssetsLibrary alloc] init]; |
1356 | + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(libraryChanged:) name:ALAssetsLibraryChangedNotification object:assetsLibrary]; |
1357 | + dataRepository = [U1DataRepository sharedDataRepository]; |
1358 | + uploadQueue = [[NSOperationQueue alloc] init]; |
1359 | + self.localAssetsToUpload = [NSMutableArray array]; |
1360 | + return self; |
1361 | +} |
1362 | + |
1363 | +- (void)dealloc |
1364 | +{ |
1365 | + [[NSNotificationCenter defaultCenter] removeObserver:self]; |
1366 | + [assetsLibrary release]; |
1367 | + [super dealloc]; |
1368 | +} |
1369 | + |
1370 | +- (void)checkForNewAssets; |
1371 | +{ |
1372 | + NSLog(@"Checking for new assets."); |
1373 | + [self walkAssetsInLibrary]; |
1374 | +} |
1375 | + |
1376 | +- (void)libraryChanged:(NSNotification*)notification; |
1377 | +{ |
1378 | + NSLog(@"The library changed, so we'll walk the assets again."); |
1379 | + [self walkAssetsInLibrary]; |
1380 | +} |
1381 | + |
1382 | +- (void)walkAssetsInLibrary; |
1383 | +{ |
1384 | + [self.assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos |
1385 | + usingBlock:^(ALAssetsGroup *group, BOOL *stop) { |
1386 | + [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop) { |
1387 | + |
1388 | + ALAsset *someAsset = asset; |
1389 | + if (someAsset == nil) |
1390 | + return; |
1391 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
1392 | + ALAssetRepresentation *defaultRep = [someAsset defaultRepresentation]; |
1393 | + NSString *assetURL = [[defaultRep url] absoluteString]; |
1394 | + NSString *groupId = [group valueForProperty:ALAssetsGroupPropertyPersistentID]; |
1395 | + |
1396 | + NSPredicate *p = [NSPredicate predicateWithFormat:@"groupId = %@ and url = %@", |
1397 | + groupId, assetURL]; |
1398 | + NSError *error = nil; |
1399 | + NSArray *results = [self.dataRepository resultsForEntityClass:[U1Asset class] matchingPredicate:p withSortDescriptors:nil error:&error]; |
1400 | + U1Asset *trackedAsset = [results lastObject]; |
1401 | + NSLog(@"Did we find an asset? (%@)", [trackedAsset description]); |
1402 | + if (trackedAsset == nil) |
1403 | + { |
1404 | + if ([[someAsset valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto]) { |
1405 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
1406 | + |
1407 | + U1Asset *newAsset = [U1Asset insertInManagedObjectContext:context]; |
1408 | + newAsset.groupId = groupId; |
1409 | + newAsset.url = assetURL; |
1410 | + newAsset.filename = [self generateFilenameForAsset:someAsset]; |
1411 | + NSLog(@"Adding and uploading an asset for %@ (filename: %@)", newAsset.url, newAsset.filename); |
1412 | + [self.localAssetsToUpload addObject:newAsset]; |
1413 | + [self uploadRepresentation:defaultRep forAsset:newAsset]; |
1414 | + [self.dataRepository save:NULL]; |
1415 | + }]; |
1416 | + } |
1417 | + } |
1418 | + }); |
1419 | + }]; |
1420 | + } |
1421 | + failureBlock:^(NSError *error) { |
1422 | + NSLog(@"Some error happened."); |
1423 | + }]; |
1424 | +} |
1425 | + |
1426 | +- (NSString *)generateFilenameForAsset:(ALAsset *)asset; |
1427 | +{ |
1428 | + // get the type of the asset |
1429 | + NSString *ext = @"JPG"; |
1430 | + |
1431 | + if ([asset valueForProperty:ALAssetPropertyType] == ALAssetTypeVideo) { |
1432 | + ext = @"M4V"; |
1433 | + } |
1434 | + |
1435 | + NSError *error = nil; |
1436 | + int idx = [[self.dataRepository resultsForEntityClass:[U1Asset class] |
1437 | + matchingPredicate:nil |
1438 | + withSortDescriptors:nil |
1439 | + error:&error] count]; |
1440 | + |
1441 | + return [NSString stringWithFormat:@"IMG_%d.%@", idx, ext]; |
1442 | +} |
1443 | + |
1444 | +- (void)uploadPendingAssets; |
1445 | +{ |
1446 | + NSLog(@"Uploading %d assets", [self.localAssetsToUpload count]); |
1447 | + [self.localAssetsToUpload enumerateObjectsUsingBlock:^(U1Asset *obj, NSUInteger idx, BOOL *stop) { |
1448 | + [self.assetsLibrary assetForURL:[NSURL URLWithString:obj.url] |
1449 | + resultBlock:^(ALAsset *asset) { |
1450 | + [self uploadRepresentation:[asset defaultRepresentation] forAsset:obj]; |
1451 | + } failureBlock:^(NSError *error) { |
1452 | + NSLog(@"Error: %@", error); |
1453 | + }]; |
1454 | + }]; |
1455 | +} |
1456 | + |
1457 | +- (void)uploadRepresentation:(ALAssetRepresentation *)rep forAsset:(U1Asset *)asset |
1458 | +{ |
1459 | + // iterate self.localAssetsToUpload, creating NSOperations for each, giving each a completionBlock to remove the asset from localAssetsToUpload if it completed properly |
1460 | + Byte *buffer = (Byte*)malloc(rep.size); |
1461 | + NSUInteger length = [rep getBytes:buffer fromOffset:0 length:rep.size error:nil]; |
1462 | + NSData *assetData = [NSData dataWithBytesNoCopy:buffer length:length freeWhenDone:YES]; |
1463 | + |
1464 | + U1AssetUploadOperation *operation = [[U1AssetUploadOperation alloc] init]; |
1465 | + operation.asset = asset; |
1466 | + operation.folder = [self.remoteUploadVolume rootFolder]; |
1467 | + operation.filename = asset.filename; |
1468 | + operation.assetData = assetData; |
1469 | + [operation setCompletionBlock:^{ |
1470 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
1471 | + if (operation.error == nil) // or the error is somehow unrecoverable (e.g., over quota) |
1472 | + { |
1473 | + [self.localAssetsToUpload removeObject:asset]; |
1474 | + } |
1475 | + }); |
1476 | + }]; |
1477 | + [self.uploadQueue addOperation:operation]; |
1478 | +} |
1479 | + |
1480 | +@end |
1481 | |
1482 | === modified file 'Files/U1Volume.h' |
1483 | --- Files/U1Volume.h 2011-09-08 16:59:34 +0000 |
1484 | +++ Files/U1Volume.h 2011-10-04 14:38:28 +0000 |
1485 | @@ -1,5 +1,22 @@ |
1486 | +// |
1487 | +// Copyright 2011 Canonical Ltd. |
1488 | +// |
1489 | +// This program is free software: you can redistribute it and/or modify it |
1490 | +// under the terms of the GNU Affero General Public License version 3, |
1491 | +// as published by the Free Software Foundation. |
1492 | +// |
1493 | +// This program is distributed in the hope that it will be useful, but |
1494 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
1495 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1496 | +// PURPOSE. See the GNU Affero General Public License for more details. |
1497 | +// |
1498 | +// You should have received a copy of the GNU Affero General Public License |
1499 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1500 | + |
1501 | #import "_U1Volume.h" |
1502 | +#import "U1FolderNode.h" |
1503 | + |
1504 | |
1505 | @interface U1Volume : _U1Volume {} |
1506 | -// Custom logic goes here. |
1507 | +- (U1FolderNode *)rootFolder; |
1508 | @end |
1509 | |
1510 | === modified file 'Files/U1Volume.m' |
1511 | --- Files/U1Volume.m 2011-09-08 16:59:34 +0000 |
1512 | +++ Files/U1Volume.m 2011-10-04 14:38:28 +0000 |
1513 | @@ -1,7 +1,59 @@ |
1514 | +// |
1515 | +// Copyright 2011 Canonical Ltd. |
1516 | +// |
1517 | +// This program is free software: you can redistribute it and/or modify it |
1518 | +// under the terms of the GNU Affero General Public License version 3, |
1519 | +// as published by the Free Software Foundation. |
1520 | +// |
1521 | +// This program is distributed in the hope that it will be useful, but |
1522 | +// WITHOUT ANY WARRANTY; without even the implied warranties of |
1523 | +// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1524 | +// PURPOSE. See the GNU Affero General Public License for more details. |
1525 | +// |
1526 | +// You should have received a copy of the GNU Affero General Public License |
1527 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1528 | + |
1529 | #import "U1Volume.h" |
1530 | +#import "U1FolderNode.h" |
1531 | +#import "U1DataRepository.h" |
1532 | + |
1533 | |
1534 | @implementation U1Volume |
1535 | |
1536 | -// Custom logic goes here. |
1537 | +- (void)updatePropertiesFromJSONDictionary:(NSDictionary *)jsonDictionary; |
1538 | +{ |
1539 | + [super updatePropertiesFromJSONDictionary:jsonDictionary]; |
1540 | + self.nodePath = [jsonDictionary objectForKey:@"node_path"]; |
1541 | +} |
1542 | + |
1543 | +- (U1FolderNode *)rootFolder; |
1544 | +{ |
1545 | + // Look up a U1FolderNode with us as the volume path and some part of us as its name? |
1546 | + // If it doesn't exist, create it, and return it. |
1547 | + U1DataRepository *dataRepository = [U1DataRepository sharedDataRepository]; |
1548 | + NSPredicate *p = [NSPredicate predicateWithFormat:@"resourcePath = %@", self.nodePath]; |
1549 | + NSError *error = nil; |
1550 | + NSArray *results = [dataRepository resultsForEntityClass:[U1FolderNode class] matchingPredicate:p withSortDescriptors:nil error:&error]; |
1551 | + U1FolderNode *rootFolder = [results lastObject]; |
1552 | + NSLog(@"Did we find a root folder? (%@)", [rootFolder description]); |
1553 | + |
1554 | + if (rootFolder == nil) |
1555 | + { |
1556 | + // Upload |
1557 | + [dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
1558 | + |
1559 | + U1FolderNode *rootFolder = [U1FolderNode insertInManagedObjectContext:context]; |
1560 | + rootFolder.resourcePath = self.nodePath; |
1561 | + rootFolder.contentPath = self.contentPath; |
1562 | + NSLog(@"Adding a rootFolder node for %@", self.nodePath); |
1563 | + [dataRepository save:NULL]; |
1564 | + }]; |
1565 | + |
1566 | + results = [dataRepository resultsForEntityClass:[U1FolderNode class] matchingPredicate:p withSortDescriptors:nil error:&error]; |
1567 | + rootFolder = [results lastObject]; |
1568 | + } |
1569 | + |
1570 | + return rootFolder; |
1571 | +} |
1572 | |
1573 | @end |
1574 | |
1575 | === modified file 'Files/U1VolumesViewController.h' |
1576 | --- Files/U1VolumesViewController.h 2011-08-31 14:56:30 +0000 |
1577 | +++ Files/U1VolumesViewController.h 2011-10-04 14:38:28 +0000 |
1578 | @@ -17,7 +17,8 @@ |
1579 | |
1580 | #import "PullRefreshTableViewController.h" |
1581 | |
1582 | -@class U1FilesService; |
1583 | +@class U1FilesClient; |
1584 | +@class U1Volume; |
1585 | |
1586 | @protocol U1VolumesViewControllerDelegate; |
1587 | |
1588 | @@ -27,12 +28,12 @@ |
1589 | @property (nonatomic, retain, readonly) IBOutlet UITableViewCell *loadingCell; |
1590 | |
1591 | @property (assign) id<U1VolumesViewControllerDelegate> delegate; |
1592 | -@property (nonatomic, retain) U1FilesService *filesService; |
1593 | +@property (retain) U1FilesClient *filesClient; |
1594 | |
1595 | @end |
1596 | |
1597 | |
1598 | @protocol U1VolumesViewControllerDelegate <NSObject> |
1599 | @required |
1600 | -- (void)volumesController:(U1VolumesViewController*)volumesController didSelectVolume:(NSDictionary*)volume; |
1601 | +- (void)volumesController:(U1VolumesViewController*)volumesController didSelectVolume:(U1Volume*)volume; |
1602 | @end |
1603 | |
1604 | === modified file 'Files/U1VolumesViewController.m' |
1605 | --- Files/U1VolumesViewController.m 2011-09-27 14:36:00 +0000 |
1606 | +++ Files/U1VolumesViewController.m 2011-10-04 14:38:28 +0000 |
1607 | @@ -15,18 +15,20 @@ |
1608 | |
1609 | #import "U1VolumesViewController.h" |
1610 | |
1611 | -#import "U1FilesService.h" |
1612 | +#import "U1FilesClient.h" |
1613 | +#import "U1Volume.h" |
1614 | |
1615 | |
1616 | @interface U1VolumesViewController () |
1617 | @property (retain) NSArray *volumes; |
1618 | +- (void)loadVolumes; |
1619 | @end |
1620 | |
1621 | |
1622 | @implementation U1VolumesViewController |
1623 | |
1624 | @synthesize loadingCell; |
1625 | -@synthesize delegate, filesService; |
1626 | +@synthesize delegate, filesClient; |
1627 | @synthesize volumes; |
1628 | |
1629 | - (id)init; |
1630 | @@ -35,6 +37,7 @@ |
1631 | if (!self) |
1632 | return nil; |
1633 | self.title = NSLocalizedString(@"Home", @""); |
1634 | + filesClient = [U1FilesClient sharedFilesClient]; |
1635 | UIImage *logoImage = [UIImage imageNamed:@"logo_4_white"]; |
1636 | UIImageView *logoView = [[UIImageView alloc] initWithImage:logoImage]; |
1637 | [self.navigationItem setTitleView:logoView]; |
1638 | @@ -45,7 +48,6 @@ |
1639 | - (void)dealloc; |
1640 | { |
1641 | [loadingCell release]; |
1642 | - [filesService release]; |
1643 | [volumes release]; |
1644 | [super dealloc]; |
1645 | } |
1646 | @@ -53,12 +55,18 @@ |
1647 | - (void)viewDidLoad; |
1648 | { |
1649 | [super viewDidLoad]; |
1650 | - [self.filesService volumeInfoWithCompletionBlock:^(NSArray *volumeInfo, NSError *error) { |
1651 | + [self.filesClient volumesWithCompletionBlock:^(NSArray *volumeInfos, NSError *error) { |
1652 | dispatch_async(dispatch_get_main_queue(), ^(void) { |
1653 | - self.volumes = volumeInfo; |
1654 | + self.volumes = volumeInfos; |
1655 | [self.tableView reloadData]; |
1656 | }); |
1657 | }]; |
1658 | + [self loadVolumes]; |
1659 | +} |
1660 | + |
1661 | +- (void)refresh; |
1662 | +{ |
1663 | + [self loadVolumes]; |
1664 | } |
1665 | |
1666 | - (void)viewDidUnload; |
1667 | @@ -93,8 +101,8 @@ |
1668 | [cell setSelectionStyle:UITableViewCellSelectionStyleGray]; |
1669 | [cell.imageView setImage:[UIImage imageNamed:@"ic_folder"]]; |
1670 | } |
1671 | - NSDictionary *volume = [self.volumes objectAtIndex:indexPath.row]; |
1672 | - NSString *volumePath = [volume objectForKey:@"path"]; |
1673 | + U1Volume *volume = [self.volumes objectAtIndex:indexPath.row]; |
1674 | + NSString *volumePath = volume.path; |
1675 | if ([@"~/.ubuntuone/Purchased from Ubuntu One" isEqualToString:volumePath]) |
1676 | volumePath = @"Purchased Music"; |
1677 | if ([volumePath hasPrefix:@"~/"]) |
1678 | @@ -106,8 +114,19 @@ |
1679 | |
1680 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; |
1681 | { |
1682 | - NSDictionary *volume = [self.volumes objectAtIndex:indexPath.row]; |
1683 | + U1Volume *volume = [self.volumes objectAtIndex:indexPath.row]; |
1684 | [self.delegate volumesController:self didSelectVolume:volume]; |
1685 | } |
1686 | |
1687 | +- (void)loadVolumes; |
1688 | +{ |
1689 | + [self.filesClient volumesWithCompletionBlock:^(NSArray *volumeInfos, NSError *error) { |
1690 | + dispatch_async(dispatch_get_main_queue(), ^(void) { |
1691 | + self.volumes = volumeInfos; |
1692 | + [self stopLoading]; |
1693 | + [self.tableView reloadData]; |
1694 | + }); |
1695 | + }]; |
1696 | +} |
1697 | + |
1698 | @end |
Also, this branch Singletonizes a bunch of the classes we use.