~threeve/ubuntuone-ios-files/folder-info-footer

« back to all changes in this revision

Viewing changes to Files/U1LocalAssetsViewController.m

  • Committer: Zachery Bir
  • Date: 2011-11-01 14:28:05 UTC
  • mfrom: (6.2.116 auto-uploads-view)
  • Revision ID: zachery.bir@canonical.com-20111101142805-uyjwtzm552h638r2
Merged urbanape's auto-uploads-view branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
//  Copyright 2011 Canonical Ltd.
 
3
//      
 
4
//  This program is free software: you can redistribute it and/or modify it
 
5
//  under the terms of the GNU Affero General Public License version 3,
 
6
//  as published by the Free Software Foundation.
 
7
//      
 
8
//  This program is distributed in the hope that it will be useful, but
 
9
//  WITHOUT ANY WARRANTY; without even the implied warranties of
 
10
//  MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
11
//  PURPOSE.  See the GNU Affero General Public License for more details.
 
12
//
 
13
//  You should have received a copy of the GNU Affero General Public License
 
14
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 
 
16
#import "U1LocalAssetsViewController.h"
 
17
 
 
18
#import "U1ByteSizeValueTransformer.h"
 
19
#import "U1FileNode.h"
 
20
#import "U1FilePreviewViewController.h"
 
21
#import "U1FilesClient.h"
 
22
#import "U1FolderItemCell.h"
 
23
#import "U1FolderNode.h"
 
24
#import "U1Node.h"
 
25
#import "UIActionSheet+U1Additions.h"
 
26
#import "U1LocalAssetsManager.h"
 
27
#import "U1DataRepository.h"
 
28
 
 
29
@interface U1LocalAssetsViewController () <U1LocalAssetsViewControllerDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, NSFetchedResultsControllerDelegate>
 
30
@property (copy) NSString *resourcePath;
 
31
@property (retain) U1ByteSizeValueTransformer *byteSizeTransformer;
 
32
@property (retain) NSIndexPath *pendingIndexPath;
 
33
@property (retain) U1FolderNode *node;
 
34
@property (retain) NSMutableArray *nodes;
 
35
@property (retain) NSFetchedResultsController *resultsController;
 
36
@property (retain) U1LocalAssetsManager *localAssetsManager;
 
37
- (void)updateFeedback:(id)sender;
 
38
- (void)loadInfoForNode;
 
39
@end
 
40
 
 
41
 
 
42
@implementation U1LocalAssetsViewController
 
43
 
 
44
@synthesize loadingCell, progressView, progressBar, progressLabel;
 
45
@synthesize delegate, filesClient, node, resourcePath;
 
46
@synthesize byteSizeTransformer, pendingIndexPath, nodes, resultsController, localAssetsManager;
 
47
 
 
48
- (id)initWithNodeResourcePath:(NSString*)theResourcePath;
 
49
{
 
50
        self = [super initWithNibName:@"U1LocalAssetsViewController" bundle:nil];
 
51
        if (!self)
 
52
                return nil;
 
53
        self.title = NSLocalizedString(@"Camera Roll", @"");
 
54
        self.resourcePath = theResourcePath;
 
55
        self.byteSizeTransformer = [[U1ByteSizeValueTransformer new] autorelease];
 
56
        self.delegate = self; // ???
 
57
        filesClient = [U1FilesClient sharedFilesClient];
 
58
        localAssetsManager = [U1LocalAssetsManager sharedLocalAssetsManager];
 
59
 
 
60
        // This button should use a camera icon and go to the image picker to take a new photo.
 
61
        UIBarButtonItem *cameraButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(takePicture:)];
 
62
        [self.navigationItem setRightBarButtonItem:cameraButton];
 
63
        [cameraButton release];
 
64
        
 
65
        UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 20)];
 
66
        // TODO: Ubuntu font
 
67
        [titleLabel setFont:[UIFont boldSystemFontOfSize:18.f]];
 
68
        [titleLabel setTextColor:[UIColor blackColor]];
 
69
        [titleLabel setShadowColor:[UIColor whiteColor]];
 
70
        [titleLabel setShadowOffset:CGSizeMake(-1, -1)];
 
71
        [titleLabel setText:self.title];
 
72
        [titleLabel sizeToFit];
 
73
        [titleLabel setOpaque:NO];
 
74
        [titleLabel setBackgroundColor:[UIColor clearColor]];
 
75
        [self.navigationItem setTitleView:titleLabel];
 
76
        [titleLabel release];
 
77
        // [uploadItem release];
 
78
        
 
79
        return self;
 
80
}
 
81
 
 
82
- (void)dealloc;
 
