Statistics
| Branch: | Tag: | Revision:

root / Classes / UploadGenericFileViewController.m @ 45f2fce6

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

    
23
#define kName 0
24
#define kContentType 1
25

    
26

    
27
@implementation UploadGenericFileViewController
28

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

    
31
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
32
    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
33
}
34

    
35
#pragma mark -
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 (UI_USER_INTERFACE_IDIOM() == 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 (UI_USER_INTERFACE_IDIOM() == 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 (UI_USER_INTERFACE_IDIOM() == 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 (UI_USER_INTERFACE_IDIOM() == 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 -
120
#pragma mark Table view data source
121

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

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

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

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

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

    
206
#pragma mark -
207
#pragma mark Save Button
208

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

    
227
    if ([folderViewController.folder.objects objectForKey:objectName] && !allowOverwrite) {
228
        NSString *alertMessage = [NSString stringWithFormat:@"An object with path '%@' in the container '%@' already exists, do you want to replace it?",objectName, folderViewController.container.name];
229
        NSString *alertTitle = @"Apply changes";
230
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertTitle
231
                                                        message:alertMessage
232
                                                       delegate:self
233
                                              cancelButtonTitle:@"Cancel"
234
                                              otherButtonTitles:@"OK", nil];
235
        [alert show];
236
        return;
237
    }
238

    
239
    activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:@"Uploading..." withProgress:YES] text:@"Uploading..." withProgress:YES];
240
    [activityIndicatorView addToView:self.view];
241
    
242
    StorageObject *object = [[StorageObject alloc] init];
243
    object.name = objectName;
244
    object.fullPath = [NSString stringWithFormat:@"%@/%@", [folder fullPath], object.name];
245
    object.fullPath = [object.fullPath substringFromIndex:1];
246
    object.contentType = contentTypeTextField.text;
247
    
248
    if (!contentType) {
249
        object.contentType = @"application/octet-stream";
250
    }
251
    
252
    object.data = data;
253
    object.bytes = [data length];
254
    
255
    [self.account.manager writeObject:self.container object:object downloadProgressDelegate:activityIndicatorView.progressView];
256
    
257
    successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectSucceeded" object:object queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification) 
258
                       {
259
                           [activityIndicatorView removeFromSuperviewAndRelease];
260
                           object.data = nil;
261
                           object.sharing = folder.sharing;
262
                           [folder.objects setObject:object forKey:object.name];
263
                           [folderViewController.tableView reloadData];
264
                           allowOverwrite = NO;
265
                           [self dismissModalViewControllerAnimated:YES];
266
                           [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
267
                       }];
268
    
269
    failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectFailed" object:object queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification) 
270
                       {
271
                           allowOverwrite = NO;
272
                           [activityIndicatorView removeFromSuperviewAndRelease];
273
                           [self alert:@"There was a problem uploading the file." request:[notification.userInfo objectForKey:@"request"]];
274
                           [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
275
                       }];
276
}
277

    
278
#pragma mark - Alertview delegate
279

    
280
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
281
{
282
    if (buttonIndex == 1) {
283
        allowOverwrite = YES;
284
        [self saveButtonPressed:nil];
285
    } 
286
}
287

    
288

    
289
#pragma mark -
290
#pragma mark Text Field Delegate
291

    
292
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
293
    [textField resignFirstResponder];
294
    return NO;
295
}
296

    
297
#pragma mark -
298
#pragma mark Memory management
299

    
300
- (void)dealloc {
301
    [account release];
302
    [container release];
303
    [folder release];
304
    [folderViewController release];
305
    [data release];
306
    [format release];
307
    [contentType release];
308
    [super dealloc];
309
}
310

    
311

    
312
@end
313