Quellcode durchsuchen

allow deletion of cached files

Tobias Conradi vor 9 Jahren
Ursprung
Commit
cc7c864114

+ 117 - 1
Apple-TV/VLCRemotePlaybackViewController.m

@@ -5,6 +5,7 @@
  * $Id$
  *
  * Authors: Felix Paul Kühne <fkuehne # videolan.org>
+ *          Tobias Conradi <videolan # tobias-conradi.de>
  *
  * Refer to the COPYING file of the official project for license.
  *****************************************************************************/
@@ -15,14 +16,20 @@
 #import "VLCMediaFileDiscoverer.h"
 #import "VLCRemoteBrowsingTVCell.h"
 #import "VLCMaskView.h"
+#import "CAAnimation+VLCWiggle.h"
 
 #define remotePlaybackReuseIdentifer @"remotePlaybackReuseIdentifer"
 
+static NSString *const VLCWiggleAnimationKey = @"VLCWiggleAnimation";
+
 @interface VLCRemotePlaybackViewController () <UICollectionViewDataSource, UICollectionViewDelegate, VLCMediaFileDiscovererDelegate>
 {
     Reachability *_reachability;
-    NSMutableArray *_discoveredFiles;
+    NSMutableArray<NSString *> *_discoveredFiles;
 }
+@property (nonatomic) UITapGestureRecognizer *playPausePressRecognizer;
+@property (nonatomic) UITapGestureRecognizer *cancelRecognizer;
+@property (nonatomic) NSIndexPath *currentlyFocusedIndexPath;
 @end
 
 @implementation VLCRemotePlaybackViewController
@@ -62,6 +69,22 @@
     discoverer.directoryPath = [[searchPaths firstObject] stringByAppendingPathComponent:@"Upload"];
     [discoverer addObserver:self];
     [discoverer startDiscovering];
+
+    UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(startEditMode)];
+    recognizer.allowedPressTypes = @[@(UIPressTypeSelect)];
+    recognizer.minimumPressDuration = 1.0;
+    [self.view addGestureRecognizer:recognizer];
+
+    UITapGestureRecognizer *cancelRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(endEditMode)];
+    cancelRecognizer.allowedPressTypes = @[@(UIPressTypeSelect),@(UIPressTypeMenu)];
+    self.cancelRecognizer = cancelRecognizer;
+    [self.view addGestureRecognizer:cancelRecognizer];
+
+    UITapGestureRecognizer *playPauseRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handlePlayPausePress)];
+    playPauseRecognizer.allowedPressTypes = @[@(UIPressTypePlayPause)];
+    self.playPausePressRecognizer = playPauseRecognizer;
+    [self.view addGestureRecognizer:playPauseRecognizer];
+
 }
 
 - (void)viewDidLayoutSubviews
@@ -132,6 +155,83 @@
     [[NSUserDefaults standardUserDefaults] synchronize];
 }
 
+
+- (void)handlePlayPausePress
+{
+    NSIndexPath *indexPathToDelete = self.currentlyFocusedIndexPath;
+    if (!indexPathToDelete) {
+        return;
+    }
+    NSString *fileToDelete = nil;
+    @synchronized(_discoveredFiles) {
+        fileToDelete = _discoveredFiles[indexPathToDelete.item];
+    }
+
+    NSString *title = fileToDelete.lastPathComponent;
+    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title
+                                                                             message:nil
+                                                                      preferredStyle:UIAlertControllerStyleAlert];
+    UIAlertAction *deleteAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"BUTTON_DELETE", nil)
+                                                           style:UIAlertActionStyleDestructive
+                                                         handler:^(UIAlertAction * _Nonnull action) {
+                                                             [self deleteFileAtIndex:indexPathToDelete];
+                                                         }];
+    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"BUTTON_CANCEL", nil)
+                                                           style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
+                                                               self.editing = NO;
+                                                           }];
+
+    [alertController addAction:deleteAction];
+    [alertController addAction:cancelAction];
+    [self presentViewController:alertController animated:YES completion:nil];
+}
+
+- (void)deleteFileAtIndex:(NSIndexPath *)indexPathToDelete
+{
+    if (!indexPathToDelete) {
+        return;
+    }
+    __block NSString *fileToDelete = nil;
+    [self.cachedMediaCollectionView performBatchUpdates:^{
+        @synchronized(_discoveredFiles) {
+            fileToDelete = _discoveredFiles[indexPathToDelete.item];
+            [_discoveredFiles removeObject:fileToDelete];
+        }
+        [self.cachedMediaCollectionView deleteItemsAtIndexPaths:@[indexPathToDelete]];
+
+    } completion:^(BOOL finished) {
+        [[NSFileManager defaultManager] removeItemAtPath:fileToDelete error:nil];
+        self.editing = NO;
+    }];
+
+}
+
+- (void)startEditMode
+{
+    self.editing = YES;
+}
+- (void)endEditMode
+{
+    self.editing = NO;
+}
+
+- (void)setEditing:(BOOL)editing
+{
+    [super setEditing:editing];
+
+    UICollectionViewCell *focusedCell = [self.cachedMediaCollectionView cellForItemAtIndexPath:self.currentlyFocusedIndexPath];
+
+    if (editing) {
+        [focusedCell.layer addAnimation:[CAAnimation vlc_wiggleAnimation]
+                                 forKey:VLCWiggleAnimationKey];
+    } else {
+        [focusedCell.layer removeAnimationForKey:VLCWiggleAnimationKey];
+    }
+
+    self.cancelRecognizer.enabled = editing;
+    self.playPausePressRecognizer.enabled = editing;
+}
+
 #pragma mark - collection view data source
 
 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
