Statistics
| Branch: | Tag: | Revision:

root / Classes / UploadGenericFileViewController.m @ e899d42b

History | View | Annotate | Download (13 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
@implementation UploadGenericFileViewController
29

    
30
@synthesize account, container, folder, folderViewController, data, format, contentType, contentTypeEditable;
31

    
32
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
33
    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
34
}
35

    
36
#pragma mark - View lifecycle
37

    
38
- (void)viewDidLoad {
39
    [super viewDidLoad];
40
    self.navigationItem.title = @"Add File";
41
    [self addSaveButton];
42
}
43

    
44
- (void)viewWillAppear:(BOOL)animated {
45
    if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
46
        nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(98.0, 13.0, 400.0, 24.0)];
47
    } else {
48
        nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(79.0, 13.0, 222.0, 24.0)];
49
    }    
50
    nameTextField.delegate = self;
51
    nameTextField.font = [UIFont systemFontOfSize:17.0];
52
    nameTextField.textColor = [UIColor value1DetailTextLabelColor];
53
    nameTextField.backgroundColor = [UIColor clearColor];
54
    nameTextField.textAlignment = UITextAlignmentRight;
55
    nameTextField.returnKeyType = UIReturnKeyDone;
56
    nameTextField.autocorrectionType = UITextAutocorrectionTypeNo;
57
    nameTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;    
58
    nameTextField.placeholder = [NSString stringWithFormat:@"ios_upload_%.0f", [[NSDate date] timeIntervalSince1970]];
59
    
60
    if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
61
        formatLabel = [[UILabel alloc] initWithFrame:CGRectMake(41.0, 15.5, 458.0, 18.0)];
62
    } else {
63
        formatLabel = [[UILabel alloc] initWithFrame:CGRectMake(21.0, 15.5, 280.0, 18.0)];
64
    }    
65
    formatLabel.font = [UIFont systemFontOfSize:17.0];
66
    formatLabel.textColor = [UIColor value1DetailTextLabelColor];
67
    formatLabel.backgroundColor = [UIColor clearColor];
68
    formatLabel.textAlignment = UITextAlignmentRight;
69
    if (!self.format) {
70
        self.format = @"";
71
    } else if ([self.format isEqualToString:@".mov"]) {
72
        self.navigationItem.title = @"Add Video";        
73
    } else if ([self.format isEqualToString:@".txt"]) {
74
        self.navigationItem.title = @"Add Text File";
75
    }    
76

    
77
    formatLabel.text = self.format;
78
    
79
    // move the text field to make room for the numbers label
80
    CGSize size = [formatLabel.text sizeWithFont:formatLabel.font constrainedToSize:CGSizeMake(280.0, 900.0f)];
81
    
82
    if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
83
        nameTextField.frame = CGRectMake(98.0, 13.0, 400.0 - size.width, 24.0);
84
    } else {
85
        nameTextField.frame = CGRectMake(79.0, 13.0, 222.0 - size.width, 24.0);
86
    }    
87
    
88
        
89
    if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
90
        contentTypeTextField = [[UITextField alloc] initWithFrame:CGRectMake(79.0, 13.0, 400.0, 24.0)];
91
    } else {
92
        contentTypeTextField = [[UITextField alloc] initWithFrame:CGRectMake(79.0, 13.0, 222.0, 24.0)];
93
    }    
94
    contentTypeTextField.delegate = self;
95
    contentTypeTextField.font = [UIFont systemFontOfSize:17.0];
96
    contentTypeTextField.textColor = [UIColor value1DetailTextLabelColor];
97
    contentTypeTextField.backgroundColor = [UIColor clearColor];
98
    contentTypeTextField.textAlignment = UITextAlignmentRight;
99
    contentTypeTextField.returnKeyType = UIReturnKeyDone;
100
    contentTypeTextField.autocorrectionType = UITextAutocorrectionTypeNo;
101
    contentTypeTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
102
    
