UI changes.
[pithos-ios] / Classes / ContainersViewController.m
1 //
2 //  ContainersViewController.m
3 //  OpenStack
4 //
5 //  Created by Mike Mayo on 12/7/10.
6 //  The OpenStack project is provided under the Apache 2.0 license.
7 //
8
9 #import "ContainersViewController.h"
10 #import "OpenStackAccount.h"
11 #import "Container.h"
12 #import "AddContainerViewController.h"
13 #import "UIViewController+Conveniences.h"
14 #import "FolderViewController.h"
15 #import "ContainerDetailViewController.h"
16 #import "AccountManager.h"
17 #import "OpenStackAppDelegate.h"
18 #import "RootViewController.h"
19 #import "APICallback.h"
20 #import "GetCDNContainersRequest.h"
21
22
23 @implementation ContainersViewController
24
25 @synthesize tableView, account;
26
27 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
28     return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
29 }
30
31 #pragma mark -
32 #pragma mark View lifecycle
33
34 - (void)viewDidLoad {
35     [super viewDidLoad];
36     self.navigationItem.title = @"Containers";
37     [self addAddButton];
38 }
39
40 - (void)viewWillAppear:(BOOL)animated {
41     [super viewWillAppear:animated];
42     
43     successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"createContainerSucceeded" object:self.account 
44                                                                          queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification)
45        {
46            [self hideToolbarActivityMessage];
47            [self.tableView reloadData];
48        }];
49     
50     failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"createContainerFailed" object:self.account 
51                                                                          queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification)
52        {
53            [self hideToolbarActivityMessage];
54            [self alert:@"There was a problem creating your container." request:[notification.userInfo objectForKey:@"request"]];
55        }];
56     
57     if ([self.account.containers count] == 0) {
58         self.tableView.allowsSelection = NO;
59         self.tableView.scrollEnabled = NO;
60         [self.tableView reloadData];        
61     }    
62     
63     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && [self.account.containers count] == 0) {
64         NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
65         [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
66         [self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
67     }
68     
69     if (!containersLoaded && [self.account.containers count] == 0) {
70         [self refreshButtonPressed:nil];
71     }
72     
73 }
74
75 - (void)viewDidDisappear:(BOOL)animated {
76     [super viewDidDisappear:animated];
77     [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
78     [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
79 }
80
81 #pragma mark -
82 #pragma mark Button Handlers
83
84 - (void)addButtonPressed:(id)sender {
85     AddContainerViewController *vc = [[AddContainerViewController alloc] initWithNibName:@"AddContainerViewController" bundle:nil];
86     vc.containersViewController = self;
87     vc.account = account;
88     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
89         vc.modalPresentationStyle = UIModalPresentationFormSheet;
90         OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
91         if (app.rootViewController.popoverController != nil) {
92             [app.rootViewController.popoverController dismissPopoverAnimated:YES];
93         }
94     }                
95     [self presentModalViewControllerWithNavigation:vc];
96     [vc release];
97 }
98
99 - (void)enableRefreshButton {
100     containersLoaded = YES;
101     refreshButton.enabled = YES;
102     [self hideToolbarActivityMessage];
103     [self showToolbarInfoMessage:accountUsageInfo];
104 }
105
106 - (void)refreshButtonPressed:(id)sender {
107
108     refreshButton.enabled = NO;
109         
110         //BOOL hadZeroContainers = [self.account.containers count] == 0;
111         
112     [self hideToolbarInfoMessage];
113     [self showToolbarActivityMessage:@"Refreshing containers..."];
114     
115     [[self.account.manager getContainersWithCallback] success:^(OpenStackRequest *request) {
116         self.account.containers = [request containers];
117         self.account.containerCount = [self.account.containers count];
118         self.account.totalBytesUsed = [[request.responseHeaders objectForKey:@"X-Account-Bytes-Used"] longLongValue];
119         self.account.quota = [[request.responseHeaders objectForKey:@"X-Account-Policy-Quota"] longLongValue];
120         accountUsageInfo = [NSString stringWithFormat:@"%@ used, %@ available",
121                             [self humanReadableSize:self.account.totalBytesUsed], [self humanReadableSize:self.account.quota]];
122                             
123         [self.account persist];
124         [self enableRefreshButton];
125         [self.tableView reloadData];
126         
127         //GetCDNContainersRequest *cdnRequest = [GetCDNContainersRequest request:self.account];
128         //[cdnRequest startAsynchronous];
129         
130     } failure:^(OpenStackRequest *request) {
131         [self enableRefreshButton];
132         if (request.responseStatusCode != 0) {
133             [self alert:@"There was a problem loading your containers." request:request];
134         }
135     }];
136 }
137
138 #pragma mark -
139 #pragma mark Table view data source
140
141 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
142     return 1;
143 }
144
145 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
146     if ([self.account.containers count] == 0) {
147         self.tableView.allowsSelection = NO;
148         self.tableView.scrollEnabled = NO;
149     } else {
150         self.tableView.allowsSelection = YES;
151         self.tableView.scrollEnabled = YES;
152     }
153     if (!containersLoaded && [self.account.containers count] == 0) {
154         return 0;
155     } else {
156         return MAX(1, [account.containers count]);    
157     }
158 }
159
160 - (CGFloat)tableView:(UITableView *)aTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
161     if ([account.containers count] == 0) {
162         return aTableView.frame.size.height;
163     } else {
164         return aTableView.rowHeight;
165     }
166 }
167 - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
168     if (containersLoaded && [self.account.containers count] == 0) {
169         return [self tableView:tableView emptyCellWithImage:[UIImage imageNamed:@"empty-containers.png"] title:@"No Containers" subtitle:@"Tap the + button to create a new container"];
170     } else {   
171         static NSString *CellIdentifier = @"Cell";
172         
173         UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
174         if (cell == nil) {
175             cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
176             if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
177                 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
178             } else {
179                 cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
180             }
181             cell.imageView.image = [UIImage imageNamed:@"folder-icon.png"];
182         }
183
184         Container *container = [self.account.sortedContainers objectAtIndex:indexPath.row];
185         cell.textLabel.text = container.name;
186         cell.detailTextLabel.text = [container humanizedSize];
187         
188         return cell;
189     }
190 }
191
192 #pragma mark -
193 #pragma mark Table view delegate
194
195 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
196     Container *container = nil;
197     if ([account.containers count] > 0) {
198         container = [self.account.sortedContainers objectAtIndex:indexPath.row];
199
200         FolderViewController *vc = [[FolderViewController alloc] initWithNibName:@"FolderViewController" bundle:nil];
201         vc.account = self.account;
202         vc.container = container;
203         vc.folder = container.rootFolder;
204         vc.containersViewController = self;
205         vc.selectedContainerIndexPath = indexPath;
206         [self.navigationController pushViewController:vc animated:YES];
207         [vc release];
208         [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
209     }
210     
211     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
212         ContainerDetailViewController *vc = [[ContainerDetailViewController alloc] initWithNibName:@"ContainerDetailViewController" bundle:nil];
213         vc.account = self.account;
214         vc.container = container;
215         vc.containersViewController = self;
216         vc.selectedContainerIndexPath = indexPath;
217         [self presentPrimaryViewController:vc];
218         [vc release];
219     }
220 }
221
222 - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
223     Container *container = nil;
224     if ([account.containers count] > 0) {
225         container = [self.account.sortedContainers objectAtIndex:indexPath.row];
226     }
227     ContainerDetailViewController *vc = [[ContainerDetailViewController alloc] initWithNibName:@"ContainerDetailViewController" bundle:nil];
228     vc.account = self.account;
229     vc.container = container;
230     vc.containersViewController = self;
231     vc.selectedContainerIndexPath = indexPath;
232     [self.navigationController pushViewController:vc animated:YES];
233     [vc release];
234 }
235
236 #pragma mark -
237 #pragma mark Helper methods
238
239 - (NSString *)humanReadableSize:(unsigned long long)bytes {
240     NSString *sizeUnit = @"bytes";
241         
242     double sizeInBytes = bytes; 
243     if (bytes > 1023 && bytes < 1048576) {
244         sizeInBytes =  bytes / 1024.0;
245         sizeUnit = @"Kb";
246     }
247     else if (bytes > 1048575 && bytes < 1073741824) {
248         sizeInBytes = bytes / 1048576.0;
249         sizeUnit = @"Mb";
250     }
251     else if (bytes > 1073741823) {
252         sizeInBytes = bytes / 1073741824.0;
253         sizeUnit = @"Gb";
254     }
255         
256     NSString *humanReadableString = [NSString stringWithFormat:@"%.1f %@", sizeInBytes, sizeUnit];
257     humanReadableString = [humanReadableString stringByReplacingOccurrencesOfString:@".0" withString:@""];
258     
259     return humanReadableString;
260 }
261
262
263 #pragma mark -
264 #pragma mark Memory management
265
266 - (void)dealloc {
267     [tableView release];
268     [account release];
269     [super dealloc];
270 }
271
272 @end