83
{
 
84
        [loadingCell release];
 
85
        [resourcePath release];
 
86
        [node release];
 
87
        [byteSizeTransformer release];
 
88
        [pendingIndexPath release];
 
89
        [nodes release];
 
90
        [resultsController release];
 
91
        [super dealloc];
 
92
}
 
93
 
 
94
- (void)viewDidLoad;
 
95
{
 
96
        [super viewDidLoad];
 
97
        [self updateFeedback:nil];
 
98
        [self refresh];
 
99
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateFeedback:) name:@"imageUploaded" object:nil];
 
100
        UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
 
101
        [longPress setMinimumPressDuration:1.f];
 
102
        [self.tableView addGestureRecognizer:longPress];
 
103
        [longPress release];
 
104
}
 
105
 
 
106
- (void)viewDidUnload;
 
107
{
 
108
        [loadingCell release], loadingCell = nil;
 
109
        [[NSNotificationCenter defaultCenter] removeObserver:self];
 
110
        [super viewDidUnload];
 
111
}
 
112
 
 
113
- (void)viewDidAppear:(BOOL)animated;
 
114
{
 
115
        [super viewDidAppear:animated];
 
116
        [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
 
117
}
 
118
 
 
119
- (void)longPress:(UILongPressGestureRecognizer*)longPress;
 
120
{
 
121
        if (longPress.state == UIGestureRecognizerStateBegan)
 
122
        {
 
123
                CGPoint p = [longPress locationInView:self.tableView];
 
124
                NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
 
125
                U1Node *childNode = [self.nodes objectAtIndex:indexPath.row];
 
126
                
 
127
                UIActionSheet *actionSheet = [UIActionSheet new];
 
128
                
 
129
                [actionSheet setTitle:[[childNode path] lastPathComponent]];
 
130
                // TODO: rename
 
131
                NSInteger publishButtonIndex = -1;
 
132
                NSInteger copyURLButtonIndex = -1;
 
133
                if ([childNode isFile])
 
134
                {
 
135
                        U1FileNode *fileNode = (id)childNode;
 
136
                        if ([[fileNode isPublic] boolValue])
 
137
                        {
 
138
                                publishButtonIndex = [actionSheet addButtonWithTitle:@"Unpublish"];
 
139
                                copyURLButtonIndex = [actionSheet addButtonWithTitle:@"Copy Public URL"];
 
140
                        }
 
141
                        else
 
142
                        {
 
143
                                publishButtonIndex = [actionSheet addButtonWithTitle:@"Publish"];
 
144
                        }
 
145
                }
 
146
                [actionSheet setCancelButtonIndex:[actionSheet addButtonWithTitle:@"Cancel"]];
 
147
                
 
148
                self.pendingIndexPath = indexPath;
 
149
                [actionSheet showInView:self.view withCompletionBlock:^(NSInteger buttonIndex) {
 
150
                        if (buttonIndex == publishButtonIndex)
 
151
                        {
 
152
                                U1FileNode *fileNode = (id)childNode;
 
153
                                if ([[fileNode isPublic] boolValue])
 
154
                                        [self.filesClient unpublishNode:fileNode completionBlock:^(U1FileNode *updatedNode, NSError *error) {
 
155
                                        }];
 
156
                                else
 
157
                                        [self.filesClient publishNode:fileNode completionBlock:^(U1FileNode *updatedNode, NSError *error) {
 
158
                                        }];
 
159
                        }
 
160
                        else if (buttonIndex == copyURLButtonIndex)
 
161
                        {
 
162
                                U1FileNode *fileNode = (id)childNode;
 
163
                                NSArray *types = UIPasteboardTypeListString;
 
164
                                [[UIPasteboard generalPasteboard] setValue:[fileNode publicURLString] forPasteboardType:[types lastObject]];
 
165
                        }
 
166
                        else if (buttonIndex == [actionSheet cancelButtonIndex])
 
167
                        {
 
168
                                //                              NSLog(@"cancel");
 
169
                        }
 
170
                        self.pendingIndexPath = nil;
 
171
                }];
 
172
        }
 
173
}
 
174
 
 
175
- (void)takePicture:(id)sender;
 
176
{
 
177
        UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
 
178
        imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
 
179
        imagePicker.delegate = self;
 
180
        [self presentModalViewController:imagePicker animated:YES];
 
181
}
 
182
 
 
183
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info;
 
184
{
 
185
        // TODO: check for jpg/png
 
186
        // TODO: handle videos (stream)
 
187
        
 
188
        [picker dismissModalViewControllerAnimated:YES];
 
189
        
 
190
        //      NSURL *imageURL = [info objectForKey:UIImagePickerControllerReferenceURL];
 
191
        UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
 
192
        
 
193
        UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);
 
194
}
 
