mirror of
https://github.com/SoPat712/YTLitePlus.git
synced 2025-08-24 03:26:09 -04:00
234 lines
7.4 KiB
Objective-C
234 lines
7.4 KiB
Objective-C
//
|
|
// FLEXMetadataSection.m
|
|
// FLEX
|
|
//
|
|
// Created by Tanner Bennett on 9/19/19.
|
|
// Copyright © 2020 FLEX Team. All rights reserved.
|
|
//
|
|
|
|
#import "FLEXMetadataSection.h"
|
|
#import "FLEXTableView.h"
|
|
#import "FLEXTableViewCell.h"
|
|
#import "FLEXObjectExplorerFactory.h"
|
|
#import "FLEXFieldEditorViewController.h"
|
|
#import "FLEXMethodCallingViewController.h"
|
|
#import "FLEXIvar.h"
|
|
#import "NSArray+FLEX.h"
|
|
#import "FLEXRuntime+UIKitHelpers.h"
|
|
|
|
@interface FLEXMetadataSection ()
|
|
@property (nonatomic, readonly) FLEXObjectExplorer *explorer;
|
|
/// Filtered
|
|
@property (nonatomic, copy) NSArray<id<FLEXRuntimeMetadata>> *metadata;
|
|
/// Unfiltered
|
|
@property (nonatomic, copy) NSArray<id<FLEXRuntimeMetadata>> *allMetadata;
|
|
@end
|
|
|
|
@implementation FLEXMetadataSection
|
|
|
|
#pragma mark - Initialization
|
|
|
|
+ (instancetype)explorer:(FLEXObjectExplorer *)explorer kind:(FLEXMetadataKind)metadataKind {
|
|
return [[self alloc] initWithExplorer:explorer kind:metadataKind];
|
|
}
|
|
|
|
- (id)initWithExplorer:(FLEXObjectExplorer *)explorer kind:(FLEXMetadataKind)metadataKind {
|
|
self = [super init];
|
|
if (self) {
|
|
_explorer = explorer;
|
|
_metadataKind = metadataKind;
|
|
|
|
[self reloadData];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
#pragma mark - Private
|
|
|
|
- (NSString *)titleWithBaseName:(NSString *)baseName {
|
|
unsigned long totalCount = self.allMetadata.count;
|
|
unsigned long filteredCount = self.metadata.count;
|
|
|
|
if (totalCount == filteredCount) {
|
|
return [baseName stringByAppendingFormat:@" (%lu)", totalCount];
|
|
} else {
|
|
return [baseName stringByAppendingFormat:@" (%lu of %lu)", filteredCount, totalCount];
|
|
}
|
|
}
|
|
|
|
- (UITableViewCellAccessoryType)accessoryTypeForRow:(NSInteger)row {
|
|
return [self.metadata[row] suggestedAccessoryTypeWithTarget:self.explorer.object];
|
|
}
|
|
|
|
#pragma mark - Public
|
|
|
|
- (void)setExcludedMetadata:(NSSet<NSString *> *)excludedMetadata {
|
|
_excludedMetadata = excludedMetadata;
|
|
[self reloadData];
|
|
}
|
|
|
|
#pragma mark - Overrides
|
|
|
|
- (NSString *)titleForRow:(NSInteger)row {
|
|
return [self.metadata[row] description];
|
|
}
|
|
|
|
- (NSString *)subtitleForRow:(NSInteger)row {
|
|
return [self.metadata[row] previewWithTarget:self.explorer.object];
|
|
}
|
|
|
|
- (NSString *)title {
|
|
switch (self.metadataKind) {
|
|
case FLEXMetadataKindProperties:
|
|
return [self titleWithBaseName:@"Properties"];
|
|
case FLEXMetadataKindClassProperties:
|
|
return [self titleWithBaseName:@"Class Properties"];
|
|
case FLEXMetadataKindIvars:
|
|
return [self titleWithBaseName:@"Ivars"];
|
|
case FLEXMetadataKindMethods:
|
|
return [self titleWithBaseName:@"Methods"];
|
|
case FLEXMetadataKindClassMethods:
|
|
return [self titleWithBaseName:@"Class Methods"];
|
|
case FLEXMetadataKindClassHierarchy:
|
|
return [self titleWithBaseName:@"Class Hierarchy"];
|
|
case FLEXMetadataKindProtocols:
|
|
return [self titleWithBaseName:@"Protocols"];
|
|
case FLEXMetadataKindOther:
|
|
return @"Miscellaneous";
|
|
}
|
|
}
|
|
|
|
- (NSInteger)numberOfRows {
|
|
return self.metadata.count;
|
|
}
|
|
|
|
- (void)setFilterText:(NSString *)filterText {
|
|
super.filterText = filterText;
|
|
|
|
if (!self.filterText.length) {
|
|
self.metadata = self.allMetadata;
|
|
} else {
|
|
self.metadata = [self.allMetadata flex_filtered:^BOOL(id<FLEXRuntimeMetadata> obj, NSUInteger idx) {
|
|
return [obj.description localizedCaseInsensitiveContainsString:self.filterText];
|
|
}];
|
|
}
|
|
}
|
|
|
|
- (void)reloadData {
|
|
switch (self.metadataKind) {
|
|
case FLEXMetadataKindProperties:
|
|
self.allMetadata = self.explorer.properties;
|
|
break;
|
|
case FLEXMetadataKindClassProperties:
|
|
self.allMetadata = self.explorer.classProperties;
|
|
break;
|
|
case FLEXMetadataKindIvars:
|
|
self.allMetadata = self.explorer.ivars;
|
|
break;
|
|
case FLEXMetadataKindMethods:
|
|
self.allMetadata = self.explorer.methods;
|
|
break;
|
|
case FLEXMetadataKindClassMethods:
|
|
self.allMetadata = self.explorer.classMethods;
|
|
break;
|
|
case FLEXMetadataKindProtocols:
|
|
self.allMetadata = self.explorer.conformedProtocols;
|
|
break;
|
|
case FLEXMetadataKindClassHierarchy:
|
|
self.allMetadata = self.explorer.classHierarchy;
|
|
break;
|
|
case FLEXMetadataKindOther:
|
|
self.allMetadata = @[self.explorer.instanceSize, self.explorer.imageName];
|
|
break;
|
|
}
|
|
|
|
// Remove excluded metadata
|
|
if (self.excludedMetadata.count) {
|
|
id filterBlock = ^BOOL(id<FLEXRuntimeMetadata> obj, NSUInteger idx) {
|
|
return ![self.excludedMetadata containsObject:obj.name];
|
|
};
|
|
|
|
// Filter exclusions and sort
|
|
self.allMetadata = [[self.allMetadata flex_filtered:filterBlock]
|
|
sortedArrayUsingSelector:@selector(compare:)
|
|
];
|
|
}
|
|
|
|
// Re-filter data
|
|
self.filterText = self.filterText;
|
|
}
|
|
|
|
- (BOOL)canSelectRow:(NSInteger)row {
|
|
UITableViewCellAccessoryType accessory = [self accessoryTypeForRow:row];
|
|
return accessory == UITableViewCellAccessoryDisclosureIndicator ||
|
|
accessory == UITableViewCellAccessoryDetailDisclosureButton;
|
|
}
|
|
|
|
- (NSString *)reuseIdentifierForRow:(NSInteger)row {
|
|
return [self.metadata[row] reuseIdentifierWithTarget:self.explorer.object] ?: kFLEXCodeFontCell;
|
|
}
|
|
|
|
- (UIViewController *)viewControllerToPushForRow:(NSInteger)row {
|
|
return [self.metadata[row] viewerWithTarget:self.explorer.object];
|
|
}
|
|
|
|
- (void (^)(__kindof UIViewController *))didPressInfoButtonAction:(NSInteger)row {
|
|
return ^(UIViewController *host) {
|
|
[host.navigationController pushViewController:[self editorForRow:row] animated:YES];
|
|
};
|
|
}
|
|
|
|
- (UIViewController *)editorForRow:(NSInteger)row {
|
|
return [self.metadata[row] editorWithTarget:self.explorer.object section:self];
|
|
}
|
|
|
|
- (void)configureCell:(__kindof FLEXTableViewCell *)cell forRow:(NSInteger)row {
|
|
cell.titleLabel.text = [self titleForRow:row];
|
|
cell.subtitleLabel.text = [self subtitleForRow:row];
|
|
cell.accessoryType = [self accessoryTypeForRow:row];
|
|
}
|
|
|
|
- (NSString *)menuSubtitleForRow:(NSInteger)row {
|
|
return [self.metadata[row] contextualSubtitleWithTarget:self.explorer.object];
|
|
}
|
|
|
|
- (NSArray<UIMenuElement *> *)menuItemsForRow:(NSInteger)row sender:(UIViewController *)sender {
|
|
NSArray<UIMenuElement *> *existingItems = [super menuItemsForRow:row sender:sender];
|
|
|
|
// These two metadata kinds don't any of the additional options below
|
|
switch (self.metadataKind) {
|
|
case FLEXMetadataKindClassHierarchy:
|
|
case FLEXMetadataKindOther:
|
|
return existingItems;
|
|
|
|
default: break;
|
|
}
|
|
|
|
id<FLEXRuntimeMetadata> metadata = self.metadata[row];
|
|
NSMutableArray<UIMenuElement *> *menuItems = [NSMutableArray new];
|
|
|
|
[menuItems addObject:[UIAction
|
|
actionWithTitle:@"Explore Metadata"
|
|
image:nil
|
|
identifier:nil
|
|
handler:^(__kindof UIAction *action) {
|
|
[sender.navigationController pushViewController:[FLEXObjectExplorerFactory
|
|
explorerViewControllerForObject:metadata
|
|
] animated:YES];
|
|
}
|
|
]];
|
|
[menuItems addObjectsFromArray:[metadata
|
|
additionalActionsWithTarget:self.explorer.object sender:sender
|
|
]];
|
|
[menuItems addObjectsFromArray:existingItems];
|
|
|
|
return menuItems.copy;
|
|
}
|
|
|
|
- (NSArray<NSString *> *)copyMenuItemsForRow:(NSInteger)row {
|
|
return [self.metadata[row] copiableMetadataWithTarget:self.explorer.object];
|
|
}
|
|
|
|
@end
|