Przeglądaj źródła

Implemented search for server content browsing.

Add a new VLCNetworkServerBrowser conforming class that works as a filter for another server browser.
Add VLCServerBrowsingTVController subclass that has a search bar with UISearchController as section title view.

Signed-off-by: Felix Paul Kühne <fkuehne@videolan.org>
Vincent L. Cone 9 lat temu
rodzic
commit
67b86dc41f

+ 24 - 0
Apple-TV/VLCNetworkServerSearchBrowser.h

@@ -0,0 +1,24 @@
+/*****************************************************************************
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2016 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Vincent L. Cone <vincent.l.cone # tuta.io>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+
+#import <UIKit/UIKit.h>
+#import "VLCNetworkServerBrowser-Protocol.h"
+
+NS_ASSUME_NONNULL_BEGIN
+@interface VLCNetworkServerSearchBrowser : NSObject <VLCNetworkServerBrowser, VLCNetworkServerBrowserDelegate>
+// change the searchText to update the filters
+@property (nonatomic, copy, nullable) NSString *searchText;
+// VLCNetworkServerSearchBrowser does not set itself as the delegate of the serverBrowser,
+// instead the delegate of the serverBrowser has to relay the delegate methods to VLCNetworkServerSearchBrowser while active.
+- (instancetype)initWithServerBrowser:(id<VLCNetworkServerBrowser>)serverBrowser;
+@end
+NS_ASSUME_NONNULL_END

+ 147 - 0
Apple-TV/VLCNetworkServerSearchBrowser.m

@@ -0,0 +1,147 @@
+/*****************************************************************************
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2016 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Vincent L. Cone <vincent.l.cone # tuta.io>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import "VLCNetworkServerSearchBrowser.h"
+
+@interface VLCNetworkServerSearchBrowser()
+@property (nonatomic) id<VLCNetworkServerBrowser> serverBrowser;
+@property (nonatomic, copy, nullable) NSIndexSet *filteredIndexes;
+@property (nonatomic, copy, null_resettable) NSArray<id<VLCNetworkServerBrowserItem>> *filteredItems;
+@property (nonatomic, null_resettable) VLCMediaList *filteredMediaList;
+@end
+
+@implementation VLCNetworkServerSearchBrowser
+@synthesize delegate = _delegate;
+
+
+- (instancetype)initWithServerBrowser:(id<VLCNetworkServerBrowser>)serverBrowser
+{
+    self = [super init];
+    if (self) {
+        _serverBrowser = serverBrowser;
+    }
+    return self;
+}
+
+- (NSString *)title
+{
+    return self.serverBrowser.title;
+}
+
+- (VLCMediaList *)mediaList
+{
+    return self.filteredMediaList;
+}
+
+- (NSArray<id<VLCNetworkServerBrowserItem>> *)items
+{
+    return self.filteredItems;
+}
+
+- (void)update
+{
+    [self.serverBrowser update];
+}
+
+- (void)setSearchText:(NSString *)searchText
+{
+    if (![_searchText isEqualToString:searchText]) {
+        _searchText = searchText;
+        [self updateFilteredItems];
+        [self.delegate networkServerBrowserDidUpdate:self];
+    }
+}
+
+#pragma mark - filtering
+- (void)setFilteredIndexes:(NSIndexSet *)filteredIndexes
+{
+    BOOL needUpdate = NO;
+    if (_filteredIndexes) {
+        needUpdate = ![_filteredIndexes isEqualToIndexSet:filteredIndexes];
+    } else if (filteredIndexes) {
+        needUpdate = YES;
+    }
+    if (needUpdate) {
+        _filteredIndexes = [filteredIndexes copy];
+
+        self.filteredItems = nil;
+        self.filteredMediaList = nil;
+    }
+}
+- (NSArray<id<VLCNetworkServerBrowserItem>> *)filteredItems
+{
+    if (!_filteredItems) {
+        NSIndexSet *indexes = self.filteredIndexes;
+        NSArray<id<VLCNetworkServerBrowserItem>> *items = self.serverBrowser.items;
+        _filteredItems = indexes ? [items objectsAtIndexes:indexes] : items;
+    }
+    return _filteredItems;
+}
+
+- (VLCMediaList *)filteredMediaList
+{
+    if (!_filteredMediaList) {
+        NSIndexSet *indexes = self.filteredIndexes;
+        VLCMediaList *mediaList = self.serverBrowser.mediaList;
+        if (indexes) {
+            __block NSUInteger count = 0;
+            VLCMediaList *filteredMediaList = [[VLCMediaList alloc] initWithArray:nil];
+            [filteredMediaList lock];
+            [mediaList lock];
+            [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
+                VLCMedia *media = [mediaList mediaAtIndex:idx];
+                [filteredMediaList insertMedia:media atIndex:count];
+                ++count;
+            }];
+            [mediaList unlock];
+            [filteredMediaList unlock];
+
+            _filteredMediaList = filteredMediaList;
+        } else {
+            _filteredMediaList = mediaList;
+        }
+    }
+    return _filteredMediaList;
+}
+
+- (void)updateFilteredItems
+{
+    NSIndexSet *filteredIndexes = nil;
+    if (self.searchText.length) {
+        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@",self.searchText];
+
+        NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];
+        NSArray<id<VLCNetworkServerBrowserItem>> *items = self.serverBrowser.items;
+        [items enumerateObjectsUsingBlock:^(id<VLCNetworkServerBrowserItem>  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+            if ([predicate evaluateWithObject:obj]) {
+                [indexSet addIndex:idx];
+            }
+        }];
+        filteredIndexes = indexSet;
+    }
+    self.filteredIndexes = filteredIndexes;
+}
+
+
+#pragma mark - VLCNetworkServerBrowserDelegate
+
+- (void)networkServerBrowserDidUpdate:(id<VLCNetworkServerBrowser>)networkBrowser
+{
+    [self updateFilteredItems];
+    [self.delegate networkServerBrowserDidUpdate:self];
+}
+
+- (void)networkServerBrowser:(id<VLCNetworkServerBrowser>)networkBrowser requestDidFailWithError:(NSError *)error
+{
+    [self.delegate networkServerBrowser:self requestDidFailWithError:error];
+}
+
+@end

+ 16 - 0
Apple-TV/VLCSearchController.h

@@ -0,0 +1,16 @@
+/*****************************************************************************
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2016 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Vincent L. Cone <vincent.l.cone # tuta.io>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import <UIKit/UIKit.h>
+
+@interface VLCSearchController : UISearchController
+
+@end

+ 28 - 0
Apple-TV/VLCSearchController.m

@@ -0,0 +1,28 @@
+/*****************************************************************************
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2016 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Vincent L. Cone <vincent.l.cone # tuta.io>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import "VLCSearchController.h"
+
+@implementation VLCSearchController
+
+- (UIViewController *)targetViewControllerForAction:(SEL)action sender:(id)sender
+{
+    return self;
+}
+- (void)showViewController:(UIViewController *)vc sender:(id)sender
+{
+    UIViewController *presentingControllerController = self.presentingViewController;
+    [self.presentingViewController showViewController:vc sender:sender];
+    [self dismissViewControllerAnimated:YES completion:nil];
+}
+
+
+@end

+ 16 - 0
Apple-TV/VLCSearchableServerBrowsingTVViewController.h

@@ -0,0 +1,16 @@
+/*****************************************************************************
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2016 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Vincent L. Cone <vincent.l.cone # tuta.io>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import "VLCServerBrowsingTVViewController.h"
+
+@interface VLCSearchableServerBrowsingTVViewController : VLCServerBrowsingTVViewController
+
+@end

+ 109 - 0
Apple-TV/VLCSearchableServerBrowsingTVViewController.m

@@ -0,0 +1,109 @@
+/*****************************************************************************
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2016 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Vincent L. Cone <vincent.l.cone # gmail.com>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import "VLCSearchableServerBrowsingTVViewController.h"
+#import "VLCNetworkServerSearchBrowser.h"
+#import "VLCSearchController.h"
+
+static NSString * const VLCSearchableServerBrowsingTVViewControllerSectionHeaderKey = @"VLCSearchableServerBrowsingTVViewControllerSectionHeader";
+@interface VLCSearchableServerBrowsingTVViewControllerHeader : UICollectionReusableView
+@property (nonatomic) UISearchBar *searchBar;
+@end
+
+@interface VLCSearchableServerBrowsingTVViewController() <UISearchControllerDelegate, UISearchResultsUpdating>
+@property (nonatomic) UISearchController *searchController;
+@property (nonatomic) VLCNetworkServerSearchBrowser *searchBrowser;
+@end
+
+@implementation VLCSearchableServerBrowsingTVViewController
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+
+    VLCNetworkServerSearchBrowser *searchBrowser = [[VLCNetworkServerSearchBrowser alloc] initWithServerBrowser:self.serverBrowser];
+    VLCServerBrowsingTVViewController *resultBrowsingViewController = [[VLCServerBrowsingTVViewController alloc] initWithServerBrowser:searchBrowser];
+    resultBrowsingViewController.subdirectoryBrowserClass = [self class];
+    _searchBrowser = searchBrowser;
+    UISearchController *searchController = [[VLCSearchController alloc] initWithSearchResultsController:resultBrowsingViewController];
+    searchController.searchResultsUpdater = self;
+    searchController.delegate = self;
+    searchController.hidesNavigationBarDuringPresentation = NO;
+    _searchController = searchController;
+    UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *)self.collectionViewLayout;
+    flowLayout.headerReferenceSize = searchController.searchBar.bounds.size;
+
+    [self.collectionView registerClass:[VLCSearchableServerBrowsingTVViewControllerHeader class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:VLCSearchableServerBrowsingTVViewControllerSectionHeaderKey];
+}
+
+#pragma mark - UICollectionViewDataSource
+
+- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
+{
+    UICollectionReusableView *supplementaryView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:VLCSearchableServerBrowsingTVViewControllerSectionHeaderKey forIndexPath:indexPath];
+
+    VLCSearchableServerBrowsingTVViewControllerHeader *header = [supplementaryView isKindOfClass:[VLCSearchableServerBrowsingTVViewControllerHeader class]] ? (id)supplementaryView : nil;
+    UISearchController *searchController = self.searchController;
+    header.searchBar = searchController.searchBar;
+    if (!searchController.active) {
+        [header addSubview:searchController.searchBar];
+    }
+    return supplementaryView;
+}
+
+#pragma mark - VLCNetworkServerBrowserDelegate
+- (void)networkServerBrowserDidUpdate:(id<VLCNetworkServerBrowser>)networkBrowser
+{
+    [super networkServerBrowserDidUpdate:networkBrowser];
+    if (self.searchController.active) {
+        [self.searchBrowser networkServerBrowserDidUpdate:networkBrowser];
+    }
+}
+
+- (void)networkServerBrowser:(id<VLCNetworkServerBrowser>)networkBrowser requestDidFailWithError:(NSError *)error
+{
+    if (self.searchController.active) {
+        [self.searchBrowser networkServerBrowser:networkBrowser requestDidFailWithError:error];
+    } else {
+        [super networkServerBrowser:networkBrowser requestDidFailWithError:error];
+    }
+}
+
+#pragma mark - UISearchControllerDelegate
+- (void)willPresentSearchController:(UISearchController *)searchController
+{
+    [self.searchBrowser networkServerBrowserDidUpdate:self.serverBrowser];
+}
+
+#pragma mark - UISearchResultsUpdating
+- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
+{
+    self.searchBrowser.searchText = searchController.searchBar.text;
+}
+
+@end
+
+@implementation VLCSearchableServerBrowsingTVViewControllerHeader
+
+- (void)setSearchBar:(UISearchBar *)searchBar {
+    _searchBar = searchBar;
+}
+
+- (void)layoutSubviews
+{
+    [super layoutSubviews];
+    // UISearchController 'steals' the search bar from us when it's active.
+    if (self.searchBar.superview == self) {
+        self.searchBar.center = self.center;
+    }
+}
+
+@end

+ 4 - 0
Apple-TV/VLCServerBrowsingTVViewController.h

@@ -14,10 +14,14 @@
 #import "VLCRemoteBrowsingCollectionViewController.h"
 #import "VLCNetworkServerBrowser-Protocol.h"
 
+NS_ASSUME_NONNULL_BEGIN
 @interface VLCServerBrowsingTVViewController : VLCRemoteBrowsingCollectionViewController <VLCNetworkServerBrowserDelegate>
 
 @property (nonatomic) BOOL downloadArtwork;
+@property (nonatomic, readonly) id<VLCNetworkServerBrowser>serverBrowser;
+@property (nonatomic, null_resettable) Class subdirectoryBrowserClass; // if not set returns [self class], must be subclass of VLCServerBrowsingTVViewController
 
 - (instancetype)initWithServerBrowser:(id<VLCNetworkServerBrowser>)serverBrowser;
 
 @end
+NS_ASSUME_NONNULL_END

+ 15 - 4
Apple-TV/VLCServerBrowsingTVViewController.m

@@ -22,11 +22,11 @@
     NSIndexPath *_currentFocus;
     BOOL _focusChangeAllowed;
 }
-@property (nonatomic, readonly) id<VLCNetworkServerBrowser>serverBrowser;
 @property (nonatomic) VLCServerBrowsingController *browsingController;
 @end
 
 @implementation VLCServerBrowsingTVViewController
+@synthesize subdirectoryBrowserClass = _subdirectoryBrowserClass;
 
 - (instancetype)initWithServerBrowser:(id<VLCNetworkServerBrowser>)serverBrowser
 {
@@ -82,6 +82,17 @@
     [self.serverBrowser update];
 }
 
+- (void)setSubdirectoryBrowserClass:(Class)subdirectoryBrowserClass
+{
+    NSParameterAssert([subdirectoryBrowserClass isSubclassOfClass:[VLCServerBrowsingTVViewController class]]);
+    _subdirectoryBrowserClass = subdirectoryBrowserClass;
+}
+
+- (Class)subdirectoryBrowserClass
+{
+    return _subdirectoryBrowserClass ?: [self class];
+}
+
 #pragma mark -
 
 - (void)reloadData
@@ -89,7 +100,7 @@
     [self.serverBrowser update];
 }
 
-#pragma mark -
+#pragma mark - VLCNetworkServerBrowserDelegate
 
 - (void)networkServerBrowserDidUpdate:(id<VLCNetworkServerBrowser>)networkBrowser
 {
@@ -110,8 +121,8 @@
 - (void)didSelectItem:(id<VLCNetworkServerBrowserItem>)item index:(NSUInteger)index singlePlayback:(BOOL)singlePlayback
 {
     if (item.isContainer) {
-        VLCServerBrowsingTVViewController *targetViewController = [[VLCServerBrowsingTVViewController alloc] initWithServerBrowser:item.containerBrowser];
-        [self.navigationController pushViewController:targetViewController animated:YES];
+        VLCServerBrowsingTVViewController *targetViewController = [[self.subdirectoryBrowserClass alloc] initWithServerBrowser:item.containerBrowser];
+        [self showViewController:targetViewController sender:self];
     } else {
         if (singlePlayback) {
             [self.browsingController streamFileForItem:item];

+ 3 - 3
Apple-TV/VLCServerListTVViewController.m

@@ -10,7 +10,7 @@
  *****************************************************************************/
 
 #import "VLCServerListTVViewController.h"
