Преглед изворни кода

Merge branch 'filesystem-actions'

Ryan Olson пре 11 година
родитељ
комит
491ba78729

+ 33 - 0
Classes/Global State Explorers/FLEXFileBrowserFileOperationController.h

@@ -0,0 +1,33 @@
+//
+//  FLEXFileBrowserFileOperationController.h
+//  Flipboard
+//
+//  Created by Daniel Rodriguez Troitino on 2/13/15.
+//  Copyright (c) 2015 Flipboard. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@protocol FLEXFileBrowserFileOperationController;
+
+@protocol FLEXFileBrowserFileOperationControllerDelegate <NSObject>
+
+- (void)fileOperationControllerDidDismiss:(id<FLEXFileBrowserFileOperationController>)controller;
+
+@end
+
+@protocol FLEXFileBrowserFileOperationController <NSObject>
+
+@property (nonatomic, weak) id<FLEXFileBrowserFileOperationControllerDelegate> delegate;
+
+- (instancetype)initWithPath:(NSString *)path;
+
+- (void)show;
+
+@end
+
+@interface FLEXFileBrowserFileDeleteOperationController : NSObject <FLEXFileBrowserFileOperationController>
+@end
+
+@interface FLEXFileBrowserFileRenameOperationController : NSObject <FLEXFileBrowserFileOperationController>
+@end

+ 137 - 0
Classes/Global State Explorers/FLEXFileBrowserFileOperationController.m

