Statistics
| Branch: | Tag: | Revision:

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