-#import "VLCServerBrowsingTVViewController.h"
+#import "VLCSearchableServerBrowsingTVViewController.h"
 #import "VLCNetworkServerLoginInformation.h"
 
 #import "VLCNetworkServerBrowserPlex.h"
@@ -154,7 +154,7 @@
     if ([service respondsToSelector:@selector(serverBrowser)]) {
         id <VLCNetworkServerBrowser> browser = [service serverBrowser];
         if (browser) {
-            VLCServerBrowsingTVViewController *browsingViewController = [[VLCServerBrowsingTVViewController alloc] initWithServerBrowser:browser];
+            VLCServerBrowsingTVViewController *browsingViewController = [[VLCSearchableServerBrowsingTVViewController alloc] initWithServerBrowser:browser];
             [self presentViewController:[[UINavigationController alloc] initWithRootViewController:browsingViewController]
                                animated:YES
                              completion:nil];
@@ -265,7 +265,7 @@
     }
 
     if (serverBrowser) {
-        VLCServerBrowsingTVViewController *targetViewController = [[VLCServerBrowsingTVViewController alloc] initWithServerBrowser:serverBrowser];
+        VLCServerBrowsingTVViewController *targetViewController = [[VLCSearchableServerBrowsingTVViewController alloc] initWithServerBrowser:serverBrowser];
         [self presentViewController:[[UINavigationController alloc] initWithRootViewController:targetViewController]
                            animated:YES
                          completion:nil];

+ 18 - 0
VLC for iOS.xcodeproj/project.pbxproj

@@ -170,6 +170,9 @@
 		7D9870691A3E03D5009CF27D /* papasscode_marker@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D9870631A3E03D5009CF27D /* papasscode_marker@2x.png */; };
 		7D9CB9DC1A4C55EF00BB74B4 /* VLCPlaybackNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9CB9DB1A4C55EF00BB74B4 /* VLCPlaybackNavigationController.m */; };
 		7DAE0C371B2EF85B00C53996 /* VLCSidebarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DAE0C361B2EF85B00C53996 /* VLCSidebarController.m */; };
