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