Browse Source

tvOS server browsing: Implement batch updates for collection view instead of refresh when items change.

Signed-off-by: Felix Paul Kühne <fkuehne@videolan.org>
Vincent L. Cone 9 years ago
parent
commit
5a1b44f127

+ 17 - 0
Apple-TV/GRKArrayDiff+UICollectionView.h

@@ -0,0 +1,17 @@
+/*****************************************************************************
+ * 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 <GRKArrayDiff/GRKArrayDiff.h>
+NS_ASSUME_NONNULL_BEGIN
+@interface GRKArrayDiff (UICollectionView)
+- (void)performBatchUpdatesWithCollectionView:(UICollectionView *)collectionView section:(NSUInteger)section dataSourceUpdate:(void(^ __nullable)(void))update completion:(void (^ __nullable)(BOOL finished))completion;
+@end
+NS_ASSUME_NONNULL_END

+ 46 - 0
Apple-TV/GRKArrayDiff+UICollectionView.m

@@ -0,0 +1,46 @@
+/*****************************************************************************
+ * 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 "GRKArrayDiff+UICollectionView.h"
+
+@implementation GRKArrayDiff (UICollectionView)
+- (void)performBatchUpdatesWithCollectionView:(UICollectionView *)collectionView section:(NSUInteger)section dataSourceUpdate:(void (^)(void))update completion:(void (^ __nullable)(BOOL finished))completion
+{
+    [collectionView performBatchUpdates:^{
+        NSArray<NSIndexPath *> *deletions = [self indexPathsForDiffType:GRKArrayDiffTypeDeletions withSection:section];
+        if (deletions.count) {
+            deletions = [deletions sortedArrayUsingSelector:@selector(compare:)];
+            [collectionView deleteItemsAtIndexPaths:deletions];
+        }
+        NSArray<NSIndexPath *> *insertions = [self indexPathsForDiffType:GRKArrayDiffTypeInsertions withSection:section];
+        if (insertions.count) {
+            insertions = [insertions sortedArrayUsingSelector:@selector(compare:)];
+            [collectionView insertItemsAtIndexPaths:insertions];
+        }
+        for (GRKArrayDiffInfo *moveInfo in self.moves) {
+            NSIndexPath *previousIndexPath = [moveInfo indexPathForIndexType:GRKArrayDiffInfoIndexTypePrevious withSection:section];
+            NSIndexPath *currentIndexPath = [moveInfo indexPathForIndexType:GRKArrayDiffInfoIndexTypeCurrent withSection:section];
+            [collectionView moveItemAtIndexPath:previousIndexPath toIndexPath:currentIndexPath];
+        }
+
+        NSArray<NSIndexPath *> *modifications = [self indexPathsForDiffType:GRKArrayDiffTypeModifications withSection:section];
+        if (modifications.count) {
+            [collectionView reloadItemsAtIndexPaths:modifications];
+        }
+
+        // perform data source update within batchUpdateBlock
+        if (update) {
+            update();
+        }
+
+    } completion:completion];
+}
+@end

+ 22 - 5
Apple-TV/VLCServerBrowsingTVViewController.m

@@ -15,6 +15,7 @@
 #import "VLCPlaybackController.h"
 #import "VLCServerBrowsingController.h"
 #import "VLCMaskView.h"
+#import "GRKArrayDiff+UICollectionView.h"
 
 @interface VLCServerBrowsingTVViewController ()
 {
@@ -23,6 +24,7 @@
     BOOL _focusChangeAllowed;
 }
 @property (nonatomic) VLCServerBrowsingController *browsingController;
+@property (nonatomic) NSArray<id <VLCNetworkServerBrowserItem>> *items;
 @end
 
 @implementation VLCServerBrowsingTVViewController
@@ -105,8 +107,23 @@
 - (void)networkServerBrowserDidUpdate:(id<VLCNetworkServerBrowser>)networkBrowser
 {
     self.title = networkBrowser.title;
-    [self.collectionView reloadData];
-    _nothingFoundLabel.hidden = [self.serverBrowser items].count > 0;
+
+    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;
 }
 
 - (void)networkServerBrowser:(id<VLCNetworkServerBrowser>)networkBrowser requestDidFailWithError:(NSError *)error {
@@ -139,14 +156,14 @@
 
 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
 {
-    NSInteger count = [self.serverBrowser items].count;
+    NSInteger count = self.items.count;
     self.nothingFoundView.hidden = count > 0;
     return count;
 }
 
 - (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
 {
-    NSArray *items = self.serverBrowser.items;
+    NSArray *items = self.items;
     NSInteger row = indexPath.row;
     if (row < items.count) {
         id<VLCNetworkServerBrowserItem> item = items[row];
@@ -164,7 +181,7 @@
 - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
 {
     NSInteger row = indexPath.row;
-    id<VLCNetworkServerBrowserItem> item = self.serverBrowser.items[row];
+    id<VLCNetworkServerBrowserItem> item = self.items[row];
 
     // would make sence if item came from search which isn't
     // currently the case on the TV

+ 1 - 0
Podfile

@@ -32,4 +32,5 @@ pod 'upnpx', '~>1.3.6'
 pod 'CocoaHTTPServer', :git => 'git://github.com/fkuehne/CocoaHTTPServer.git' # has our fixes
 pod 'MetaDataFetcherKit', :git => 'https://code.videolan.org/fkuehne/MetaDataFetcherKit.git', :commit => '81c45087'
 pod "OROpenSubtitleDownloader", :git => 'https://github.com/orta/OROpenSubtitleDownloader.git', :commit => '0509eac2'
+pod 'GRKArrayDiff', :git => 'https://github.com/vlcone/GRKArrayDiff.git', :branch => 'patch-1' # added tvOS target
 end

+ 9 - 0
Podfile.lock

@@ -18,6 +18,7 @@ PODS:
     - box-ios-sdk-v2/no-arc (= 1.2.3)
   - box-ios-sdk-v2/no-arc (1.2.3)
   - CocoaHTTPServer (2.3)
+  - GRKArrayDiff (2.0)
   - HockeySDK (3.6.4)
   - InAppSettingsKit (2.2.2)
   - MetaDataFetcherKit (0.2.0):
@@ -37,6 +38,7 @@ PODS:
 DEPENDENCIES:
   - box-ios-sdk-v2 (from `git://github.com/fkuehne/box-ios-sdk-v2.git`)
   - CocoaHTTPServer (from `git://github.com/fkuehne/CocoaHTTPServer.git`)
+  - GRKArrayDiff (from `https://github.com/vlcone/GRKArrayDiff.git`, branch `patch-1`)
   - HockeySDK (~> 3.6.4)
   - InAppSettingsKit (from `git://github.com/fkuehne/InAppSettingsKit.git`, commit
     `415ea6bb`)
@@ -54,6 +56,9 @@ EXTERNAL SOURCES:
     :git: git://github.com/fkuehne/box-ios-sdk-v2.git
   CocoaHTTPServer:
     :git: git://github.com/fkuehne/CocoaHTTPServer.git
+  GRKArrayDiff:
+    :branch: patch-1
+    :git: https://github.com/vlcone/GRKArrayDiff.git
   InAppSettingsKit:
     :commit: 415ea6bb
     :git: git://github.com/fkuehne/InAppSettingsKit.git
@@ -73,6 +78,9 @@ CHECKOUT OPTIONS:
   CocoaHTTPServer:
     :commit: 570343ea4207c832e08e8d368b5e6faf35307031
     :git: git://github.com/fkuehne/CocoaHTTPServer.git
+  GRKArrayDiff:
+    :commit: edc471b0a8c953d04b8c3adf931e42dc21485a1a
+    :git: https://github.com/vlcone/GRKArrayDiff.git
   InAppSettingsKit:
     :commit: 415ea6bb
     :git: git://github.com/fkuehne/InAppSettingsKit.git
@@ -90,6 +98,7 @@ SPEC CHECKSUMS:
   AFNetworking: 1100906802d9479aa0949e8e2cbc1d4e6beba327
   box-ios-sdk-v2: 9423bd75373350ea40b92f3d2d6e89f81d96d634
   CocoaHTTPServer: 07df8b05a8bde406fe367d22c90a24a2fd4ca49f
+  GRKArrayDiff: 212b45aacf6c5f691d4ee5207bfc7b9a4ececdd6
   HockeySDK: c07cdd580296737edcd0963e292c19885a53f563
   InAppSettingsKit: 76d5cfbaa3e3f8aa53fe3628516da7eb1aa6a5cb
   MetaDataFetcherKit: 6cbb2f651c56e16015ec08535e090bc923deb6cb

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

@@ -560,6 +560,7 @@
 		DD9D8F651C01F96700B4060F /* VLCPlaybackInfoChaptersTVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D8F631C01F96700B4060F /* VLCPlaybackInfoChaptersTVViewController.m */; };
 		DD9D8F681C01FAB500B4060F /* VLCPlaybackInfoChaptersTVViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD9D8F671C01FAB500B4060F /* VLCPlaybackInfoChaptersTVViewController.xib */; };
 		DD9D8F6B1C01FE5B00B4060F /* VLCPlaybackInfoCollectionViewDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D8F6A1C01FE5B00B4060F /* VLCPlaybackInfoCollectionViewDataSource.m */; };
