Show activity indicator views when creating or refreshing containers
authorMiltiadis Vasilakis <mvasilak@gmail.com>
Thu, 6 Dec 2012 19:44:32 +0000 (21:44 +0200)
committerMiltiadis Vasilakis <mvasilak@gmail.com>
Thu, 6 Dec 2012 19:44:32 +0000 (21:44 +0200)
Show activity indicator view, in the view responsible for the container creation or refresh, instead of a toolbar activity message always in the containers view controller.

Classes/AddContainerViewController.h
Classes/AddContainerViewController.m
Classes/AddFolderViewController.h
Classes/AddFolderViewController.m
Classes/ContainersViewController.h
Classes/ContainersViewController.m

index e71182a..a1b2089 100755 (executable)
@@ -6,12 +6,10 @@
 //  The OpenStack project is provided under the Apache 2.0 license.
 //
 
-#import <UIKit/UIKit.h>
-
 @class ContainersViewController, OpenStackAccount;
 
 @interface AddContainerViewController : UITableViewController <UITextFieldDelegate> {
-    UITextField *nameTextField;
+    UITextField *textField;
     ContainersViewController *containersViewController;
     OpenStackAccount *account;
 }
index 8f66d2d..d462c06 100755 (executable)
 #import "AccountManager.h"
 #import "RSTextFieldCell.h"
 #import "APICallback.h"
-
+#import "ActivityIndicatorView.h"
 
 @implementation AddContainerViewController
 
 @synthesize containersViewController, account;
 
+#pragma mark - View lifecycle
+
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
     return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
 }
 
-#pragma mark -
-#pragma mark View lifecycle
-
 - (void)viewDidLoad {
     [super viewDidLoad];
     self.navigationItem.title = @"Add Container";
     [self addSaveButton];
 }
 
-#pragma mark -
-#pragma mark Table view data source
+- (void)viewDidAppear:(BOOL)animated {
+    [super viewDidAppear:animated];
+    [textField becomeFirstResponder];
+}
+
+#pragma mark - Memory management
 
-- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
-    return 1;
+- (void)dealloc {
+    [containersViewController release];
+    [account release];
+    [super dealloc];
 }
 
