ソースを参照

replace server browsing table view with collection view

Tobias Conradi 9 年 前
コミット
6dfb787fe0

+ 14 - 0
SharedSources/UI Elements/VLCMaskView.h

@@ -0,0 +1,14 @@
+//
+//  VLCMaskView.h
+//  VLC for iOS
+//
+//  Created by Tobias Conradi on 07.11.15.
+//  Copyright © 2015 VideoLAN. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface VLCMaskView : UIView
+@property (nonatomic) CGFloat maskStart;
+@property (nonatomic) CGFloat maskEnd;
+@end

+ 76 - 0
SharedSources/UI Elements/VLCMaskView.m

@@ -0,0 +1,76 @@
+//
+//  VLCMaskView.m
+//  VLC for iOS
+//
+//  Created by Tobias Conradi on 07.11.15.
+//  Copyright © 2015 VideoLAN. All rights reserved.
+//
+
+#import "VLCMaskView.h"
+#import <QuartzCore/QuartzCore.h>
+
+@interface VLCMaskView()
+@property (nonatomic) CAGradientLayer *gradientLayer;
+@end
+
+@implementation VLCMaskView
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+    if (self) {
+        [self.layer addSublayer:self.gradientLayer];
+        [self updateGradientLayer];
+    }
+    return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder
+{
+    self = [super initWithCoder:aDecoder];
+    if (self) {
+        [self.layer addSublayer:self.gradientLayer];
+        [self updateGradientLayer];
+    }
+    return self;
+}
+
+- (void)layoutSubviews
+{
+    [super layoutSubviews];
+    [self updateGradientLayer];
+}
+
+- (void)updateGradientLayer
+{
+    CGSize size = self.bounds.size;
+    CGFloat height = size.height;
+
+    self.gradientLayer.frame = CGRectMake(0, 0, size.width, height);
+    self.gradientLayer.locations = @[@(self.maskEnd / height), @(self.maskStart / height)];
+}
+
+
+#pragma mark - Properties
+
+- (CAGradientLayer *)gradientLayer
+{
+    if (!_gradientLayer) {
+        _gradientLayer = [CAGradientLayer layer];
+        _gradientLayer.colors = @[(id)[UIColor colorWithWhite:0.0 alpha:0.0].CGColor, (id)[UIColor colorWithWhite:0.0 alpha:1.0].CGColor];
+    }
+    return _gradientLayer;
+}
+
+- (void)setMaskStart:(CGFloat)maskStart
+{
+    _maskStart = maskStart;
+    [self updateGradientLayer];
+}
+
+- (void)setMaskEnd:(CGFloat)maskEnd
+{
+    _maskEnd = maskEnd;
+    [self updateGradientLayer];
+}
+@end

+ 1 - 1
VLC for Apple TV/VLCServerBrowsingTVCell.h

@@ -15,7 +15,7 @@
 
 extern NSString *const VLCServerBrowsingTVCellIdentifier;
 
-@interface VLCServerBrowsingTVCell : UITableViewCell <VLCServerBrowsingCell>
+@interface VLCServerBrowsingTVCell : UICollectionViewCell <VLCServerBrowsingCell>
 
 @property (nonatomic, weak) IBOutlet VLCNetworkImageView *thumbnailImageView;
 @property (nonatomic, weak) IBOutlet UILabel *titleLabel;

+ 11 - 4
VLC for Apple TV/VLCServerBrowsingTVCell.m

@@ -18,15 +18,13 @@ NSString *const VLCServerBrowsingTVCellIdentifier = @"VLCServerBrowsingTVCell";
 {
     MDFMovieDBFetcher *_metadataFetcher;
 }
+@property (nonatomic) IBOutlet NSLayoutConstraint *aspectRationConstraint;
+
 @end
 
 @implementation VLCServerBrowsingTVCell
 @synthesize thumbnailURL = _thumbnailURL, isDirectory = _isDirectory;
 
-- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
-{
-    return [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
-}
 
 
 - (void)awakeFromNib
@@ -96,6 +94,15 @@ NSString *const VLCServerBrowsingTVCellIdentifier = @"VLCServerBrowsingTVCell";
     return self.subtitleLabel.text;
 }
 
+- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
+{
+    [coordinator addCoordinatedAnimations:^{
+        self.transform = self.focused ? CGAffineTransformMakeScale(1.3, 1.3): CGAffineTransformIdentity;
+    } completion:nil];
+}
+
+#pragma mark - MDFMovieDB
+
 - (void)MDFMovieDBFetcher:(MDFMovieDBFetcher *)aFetcher didFindMovie:(MDFMovie *)details forSearchRequest:(NSString *)searchRequest
 {
     if (details == nil)

+ 39 - 39
VLC for Apple TV/VLCServerBrowsingTVCell.xib

@@ -2,63 +2,63 @@
 <document type="com.apple.InterfaceBuilder.AppleTV.XIB" version="3.0" toolsVersion="9059" systemVersion="15B42" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES">
     <dependencies>
         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
-        <capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
-        <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
     </dependencies>
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="150" id="Tcc-PQ-zMX" customClass="VLCServerBrowsingTVCell">
-            <rect key="frame" x="0.0" y="0.0" width="1920" height="150"/>
-            <autoresizingMask key="autoresizingMask"/>
-            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Tcc-PQ-zMX" id="Ygk-DT-1Ta">
-                <rect key="frame" x="0.0" y="0.0" width="1904" height="150"/>
+        <collectionViewCell opaque="NO" multipleTouchEnabled="YES" contentMode="center" id="Q7n-Zw-Frg" customClass="VLCServerBrowsingTVCell">
+            <rect key="frame" x="0.0" y="0.0" width="300" height="300"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
+                <rect key="frame" x="0.0" y="0.0" width="300" height="300"/>
                 <autoresizingMask key="autoresizingMask"/>
                 <subviews>
-                    <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Diw-kq-1Zk" customClass="VLCNetworkImageView">
-                        <rect key="frame" x="8" y="8" width="238" height="134"/>
+                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="h3U-B3-AOa">
+                        <rect key="frame" x="8" y="202" width="284" height="30"/>
                         <animations/>
-                        <constraints>
-                            <constraint firstAttribute="width" secondItem="Diw-kq-1Zk" secondAttribute="height" multiplier="16:9" id="y1w-5g-IDp"/>
-                        </constraints>
-                    </imageView>
-                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TIO-jK-60o" userLabel="TitleLabel">
-                        <rect key="frame" x="254" y="52" width="1658" height="46"/>
-                        <animations/>
-                        <fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
+                        <fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
                         <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
                         <nil key="highlightedColor"/>
                     </label>
-                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="300" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4q6-BG-uo0" userLabel="SubtitleLabel">
-                        <rect key="frame" x="254" y="112" width="1658" height="30"/>
+                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="I51-60-pwl">
+                        <rect key="frame" x="8" y="240" width="284" height="35"/>
                         <animations/>
-                        <fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
+                        <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/>
                         <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
                         <nil key="highlightedColor"/>
                     </label>
+                    <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" placeholderIntrinsicWidth="300" placeholderIntrinsicHeight="169" translatesAutoresizingMaskIntoConstraints="NO" id="tHQ-sR-zn4" customClass="VLCNetworkImageView">
+                        <rect key="frame" x="0.0" y="13" width="300" height="169"/>
+                        <animations/>
+                    </imageView>
                 </subviews>
                 <animations/>
-                <constraints>
-                    <constraint firstItem="4q6-BG-uo0" firstAttribute="top" relation="greaterThanOrEqual" secondItem="TIO-jK-60o" secondAttribute="bottom" id="0Cw-Zg-YdT"/>
-                    <constraint firstItem="4q6-BG-uo0" firstAttribute="leading" secondItem="Diw-kq-1Zk" secondAttribute="trailing" constant="8" symbolic="YES" id="4JT-bL-xgJ"/>
-                    <constraint firstItem="TIO-jK-60o" firstAttribute="centerY" secondItem="Ygk-DT-1Ta" secondAttribute="centerY" priority="250" id="6mH-XN-FhD"/>
-                    <constraint firstAttribute="trailingMargin" secondItem="4q6-BG-uo0" secondAttribute="trailing" id="D8M-Ob-ojk"/>
-                    <constraint firstItem="TIO-jK-60o" firstAttribute="top" relation="greaterThanOrEqual" secondItem="Ygk-DT-1Ta" secondAttribute="topMargin" id="PdB-cs-3vU"/>
-                    <constraint firstItem="TIO-jK-60o" firstAttribute="leading" secondItem="Diw-kq-1Zk" secondAttribute="trailing" constant="8" symbolic="YES" id="Tbh-RC-OQm"/>
-                    <constraint firstAttribute="bottomMargin" secondItem="Diw-kq-1Zk" secondAttribute="bottom" id="VIf-rD-KS8"/>
-                    <constraint firstItem="Diw-kq-1Zk" firstAttribute="leading" secondItem="Ygk-DT-1Ta" secondAttribute="leadingMargin" id="Z1h-4m-nw8"/>
-                    <constraint firstAttribute="trailingMargin" secondItem="TIO-jK-60o" secondAttribute="trailing" id="dcO-hV-zoC"/>
-                    <constraint firstItem="4q6-BG-uo0" firstAttribute="bottom" secondItem="Ygk-DT-1Ta" secondAttribute="bottomMargin" id="fxP-Kg-4vy"/>
-                    <constraint firstItem="Diw-kq-1Zk" firstAttribute="top" secondItem="Ygk-DT-1Ta" secondAttribute="topMargin" id="mfh-x3-2Cc"/>
-                </constraints>
-            </tableViewCellContentView>
+                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
+            </view>
             <animations/>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="h3U-B3-AOa" secondAttribute="trailing" constant="8" id="Ge1-kn-QhB"/>
+                <constraint firstItem="I51-60-pwl" firstAttribute="leading" secondItem="Q7n-Zw-Frg" secondAttribute="leading" constant="8" id="H8p-nC-etm"/>
+                <constraint firstItem="h3U-B3-AOa" firstAttribute="centerX" secondItem="Q7n-Zw-Frg" secondAttribute="centerX" id="Ju6-jJ-msL"/>
+                <constraint firstItem="h3U-B3-AOa" firstAttribute="top" secondItem="tHQ-sR-zn4" secondAttribute="bottom" constant="20" id="LuX-cK-Eln"/>
+                <constraint firstItem="h3U-B3-AOa" firstAttribute="centerY" secondItem="Q7n-Zw-Frg" secondAttribute="centerY" constant="67" id="MFX-5P-qst"/>
+                <constraint firstItem="I51-60-pwl" firstAttribute="centerX" secondItem="Q7n-Zw-Frg" secondAttribute="centerX" id="Oor-FV-rN3"/>
+                <constraint firstItem="I51-60-pwl" firstAttribute="top" secondItem="h3U-B3-AOa" secondAttribute="bottom" constant="8" id="UJB-cg-tjo"/>
+                <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="I51-60-pwl" secondAttribute="bottom" constant="8" id="UxF-cz-tVA"/>
+                <constraint firstItem="I51-60-pwl" firstAttribute="centerX" secondItem="Q7n-Zw-Frg" secondAttribute="centerX" id="b1v-nG-XoP"/>
+                <constraint firstAttribute="trailing" secondItem="tHQ-sR-zn4" secondAttribute="trailing" id="bmc-sc-RXt"/>
+                <constraint firstAttribute="trailing" secondItem="I51-60-pwl" secondAttribute="trailing" constant="8" id="ftZ-YD-4bt"/>
+                <constraint firstItem="h3U-B3-AOa" firstAttribute="leading" secondItem="Q7n-Zw-Frg" secondAttribute="leading" constant="8" id="p8s-T6-E5f"/>
+                <constraint firstItem="tHQ-sR-zn4" firstAttribute="leading" secondItem="Q7n-Zw-Frg" secondAttribute="leading" id="tfE-v0-GDf"/>
+                <constraint firstItem="tHQ-sR-zn4" firstAttribute="top" relation="greaterThanOrEqual" secondItem="Q7n-Zw-Frg" secondAttribute="top" id="yTa-gB-hID"/>
+            </constraints>
+            <size key="customSize" width="314" height="270"/>
             <connections>
-                <outlet property="subtitleLabel" destination="4q6-BG-uo0" id="ST7-jm-Fva"/>
-                <outlet property="thumbnailImageView" destination="Diw-kq-1Zk" id="kfh-1g-s9S"/>
-                <outlet property="titleLabel" destination="TIO-jK-60o" id="ZV5-Ww-sG3"/>
+                <outlet property="subtitleLabel" destination="I51-60-pwl" id="QAu-qM-AqE"/>
+                <outlet property="thumbnailImageView" destination="tHQ-sR-zn4" id="Lfb-zG-339"/>
+                <outlet property="titleLabel" destination="h3U-B3-AOa" id="skp-ZA-fQ8"/>
             </connections>
-            <point key="canvasLocation" x="152" y="-196.5"/>
-        </tableViewCell>
+            <point key="canvasLocation" x="-262" y="-339.5"/>
+        </collectionViewCell>
     </objects>
 </document>

+ 1 - 1
VLC for Apple TV/VLCServerBrowsingTVTableViewController.h

@@ -11,7 +11,7 @@
 
 #import <UIKit/UIKit.h>
 #import "VLCNetworkServerBrowser-Protocol.h"
-@interface VLCServerBrowsingTVTableViewController : UITableViewController <VLCNetworkServerBrowserDelegate>
+@interface VLCServerBrowsingTVViewController : UICollectionViewController <VLCNetworkServerBrowserDelegate>
 
 - (instancetype)initWithServerBrowser:(id<VLCNetworkServerBrowser>)serverBrowser;
 @end

+ 59 - 20
VLC for Apple TV/VLCServerBrowsingTVTableViewController.m

@@ -9,23 +9,23 @@
  * Refer to the COPYING file of the official project for license.
  *****************************************************************************/
 
-#import "VLCServerBrowsingTVTableViewController.h"
+#import "VLCServerBrowsingTVViewController.h"
 #import "VLCServerBrowsingTVCell.h"
 #import "VLCPlayerDisplayController.h"
 #import "VLCPlaybackController.h"
 #import "VLCServerBrowsingController.h"
+#import "VLCMaskView.h"
 
-@interface VLCServerBrowsingTVTableViewController ()
+@interface VLCServerBrowsingTVViewController ()
 @property (nonatomic, readonly) id<VLCNetworkServerBrowser>serverBrowser;
 @property (nonatomic) VLCServerBrowsingController *browsingController;
-
 @end
 
-@implementation VLCServerBrowsingTVTableViewController
+@implementation VLCServerBrowsingTVViewController
 
 - (instancetype)initWithServerBrowser:(id<VLCNetworkServerBrowser>)serverBrowser
 {
-    self = [super init];
+    self = [super initWithNibName:@"VLCServerBrowsingTVViewController" bundle:nil];
     if (self) {
         _serverBrowser = serverBrowser;
         serverBrowser.delegate = self;
@@ -37,11 +37,17 @@
     return self;
 }
 
+
 - (void)viewDidLoad {
     [super viewDidLoad];
-    self.tableView.rowHeight = 150;
-    [self.tableView registerNib:[UINib nibWithNibName:@"VLCServerBrowsingTVCell" bundle:nil] forCellReuseIdentifier:VLCServerBrowsingTVCellIdentifier];
+
+    UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *)self.collectionViewLayout;
+    const CGFloat inset = 50;
+    flowLayout.sectionInset = UIEdgeInsetsMake(inset, inset, inset, inset);
+    [self.collectionView registerNib:[UINib nibWithNibName:@"VLCServerBrowsingTVCell" bundle:nil] forCellWithReuseIdentifier:VLCServerBrowsingTVCellIdentifier];
     self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(reloadData)];
+
+    self.collectionView.maskView = [[VLCMaskView alloc] initWithFrame:self.collectionView.bounds];
 }
 
 - (void)viewDidAppear:(BOOL)animated {
@@ -49,6 +55,33 @@
     [self.serverBrowser update];
 }
 
