|
@@ -15,7 +15,11 @@
|
|
|
|
|
|
|
|
@property (nonatomic, copy) NSString *path;
|
|
@property (nonatomic, copy) NSString *path;
|
|
|
@property (nonatomic, copy) NSArray *childPaths;
|
|
@property (nonatomic, copy) NSArray *childPaths;
|
|
|
|
|
+@property (nonatomic, strong) NSArray *searchPaths;
|
|
|
@property (nonatomic, strong) NSNumber *recursiveSize;
|
|
@property (nonatomic, strong) NSNumber *recursiveSize;
|
|
|
|
|
+@property (nonatomic, strong) NSNumber *searchPathsSize;
|
|
|
|
|
+@property (nonatomic, strong) UISearchDisplayController *searchController;
|
|
|
|
|
+@property (nonatomic) NSOperationQueue *operationQueue;
|
|
|
|
|
|
|
|
@end
|
|
@end
|
|
|
|
|
|
|
@@ -32,10 +36,21 @@
|
|
|
if (self) {
|
|
if (self) {
|
|
|
self.path = path;
|
|
self.path = path;
|
|
|
self.title = [path lastPathComponent];
|
|
self.title = [path lastPathComponent];
|
|
|
|
|
+ self.operationQueue = [NSOperationQueue new];
|
|
|
|
|
|
|
|
|
|
+ //add search controller
|
|
|
|
|
+ UISearchBar *searchBar = [UISearchBar new];
|
|
|
|
|
+ [searchBar sizeToFit];
|
|
|
|
|
+ self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
|
|
|
|
|
+ self.searchController.delegate = self;
|
|
|
|
|
+ self.searchController.searchResultsDataSource = self;
|
|
|
|
|
+ self.searchController.searchResultsDelegate = self;
|
|
|
|
|
+ self.tableView.tableHeaderView = self.searchController.searchBar;
|
|
|
|
|
+
|
|
|
|
|
+ //computing path size
|
|
|
FLEXFileBrowserTableViewController *__weak weakSelf = self;
|
|
FLEXFileBrowserTableViewController *__weak weakSelf = self;
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
|
- NSFileManager *fileManager = [[NSFileManager alloc] init];
|
|
|
|
|
|
|
+ NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
|
NSDictionary *attributes = [fileManager attributesOfItemAtPath:path error:NULL];
|
|
NSDictionary *attributes = [fileManager attributesOfItemAtPath:path error:NULL];
|
|
|
uint64_t totalSize = [attributes fileSize];
|
|
uint64_t totalSize = [attributes fileSize];
|
|
|
|
|
|
|
@@ -61,6 +76,37 @@
|
|
|
return self;
|
|
return self;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+#pragma mark - FLEXFileBrowserSearchOperationDelegate
|
|
|
|
|
+
|
|
|
|
|
+- (void)fileBrowserSearchOperationResult:(NSArray *)searchResult size:(uint64_t)size
|
|
|
|
|
+{
|
|
|
|
|
+ self.searchPaths = searchResult;
|
|
|
|
|
+ self.searchPathsSize = @(size);
|
|
|
|
|
+ [self.searchController.searchResultsTableView reloadData];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#pragma mark - UISearchDisplayDelegate
|
|
|
|
|
+
|
|
|
|
|
+- (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];
|
|
|
|
|
+
|
|
|
|
|
+ return YES;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+- (void)searchDisplayController:(UISearchDisplayController *)controller willHideSearchResultsTableView:(UITableView *)tableView
|
|
|
|
|
+{
|
|
|
|
|
+ //confirm to clear all operations
|
|
|
|
|
+ [self.operationQueue cancelAllOperations];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
|
|
|
#pragma mark - Table view data source
|
|
#pragma mark - Table view data source
|
|
|
|
|
|
|
@@ -71,25 +117,49 @@
|
|
|
|
|
|
|
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
|
|
{
|
|
{
|
|
|
- return [self.childPaths count];
|
|
|
|
|
|
|
+ if (tableView == self.tableView) {
|
|
|
|
|
+ return [self.childPaths count];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return [self.searchPaths count];
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
|
|
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
|
|
|
{
|
|
{
|
|
|
|
|
+ NSNumber *currentSize;
|
|
|
|
|
+ NSArray *currentPaths;
|
|
|
|
|
+
|
|
|
|
|
+ if (tableView == self.tableView) {
|
|
|
|
|
+ currentSize = self.recursiveSize;
|
|
|
|
|
+ currentPaths = self.childPaths;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ currentSize = self.searchPathsSize;
|
|
|
|
|
+ currentPaths = self.searchPaths;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
NSString *sizeString = nil;
|
|
NSString *sizeString = nil;
|
|
|
- if (!self.recursiveSize) {
|
|
|
|
|
|
|
+ if (!currentSize) {
|
|
|
sizeString = @"Computing size…";
|
|
sizeString = @"Computing size…";
|
|
|
} else {
|
|
} else {
|
|
|
- sizeString = [NSByteCountFormatter stringFromByteCount:[self.recursiveSize longLongValue] countStyle:NSByteCountFormatterCountStyleFile];
|
|
|
|
|
|
|
+ sizeString = [NSByteCountFormatter stringFromByteCount:[currentSize longLongValue] countStyle:NSByteCountFormatterCountStyleFile];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return [NSString stringWithFormat:@"%lu files (%@)", (unsigned long)[self.childPaths count], sizeString];
|
|
|
|
|
|
|
+ return [NSString stringWithFormat:@"%lu files (%@)", (unsigned long)[currentPaths count], sizeString];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
|
{
|
|
{
|
|
|
- NSString *subpath = [self.childPaths objectAtIndex:indexPath.row];
|
|
|
|
|
- NSString *fullPath = [self.path stringByAppendingPathComponent:subpath];
|
|
|
|
|
|
|
+ NSString *subpath;
|
|
|
|
|
+ NSString *fullPath;
|
|
|
|
|
+
|
|
|
|
|
+ if (tableView == self.tableView) {
|
|
|
|
|
+ subpath = [self.childPaths objectAtIndex:indexPath.row];
|
|
|
|
|
+ fullPath = [self.path stringByAppendingPathComponent:subpath];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ fullPath = [self.searchPaths objectAtIndex:indexPath.row];
|
|
|
|
|
+ subpath = [fullPath lastPathComponent];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:NULL];
|
|
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:NULL];
|
|
|
BOOL isDirectory = [[attributes fileType] isEqual:NSFileTypeDirectory];
|
|
BOOL isDirectory = [[attributes fileType] isEqual:NSFileTypeDirectory];
|
|
|
NSString *subtitle = nil;
|
|
NSString *subtitle = nil;
|
|
@@ -108,7 +178,7 @@
|
|
|
// Separate image and text only cells because otherwise the separator lines get out-of-whack on image cells reused with text only.
|
|
// Separate image and text only cells because otherwise the separator lines get out-of-whack on image cells reused with text only.
|
|
|
BOOL showImagePreview = [FLEXUtility isImagePathExtension:[fullPath pathExtension]];
|
|
BOOL showImagePreview = [FLEXUtility isImagePathExtension:[fullPath pathExtension]];
|
|
|
NSString *cellIdentifier = showImagePreview ? imageCellIdentifier : textCellIdentifier;
|
|
NSString *cellIdentifier = showImagePreview ? imageCellIdentifier : textCellIdentifier;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!cell) {
|
|
if (!cell) {
|
|
|
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
|
|
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
|
|
|
cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];
|
|
cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];
|
|
@@ -116,7 +186,7 @@
|
|
|
cell.detailTextLabel.textColor = [UIColor grayColor];
|
|
cell.detailTextLabel.textColor = [UIColor grayColor];
|
|
|
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
|
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
|
|
}
|
|
}
|
|
|
- NSString *cellTitle = [subpath lastPathComponent];
|
|
|
|
|
|
|
+ NSString *cellTitle = [fullPath lastPathComponent];
|
|
|
cell.textLabel.text = cellTitle;
|
|
cell.textLabel.text = cellTitle;
|
|
|
cell.detailTextLabel.text = subtitle;
|
|
cell.detailTextLabel.text = subtitle;
|
|
|
|
|
|
|
@@ -130,8 +200,17 @@
|
|
|
|
|
|
|
|
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
|
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
|
|
{
|
|
{
|
|
|
- NSString *subpath = [self.childPaths objectAtIndex:indexPath.row];
|
|
|
|
|
- NSString *fullPath = [self.path stringByAppendingPathComponent:subpath];
|
|
|
|
|
|
|
+ NSString *subpath;
|
|
|
|
|
+ NSString *fullPath;
|
|
|
|
|
+
|
|
|
|
|
+ if (tableView == self.tableView) {
|
|
|
|
|
+ subpath = [self.childPaths objectAtIndex:indexPath.row];
|
|
|
|
|
+ fullPath = [self.path stringByAppendingPathComponent:subpath];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ fullPath = [self.searchPaths objectAtIndex:indexPath.row];
|
|
|
|
|
+ subpath = [fullPath lastPathComponent];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
BOOL isDirectory = NO;
|
|
BOOL isDirectory = NO;
|
|
|
BOOL stillExists = [[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDirectory];
|
|
BOOL stillExists = [[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDirectory];
|
|
|
if (stillExists) {
|
|
if (stillExists) {
|