mirror of
				https://github.com/SoPat712/YTLitePlus.git
				synced 2025-10-30 20:34:03 -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
 | 
