VLCServerBrowsingTVViewController.m 8.51 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/*****************************************************************************
 * VLC for iOS
 *****************************************************************************
 * Copyright (c) 2015 VideoLAN. All rights reserved.
 * $Id$
 *
 * Authors: Tobias Conradi <videolan # tobias-conradi.de>
 *
 * Refer to the COPYING file of the official project for license.
 *****************************************************************************/
11

12
#import "VLCServerBrowsingTVViewController.h"
13
#import "VLCRemoteBrowsingTVCell.h"
14 15
#import "VLCPlayerDisplayController.h"
#import "VLCPlaybackController.h"
16
#import "VLCServerBrowsingController.h"
17
#import "VLCMaskView.h"
18
#import "GRKArrayDiff+UICollectionView.h"
19

20
@interface VLCServerBrowsingTVViewController ()
21 22
{
    UILabel *_nothingFoundLabel;
23 24
    NSIndexPath *_currentFocus;
    BOOL _focusChangeAllowed;
25
}
26
@property (nonatomic) VLCServerBrowsingController *browsingController;
27
@property (nonatomic) NSArray<id <VLCNetworkServerBrowserItem>> *items;
28 29
@end

30
@implementation VLCServerBrowsingTVViewController
31
@synthesize subdirectoryBrowserClass = _subdirectoryBrowserClass;
32 33 34

- (instancetype)initWithServerBrowser:(id<VLCNetworkServerBrowser>)serverBrowser
{
35
    self = [super initWithNibName:@"VLCRemoteBrowsingCollectionViewController" bundle:nil];
36 37 38
    if (self) {
        _serverBrowser = serverBrowser;
        serverBrowser.delegate = self;
39 40 41

        _browsingController = [[VLCServerBrowsingController alloc] initWithViewController:self serverBrowser:serverBrowser];

42
        self.title = serverBrowser.title;
43 44

        self.downloadArtwork = [[NSUserDefaults standardUserDefaults] boolForKey:kVLCSettingDownloadArtwork];
45 46 47

        _currentFocus = [NSIndexPath indexPathForRow:0 inSection:0];
        _focusChangeAllowed = YES;
48 49 50 51
    }
    return self;
}

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
- (void)viewDidLoad
{
    [super viewDidLoad];

    self.nothingFoundLabel.text = NSLocalizedString(@"FOLDER_EMPTY", nil);
    [self.nothingFoundLabel sizeToFit];
    UIView *nothingFoundView = self.nothingFoundView;
    [nothingFoundView sizeToFit];
    [nothingFoundView setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self.view addSubview:nothingFoundView];

    NSLayoutConstraint *yConstraint = [NSLayoutConstraint constraintWithItem:nothingFoundView
                                                                   attribute:NSLayoutAttributeCenterY
                                                                   relatedBy:NSLayoutRelationEqual
                                                                      toItem:self.view
                                                                   attribute:NSLayoutAttributeCenterY
                                                                  multiplier:1.0
                                                                    constant:0.0];
    [self.view addConstraint:yConstraint];
    NSLayoutConstraint *xConstraint = [NSLayoutConstraint constraintWithItem:nothingFoundView
                                                                   attribute:NSLayoutAttributeCenterX
                                                                   relatedBy:NSLayoutRelationEqual
                                                                      toItem:self.view
                                                                   attribute:NSLayoutAttributeCenterX
                                                                  multiplier:1.0
                                                                    constant:0.0];
    [self.view addConstraint:xConstraint];
}

81 82
- (void)viewDidAppear:(BOOL)animated
{
83 84 85 86
    [super viewDidAppear:animated];
    [self.serverBrowser update];
}

87 88 89 90 91 92 93 94 95 96 97
- (void)setSubdirectoryBrowserClass:(Class)subdirectoryBrowserClass
{
    NSParameterAssert([subdirectoryBrowserClass isSubclassOfClass:[VLCServerBrowsingTVViewController class]]);
    _subdirectoryBrowserClass = subdirectoryBrowserClass;
}

- (Class)subdirectoryBrowserClass
{
    return _subdirectoryBrowserClass ?: [self class];
}

98 99
#pragma mark -

100 101
- (void)reloadData
{
Tobias's avatar
Tobias committed
102 103 104
    [self.serverBrowser update];
}

105
#pragma mark - VLCNetworkServerBrowserDelegate
Tobias's avatar
Tobias committed
106