@@ -0,0 +1,137 @@
+//
+//  FLEXFileBrowserFileOperationController.m
+//  Flipboard
+//
+//  Created by Daniel Rodriguez Troitino on 2/13/15.
+//  Copyright (c) 2015 Flipboard. All rights reserved.
+//
+
+#import "FLEXFileBrowserFileOperationController.h"
+
+@interface FLEXFileBrowserFileDeleteOperationController () <UIAlertViewDelegate>
+
+@property (nonatomic, copy, readonly) NSString *path;
+
+@end
+
+@implementation FLEXFileBrowserFileDeleteOperationController
+
+@synthesize delegate = _delegate;
+
+- (instancetype)init
+{
+    return [self initWithPath:nil];
+}
+
+- (instancetype)initWithPath:(NSString *)path
+{
+    self = [super init];
+    if (self) {
+        _path = path;
+    }
+
+    return self;
+}
+
+- (void)show
+{
+    BOOL isDirectory = NO;
+    BOOL stillExists = [[NSFileManager defaultManager] fileExistsAtPath:self.path isDirectory:&isDirectory];
+
+    if (stillExists) {
+        UIAlertView *deleteWarning = [[UIAlertView alloc]
+                                      initWithTitle:[NSString stringWithFormat:@"Delete %@?", self.path.lastPathComponent]
+                                      message:[NSString stringWithFormat:@"The %@ will be deleted. This operation cannot be undone", isDirectory ? @"directory" : @"file"]
+                                      delegate:self
+                                      cancelButtonTitle:@"Cancel"
+                                      otherButtonTitles:@"Delete", nil];
+        [deleteWarning show];
+    } else {
+        [[[UIAlertView alloc] initWithTitle:@"File Removed" message:@"The file at the specified path no longer exists." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
+    }
+}
+
+#pragma mark - UIAlertViewDelegate
+
+- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
+{
+    if (buttonIndex == alertView.cancelButtonIndex) {
+        // Nothing, just cancel
+    } else if (buttonIndex == alertView.firstOtherButtonIndex) {
+        [[NSFileManager defaultManager] removeItemAtPath:self.path error:NULL];
+    }
+}
+
+- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
+{
+    [self.delegate fileOperationControllerDidDismiss:self];
+}
+
+@end
+
+@interface FLEXFileBrowserFileRenameOperationController () <UIAlertViewDelegate>
+
+@property (nonatomic, copy, readonly) NSString *path;
+
+@end
+
+@implementation FLEXFileBrowserFileRenameOperationController
+
+@synthesize delegate = _delegate;
+
+- (instancetype)init
+{
+    return [self initWithPath:nil];
+}
+
+- (instancetype)initWithPath:(NSString *)path
+{
+    self = [super init];
+    if (self) {
+        _path = path;
+    }
+
+    return self;
+}
+
+- (void)show
+{
+    BOOL isDirectory = NO;
+    BOOL stillExists = [[NSFileManager defaultManager] fileExistsAtPath:self.path isDirectory:&isDirectory];
+
+    if (stillExists) {
+        UIAlertView *renameDialog = [[UIAlertView alloc]
+                                     initWithTitle:[NSString stringWithFormat:@"Rename %@?", self.path.lastPathComponent]
+                                     message:nil
+                                     delegate:self
+                                     cancelButtonTitle:@"Cancel"
+                                     otherButtonTitles:@"Rename", nil];
+        renameDialog.alertViewStyle = UIAlertViewStylePlainTextInput;
+        UITextField *textField = [renameDialog textFieldAtIndex:0];
+        textField.placeholder = @"New file name";
+        textField.text = self.path.lastPathComponent;
+        [renameDialog show];
+    } else {
+        [[[UIAlertView alloc] initWithTitle:@"File Removed" message:@"The file at the specified path no longer exists." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
+    }
+}
+
+#pragma mark - UIAlertViewDelegate
+
+- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
+{
+    if (buttonIndex == alertView.cancelButtonIndex) {
+        // Nothing, just cancel
+    } else if (buttonIndex == alertView.firstOtherButtonIndex) {
+        NSString *newFileName = [alertView textFieldAtIndex:0].text;
+        NSString *newPath = [[self.path stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFileName];
+        [[NSFileManager defaultManager] moveItemAtPath:self.path toPath:newPath error:NULL];
+    }
+}
+
+- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
+{
+    [self.delegate fileOperationControllerDidDismiss:self];
+}
+
+@end

+ 125 - 12
Classes/Global State Explorers/FLEXFileBrowserTableViewController.m

@@ -7,20 +7,26 @@
 //
 
 #import "FLEXFileBrowserTableViewController.h"
+#import "FLEXFileBrowserFileOperationController.h"
 #import "FLEXUtility.h"
 #import "FLEXWebViewController.h"
 #import "FLEXImagePreviewViewController.h"
 
-@interface FLEXFileBrowserTableViewController ()
+@interface FLEXFileBrowserTableViewCell : UITableViewCell
+@end
+
+@interface FLEXFileBrowserTableViewController () <FLEXFileBrowserFileOperationControllerDelegate>
 
 @property (nonatomic, copy) NSString *path;
 @property (nonatomic, copy) NSArray *childPaths;
+@property (nonatomic, copy) NSString *searchString;
 @property (nonatomic, strong) NSArray *searchPaths;
 @property (nonatomic, strong) NSNumber *recursiveSize;
 @property (nonatomic, strong) NSNumber *searchPathsSize;
 @property (nonatomic, strong) UISearchDisplayController *searchController;
 @property (nonatomic) NSOperationQueue *operationQueue;
 @property (nonatomic, strong) UIDocumentInteractionController *documentController;
+@property (nonatomic, strong) id<FLEXFileBrowserFileOperationController> fileOperationController;
 
 @end
 
@@ -71,12 +77,23 @@
                 [strongSelf.tableView reloadData];
             });
         });
-        
-        self.childPaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];
+
+        [self reloadChildPaths];
     }
     return self;
 }
 
+#pragma mark - UIViewController
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+
+    UIMenuItem *renameMenuItem = [[UIMenuItem alloc] initWithTitle:@"Rename" action:@selector(fileBrowserRename:)];
+    UIMenuItem *deleteMenuItem = [[UIMenuItem alloc] initWithTitle:@"Delete" action:@selector(fileBrowserDelete:)];
+    [UIMenuController sharedMenuController].menuItems = @[renameMenuItem, deleteMenuItem];
+}
+
 #pragma mark - FLEXFileBrowserSearchOperationDelegate
 
 - (void)fileBrowserSearchOperationResult:(NSArray *)searchResult size:(uint64_t)size
@@ -90,14 +107,8 @@
 
 - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
 {
-    self.searchPaths = nil;
-    self.searchPathsSize = nil;
-    
-    //clear pre search request and start a new one
-    [self.operationQueue cancelAllOperations];
-    FLEXFileBrowserSearchOperation *newOperation = [[FLEXFileBrowserSearchOperation alloc] initWithPath:self.path searchString:searchString];
-    newOperation.delegate = self;
-    [self.operationQueue addOperation:newOperation];
+    self.searchString = searchString;
+    [self reloadSearchPaths];
 
     return YES;
 }