+
+- (void)viewDidLayoutSubviews
+{
+    [super viewDidLayoutSubviews];
+
+    UICollectionView *collectionView = self.collectionView;
+    VLCMaskView *maskView = (VLCMaskView *)collectionView.maskView;
+    maskView.maskEnd = self.topLayoutGuide.length * 0.8;
+
+    /*
+     Update the position from where the collection view's content should
+     start to fade out. The size of the fade increases as the collection
+     view scrolls to a maximum of half the navigation bar's height.
+     */
+    CGFloat maximumMaskStart = maskView.maskEnd + (self.topLayoutGuide.length * 0.5);
+    CGFloat verticalScrollPosition = MAX(0, collectionView.contentOffset.y + collectionView.contentInset.top);
+    maskView.maskStart = MIN(maximumMaskStart, maskView.maskEnd + verticalScrollPosition);
+
+    /*
+     Position the mask view so that it is always fills the visible area of
+     the collection view.
+     */
+    CGSize collectionViewSize = self.collectionView.bounds.size;
+    maskView.frame = CGRectMake(0, collectionView.contentOffset.y, collectionViewSize.width, collectionViewSize.height);
+    
+}
+
 #pragma mark -
 
 - (void)reloadData {
@@ -59,7 +92,7 @@
 
 - (void)networkServerBrowserDidUpdate:(id<VLCNetworkServerBrowser>)networkBrowser {
     self.title = networkBrowser.title;
-    [self.tableView reloadData];
+    [self.collectionView reloadData];
 }
 
 - (void)networkServerBrowser:(id<VLCNetworkServerBrowser>)networkBrowser requestDidFailWithError:(NSError *)error {
@@ -74,7 +107,7 @@
 - (void)didSelectItem:(id<VLCNetworkServerBrowserItem>)item index:(NSUInteger)index singlePlayback:(BOOL)singlePlayback
 {
     if (item.isContainer) {
-        VLCServerBrowsingTVTableViewController *targetViewController = [[VLCServerBrowsingTVTableViewController alloc] initWithServerBrowser:item.containerBrowser];
+        VLCServerBrowsingTVViewController *targetViewController = [[VLCServerBrowsingTVViewController alloc] initWithServerBrowser:item.containerBrowser];
         [self.navigationController pushViewController:targetViewController animated:YES];
     } else {
         if (singlePlayback) {
@@ -87,25 +120,31 @@
     }
 }
 
-#pragma mark - Table view data source
 
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+#pragma mark - collection view data source
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
+{
     return [self.serverBrowser items].count;
 }
 
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
 {
-    VLCServerBrowsingTVCell *cell = (VLCServerBrowsingTVCell *)[tableView dequeueReusableCellWithIdentifier:VLCServerBrowsingTVCellIdentifier];
-    if (!cell) {
-        cell = [[VLCServerBrowsingTVCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:VLCServerBrowsingTVCellIdentifier];
-    }
-    id<VLCNetworkServerBrowserItem> item = self.serverBrowser.items[indexPath.row];
-
-    [self.browsingController configureCell:cell withItem:item];
+    VLCServerBrowsingTVCell *cell = (VLCServerBrowsingTVCell *)[collectionView dequeueReusableCellWithReuseIdentifier:VLCServerBrowsingTVCellIdentifier forIndexPath:indexPath];
     return cell;
 }
 
-- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
+{
+        id<VLCNetworkServerBrowserItem> item = self.serverBrowser.items[indexPath.row];
+
+    if ([cell conformsToProtocol:@protocol(VLCServerBrowsingCell)]) {
+        [self.browsingController configureCell:(id<VLCServerBrowsingCell>)cell withItem:item];
+    }
+}
+
+- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
+{
     NSInteger row = indexPath.row;
     id<VLCNetworkServerBrowserItem> item = self.serverBrowser.items[row];
 

+ 31 - 0
VLC for Apple TV/VLCServerBrowsingTVViewController.xib

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder.AppleTV.XIB" version="3.0" toolsVersion="9059" systemVersion="15B42" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="VLCServerBrowsingTVViewController">
+            <connections>
+                <outlet property="collectionView" destination="NUi-8f-W1D" id="iDT-ID-8jS"/>
+                <outlet property="preferredFocusedView" destination="NUi-8f-W1D" id="mXv-Wn-Sh7"/>
+                <outlet property="view" destination="NUi-8f-W1D" id="oDs-Vy-NyX"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" id="NUi-8f-W1D">
+            <rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <animations/>
+            <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="50" minimumInteritemSpacing="50" id="o9k-mG-llf">
+                <size key="itemSize" width="300" height="300"/>
+                <size key="headerReferenceSize" width="0.0" height="0.0"/>
+                <size key="footerReferenceSize" width="0.0" height="0.0"/>
+                <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
+            </collectionViewFlowLayout>
+            <connections>
+                <outlet property="dataSource" destination="-1" id="Jwj-RD-1Py"/>
+                <outlet property="delegate" destination="-1" id="Ng7-Ok-jZx"/>
+            </connections>
+        </collectionView>
+    </objects>
+</document>

+ 3 - 3
VLC for Apple TV/VLCServerListTVTableViewController.m

@@ -11,7 +11,7 @@
 
 #import "VLCServerListTVTableViewController.h"
 #import "VLCLocalNetworkServerTVCell.h"
-#import "VLCServerBrowsingTVTableViewController.h"
+#import "VLCServerBrowsingTVViewController.h"
 #import "VLCNetworkServerLoginInformation.h"
 
 #import "VLCNetworkServerBrowserPlex.h"
@@ -124,7 +124,7 @@
     if ([service respondsToSelector:@selector(serverBrowser)]) {
         id <VLCNetworkServerBrowser> browser = [service serverBrowser];
         if (browser) {
-            VLCServerBrowsingTVTableViewController *browsingViewController = [[VLCServerBrowsingTVTableViewController alloc] initWithServerBrowser:browser];
+            VLCServerBrowsingTVViewController *browsingViewController = [[VLCServerBrowsingTVViewController alloc] initWithServerBrowser:browser];
             [self presentViewController:[[UINavigationController alloc] initWithRootViewController:browsingViewController]
                                animated:YES
                              completion:nil];
@@ -229,7 +229,7 @@
     }
 
     if (serverBrowser) {
-        VLCServerBrowsingTVTableViewController *targetViewController = [[VLCServerBrowsingTVTableViewController alloc] initWithServerBrowser:serverBrowser];
+        VLCServerBrowsingTVViewController *targetViewController = [[VLCServerBrowsingTVViewController alloc] initWithServerBrowser:serverBrowser];
         [self presentViewController:[[UINavigationController alloc] initWithRootViewController:targetViewController]
                            animated:YES
                          completion:nil];

+ 16 - 6
VLC for iOS.xcodeproj/project.pbxproj

@@ -237,6 +237,8 @@
 		CC1BBC58170493E100A20CBF /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC1BBC57170493E100A20CBF /* CoreData.framework */; };
 		CCE2A22E17A5859E00D9EAAD /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CCE2A22D17A5859E00D9EAAD /* CoreText.framework */; };
 		D9C52A9E9D4D5AFA7EF1B45A /* libPods-vlc-ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAF8927B0BE9C328466C0EA7 /* libPods-vlc-ios.a */; };
+		DD13A36E1BEE0F7100A35554 /* VLCServerBrowsingTVViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD13A36D1BEE0F7100A35554 /* VLCServerBrowsingTVViewController.xib */; };
+		DD13A37B1BEE2FAA00A35554 /* VLCMaskView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD13A37A1BEE2FAA00A35554 /* VLCMaskView.m */; };
 		DD1A45FD1B676BAC00086F57 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DDE1BCE41B676B8800A4B9CE /* Localizable.strings */; };
 		DD1CB0321BB9E005006EDDE6 /* VLCMovieViewControlPanelViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDAD5C2D1BB9A1E6006AFD3B /* VLCMovieViewControlPanelViewController.m */; };
 		DD1CB05A1BBAC549006EDDE6 /* VLCVolumeView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1CB0591BBAC549006EDDE6 /* VLCVolumeView.m */; };