195
 
 
196
- (void)updateFeedback:(id)sender;
 
197
{
 
198
        // Update the label and the progress bar
 
199
        // progressLabel = (numberOfAssets - assetsPendingUpload) / numberOfAssets
 
200
        dispatch_async(dispatch_get_main_queue(), ^{
 
201
                U1LocalAssetsManager *localAssets = [U1LocalAssetsManager sharedLocalAssetsManager];
 
202
                int totalAssets = [localAssets numberOfAssets];
 
203
                int assetsUploaded = [localAssets numberOfAssetsUploaded];
 
204
                float percentDone = (float)assetsUploaded / (float)totalAssets;
 
205
                self.progressLabel.text = [NSString stringWithFormat:@"%d of %d uploaded", assetsUploaded, totalAssets];
 
206
                self.progressBar.progress = percentDone;
 
207
                [self.tableView reloadData];
 
208
        });
 
209
}
 
210
 
 
211
#pragma mark UITableViewDataSource Methods
 
212
 
 
213
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
 
214
{
 
215
        if (!self.resultsController)
 
216
                return 1;
 
217
        
 
218
        return [[[self.resultsController sections] objectAtIndex:section] numberOfObjects];
 
219
}
 
220
 
 
221
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
 
222
{
 
223
        if (section == 0 && [self.localAssetsManager.localAssetsToUpload count] > 0)
 
224
        {
 
225
                return 66.0f;
 
226
        }
 
227
        
 
228
        return [tableView sectionHeaderHeight];
 
229
}
 
230
 
 
231
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
 
232
{
 
233
        if (section == 0 && [self.localAssetsManager.localAssetsToUpload count] > 0)
 
234
        {
 
235
                return self.progressView;
 
236
        }
 
237
        
 
238
        return nil;
 
239
}
 
240
 
 
241
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
 
242
{
 
243
        if (!self.resultsController)
 
244
        {
 
245
                return self.loadingCell;
 
246
        }
 
247
        
 
248
        U1FolderItemCell *cell = [U1FolderItemCell cellForTableView:tableView];
 
249
        
 
250
        U1Node *childNode = [self.resultsController objectAtIndexPath:indexPath];
 
251
        cell.nameLabel.text = [childNode.resourcePath lastPathComponent];
 
252
        NSString *detailString = @"Pending";
 
253
//  TODO: get this thumbnail loading happening inside an operation queue, tied to visible rows
 
254
//      [self.localAssetsManager thumbnailForNode:childNode completionBlock:^(CGImageRef thumbnail) {
 
255
//              cell.iconImageView.image = [UIImage imageWithCGImage:thumbnail];
 
256
//      }];
 
257
        
 
258
        BOOL hasChildren = [[childNode hasChildren] boolValue];
 
259
        [cell setAccessoryType:(hasChildren ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone)];
 
260
        
 
261
        if (childNode.generation == nil)
 
262
        {
 
263
                cell.nameLabel.textColor = [UIColor grayColor];
 
264
                // query the local assets manager to see if this childNode's corresponding asset is actually in the upload operation queue
 
265
                BOOL isUploading = [self.localAssetsManager isResourceUploading:childNode.resourcePath];
 
266
                if (isUploading)
 
267
                {
 
268
                        [cell.uploadIndicator setHidden:NO];
 
269
                        [cell.uploadIndicator startAnimating];
 
270
                        detailString = @"Uploading";
 
271
                }
 
272
                else {
 
273
                        [cell.uploadIndicator setHidden:YES];
 
274
                        [cell.uploadIndicator stopAnimating];
 
275
                }
 
276
        }
 
277
        else
 
278
        {
 
279
                cell.nameLabel.textColor = [UIColor blackColor];
 
280
                [cell.detailLabel setHidden:NO];
 
281
                [cell.uploadIndicator setHidden:YES];
 
282
                [cell.uploadIndicator stopAnimating];
 
283
        }
 
284
        
 
285
        [cell.imageView setImage:nil];
 
286
        if ([childNode isFolder])
 
287
        {
 
288
                [cell.imageView setImage:[UIImage imageNamed:@"ic_folder"]];
 
289
                detailString = [childNode.modificationDate description];
 
290
        }
 
291
        else
 
292
        {
 
293
                NSString *contentPath = childNode.contentPath;
 
294
                NSURL *contentURL = [NSURL fileURLWithPath:contentPath];
 
295
                UIDocumentInteractionController *docController = [UIDocumentInteractionController interactionControllerWithURL:contentURL];
 
296
                [cell.imageView setImage:[docController.icons objectAtIndex:0]];
 
297
                NSNumber *size = [childNode valueForKey:@"size"];
 
298
                NSString *sizeString = [self.byteSizeTransformer transformedValue:size];
 
299
                if (childNode.generation != nil)
 
300
                {
 
301
                        detailString = [sizeString stringByAppendingFormat:@", modified %@", childNode.modificationDate];
 
302
                }
 
303
        }
 
304
        
 
305
        [cell.detailLabel setText:detailString];
 
306
        return cell;
 
307
}
 
