VLCMenuTableViewController.m 16.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*****************************************************************************
 * VLCMenuTableViewController.m
 * VLC for iOS
 *****************************************************************************
 * Copyright (c) 2013 VideoLAN. All rights reserved.
 * $Id$
 *
 * Authors: Felix Paul Kühne <fkuehne # videolan.org>
 *          Gleb Pinigin <gpinigin # gmail.com>
 *          Jean-Romain Prévost <jr # 3on.fr>
 *          Carola Nitz <nitz.carola # googlemail.com>
 *          Tamas Timar <ttimar.vlc # gmail.com>
 *          Pierre Sagaspe <pierre.sagaspe # me.com>
 *
 * Refer to the COPYING file of the official project for license.
 *****************************************************************************/
17
18
19

#import "VLCMenuTableViewController.h"
#import "GHRevealViewController.h"
20
#import "VLCSidebarViewCell.h"
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#import "Reachability.h"
#import <QuartzCore/QuartzCore.h>
#import "VLCWiFiUploadTableViewCell.h"
#import "VLCHTTPUploaderController.h"
#import "VLCAppDelegate.h"
#import "HTTPServer.h"
#import "IASKAppSettingsViewController.h"
#import "GHRevealViewController.h"
#import "VLCLocalServerListViewController.h"
#import "VLCOpenNetworkStreamViewController.h"
#import "VLCSettingsController.h"
#import "UINavigationController+Theme.h"
#import "UIBarButtonItem+Theme.h"
#import "VLCAboutViewController.h"
#import "VLCPlaylistViewController.h"
#import "VLCBugreporter.h"

@interface VLCMenuTableViewController () <UITableViewDataSource, UITableViewDelegate>
{
    NSArray *_sectionHeaderTexts;
    NSArray *_menuItemsSectionOne;
    NSArray *_menuItemsSectionTwo;
    NSArray *_menuItemsSectionThree;

    UILabel *_uploadLocationLabel;
46
    UIButton *_uploadButton;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    Reachability *_reachability;
}

@property (nonatomic) VLCHTTPUploaderController *uploadController;
@property (nonatomic) VLCAppDelegate *appDelegate;
@property (nonatomic) GHRevealViewController *revealController;

@end

@implementation VLCMenuTableViewController

- (void)dealloc
{
    [_reachability stopNotifier];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.view.frame = CGRectMake(0.0f, 0.0f, kGHRevealSidebarWidth, CGRectGetHeight(self.view.bounds));
	self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;

Felix Paul Kühne's avatar
Felix Paul Kühne committed
71
    _sectionHeaderTexts = @[@"SECTION_HEADER_LIBRARY", @"SECTION_HEADER_NETWORK", @"Settings"];
72
    _menuItemsSectionOne = @[@"LIBRARY_ALL_FILES", @"LIBRARY_MUSIC", @"LIBRARY_SERIES"];
Carola's avatar
Carola committed
73
    _menuItemsSectionTwo = @[@"LOCAL_NETWORK", @"OPEN_NETWORK", @"DOWNLOAD_FROM_HTTP", @"WiFi Upload", @"Dropbox", @"Google Drive"];
74
75
    _menuItemsSectionThree = @[@"Settings", @"ABOUT_APP"];

76
77
    _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0.0f, 44.0f + 20.0f, kGHRevealSidebarWidth, CGRectGetHeight(self.view.bounds) - (44.0f + 20.0f)) style:UITableViewStylePlain];
    _tableView.delegate = self;
78
79
	_tableView.dataSource = self;
	_tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
Felix Paul Kühne's avatar
Felix Paul Kühne committed
80
	_tableView.backgroundColor = [UIColor colorWithRed:(43.0f/255.0f) green:(43.0f/255.0f) blue:(43.0f/255.0f) alpha:1.0f];
81
82
83
	_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    _tableView.rowHeight = [VLCWiFiUploadTableViewCell heightOfCell];

Felix Paul Kühne's avatar
Felix Paul Kühne committed
84
85
86
    self.view = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, kGHRevealSidebarWidth, CGRectGetHeight(self.view.bounds))];
    [self.view addSubview:_tableView];

Felix Paul Kühne's avatar
Felix Paul Kühne committed
87
    if (SYSTEM_RUNS_IOS7_OR_LATER) {
88
89
90
91
92
        UIView *brandingBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, kGHRevealSidebarWidth, 64.0f)];
        brandingBackgroundView.backgroundColor = [UIColor colorWithRed:0.1608 green:0.1608 blue:0.1608 alpha:1.0000];
        [self.view addSubview:brandingBackgroundView];
    } else {
        UIImageView *brandingBackgroundImageView;
93
        brandingBackgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 20.0f, kGHRevealSidebarWidth, 44.0f)];
