root / Classes / UploadGenericFileViewController.m @ 29cc4957
History | View | Annotate | Download (12.6 kB)
1 |
// |
---|---|
2 |
// UploadGenericFileViewController.m |
3 |
// OpenStack |
4 |
// |
5 |
// Created by Mike Mayo on 1/6/11. |
6 |
// Copyright 2011 __MyCompanyName__. All rights reserved. |
7 |
// |
8 |
|
9 |
#import "UploadGenericFileViewController.h" |
10 |
#import "OpenStackAccount.h" |
11 |
#import "AccountManager.h" |
12 |
#import "Container.h" |
13 |
#import "Folder.h" |
14 |
#import "FolderViewController.h" |
15 |
#import "ActivityIndicatorView.h" |
16 |
#import "UIViewController+Conveniences.h" |
17 |
#import "UIColor+MoreColors.h" |
18 |
#import "StorageObject.h" |
19 |
#import "OCMimeType.h" |
20 |
#import "RSTextFieldCell.h" |
21 |
#import "NSObject+Conveniences.h" |
22 |
#import "APICallback.h" |
23 |
#import "ComputeModel.h" |
24 |
|
25 |
#define kName 0 |
26 |
#define kContentType 1 |
27 |
|
28 |
|
29 |
@implementation UploadGenericFileViewController |
30 |
|
31 |
@synthesize account, container, folder, folderViewController, data, format, contentType, contentTypeEditable; |
32 |
|
33 |
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { |
34 |
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); |
35 |
} |
36 |
|
37 |
#pragma mark - |
38 |
#pragma mark View lifecycle |
39 |
|
40 |
- (void)viewDidLoad { |
41 |
[super viewDidLoad]; |
42 |
self.navigationItem.title = @"Add File"; |
43 |
[self addSaveButton]; |
44 |
} |
45 |
|
46 |
- (void)viewWillAppear:(BOOL)animated { |
47 |
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { |
48 |
nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(98.0, 13.0, 400.0, 24.0)]; |
49 |
} else { |
50 |
nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(79.0, 13.0, 222.0, 24.0)]; |
51 |
} |
52 |
nameTextField.delegate = self; |
53 |
nameTextField.font = [UIFont systemFontOfSize:17.0]; |
54 |
nameTextField.textColor = [UIColor value1DetailTextLabelColor]; |
55 |
nameTextField.backgroundColor = [UIColor clearColor]; |
56 |
nameTextField.textAlignment = UITextAlignmentRight; |
57 |
nameTextField.returnKeyType = UIReturnKeyDone; |
58 |
nameTextField.autocorrectionType = UITextAutocorrectionTypeNo; |
59 |
nameTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; |
60 |
nameTextField.placeholder = [NSString stringWithFormat:@"ios_upload_%.0f", [[NSDate date] timeIntervalSince1970]]; |
61 |
|
62 |
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { |
63 |
formatLabel = [[UILabel alloc] initWithFrame:CGRectMake(41.0, 15.5, 458.0, 18.0)]; |
64 |
} else { |
65 |
formatLabel = [[UILabel alloc] initWithFrame:CGRectMake(21.0, 15.5, 280.0, 18.0)]; |
66 |
} |
67 |
formatLabel.font = [UIFont systemFontOfSize:17.0]; |
68 |
formatLabel.textColor = [UIColor value1DetailTextLabelColor]; |
69 |
formatLabel.backgroundColor = [UIColor clearColor]; |
70 |
formatLabel.textAlignment = UITextAlignmentRight; |
71 |
if (!self.format) { |
72 |
self.format = @""; |
73 |
} else if ([self.format isEqualToString:@".mov"]) { |
74 |
self.navigationItem.title = @"Add Video"; |
75 |
} else if ([self.format isEqualToString:@".txt"]) { |
76 |
self.navigationItem.title = @"Add Text File"; |
77 |
} |
78 |
|
79 |
formatLabel.text = self.format; |
80 |
|
81 |
// move the text field to make room for the numbers label |
82 |
CGSize size = [formatLabel.text sizeWithFont:formatLabel.font constrainedToSize:CGSizeMake(280.0, 900.0f)]; |
83 |
|
84 |
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { |
85 |
nameTextField.frame = CGRectMake(98.0, 13.0, 400.0 - size.width, 24.0); |
86 |
} else { |
87 |
nameTextField.frame = CGRectMake(79.0, 13.0, 222.0 - size.width, 24.0); |
88 |
} |
89 |
|
90 |
|
91 |
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { |
92 |
contentTypeTextField = [[UITextField alloc] initWithFrame:CGRectMake(79.0, 13.0, 400.0, 24.0)]; |
93 |
} else { |
94 |
contentTypeTextField = [[UITextField alloc] initWithFrame:CGRectMake(79.0, 13.0, 222.0, 24.0)]; |
95 |
} |
96 |
contentTypeTextField.delegate = self; |
97 |
contentTypeTextField.font = [UIFont systemFontOfSize:17.0]; |
98 |
contentTypeTextField.textColor = [UIColor value1DetailTextLabelColor]; |
99 |
contentTypeTextField.backgroundColor = [UIColor clearColor]; |
100 |
contentTypeTextField.textAlignment = UITextAlignmentRight; |
101 |
contentTypeTextField.returnKeyType = UIReturnKeyDone; |
102 |
contentTypeTextField.autocorrectionType = UITextAutocorrectionTypeNo; |
103 |
contentTypeTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; |
104 |
|
105 |
if (contentTypeEditable) { |
106 |
if (self.contentType) { |
107 |
contentTypeTextField.text = self.contentType; |
108 |
} else { |
109 |
contentTypeTextField.text = [OCMimeType mimeTypeForFileExtension:[self.format substringFromIndex:1]]; |
110 |
} |
111 |
} else { |
112 |
contentTypeTextField.enabled = NO; |
113 |
if (self.contentType) { |
114 |
contentTypeTextField.placeholder = self.contentType; |
115 |
} else { |
116 |
contentTypeTextField.placeholder = [OCMimeType mimeTypeForFileExtension:[self.format substringFromIndex:1]]; |
117 |
} |
118 |
} |
119 |
} |
120 |
|
121 |
#pragma mark - |
122 |
#pragma mark Table view data source |
123 |
|
124 |
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { |
125 |
return 2; |
126 |
} |
127 |
|
128 |
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { |
129 |
if (section == kName) { |
130 |
return 2; |
131 |
} else { |
132 |
return 1; |
133 |
} |
134 |
} |
135 |
|
136 |
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { |
137 |
if (section == kContentType) { |
138 |
return @"The Content Type (MIME Type) is a universal way to describe content regardless of the file extension."; |
139 |
} else { |
140 |
return @""; |
141 |
} |
142 |
} |
143 |
|
144 |
- (UITableViewCell *)tableView:(UITableView *)tableView textFieldCellForRowAtIndexPath:(NSIndexPath *)indexPath { |
145 |
if (indexPath.section == kName) { |
146 |
static NSString *CellIdentifier = @"NameCell"; |
147 |
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; |
148 |
if (cell == nil) { |
149 |
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease]; |
150 |
cell.selectionStyle = UITableViewCellSelectionStyleNone; |
151 |
cell.textLabel.text = @"Name"; |
152 |
[cell addSubview:nameTextField]; |
153 |
[cell addSubview:formatLabel]; |
154 |
} |
155 |
return cell; |
156 |
} else { |
157 |
static NSString *CellIdentifier = @"ContentTypeCell"; |
158 |
RSTextFieldCell *cell = (RSTextFieldCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; |
159 |
if (cell == nil) { |
160 |
cell = [[[RSTextFieldCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease]; |
161 |
cell.selectionStyle = UITableViewCellSelectionStyleNone; |
162 |
cell.modalPresentationStyle = UIModalPresentationFormSheet; |
163 |
cell.textLabel.text = @"Content Type"; |
164 |
contentTypeTextField = cell.textField; |
165 |
if (contentTypeEditable) { |
166 |
if (self.contentType) { |
167 |
contentTypeTextField.text = self.contentType; |
168 |
} else { |
169 |
contentTypeTextField.text = [OCMimeType mimeTypeForFileExtension:[self.format substringFromIndex:1]]; |
170 |
} |
171 |
} else { |
172 |
contentTypeTextField.enabled = NO; |
173 |
if (self.contentType) { |
174 |
contentTypeTextField.placeholder = self.contentType; |
175 |
} else { |
176 |
contentTypeTextField.placeholder = [OCMimeType mimeTypeForFileExtension:[self.format substringFromIndex:1]]; |
177 |
} |
178 |
} |
179 |
|
180 |
} |
181 |
return cell; |
182 |
} |
183 |
} |
184 |
|
185 |
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { |
186 |
|
187 |
if (indexPath.section == kName && indexPath.row == 0) { |
188 |
return [self tableView:tableView textFieldCellForRowAtIndexPath:indexPath]; |
189 |
} else if (indexPath.section == kContentType) { |
190 |
return [self tableView:tableView textFieldCellForRowAtIndexPath:indexPath]; |
191 |
} else { |
192 |
static NSString *CellIdentifier = @"Cell"; |
193 |
|
194 |
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; |
195 |
if (cell == nil) { |
196 |
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease]; |
197 |
} |
198 |
|
199 |
cell.textLabel.text = @"Size"; |
200 |
cell.detailTextLabel.text = [Container humanizedBytes:[data length]]; |
201 |
cell.selectionStyle = UITableViewCellSelectionStyleNone; |
202 |
cell.accessoryType = UITableViewCellAccessoryNone; |
203 |
|
204 |
return cell; |
205 |
} |
206 |
} |
207 |
|
208 |
#pragma mark - |
209 |
#pragma mark Save Button |
210 |
|
211 |
- (void)saveButtonPressed:(id)sender { |
212 |
[nameTextField resignFirstResponder]; |
213 |
NSString *objectName; |
214 |
if (nameTextField.text && ![nameTextField.text isEqualToString:@""]) { |
215 |
objectName = [NSString stringWithFormat:@"%@%@", nameTextField.text, format]; |
216 |
} else { |
217 |
objectName = [NSString stringWithFormat:@"%@%@", nameTextField.placeholder, format]; |
218 |
} |
219 |
|
220 |
BOOL objectNameHasTrailingSlash = [objectName hasSuffix:@"/"]; |
221 |
NSUInteger indexOfFirstSlash = [objectName rangeOfString:@"/"].location; |
222 |
|
223 |
if ((!objectNameHasTrailingSlash && indexOfFirstSlash != NSNotFound) || |
224 |
(objectNameHasTrailingSlash && indexOfFirstSlash < objectName.length - 1)) { |
225 |
[self alert:@"Invalid folder name" message:@"'/' characters are only allowed at the end of folder names"]; |
226 |
return; |
227 |
} |
228 |
|
229 |
if ([folderViewController.folder.objects objectForKey:objectName] && !allowOverwrite) { |
230 |
NSString *alertMessage = [NSString stringWithFormat:@"An object with path '%@' in the container '%@' already exists, do you want to replace it?",objectName, folderViewController.container.name]; |
231 |
NSString *alertTitle = @"Apply changes"; |
232 |
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertTitle |
233 |
message:alertMessage |
234 |
delegate:self |
235 |
cancelButtonTitle:@"Cancel" |
236 |
otherButtonTitles:@"OK", nil]; |
237 |
[alert show]; |
238 |
[alert release]; |
239 |
return; |
240 |
} |
241 |
[activityIndicatorView release]; |
242 |
activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:@"Uploading..." withProgress:YES] text:@"Uploading..." withProgress:YES]; |
243 |
[activityIndicatorView addToView:self.view]; |
244 |
|
245 |
StorageObject *object = [[StorageObject alloc] init]; |
246 |
object.name = objectName; |
247 |
object.fullPath = [NSString stringWithFormat:@"%@/%@", [folder fullPath], object.name]; |
248 |
object.fullPath = [object.fullPath substringFromIndex:1]; |
249 |
object.contentType = contentTypeTextField.text; |
250 |
|
251 |
if (!contentType) { |
252 |
object.contentType = @"application/octet-stream"; |
253 |
} |
254 |
|
255 |
object.data = data; |
256 |
object.bytes = [data length]; |
257 |
|
258 |
[[self.account.manager writeObject:self.container object:object downloadProgressDelegate:activityIndicatorView.progressView] |
259 |
success:^(OpenStackRequest *request) { |
260 |
[activityIndicatorView removeFromSuperview]; |
261 |
object.data = nil; |
262 |
object.sharing = folder.sharing; |
263 |
object.lastModified = [ComputeModel dateFromRFC1123String:[request.responseHeaders objectForKey:@"Date"]]; |
264 |
|
265 |
BOOL currentFolderIsRoot = NO; |
266 |
if ([folderViewController.folder isEqual:container.rootFolder]) { |
267 |
currentFolderIsRoot = YES; |
268 |
} |
269 |
[folder.objects setObject:object forKey:object.name]; |
270 |
[folderViewController.tableView reloadData]; |
271 |
if (currentFolderIsRoot) { |
272 |
container.count += 1; |
273 |
container.rootFolder = folder; |
274 |
[self.account.containers setObject:container forKey:container.name]; |
275 |
} |
276 |
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) |
277 |
[folderViewController setDetailViewController]; |
278 |
allowOverwrite = NO; |
279 |
[self dismissModalViewControllerAnimated:YES]; |
280 |
} |
281 |
failure:^(OpenStackRequest *request) { |
282 |
allowOverwrite = NO; |
283 |
[activityIndicatorView removeFromSuperview]; |
284 |
[self alert:@"There was a problem uploading the file." request:request]; |
285 |
}]; |
286 |
} |
287 |
|
288 |
#pragma mark - Alertview delegate |
289 |
|
290 |
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex |
291 |
{ |
292 |
if (buttonIndex == 1) { |
293 |
allowOverwrite = YES; |
294 |
[self saveButtonPressed:nil]; |
295 |
} |
296 |
} |
297 |
|
298 |
|
299 |
#pragma mark - |
300 |
#pragma mark Text Field Delegate |
301 |
|
302 |
- (BOOL)textFieldShouldReturn:(UITextField *)textField { |
303 |
[textField resignFirstResponder]; |
304 |
return NO; |
305 |
} |
306 |
|
307 |
#pragma mark - |
308 |
#pragma mark Memory management |
309 |
|
310 |
- (void)dealloc { |
311 |
[account release]; |
312 |
[container release]; |
313 |
[folder release]; |
314 |
[folderViewController release]; |
315 |
[data release]; |
316 |
[format release]; |
317 |
[contentType release]; |
318 |
[activityIndicatorView release]; |
319 |
[super dealloc]; |
320 |
} |
321 |
|
322 |
|
323 |
@end |
324 |
|