VLCSettingsController.m 9.35 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*****************************************************************************
 * VLCSettingsController.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>
 *          Carola Nitz <nitz.carola # googlemail.com>
 *
 * Refer to the COPYING file of the official project for license.
 *****************************************************************************/
Felix Paul Kühne's avatar
Felix Paul Kühne committed
14

15
#import "VLCSettingsController.h"
16
#import "IASKSettingsReader.h"
17
#import "PAPasscodeViewController.h"
18
#import <LocalAuthentication/LocalAuthentication.h>
19
#import "VLC-Swift.h"
20

21 22
NSString * const kVLCSectionTableHeaderViewIdentifier = @"VLCSectionTableHeaderViewIdentifier";

23
@interface VLCSettingsController ()<PAPasscodeViewControllerDelegate>
24 25 26 27
{
    VLCActionSheet *actionSheet;
    VLCSettingsSpecifierManager *specifierManager;
}
28 29
@end

30
@implementation VLCSettingsController
Felix Paul Kühne's avatar
Felix Paul Kühne committed
31

32
- (instancetype)initWithStyle:(UITableViewStyle)style
Felix Paul Kühne's avatar
Felix Paul Kühne committed
33
{
34 35
    self = [super initWithStyle:style];
    if (self) {
36
        [self setupUI];
37
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(settingDidChange:) name:kIASKAppSettingChanged object:nil];
38
    }
39

Felix Paul Kühne's avatar
Felix Paul Kühne committed
40 41 42
    return self;
}

43 44 45 46 47 48 49 50 51
- (void)setupUI
{
    self.title = NSLocalizedString(@"Settings", nil);
    self.tabBarItem = [[UITabBarItem alloc] initWithTitle: NSLocalizedString(@"Settings", nil)
                                                    image: [UIImage imageNamed:@"Settings"]
                                            selectedImage: [UIImage imageNamed:@"Settings"]];
    self.tabBarItem.accessibilityIdentifier = VLCAccessibilityIdentifier.settings;
}

52
- (void)viewDidLoad
Felix Paul Kühne's avatar
Felix Paul Kühne committed
53
{
54 55
    [super viewDidLoad];

56 57 58 59
    self.modalPresentationStyle = UIModalPresentationFormSheet;
    self.delegate = self;
    self.showDoneButton = NO;
    self.showCreditsFooter = NO;
60 61 62
    
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"BUTTON_ABOUT", nil) style:UIBarButtonItemStylePlain target:self action:@selector(showAbout)];
    self.navigationItem.leftBarButtonItem.accessibilityIdentifier = VLCAccessibilityIdentifier.about;
63

64
    self.neverShowPrivacySettings = YES;
65
    self.tableView.rowHeight = UITableViewAutomaticDimension;
66
    self.tableView.estimatedRowHeight = 100;
67 68
    self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
    self.tableView.estimatedSectionHeaderHeight = 64;
69
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
70
    [self.tableView registerClass:[VLCSectionTableHeaderView class] forHeaderFooterViewReuseIdentifier:kVLCSectionTableHeaderViewIdentifier];
71
    [self themeDidChange];
72 73 74 75 76 77
    
    actionSheet = [[VLCActionSheet alloc] init];
    actionSheet.modalPresentationStyle = UIModalPresentationCustom;
    [actionSheet.collectionView registerClass:[VLCSettingsSheetCell class] forCellWithReuseIdentifier:VLCSettingsSheetCell.identifier];
    
    specifierManager = [[VLCSettingsSpecifierManager alloc] initWithSettingsReader:self.settingsReader settingsStore:self.settingsStore];
78 79 80 81
}

- (void)themeDidChange
{
82
    self.view.backgroundColor = PresentationTheme.current.colors.background;
83
    [self setNeedsStatusBarAppearanceUpdate];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
84 85
}

86
- (void)viewWillAppear:(BOOL)animated
87
{
88
    [super viewWillAppear:animated];
89 90 91
    [self filterCellsWithAnimation:NO];
}

92 93 94 95 96
- (UIStatusBarStyle)preferredStatusBarStyle
{
    return PresentationTheme.current.colors.statusBarStyle;
}

97 98
- (NSSet *)hiddenBiometryKeys
{
99
    if (@available(iOS 11.0.1, *)) {
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
        LAContext *laContext = [[LAContext alloc] init];
        if ([laContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:nil]) {
            switch (laContext.biometryType) {
                case LABiometryTypeFaceID:
                    return [NSSet setWithObject:kVLCSettingPasscodeAllowTouchID];
                case LABiometryTypeTouchID:
                    return [NSSet setWithObject:kVLCSettingPasscodeAllowFaceID];
                case LABiometryNone:
                    return [NSSet setWithObjects:kVLCSettingPasscodeAllowFaceID, kVLCSettingPasscodeAllowTouchID, nil];
            }
        }
        return [NSSet setWithObjects:kVLCSettingPasscodeAllowFaceID, kVLCSettingPasscodeAllowTouchID, nil];
    }
    return [NSSet setWithObject:kVLCSettingPasscodeAllowFaceID];
}