+		DDA1B8EE1CD4DC2A0076BC45 /* GRKArrayDiff+UICollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = DDA1B8ED1CD4DC2A0076BC45 /* GRKArrayDiff+UICollectionView.m */; };
 		DDAD5C2B1BB999CA006AFD3B /* VLCMovieViewControlPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = DDAD5C2A1BB999CA006AFD3B /* VLCMovieViewControlPanel.xib */; };
 		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 */; };
@@ -1363,6 +1364,8 @@
 		DD9FBE751BAD6BB600FFE77A /* WKInterfaceController+VLCConnectionAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WKInterfaceController+VLCConnectionAlert.h"; sourceTree = "<group>"; };
 		DD9FBE761BAD6BB600FFE77A /* WKInterfaceController+VLCConnectionAlert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "WKInterfaceController+VLCConnectionAlert.m"; sourceTree = "<group>"; };
 		DD9FBE791BADA8E300FFE77A /* VLC WatchKit Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = "VLC WatchKit Extension.entitlements"; path = "../VLC WatchKit Extension.entitlements"; sourceTree = "<group>"; };
+		DDA1B8EC1CD4DC2A0076BC45 /* GRKArrayDiff+UICollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GRKArrayDiff+UICollectionView.h"; sourceTree = "<group>"; };
+		DDA1B8ED1CD4DC2A0076BC45 /* GRKArrayDiff+UICollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GRKArrayDiff+UICollectionView.m"; sourceTree = "<group>"; };
 		DDAD5C2A1BB999CA006AFD3B /* VLCMovieViewControlPanel.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = VLCMovieViewControlPanel.xib; path = Resources/VLCMovieViewControlPanel.xib; sourceTree = SOURCE_ROOT; };
 		DDAD5C2C1BB9A1E6006AFD3B /* VLCMovieViewControlPanelViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCMovieViewControlPanelViewController.h; path = Sources/VLCMovieViewControlPanelViewController.h; sourceTree = SOURCE_ROOT; };
 		DDAD5C2D1BB9A1E6006AFD3B /* VLCMovieViewControlPanelViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCMovieViewControlPanelViewController.m; path = Sources/VLCMovieViewControlPanelViewController.m; sourceTree = SOURCE_ROOT; };
@@ -2326,6 +2329,8 @@
 				DD9D8F5E1C00C73F00B4060F /* VLCDeleteHintTVView.m */,
 				7D6262181C18AECD00F7CB24 /* VLCDeletionCapableViewController.h */,
 				7D6262191C18AECD00F7CB24 /* VLCDeletionCapableViewController.m */,
+				DDA1B8EC1CD4DC2A0076BC45 /* GRKArrayDiff+UICollectionView.h */,
+				DDA1B8ED1CD4DC2A0076BC45 /* GRKArrayDiff+UICollectionView.m */,
 			);
 			name = "Common Code";
 			sourceTree = "<group>";
@@ -3401,6 +3406,7 @@
 				DD3EFF521BDEBCE500B68579 /* VLCPlexWebAPI.m in Sources */,
 				7D0EDE091BE7752800363AA1 /* VLCLocalNetworkServiceBrowserFTP.m in Sources */,
 				7DF383C11BF231BC00D71A5C /* VLCCloudStorageTVViewController.m in Sources */,
+				DDA1B8EE1CD4DC2A0076BC45 /* GRKArrayDiff+UICollectionView.m in Sources */,
 				DD8095F91BE6268A0065D8E1 /* VLCPlaybackInfoPanelTVViewController.m in Sources */,
 				DD3EABE91BE13D5B003668DA /* VLCRemoteBrowsingTVCell.m in Sources */,
 				7DEBF3791C075EBC007A4043 /* VLCPlaybackInfoSubtitlesFetcherViewController.m in Sources */,