308
 
 
309
 
 
310
#pragma mark UITableViewDelegate Methods
 
311
 
 
312
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
 
313
{
 
314
        U1Node *childNode = [self.resultsController objectAtIndexPath:indexPath];
 
315
        [self.delegate localAssetsController:self didSelectNode:childNode];
 
316
}
 
317
 
 
318
- (void)refresh;
 
319
{
 
320
        [self loadInfoForNode];
 
321
}
 
322
 
 
323
 
 
324
#pragma mark Private Methods
 
325
 
 
326
- (void)loadInfoForNode;
 
327
{
 
328
        NSParameterAssert(self.resourcePath != nil);
 
329
        
 
330
        [self.filesClient fetchFolderWithResourcePath:self.resourcePath completionBlock:^(U1Node *theNode, NSFetchedResultsController *childrenResultsController, NSError *error) {
 
331
                
 
332
                self.node = (id)theNode;
 
333
                self.resultsController = childrenResultsController;
 
334
                [self.resultsController setDelegate:self];
 
335
                [self stopLoading];
 
336
                [self.tableView reloadData];
 
337
        }];
 
338
}
 
339
 
 
340
#pragma mark NSFetchedResultsControllerDelegate Methods
 
341
 
 
342
 
 
343
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller;
 
344
{
 
345
        [self.tableView beginUpdates];
 
346
}
 
347
 
 
348
 
 
349
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
 
350
                   atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type;
 
351
{
 
352
        switch (type)
 
353
        {
 
354
                case NSFetchedResultsChangeInsert:
 
355
                        [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
 
356
                                                  withRowAnimation:UITableViewRowAnimationFade];
 
357
                        break;
 
358
                        
 
359
                case NSFetchedResultsChangeDelete:
 
360
                        [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
 
361
                                                  withRowAnimation:UITableViewRowAnimationFade];
 
362
                        break;
 
363
        }
 
364
}
 
365
 
 
366
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
 
367
           atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
 
368
          newIndexPath:(NSIndexPath *)newIndexPath;
 
369
{
 
370
        
 
371
        UITableView *tableView = self.tableView;
 
372
        
 
373
        switch (type)
 
374
        {
 
375
                        
 
376
                case NSFetchedResultsChangeInsert:
 
377
                        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
 
378
                                                         withRowAnimation:UITableViewRowAnimationFade];
 
379
                        break;
 
380
                        
 
381
                case NSFetchedResultsChangeDelete:
 
382
                        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
 
383
                                                         withRowAnimation:UITableViewRowAnimationFade];
 
384
                        break;
 
385
                        
 
386
                case NSFetchedResultsChangeUpdate:
 
387
                        // TODO: 
 
388
                        //            [self configureCell:[tableView cellForRowAtIndexPath:indexPath]
 
389
                        //                                      atIndexPath:indexPath];
 
390
                        [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
 
391
                                                                  withRowAnimation:UITableViewRowAnimationNone];
 
392
                        break;
 
393
                        
 
394
                case NSFetchedResultsChangeMove:
 
395
                        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
 
396
                                                         withRowAnimation:UITableViewRowAnimationFade];
 
397
                        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
 
398
                                                         withRowAnimation:UITableViewRowAnimationFade];
 
399
                        break;
 
400
        }
 
401
}
 
402
 
 
403
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller;
 
404
{
 
405
        [self.tableView endUpdates];
 
406
}
 
407
 
 
408
#pragma mark U1LocalAssetsViewControllerDelegate Methods
 
409
 
 
410
- (void)localAssetsController:(U1LocalAssetsViewController *)localAssetsController didSelectNode:(U1Node *)aNode
 
411
{
 
412
        if ([aNode isFile])
 
413
        {
 
414
                U1FilePreviewViewController *fileController = [[U1FilePreviewViewController alloc] initWithNode:(id)node];
 
415
                [self.navigationController pushViewController:fileController animated:YES];
 
416
                [fileController release];
 
417
        }
 
418
}
 
419
 
 
420
@end