@implementation FolderViewController
@synthesize account, container, folder, name, containersViewController, selectedContainerIndexPath, contentsLoaded, parentFolderViewController, selectedFolderIndexPath, tableView, needsRefreshing, folderHasBeenRemoved, refreshWhenAppeared, folderDetailVC, selectedObjectViewController, refreshButton;
-@synthesize searchBar, searchFilter;
+@synthesize searchBar, searchDisplayController, searchFilter;
#pragma mark - View lifecycle
[super viewDidLoad];
[self addAddButton];
[self addHomeButton];
+
+ searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
+ searchDisplayController.delegate = self;
+ searchDisplayController.searchResultsDataSource = self;
+ searchDisplayController.searchResultsDelegate = self;
}
- (void)viewWillAppear:(BOOL)animated {
[selectedFolderIndexPath release];
[refreshButton release];
[searchBar release];
+ [searchDisplayController release];
[searchFilter release];
[super dealloc];
}
#pragma mark - Internal
- (void)showSearchBar:(BOOL)show {
- if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
- if (show && self.searchBar.hidden) {
- // Add search bar above the tableview
- CGRect tableViewFrame = self.tableView.frame;
- tableViewFrame.origin.y += 44.0;
- tableViewFrame.size.height -= 44.0;
- self.tableView.frame = tableViewFrame;
- self.searchBar.hidden = NO;
- [self.view addSubview:self.searchBar];
- } else if (!show && !self.searchBar.hidden) {
- // Remove search bar above the tableview
- CGRect tableViewFrame = self.tableView.frame;
- tableViewFrame.origin.y -= 44.0;
- tableViewFrame.size.height += 44.0;
- self.tableView.frame = tableViewFrame;
- [self.searchBar removeFromSuperview];
- self.searchBar.hidden = YES;
- }
- } else {
- if (show && ![self.tableView.tableHeaderView isEqual:self.searchBar]) {
- self.searchBar.hidden = NO;
- self.tableView.tableHeaderView = self.searchBar;
+ if (show && ![self.tableView.tableHeaderView isEqual:self.searchBar]) {
+ self.searchBar.hidden = NO;
+ self.tableView.tableHeaderView = self.searchBar;
+ if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
self.tableView.contentOffset = CGPointMake(0.0, 44.0);
- } else if (!show) {
- self.tableView.tableHeaderView = nil;
- self.searchBar.hidden = YES;
}
+ } else if (!show) {
+ self.tableView.tableHeaderView = nil;
+ self.searchBar.hidden = YES;
}
}
int rootFolderControllerIndex = [viewControllers indexOfObject:self.containersViewController] + 1;
FolderViewController *rootFolderViewController = [viewControllers objectAtIndex:rootFolderControllerIndex];
rootFolderViewController.folder = self.container.rootFolder;
- [rootFolderViewController.tableView reloadData];
+ [rootFolderViewController reloadData];
for (int i = rootFolderControllerIndex + 1; i < [viewControllers count]; i++) {
FolderViewController *folderViewController = [viewControllers objectAtIndex:i];
folderViewController.folder = [parentFolder.folders objectForKey:folderViewController.folder.name];
if (folderViewController.folder) {
- [folderViewController.tableView reloadData];
+ [folderViewController reloadData];
} else {
folderViewController.folderHasBeenRemoved = YES;
}
}
- (void)deleteFolderRow {
- [self.parentFolderViewController.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:selectedFolderIndexPath] withRowAnimation:UITableViewRowAnimationLeft];
+ [self.parentFolderViewController.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:selectedFolderIndexPath]
+ withRowAnimation:UITableViewRowAnimationLeft];
+ if (self.parentFolderViewController.searchDisplayController.active &&
+ self.parentFolderViewController.searchFilter && self.parentFolderViewController.searchFilter.length)
+ [self.parentFolderViewController.searchDisplayController.searchResultsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:selectedFolderIndexPath]
+ withRowAnimation:UITableViewRowAnimationLeft];
}
- (void)deleteObjectRow:(NSTimer *)timer {
[self.folder removeObject:[timer.userInfo objectForKey:@"object"]];
- [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[timer.userInfo objectForKey:@"indexPath"]] withRowAnimation:UITableViewRowAnimationLeft];
+ [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[timer.userInfo objectForKey:@"indexPath"]]
+ withRowAnimation:UITableViewRowAnimationLeft];
+ if (self.searchDisplayController.active && self.searchFilter && self.searchFilter.length)
+ [self.searchDisplayController.searchResultsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[timer.userInfo objectForKey:@"indexPath"]]
+ withRowAnimation:UITableViewRowAnimationLeft];
self.refreshButton.enabled = YES;
}
+- (NSArray *)searchResults {
+ return [self.folder sortedContentsWithNameThatStartsWith:self.searchFilter];
+}
+
#pragma mark - Properties
- (UISearchBar *)searchBar {
if (!searchBar) {
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 44.0)];
searchBar.placeholder = @"Search Folder";
- searchBar.barStyle = UIBarStyleBlack;
+ searchBar.barStyle = UIBarStyleBlackOpaque;
searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
+ searchBar.scopeButtonTitles = @[@"name", @"date", @"type", @"all"];
searchBar.hidden = YES;
searchBar.delegate = self;
}
#pragma mark - Actions
+- (void)reloadData {
+ [self.tableView reloadData];
+ if (self.searchDisplayController.active && self.searchFilter && self.searchFilter.length)
+ [self.searchDisplayController.searchResultsTableView reloadData];
+}
+
- (void)setDetailViewController {
self.selectedObjectViewController = nil;
if ([self.folder isEqual:self.container.rootFolder]) {
}
- (void)deleteAnimatedObject:(StorageObject *)object {
- NSIndexPath *deleteIndexPath = [NSIndexPath indexPathForRow:[[self.folder sortedContentsWithNameThatStartsWith:self.searchFilter] indexOfObject:object] inSection:0];
+ NSIndexPath *deleteIndexPath = [NSIndexPath indexPathForRow:[[self searchResults] indexOfObject:object] inSection:0];
[self.tableView selectRowAtIndexPath:deleteIndexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
+ if (self.searchDisplayController.active && self.searchFilter && self.searchFilter.length)
+ [self.searchDisplayController.searchResultsTableView selectRowAtIndexPath:deleteIndexPath
+ animated:YES
+ scrollPosition:UITableViewScrollPositionNone];
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:object, @"object", deleteIndexPath, @"indexPath", nil];
[NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(deleteObjectRow:) userInfo:userInfo repeats:NO];
}
+#pragma mark - UIScrollViewDelegate
+
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
+ if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) && !self.searchBar.hidden && !self.searchDisplayController.active) {
+ CGRect searchBarFrame = self.searchBar.frame;
+ searchBarFrame.origin.y = scrollView.contentOffset.y;
+ searchBar.frame = searchBarFrame;
+ }
+}
+
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
if (self.folder.objectsAndFoldersCount) {
- return [[self.folder sortedContentsWithNameThatStartsWith:self.searchFilter] count];
+ // For the search results tableView this will be returned because search is allowed only when the folder is not empty.
+ return [[self searchResults] count];
} else if (contentsLoaded) {
return 1;
} else {
}
- (CGFloat)tableView:(UITableView *)aTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
- if (!folder.objectsAndFoldersCount) {
- aTableView.scrollEnabled = NO;
- aTableView.allowsSelection = NO;
- return aTableView.frame.size.height;
- } else {
+ if (self.folder.objectsAndFoldersCount) {
+ // For the search results tableView this will be returned because search is allowed only when the folder is not empty.
aTableView.scrollEnabled = YES;
aTableView.allowsSelection = YES;
return aTableView.rowHeight;
+ } else {
+ aTableView.scrollEnabled = NO;
+ aTableView.allowsSelection = NO;
+ return aTableView.frame.size.height;
}
}
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (!self.folder.objectsAndFoldersCount) {
NSString *noFoldersTitle = (self.account.shared || self.account.sharingAccount) ?
- @"No shared Files or Folders" : @"No Files or Folders";
+ @"No shared Files or Folders" : @"No Files or Folders";
NSString *noFoldersSubtitle = (self.account.shared || self.account.sharingAccount || [self.folder.name hasSuffix:@"/"]) ?
- @"" : @"Tap the + button to create a new one";
- NSString *deleteFolderButtonTitle = (self.account.shared || self.account.sharingAccount) ?
- nil : @"Delete Folder";
+ @"" : @"Tap the + button to create a new one";
+ NSString *deleteFolderButtonTitle = (self.account.shared || self.account.sharingAccount) ? nil : @"Delete Folder";
SEL deleteButtonSelector = (self.account.shared || self.account.sharingAccount) ? nil : @selector(deleteButtonPressed:);
self.navigationItem.rightBarButtonItem.enabled = (self.account.shared || [self.folder.name hasSuffix:@"/"]) ? NO : YES;
deleteButtonSelector:deleteButtonSelector];
}
} else {
+ // For the search results tableView this will be returned because search is allowed only when the folder is not empty.
static NSString *CellIdentifier = @"Cell";
-
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
- if (cell == nil) {
+ if (!cell)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
- }
-
- id item = [[self.folder sortedContentsWithNameThatStartsWith:self.searchFilter] objectAtIndex:indexPath.row];
- cell.textLabel.text = [item name];
+ id item = [[self searchResults] objectAtIndex:indexPath.row];
if ([[item class] isEqual:[Folder class]]) {
+ Folder *cellFolder = (Folder *)item;
+ cell.textLabel.text = cellFolder.name;
[cell.textLabel setLineBreakMode:UILineBreakModeTailTruncation];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else {
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
+
cell.imageView.image = [UIImage imageNamed:@"folder-icon.png"];
NSString *folderString = @"";
- NSString *objectString = @"";
- if ([[item folders] count] > 1) {
- folderString = [NSString stringWithFormat:@"%i folders, ", [[item folders] count]];
- } else if ([[item folders] count] > 0) {
+ if (cellFolder.folders.count > 1) {
+ folderString = [NSString stringWithFormat:@"%ul folders, ", cellFolder.folders.count];
+ } else if (cellFolder.folders.count > 0) {
folderString = @"1 folder, ";
}
- if ([[item objects] count] != 1) {
- objectString = [NSString stringWithFormat:@"%i objects", [[item objects] count]];
- } else if ([[item objects] count]) {
+ NSString *objectString = @"";
+ if (cellFolder.objects.count != 1) {
+ objectString = [NSString stringWithFormat:@"%ul objects", cellFolder.objects.count];
+ } else {
objectString = @"1 object";
}
cell.detailTextLabel.text = [NSString stringWithFormat:@"%@%@", folderString, objectString];
} else if ([[item class] isEqual:[StorageObject class]]) {
+ StorageObject *cellObject = (StorageObject *)item;
+ cell.textLabel.text = cellObject.name;
[cell.textLabel setLineBreakMode:UILineBreakModeMiddleTruncation];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
cell.accessoryType = UITableViewCellAccessoryNone;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
- StorageObject *object = item;
- CFStringRef mimeType = (CFStringRef)object.contentType;
+ CFStringRef mimeType = (CFStringRef)cellObject.contentType;
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
NSString *emptyPath = [[NSBundle mainBundle] pathForResource:@"empty-file" ofType:@""];
UIDocumentInteractionController *udic = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:emptyPath]];
if (((NSString *)uti).length > 0)
udic.UTI = (NSString *)uti;
- if ([udic.icons count] > 0)
+ if (udic.icons.count > 0)
cell.imageView.image = [udic.icons objectAtIndex:0];
- if ([item lastModifiedString])
- cell.detailTextLabel.text = [NSString stringWithFormat:@"%@, %@", [item humanizedBytes], [item lastModifiedString]];
- else
- cell.detailTextLabel.text = [item humanizedBytes];
+
+ if (cellObject.lastModifiedString) {
+ cell.detailTextLabel.text = [NSString stringWithFormat:@"%@, %@", cellObject.humanizedBytes, cellObject.lastModifiedString];
+ } else {
+ cell.detailTextLabel.text = cellObject.humanizedBytes;
+ }
}
return cell;
#pragma mark - UITableViewDelegate
-- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (folder.objectsAndFoldersCount) {
- id item = [[self.folder sortedContentsWithNameThatStartsWith:self.searchFilter] objectAtIndex:indexPath.row];
+ id item = [[self searchResults] objectAtIndex:indexPath.row];
if ([[item class] isEqual:[Folder class]]) {
FolderViewController *vc = [[FolderViewController alloc] initWithNibName:@"FolderViewController" bundle:nil];
vc.account = self.account;
[self.navigationController pushViewController:vc animated:YES];
vc.contentsLoaded = YES;
vc.folder = item;
- [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+ [aTableView deselectRowAtIndexPath:indexPath animated:YES];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
self.selectedObjectViewController = nil;
FolderDetailViewController *folderDetailViewController = [[FolderDetailViewController alloc] initWithNibName:@"FolderDetailViewController" bundle:nil];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
self.selectedObjectViewController = vc;
OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
- if (app.rootViewController.popoverController != nil) {
+ if (app.rootViewController.popoverController) {
[app.rootViewController.popoverController dismissPopoverAnimated:YES];
}
} else {
- [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+ [aTableView deselectRowAtIndexPath:indexPath animated:YES];
}
[vc release];
}
}
}
-- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
+- (void)tableView:(UITableView *)aTableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
FolderDetailViewController *vc = [[FolderDetailViewController alloc] initWithNibName:@"FolderDetailViewController" bundle:nil];
vc.account = account;
vc.container = container;
- vc.folder = [[self.folder sortedContentsWithNameThatStartsWith:self.searchFilter] objectAtIndex:indexPath.row];
+ vc.folder = [[self searchResults] objectAtIndex:indexPath.row];
vc.folderViewController = self;
[self.navigationController pushViewController:vc animated:YES];
[vc release];
}
-#pragma mark - UISearchBarDelegate
+#pragma mark - UISearchDisplayDelegate
+
+- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
+ return NO;
+}
-- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
- [self.searchBar setShowsCancelButton:YES animated:YES];
+- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
+ return YES;
+}
+
+- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
+ self.searchFilter = nil;
+ [self reloadData];
}
+#pragma mark - UISearchBarDelegate
+
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
self.searchFilter = searchText;
- [self.tableView reloadData];
+ [self reloadData];
if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) && self.selectedObjectViewController) {
if (self.searchFilter && self.searchFilter.length && ![self.selectedObjectViewController.object.name hasPrefix:self.searchFilter]) {
[self setDetailViewController];
} else {
- NSIndexPath *selectIndexPath = [NSIndexPath indexPathForRow:[[self.folder sortedContentsWithNameThatStartsWith:self.searchFilter] indexOfObject:self.selectedObjectViewController.object] inSection:0];
+ NSIndexPath *selectIndexPath = [NSIndexPath indexPathForRow:[[self searchResults] indexOfObject:self.selectedObjectViewController.object] inSection:0];
[self.tableView selectRowAtIndexPath:selectIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
+ if (self.searchDisplayController.active && self.searchFilter && self.searchFilter.length)
+ [self.searchDisplayController.searchResultsTableView selectRowAtIndexPath:selectIndexPath
+ animated:NO
+ scrollPosition:UITableViewScrollPositionNone];
}
}
}
-- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
- self.searchBar.text = @"";
- self.searchFilter = nil;
- [self.tableView reloadData];
- [self.searchBar resignFirstResponder];
- [self.searchBar setShowsCancelButton:NO animated:YES];
-}
-
-- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
- [self.searchBar resignFirstResponder];
- // The following code might not work in iOS > 5.0
- // and there might be problems with apple since it uses internal variables.
-// for(id subview in [self.searchBar subviews]) {
-// if ([subview isKindOfClass:[UIButton class]]) {
-// [subview setEnabled:YES];
-// }
-// }
-}
-
#pragma mark - Button Handlers
- (IBAction)homeButtonPressed:(id)sender {
usingBlock:^(NSNotification* notification)
{
needsRefreshing = NO;
- [self.tableView reloadData];
+ [self reloadData];
[activityIndicatorView removeFromSuperviewAndRelease];
[self alert:@"Error" message:@"Failed to retrieve files from server"];
[[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
NSString *activityMessage = @"Deleting folder...";
activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
- [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y];
+ [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y];
[[self.account.manager deleteObject:self.container object:object]
success:^(OpenStackRequest *request) {
[activityIndicatorView removeFromSuperviewAndRelease];
[self.navigationController popViewControllerAnimated:YES];
- if (self.folder.parent) {
- if (!self.folder.parent.objectsAndFoldersCount) {
- [self.parentFolderViewController.tableView reloadData];
- self.parentFolderViewController.folder = self.parentFolderViewController.folder;
- } else {
- [self.parentFolderViewController.tableView selectRowAtIndexPath:selectedFolderIndexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
- [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(deleteFolderRow) userInfo:nil repeats:NO];
- }
- if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
- [self.parentFolderViewController setDetailViewController];
- } else {
- if (!self.container.rootFolder.objectsAndFoldersCount) {
- [self.parentFolderViewController.tableView reloadData];
- self.parentFolderViewController.folder = self.parentFolderViewController.folder;
- } else {
- [self.parentFolderViewController.tableView selectRowAtIndexPath:selectedFolderIndexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
- [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(deleteFolderRow) userInfo:nil repeats:NO];
- }
+ if ((self.folder.parent && !self.folder.parent.objectsAndFoldersCount) ||
+ (!self.folder.parent && !self.container.rootFolder.objectsAndFoldersCount)) {
+ [self.parentFolderViewController reloadData];
+ self.parentFolderViewController.folder = self.parentFolderViewController.folder;
+ } else if ((self.folder.parent && self.folder.parent.objectsAndFoldersCount) ||
+ (!self.folder.parent && self.container.rootFolder.objectsAndFoldersCount)) {
+ [self.parentFolderViewController.tableView selectRowAtIndexPath:selectedFolderIndexPath
+ animated:YES
+ scrollPosition:UITableViewScrollPositionNone];
+ if (self.parentFolderViewController.searchDisplayController.active &&
+ self.parentFolderViewController.searchFilter && self.parentFolderViewController.searchFilter.length)
+ [self.parentFolderViewController.searchDisplayController.searchResultsTableView selectRowAtIndexPath:selectedFolderIndexPath
+ animated:YES
+ scrollPosition:UITableViewScrollPositionNone];
+ [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(deleteFolderRow) userInfo:nil repeats:NO];
}
+ if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) && self.folder.parent)
+ [self.parentFolderViewController setDetailViewController];
[object release];
}
failure:^(OpenStackRequest *request) {
}
@end
-