2 // ContainerDetailViewController.m
5 // Created by Mike Mayo on 12/22/10.
6 // The OpenStack project is provided under the Apache 2.0 license.
9 #import "ContainerDetailViewController.h"
10 #import "OpenStackAccount.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 "EditMetadataViewController.h"
20 #import "EditPolicyViewController.h"
22 #import "FolderViewController.h"
27 #define kCDNAttributes 4
28 #define kLogRetention 5
29 #define kReferrerACL 6
30 #define kUserAgentACL 7
32 #define maxMetadataViewableLength 12
39 Publish to CDN [On/Off]
40 @"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."
45 Log Retention [On/Off]
46 @"When Log Retention is enabled, CDN access logs will be stored in the .CDN_ACCESS_LOGS container in your account."
49 @"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."
52 @"The User Agent ACL is a PCRE that must match the user agent that your users are using to access the CDN content."
56 @implementation ContainerDetailViewController
58 @synthesize account, container, containersViewController, selectedContainerIndexPath, rootFolderViewController;
60 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
61 return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
64 - (void)setBackgroundView {
65 if (!self.container) {
66 UIView *viewContainer = [[UIView alloc] init];
67 viewContainer.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
68 viewContainer.backgroundColor = [UIColor iPadTableBackgroundColor];
70 UILabel *label = [[UILabel alloc] init];
71 label.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
72 label.backgroundColor = [UIColor clearColor];
73 label.textColor = [UIColor emptyCollectionGrayColor];
74 label.font = [UIFont boldSystemFontOfSize:18.0];
75 label.text = @"No container selected";
76 label.textAlignment = UITextAlignmentCenter;
77 [viewContainer addSubview:label];
80 self.tableView.backgroundView = viewContainer;
81 [viewContainer release];
86 #pragma mark View lifecycle
90 cdnEnabledSwitch = [[UISwitch alloc] init];
91 cdnEnabledSwitch.on = container.cdnEnabled;
92 [cdnEnabledSwitch addTarget:self action:@selector(cdnEnabledSwitchChanged:) forControlEvents:UIControlEventValueChanged];
94 logRetentionSwitch = [[UISwitch alloc] init];
95 logRetentionSwitch.on = container.logRetention;
96 [logRetentionSwitch addTarget:self action:@selector(logRetentionSwitchChanged:) forControlEvents:UIControlEventValueChanged];
98 ttlSlider = [[UISlider alloc] init];
99 cdnURLActionSheet = [[UIActionSheet alloc] initWithTitle:container.cdnURL delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Copy to Pasteboard", nil];
100 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];
102 if (!account.sharingAccount) {
103 deleteSection = container.cdnEnabled ? 8 : 3;
104 policySection = container.cdnEnabled ? 7 : 2;
111 - (void)viewWillAppear:(BOOL)animated {
112 [super viewWillAppear:animated];
114 self.navigationItem.title = container.name;
116 originalTTL = container.ttl;
117 [self setBackgroundView];
118 [self.tableView reloadData];
124 - (float)ttlToPercentage {
125 return self.container.ttl / 259200.0;
128 - (NSInteger)ttlFromPercentage:(float)percentage {
129 return percentage * 259200;
132 - (NSString *)ttlToHours {
133 NSString *result = [NSString stringWithFormat:@"%.0f hours", self.container.ttl / 3600.0];
134 if ([result isEqualToString:@"1 hours"]) {
140 - (void)ttlSliderFinished:(id)sender {
141 NSString *activityMessage = @"Updating TTL...";
142 activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
143 [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y];
145 [self.account.manager updateCDNContainer:self.container];
147 successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"updateCDNContainerSucceeded" object:self.container
148 queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification)
150 [activityIndicatorView removeFromSuperviewAndRelease];
151 [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
154 failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"updateCDNContainerFailed" object:self.container
155 queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification)
157 [activityIndicatorView removeFromSuperviewAndRelease];
158 container.ttl = originalTTL;
159 [self.tableView reloadData];
160 [self alert:@"There was a problem updating this container." request:[notification.userInfo objectForKey:@"request"]];
161 [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
165 - (void)ttlSliderMoved:(id)sender {
166 CGFloat newTTL = ttlSlider.value;
167 self.container.ttl = [self ttlFromPercentage:newTTL];
168 ttlLabel.text = [self ttlToHours];
173 #pragma mark Table view data source
175 - (CGFloat)findLabelHeight:(NSString*)text font:(UIFont *)font {
176 CGSize textLabelSize;
178 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
179 textLabelSize = CGSizeMake(577.0, 9000.0f);
181 textLabelSize = CGSizeMake(260.0, 9000.0f);
183 // pad \n\n to fix layout bug
184 CGSize stringSize = [text sizeWithFont:font constrainedToSize:textLabelSize lineBreakMode:UILineBreakModeWordWrap];
185 return stringSize.height;
188 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
189 if (indexPath.section == deleteSection) {
190 return tableView.rowHeight;
191 } else if (indexPath.section == kCDNAttributes) {
192 if (indexPath.row == 0) { // URL
193 return tableView.rowHeight;
194 //return 22.0 + [self findLabelHeight:container.cdnURL font:[UIFont systemFontOfSize:18.0]];
195 } else { // if (indexPath.row == 1) {
196 return tableView.rowHeight + ttlSlider.frame.size.height + 3.0;
199 return tableView.rowHeight;
203 - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
204 if (section == deleteSection) {
205 return @"Only empty containers can be deleted.";
206 } else if (section == kCDNAccess) {
207 //return @"CDN allows you to access files in this container via the public internet. Transfer charges apply.";
208 return @"CDN allows you to access files via the public internet. Transfer charges apply.";
209 } else if (section == kLogRetention) {
210 return @"When enabled, access logs will be stored in the .CDN_ACCESS_LOGS container.";
211 } else if (section == kReferrerACL) {
212 return @"The Referrer ACL is a Perl Compatible Regular Expression that must match the referrer for all content requests.";
213 } else if (section == kUserAgentACL) {
214 return @"The User Agent ACL is a Perl Compatible Regular Expression that must match the user agent for all content requests.";
220 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
221 if (self.container) {
222 int numberOfSections;
224 numberOfSections = container.cdnEnabled ? 4 : 9;
226 numberOfSections = container.cdnEnabled ? 9 : 4;
228 if (account.sharingAccount)
229 return numberOfSections - 2;
231 return numberOfSections;
237 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
238 // Return the number of rows in the section.
239 if (section == kOverview) {
241 } else if (section == kMetadata) {
242 if (account.sharingAccount)
243 return [container.metadata count];
245 return 1 + [container.metadata count];
246 } else if (section == policySection) {
247 if (account.sharingAccount)
256 - (UITableViewCell *)tableView:(UITableView *)tableView ttlCellForRowAtIndexPath:(NSIndexPath *)indexPath {
257 static NSString *CellIdentifier = @"TTLCell";
259 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
261 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
262 cell.selectionStyle = UITableViewCellSelectionStyleNone;
264 UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 13.0, 280.0, 20.0)];
265 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
266 textLabel.frame = CGRectMake(54.0, 13.0, 458.0, 20.0);
268 textLabel.font = [UIFont boldSystemFontOfSize:17.0];
269 textLabel.text = @"TTL";
270 textLabel.textColor = [UIColor blackColor];
271 textLabel.backgroundColor = [UIColor clearColor];
272 [cell addSubview:textLabel];
275 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
276 ttlSlider.frame = CGRectMake(54.0, 38.0, 596.0, ttlSlider.frame.size.height);
278 ttlSlider.frame = CGRectMake(20.0, 38.0, 280.0, ttlSlider.frame.size.height);
280 [ttlSlider addTarget:self action:@selector(ttlSliderMoved:) forControlEvents:UIControlEventValueChanged];
281 [ttlSlider addTarget:self action:@selector(ttlSliderFinished:) forControlEvents:UIControlEventTouchUpInside];
283 [cell addSubview:ttlSlider];
284 ttlLabel = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 14.0, 280.0, 18.0)];
285 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
286 ttlLabel.frame = CGRectMake(54.0, 14.0, 596.0, 18.0);
288 ttlLabel.font = [UIFont systemFontOfSize:17.0];
289 ttlLabel.textColor = [UIColor value1DetailTextLabelColor];
290 ttlLabel.backgroundColor = [UIColor clearColor];
291 ttlLabel.textAlignment = UITextAlignmentRight;
292 [cell addSubview:ttlLabel];
295 ttlLabel.text = [self ttlToHours];
296 ttlSlider.value = [self ttlToPercentage];
301 - (UITableViewCell *)tableView:(UITableView *)tableView deleteCellForRowAtIndexPath:(NSIndexPath *)indexPath {
302 static NSString *CellIdentifier = @"DeleteCell";
304 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
306 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
307 cell.textLabel.textAlignment = UITextAlignmentCenter;
308 cell.textLabel.text = @"Delete Container";
311 if (self.container.rootFolder) {
312 if (self.container.count == 0 || ([self.container.rootFolder.folders count] + [self.container.rootFolder.objects count] == 0)) {
313 cell.textLabel.textColor = [UIColor blackColor];
314 cell.selectionStyle = UITableViewCellSelectionStyleBlue;
316 cell.textLabel.textColor = [UIColor grayColor];
317 cell.selectionStyle = UITableViewCellSelectionStyleNone;
318 cell.userInteractionEnabled = NO;
321 if (self.container.count == 0) {
322 cell.textLabel.textColor = [UIColor blackColor];
323 cell.selectionStyle = UITableViewCellSelectionStyleBlue;
325 cell.textLabel.textColor = [UIColor grayColor];
326 cell.selectionStyle = UITableViewCellSelectionStyleNone;
327 cell.userInteractionEnabled = NO;
334 // Customize the appearance of table view cells.
335 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
337 static NSString *CellIdentifier = @"Cell";
339 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
341 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
342 cell.selectionStyle = UITableViewCellSelectionStyleNone;
343 cell.textLabel.backgroundColor = [UIColor clearColor];
344 cell.detailTextLabel.backgroundColor = [UIColor clearColor];
345 cell.detailTextLabel.numberOfLines = 0;
346 cell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
347 cell.detailTextLabel.textAlignment = UITextAlignmentLeft;
350 cell.accessoryType = UITableViewCellAccessoryNone;
351 cell.selectionStyle = UITableViewCellSelectionStyleNone;
353 if (indexPath.section == kOverview) {
354 cell.accessoryView = nil;
355 if (indexPath.row == 0) {
356 cell.textLabel.text = @"Name";
357 cell.detailTextLabel.text = container.name;
358 } else if (indexPath.row == 1) {
359 cell.textLabel.text = @"Size";
360 cell.detailTextLabel.text = [container humanizedSize];
362 } else if (indexPath.section == kMetadata) {
363 if (account.sharingAccount) {
364 cell.accessoryType = UITableViewCellAccessoryNone;
365 cell.selectionStyle = UITableViewCellSelectionStyleNone;
366 cell.userInteractionEnabled = NO;
369 cell.selectionStyle = UITableViewCellSelectionStyleBlue;
370 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
372 if (indexPath.row == [container.metadata count]) {
373 cell.textLabel.text = @"Add Metadata";
374 cell.detailTextLabel.text = @"";
376 NSString *key = [[container.metadata allKeys] objectAtIndex:indexPath.row];
377 NSString *value = [container.metadata objectForKey:key];
378 NSString *metadataKeyCellText = key;
379 NSString *metadataValueCellText = value;
380 if ([metadataKeyCellText length] > maxMetadataViewableLength) {
381 metadataKeyCellText = [metadataKeyCellText substringToIndex:(maxMetadataViewableLength - 3)];
382 metadataKeyCellText = [metadataKeyCellText stringByAppendingString:@"..."];
384 if ([metadataValueCellText length] > maxMetadataViewableLength) {
385 metadataValueCellText = [metadataValueCellText substringToIndex:(maxMetadataViewableLength - 3)];
386 metadataValueCellText = [metadataValueCellText stringByAppendingString:@"..."];
388 cell.textLabel.text = metadataKeyCellText;
389 cell.detailTextLabel.text = metadataValueCellText;
391 } else if (indexPath.section == policySection) {
392 cell.selectionStyle = UITableViewCellSelectionStyleBlue;
393 if (indexPath.row == 0) {
394 cell.textLabel.text = @"Versioning";
395 cell.detailTextLabel.text = container.versioning;
396 cell.accessoryType = UITableViewCellAccessoryNone;
397 cell.selectionStyle = UITableViewCellEditingStyleNone;
399 else if (indexPath.row == 1) {
400 cell.textLabel.text = @"Quota";
401 cell.detailTextLabel.text = [NSString stringWithFormat:@"%u", container.quota];
402 cell.accessoryType = UITableViewCellAccessoryNone;
403 cell.selectionStyle = UITableViewCellEditingStyleNone;
406 cell.textLabel.text = @"Edit policy";
407 cell.detailTextLabel.text = @"";
408 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
410 } else if (indexPath.section == deleteSection) {
411 return [self tableView:tableView deleteCellForRowAtIndexPath:indexPath];
412 } else if (indexPath.section == kLogRetention) {
413 cell.textLabel.text = @"Log Retention";
414 cell.detailTextLabel.text = @"";
415 cell.accessoryView = logRetentionSwitch;
416 cell.accessoryType = UITableViewCellAccessoryNone;
417 cell.selectionStyle = UITableViewCellSelectionStyleNone;
418 } else if (indexPath.section == kReferrerACL) {
419 cell.textLabel.text = @"Referrer ACL";
420 cell.detailTextLabel.text = container.referrerACL;
421 cell.accessoryView = nil;
422 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
423 cell.selectionStyle = UITableViewCellSelectionStyleBlue;
424 cell.detailTextLabel.numberOfLines = 1;
425 } else if (indexPath.section == kUserAgentACL) {
426 cell.textLabel.text = @"User Agent ACL";
427 cell.detailTextLabel.text = container.useragentACL;
428 cell.accessoryView = nil;
429 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
430 cell.selectionStyle = UITableViewCellSelectionStyleBlue;
431 cell.detailTextLabel.numberOfLines = 1;
438 #pragma mark Table view delegate
440 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
442 if (indexPath.section == kMetadata) {
443 EditMetadataViewController *vc = [[EditMetadataViewController alloc] initWithNibName:@"EditMetadataViewController" bundle:nil];
444 NSString *metadataKey;
445 NSString *metadataValue;
447 if (indexPath.row == [self.container.metadata count]) {
450 vc.removeMetadataEnabled = FALSE;
451 vc.navigationItem.title = @"Add Metadata";
454 metadataKey = [[self.container.metadata allKeys] objectAtIndex:indexPath.row];
455 metadataValue = [self.container.metadata objectForKey:metadataKey];
456 vc.removeMetadataEnabled = TRUE;
457 vc.navigationItem.title = @"Edit Metadata";
460 StorageObject *object = [[[StorageObject alloc] init] autorelease];
461 object.name = container.name;
462 object.metadata = container.metadata;
463 object.fullPath = @"";
465 vc.metadataKey = metadataKey;
466 vc.metadataValue = metadataValue;
467 vc.account = account;
468 vc.container = container;
471 [self.navigationController pushViewController:vc animated:YES];
473 } else if (indexPath.section == policySection) {
474 if (indexPath.row == 2) {
475 EditPolicyViewController *vc = [[EditPolicyViewController alloc] initWithNibName:@"EditPolicyViewController" bundle:nil];
477 vc.account = account;
478 vc.container = container;
479 vc.containerDetailViewController = self;
481 [self.navigationController pushViewController:vc animated:YES];
484 } else if (indexPath.section == deleteSection) {
485 if (self.container.count == 0 || ([self.container.rootFolder.folders count] + [self.container.rootFolder.objects count] == 0)) {
486 [deleteActionSheet showInView:self.view];
488 } else if (indexPath.section == kCDNAttributes && indexPath.row == 0) {
489 [cdnURLActionSheet showInView:self.view];
490 } else if (indexPath.section == kReferrerACL) {
491 ReferrerACLViewController *vc = [[ReferrerACLViewController alloc] initWithNibName:@"ReferrerACLViewController" bundle:nil];
492 vc.account = self.account;
493 vc.container = self.container;
494 vc.containerDetailViewController = self;
495 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
496 vc.modalPresentationStyle = UIModalPresentationFormSheet;
497 [self presentModalViewControllerWithNavigation:vc animated:YES];
499 [self.navigationController pushViewController:vc animated:YES];
502 } else if (indexPath.section == kUserAgentACL) {
503 UserAgentACLViewController *vc = [[UserAgentACLViewController alloc] initWithNibName:@"UserAgentACLViewController" bundle:nil];
504 vc.account = self.account;
505 vc.container = self.container;
506 vc.containerDetailViewController = self;
507 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
508 vc.modalPresentationStyle = UIModalPresentationFormSheet;
509 [self presentModalViewControllerWithNavigation:vc animated:YES];
511 [self.navigationController pushViewController:vc animated:YES];
518 #pragma mark Switches
520 - (void)cdnEnabledSwitchChanged:(id)sender {
522 NSString *activityMessage = @"Disabling CDN Access...";
523 if (!container.cdnEnabled) {
524 activityMessage = @"Enabling CDN Access...";
526 activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
527 [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y];
528 container.cdnEnabled = !container.cdnEnabled;
529 [self.account.manager updateCDNContainer:container];
531 successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"updateCDNContainerSucceeded" object:self.container
532 queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification)
534 [activityIndicatorView removeFromSuperviewAndRelease];
536 NSIndexSet *sections = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(3, 4)];
537 NSInteger oldDeleteSection = deleteSection;
538 if (container.cdnEnabled) {
541 [self.tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(oldDeleteSection, 1)] withRowAnimation:UITableViewRowAnimationBottom];
543 [self.tableView insertSections:sections withRowAnimation:UITableViewRowAnimationBottom];
547 [self.tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(deleteSection, 1)] withRowAnimation:UITableViewRowAnimationTop];
549 [self.tableView deleteSections:sections withRowAnimation:UITableViewRowAnimationTop];
552 [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
555 failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"updateCDNContainerFailed" object:self.container
556 queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification)
558 [activityIndicatorView removeFromSuperviewAndRelease];
559 container.cdnEnabled = !container.cdnEnabled;
560 cdnEnabledSwitch.on = !cdnEnabledSwitch.on;
561 [self alert:@"There was a problem updating this container." request:[notification.userInfo objectForKey:@"request"]];
562 [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
566 - (void)logRetentionSwitchChanged:(id)sender {
568 NSString *activityMessage = @"Disabling Log Retention...";
569 if (!container.logRetention) {
570 activityMessage = @"Enabling Log Retention...";
572 activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
573 [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y];
575 container.logRetention = !container.logRetention;
576 [self.account.manager updateCDNContainer:container];
578 successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"updateCDNContainerSucceeded" object:self.container
579 queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification)
581 [activityIndicatorView removeFromSuperviewAndRelease];
582 [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
585 failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"updateCDNContainerFailed" object:self.container
586 queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification)
588 [activityIndicatorView removeFromSuperviewAndRelease];
589 container.logRetention = !container.logRetention;
590 logRetentionSwitch.on = !logRetentionSwitch.on;
591 [self alert:@"There was a problem updating this container." request:[notification.userInfo objectForKey:@"request"]];
592 [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
597 #pragma mark Action Sheet
599 - (void)deleteContainerRow {
600 if ([self.account.containers count] == 0) {
601 [self.containersViewController.tableView reloadData];
603 [self.containersViewController.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:selectedContainerIndexPath] withRowAnimation:UITableViewRowAnimationLeft];
605 [self.rootFolderViewController.navigationController popViewControllerAnimated:YES];
608 - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
609 if ([actionSheet isEqual:cdnURLActionSheet]) {
610 if (buttonIndex == 0) {
611 UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
612 [pasteboard setString:container.cdnURL];
614 [self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kCDNAttributes] animated:YES];
615 } else if ([actionSheet isEqual:deleteActionSheet]) {
616 if (buttonIndex == 0) {
618 NSString *activityMessage = @"Deleting container...";
619 activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
620 [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y];
622 [self.account.manager deleteContainer:self.container];
624 successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"deleteContainerSucceeded" object:self.container
625 queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification)
627 [activityIndicatorView removeFromSuperviewAndRelease];
629 [self.account.containers removeObjectForKey:self.container.name];
630 [self.account persist];
632 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && [self.account.containers count] == 0) {
633 // on ipad, delete needs to get rid of the container on the main view
634 self.container = nil;
635 [self setBackgroundView];
636 [self.tableView reloadData];
638 [self.navigationController popViewControllerAnimated:YES];
641 [self deleteContainerRow];
642 //[NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(deleteContainerRow) userInfo:nil repeats:NO];
644 [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
647 failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"deleteContainerFailed" object:self.container
648 queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification)
650 [activityIndicatorView removeFromSuperviewAndRelease];
651 [self alert:@"There was a problem deleting this container." request:[notification.userInfo objectForKey:@"request"]];
652 [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
657 [self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:deleteSection] animated:YES];
663 #pragma mark Memory management
668 [cdnEnabledSwitch release];
670 [cdnURLActionSheet release];
671 [deleteActionSheet release];
672 [containersViewController release];
673 [selectedContainerIndexPath release];
674 [rootFolderViewController release];