+		7DB174A71CD20D7B0085BCF0 /* VLCSearchableServerBrowsingTVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB174A61CD20D7B0085BCF0 /* VLCSearchableServerBrowsingTVViewController.m */; };
+		7DB174B41CD20DC00085BCF0 /* VLCNetworkServerSearchBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB174B11CD20DC00085BCF0 /* VLCNetworkServerSearchBrowser.m */; };
+		7DB174B51CD20DC00085BCF0 /* VLCSearchController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB174B31CD20DC00085BCF0 /* VLCSearchController.m */; };
 		7DB638AB185BC0890003887C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7DB638AA185BC0890003887C /* Images.xcassets */; };
 		7DB847D71A5871570002DC30 /* VLCOneDriveObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB847D61A5871570002DC30 /* VLCOneDriveObject.m */; };
 		7DBB788A1B30423B00894467 /* VLCKeychainCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DBB78891B30423B00894467 /* VLCKeychainCoordinator.m */; };
@@ -1061,6 +1064,12 @@
 		7D9CB9DB1A4C55EF00BB74B4 /* VLCPlaybackNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCPlaybackNavigationController.m; path = Sources/VLCPlaybackNavigationController.m; sourceTree = SOURCE_ROOT; };
 		7DAE0C351B2EF85B00C53996 /* VLCSidebarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCSidebarController.h; path = Sources/VLCSidebarController.h; sourceTree = SOURCE_ROOT; };
 		7DAE0C361B2EF85B00C53996 /* VLCSidebarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCSidebarController.m; path = Sources/VLCSidebarController.m; sourceTree = SOURCE_ROOT; };
+		7DB174A51CD20D7B0085BCF0 /* VLCSearchableServerBrowsingTVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCSearchableServerBrowsingTVViewController.h; sourceTree = "<group>"; };
+		7DB174A61CD20D7B0085BCF0 /* VLCSearchableServerBrowsingTVViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCSearchableServerBrowsingTVViewController.m; sourceTree = "<group>"; };
+		7DB174B01CD20DC00085BCF0 /* VLCNetworkServerSearchBrowser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCNetworkServerSearchBrowser.h; path = "Apple-TV/VLCNetworkServerSearchBrowser.h"; sourceTree = SOURCE_ROOT; };
+		7DB174B11CD20DC00085BCF0 /* VLCNetworkServerSearchBrowser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCNetworkServerSearchBrowser.m; path = "Apple-TV/VLCNetworkServerSearchBrowser.m"; sourceTree = SOURCE_ROOT; };
+		7DB174B21CD20DC00085BCF0 /* VLCSearchController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCSearchController.h; path = "Apple-TV/VLCSearchController.h"; sourceTree = SOURCE_ROOT; };
+		7DB174B31CD20DC00085BCF0 /* VLCSearchController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCSearchController.m; path = "Apple-TV/VLCSearchController.m"; sourceTree = SOURCE_ROOT; };
 		7DB2486E18EA1D6D0097ADD2 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = "<group>"; };
 		7DB638AA185BC0890003887C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = "../vlc-ios/Images.xcassets"; sourceTree = "<group>"; };
 		7DB847D51A5871570002DC30 /* VLCOneDriveObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCOneDriveObject.h; path = Sources/VLCOneDriveObject.h; sourceTree = SOURCE_ROOT; };
@@ -2240,6 +2249,8 @@
 				DDDEA6AE1BE027FA000BB7A2 /* VLCServerBrowsingTVViewController.m */,
 				7D7EF3D71BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.h */,
 				7D7EF3D81BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.m */,