@@ -106,6 +117,8 @@
 {
     //confirm to clear all operations
     [self.operationQueue cancelAllOperations];
+    [self reloadChildPaths];
+    [self.tableView reloadData];
 }
 
 
@@ -178,7 +191,7 @@
     NSString *cellIdentifier = showImagePreview ? imageCellIdentifier : textCellIdentifier;
     
     if (!cell) {
-        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
+        cell = [[FLEXFileBrowserTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
         cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];
         cell.detailTextLabel.font = [FLEXUtility defaultTableViewCellLabelFont];
         cell.detailTextLabel.textColor = [UIColor grayColor];
@@ -253,9 +266,31 @@
         }
     } else {
         [[[UIAlertView alloc] initWithTitle:@"File Removed" message:@"The file at the specified path no longer exists." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
+        [self reloadDisplayedPaths];
     }
 }
 
+- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    return YES;
+}
+
+- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
+{
+    return action == @selector(fileBrowserDelete:) || action == @selector(fileBrowserRename:);
+}
+
+- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
+{
+    // Empty, but has to exist for the menu to show
+}
+
+#pragma mark - FLEXFileBrowserFileOperationControllerDelegate
+
+- (void)fileOperationControllerDidDismiss:(id<FLEXFileBrowserFileOperationController>)controller {
+    [self reloadDisplayedPaths];
+}
+
 - (void)openFileController:(NSString *)fullPath
 {
     UIDocumentInteractionController *controller = [UIDocumentInteractionController new];
@@ -265,4 +300,82 @@
     self.documentController = controller;
 }
 
+- (void)fileBrowserRename:(UITableViewCell *)sender
+{
+    NSString *fullPath = nil;
+
+    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
+    if (indexPath) {
+        NSString *subpath = [self.childPaths objectAtIndex:indexPath.row];
+        fullPath = [self.path stringByAppendingPathComponent:subpath];
+    } else {
+        indexPath = [self.searchDisplayController.searchResultsTableView indexPathForCell:sender];
+        fullPath = [self.searchPaths objectAtIndex:indexPath.row];
+    }
+
+    self.fileOperationController = [[FLEXFileBrowserFileRenameOperationController alloc] initWithPath:fullPath];
+    self.fileOperationController.delegate = self;
+    [self.fileOperationController show];
+}
+
+- (void)fileBrowserDelete:(UITableViewCell *)sender
+{
+    NSString *fullPath = nil;
+
+    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
+    if (indexPath) {
+        NSString *subpath = [self.childPaths objectAtIndex:indexPath.row];
+        fullPath = [self.path stringByAppendingPathComponent:subpath];
+    } else {
+        indexPath = [self.searchDisplayController.searchResultsTableView indexPathForCell:sender];
+        fullPath = [self.searchPaths objectAtIndex:indexPath.row];
+    }
+
+    self.fileOperationController = [[FLEXFileBrowserFileDeleteOperationController alloc] initWithPath:fullPath];
+    self.fileOperationController.delegate = self;
+    [self.fileOperationController show];
+}
+
+- (void)reloadDisplayedPaths {
+    if (self.searchDisplayController.isActive) {
+        [self reloadSearchPaths];
+        [self.searchDisplayController.searchResultsTableView reloadData];
+    } else {
+        [self reloadChildPaths];
+        [self.tableView reloadData];
+    }
+}
+
+- (void)reloadChildPaths {
+    self.childPaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.path error:NULL];
+}
+
+- (void)reloadSearchPaths {
+    self.searchPaths = nil;
+    self.searchPathsSize = nil;
+
+    //clear pre search request and start a new one
+    [self.operationQueue cancelAllOperations];
+    FLEXFileBrowserSearchOperation *newOperation = [[FLEXFileBrowserSearchOperation alloc] initWithPath:self.path searchString:self.searchString];
+    newOperation.delegate = self;
+    [self.operationQueue addOperation:newOperation];
+}
+
+@end
+
+
+@implementation FLEXFileBrowserTableViewCell
+
+- (void)fileBrowserRename:(UIMenuController *)sender
+{
+    id target = [self.nextResponder targetForAction:_cmd withSender:sender];
+    [[UIApplication sharedApplication] sendAction:_cmd to:target from:self forEvent:nil];
+}
+
+- (void)fileBrowserDelete:(UIMenuController *)sender
+{
+    id target = [self.nextResponder targetForAction:_cmd withSender:sender];
+    [[UIApplication sharedApplication] sendAction:_cmd to:target from:self forEvent:nil];
+}
+
 @end