@@ -332,7 +334,7 @@
 		DDB7C6A41BAEB28200E6570E /* WKInterfaceController+VLCConnectionAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9FBE761BAD6BB600FFE77A /* WKInterfaceController+VLCConnectionAlert.m */; };
 		DDB959421AFBB30500BB8CFF /* MappingModel_2_5_to_2_6.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = DDB959411AFBB30500BB8CFF /* MappingModel_2_5_to_2_6.xcmappingmodel */; };
 		DDC10BE41AEE8EA700890DC3 /* VLCTimeNavigationTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = DDC10BE31AEE8EA700890DC3 /* VLCTimeNavigationTitleView.m */; };
-		DDDEA6AF1BE027FA000BB7A2 /* VLCServerBrowsingTVTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDEA6AE1BE027FA000BB7A2 /* VLCServerBrowsingTVTableViewController.m */; };
+		DDDEA6AF1BE027FA000BB7A2 /* VLCServerBrowsingTVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDEA6AE1BE027FA000BB7A2 /* VLCServerBrowsingTVViewController.m */; };
 		DDEAECBE1BDEBF6700756C83 /* VLCNetworkServerLoginInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEAECBD1BDEBF6700756C83 /* VLCNetworkServerLoginInformation.m */; };
 		DDEAECBF1BDEBF6700756C83 /* VLCNetworkServerLoginInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEAECBD1BDEBF6700756C83 /* VLCNetworkServerLoginInformation.m */; };
 		DDEAECC61BDEC79D00756C83 /* VLCLocalNetworkServiceBrowserSAP.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEAECC51BDEC79D00756C83 /* VLCLocalNetworkServiceBrowserSAP.m */; };