+				7DB174A51CD20D7B0085BCF0 /* VLCSearchableServerBrowsingTVViewController.h */,
+				7DB174A61CD20D7B0085BCF0 /* VLCSearchableServerBrowsingTVViewController.m */,
 			);
 			name = "Network UI";
 			sourceTree = "<group>";
@@ -2527,6 +2538,10 @@
 				DD3EFF2C1BDEBCE500B68579 /* VLCNetworkServerBrowser-Protocol.h */,
 				DD3EAC071BE2192A003668DA /* VLCServerBrowsingController.h */,
 				DD3EAC081BE2192A003668DA /* VLCServerBrowsingController.m */,
+				7DB174B01CD20DC00085BCF0 /* VLCNetworkServerSearchBrowser.h */,
+				7DB174B11CD20DC00085BCF0 /* VLCNetworkServerSearchBrowser.m */,
+				7DB174B21CD20DC00085BCF0 /* VLCSearchController.h */,
+				7DB174B31CD20DC00085BCF0 /* VLCSearchController.m */,
 			);
 			path = ServerBrowsing;
 			sourceTree = "<group>";
@@ -3382,6 +3397,7 @@
 				DD4089F51BF6556F0022745E /* VLCFullWidthCollectionViewFlowLayout.m in Sources */,
 				DD3EFF3A1BDEBCE500B68579 /* VLCLocalNetworkServiceVLCMedia.m in Sources */,
 				7D7EF3DA1BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.m in Sources */,