+ 6 - 0
Example/UICatalog.xcodeproj/project.pbxproj

@@ -44,6 +44,7 @@
 		535682BF18F3670300BAAD62 /* UIColor+AAPLApplicationSpecific.m in Sources */ = {isa = PBXBuildFile; fileRef = 535682A618F3670300BAAD62 /* UIColor+AAPLApplicationSpecific.m */; };
 		53874F9918F36B1800510922 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 53874F9718F36B1800510922 /* Localizable.strings */; };
 		650855EB1A9007D5006109A1 /* FLEXArgumentInputDateView.m in Sources */ = {isa = PBXBuildFile; fileRef = 650855EA1A9007D5006109A1 /* FLEXArgumentInputDateView.m */; };
+		65F8DC6C1A8F11020076F87B /* FLEXFileBrowserFileOperationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 65F8DC6B1A8F11020076F87B /* FLEXFileBrowserFileOperationController.m */; };
 		943203FE1978F42F00E24DB3 /* AAPLCatalogTableTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 943203FD1978F42F00E24DB3 /* AAPLCatalogTableTableViewController.m */; };
 		944F7489197B458C009AB039 /* FLEXArrayExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7426197B458C009AB039 /* FLEXArrayExplorerViewController.m */; };
 		944F748A197B458C009AB039 /* FLEXClassExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 944F7428197B458C009AB039 /* FLEXClassExplorerViewController.m */; };
@@ -168,6 +169,8 @@
 		53874F9818F36B1800510922 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
 		650855E91A9007D5006109A1 /* FLEXArgumentInputDateView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArgumentInputDateView.h; sourceTree = "<group>"; };
 		650855EA1A9007D5006109A1 /* FLEXArgumentInputDateView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXArgumentInputDateView.m; sourceTree = "<group>"; };
+		65F8DC6A1A8F11020076F87B /* FLEXFileBrowserFileOperationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXFileBrowserFileOperationController.h; sourceTree = "<group>"; };
+		65F8DC6B1A8F11020076F87B /* FLEXFileBrowserFileOperationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXFileBrowserFileOperationController.m; sourceTree = "<group>"; };
 		943203FC1978F42F00E24DB3 /* AAPLCatalogTableTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AAPLCatalogTableTableViewController.h; sourceTree = "<group>"; };
 		943203FD1978F42F00E24DB3 /* AAPLCatalogTableTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AAPLCatalogTableTableViewController.m; sourceTree = "<group>"; };
 		944F7425197B458C009AB039 /* FLEXArrayExplorerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXArrayExplorerViewController.h; sourceTree = "<group>"; };
@@ -568,6 +571,8 @@
 				944F7475197B458C009AB039 /* FLEXClassesTableViewController.m */,
 				944F7476197B458C009AB039 /* FLEXFileBrowserTableViewController.h */,
 				944F7477197B458C009AB039 /* FLEXFileBrowserTableViewController.m */,
+				65F8DC6A1A8F11020076F87B /* FLEXFileBrowserFileOperationController.h */,
+				65F8DC6B1A8F11020076F87B /* FLEXFileBrowserFileOperationController.m */,
 				0149BFE0198FAFC700B90A1B /* FLEXFileBrowserSearchOperation.h */,
 				0149BFE1198FAFC700B90A1B /* FLEXFileBrowserSearchOperation.m */,
 				944F7478197B458C009AB039 /* FLEXGlobalsTableViewController.h */,
@@ -726,6 +731,7 @@
 				944F74B3197B458C009AB039 /* FLEXLiveObjectsTableViewController.m in Sources */,
 				944F748E197B458C009AB039 /* FLEXImageExplorerViewController.m in Sources */,
 				944F74B6197B458C009AB039 /* FLEXHierarchyTableViewController.m in Sources */,
+				65F8DC6C1A8F11020076F87B /* FLEXFileBrowserFileOperationController.m in Sources */,
 				535682BC18F3670300BAAD62 /* AAPLTextViewController.m in Sources */,
 				944F74B4197B458C009AB039 /* FLEXWebViewController.m in Sources */,
 				944F74A5197B458C009AB039 /* FLEXFieldEditorViewController.m in Sources */,