X-Git-Url: https://code.grnet.gr/git/pithos-ios/blobdiff_plain/d6b38316924ac9fff419909a650e0572f99b3eaa..1e0727825e64e25aa9afe67829eed2152b273eb7:/Classes/StorageObjectViewController.m diff --git a/Classes/StorageObjectViewController.m b/Classes/StorageObjectViewController.m index b1a46eb..98c353d 100755 --- a/Classes/StorageObjectViewController.m +++ b/Classes/StorageObjectViewController.m @@ -22,231 +22,490 @@ #import "EditMetadataViewController.h" #import "Provider.h" #import "EditPermissionsViewController.h" +#import "TextViewCell.h" +#import "NSString+Conveniences.h" +#import "APICallback.h" +#import "ObjectVersionsViewController.h" +#import +#import +#import "ActivityIndicatorView.h" #define kDetails 0 -#define kMetadata 1 -#define kPublic 2 -#define kPermissions 3 +#define kActions 1 +#define kMetadata 2 #define maxMetadataViewableLength 12 - // TODO: use etag to reset download // TODO: try downloading directly to the file to save memory. don't use object.data /* - Name whatever.txt - Full Path - Size 123 KB - Content Type text/plain - - Metadata - Key Value -> tap goes to a metadata item VC to edit or delete - Key Value - Add Metadata... (if max not already reached) +Name whatever.txt +Full Path folder/whatever.txt +Size 123 KB +Type text/plain +Last Modified 2012-12-21 11:11:00 + +if fileDownloaded: + Open File + Mail File + Delete from Cache +else if fileDownloading: + Open File (disabled) + Mail File (disabled) + Downloading (progress view) + Cancel +else: + Open File + Mail File + +Metadata +Key Value -> tap goes to a metadata item VC to edit or delete +Key Value +Add Metadata... (if max not already reached) + +Public URL On/Off + +Share - CDN URL sections (action sheet to copy, open in safari, and email link) +Versions - Download File (if downloaded, Open File and Mail File as Attachment) - "After you download the file, you'll be able to attempt to open it and mail is as an attachment." - - Delete Object - */ +Delete Object +*/ @implementation StorageObjectViewController -@synthesize account, container, folder, object, tableView, folderViewController; -@synthesize oldPubicURI; +@synthesize account, container, folder, object, folderViewController; +@synthesize oldPublicURI, permissions, documentInteractionController, objectIsReadOnly, versionID; -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { - return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); -} +#pragma mark - View lifecycle -- (void)setBackgroundView { - - UIImageView *logo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cloudfiles-large.png"]]; - - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - UIView *backgroundContainer = [[UIView alloc] init]; - backgroundContainer.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - backgroundContainer.backgroundColor = [UIColor iPadTableBackgroundColor]; - logo.contentMode = UIViewContentModeScaleAspectFit; - logo.frame = CGRectMake(100.0, 100.0, 1000.0, 1000.0); - logo.alpha = 0.5; - [backgroundContainer addSubview:logo]; - tableView.backgroundView = backgroundContainer; - [backgroundContainer release]; - } else { - self.tableView.backgroundView = nil; - } - [logo release]; -} - -- (IBAction)homeButtonPressed:(id)sender { - [self.navigationController popToRootViewControllerAnimated:YES]; +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { + return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); } -#pragma mark - -#pragma mark View lifecycle - - (void)viewDidLoad { [super viewDidLoad]; + objectIsPublicSwitch = [[UISwitch alloc] init]; [objectIsPublicSwitch addTarget:self action:@selector(objectIsPublicSwitchChanged:) forControlEvents:UIControlEventValueChanged]; - deleteActionSheet = [[UIActionSheet alloc] initWithTitle:@"Are you sure you want to delete this file? This operation cannot be undone." delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Delete File" otherButtonTitles:nil]; - - permissions = [[NSMutableDictionary alloc] init]; - NSArray *sharingArray = [object.sharing componentsSeparatedByString:@";"]; - for (NSString *typeSpecificPermissions in sharingArray) { - NSArray *array=[typeSpecificPermissions componentsSeparatedByString:@"="]; - NSString *permissionsType = [array objectAtIndex:0]; - if ([permissionsType hasPrefix:@" "]) - permissionsType = [permissionsType substringFromIndex:1]; - - NSArray *users = [[array objectAtIndex:1] componentsSeparatedByString:@","]; - for (NSString *user in users) { - [permissions setObject:permissionsType forKey:user]; + self.permissions = [object permissions]; + objectIsReadOnly = NO; + if (account.sharingAccount) { + if (permissions.count) { + objectIsReadOnly = ![[permissions objectForKey:account.username] isEqualToString:@"write"]; } - } + objectIsPublicSwitch.enabled = NO; + } + + downloadProgressView = [[AnimatedProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault]; + fileDownloading = NO; + OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; + OpenStackRequest *request = [app objectDownloadRequestForAccount:account container:container object:object]; + if (request) { + fileDownloading = YES; + request.downloadProgressDelegate = self; + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:kActions] withRowAnimation:UITableViewRowAnimationNone]; + } + } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.navigationItem.title = object.name; - NSIndexPath* selection = [self.tableView indexPathForSelectedRow]; + NSIndexPath *selection = [self.tableView indexPathForSelectedRow]; if (selection) [self.tableView deselectRowAtIndexPath:selection animated:YES]; - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *shortPath = [NSString stringWithFormat:@"/%@/%@", self.container.name, self.object.fullPath]; - NSString *filePath = [documentsDirectory stringByAppendingString:shortPath]; - - NSFileManager *fileManager = [NSFileManager defaultManager]; - fileDownloaded = [fileManager fileExistsAtPath:filePath]; - - downloadProgressView = [[AnimatedProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault]; + OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; + if ([app cacheFilePathForHash:object.hash]) { + fileDownloaded = YES; + } else { + fileDownloaded = NO; + } - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) { CGRect rect = downloadProgressView.frame; rect.size.width = 440.0; downloadProgressView.frame = rect; } - [self setBackgroundView]; - if (self.container.cdnEnabled) { - cdnURLSection = 4; - actionsSection = 5; - deleteSection = 6; - } else { - cdnURLSection = -1; - actionsSection = 4; - deleteSection = 5; + publicLinkSection = 3; + permissionsSection = 4; + versionsSection = 5; + deleteSection = 6; + + if (versionID) { + publicLinkSection = -1; + permissionsSection = -1; + versionsSection = -1; + deleteSection = -1; + objectIsReadOnly = YES; + } + if (account.sharingAccount || account.shared) { + versionsSection = -1; + deleteSection = -1; } - // let's see if we can tweet - UIApplication *app = [UIApplication sharedApplication]; - NSURL *twitterURL = [NSURL URLWithString:@"twitter://post?message=test"]; + objectIsPublic = ([object.publicURI length]); + objectIsPublicSwitch.on = objectIsPublic; + [self.tableView reloadData]; +} - if ([app canOpenURL:twitterURL]) { - cdnURLActionSheet = [[UIActionSheet alloc] initWithTitle:[[NSString stringWithFormat:@"%@/%@", self.container.cdnURL, self.object.fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Copy to Pasteboard", @"Open in Safari", @"Email Link to File", @"Tweet Link to File", nil]; +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + if (!object.metadata) { + [self reloadMetadataSection]; } else { - cdnURLActionSheet = [[UIActionSheet alloc] initWithTitle:[[NSString stringWithFormat:@"%@/%@", self.container.cdnURL, self.object.fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Copy to Pasteboard", @"Open in Safari", @"Email Link to File", nil]; + [self updatePermissionsUserCatalog]; + } + if (fileDownloading) { + [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:kActions] + atScrollPosition:UITableViewScrollPositionMiddle + animated:YES]; + } +} + +#pragma mark - Memory management + +- (void)dealloc { + if (fileDownloading) { + OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; + OpenStackRequest *request = [app objectDownloadRequestForAccount:account container:container object:object]; + request.downloadProgressDelegate = nil; } + [account release]; + [downloadProgressView release]; + [cdnURLActionSheet release]; + [folderViewController release]; + [oldPublicURI release]; + [permissions release]; + [objectIsPublicSwitch release]; + [documentInteractionController release]; + [versionID release]; + [super dealloc]; +} + +#pragma mark - Internal + +- (void)objectIsPublicSwitchChanged:(id)sender { + NSString *activityMessage = [NSString stringWithFormat:@"Enabling public link.."]; + self.oldPublicURI = object.publicURI; - objectIsPublic = (object.publicURI != nil); - objectIsPublicSwitch.on = objectIsPublic; - [self.tableView reloadData]; + if (objectIsPublic) { + activityMessage = [NSString stringWithFormat:@"Disabling public link.."]; + object.publicURI = @""; + } else { + object.publicURI = @"TRUE"; + } + __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:activityMessage + andAddToView:self.view + scrollOffset:self.tableView.contentOffset.y]; + objectIsPublic = !objectIsPublic; + [[self.account.manager writeObjectMetadata:container object:object] + success:^(OpenStackRequest *request) { + NSIndexPath *publicURICellIndexPath = [NSIndexPath indexPathForRow:1 inSection:publicLinkSection]; + if (objectIsPublic) { + [[self.account.manager getObjectInfo:container object:object version:versionID] + success:^(OpenStackRequest *request) { + [activityIndicatorView stopAnimatingAndRemoveFromSuperview]; + object.publicURI = [request.responseHeaders objectForKey:@"X-Object-Public"]; + NSIndexPath *publicURICellIndexPath = [NSIndexPath indexPathForRow:1 inSection:publicLinkSection]; + [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:publicURICellIndexPath] + withRowAnimation:UITableViewRowAnimationBottom]; + } + failure:^(OpenStackRequest *request) { + [activityIndicatorView stopAnimatingAndRemoveFromSuperview]; + [self alert:@"There was a problem retrieving the public link from the server." request:request]; + }]; + } else { + [activityIndicatorView stopAnimatingAndRemoveFromSuperview]; + [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:publicURICellIndexPath] + withRowAnimation:UITableViewRowAnimationTop]; + } + } + failure:^(OpenStackRequest *request) { + [activityIndicatorView stopAnimatingAndRemoveFromSuperview]; + objectIsPublic = !objectIsPublic; + objectIsPublicSwitch.on = !objectIsPublicSwitch.on; + object.publicURI = oldPublicURI; + [self alert:@"There was a problem enabling the public link." request:request]; + }]; } -#pragma mark - -#pragma mark Table view data source +- (void)openFile { + OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; + NSString *filePath = [app cacheFilePathForHash:object.hash]; + self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:filePath]]; + self.documentInteractionController.delegate = self; + self.documentInteractionController.name = object.name; + + CGRect frameToPresentMenuFrom; + if ([[UIDevice currentDevice].systemVersion hasPrefix:@"6"]) { + frameToPresentMenuFrom = CGRectMake(0.0, + self.tableView.contentOffset.y, + self.view.frame.size.width, + 1.0); + } else { + UITableViewCell *openFileCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kActions]]; + frameToPresentMenuFrom = CGRectMake(openFileCell.frame.origin.x, + openFileCell.frame.origin.y - self.tableView.contentOffset.y, + openFileCell.frame.size.width, + openFileCell.frame.size.height); + } + if (![self.documentInteractionController presentOptionsMenuFromRect:frameToPresentMenuFrom inView:self.view animated:YES]) { + if ([self.object isPlayableMedia]) { + MediaViewController *vc = [[MediaViewController alloc] initWithNibName:@"MediaViewController" bundle:nil]; + vc.container = self.container; + vc.object = self.object; + [self.navigationController pushViewController:vc animated:YES]; + [vc release]; + } else { + [self alert:@"Error" message:@"This file could not be opened."]; + } + } +} + +- (void)mailFile { + if (![MFMailComposeViewController canSendMail]) { + [self alert:@"Cannot send mail" message:@"Your device has not been configured for sending mail"]; + } else { + OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; + NSString *filePath = [app cacheFilePathForHash:object.hash]; + NSData *data = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:filePath]]; + + MFMailComposeViewController *vc = [[MFMailComposeViewController alloc] init]; + vc.mailComposeDelegate = self; + [vc setSubject:object.name]; + [vc addAttachmentData:data mimeType:object.contentType fileName:object.name]; + [vc setMessageBody:@"" isHTML:NO]; + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) + vc.modalPresentationStyle = UIModalPresentationPageSheet; + [self presentModalViewController:vc animated:YES]; + [vc release]; + } +} + +- (void)updatePermissionsUserCatalog { + NSMutableArray *UUIDs = [NSMutableArray arrayWithCapacity:permissions.count]; + for (NSString *user in permissions) { + NSRange rangeOfColumn = [user rangeOfString:@":"]; + NSString *UUID = (rangeOfColumn.location == NSNotFound) ? user : [user substringToIndex:rangeOfColumn.location]; + if (![UUID isEqualToString:@"*"]) { + [UUIDs addObject:UUID]; + } + } + if (UUIDs.count) { + __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Loading permissions..." + andAddToView:self.view]; + [[self.account.manager userCatalogForDisplaynames:nil UUIDs:UUIDs] + success:^(OpenStackRequest *request) { + [activityIndicatorView stopAnimatingAndRemoveFromSuperview]; + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:permissionsSection] withRowAnimation:UITableViewRowAnimationNone]; + } + failure:^(OpenStackRequest *request) { + [activityIndicatorView stopAnimatingAndRemoveFromSuperview]; + if (request.responseStatusCode != 404) { + // Don't show alert on 404, since it can be a pre-UUID server. + [self alert:@"Failed to translate sharing UUIDs." request:request]; + } + }]; + } +} + +- (void)delete { + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) { + folderViewController.deletedObject = object; + [self.navigationController popViewControllerAnimated:YES]; + } else { + [folderViewController deleteAnimatedObject:object]; + [folderViewController setDetailViewController]; + } +} + +#pragma mark - Actions + +- (void)reloadMetadataSection { + __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Loading metadata..." + andAddToView:self.view]; + [[self.account.manager getObjectInfo:container object:object version:versionID] + success:^(OpenStackRequest *request) { + [activityIndicatorView stopAnimatingAndRemoveFromSuperview]; + object.metadata = [NSMutableDictionary dictionary]; + for (NSString *header in request.responseHeaders) { + NSString *metadataKey; + NSString *metadataValue; + if ([header rangeOfString:@"X-Object-Meta-"].location != NSNotFound) { + metadataKey = [NSString decodeFromPercentEscape:[header substringFromIndex:14]]; + metadataValue = [NSString decodeFromPercentEscape:[request.responseHeaders objectForKey:header]]; + [object.metadata setObject:metadataValue forKey:metadataKey]; + } + } + [self.tableView reloadData]; + [self updatePermissionsUserCatalog]; + } + failure:^(OpenStackRequest *request) { + [activityIndicatorView stopAnimatingAndRemoveFromSuperview]; + [self alert:@"There was a problem retrieving the object's metadata." request:request]; + }]; +} + +- (void)downloadFileForAction:(StorageObjectAction)action { + if (fileDownloading) + return; + fileDownloading = YES; + [downloadProgressView setProgress:0.0 animated:NO]; + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:kActions] withRowAnimation:UITableViewRowAnimationNone]; + [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:kActions] + atScrollPosition:UITableViewScrollPositionMiddle + animated:YES]; + NSMutableDictionary *requestUserInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:action] forKey:@"action"]; + [[self.account.manager getObject:self.container object:self.object downloadProgressDelegate:self requestUserInfo:requestUserInfo version:versionID] + success:^(OpenStackRequest *request) { + if (request.isCancelled) { + fileDownloaded = NO; + fileDownloading = NO; + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:kActions] withRowAnimation:UITableViewRowAnimationNone]; + } else { + fileDownloaded = YES; + fileDownloading = NO; + if ([self.navigationController.visibleViewController isEqual:self]) { + if ([[request.userInfo objectForKey:@"action"] integerValue] == StorageObjectActionMailFile) { + [self mailFile]; + } else { + [self openFile]; + } + } + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:kActions] withRowAnimation:UITableViewRowAnimationNone]; + } + } + failure:^(OpenStackRequest *request) { + fileDownloaded = NO; + fileDownloading = NO; + [self alert:@"File failed to download." request:request]; + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:kActions] withRowAnimation:UITableViewRowAnimationNone]; + }]; +} + +#pragma mark - UITableViewDataSource - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return self.container.cdnEnabled ? 7 : 6; + int numberOfSections = 7; + if (publicLinkSection < 0) + numberOfSections--; + if (permissionsSection < 0) + numberOfSections--; + if (versionsSection < 0) + numberOfSections--; + if (deleteSection < 0) + numberOfSections--; + + return numberOfSections; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section == kDetails) { - return 4; + return (object.lastModifiedString ? 5: 4); + } else if (section == kActions) { + if (fileDownloaded) { + return 3; + } else if (fileDownloading) { + return 4; + } else { + return 2; + } } else if (section == kMetadata) { - return 1 + [object.metadata count]; - } else if (section == cdnURLSection) { - return 1; - } else if (section == actionsSection) { - return fileDownloaded ? 2 : 1; - } else if (section == kPublic) { - return objectIsPublic ? 2 : 1; - } else if (section == kPermissions) { - return 1 + [permissions count]; + if (objectIsReadOnly) { + return [object.metadata count]; + } else { + return ([object.metadata count] + 1); + } + } else if (section == publicLinkSection) { + return (objectIsPublic ? 2 : 1); + } else if (section == permissionsSection) { + if (account.sharingAccount || objectIsReadOnly) { + return permissions.count; + } else { + return (permissions.count + 1); + } } else { return 1; } } -- (CGFloat)findLabelHeight:(NSString*)text font:(UIFont *)font { - CGSize textLabelSize; - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - // 616, 678 - textLabelSize = CGSizeMake(596.0, 9000.0f); - } else { - textLabelSize = CGSizeMake(280.0, 9000.0f); - } - CGSize stringSize = [text sizeWithFont:font constrainedToSize:textLabelSize lineBreakMode:UILineBreakModeCharacterWrap]; - return stringSize.height; -} - - (CGFloat)tableView:(UITableView *)aTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { CGFloat result = aTableView.rowHeight; - - if (indexPath.section == cdnURLSection) { - result = 22.0 + [self findLabelHeight:[[NSString stringWithFormat:@"%@/%@", self.container.cdnURL, self.object.fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] font:[UIFont systemFontOfSize:18.0]]; - } else if (indexPath.section == kDetails && indexPath.row == 1) { - CGSize textLabelSize; - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - textLabelSize = CGSizeMake(537.0, 9000.0f); - } else { - textLabelSize = CGSizeMake(221.0, 9000.0f); - } - CGSize stringSize = [object.fullPath sizeWithFont:[UIFont systemFontOfSize:18.0] constrainedToSize:textLabelSize lineBreakMode:UILineBreakModeWordWrap]; - return 22.0 + stringSize.height; - } else if (indexPath.section == kDetails && indexPath.row == 0) { - CGSize textLabelSize; - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - textLabelSize = CGSizeMake(537.0, 9000.0f); + if ((indexPath.section == kDetails) && ((indexPath.row == 0) || (indexPath.row == 1))) { + NSString *text; + if (indexPath.row == 0) { + text = object.name; } else { - textLabelSize = CGSizeMake(221.0, 9000.0f); + text = object.fullPath; } - CGSize stringSize = [object.name sizeWithFont:[UIFont systemFontOfSize:18.0] constrainedToSize:textLabelSize lineBreakMode:UILineBreakModeWordWrap]; - return 22.0 + stringSize.height; - } else if (indexPath.section == kPublic && indexPath.row == 1) { - result = 22.0 + [self findLabelHeight:[NSString stringWithFormat:@"%@%@", self.account.provider.authEndpointURL, self.object.fullPath] font:[UIFont systemFontOfSize:15.0]]; - return result; + result = 22.0 + [text sizeWithFont:[UIFont systemFontOfSize:18.0] + constrainedToSize:(([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) ? + CGSizeMake(537.0, 9000.0) : + CGSizeMake(221.0, 9000.0)) + lineBreakMode:UILineBreakModeCharacterWrap].height; + } else if ((indexPath.section == publicLinkSection) && (indexPath.row == 1)) { + NSURL *publicLinkURL = [account.provider.publicLinkURLPrefix URLByAppendingPathComponent: + [NSString encodeToPercentEscape:[self.object.publicURI substringFromIndex:1] + charactersToEncode:@"!*'();:@&=+$,?%#[]"]]; + result = 30.0 + [[publicLinkURL description] sizeWithFont:[UIFont systemFontOfSize:18.0] + constrainedToSize:(([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) ? + CGSizeMake(596.0, 9000.0) : + CGSizeMake(280.0, 9000.0)) + lineBreakMode:UILineBreakModeCharacterWrap].height; } - return MAX(aTableView.rowHeight, result); } - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + if ((indexPath.section == publicLinkSection) && (indexPath.row == 1)) { + static NSString *CellIdentifier = @"TextViewCell"; + TextViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[TextViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + cell.textView.frame = cell.contentView.frame; + + } + cell.selectionStyle = UITableViewCellSelectionStyleNone; + cell.textView.backgroundColor = [UIColor clearColor]; + cell.textView.font = [UIFont systemFontOfSize:15.0]; + cell.textView.dataDetectorTypes = UIDataDetectorTypeLink; + cell.textView.text = [[account.provider.publicLinkURLPrefix URLByAppendingPathComponent: + [NSString encodeToPercentEscape:[self.object.publicURI substringFromIndex:1] + charactersToEncode:@"!*'();:@&=+$,?%#[]"]] description]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + cell.accessoryView = UITableViewCellAccessoryNone; + return cell; + } - static NSString *CellIdentifier = @"Cell"; + if (indexPath.section == deleteSection) { + static NSString *CellIdentifier = @"DeleteCell"; + UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + cell.selectionStyle = UITableViewCellSelectionStyleBlue; + cell.textLabel.textAlignment = UITextAlignmentCenter; + cell.textLabel.text = @"Delete Object"; + } + return cell; + } + static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease]; - //cell.backgroundColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.93]; cell.textLabel.backgroundColor = [UIColor clearColor]; cell.detailTextLabel.backgroundColor = [UIColor clearColor]; - cell.detailTextLabel.numberOfLines = 0; cell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap; } - - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - cell.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.8]; - } - + cell.textLabel.textColor = [UIColor blackColor]; + cell.detailTextLabel.numberOfLines = 0; + cell.userInteractionEnabled = YES; cell.detailTextLabel.textAlignment = UITextAlignmentRight; cell.accessoryView = nil; cell.textLabel.font = [UIFont boldSystemFontOfSize:17.0]; @@ -268,10 +527,21 @@ } else if (indexPath.row == 3) { cell.textLabel.text = @"Type"; cell.detailTextLabel.text = object.contentType; + } else if (indexPath.row == 4) { + cell.textLabel.text = @"Last Modified"; + cell.detailTextLabel.text = object.lastModifiedString; } } else if (indexPath.section == kMetadata) { - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.selectionStyle = UITableViewCellSelectionStyleBlue; + if (objectIsReadOnly) { + cell.accessoryType = UITableViewCellAccessoryNone; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + cell.userInteractionEnabled = NO; + } + else { + cell.selectionStyle = UITableViewCellSelectionStyleBlue; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + } + cell.accessoryView = nil; if (indexPath.row == [object.metadata count]) { cell.textLabel.text = @"Add Metadata"; @@ -293,7 +563,7 @@ cell.textLabel.text = metadataKeyCellText; cell.detailTextLabel.text = metadataValueCellText; } - } else if (indexPath.section == kPublic) { + } else if (indexPath.section == publicLinkSection) { if (indexPath.row == 0) { cell.textLabel.text = @"Public URL"; cell.detailTextLabel.text = @""; @@ -301,79 +571,86 @@ cell.accessoryType = UITableViewCellAccessoryNone; cell.selectionStyle = UITableViewCellSelectionStyleNone; } - else if (indexPath.row == 1) { - cell.textLabel.numberOfLines = 0; - cell.textLabel.lineBreakMode = UILineBreakModeWordWrap; - cell.textLabel.text = [NSString stringWithFormat:@"%@%@", self.account.provider.authEndpointURL, object.publicURI]; - cell.textLabel.font = [UIFont systemFontOfSize:15.0]; + } else if (indexPath.section == permissionsSection) { + if (account.sharingAccount) { + cell.accessoryType = UITableViewCellAccessoryNone; cell.selectionStyle = UITableViewCellSelectionStyleNone; - cell.accessoryView = UITableViewCellAccessoryNone; - cell.detailTextLabel.text = @""; + cell.userInteractionEnabled = NO; + } else { + cell.selectionStyle = UITableViewCellSelectionStyleBlue; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } - } else if (indexPath.section == kPermissions) { - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.selectionStyle = UITableViewCellSelectionStyleBlue; cell.accessoryView = nil; - if (indexPath.row == [permissions count]) { - cell.textLabel.text = @"Add Permissions"; + + if (indexPath.row == permissions.count) { + cell.textLabel.text = @"Share"; cell.detailTextLabel.text = @""; - } - else { - NSString *user = [[permissions allKeys] objectAtIndex:indexPath.row]; - cell.textLabel.text = user; - cell.detailTextLabel.text = [permissions objectForKey:user]; - } - } else if (indexPath.section == cdnURLSection) { - cell.detailTextLabel.textAlignment = UITextAlignmentLeft; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.textLabel.text = @""; - cell.detailTextLabel.text = [[NSString stringWithFormat:@"%@/%@", self.container.cdnURL, self.object.fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - } else if (indexPath.section == actionsSection) { - cell.accessoryView = nil; - if (performingAction) { - cell.textLabel.textColor = [UIColor grayColor]; - cell.selectionStyle = UITableViewCellSelectionStyleNone; - cell.accessoryType = UITableViewCellAccessoryNone; } else { - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.selectionStyle = UITableViewCellSelectionStyleBlue; + NSString *user = [[[permissions allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] objectAtIndex:indexPath.row]; + NSRange rangeOfColumn = [user rangeOfString:@":"]; + NSString *UUID = (rangeOfColumn.location == NSNotFound) ? user : [user substringToIndex:rangeOfColumn.location]; + NSString *group = ((rangeOfColumn.location == NSNotFound) || (rangeOfColumn.location == user.length - 1)) ? nil : [user substringFromIndex:(rangeOfColumn.location + 1)]; + NSMutableString *displayname = [NSMutableString stringWithString:[account displaynameForUUID:UUID safe:YES]]; + if (group) { + [displayname appendFormat:@":%@", group]; + } + cell.textLabel.text = displayname; + + cell.detailTextLabel.numberOfLines = 1; + cell.detailTextLabel.lineBreakMode = UILineBreakModeTailTruncation; + cell.detailTextLabel.text = ([[permissions objectForKey:user] isEqualToString:@"write"] ? @"Read/Write" : @"Read Only"); } - + } else if (indexPath.section == kActions) { if (indexPath.row == 0) { - if (fileDownloaded) { - cell.textLabel.text = @"Open File"; + cell.textLabel.text = @"Open File"; + cell.accessoryType = UITableViewCellAccessoryNone; + cell.detailTextLabel.text = @""; + if (fileDownloading) { + cell.textLabel.textColor = [UIColor grayColor]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; } else { - if (fileDownloading) { - cell.accessoryView = downloadProgressView; - // TODO: if you leave this view while downloading, there's EXC_BAD_ACCESS - cell.textLabel.text = @"Downloading"; - } else { - cell.textLabel.text = @"Download File"; - } + cell.selectionStyle = UITableViewCellSelectionStyleBlue; } - cell.detailTextLabel.text = @""; - } else if (indexPath.row == 1) { cell.textLabel.text = @"Email File as Attachment"; cell.detailTextLabel.text = @""; + cell.accessoryType = UITableViewCellAccessoryNone; + if (fileDownloading) { + cell.textLabel.textColor = [UIColor grayColor]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + } else { + cell.selectionStyle = UITableViewCellSelectionStyleBlue; + } + } else if (indexPath.row == 2) { + if (fileDownloaded) { + cell.textLabel.text = @"Remove from Cache"; + cell.accessoryType = UITableViewCellAccessoryNone; + cell.detailTextLabel.text = @""; + } else if (fileDownloading) { + cell.textLabel.text = @"Downloading"; + cell.accessoryType = UITableViewCellAccessoryNone; + cell.detailTextLabel.text = @""; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + cell.accessoryView = downloadProgressView; + } + } else if (indexPath.row == 3) { + if (fileDownloading) { + cell.textLabel.text = @"Cancel"; + cell.accessoryType = UITableViewCellAccessoryNone; + cell.detailTextLabel.text = @""; + } } - } else if (indexPath.section == deleteSection) { - cell.textLabel.text = @"Delete Object"; - cell.detailTextLabel.text = @""; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + } else if (indexPath.section == versionsSection) { cell.selectionStyle = UITableViewCellSelectionStyleBlue; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + cell.textLabel.text = @"Versions"; + cell.detailTextLabel.text = @""; } return cell; } - -#pragma mark - -#pragma mark Table view delegate - -- (void)reloadActionsTitleRow:(NSTimer *)timer { - [[timer.userInfo objectForKey:@"tableView"] reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:actionsSection]] withRowAnimation:UITableViewRowAnimationNone]; -} +#pragma mark - UITableViewDelegate - (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == kMetadata) { @@ -384,13 +661,12 @@ if (indexPath.row == [self.object.metadata count]) { metadataKey = @""; metadataValue = @""; - vc.deleteEnabled = FALSE; + vc.removeMetadataEnabled = FALSE; vc.navigationItem.title = @"Add Metadata"; - } - else { + } else { metadataKey = [[self.object.metadata allKeys] objectAtIndex:indexPath.row]; metadataValue = [self.object.metadata objectForKey:metadataKey]; - vc.deleteEnabled = YES; + vc.removeMetadataEnabled = YES; vc.navigationItem.title = @"Edit Metadata"; } @@ -401,103 +677,91 @@ vc.object = object; [self.navigationController pushViewController:vc animated:YES]; [vc release]; - } else if (indexPath.section == kPermissions) { + } else if (indexPath.section == permissionsSection) { EditPermissionsViewController *vc = [[EditPermissionsViewController alloc] initWithNibName:@"EditPermissionsViewController" bundle:nil]; NSString *user; - if (indexPath.row == [permissions count]) { + if (indexPath.row == permissions.count) { user = @""; - vc.newPermissionsEntry = TRUE; - vc.navigationItem.title = @"Add Permissions"; - } - else { - user = [[permissions allKeys] objectAtIndex:indexPath.row]; + vc.removePermissionsEnabled = NO; + vc.navigationItem.title = @"Add Permission"; + } else { + user = [[[permissions allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] objectAtIndex:indexPath.row]; NSString *userPermissions = [permissions objectForKey:user]; - if ([userPermissions rangeOfString:@"read"].location != NSNotFound) + if ([userPermissions rangeOfString:@"read"].location != NSNotFound) { vc.readPermissionSelected = YES; - else + } else { vc.readPermissionSelected = NO; - - if ([userPermissions rangeOfString:@"write"].location != NSNotFound) + } + if ([userPermissions rangeOfString:@"write"].location != NSNotFound) { vc.writePermissionSelected = YES; - else + } else { vc.writePermissionSelected = NO; - - vc.newPermissionsEntry = FALSE; - vc.navigationItem.title = @"Edit Permissions"; + } + vc.removePermissionsEnabled = YES; + vc.navigationItem.title = @"Edit Permission"; } - vc.user = user; + vc.permissionUser = user; vc.permissions = permissions; vc.account = account; vc.container = container; vc.object = object; + vc.folderViewController = folderViewController; [self.navigationController pushViewController:vc animated:YES]; [vc release]; - } else if (indexPath.section == cdnURLSection) { - [cdnURLActionSheet showInView:self.view]; - } else if (indexPath.section == actionsSection) { + } else if (indexPath.section == kActions) { if (indexPath.row == 0) { if (fileDownloaded) { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *shortPath = [NSString stringWithFormat:@"/%@/%@", self.container.name, self.object.fullPath]; - NSString *filePath = [documentsDirectory stringByAppendingString:shortPath]; - - UIDocumentInteractionController *vc = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:filePath]]; - vc.delegate = self; - - if (![vc presentPreviewAnimated:YES]) { - - if ([self.object isPlayableMedia]) { - MediaViewController *vc = [[MediaViewController alloc] initWithNibName:@"MediaViewController" bundle:nil]; - vc.container = self.container; - vc.object = self.object; - [self.navigationController pushViewController:vc animated:YES]; - [vc release]; - } else { - [self alert:@"Error" message:@"This file could not be opened."]; - [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; - } - } - - [self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:actionsSection] animated:YES]; - - } else { - if (!fileDownloading) { - // download the file - fileDownloading = YES; - [self.account.manager getObject:self.container object:self.object downloadProgressDelegate:self]; - [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:actionsSection]] withRowAnimation:UITableViewRowAnimationNone]; - } - + [self openFile]; + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; + } else if (!fileDownloading) { + [self downloadFileForAction:StorageObjectActionOpenFile]; + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; } } else if (indexPath.row == 1) { - - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *shortPath = @""; - - if (self.container && [self.container respondsToSelector:@selector(name)] && self.object && [self.object respondsToSelector:@selector(fullPath)]) { - shortPath = [NSString stringWithFormat:@"/%@/%@", self.container.name, self.object.fullPath]; + if (fileDownloaded) { + [self mailFile]; + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; + } else if (!fileDownloading) { + [self downloadFileForAction:StorageObjectActionMailFile]; + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; + } + } else if ((indexPath.row == 2) && fileDownloaded) { + OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; + BOOL removed = [app removeCacheObjectForHash:object.hash]; + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; + if (removed) { + fileDownloaded = NO; + fileDownloading = NO; + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:kActions] withRowAnimation:UITableViewRowAnimationNone]; + } + } else if ((indexPath.row == 3) && fileDownloading) { + OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; + OpenStackRequest *request = [app objectDownloadRequestForAccount:account container:container object:object]; + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; + if (request) { + request.downloadProgressDelegate = nil; + [request cancel]; + fileDownloaded = NO; + fileDownloading = NO; + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:kActions] withRowAnimation:UITableViewRowAnimationNone]; } - - NSString *filePath = [documentsDirectory stringByAppendingString:shortPath]; - NSData *data = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:filePath]]; - - MFMailComposeViewController *vc = [[MFMailComposeViewController alloc] init]; - vc.mailComposeDelegate = self; - [vc setSubject:self.object.name]; - [vc addAttachmentData:data mimeType:self.object.contentType fileName:self.object.name]; - [vc setMessageBody:@"" isHTML:NO]; - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - vc.modalPresentationStyle = UIModalPresentationPageSheet; - } - [self presentModalViewController:vc animated:YES]; - [vc release]; } } else if (indexPath.section == deleteSection) { + UIActionSheet *deleteActionSheet = [[[UIActionSheet alloc] initWithTitle:@"Are you sure you want to delete this file? This operation cannot be undone." + delegate:self + cancelButtonTitle:@"Cancel" + destructiveButtonTitle:@"Delete File" + otherButtonTitles:nil] autorelease]; [deleteActionSheet showInView:self.view]; + } else if (indexPath.section == versionsSection) { + ObjectVersionsViewController *vc = [[ObjectVersionsViewController alloc] initWithNibName:@"ObjectVersionsViewController" bundle:nil]; + vc.account = account; + vc.container = container; + vc.object = object; + [self.navigationController pushViewController:vc animated:YES]; + [vc release]; } } @@ -506,213 +770,48 @@ if (newProgress >= 1.0) { fileDownloading = NO; fileDownloaded = YES; - - [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:1 inSection:actionsSection]] withRowAnimation:UITableViewRowAnimationBottom]; - [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:actionsSection]] withRowAnimation:UITableViewRowAnimationNone]; + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:kActions] withRowAnimation:UITableViewRowAnimationNone]; } } -#pragma mark - -#pragma mark Document Interation Controller Delegate +#pragma mark - UIDocumentInteractionControllerDelegate - (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *) controller { return self.navigationController; } -- (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controllers { - [self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:actionsSection] animated:YES]; -} - -#pragma mark - -#pragma mark Action Sheet Delegate - -- (void)deleteObjectRow { - [self.folderViewController.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:selectedIndexPath] withRowAnimation:UITableViewRowAnimationLeft]; -} +#pragma mark - UIActionSheetDelegate - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { - if ([actionSheet isEqual:deleteActionSheet]) { - if (buttonIndex == 0) { - // delete the file and pop out - [self showToolbarActivityMessage:@"Deleting file..."]; - - [self.account.manager deleteObject:self.container object:self.object]; - - deleteSuccessObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"deleteObjectSucceeded" object:self.object - queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification) - { - [self hideToolbarActivityMessage]; - performingAction = NO; - [self.folder.objects removeObjectForKey:self.object.name]; - [self.navigationController popViewControllerAnimated:YES]; - if ([self.folder.objects count] + [self.folder.folders count] == 0) { - [self.folderViewController.tableView reloadData]; - } else { - [self.folderViewController.tableView selectRowAtIndexPath:selectedIndexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; - [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(deleteObjectRow) userInfo:nil repeats:NO]; - } - [[NSNotificationCenter defaultCenter] removeObserver:deleteSuccessObserver]; - }]; - - deleteFailureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"deleteObjectFailed" object:self.object - queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification) - { - [self hideToolbarActivityMessage]; - performingAction = NO; - [self alert:@"There was a problem deleting this file." request:[notification.userInfo objectForKey:@"request"]]; - - [[NSNotificationCenter defaultCenter] removeObserver:deleteFailureObserver]; - - }]; - - } - NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:deleteSection]; - [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; - } else if ([actionSheet isEqual:cdnURLActionSheet]) { - NSURL *url = [NSURL URLWithString:[[NSString stringWithFormat:@"%@/%@", self.container.cdnURL, self.object.fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; - - if (buttonIndex == 0) { - // copy to pasteboard - UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; - [pasteboard setString:[url description]]; - } else if (buttonIndex == 1) { - // open in safari - UIApplication *application = [UIApplication sharedApplication]; - if ([application canOpenURL:url]) { - [application openURL:url]; - } else { - [self alert:@"Error" message:[NSString stringWithFormat:@"This URL cannot be opened.\n%@", url]]; - } - } else if (buttonIndex == 2) { - // email link to file - MFMailComposeViewController *vc = [[MFMailComposeViewController alloc] init]; - vc.mailComposeDelegate = self; - [vc setSubject:self.object.name]; - [vc setMessageBody:[url description] isHTML:NO]; - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - vc.modalPresentationStyle = UIModalPresentationPageSheet; - } - [self presentModalViewController:vc animated:YES]; - [vc release]; - } else if (buttonIndex == 3) { - // tweet link to file - UIApplication *app = [UIApplication sharedApplication]; - NSURL *twitterURL = [NSURL URLWithString:[NSString stringWithFormat:@"twitter://post?message=%@", [[url description] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]; - if ([app canOpenURL:twitterURL]) { - [app openURL:twitterURL]; - } - } - [self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:cdnURLSection] animated:YES]; + if (buttonIndex == 0) { + // delete the file and pop out + __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Deleting file..." + andAddToView:self.view]; + [[self.account.manager deleteObject:self.container object:self.object] + success:^(OpenStackRequest *request) { + [activityIndicatorView stopAnimatingAndRemoveFromSuperview]; + [self delete]; + } + failure:^(OpenStackRequest *request) { + [activityIndicatorView stopAnimatingAndRemoveFromSuperview]; + // 404 Not Found means it's not there, so we can show the user that it's deleted + if (request.responseStatusCode == 404) { + [self delete]; + } else { + [self alert:@"There was a problem deleting this file." request:request]; + } + }]; } + NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:deleteSection]; + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; } -#pragma mark - -#pragma mark Mail Composer Delegate +#pragma mark - MFMailComposeViewControllerDelegate // Dismisses the email composition interface when users tap Cancel or Send. -- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error { +- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error { [self dismissModalViewControllerAnimated:YES]; - [self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:actionsSection] animated:YES]; -} - -#pragma mark - -#pragma mark Switches - -- (void)objectIsPublicSwitchChanged:(id)sender -{ - NSString *activityMessage = [NSString stringWithFormat:@"Enabling public link.."]; - self.oldPubicURI = object.publicURI; - - if (objectIsPublic) { - activityMessage = [NSString stringWithFormat:@"Disabling public link.."]; - object.publicURI = @""; - } - else { - object.publicURI = @"TRUE"; - } - - activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage]; - [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y]; - - objectIsPublic = !objectIsPublic; - [self.account.manager writeObjectMetadata:container object:object]; - if (objectIsPublic) { - getObjectInfoSuccessObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"getObjectInfoSucceeded" - object:object - queue:[NSOperationQueue mainQueue] - usingBlock:^(NSNotification *notification) - { - [activityIndicatorView removeFromSuperviewAndRelease]; - OpenStackRequest *request = [notification.userInfo objectForKey:@"request"]; - object.publicURI = [request.responseHeaders objectForKey:@"X-Object-Public"]; - NSIndexPath *publicURICellIndexPath = [NSIndexPath indexPathForRow:1 inSection:kPublic]; - [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:publicURICellIndexPath] - withRowAnimation:UITableViewRowAnimationBottom]; - - [[NSNotificationCenter defaultCenter] removeObserver:getObjectInfoSuccessObserver]; - }]; - - getObjectInfoFailureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"getObjectInfoFailed" - object:object - queue:[NSOperationQueue mainQueue] - usingBlock:^(NSNotification *notification) - { - [activityIndicatorView removeFromSuperviewAndRelease]; - [self alert:@"There was a problem retrieving the public link from the server." request:[notification.userInfo objectForKey:@"request"]]; - [[NSNotificationCenter defaultCenter] removeObserver:getObjectInfoFailureObserver]; - }]; - } - enablePublicSuccessObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataSucceeded" - object:object - queue:[NSOperationQueue mainQueue] - usingBlock:^(NSNotification* notification) - { - NSIndexPath *publicURICellIndexPath = [NSIndexPath indexPathForRow:1 inSection:kPublic]; - if (objectIsPublic) { - [self.account.manager getObjectInfo:container object:object]; - } - else { - [activityIndicatorView removeFromSuperviewAndRelease]; - [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:publicURICellIndexPath] - withRowAnimation:UITableViewRowAnimationTop]; - } - - [[NSNotificationCenter defaultCenter] removeObserver:enablePublicSuccessObserver]; - }]; - - enablePublicFailureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataFailed" - object:object - queue:[NSOperationQueue mainQueue] - usingBlock:^(NSNotification* notification) - { - [activityIndicatorView removeFromSuperviewAndRelease]; - objectIsPublic = !objectIsPublic; - objectIsPublicSwitch.on = !objectIsPublicSwitch.on; - object.publicURI = oldPubicURI; - [self alert:@"There was a problem enabling the public link." request:[notification.userInfo objectForKey:@"request"]]; - [[NSNotificationCenter defaultCenter] removeObserver:enablePublicFailureObserver]; - }]; - - } - - -#pragma mark - -#pragma mark Memory management - -- (void)dealloc { - [account release]; - [downloadProgressView release]; - [deleteActionSheet release]; - [cdnURLActionSheet release]; - [tableView release]; - [folderViewController release]; - [objectIsPublicSwitch release]; - [permissions release]; - [super dealloc]; -} - - @end