94
95
96
97
        brandingBackgroundImageView.contentMode = UIViewContentModeScaleToFill;
        brandingBackgroundImageView.image = [UIImage imageNamed:@"headerSidebar"];
        [self.view addSubview:brandingBackgroundImageView];
    }
98
    UIImageView *brandingImageView;
99
    brandingImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, kGHRevealSidebarWidth, 44.0f + 40.0f)];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
100
101
102
103
104
    brandingImageView.contentMode = UIViewContentModeCenter;
    brandingImageView.image = [UIImage imageNamed:@"title"];
    [self.view addSubview:brandingImageView];

    [self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionTop];
105
106
107
108
109
110
111
112
113
114
115

    _reachability = [Reachability reachabilityForLocalWiFi];
    [_reachability startNotifier];

    [self netReachabilityChanged:nil];

    self.appDelegate = [[UIApplication sharedApplication] delegate];
    self.uploadController = self.appDelegate.uploadController;
    self.revealController = self.appDelegate.revealController;

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(netReachabilityChanged:) name:kReachabilityChangedNotification object:nil];
116
117
118
119

    BOOL isHTTPServerOn = [[NSUserDefaults standardUserDefaults] boolForKey:kVLCSettingSaveHTTPUploadServerStatus];
    [self.uploadController changeHTTPServerState:isHTTPServerOn];
    [self updateHTTPServerAddress];
120
121
122
123
}

- (void)viewWillAppear:(BOOL)animated {
	self.view.frame = CGRectMake(0.0f, 0.0f,kGHRevealSidebarWidth, CGRectGetHeight(self.view.bounds));
124
    [self netReachabilityChanged:nil];
125
126
127
128
129
}

- (void)netReachabilityChanged:(NSNotification *)notification
{
    if (_reachability.currentReachabilityStatus == ReachableViaWiFi) {
130
        _uploadButton.enabled = YES;
131
        [self updateHTTPServerAddress];
132
    } else {
133
        [_uploadButton setImage:[UIImage imageNamed:@"WifiUp"] forState:UIControlStateNormal];
134
        _uploadButton.enabled = NO;
135
        [_uploadButton setImage:[UIImage imageNamed:@"WiFiUp"] forState:UIControlStateDisabled];
136
        _uploadLocationLabel.text = NSLocalizedString(@"HTTP_UPLOAD_NO_CONNECTIVITY", @"");
137
        [self.uploadController changeHTTPServerState:NO];
138
139
140
    }
}

141
142
143
- (BOOL)shouldAutorotate
{
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
144
	return (orientation == UIInterfaceOrientationPortraitUpsideDown) ? (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) : YES;
145
146
147
148
149
150
151
152
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 3;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section == 0) // media
153
        return _menuItemsSectionOne.count;
154
    else if (section == 1) // network
155
        return _menuItemsSectionTwo.count;
156
    else if (section == 2) // settings & co
157
        return _menuItemsSectionThree.count;
158
159
160
161
162
163
164
165
    else
        return 0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"VLCMenuCell";
    static NSString *WiFiCellIdentifier = @"VLCMenuWiFiCell";

Felix Paul Kühne's avatar
Felix Paul Kühne committed
166
167
168
169
170
171
172
173
    NSString *rawTitle;
    NSUInteger section = indexPath.section;
    if (section == 0)
        rawTitle = _menuItemsSectionOne[indexPath.row];
    else if(section == 1)
        rawTitle = _menuItemsSectionTwo[indexPath.row];
    else if(section == 2)
        rawTitle = _menuItemsSectionThree[indexPath.row];
174
175
176

    UITableViewCell *cell;