+				7DB174B41CD20DC00085BCF0 /* VLCNetworkServerSearchBrowser.m in Sources */,
 				DD3EFF521BDEBCE500B68579 /* VLCPlexWebAPI.m in Sources */,
 				7D0EDE091BE7752800363AA1 /* VLCLocalNetworkServiceBrowserFTP.m in Sources */,
 				7DF383C11BF231BC00D71A5C /* VLCCloudStorageTVViewController.m in Sources */,
@@ -3391,6 +3407,7 @@
 				DD3EABFD1BE14C4B003668DA /* UIViewController+VLCAlert.m in Sources */,
 				7D7EF3DD1BD5779F00CD4CEE /* VLCPlaybackController.m in Sources */,
 				DD3EFF361BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserNetService.m in Sources */,
+				7DB174A71CD20D7B0085BCF0 /* VLCSearchableServerBrowsingTVViewController.m in Sources */,
 				7D51B3B01BF0EEF4005AF4D5 /* VLCPlaybackInfoMediaInfoTVViewController.m in Sources */,
 				7D13347C1BE132EA0012E919 /* VLCLocalNetworkServiceBrowserUPnP.m in Sources */,
 				7DC5A3E71BF6370800CFEBA8 /* VLCRemotePlaybackViewController.m in Sources */,
@@ -3418,6 +3435,7 @@
 				7D0C35341BD97C7B0058CD19 /* VLCOneDriveObject.m in Sources */,
 				7D0C35331BD97C100058CD19 /* VLCOneDriveController.m in Sources */,
 				7D0EDE061BE774BF00363AA1 /* WhiteRaccoon.m in Sources */,
+				7DB174B51CD20DC00085BCF0 /* VLCSearchController.m in Sources */,
 				DD13A37B1BEE2FAA00A35554 /* VLCMaskView.m in Sources */,
 				7DF383AC1BF206F100D71A5C /* VLCRemoteBrowsingCollectionViewController.m in Sources */,
 				DD9D8F5F1C00C73F00B4060F /* VLCDeleteHintTVView.m in Sources */,