Copy of rackspace-ios version 2.1.1
[pithos-ios] / Classes / ContainerDetailViewController.m
1 //
2 //  ContainerDetailViewController.m
3 //  OpenStack
4 //
5 //  Created by Mike Mayo on 12/22/10.
6 //  The OpenStack project is provided under the Apache 2.0 license.
7 //
8
9 #import "ContainerDetailViewController.h"
10 #import "OpenStackAccount.h"
11 #import "Container.h"
12 #import "ActivityIndicatorView.h"
13 #import "AccountManager.h"
14 #import "UIViewController+Conveniences.h"
15 #import "UIColor+MoreColors.h"
16 #import "ReferrerACLViewController.h"
17 #import "UserAgentACLViewController.h"
18 #import "ContainersViewController.h"
19 #import "Folder.h"
20
21 #define kOverview 0
22 #define kCDNAccess 1
23 #define kCDNAttributes 2
24 #define kLogRetention 3
25 #define kReferrerACL 4
26 #define kUserAgentACL 5
27
28 /*
29  #define kOverview 0
30  #define kCDNAccess 1
31  #define kCDNAttributes 2
32  #define kLogRetention 3
33  #define kReferrerACL 4
34  #define kUserAgentACL 5
35  Name
36  Size
37  
38  Publish to CDN [On/Off]
39  @"Containers published to the CDN will be viewable to everyone.  If you disable CDN access, container contents will not be purged from the CDN until the TTL expires."
40  
41  CDN URL
42  TTL
43  
44  Log Retention [On/Off]
45  @"When Log Retention is enabled, CDN access logs will be stored in the .CDN_ACCESS_LOGS container in your account."
46  
47  Referrer ACL
48  @"The Referrer ACL is a Perl Compatible Regular Expression (PCRE) that must match the referrer in order for container contents to be served.  This is a useful mechanism to prevent other content providers from hot-linking your CDN content."
49  
50  User Agent ACL
51  @"The User Agent ACL is a PCRE that must match the user agent that your users are using to access the CDN content." 
52  
53  */
54
55 @implementation ContainerDetailViewController
56
57 @synthesize account, container, containersViewController, selectedContainerIndexPath;
58
59 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
60     return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
61 }
62
63 - (void)setBackgroundView {
64     if (!self.container) {
65         UIView *viewContainer = [[UIView alloc] init];
66         viewContainer.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
67         viewContainer.backgroundColor = [UIColor iPadTableBackgroundColor];
68         
69         UILabel *label = [[UILabel alloc] init];
70         label.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
71         label.backgroundColor = [UIColor clearColor];
72         label.textColor = [UIColor emptyCollectionGrayColor];
73         label.font = [UIFont boldSystemFontOfSize:18.0];
74         label.text = @"No container selected";
75         label.textAlignment = UITextAlignmentCenter;
76         [viewContainer addSubview:label];
77         [label release];
78         
79         self.tableView.backgroundView = viewContainer;
80         [viewContainer release];
81     }
82 }
83
84 #pragma mark -
85 #pragma mark View lifecycle
86
87 - (void)viewDidLoad {
88     [super viewDidLoad];
89     cdnEnabledSwitch = [[UISwitch alloc] init];
90     cdnEnabledSwitch.on = container.cdnEnabled;
91     [cdnEnabledSwitch addTarget:self action:@selector(cdnEnabledSwitchChanged:) forControlEvents:UIControlEventValueChanged];
92     
93     logRetentionSwitch = [[UISwitch alloc] init];
94     logRetentionSwitch.on = container.logRetention;
95     [logRetentionSwitch addTarget:self action:@selector(logRetentionSwitchChanged:) forControlEvents:UIControlEventValueChanged];
96
97     ttlSlider = [[UISlider alloc] init];
98     cdnURLActionSheet = [[UIActionSheet alloc] initWithTitle:container.cdnURL delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Copy to Pasteboard", nil];
99     deleteActionSheet = [[UIActionSheet alloc] initWithTitle:@"Are you sure you want to delete this container?  This operation cannot be undone." delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Delete Container" otherButtonTitles:nil];
100     
101     deleteSection = container.cdnEnabled ? 6 : 2;
102 }
103
104 - (void)viewWillAppear:(BOOL)animated {
105     [super viewWillAppear:animated];
106     if (container) {
107         self.navigationItem.title = container.name;
108     } else {
109         self.navigationItem.title = @"Cloud Files Container";
110     }
111     originalTTL = container.ttl;
112     [self setBackgroundView];
113 }
114
115 #pragma mark -
116 #pragma mark TTL
117
118 - (float)ttlToPercentage {
119     return self.container.ttl / 259200.0;
120 }
121
122 - (NSInteger)ttlFromPercentage:(float)percentage {
123     return percentage * 259200;
124 }
125
126 - (NSString *)ttlToHours {
127     NSString *result = [NSString stringWithFormat:@"%.0f hours", self.container.ttl / 3600.0];
128     if ([result isEqualToString:@"1 hours"]) {
129         result = @"1 hour";
130     }
131     return result;
132 }
133
134 - (void)ttlSliderFinished:(id)sender {
135     NSString *activityMessage = @"Updating TTL...";
136     activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
137     [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y];
138     
139     [self.account.manager updateCDNContainer:self.container];
140     
141     successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"updateCDNContainerSucceeded" object:self.container
142                                                                          queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification) 
143        {
144            [activityIndicatorView removeFromSuperviewAndRelease];
145            [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
146        }];
147     
148     failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"updateCDNContainerFailed" object:self.container
149                                                                          queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification) 
150        {
151            [activityIndicatorView removeFromSuperviewAndRelease];
152            container.ttl = originalTTL;
153            [self.tableView reloadData];
154            [self alert:@"There was a problem updating this container." request:[notification.userInfo objectForKey:@"request"]];
155            [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
156        }];
157 }
158
159 - (void)ttlSliderMoved:(id)sender {
160         CGFloat newTTL = ttlSlider.value;
161     self.container.ttl = [self ttlFromPercentage:newTTL];
162     ttlLabel.text = [self ttlToHours];
163 }
164
165
166 #pragma mark -
167 #pragma mark Table view data source
168
169 - (CGFloat)findLabelHeight:(NSString*)text font:(UIFont *)font {
170     CGSize textLabelSize;
171     
172     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
173         textLabelSize = CGSizeMake(577.0, 9000.0f);
174     } else {
175         textLabelSize = CGSizeMake(260.0, 9000.0f);
176     }
177     // pad \n\n to fix layout bug
178     CGSize stringSize = [text sizeWithFont:font constrainedToSize:textLabelSize lineBreakMode:UILineBreakModeWordWrap];
179     return stringSize.height;
180 }
181
182 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
183     if (indexPath.section == deleteSection) {
184         return tableView.rowHeight;
185     } else if (indexPath.section == kCDNAttributes) {
186         if (indexPath.row == 0) { // URL
187             return tableView.rowHeight;
188             //return 22.0 + [self findLabelHeight:container.cdnURL font:[UIFont systemFontOfSize:18.0]];
189         } else { // if (indexPath.row == 1) {
190             return tableView.rowHeight + ttlSlider.frame.size.height + 3.0;
191         }
192     } else {
193         return tableView.rowHeight;
194     }
195 }
196
197 - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
198     if (section == deleteSection) {
199         return @"Only empty containers can be deleted.";
200     } else if (section == kCDNAccess) {
201         //return @"CDN allows you to access files in this container via the public internet. Transfer charges apply.";
202         return @"CDN allows you to access files via the public internet. Transfer charges apply.";
203     } else if (section == kLogRetention) {
204         return @"When enabled, access logs will be stored in the .CDN_ACCESS_LOGS container.";
205     } else if (section == kReferrerACL) {
206         return @"The Referrer ACL is a Perl Compatible Regular Expression that must match the referrer for all content requests.";
207     } else if (section == kUserAgentACL) {
208         return @"The User Agent ACL is a Perl Compatible Regular Expression that must match the user agent for all content requests.";
209     } else {
210         return @"";
211     }
212 }
213
214 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
215     if (self.container) {
216         if (transitioning) {
217             return container.cdnEnabled ? 3 : 7;
218         } else {
219             return container.cdnEnabled ? 7 : 3;
220         }
221     } else {
222         return 0;
223     }
224 }
225
226 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
227     // Return the number of rows in the section.
228     if (section == deleteSection) {
229         return 1;
230     } else if (section == kOverview) {
231         return 2;
232     } else if (section == kCDNAccess) {
233         return 1;
234     } else if (section == kCDNAttributes) {
235         return 2;
236     } else {
237         return 1;
238     }
239 }
240
241 - (UITableViewCell *)tableView:(UITableView *)tableView ttlCellForRowAtIndexPath:(NSIndexPath *)indexPath {
242     static NSString *CellIdentifier = @"TTLCell";
243     
244     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
245     if (cell == nil) {
246         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
247         cell.selectionStyle = UITableViewCellSelectionStyleNone;
248         
249         UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 13.0, 280.0, 20.0)];
250         if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
251             textLabel.frame = CGRectMake(54.0, 13.0, 458.0, 20.0);
252         }
253         textLabel.font = [UIFont boldSystemFontOfSize:17.0];
254         textLabel.text = @"TTL";
255         textLabel.textColor = [UIColor blackColor];
256         textLabel.backgroundColor = [UIColor clearColor];
257         [cell addSubview:textLabel];
258         [textLabel release];
259         
260         if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
261             ttlSlider.frame = CGRectMake(54.0, 38.0, 596.0, ttlSlider.frame.size.height);
262         } else {
263             ttlSlider.frame = CGRectMake(20.0, 38.0, 280.0, ttlSlider.frame.size.height);
264         }
265         [ttlSlider addTarget:self action:@selector(ttlSliderMoved:) forControlEvents:UIControlEventValueChanged];
266         [ttlSlider addTarget:self action:@selector(ttlSliderFinished:) forControlEvents:UIControlEventTouchUpInside];
267         
268         [cell addSubview:ttlSlider];
269         ttlLabel = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 14.0, 280.0, 18.0)];
270         if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
271             ttlLabel.frame = CGRectMake(54.0, 14.0, 596.0, 18.0);
272         }
273         ttlLabel.font = [UIFont systemFontOfSize:17.0];
274         ttlLabel.textColor = [UIColor value1DetailTextLabelColor];
275         ttlLabel.backgroundColor = [UIColor clearColor];
276         ttlLabel.textAlignment = UITextAlignmentRight;
277         [cell addSubview:ttlLabel];
278     }
279     
280     ttlLabel.text = [self ttlToHours];
281     ttlSlider.value = [self ttlToPercentage];
282     
283     return cell;
284 }
285
286 - (UITableViewCell *)tableView:(UITableView *)tableView deleteCellForRowAtIndexPath:(NSIndexPath *)indexPath {
287     static NSString *CellIdentifier = @"DeleteCell";
288     
289     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
290     if (cell == nil) {
291         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
292         cell.textLabel.textAlignment = UITextAlignmentCenter;
293         cell.textLabel.text = @"Delete Container";
294     }
295     
296     if (self.container.rootFolder) {
297         if (self.container.count == 0 || ([self.container.rootFolder.folders count] + [self.container.rootFolder.objects count] == 0)) {
298             cell.textLabel.textColor = [UIColor blackColor];
299             cell.selectionStyle = UITableViewCellSelectionStyleBlue;
300         } else {
301             cell.textLabel.textColor = [UIColor grayColor];
302             cell.selectionStyle = UITableViewCellSelectionStyleNone;
303         }
304     } else {
305         if (self.container.count == 0) {
306             cell.textLabel.textColor = [UIColor blackColor];
307             cell.selectionStyle = UITableViewCellSelectionStyleBlue;
308         } else {
309             cell.textLabel.textColor = [UIColor grayColor];
310             cell.selectionStyle = UITableViewCellSelectionStyleNone;
311         }
312     }
313     
314     return cell;
315 }
316
317 // Customize the appearance of table view cells.
318 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
319     
320     static NSString *CellIdentifier = @"Cell";
321     
322     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
323     if (cell == nil) {
324         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
325         cell.selectionStyle = UITableViewCellSelectionStyleNone;
326         cell.textLabel.backgroundColor = [UIColor clearColor];
327         cell.detailTextLabel.backgroundColor = [UIColor clearColor];
328         cell.detailTextLabel.numberOfLines = 0;
329         cell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
330         cell.detailTextLabel.textAlignment = UITextAlignmentLeft;
331     }
332     
333     cell.accessoryType = UITableViewCellAccessoryNone;
334     cell.selectionStyle = UITableViewCellSelectionStyleNone;
335     
336     if (indexPath.section == kOverview) {
337         cell.accessoryView = nil;
338         if (indexPath.row == 0) {
339             cell.textLabel.text = @"Name";
340             cell.detailTextLabel.text = container.name;
341         } else if (indexPath.row == 1) {
342             cell.textLabel.text = @"Size";
343             cell.detailTextLabel.text = [container humanizedSize];
344         }
345     } else if (indexPath.section == kCDNAccess) {
346         cell.textLabel.text = @"Publish to CDN";
347         cell.detailTextLabel.text = @"";
348         cell.accessoryView = cdnEnabledSwitch;
349         cell.selectionStyle = UITableViewCellSelectionStyleNone;
350     } else if (indexPath.section == deleteSection) {
351         return [self tableView:tableView deleteCellForRowAtIndexPath:indexPath];
352     } else if (indexPath.section == kCDNAttributes) {
353         if (indexPath.row == 0) {
354             cell.textLabel.text = @"Public URL";
355             //cell.detailTextLabel.text = container.cdnURL;
356             cell.detailTextLabel.text = @"";
357             cell.accessoryView = nil;
358             cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
359             cell.selectionStyle = UITableViewCellSelectionStyleBlue;
360             cell.detailTextLabel.lineBreakMode = UILineBreakModeTailTruncation;
361             cell.detailTextLabel.numberOfLines = 0;
362             //cell.detailTextLabel.adjustsFontSizeToFitWidth = YES;
363         } else if (indexPath.row == 1) {
364             return [self tableView:tableView ttlCellForRowAtIndexPath:indexPath];
365         }
366     } else if (indexPath.section == kLogRetention) {
367         cell.textLabel.text = @"Log Retention";
368         cell.detailTextLabel.text = @"";
369         cell.accessoryView = logRetentionSwitch;
370         cell.accessoryType = UITableViewCellAccessoryNone;
371         cell.selectionStyle = UITableViewCellSelectionStyleNone;
372     } else if (indexPath.section == kReferrerACL) {
373         cell.textLabel.text = @"Referrer ACL";
374         cell.detailTextLabel.text = container.referrerACL;
375         cell.accessoryView = nil;
376         cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
377         cell.selectionStyle = UITableViewCellSelectionStyleBlue;
378         cell.detailTextLabel.numberOfLines = 1;
379     } else if (indexPath.section == kUserAgentACL) {
380         cell.textLabel.text = @"User Agent ACL";
381         cell.detailTextLabel.text = container.useragentACL;
382         cell.accessoryView = nil;
383         cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
384         cell.selectionStyle = UITableViewCellSelectionStyleBlue;
385         cell.detailTextLabel.numberOfLines = 1;
386     }
387     
388     return cell;
389 }
390
391 #pragma mark -
392 #pragma mark Table view delegate
393
394 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
395     if (indexPath.section == deleteSection) {
396         if (self.container.count == 0 || ([self.container.rootFolder.folders count] + [self.container.rootFolder.objects count] == 0)) {
397             [deleteActionSheet showInView:self.view];
398         }
399     } else if (indexPath.section == kCDNAttributes && indexPath.row == 0) {
400         [cdnURLActionSheet showInView:self.view];
401     } else if (indexPath.section == kReferrerACL) {
402         ReferrerACLViewController *vc = [[ReferrerACLViewController alloc] initWithNibName:@"ReferrerACLViewController" bundle:nil];
403         vc.account = self.account;
404         vc.container = self.container;
405         vc.containerDetailViewController = self;
406         if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
407             vc.modalPresentationStyle = UIModalPresentationFormSheet;
408             [self presentModalViewControllerWithNavigation:vc animated:YES];
409         } else {
410             [self.navigationController pushViewController:vc animated:YES];
411         }        
412         [vc release];
413     } else if (indexPath.section == kUserAgentACL) {
414         UserAgentACLViewController *vc = [[UserAgentACLViewController alloc] initWithNibName:@"UserAgentACLViewController" bundle:nil];
415         vc.account = self.account;
416         vc.container = self.container;
417         vc.containerDetailViewController = self;
418         if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
419             vc.modalPresentationStyle = UIModalPresentationFormSheet;
420             [self presentModalViewControllerWithNavigation:vc animated:YES];
421         } else {
422             [self.navigationController pushViewController:vc animated:YES];
423         }        
424         [vc release];
425     }
426 }
427
428 #pragma mark -
429 #pragma mark Switches
430
431 - (void)cdnEnabledSwitchChanged:(id)sender {
432     
433     NSString *activityMessage = @"Disabling CDN Access...";
434     if (!container.cdnEnabled) {
435         activityMessage = @"Enabling CDN Access...";
436     }
437     activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
438     [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y];    
439     container.cdnEnabled = !container.cdnEnabled;
440     [self.account.manager updateCDNContainer:container];
441     
442     successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"updateCDNContainerSucceeded" object:self.container
443                                                                          queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification) 
444     {
445         [activityIndicatorView removeFromSuperviewAndRelease];
446         
447         NSIndexSet *sections = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(3, 4)];
448         NSInteger oldDeleteSection = deleteSection;
449         if (container.cdnEnabled) {
450             deleteSection = 6;
451             transitioning = YES;
452             [self.tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(oldDeleteSection, 1)] withRowAnimation:UITableViewRowAnimationBottom];
453             transitioning = NO;
454             [self.tableView insertSections:sections withRowAnimation:UITableViewRowAnimationBottom];
455         } else {
456             deleteSection = 2;
457             transitioning = YES;
458             [self.tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(deleteSection, 1)] withRowAnimation:UITableViewRowAnimationTop];
459             transitioning = NO;
460             [self.tableView deleteSections:sections withRowAnimation:UITableViewRowAnimationTop];
461         }
462         
463         [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
464     }];
465     
466     failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"updateCDNContainerFailed" object:self.container
467                                                                          queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification) 
468     {
469         [activityIndicatorView removeFromSuperviewAndRelease];
470         container.cdnEnabled = !container.cdnEnabled;
471         cdnEnabledSwitch.on = !cdnEnabledSwitch.on;
472         [self alert:@"There was a problem updating this container." request:[notification.userInfo objectForKey:@"request"]];           
473         [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
474     }];
475 }
476
477 - (void)logRetentionSwitchChanged:(id)sender {
478
479     NSString *activityMessage = @"Disabling Log Retention...";
480     if (!container.logRetention) {
481         activityMessage = @"Enabling Log Retention...";
482     }
483     activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
484     [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y];    
485
486     container.logRetention = !container.logRetention;
487     [self.account.manager updateCDNContainer:container];
488     
489     successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"updateCDNContainerSucceeded" object:self.container
490                                                                          queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification) 
491        {
492            [activityIndicatorView removeFromSuperviewAndRelease];
493            [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
494        }];
495     
496     failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"updateCDNContainerFailed" object:self.container
497                                                                          queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification) 
498        {
499            [activityIndicatorView removeFromSuperviewAndRelease];
500            container.logRetention = !container.logRetention;
501            logRetentionSwitch.on = !logRetentionSwitch.on;
502            [self alert:@"There was a problem updating this container." request:[notification.userInfo objectForKey:@"request"]];
503            [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
504        }];
505 }
506
507 #pragma mark -
508 #pragma mark Action Sheet
509
510 - (void)deleteContainerRow {
511     if ([self.account.containers count] == 0) {
512         [self.containersViewController.tableView reloadData];
513     } else {
514         [self.containersViewController.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:selectedContainerIndexPath] withRowAnimation:UITableViewRowAnimationLeft];
515     }
516 }
517
518 - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
519     if ([actionSheet isEqual:cdnURLActionSheet]) {
520         if (buttonIndex == 0) {
521             UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
522             [pasteboard setString:container.cdnURL];
523         }
524         [self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kCDNAttributes] animated:YES];
525     } else if ([actionSheet isEqual:deleteActionSheet]) {
526         if (buttonIndex == 0) {
527          
528             NSString *activityMessage = @"Deleting container...";
529             activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
530             [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y];    
531             
532             [self.account.manager deleteContainer:self.container];
533             
534             successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"deleteContainerSucceeded" object:self.container
535                                                                                  queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification) 
536             {
537                 [activityIndicatorView removeFromSuperviewAndRelease];
538
539                 [self.account.containers removeObjectForKey:self.container.name];
540                 [self.account persist];
541                 
542                 
543                 if ([self.account.containers count] == 0 && UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
544                     // on ipad, delete needs to get rid of the container on the main view
545                     self.container = nil;
546                     [self setBackgroundView];
547                     [self.tableView reloadData];
548                 } else {
549                     [self.navigationController popViewControllerAnimated:YES];
550                 }
551                 
552                 [self.containersViewController.tableView selectRowAtIndexPath:selectedContainerIndexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
553                 [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(deleteContainerRow) userInfo:nil repeats:NO];
554                 
555                 [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
556             }];
557             
558             failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"deleteContainerFailed" object:self.container
559                                                                                  queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification) 
560             {
561                 [activityIndicatorView removeFromSuperviewAndRelease];
562                 [self alert:@"There was a problem deleting this container." request:[notification.userInfo objectForKey:@"request"]];
563                 [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
564             }];
565             
566         }
567         
568         [self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:deleteSection] animated:YES];
569     }
570 }
571
572
573 #pragma mark -
574 #pragma mark Memory management
575
576 - (void)dealloc {
577     [account release];
578     [container release];
579     [cdnEnabledSwitch release];
580     [ttlSlider release];
581     [cdnURLActionSheet release];
582     [deleteActionSheet release];
583     [containersViewController release];
584     [selectedContainerIndexPath release];
585     [super dealloc];
586 }
587
588 @end
589