Felix Paul Kühne's avatar
Felix Paul Kühne committed
177
    if ([rawTitle isEqualToString:@"WiFi Upload"]) {
178
179
180
181
        cell = (VLCWiFiUploadTableViewCell *)[tableView dequeueReusableCellWithIdentifier:WiFiCellIdentifier];
        if (cell == nil)
            cell = [VLCWiFiUploadTableViewCell cellWithReuseIdentifier:WiFiCellIdentifier];
    } else {
182
        cell = (VLCSidebarViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
183
        if (cell == nil)
184
            cell = [[VLCSidebarViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
185
186
    }

Felix Paul Kühne's avatar
Felix Paul Kühne committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
    if (section == 0) {
        if ([rawTitle isEqualToString:@"LIBRARY_ALL_FILES"])
            cell.imageView.image = [UIImage imageNamed:@"AllFiles"];
        else if ([rawTitle isEqualToString:@"LIBRARY_MUSIC"])
            cell.imageView.image = [UIImage imageNamed:@"MusicAlbums"];
        else if ([rawTitle isEqualToString:@"LIBRARY_SERIES"])
            cell.imageView.image = [UIImage imageNamed:@"TVShows"];
    } else if (section == 1) {
        if ([rawTitle isEqualToString:@"LOCAL_NETWORK"])
            cell.imageView.image = [UIImage imageNamed:@"Local"];
        else if ([rawTitle isEqualToString:@"OPEN_NETWORK"])
            cell.imageView.image = [UIImage imageNamed:@"OpenNetStream"];
        else if ([rawTitle isEqualToString:@"DOWNLOAD_FROM_HTTP"])
            cell.imageView.image = [UIImage imageNamed:@"Downloads"];
        else if ([rawTitle isEqualToString:@"Dropbox"]) {
            cell.textLabel.text = rawTitle;
            cell.imageView.image = [UIImage imageNamed:@"Dropbox"];
Carola's avatar
Carola committed
204
205
206
        } else if ([rawTitle isEqualToString:@"Google Drive"]) {
            cell.textLabel.text = rawTitle;
            cell.imageView.image = [UIImage imageNamed:@"Drive"];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
207
208
209
210
211
212
213
214
215
216
217
218
219
220
        } else if ([rawTitle isEqualToString:@"WiFi Upload"]) {
            _uploadLocationLabel = [(VLCWiFiUploadTableViewCell*)cell uploadAddressLabel];
            _uploadButton = [(VLCWiFiUploadTableViewCell*)cell serverOnButton];
            [_uploadButton addTarget:self action:@selector(toggleHTTPServer:) forControlEvents:UIControlEventTouchUpInside];
        }
    } else if (section == 2) {
        if ([rawTitle isEqualToString:@"Settings"])
            cell.imageView.image = [UIImage imageNamed:@"Settings"];
        else
            cell.imageView.image = [UIImage imageNamed:@"About"];
    }

    if (!([rawTitle isEqualToString:@"Dropbox"] || [rawTitle isEqualToString:@"WiFi Upload"]))
        cell.textLabel.text = NSLocalizedString(rawTitle, @"");
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239

    return cell;
}

#pragma mark - tv delegate
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    if (section < 3)
        return 21.f;
    return 0.;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
	NSObject *headerText = NSLocalizedString(_sectionHeaderTexts[section], @"");
	UIView *headerView = nil;
	if (headerText != [NSNull null]) {
		headerView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, [UIScreen mainScreen].bounds.size.height, 21.0f)];
		CAGradientLayer *gradient = [CAGradientLayer layer];
		gradient.frame = headerView.bounds;
		gradient.colors = @[
Felix Paul Kühne's avatar
Felix Paul Kühne committed
240
241
                      (id)[UIColor colorWithRed:(66.0f/255.0f) green:(66.0f/255.0f) blue:(66.0f/255.0f) alpha:1.0f].CGColor,
                      (id)[UIColor colorWithRed:(56.0f/255.0f) green:(56.0f/255.0f) blue:(56.0f/255.0f) alpha:1.0f].CGColor,
242
243
244
245
246
247
248
249
                      ];
		[headerView.layer insertSublayer:gradient atIndex:0];

		UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectInset(headerView.bounds, 12.0f, 5.0f)];
		textLabel.text = (NSString *) headerText;
		textLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:([UIFont systemFontSize] * 0.8f)];
		textLabel.shadowOffset = CGSizeMake(0.0f, 1.0f);
		textLabel.shadowColor = [UIColor colorWithWhite:0.0f alpha:0.25f];
250
		textLabel.textColor = [UIColor colorWithRed:(118.0f/255.0f) green:(118.0f/255.0f) blue:(118.0f/255.0f) alpha:1.0f];
251
252
253
254
		textLabel.backgroundColor = [UIColor clearColor];
		[headerView addSubview:textLabel];

		UIView *topLine = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, [UIScreen mainScreen].bounds.size.height, 1.0f)];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
255
		topLine.backgroundColor = [UIColor colorWithRed:(95.0f/255.0f) green:(95.0f/255.0f) blue:(95.0f/255.0f) alpha:1.0f];
256
257
258
		[headerView addSubview:topLine];

		UIView *bottomLine = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 21.0f, [UIScreen mainScreen].bounds.size.height, 1.0f)];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
259
		bottomLine.backgroundColor = [UIColor colorWithRed:(16.0f/255.0f) green:(16.0f/255.0f) blue:(16.0f/255.0f) alpha:1.0f];
260
261
262
263
264
265
266
267
268
269
		[headerView addSubview:bottomLine];
	}
	return headerView;
}

#pragma mark - menu implementation