103
    if (contentTypeEditable) {
104
        if (self.contentType) {
105
            contentTypeTextField.text = self.contentType;
106
        } else {
107
            contentTypeTextField.text = [OCMimeType mimeTypeForFileExtension:[self.format substringFromIndex:1]];
108
        }
109
    } else {
110
        contentTypeTextField.enabled = NO;
111
        if (self.contentType) {
112
            contentTypeTextField.placeholder = self.contentType;
113
        } else {
114
            contentTypeTextField.placeholder = [OCMimeType mimeTypeForFileExtension:[self.format substringFromIndex:1]];
115
        }
116
    }
117
}
118

    
119
#pragma mark - Table view data source
120

    
121
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
122
    return 2;
123
}
124

    
125
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
126
    if (section == kName) {
127
        return 2;
128
    } else {
129
        return 1;
130
    }
131
}
132

    
133
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
134
    if (section == kContentType) {
135
        return @"The Content Type (MIME Type) is a universal way to describe content regardless of the file extension.";
136
    } else {
137
        return @"";
138
    }
139
}
140

    
141
- (UITableViewCell *)tableView:(UITableView *)tableView textFieldCellForRowAtIndexPath:(NSIndexPath *)indexPath {
142
    if (indexPath.section == kName) {
143
        static NSString *CellIdentifier = @"NameCell";    
144
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
145
        if (cell == nil) {
146
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
147
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
148
            cell.textLabel.text = @"Name";
149
            [cell addSubview:nameTextField];
150
            [cell addSubview:formatLabel];
151
        }
152
        return cell;
153
    } else {
154
        static NSString *CellIdentifier = @"ContentTypeCell";
155
        RSTextFieldCell *cell = (RSTextFieldCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
156
        if (cell == nil) {
157
            cell = [[[RSTextFieldCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
158
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
159
            cell.modalPresentationStyle = UIModalPresentationFormSheet;
160
            cell.textLabel.text = @"Content Type";
161
            contentTypeTextField = cell.textField;
162
            if (contentTypeEditable) {
163
                if (self.contentType) {
164
                    contentTypeTextField.text = self.contentType;
165
                } else {
166
                    contentTypeTextField.text = [OCMimeType mimeTypeForFileExtension:[self.format substringFromIndex:1]];
167
                }
168
            } else {
169
                contentTypeTextField.enabled = NO;
170
                if (self.contentType) {
171
                    contentTypeTextField.placeholder = self.contentType;
172
                } else {
173
                    contentTypeTextField.placeholder = [OCMimeType mimeTypeForFileExtension:[self.format substringFromIndex:1]];
174
                }
175
            }
176
            
177
        }    
178
        return cell;
179
    }
180
}
181

    
182
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
183
    
184
    if (indexPath.section == kName && indexPath.row == 0) {
185
        return [self tableView:tableView textFieldCellForRowAtIndexPath:indexPath];
186
    } else if (indexPath.section == kContentType) {
187
        return [self tableView:tableView textFieldCellForRowAtIndexPath:indexPath];
188
    } else {
189
        static NSString *CellIdentifier = @"Cell";
190
        
191
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
192
        if (cell == nil) {
193
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
194
        }
195
        
196
        cell.textLabel.text = @"Size";
197
        cell.detailTextLabel.text = [Container humanizedBytes:[data length]];
198
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
199
        cell.accessoryType = UITableViewCellAccessoryNone;
200
        
201
        return cell;
202
    }
203
}
204

    
205
#pragma mark - Save Button
206

    
207
- (void)saveButtonPressed:(id)sender {
208
    [nameTextField resignFirstResponder];
209
    NSString *objectName;
210
    if (nameTextField.text && ![nameTextField.text isEqualToString:@""]) {
211
        objectName = [NSString stringWithFormat:@"%@%@", nameTextField.text, format];
212
    } else {
213
        objectName = [NSString stringWithFormat:@"%@%@", nameTextField.placeholder, format];
214
    }
215
    
216
    BOOL objectNameHasTrailingSlash = [objectName hasSuffix:@"/"];
217
    NSUInteger indexOfFirstSlash = [objectName rangeOfString:@"/"].location;
218
    
219
    if ((!objectNameHasTrailingSlash && indexOfFirstSlash != NSNotFound) || 
220
        (objectNameHasTrailingSlash && indexOfFirstSlash < objectName.length - 1)) {
221
        [self alert:@"Invalid folder name" message:@"'/' characters are only allowed at the end of folder names"];
222
        return;
223
    }
224

    
225
    if ([folderViewController.folder.objects objectForKey:objectName] && !allowOverwrite) {
226
        NSString *alertMessage = [NSString stringWithFormat:@"An object with path '%@' in the container '%@' already exists, do you want to replace it?",objectName, folderViewController.container.name];
227
        NSString *alertTitle = @"Apply changes";
228
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertTitle
229
                                                        message:alertMessage
230
                                                       delegate:self
231
                                              cancelButtonTitle:@"Cancel"
232
                                              otherButtonTitles:@"OK", nil];
233
        [alert show];
234
        [alert release];
235
        return;
236
    }
237
    
238
    StorageObject *object = [[StorageObject alloc] init];
239
    object.name = objectName;
240
    object.fullPath = [NSString stringWithFormat:@"%@/%@", [folder fullPath], object.name];
241
    object.fullPath = [object.fullPath substringFromIndex:1];
242
    object.contentType = contentTypeTextField.text;
243
    if (!contentType) {
244
        object.contentType = @"application/octet-stream";
245
    }
246
    object.data = data;
247
    object.bytes = [data length];
248
    
249
    __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Uploading..."
250
                                                                                                   withProgress:YES
251
                                                                                                   andAddToView:self.view];
252
    [[self.account.manager writeObject:self.container object:object downloadProgressDelegate:activityIndicatorView.progressView]
253
     success:^(OpenStackRequest *request) {
254
         object.data = nil;
255
         object.sharing = folder.sharing;
256
         object.lastModified = [ComputeModel dateFromRFC1123String:[request.responseHeaders objectForKey:@"Date"]];
257
         BOOL currentFolderIsRoot = [folderViewController.folder isEqual:container.rootFolder];
258
         [folder addObject:object];
259
         folderViewController.folder = folderViewController.folder;
260
         if (currentFolderIsRoot) {
261
             container.count += 1;
262
             container.rootFolder = folder;
263
             [self.account.containers setObject:container forKey:container.name];
264
         }
265
         if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
266
             [folderViewController setDetailViewController];
267
         allowOverwrite = NO;
268
         [[self.account.manager getObjectInfo:self.container object:object]
269
          success:^(OpenStackRequest *request) {
270
              [activityIndicatorView removeFromSuperview];
271
              object.hash = [request.responseHeaders objectForKey:@"X-Object-Hash"];
272
              [self dismissModalViewControllerAnimated:YES];
273
          }
274
          failure:^(OpenStackRequest *request) {
275
              [activityIndicatorView removeFromSuperview];
276
              [self dismissModalViewControllerAnimated:YES];
277
          }];
278
     }
279
     failure:^(OpenStackRequest *request) {
280
         allowOverwrite = NO;
281
         [activityIndicatorView removeFromSuperview];
282
         [self alert:@"There was a problem uploading the file." request:request];
283
     }];    
284
}
285

    
286
#pragma mark - Alertview delegate
287

    
288
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
289
    if (buttonIndex == 1) {
290
        allowOverwrite = YES;
291
        [self saveButtonPressed:nil];
292
    } 
293
}
294

    
295

    
296
#pragma mark - Text Field Delegate
297

    
298
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
299
    [textField resignFirstResponder];
300
    return NO;
301
}
302

    
303
#pragma mark - Memory management
304

    
305
- (void)dealloc {
306
    [account release];
307
    [container release];
308
    [folder release];
309
    [folderViewController release];
310
    [data release];
311
    [format release];
312
    [contentType release];
313
    [super dealloc];
314
}
315

    
316
@end
317