107 108
- (void)networkServerBrowserDidUpdate:(id<VLCNetworkServerBrowser>)networkBrowser
{
109
    self.title = networkBrowser.title;
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126

    NSArray *oldItems = self.items;
    NSArray *newItems = networkBrowser.items;
    GRKArrayDiff *diff = [[GRKArrayDiff alloc] initWithPreviousArray:oldItems
                                                        currentArray:newItems
                                                       identityBlock:^NSString * _Nullable(id <VLCNetworkServerBrowserItem> item) {
                                                           return [NSString stringWithFormat:@"%@#%@",item.URL.absoluteString ?: @"", item.name];
                                                       }
                                                       modifiedBlock:nil];

    [diff performBatchUpdatesWithCollectionView:self.collectionView
                                        section:0
                               dataSourceUpdate:^{
                                   self.items = newItems;
                               } completion:nil];

    _nothingFoundLabel.hidden = self.items.count > 0;
127 128 129 130
}

- (void)networkServerBrowser:(id<VLCNetworkServerBrowser>)networkBrowser requestDidFailWithError:(NSError *)error {

131 132 133
    [self vlc_showAlertWithTitle:NSLocalizedString(@"LOCAL_SERVER_CONNECTION_FAILED_TITLE", nil)
                         message:NSLocalizedString(@"LOCAL_SERVER_CONNECTION_FAILED_MESSAGE", nil)
                     buttonTitle:NSLocalizedString(@"BUTTON_CANCEL", nil)];
134 135 136
}

#pragma mark -
137 138 139 140

- (void)didSelectItem:(id<VLCNetworkServerBrowserItem>)item index:(NSUInteger)index singlePlayback:(BOOL)singlePlayback
{
    if (item.isContainer) {
141 142
        VLCServerBrowsingTVViewController *targetViewController = [[self.subdirectoryBrowserClass alloc] initWithServerBrowser:item.containerBrowser];
        [self showViewController:targetViewController sender:self];
143 144 145 146 147 148 149 150
    } else {
        if (singlePlayback) {
            [self.browsingController streamFileForItem:item];
        } else {
            VLCMediaList *mediaList = self.serverBrowser.mediaList;
            [self.browsingController configureSubtitlesInMediaList:mediaList];
            [self.browsingController streamMediaList:mediaList startingAtIndex:index];
        }
151 152 153 154
    }
}


155 156 157 158
#pragma mark - collection view data source

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
159
    NSInteger count = self.items.count;
160 161
    self.nothingFoundView.hidden = count > 0;
    return count;
162 163
}

164 165
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
166
    NSArray *items = self.items;
167 168 169
    NSInteger row = indexPath.row;
    if (row < items.count) {
        id<VLCNetworkServerBrowserItem> item = items[row];
170

171
        if ([cell isKindOfClass:[VLCRemoteBrowsingTVCell class]]) {
172 173 174
            ((VLCRemoteBrowsingTVCell *) cell).downloadArtwork = self.downloadArtwork;
        }

175 176 177
        if ([cell conformsToProtocol:@protocol(VLCRemoteBrowsingCell)]) {
            [self.browsingController configureCell:(id<VLCRemoteBrowsingCell>)cell withItem:item];
        }
178 179 180 181 182
    }
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
183
    NSInteger row = indexPath.row;
184
    id<VLCNetworkServerBrowserItem> item = self.items[row];
185

186 187
    // would make sence if item came from search which isn't
    // currently the case on the TV
188
    const BOOL singlePlayback = ![[NSUserDefaults standardUserDefaults] boolForKey:kVLCAutomaticallyPlayNextItem];
189
    [self didSelectItem:item index:row singlePlayback:singlePlayback];
190 191
}

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
#pragma mark - focus recovery workaround

- (void)collectionView:(UICollectionView *)collectionView didUpdateFocusInContext:(UICollectionViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
{
    if (context.previouslyFocusedIndexPath == nil && context.nextFocusedIndexPath != nil)
        [self setNeedsFocusUpdate];

    if (context.previouslyFocusedIndexPath != nil && context.nextFocusedIndexPath != nil)
        _currentFocus = context.nextFocusedIndexPath;

    _focusChangeAllowed = context.nextFocusedIndexPath != nil;
}

- (BOOL)collectionView:(UICollectionView *)collectionView canFocusItemAtIndexPath:(NSIndexPath *)indexPath
{
    return _focusChangeAllowed || [_currentFocus compare:indexPath] == NSOrderedSame;
}

- (NSIndexPath *)indexPathForPreferredFocusedViewInCollectionView:(UICollectionView *)collectionView
{
    return _currentFocus;
}

215
@end