#import "TextViewCell.h"
#import "NSString+Conveniences.h"
#import "APICallback.h"
+#import "ObjectVersionsViewController.h"
+#import <MediaPlayer/MPMoviePlayerController.h>
+#import <MessageUI/MessageUI.h>
+#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)
-
- CDN URL sections (action sheet to copy, open in safari, and email link)
+Name whatever.txt
+Full Path folder/whatever.txt
+Size 123 KB
+Type text/plain
+Last Modified 2012-12-21 11:11:00
+
+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."
+
+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
- 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."
+Versions
- Delete Object
- */
+Delete Object
+*/
@implementation StorageObjectViewController
-@synthesize account, container, folder, object, tableView, folderViewController;
-@synthesize oldPubicURI, documentInteractionController;
+@synthesize account, container, folder, object, folderViewController;
+@synthesize oldPubicURI, documentInteractionController, actionSelectedIndexPath, 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];
if (object.sharing.length > 0) {
NSArray *sharingArray = [object.sharing componentsSeparatedByString:@";"];
}
objectIsPublicSwitch.enabled = NO;
}
+
+ downloadProgressView = [[AnimatedProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
+ fileDownloading = ([self.account.manager.objectDownloadRequests objectForKey:object.fullPath] != nil) ? YES : NO;
+ if (fileDownloading) {
+ OpenStackRequest *request = [self.account.manager.objectDownloadRequests objectForKey:object.fullPath];
+ self.actionSelectedIndexPath = [request.userInfo objectForKey:@"actionSelectedIndexPath"];
+ [request setDownloadProgressDelegate:self];
+ }
}
- (void)viewWillAppear:(BOOL)animated {
NSIndexPath *selection = [self.tableView indexPathForSelectedRow];
if (selection)
[self.tableView deselectRowAtIndexPath:selection animated:YES];
+ OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
+ if ([app.cachedObjectsDictionary objectForKey:object.hash] != nil) {
+ if ([[NSFileManager defaultManager] fileExistsAtPath:[app.cachedObjectsDictionary objectForKey:object.hash]]) {
+ fileDownloaded = YES;
+ } else {
+ fileDownloaded = NO;
+ [app.cachedObjectsDictionary removeObjectForKey:object.hash];
+ [app saveCacheDictionary];
+ }
+ } else {
+ fileDownloaded = NO;
+ }
- 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];
-
- 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"];
-
- 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];
- } 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];
- }
objectIsPublic = ([object.publicURI length]);
objectIsPublicSwitch.on = objectIsPublic;
[self.tableView reloadData];
}
-#pragma mark -
-#pragma mark Table view data source
+- (void)viewDidAppear:(BOOL)animated {
+ if (object.metadata == nil) {
+ [self reloadMetadataSection];
+ }
+}
+
+#pragma mark - Memory management
+
+- (void)dealloc {
+ if (fileDownloading) {
+ OpenStackRequest *request = [self.account.manager.objectDownloadRequests objectForKey:object.fullPath];
+ [request setDownloadProgressDelegate:nil];
+ }
+ [account release];
+ [downloadProgressView release];
+ [cdnURLActionSheet release];
+ [folderViewController release];
+ [objectIsPublicSwitch release];
+ [permissions release];
+ [documentInteractionController release];
+ [actionSelectedIndexPath release];
+ [versionID release];
+ [super dealloc];
+}
+
+#pragma mark - Internal
+
+- (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";
+ }
+ __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 removeFromSuperview];
+ 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 removeFromSuperview];
+ [self alert:@"There was a problem retrieving the public link from the server." request:request];
+ }];
+ } else {
+ [activityIndicatorView removeFromSuperview];
+ [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:publicURICellIndexPath]
+ withRowAnimation:UITableViewRowAnimationTop];
+ }
+ }
+ failure:^(OpenStackRequest *request) {
+ [activityIndicatorView removeFromSuperview];
+ objectIsPublic = !objectIsPublic;
+ objectIsPublicSwitch.on = !objectIsPublicSwitch.on;
+ object.publicURI = oldPubicURI;
+ [self alert:@"There was a problem enabling the public link." request:request];
+ }];
+}
+
+#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 removeFromSuperview];
+ 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];
+ }
+ }
+ NSIndexSet *metadataSections = [NSIndexSet indexSetWithIndex:kMetadata];
+ [self.tableView reloadSections:metadataSections withRowAnimation:UITableViewRowAnimationFade];
+ }
+ failure:^(OpenStackRequest *request) {
+ [activityIndicatorView removeFromSuperview];
+ [self alert:@"There was a problem retrieving the object's metadata." request:request];
+ }];
+}
+
+#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
- if (account.sharingAccount || account.shared)
- return self.container.cdnEnabled ? 6 : 5;
- else
- 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) {
+ return 2;
} else if (section == kMetadata) {
- if (objectIsReadOnly)
+ if (objectIsReadOnly) {
return [object.metadata count];
- else
+ } else {
return 1 + [object.metadata count];
- } else if (section == cdnURLSection) {
- return 1;
- } else if (section == actionsSection) {
- return fileDownloaded ? 2 : 1;
- } else if (section == kPublic) {
+ }
+ } else if (section == publicLinkSection) {
return objectIsPublic ? 2 : 1;
- } else if (section == kPermissions) {
- if (account.sharingAccount)
+ } else if (section == permissionsSection) {
+ if (account.sharingAccount || objectIsReadOnly) {
return [permissions count];
- else
+ } else {
return 1 + [permissions count];
+ }
} 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);
- } else {
- textLabelSize = CGSizeMake(221.0, 9000.0f);
+ if ((indexPath.section == kDetails) && ((indexPath.row == 0) || (indexPath.row == 1))) {
+ NSString *text;
+ if (indexPath.row == 0) {
+ text = object.name;
+ } else if (indexPath.row == 1) {
+ 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) {
- NSString *publicLinkUrl = [NSString stringWithFormat:@"%@%@",
- account.pithosPublicLinkURLPrefix,
- self.object.publicURI];
-
- result = 30.0 + [self findLabelHeight:publicLinkUrl font:[UIFont systemFontOfSize:15.0]];
+ 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.pithosPublicLinkURLPrefix 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 {
-
- static NSString *CellIdentifier = @"Cell";
- static NSString *TextViewCellIdentifier = @"TextViewCell";
-
- if (indexPath.section == kPublic) {
- if (indexPath.row == 1) {
- TextViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:TextViewCellIdentifier];
- if (cell == nil) {
- cell = [[[TextViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TextViewCellIdentifier] autorelease];
- cell.textView.frame = cell.contentView.frame;
+ 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 = [NSString stringWithFormat:@"%@%@",
- account.pithosPublicLinkURLPrefix,
- [NSString encodeToPercentEscape:self.object.publicURI charactersToEncode:@"!*'();:@&=+$,?%#[]"]];
-
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
- cell.accessoryView = UITableViewCellAccessoryNone;
- return cell;
}
+ cell.selectionStyle = UITableViewCellSelectionStyleNone;
+ cell.textView.backgroundColor = [UIColor clearColor];
+ cell.textView.font = [UIFont systemFontOfSize:15.0];
+ cell.textView.dataDetectorTypes = UIDataDetectorTypeLink;
+ cell.textView.text = [[account.pithosPublicLinkURLPrefix URLByAppendingPathComponent:
+ [NSString encodeToPercentEscape:[self.object.publicURI substringFromIndex:1]
+ charactersToEncode:@"!*'();:@&=+$,?%#[]"]] description];
+ cell.selectionStyle = UITableViewCellSelectionStyleNone;
+ cell.accessoryView = UITableViewCellAccessoryNone;
+ return 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.textLabel.backgroundColor = [UIColor clearColor];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
- cell.detailTextLabel.numberOfLines = 0;
cell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
}
-
- if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
+ cell.textLabel.textColor = [UIColor blackColor];
+ cell.detailTextLabel.numberOfLines = 0;
+ if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
cell.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.8];
}
cell.userInteractionEnabled = YES;
} 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) {
if (objectIsReadOnly) {
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 = @"";
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
- } else if (indexPath.section == kPermissions) {
+ } else if (indexPath.section == permissionsSection) {
if (account.sharingAccount) {
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.accessoryView = nil;
if (indexPath.row == [permissions count]) {
- cell.textLabel.text = @"Add Permissions";
+ cell.textLabel.text = @"Share";
cell.detailTextLabel.text = @"";
- }
- else {
+ } else {
NSString *user = [[permissions allKeys] objectAtIndex:indexPath.row];
cell.textLabel.text = user;
- cell.detailTextLabel.text = [permissions objectForKey:user];
+ NSString *accessType;
+ if ([[permissions objectForKey:user] isEqualToString:@"write"])
+ accessType = @"Read/Write";
+ else
+ accessType = @"Read Only";
+ cell.detailTextLabel.numberOfLines = 1;
+ cell.detailTextLabel.lineBreakMode = UILineBreakModeTailTruncation;
+ cell.detailTextLabel.text = accessType;
}
- } 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 if (indexPath.section == kActions) {
+ if (fileDownloading) {
+ if (actionSelectedIndexPath.row == indexPath.row) {
+ cell.accessoryView = downloadProgressView;
+ } else {
+ cell.textLabel.textColor = [UIColor grayColor];
+ cell.selectionStyle = UITableViewCellSelectionStyleNone;
+ }
} else {
- cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
+ cell.selectionStyle = UITableViewCellSelectionStyleBlue;
+ cell.accessoryView = nil;
}
-
if (indexPath.row == 0) {
- if (fileDownloaded) {
- cell.textLabel.text = @"Open File";
- cell.accessoryType = UITableViewCellAccessoryNone;
- cell.selectionStyle = UITableViewCellSelectionStyleBlue;
- } 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.textLabel.text = @"Open File";
+ cell.accessoryType = UITableViewCellAccessoryNone;
cell.detailTextLabel.text = @"";
} else if (indexPath.row == 1) {
cell.textLabel.text = @"Email File as Attachment";
cell.detailTextLabel.text = @"";
- cell.selectionStyle = UITableViewCellSelectionStyleBlue;
+ cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
- } else if (indexPath.section == deleteSection) {
+ } else if (indexPath.section == versionsSection) {
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
- cell.textLabel.text = @"Delete Object";
+ 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) {
metadataValue = @"";
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.removeMetadataEnabled = YES;
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]) {
user = @"";
vc.removePermissionsEnabled = NO;
- vc.navigationItem.title = @"Add Permissions";
- }
- else {
+ vc.navigationItem.title = @"Share";
+ } else {
user = [[permissions allKeys] objectAtIndex:indexPath.row];
NSString *userPermissions = [permissions objectForKey:user];
if ([userPermissions rangeOfString:@"read"].location != NSNotFound)
vc.writePermissionSelected = NO;
vc.removePermissionsEnabled = YES;
- vc.navigationItem.title = @"Edit Permissions";
+ vc.navigationItem.title = @"Edit Sharing";
}
vc.user = user;
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) {
- if (indexPath.row == 0) {
+ } else if (indexPath.section == kActions) {
+ if (!fileDownloaded) {
+ if (!fileDownloading) {
+ // download the file
+ fileDownloading = YES;
+ self.actionSelectedIndexPath = indexPath;
+ [self.tableView reloadData];
+ NSMutableDictionary *requestUserInfo = [NSDictionary dictionaryWithObject:indexPath forKey:@"actionSelectedIndexPath"];
+ [[self.account.manager getObject:self.container object:self.object downloadProgressDelegate:self requestUserInfo:requestUserInfo version:versionID]
+ success:^(OpenStackRequest *request) {
+ fileDownloaded = YES;
+ fileDownloading = NO;
+ if ([self.navigationController.visibleViewController isEqual:self])
+ [self.tableView.delegate tableView:self.tableView didSelectRowAtIndexPath:indexPath];
+ [self.tableView reloadData];
+ [self.folderViewController reloadData];
+ }
+ failure:^(OpenStackRequest *request) {
+ fileDownloaded = NO;
+ fileDownloading = NO;
+ [self alert:@"File failed to download." request:request];
+ [self.tableView reloadData];
+ }];
+ [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:indexPath.row inSection:kActions]] withRowAnimation:UITableViewRowAnimationNone];
+ }
+ } else 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];
-
+ OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
+ NSString *filePath = [app.cachedObjectsDictionary objectForKey:object.hash];
self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:filePath]];
self.documentInteractionController.delegate = self;
+ self.documentInteractionController.name = object.name;
UITableViewCell *openFileCell = [self.tableView cellForRowAtIndexPath:indexPath];
- if (![self.documentInteractionController presentOptionsMenuFromRect:openFileCell.frame inView:self.view animated:YES]) {
+ CGRect 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;
}
}
- [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.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kActions] animated:YES];
- }
+ }
} else if (indexPath.row == 1) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if (![MFMailComposeViewController canSendMail]) {
[self alert:@"Cannot send mail" message:@"Your device has not been configured for sending email"];
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
- }
- else {
+ } else {
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) {
+ if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
vc.modalPresentationStyle = UIModalPresentationPageSheet;
}
[self presentModalViewController:vc animated:YES];
}
}
} 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];
}
}
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 reloadData];
}
}
-
-#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
-
- NSString *activityMessage = @"Deleting file";
-
- activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
- [activityIndicatorView addToView:self.view];
-
-
- [[self.account.manager deleteObject:self.container object:self.object]
- success:^(OpenStackRequest *request) {
- [activityIndicatorView removeFromSuperviewAndRelease];
- performingAction = NO;
- [self.folder.objects removeObjectForKey:self.object.name];
-
- if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
- [self.navigationController popViewControllerAnimated:YES];
- if (account.shared)
- self.folderViewController.needsRefreshing = YES;
- } else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
- if (!account.shared)
- [self.folderViewController setDetailViewController];
- else
- if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
- [self.folderViewController refreshButtonPressed:nil];
- }
-
- 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];
- }
+ if (buttonIndex == 0) {
+ // delete the file and pop out
+ self.folderViewController.refreshButton.enabled = NO;
+ __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Deleting file..."
+ andAddToView:self.view];
+ [[self.account.manager deleteObject:self.container object:self.object]
+ success:^(OpenStackRequest *request) {
+ [activityIndicatorView removeFromSuperview];
+ if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) {
+ [self.navigationController popViewControllerAnimated:YES];
+ if (account.shared)
+ self.folderViewController.needsRefreshing = YES;
+ } else if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
+ self.folderViewController.selectedObjectViewController = nil;
+ if (!account.shared)
+ [self.folderViewController setDetailViewController];
+ else
+ [self.folderViewController refreshButtonPressed:nil];
+// self.folderViewController.refreshButton.enabled = YES;
}
- failure:^(OpenStackRequest *request) {
- [activityIndicatorView removeFromSuperviewAndRelease];
- [self hideToolbarActivityMessage];
- performingAction = NO;
- [self alert:@"There was a problem deleting this file." request:request];
- }];
- }
- 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 (self.folder.objectsAndFoldersCount == 1) {
+ [self.folder removeObject:self.object];
+ self.folderViewController.folder = self.folderViewController.folder;
+ } else {
+ [self.folderViewController deleteAnimatedObject:self.object];
+ }
+ self.folderViewController.refreshButton.enabled = YES;
+ }
+ failure:^(OpenStackRequest *request) {
+ [activityIndicatorView removeFromSuperview];
+ [self alert:@"There was a problem deleting this file." request:request];
+ self.folderViewController.refreshButton.enabled = YES;
+ }];
}
+ 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 {
[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]
- success:^(OpenStackRequest *request) {
- NSIndexPath *publicURICellIndexPath = [NSIndexPath indexPathForRow:1 inSection:kPublic];
- if (objectIsPublic) {
- [[self.account.manager getObjectInfo:container object:object]
- success:^(OpenStackRequest *request) {
- [activityIndicatorView removeFromSuperviewAndRelease];
- object.publicURI = [request.responseHeaders objectForKey:@"X-Object-Public"];
- NSIndexPath *publicURICellIndexPath = [NSIndexPath indexPathForRow:1 inSection:kPublic];
- [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:publicURICellIndexPath]
- withRowAnimation:UITableViewRowAnimationBottom];
- }
- failure:^(OpenStackRequest *request) {
- [activityIndicatorView removeFromSuperviewAndRelease];
- [self alert:@"There was a problem retrieving the public link from the server." request:request];
- }];
- }
- else {
- [activityIndicatorView removeFromSuperviewAndRelease];
- [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:publicURICellIndexPath]
- withRowAnimation:UITableViewRowAnimationTop];
- }
- }
- failure:^(OpenStackRequest *request) {
- [activityIndicatorView removeFromSuperviewAndRelease];
- objectIsPublic = !objectIsPublic;
- objectIsPublicSwitch.on = !objectIsPublicSwitch.on;
- object.publicURI = oldPubicURI;
- [self alert:@"There was a problem enabling the public link." request:request];
-
- }];
+ [self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:kActions] animated:YES];
}
-
-
-#pragma mark -
-#pragma mark Memory management
-
-- (void)dealloc {
- [account release];
- [downloadProgressView release];
- [deleteActionSheet release];
- [cdnURLActionSheet release];
- [tableView release];
- [folderViewController release];
- [objectIsPublicSwitch release];
- [permissions release];
- [documentInteractionController release];
-
- [super dealloc];
-}
-
-
@end