@@ -834,6 +836,9 @@
 		CCAF837E17DE46D800E3578F /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
 		CCE2A22D17A5859E00D9EAAD /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; };
 		DAF8927B0BE9C328466C0EA7 /* libPods-vlc-ios.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-vlc-ios.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		DD13A36D1BEE0F7100A35554 /* VLCServerBrowsingTVViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = VLCServerBrowsingTVViewController.xib; sourceTree = "<group>"; };
+		DD13A3791BEE2FAA00A35554 /* VLCMaskView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCMaskView.h; path = "UI Elements/VLCMaskView.h"; sourceTree = "<group>"; };
+		DD13A37A1BEE2FAA00A35554 /* VLCMaskView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCMaskView.m; path = "UI Elements/VLCMaskView.m"; sourceTree = "<group>"; };
 		DD1A45FC1B676BAC00086F57 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
 		DD1CB0581BBAC549006EDDE6 /* VLCVolumeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCVolumeView.h; path = Sources/VLCVolumeView.h; sourceTree = SOURCE_ROOT; };
 		DD1CB0591BBAC549006EDDE6 /* VLCVolumeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCVolumeView.m; path = Sources/VLCVolumeView.m; sourceTree = SOURCE_ROOT; };
@@ -983,8 +988,8 @@
 		DDB959411AFBB30500BB8CFF /* MappingModel_2_5_to_2_6.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; name = MappingModel_2_5_to_2_6.xcmappingmodel; path = ../ImportedSources/MediaLibraryKit/MappingModel_2_5_to_2_6.xcmappingmodel; sourceTree = "<group>"; };
 		DDC10BE21AEE8EA700890DC3 /* VLCTimeNavigationTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCTimeNavigationTitleView.h; path = Sources/VLCTimeNavigationTitleView.h; sourceTree = SOURCE_ROOT; };
 		DDC10BE31AEE8EA700890DC3 /* VLCTimeNavigationTitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCTimeNavigationTitleView.m; path = Sources/VLCTimeNavigationTitleView.m; sourceTree = SOURCE_ROOT; };
-		DDDEA6AD1BE027FA000BB7A2 /* VLCServerBrowsingTVTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCServerBrowsingTVTableViewController.h; sourceTree = "<group>"; };
-		DDDEA6AE1BE027FA000BB7A2 /* VLCServerBrowsingTVTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCServerBrowsingTVTableViewController.m; sourceTree = "<group>"; };
+		DDDEA6AD1BE027FA000BB7A2 /* VLCServerBrowsingTVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCServerBrowsingTVViewController.h; sourceTree = "<group>"; };
+		DDDEA6AE1BE027FA000BB7A2 /* VLCServerBrowsingTVViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCServerBrowsingTVViewController.m; sourceTree = "<group>"; };
 		DDE1BCE51B676B8800A4B9CE /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = "<group>"; };
 		DDEAECBC1BDEBF6700756C83 /* VLCNetworkServerLoginInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCNetworkServerLoginInformation.h; sourceTree = "<group>"; };
 		DDEAECBD1BDEBF6700756C83 /* VLCNetworkServerLoginInformation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCNetworkServerLoginInformation.m; sourceTree = "<group>"; };
@@ -1634,6 +1639,7 @@
 				7DDE418E1BE9225A0065C53A /* VLCAboutViewController.xib */,
 				7D6069711BD94AD600AB765C /* VLCCloudStorageTableViewCell.xib */,
 				DD3EAC121BE26166003668DA /* VLCServerBrowsingTVCell.xib */,