- (void)updateHTTPServerAddress
{
    HTTPServer *server = self.uploadController.httpServer;
270
271
272
273
274
    if (server.isRunning) {
        if (server.listeningPort != 80)
            _uploadLocationLabel.text = [NSString stringWithFormat:@"http://%@:%i", [self.uploadController currentIPAddress], server.listeningPort];
        else
            _uploadLocationLabel.text = [NSString stringWithFormat:@"http://%@", [self.uploadController currentIPAddress]];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
275
        [_uploadButton setImage:[UIImage imageNamed:@"WifiUpOn"] forState:UIControlStateNormal];
276
    } else {
277
        _uploadLocationLabel.text = NSLocalizedString(@"HTTP_UPLOAD_SERVER_OFF", @"");
Felix Paul Kühne's avatar
Felix Paul Kühne committed
278
        [_uploadButton setImage:[UIImage imageNamed:@"WifiUp"] forState:UIControlStateNormal];
279
    }
280
281
}

282
- (IBAction)toggleHTTPServer:(UIButton *)sender
283
{
284
285
    if (_uploadButton.enabled) {
        BOOL futureHTTPServerState = ![[NSUserDefaults standardUserDefaults] boolForKey:kVLCSettingSaveHTTPUploadServerStatus];
286

287
288
289
290
291
        [[NSUserDefaults standardUserDefaults] setBool:futureHTTPServerState forKey:kVLCSettingSaveHTTPUploadServerStatus];
        [self.uploadController changeHTTPServerState:futureHTTPServerState];
        [self updateHTTPServerAddress];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
292
293
294
295
296
297
298
299
300
301
302
}

- (void)_revealItem:(NSUInteger)itemIndex inSection:(NSUInteger)sectionNumber
{
    UIViewController *viewController;
    if (sectionNumber == 1) {
        if (itemIndex == 0)
            viewController = [[VLCLocalServerListViewController alloc] init];
        else if (itemIndex == 1)
            viewController = [[VLCOpenNetworkStreamViewController alloc] init];
        else if (itemIndex == 2)
303
            viewController = self.appDelegate.downloadViewController;
304
305
        else if (itemIndex == 3)
            [self toggleHTTPServer:nil];
306
307
        else if (itemIndex == 4)
            viewController = self.appDelegate.dropboxTableViewController;
Carola's avatar
Carola committed
308
309
        else if (itemIndex == 5)
            viewController = self.appDelegate.googleDriveTableViewController;
310
311
312
313
314
315
316
317
    } else if (sectionNumber == 2) {
        if (itemIndex == 0) {
            if (!self.settingsController)
                self.settingsController = [[VLCSettingsController alloc] init];

            if (!self.settingsViewController) {
                self.settingsViewController = [[IASKAppSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped];
                self.settingsController.viewController = self.settingsViewController;
318
                self.settingsViewController.navigationItem.leftBarButtonItem = [UIBarButtonItem themedRevealMenuButtonWithTarget:self.settingsController.viewController andSelector:@selector(dismiss:)];
319
320
321
322
323
324
325
326
327
328
            }

            self.settingsViewController.modalPresentationStyle = UIModalPresentationFormSheet;
            self.settingsViewController.delegate = self.settingsController;
            self.settingsViewController.showDoneButton = NO;
            self.settingsViewController.showCreditsFooter = NO;

            viewController = self.settingsController.viewController;
        } else if (itemIndex == 1)
            viewController = [[VLCAboutViewController alloc] init];
329
    } else {
330
        viewController = self.appDelegate.playlistViewController;
331
332
        [self.appDelegate.playlistViewController setLibraryMode:itemIndex];
    }
333
334
335
336

    if (!viewController)
        return;

337
338
339
340
341
342
343
344
345
346
    UINavigationController *navCon = nil;
    if ([_revealController.contentViewController isKindOfClass:[UINavigationController class]]) {
        navCon = (UINavigationController*)_revealController.contentViewController;
        navCon.viewControllers = @[viewController];
    } else {
        navCon = [[UINavigationController alloc] initWithRootViewController:viewController];
        [navCon loadTheme];

        _revealController.contentViewController = navCon;
    }
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375

	[_revealController toggleSidebar:NO duration:kGHRevealSidebarDefaultAnimationDuration];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
	[self _revealItem:indexPath.row inSection:indexPath.section];
}

#pragma mark Public Methods
- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition {
	[self.tableView selectRowAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition];
	if (scrollPosition == UITableViewScrollPositionNone)
		[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated];

    [self _revealItem:indexPath.row inSection:indexPath.section];
}

#pragma mark - shake to support

- (BOOL)canBecomeFirstResponder {
    return YES;
}

- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
    if (motion == UIEventSubtypeMotionShake)
        [[VLCBugreporter sharedInstance] handleBugreportRequest];
}

@end