116 117 118
- (void)filterCellsWithAnimation:(BOOL)shouldAnimate
{
    NSMutableSet *hideKeys = [[NSMutableSet alloc] init];
119
    if (![VLCKeychainCoordinator passcodeLockEnabled]) {
120
        [hideKeys addObject:kVLCSettingPasscodeAllowTouchID];
121 122 123 124 125
        [hideKeys addObject:kVLCSettingPasscodeAllowFaceID];
        [self setHiddenKeys:hideKeys animated:shouldAnimate];
        return;
    }
    [self setHiddenKeys:[self hiddenBiometryKeys] animated:shouldAnimate];
126 127
}

128
- (void)settingDidChange:(NSNotification*)notification
129
{
130
    if ([notification.object isEqual:kVLCSettingPasscodeOnKey]) {
131
        BOOL passcodeOn = [[notification.userInfo objectForKey:kVLCSettingPasscodeOnKey] boolValue];
132

133 134 135
        if (passcodeOn) {
            PAPasscodeViewController *passcodeLockController = [[PAPasscodeViewController alloc] initForAction:PasscodeActionSet];
            passcodeLockController.delegate = self;
136
            [self presentViewController:passcodeLockController animated:YES completion:nil];
137
        } else {
138
            [self updateForPasscode:nil];
139 140
        }
    }
141 142 143 144 145
    if ([notification.object isEqual:kVLCSettingAppTheme]) {
        BOOL darkTheme = [[notification.userInfo objectForKey:kVLCSettingAppTheme] boolValue];
        PresentationTheme.current = darkTheme ? PresentationTheme.darkTheme : PresentationTheme.brightTheme;
        [self themeDidChange];
    }
146 147
}

148
- (void)updateUIAndCoreSpotlightForPasscodeSetting:(BOOL)passcodeOn
149 150 151
{
    [self filterCellsWithAnimation:YES];

152 153
    [[MLMediaLibrary sharedMediaLibrary] setSpotlightIndexingEnabled:!passcodeOn];
    if (passcodeOn) {
154 155 156 157 158
        // delete whole index for VLC
        [[CSSearchableIndex defaultSearchableIndex] deleteAllSearchableItemsWithCompletionHandler:nil];
    }
}

159
- (void)showAbout
160 161
{
    VLCAboutViewController *aboutVC = [[VLCAboutViewController alloc] init];
162 163
    UINavigationController *modalNavigationController = [[UINavigationController alloc] initWithRootViewController:aboutVC];
    [self presentViewController:modalNavigationController animated:YES completion:nil];
164
}
165

166 167 168 169
#pragma mark - PAPasscode delegate

- (void)PAPasscodeViewControllerDidCancel:(PAPasscodeViewController *)controller
{
170
    [self updateForPasscode:nil];
171 172 173 174
}

- (void)PAPasscodeViewControllerDidSetPasscode:(PAPasscodeViewController *)controller
{
175
    [self updateForPasscode:controller.passcode];
176 177
}

178 179
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
180 181 182
    IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath];
    VLCSettingsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:specifier.type];
    if (!cell) {
183
        cell = [[VLCSettingsTableViewCell alloc] initWithReuseIdentifier:specifier.type target:self];
184
    }
185
    [cell configureWithSpecifier:specifier settingsValue:[self.settingsStore objectForKey:specifier.key]];
186 187 188
    return cell;
}

189 190
- (void)updateForPasscode:(NSString *)passcode
{
191 192 193 194 195 196 197 198
    NSError *error = nil;
    [VLCKeychainCoordinator setPasscodeWithPasscode:passcode error:&error];
    if (error == nil) {
        if (passcode == nil) {
            //Set manually the value to NO to disable the UISwitch.
            [[NSUserDefaults standardUserDefaults] setBool:NO forKey:kVLCSettingPasscodeOnKey];
        }
        [self updateUIAndCoreSpotlightForPasscodeSetting:passcode != nil];
199 200 201 202 203
    }
    if ([self.navigationController.presentedViewController isKindOfClass:[PAPasscodeViewController class]]) {
        [self.navigationController.presentedViewController dismissViewControllerAnimated:YES completion:nil];
    }
}
204

205 206 207 208 209 210 211 212
#pragma mark - InAppSettings customization

- (UIView *)settingsViewController:(id<IASKViewController>)settingsViewController tableView:(UITableView *)tableView viewForHeaderForSection:(NSInteger)section
{
    if (section == 0) {
        return nil;
    }
    VLCSectionTableHeaderView *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:kVLCSectionTableHeaderViewIdentifier];
213
    header.label.text = [self.settingsReader titleForSection:section];
214 215 216
    return header;
}

217 218 219 220 221 222 223 224 225 226 227 228
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath];

    if ([specifier.type isEqualToString: kIASKPSMultiValueSpecifier]) {
        [self displayActionSheetFor:specifier];
    } else {
        [super tableView:tableView didSelectRowAtIndexPath:indexPath];
    }
}

229 230 231 232 233
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return nil;
}

234 235 236 237 238 239 240 241 242 243 244
- (void)displayActionSheetFor:(IASKSpecifier *)specifier
{
    specifierManager.specifier = specifier;
    actionSheet.delegate = specifierManager;
    actionSheet.dataSource = specifierManager;
    
    [self presentViewController:actionSheet animated:YES completion:^{
        [self->actionSheet.collectionView selectItemAtIndexPath:self->specifierManager.selectedIndex animated:NO scrollPosition:UICollectionViewScrollPositionCenteredVertically];
    }];
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
245
@end