+#pragma mark - UITableViewDataSource
+
 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
     return 1;
 }
 }
 
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
-    
-    static NSString *CellIdentifier = @"Cell";
-    
-    RSTextFieldCell *cell = (RSTextFieldCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
+    static NSString *cellIdentifier = @"ContainerNameCell";
+    RSTextFieldCell *cell = (RSTextFieldCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
     if (cell == nil) {
-        cell = [[[RSTextFieldCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
-        cell.selectionStyle = UITableViewCellSelectionStyleNone;
+        cell = [[[RSTextFieldCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier] autorelease];
         cell.modalPresentationStyle = UIModalPresentationFormSheet;
-        nameTextField = cell.textField;
-        nameTextField.delegate = self;
-        [nameTextField becomeFirstResponder];
+        textField = cell.textField;
+        textField.delegate = self;
+        textField.clearButtonMode = UITextFieldViewModeWhileEditing;
     }
-    
     cell.textLabel.text = @"Name";
-    
     return cell;
 }
 
-#pragma mark -
-#pragma mark Button Handlers
+#pragma mark - UITextFieldDelegate
+
+- (BOOL)textFieldShouldReturn:(UITextField *)textField {
+    [self saveButtonPressed:nil];
+    return NO;
+}
+
+#pragma mark - Button handlers
 
 - (void)saveButtonPressed:(id)sender {
-    if ([nameTextField.text isEqualToString:@""]) {
-        [self alert:nil message:@"Please enter a name."];
-        [nameTextField becomeFirstResponder];
+    if ([textField.text isEqualToString:@""]) {
+        [self alert:@"Container Name Required" message:@"Please enter a container name."];
     } else {
-        [self.containersViewController showToolbarActivityMessage:@"Creating container..."];
-
+        [textField resignFirstResponder];
+        __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Creating container..."
+                                                                                                       andAddToView:self.view];
         Container *container = [[Container alloc] init];
-        container.name = nameTextField.text;
+        container.name = textField.text;
         [[self.account.manager createContainer:container] 
          success:^(OpenStackRequest *request) {
-             [self.containersViewController showToolbarInfoMessage:self.containersViewController.accountUsageInfo];
              [self.containersViewController.tableView reloadData];
+             [activityIndicatorView removeFromSuperview];
+             [self dismissModalViewControllerAnimated:YES];
+             [container release];
          }
          failure:^(OpenStackRequest *request) {
-             [self.containersViewController showToolbarInfoMessage:self.containersViewController.accountUsageInfo];
+             [activityIndicatorView removeFromSuperview];
              [self.containersViewController alert:@"There was a problem creating your container." request:request];
+             [container release];
          }];
-        [container release];
-        [self dismissModalViewControllerAnimated:YES];
     }
 }
 
-#pragma mark -
-#pragma mark Text Field Delegate
-
-- (BOOL)textFieldShouldReturn:(UITextField *)textField {
-    [self saveButtonPressed:nil];
-    return NO;
-}
-
-#pragma mark -
-#pragma mark Memory management
-
-- (void)dealloc {
-    [containersViewController release];
-    [account release];
-    [super dealloc];
-}
-
 @end
index b924533..f542981 100755 (executable)
@@ -14,9 +14,6 @@
     Container *container;
     Folder *folder;
     FolderViewController *folderViewController;
-    BOOL saving;
-    id successObserver;
-    id failureObserver;
     BOOL allowOverwrite;
 }
 
index 4172105..b8f8781 100755 (executable)
 #import "FolderViewController.h"
 #import "APICallback.h"
 
-
 @implementation AddFolderViewController
 
 @synthesize account, container, folder, folderViewController;
 
+#pragma mark - View lifecycle
+
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
     return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
 }
 
-#pragma mark -
-#pragma mark View lifecycle
-
 - (void)viewDidLoad {
     [super viewDidLoad];
     self.navigationItem.title = @"Add Folder";
     [textField becomeFirstResponder];
 }
 
-#pragma mark -
-#pragma mark Save Button
+#pragma mark - Memory management
 
-- (void)saveButtonPressed:(id)sender {    
-    if (!saving) {        
-        if ([textField.text isEqualToString:@""]) {
-            [self alert:@"Folder Name Required" message:@"Please enter a folder name."];
-        } else {
-            [textField resignFirstResponder];
-            NSString *objectName;
-            BOOL objectNameHasTrailingSlash = [textField.text hasSuffix:@"/"];
-            NSUInteger indexOfFirstSlash = [textField.text rangeOfString:@"/"].location;
-            
-            if ((!objectNameHasTrailingSlash && indexOfFirstSlash != NSNotFound) || 
-                (objectNameHasTrailingSlash && indexOfFirstSlash < textField.text.length - 1)) {
-                [self alert:@"Invalid folder name" message:@"'/' characters are only allowed at the end of folder names"];
-                return;
-            }
-                
-            if (folder && folder.name) {
-                objectName = [NSString stringWithFormat:@"%@/%@", [folder fullPath], textField.text];
-            } else {
-                objectName = textField.text;
-            }
-            
-            if ([folderViewController.folder.folders objectForKey:objectName] && !allowOverwrite) {
-                NSString *alertMessage = [NSString stringWithFormat:@"An object with path '%@' in the container '%@' already exists, do you want to replace it?",objectName, folderViewController.container.name];
-                NSString *alertTitle = @"Apply changes";
-                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertTitle
-                                                                message:alertMessage
-                                                               delegate:self
-                                                      cancelButtonTitle:@"Cancel"
-                                                      otherButtonTitles:@"OK", nil];
-                [alert show];
-                [alert release];
-                return;
-            }
-
-            StorageObject *object = [[StorageObject alloc] init];
-            object.name = object.fullPath = objectName;
-            object.data = [NSData data];
-            object.contentType = @"application/directory";
-            
-            __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Adding folder..."
-                                                                                                           andAddToView:self.view];
-            [[self.account.manager writeObject:self.container object:object downloadProgressDelegate:nil]
-             success:^(OpenStackRequest *request) {
-                 Folder *newFolder = [[Folder alloc] init];
-                 if (objectNameHasTrailingSlash)
-                     object.name = [object.name substringToIndex:object.name.length - 1];
-                 newFolder.name = [[object.name componentsSeparatedByString:@"/"] lastObject];
-                 if (objectNameHasTrailingSlash)
-                     newFolder.name = [newFolder.name stringByAppendingString:@"/"];
-                 newFolder.parent = folder;
-                 newFolder.sharing = folder.sharing;
-                 BOOL currentFolderIsRoot = NO;
-                 if ([folderViewController.folder isEqual:container.rootFolder]) {
-                     currentFolderIsRoot = YES;
-                 }
-                 [folder addFolder:newFolder];
-                 folderViewController.folder = folderViewController.folder;
-                 if (currentFolderIsRoot) {
-                     container.count += 1;
-                     container.rootFolder = folder;
-                     [self.account.containers setObject:container forKey:container.name];
-                 }
-                 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
-                     [folderViewController setDetailViewController];
-                 
-                 allowOverwrite = NO;
-                 [activityIndicatorView removeFromSuperview];
-                 [self dismissModalViewControllerAnimated:YES];
-                 [newFolder release];
-                 [object release];
-             }
-             failure:^(OpenStackRequest *request) {
-                 allowOverwrite = NO;
-                 [activityIndicatorView removeFromSuperview];
-                 [self alert:@"There was a problem creating this folder." request:request];
-                 [object release];
-             }];
-        }
-    }
+- (void)dealloc {
+    [account release];
+    [container release];
+    [folder release];
+    [folderViewController release];
+    [super dealloc];
 }
 
-#pragma mark -
-#pragma mark Table view data source
-
-- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
-    return 1;
-}
+#pragma mark - UITableViewDataSource
 
 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
     return 1;
 }
 
-- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
-    return @"If your folder name contains any forward slash characters, multiple folder objects will be created.";
-}
-
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
-    static NSString *CellIdentifier = @"FolderNameCell";
-    RSTextFieldCell *cell = (RSTextFieldCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
+    static NSString *cellIdentifier = @"FolderNameCell";
+    RSTextFieldCell *cell = (RSTextFieldCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
     if (cell == nil) {
-        cell = [[[RSTextFieldCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
+        cell = [[[RSTextFieldCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier] autorelease];
         cell.modalPresentationStyle = UIModalPresentationFormSheet;
                textField = cell.textField;
         textField.delegate = self;
                textField.clearButtonMode = UITextFieldViewModeWhileEditing;
-    }    
+    }
     cell.textLabel.text = @"Name";
     return cell;
 }
 
-#pragma mark - Alertview delegate
-
-- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
-{
-    if (buttonIndex == 1) {
-        allowOverwrite = YES;
-        [self saveButtonPressed:nil];
-    } 
-}
-
-
-#pragma mark -
-#pragma mark Text Field Delegate
+#pragma mark - UITextFieldDelegate
 
 - (BOOL)textFieldShouldReturn:(UITextField *)textField {
     [self saveButtonPressed:nil];
     return NO;
 }
 
-#pragma mark -
-#pragma mark Memory management
+#pragma mark - UIAlertViewDelegate
 
-- (void)dealloc {
-    [account release];
-    [container release];
-    [folder release];
-    [folderViewController release];
-    [super dealloc];
+- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
+    if (buttonIndex == 1) {
+        allowOverwrite = YES;
+        [self saveButtonPressed:nil];
+    }
+}
+
+#pragma mark - Button handlers
+
+- (void)saveButtonPressed:(id)sender {
+    if ([textField.text isEqualToString:@""]) {
+        [self alert:@"Folder Name Required" message:@"Please enter a folder name."];
+    } else {
+        [textField resignFirstResponder];
+        NSString *objectName;
+        BOOL objectNameHasTrailingSlash = [textField.text hasSuffix:@"/"];
+        NSUInteger indexOfFirstSlash = [textField.text rangeOfString:@"/"].location;
+        if ((!objectNameHasTrailingSlash && indexOfFirstSlash != NSNotFound) ||
+            (objectNameHasTrailingSlash && indexOfFirstSlash < textField.text.length - 1)) {
+            [self alert:@"Invalid folder name" message:@"'/' characters are only allowed at the end of folder names"];
+            return;
+        }
+            
+        if (folder && folder.name) {
+            objectName = [NSString stringWithFormat:@"%@/%@", [folder fullPath], textField.text];
+        } else {
+            objectName = textField.text;
+        }
+        
+        if ([folderViewController.folder.folders objectForKey:objectName] && !allowOverwrite) {
+            NSString *alertMessage = [NSString stringWithFormat:@"An object with path '%@' in the container '%@' already exists, do you want to replace it?",
+                                      objectName, folderViewController.container.name];
+            NSString *alertTitle = @"Apply changes";
+            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertTitle
+                                                            message:alertMessage
+                                                           delegate:self
+                                                  cancelButtonTitle:@"Cancel"
+                                                  otherButtonTitles:@"OK", nil];
+            [alert show];
+            [alert release];
+            return;
+        }
+
+        StorageObject *object = [[StorageObject alloc] init];
+        object.name = object.fullPath = objectName;
+        object.data = [NSData data];
+        object.contentType = @"application/directory";
+        
+        __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Adding folder..."
+                                                                                                       andAddToView:self.view];
+        [[self.account.manager writeObject:self.container object:object downloadProgressDelegate:nil]
+         success:^(OpenStackRequest *request) {
+             Folder *newFolder = [[Folder alloc] init];
+             if (objectNameHasTrailingSlash)
+                 object.name = [object.name substringToIndex:object.name.length - 1];
+             newFolder.name = [[object.name componentsSeparatedByString:@"/"] lastObject];
+             if (objectNameHasTrailingSlash)
+                 newFolder.name = [newFolder.name stringByAppendingString:@"/"];
+             newFolder.parent = folder;
+             newFolder.sharing = folder.sharing;
+             BOOL currentFolderIsRoot = NO;
+             if ([folderViewController.folder isEqual:container.rootFolder]) {
+                 currentFolderIsRoot = YES;
+             }
+             [folder addFolder:newFolder];
+             folderViewController.folder = folderViewController.folder;
+             if (currentFolderIsRoot) {
+                 container.count += 1;
+                 container.rootFolder = folder;
+                 [self.account.containers setObject:container forKey:container.name];
+             }
+             if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
+                 [folderViewController setDetailViewController];
+             
+             allowOverwrite = NO;
+             [activityIndicatorView removeFromSuperview];
+             [self dismissModalViewControllerAnimated:YES];
+             [newFolder release];
+             [object release];
+         }
+         failure:^(OpenStackRequest *request) {
+             allowOverwrite = NO;
+             [activityIndicatorView removeFromSuperview];
+             [self alert:@"There was a problem creating this folder." request:request];
+             [object release];
+         }];
+    }
 }
 
 @end
index f389ffe..a1a00b7 100755 (executable)
@@ -24,7 +24,7 @@
 
 @property (nonatomic, retain) IBOutlet UITableView *tableView;
 @property (nonatomic, retain) OpenStackAccount *account;
-@property (nonatomic, retain) NSString *accountUsageInfo;
+@property (nonatomic, readonly) NSString *accountUsageInfo;
 @property (nonatomic, assign) AccountHomeViewController *accountHomeViewController;
 @property (nonatomic, retain) ContainerDetailViewController *containerDetailViewController;
 
index 12e9695..4a64ae2 100755 (executable)
@@ -20,6 +20,7 @@
 #import "APICallback.h"
 #import "Provider.h"
 #import "AccountHomeViewController.h"
+#import "ActivityIndicatorView.h"
 
 @implementation ContainersViewController
 
@@ -60,7 +61,6 @@
 #pragma mark - Memory management
 
 - (void)dealloc {
-    self.accountUsageInfo = nil;
     [tableView release];
     [account release];
     [containerDetailViewController release];
 
 #pragma mark - Internal
 
-- (void)enableRefreshButton {
-    refreshButton.enabled = YES;
-    [self showToolbarInfoMessage:self.accountUsageInfo];
-}
-
 - (void)createContainerWithName:(NSString *)containerName {
-    [self showToolbarActivityMessage:@"Creating container..."];
+    __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Creating container..."
+                                                                                                   andAddToView:self.view];
+
     Container *container = [[Container alloc] init];
     container.name = containerName;
     [[self.account.manager createContainer:container]
      success:^(OpenStackRequest *request) {
-         [self showToolbarInfoMessage:self.accountUsageInfo];
+         [activityIndicatorView removeFromSuperview];
          [self.tableView reloadData];
      }
      failure:^(OpenStackRequest *request) {
-         [self showToolbarInfoMessage:self.accountUsageInfo];
+         [activityIndicatorView removeFromSuperview];
          [self alert:@"There was a problem creating your container." request:request];
      }];
     [container release];
 #pragma mark - Properties
 
 - (NSString *)accountUsageInfo {
-    if (self.account.sharingAccount || (!self.account.bytesUsed && !self.account.policyQuota)) {
-        [accountUsageInfo release];
-        accountUsageInfo = nil;
-    } else if (!accountUsageInfo) {
-        if (self.account.bytesUsed && self.account.policyQuota) {
-            accountUsageInfo = [NSString stringWithFormat:@"%@ used, %@ available",
-                                [NSObject osxStyleHumanizedBytesNumber:self.account.bytesUsed],
-                                [NSObject osxStyleHumanizedBytesNumber:self.account.policyQuota]];
-        } else if (self.account.bytesUsed) {
-            accountUsageInfo = [NSString stringWithFormat:@"%@ used", [NSObject osxStyleHumanizedBytesNumber:self.account.bytesUsed]];
-        } else if (self.account.policyQuota) {
-            accountUsageInfo = [NSString stringWithFormat:@"%@ available", [NSObject osxStyleHumanizedBytesNumber:self.account.policyQuota]];
-        }
-        [accountUsageInfo retain];
+    if (self.account.sharingAccount)
+        return nil;
+    if (self.account.bytesUsed && self.account.policyQuota) {
+        return [NSString stringWithFormat:@"%@ used, %@ available",
+                [NSObject osxStyleHumanizedBytesNumber:self.account.bytesUsed],
+                [NSObject osxStyleHumanizedBytesNumber:self.account.policyQuota]];
+    } else if (self.account.bytesUsed) {
+        return [NSString stringWithFormat:@"%@ used", [NSObject osxStyleHumanizedBytesNumber:self.account.bytesUsed]];
+    } else if (self.account.policyQuota) {
+        return [NSString stringWithFormat:@"%@ available", [NSObject osxStyleHumanizedBytesNumber:self.account.policyQuota]];
+    } else {
+        return nil;
     }
-    return accountUsageInfo;
 }
 
 #pragma mark - Button Handlers
 }
 
 - (void)refreshButtonPressed:(id)sender {
-    refreshButton.enabled = NO;
-    [self showToolbarActivityMessage:@"Refreshing containers..."];
-    
+    __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Loading..."
+                                                                                                   andAddToView:self.view];
     [[self.account.manager getContainers] success:^(OpenStackRequest *request) {
         self.account.containers = [request containers];
         self.account.containerCount = [self.account.containers count];
         NSString *policyQuotaString = [request.responseHeaders objectForKey:@"X-Account-Policy-Quota"];
         self.account.policyQuota = (policyQuotaString ?
                                     [NSNumber numberWithUnsignedLongLong:strtoull([policyQuotaString UTF8String], NULL, 0)] : nil);
-        self.accountUsageInfo = nil;
         
         [self.account persist];
         containersLoaded = YES;
-        [self enableRefreshButton];
+        
+        [activityIndicatorView removeFromSuperview];
+        [self showToolbarInfoMessage:self.accountUsageInfo];
         [self.tableView reloadData];
         if (!account.shared && !account.sharingAccount) {
             if (![self.account.containers objectForKey:@"pithos"])
         }
     } failure:^(OpenStackRequest *request) {
         containersLoaded = NO;
-        [self enableRefreshButton];
+        [activityIndicatorView removeFromSuperview];
+        [self showToolbarInfoMessage:self.accountUsageInfo];
         if (request.responseStatusCode != 0) {
             [self alert:@"There was a problem loading your containers." request:request];
         }