+				DD13A36D1BEE0F7100A35554 /* VLCServerBrowsingTVViewController.xib */,
 				7D3E528A1BD7B5E100309D15 /* VLCCloudServicesTVViewController.xib */,
 				7DEC8BDD1BD67899006E1093 /* VLCFullscreenMovieTVViewController.xib */,
 				DD8095E41BE3F4240065D8E1 /* VLCPlaybackInfoTVViewController.xib */,
@@ -1694,6 +1700,8 @@
 				9BADAF44185FBD9D00108BD8 /* VLCFrostedGlasView.m */,
 				DD3EAC021BE153B4003668DA /* VLCNetworkImageView.h */,
 				DD3EAC031BE153B4003668DA /* VLCNetworkImageView.m */,
+				DD13A3791BEE2FAA00A35554 /* VLCMaskView.h */,
+				DD13A37A1BEE2FAA00A35554 /* VLCMaskView.m */,
 			);
 			name = "UI Elements";
 			sourceTree = "<group>";
@@ -1703,8 +1711,8 @@
 			children = (
 				DDEAECEB1BDFE99200756C83 /* VLCServerListTVTableViewController.h */,
 				DDEAECEC1BDFE99200756C83 /* VLCServerListTVTableViewController.m */,
-				DDDEA6AD1BE027FA000BB7A2 /* VLCServerBrowsingTVTableViewController.h */,
-				DDDEA6AE1BE027FA000BB7A2 /* VLCServerBrowsingTVTableViewController.m */,
+				DDDEA6AD1BE027FA000BB7A2 /* VLCServerBrowsingTVViewController.h */,
+				DDDEA6AE1BE027FA000BB7A2 /* VLCServerBrowsingTVViewController.m */,
 				7DC71D231BC830A5001FACAA /* VLCLocalNetworkTVViewController.h */,
 				7DC71D241BC830A5001FACAA /* VLCLocalNetworkTVViewController.m */,
 				DDEAECF21BDFEAE300756C83 /* VLCLocalNetworkServerTVCell.h */,
@@ -2373,6 +2381,7 @@
 				7D4CAAFC1BDE548A00A08EF5 /* Localizable.strings in Resources */,
 				7DDE41931BE925820065C53A /* Assets.xcassets in Resources */,
 				7DEDD38E1BE936F30053802C /* OpenSans-Regular.ttf in Resources */,
+				DD13A36E1BEE0F7100A35554 /* VLCServerBrowsingTVViewController.xib in Resources */,
 				DDEAECF61BDFEAFA00756C83 /* VLCLocalNetworkServerTVCell.xib in Resources */,
 				DD8095EC1BE4F04E0065D8E1 /* VLCPlaybackInfoRateTVViewController.xib in Resources */,
 				7D405ED61BEA1F56006ED886 /* jquery-1.10.1.min.js in Resources */,
@@ -2590,7 +2599,7 @@
 				DD3EFF381BDEBCE500B68579 /* VLCLocalNetworkServiceNetService.m in Sources */,
 				DD8095D61BE3C3BA0065D8E1 /* VLCTransportBar.m in Sources */,
 				DDEAECF71BDFEB0200756C83 /* VLCLocalNetworkServerTVCell.m in Sources */,
-				DDDEA6AF1BE027FA000BB7A2 /* VLCServerBrowsingTVTableViewController.m in Sources */,
+				DDDEA6AF1BE027FA000BB7A2 /* VLCServerBrowsingTVViewController.m in Sources */,
 				DD3EFF461BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserManualConnect.m in Sources */,
 				7D13347F1BE132ED0012E919 /* VLCLocalNetworkServiceUPnP.m in Sources */,
 				DD3EFF4A1BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserPlex.m in Sources */,
@@ -2628,6 +2637,7 @@
 				7D0C35331BD97C100058CD19 /* VLCOneDriveController.m in Sources */,
 				7D0EDE061BE774BF00363AA1 /* WhiteRaccoon.m in Sources */,
 				7D60696B1BD93AC800AB765C /* VLCDropboxTableViewController.m in Sources */,
+				DD13A37B1BEE2FAA00A35554 /* VLCMaskView.m in Sources */,
 				7D405ED01BEA11C1006ED886 /* VLCHTTPConnection.m in Sources */,
 				DD490B1F1BE95B5C0010F335 /* VLCSiriRemoteGestureRecognizer.m in Sources */,
 				DD3EFF3C1BDEBCE500B68579 /* VLCNetworkServerBrowserVLCMedia.m in Sources */,