@@ -171,6 +271,22 @@
 
     return ret;
 }
+-(BOOL)collectionView:(UICollectionView *)collectionView shouldUpdateFocusInContext:(UICollectionViewFocusUpdateContext *)context
+{
+    if (self.editing) {
+        return context.nextFocusedIndexPath == nil;
+    }
+    return YES;
+}
+
+- (void)collectionView:(UICollectionView *)collectionView didUpdateFocusInContext:(UICollectionViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
+{
+    NSIndexPath *nextPath = context.nextFocusedIndexPath;
+    if (!nextPath) {
+        self.editing = NO;
+    }
+    self.currentlyFocusedIndexPath = nextPath;
+}
 
 #pragma mark - collection view delegate
 

+ 16 - 0
SharedSources/CAAnimation+VLCWiggle.h

@@ -0,0 +1,16 @@
+/*****************************************************************************
+ * 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.
+ *****************************************************************************/
+
+#import <QuartzCore/QuartzCore.h>
+
+@interface CAAnimation (VLCWiggle)
++ (instancetype)vlc_wiggleAnimation;
+@end

+ 52 - 0
SharedSources/CAAnimation+VLCWiggle.m

@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * 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.
+ *****************************************************************************/
+
+#import "CAAnimation+VLCWiggle.h"
+
+@implementation CAAnimation (VLCWiggle)
++ (instancetype)vlc_wiggleAnimation
+{
+    CAKeyframeAnimation *position = [CAKeyframeAnimation animation];
+    position.keyPath = @"position";
+    position.values = @[
+                        [NSValue valueWithCGPoint:CGPointZero],
+                        [NSValue valueWithCGPoint:CGPointMake(-1, 0)],
+                        [NSValue valueWithCGPoint:CGPointMake(1, 0)],
+                        [NSValue valueWithCGPoint:CGPointMake(-1, 1)],
+                        [NSValue valueWithCGPoint:CGPointMake(1, -1)],
+                        [NSValue valueWithCGPoint:CGPointZero]
+                        ];
+    position.timingFunctions = @[
+                                 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
+                                 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]
+                                 ];
+    position.additive = YES;
+
+    CAKeyframeAnimation *rotation = [CAKeyframeAnimation animation];
+    rotation.keyPath = @"transform.rotation";
+    rotation.values = @[
+                        @0,
+                        @0.03,
+                        @0,
+                        [NSNumber numberWithFloat:-0.02]
+                        ];
+    rotation.timingFunctions = @[
+                                 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
+                                 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]
+                                 ];
+
+    CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
+    group.animations = @[position, rotation];
+    group.duration = 0.4;
+    group.repeatCount = HUGE_VALF;
+    return group;
+}
+@end

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

@@ -344,6 +344,7 @@
 		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 */; };
+		DDBE44FF1BFB6A8B00E5D35E /* CAAnimation+VLCWiggle.m in Sources */ = {isa = PBXBuildFile; fileRef = DDBE44FE1BFB6A8B00E5D35E /* CAAnimation+VLCWiggle.m */; };
 		DDC10BE41AEE8EA700890DC3 /* VLCTimeNavigationTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = DDC10BE31AEE8EA700890DC3 /* VLCTimeNavigationTitleView.m */; };
 		DDDEA6AF1BE027FA000BB7A2 /* VLCServerBrowsingTVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDEA6AE1BE027FA000BB7A2 /* VLCServerBrowsingTVViewController.m */; };
 		DDEAECBE1BDEBF6700756C83 /* VLCNetworkServerLoginInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = DDEAECBD1BDEBF6700756C83 /* VLCNetworkServerLoginInformation.m */; };
@@ -1029,6 +1030,8 @@
 		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; };
 		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>"; };
+		DDBE44FD1BFB6A8B00E5D35E /* CAAnimation+VLCWiggle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CAAnimation+VLCWiggle.h"; sourceTree = "<group>"; };
+		DDBE44FE1BFB6A8B00E5D35E /* CAAnimation+VLCWiggle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CAAnimation+VLCWiggle.m"; 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 /* VLCServerBrowsingTVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCServerBrowsingTVViewController.h; sourceTree = "<group>"; };
@@ -2184,6 +2187,8 @@
 				DD3EABFB1BE14C4B003668DA /* UIViewController+VLCAlert.m */,
 				DD3EA62F1AF50CFE007FF096 /* VLCWatchMessage.h */,
 				DD3EA6301AF50CFE007FF096 /* VLCWatchMessage.m */,
+				DDBE44FD1BFB6A8B00E5D35E /* CAAnimation+VLCWiggle.h */,
+				DDBE44FE1BFB6A8B00E5D35E /* CAAnimation+VLCWiggle.m */,
 			);
 			path = SharedSources;
 			sourceTree = "<group>";
@@ -2732,6 +2737,7 @@
 				7D405ED31BEA11CD006ED886 /* VLCHTTPUploaderController.m in Sources */,
 				7DF90B4B1BE7A8110059C0E3 /* IASKSpecifier.m in Sources */,
 				7D0EDE0A1BE7752C00363AA1 /* VLCNetworkServerBrowserFTP.m in Sources */,
+				DDBE44FF1BFB6A8B00E5D35E /* CAAnimation+VLCWiggle.m in Sources */,
 				DD3EFF4E1BDEBCE500B68579 /* VLCNetworkServerBrowserPlex.m in Sources */,
 				7DF90B4A1BE7A8110059C0E3 /* IASKSettingsReader.m in Sources */,
 				DD3EFF3E1BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserHTTP.m in Sources */,