// AccountGroupsViewController.m
// pithos-ios
//
-// Copyright 2011 GRNET S.A. All rights reserved.
+// Copyright 2011-2013 GRNET S.A. All rights reserved.
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// or implied, of GRNET S.A.
#import "AccountGroupsViewController.h"
+#import "OpenStackAccount.h"
+#import "ActivityIndicatorView.h"
#import "AccountManager.h"
#import "OpenStackRequest.h"
#import "EditAccountGroupsViewController.h"
-
+#import "UIViewController+Conveniences.h"
+#import "NSString+Conveniences.h"
+#import "APICallback.h"
@implementation AccountGroupsViewController
-@synthesize account, groups;
-
-
-- (void)dealloc
-{
- [account release];
- [groups release];
- [metadata release];
- [super dealloc];
-}
-
+@synthesize account, groups, metadata;
#pragma mark - View lifecycle
-- (void)viewDidLoad
-{
- [super viewDidLoad];
- self.navigationItem.title = @"Groups";
- groups = [[NSMutableDictionary alloc] init];
- metadata = [[NSMutableDictionary alloc] init];
-
- NSString *activityMessage = @"Loading..";
- activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
- [activityIndicatorView addToView:self.view];
-
- [self.account.manager getStorageAccountInfo];
- successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"getStorageAccountInfoSucceeded"
- object:account
- queue:[NSOperationQueue mainQueue]
- usingBlock:^(NSNotification *notification)
- {
- [activityIndicatorView removeFromSuperviewAndRelease];
- OpenStackRequest *request = [notification.userInfo objectForKey:@"request"];
- for (NSString *key in request.responseHeaders) {
- if ([key hasPrefix:@"X-Account-Group-"]) {
- NSString *groupName = [key substringFromIndex:16];
- NSString *groupUsers = [request.responseHeaders objectForKey:key];
- [groups setObject:groupUsers forKey:groupName];
- }
- }
-
- for (NSString *header in request.responseHeaders) {
- if ([header hasPrefix:@"X-Account-Meta-"]) {
- NSString *metadataKey = [header substringFromIndex:15];
- NSString *metadataValue = [request.responseHeaders objectForKey:header];
- [metadata setObject:metadataValue forKey:metadataKey];
- }
- }
-
- [self.tableView reloadData];
- [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
- }];
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
+ return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
-- (void)viewDidUnload
-{
- [super viewDidUnload];
- // Release any retained subviews of the main view.
- // e.g. self.myOutlet = nil;
-}
-
-- (void)viewWillAppear:(BOOL)animated
-{
+- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
- [self.tableView reloadData];
+ self.navigationItem.title = @"Groups";
}
-- (void)viewDidAppear:(BOOL)animated
-{
+- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
+ __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Loading groups..."
+ andAddToView:self.view];
+ [[self.account.manager getStorageAccountInfo]
+ success:^(OpenStackRequest *request) {
+ self.groups = [NSMutableDictionary dictionary];
+ self.metadata = [NSMutableDictionary dictionary];
+
+ for (NSString *headerName in request.responseHeaders) {
+ if ([headerName hasPrefix:@"X-Account-Group-"]) {
+ [groups setObject:[[NSString decodeFromPercentEscape:[request.responseHeaders objectForKey:headerName]] componentsSeparatedByString:@","]
+ forKey:[NSString decodeFromPercentEscape:[headerName substringFromIndex:16]]];
+ } else if ([headerName hasPrefix:@"X-Account-Meta-"]) {
+ [metadata setObject:[NSString decodeFromPercentEscape:[request.responseHeaders objectForKey:headerName]]
+ forKey:[NSString decodeFromPercentEscape:[headerName substringFromIndex:15]]];
+ }
+ }
+
+ NSMutableArray *UUIDs = [NSMutableArray array];
+ for (NSString *groupName in groups) {
+ [UUIDs addObjectsFromArray:[groups objectForKey:groupName]];
+ }
+ if (UUIDs.count) {
+ [[self.account.manager userCatalogForDisplaynames:nil UUIDs:UUIDs]
+ success:^(OpenStackRequest *request) {
+ [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
+ [self.tableView reloadData];
+ }
+ failure:^(OpenStackRequest *request) {
+ [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
+ [self.tableView reloadData];
+ if (request.responseStatusCode != 404) {
+ // Don't show alert on 404, since it can be a pre-UUID server.
+ [self alert:@"Failed to translate group UUIDs." request:request];
+ }
+ }];
+ } else {
+ [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
+ [self.tableView reloadData];
+ }
+ }
+ failure:^(OpenStackRequest *request) {
+ [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
+ [self alert:@"Failed to get account information." request:request];
+ }];
}
-- (void)viewWillDisappear:(BOOL)animated
-{
- [super viewWillDisappear:animated];
-}
+#pragma mark - Internal
-- (void)viewDidDisappear:(BOOL)animated
-{
- [super viewDidDisappear:animated];
+- (NSMutableArray *)groupUsersForGroupName:(NSString *)groupName {
+ NSArray *groupUUIDs = [groups objectForKey:groupName];
+ NSMutableArray *groupUsers = [NSMutableArray arrayWithCapacity:groupUUIDs.count];
+ for (NSString *UUID in groupUUIDs) {
+ [groupUsers addObject:[self.account displaynameForUUID:UUID safe:YES]];
+ }
+ return groupUsers;
}
-- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
-{
- // Return YES for supported orientations
- return (interfaceOrientation == UIInterfaceOrientationPortrait);
+- (NSMutableString *)groupUsersStringForGroupName:(NSString *)groupName {
+ NSMutableArray *groupUsers = [self groupUsersForGroupName:groupName];
+ NSMutableString *groupUsersString = [NSMutableString string];
+ for (NSUInteger index = 0; index < groupUsers.count; index++) {
+ if (index) {
+ [groupUsersString appendString:@","];
+ }
+ [groupUsersString appendString:[groupUsers objectAtIndex:index]];
+ }
+ return groupUsersString;
}
-#pragma mark - Table view data source
+#pragma mark - Memory management
-- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
-{
- return 1;
+- (void)dealloc {
+ [account release];
+ [groups release];
+ [metadata release];
+ [super dealloc];
}
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
-{
- return [groups count] + 1;
-}
+#pragma mark - UITableViewDataSource
-- (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;
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+ return (groups.count + 1);
}
- (CGFloat)tableView:(UITableView *)aTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
- CGFloat result = aTableView.rowHeight;
-
- if ([groups count] > 0 && indexPath.row < [groups count]) {
- NSString *groupName = [[groups allKeys] objectAtIndex:indexPath.row];
- NSString *groupUsers = [groups objectForKey:groupName];
-
- result = 22.0 + [self findLabelHeight:[[NSString stringWithFormat:@"%@", groupUsers] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] font:[UIFont systemFontOfSize:18.0]];
-
+ CGFloat result;
+ if (indexPath.row < groups.count) {
+ NSString *groupName = [[[groups allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] objectAtIndex:indexPath.row];
+ result = 22.0 + [[self groupUsersStringForGroupName:groupName] 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);
}
return aTableView.rowHeight;
}
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-{
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
-
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
- if (indexPath.row < [groups count]) {
- NSString *groupName = [[groups allKeys] objectAtIndex:indexPath.row];
+ if (indexPath.row < groups.count) {
+ NSString *groupName = [[[groups allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] objectAtIndex:indexPath.row];
cell.textLabel.text = groupName;
- cell.detailTextLabel.text = [groups objectForKey:groupName];
+ cell.detailTextLabel.text = [self groupUsersStringForGroupName:groupName];
cell.detailTextLabel.numberOfLines = 0;
cell.detailTextLabel.lineBreakMode = UILineBreakModeCharacterWrap;
- }
- else {
+ } else {
cell.textLabel.text = @"Add Group";
cell.detailTextLabel.text = @"";
}
}
-#pragma mark - Table view delegate
+#pragma mark - UITableViewDelegate
-- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
-{
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
EditAccountGroupsViewController *vc = [[EditAccountGroupsViewController alloc] initWithNibName:@"EditAccountGroupsViewController" bundle:nil];
-
vc.account = self.account;
vc.metadata = metadata;
vc.groups = groups;
- if (indexPath.row < [groups count]) {
- NSString *groupName = [[groups allKeys] objectAtIndex:indexPath.row];
- NSString *groupUsers = [groups objectForKey:groupName];
-
+ if (indexPath.row < groups.count) {
+ NSString *groupName = [[[groups allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] objectAtIndex:indexPath.row];
vc.removeGroupEnabled = YES;
vc.groupName = groupName;
- vc.groupUsers = groupUsers;
vc.navigationItem.title = @"Edit Group";
- }
- else {
+ } else {
vc.removeGroupEnabled = NO;
vc.groupName = @"";
- vc.groupUsers = @"";
vc.navigationItem.title = @"Add Group";
}