From 63ac9e37179f10c1e47875fecca6d1ca4962d40f Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Fri, 10 Feb 2023 11:56:33 +0200 Subject: [PATCH 01/13] Fix typos --- Classes/Core/Controllers/FLEXFilteringTableViewController.h | 2 +- Example/FLEXample/AppDelegate.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Classes/Core/Controllers/FLEXFilteringTableViewController.h b/Classes/Core/Controllers/FLEXFilteringTableViewController.h index f0488a17d2..3573924b43 100644 --- a/Classes/Core/Controllers/FLEXFilteringTableViewController.h +++ b/Classes/Core/Controllers/FLEXFilteringTableViewController.h @@ -35,7 +35,7 @@ #pragma mark - FLEXFilteringTableViewController /// A table view which implements \c UITableView* methods using arrays of -/// \c FLEXTableViewSection objects provied by a special delegate. +/// \c FLEXTableViewSection objects provided by a special delegate. @interface FLEXFilteringTableViewController : FLEXTableViewController /// Stores the current search query. diff --git a/Example/FLEXample/AppDelegate.swift b/Example/FLEXample/AppDelegate.swift index 40378a3a1f..8e568a7088 100644 --- a/Example/FLEXample/AppDelegate.swift +++ b/Example/FLEXample/AppDelegate.swift @@ -26,7 +26,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { didFinishLaunchingWithOptions options: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { FLEXManager.shared.isNetworkDebuggingEnabled = true - // Add at least oen custom user defaults key to explore + // Add at least one custom user defaults key to explore UserDefaults.standard.set("foo", forKey: "FLEXamplePrefFoo") // To show off the system log viewer, send 10 example log messages at 3 second intervals From 23352daafb327f549527956ce4ad230a08baf5b6 Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Fri, 10 Feb 2023 11:56:35 +0200 Subject: [PATCH 02/13] Add demo global entries --- Example/FLEXample/AppDelegate.swift | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/Example/FLEXample/AppDelegate.swift b/Example/FLEXample/AppDelegate.swift index 8e568a7088..b16bb4f90b 100644 --- a/Example/FLEXample/AppDelegate.swift +++ b/Example/FLEXample/AppDelegate.swift @@ -25,7 +25,33 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions options: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { FLEXManager.shared.isNetworkDebuggingEnabled = true - + + // To show off the global entries, register one of each type + + FLEXManager.shared.registerGlobalEntry(withName: "Object") { + return "Object" + } + + FLEXManager.shared.registerGlobalEntry(withName: "View controller") { + let label = UILabel() + label.text = "View controller" + label.translatesAutoresizingMaskIntoConstraints = false + + let controller = UIViewController() + controller.view.backgroundColor = .darkGray + controller.view.addSubview(label) + NSLayoutConstraint.activate([ + label.centerXAnchor.constraint(equalTo: controller.view.centerXAnchor), + label.centerYAnchor.constraint(equalTo: controller.view.centerYAnchor) + ]) + + return controller + } + + FLEXManager.shared.registerGlobalEntry(withName: "Action") { host in + FLEXAlert.showQuickAlert("Action", from: host) + } + // Add at least one custom user defaults key to explore UserDefaults.standard.set("foo", forKey: "FLEXamplePrefFoo") From 97cb8c8b972ce327e2c2d2d31977e21d9e0d424d Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Fri, 10 Feb 2023 11:45:29 +0200 Subject: [PATCH 03/13] Move main global entries code to a dedicated class --- .../Globals/FLEXGlobalsViewController.m | 5 +- .../Globals/FLEXUserGlobalEntriesContainer.h | 56 +++++++++++++ .../Globals/FLEXUserGlobalEntriesContainer.m | 78 +++++++++++++++++++ Classes/Manager/FLEXManager+Extensibility.m | 43 ++-------- Classes/Manager/FLEXManager.m | 5 +- Classes/Manager/Private/FLEXManager+Private.h | 7 +- .../FLEXUserGlobalEntriesContainer+Private.h | 18 +++++ FLEX.podspec | 3 +- generate-spm-headers.sh | 2 + 9 files changed, 171 insertions(+), 46 deletions(-) create mode 100644 Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h create mode 100644 Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m create mode 100644 Classes/Manager/Private/FLEXUserGlobalEntriesContainer+Private.h diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m index 569b5633df..e7286ed008 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m @@ -19,6 +19,7 @@ #import "FLEXCookiesViewController.h" #import "FLEXGlobalsEntry.h" #import "FLEXManager+Private.h" +#import "FLEXUserGlobalEntriesContainer+Private.h" #import "FLEXSystemLogViewController.h" #import "FLEXNetworkMITMViewController.h" #import "FLEXAddressExplorerCoordinator.h" @@ -188,11 +189,11 @@ - (void)viewWillAppear:(BOOL)animated { - (NSArray *)makeSections { NSMutableArray *sections = [NSMutableArray array]; // Do we have custom sections to add? - if (FLEXManager.sharedManager.userGlobalEntries.count) { + if (FLEXManager.sharedManager.mainUserGlobalEntriesContainer.userGlobalEntries.count) { NSString *title = [[self class] globalsTitleForSection:FLEXGlobalsSectionCustom]; FLEXGlobalsSection *custom = [FLEXGlobalsSection title:title - rows:FLEXManager.sharedManager.userGlobalEntries + rows:FLEXManager.sharedManager.mainUserGlobalEntriesContainer.userGlobalEntries ]; [sections addObject:custom]; } diff --git a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h new file mode 100644 index 0000000000..777f46dffa --- /dev/null +++ b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h @@ -0,0 +1,56 @@ +// +// FLEXUserGlobalEntriesContainer.h +// FLEX +// +// Created by Iulian Onofrei on 2023-02-10. +// Copyright © 2023 FLEX Team. All rights reserved. +// + +#import + +#import "FLEXGlobalsEntry.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FLEXUserGlobalEntriesContainer : NSObject + +/// Adds an entry at the top of the list of Global State items. +/// Call this method before this view controller is displayed. +/// @param entryName The string to be displayed in the cell. +/// @param objectFutureBlock When you tap on the row, information about the object returned +/// by this block will be displayed. Passing a block that returns an object allows you to display +/// information about an object whose actual pointer may change at runtime (e.g. +currentUser) +/// @note This method must be called from the main thread. +/// The objectFutureBlock will be invoked from the main thread and may return nil. +/// @note The passed block will be copied and retain for the duration of the application, +/// you may want to use __weak references. +- (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock; + +/// Adds an entry at the top of the list of Global State items. +/// Call this method before this view controller is displayed. +/// @param entryName The string to be displayed in the cell. +/// @param viewControllerFutureBlock When you tap on the row, view controller returned +/// by this block will be pushed on the navigation controller stack. +/// @note This method must be called from the main thread. +/// The viewControllerFutureBlock will be invoked from the main thread and may not return nil. +/// @note The passed block will be copied and retain for the duration of the application, +/// you may want to use __weak references as needed. +- (void)registerGlobalEntryWithName:(NSString *)entryName + viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock; + +/// Adds an entry at the top of the list of Global State items. +/// @param entryName The string to be displayed in the cell. +/// @param rowSelectedAction When you tap on the row, this block will be invoked +/// with the host table view view controller. Use it to deselect the row or present an alert. +/// @note This method must be called from the main thread. +/// The rowSelectedAction will be invoked from the main thread. +/// @note The passed block will be copied and retain for the duration of the application, +/// you may want to use __weak references as needed. +- (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction; + +/// Removes all registered global entries. +- (void)clearGlobalEntries; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m new file mode 100644 index 0000000000..a9d6f28b58 --- /dev/null +++ b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m @@ -0,0 +1,78 @@ +// +// FLEXUserGlobalEntriesContainer.m +// FLEX +// +// Created by Iulian Onofrei on 2023-02-10. +// Copyright © 2023 FLEX Team. All rights reserved. +// + +#import "FLEXUserGlobalEntriesContainer.h" +#import "FLEXObjectExplorerFactory.h" +#import "FLEXUserGlobalEntriesContainer+Private.h" + +@interface FLEXUserGlobalEntriesContainer () + +@property (nonatomic, readonly) NSMutableArray *userGlobalEntries; + +@end + +@implementation FLEXUserGlobalEntriesContainer + +- (instancetype)init { + self = [super init]; + if (self) { + _userGlobalEntries = [NSMutableArray new]; + } + return self; +} + +- (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock { + NSParameterAssert(entryName); + NSParameterAssert(objectFutureBlock); + NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); + + entryName = entryName.copy; + FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString *{ + return entryName; + } viewControllerFuture:^UIViewController *{ + return [FLEXObjectExplorerFactory explorerViewControllerForObject:objectFutureBlock()]; + }]; + + [self.userGlobalEntries addObject:entry]; +} + +- (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock { + NSParameterAssert(entryName); + NSParameterAssert(viewControllerFutureBlock); + NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); + + entryName = entryName.copy; + FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString *{ + return entryName; + } viewControllerFuture:^UIViewController *{ + UIViewController *viewController = viewControllerFutureBlock(); + NSCAssert(viewController, @"'%@' entry returned nil viewController. viewControllerFutureBlock should never return nil.", entryName); + return viewController; + }]; + + [self.userGlobalEntries addObject:entry]; +} + +- (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction { + NSParameterAssert(entryName); + NSParameterAssert(rowSelectedAction); + NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); + + entryName = entryName.copy; + FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString * _Nonnull{ + return entryName; + } action:rowSelectedAction]; + + [self.userGlobalEntries addObject:entry]; +} + +- (void)clearGlobalEntries { + [self.userGlobalEntries removeAllObjects]; +} + +@end diff --git a/Classes/Manager/FLEXManager+Extensibility.m b/Classes/Manager/FLEXManager+Extensibility.m index 0872ee66ff..1ea3648b61 100644 --- a/Classes/Manager/FLEXManager+Extensibility.m +++ b/Classes/Manager/FLEXManager+Extensibility.m @@ -9,7 +9,6 @@ #import "FLEXManager+Extensibility.h" #import "FLEXManager+Private.h" #import "FLEXNavigationController.h" -#import "FLEXObjectExplorerFactory.h" #import "FLEXKeyboardShortcutManager.h" #import "FLEXExplorerViewController.h" #import "FLEXNetworkMITMViewController.h" @@ -17,6 +16,7 @@ #import "FLEXFileBrowserController.h" #import "FLEXArgumentInputStructView.h" #import "FLEXUtility.h" +#import "FLEXUserGlobalEntriesContainer.h" @interface FLEXManager (ExtensibilityPrivate) @property (nonatomic, readonly) UIViewController *topViewController; @@ -27,52 +27,19 @@ @implementation FLEXManager (Extensibility) #pragma mark - Globals Screen Entries - (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock { - NSParameterAssert(entryName); - NSParameterAssert(objectFutureBlock); - NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); - - entryName = entryName.copy; - FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString *{ - return entryName; - } viewControllerFuture:^UIViewController *{ - return [FLEXObjectExplorerFactory explorerViewControllerForObject:objectFutureBlock()]; - }]; - - [self.userGlobalEntries addObject:entry]; + [self.mainUserGlobalEntriesContainer registerGlobalEntryWithName:entryName objectFutureBlock:objectFutureBlock]; } - (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock { - NSParameterAssert(entryName); - NSParameterAssert(viewControllerFutureBlock); - NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); - - entryName = entryName.copy; - FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString *{ - return entryName; - } viewControllerFuture:^UIViewController *{ - UIViewController *viewController = viewControllerFutureBlock(); - NSCAssert(viewController, @"'%@' entry returned nil viewController. viewControllerFutureBlock should never return nil.", entryName); - return viewController; - }]; - - [self.userGlobalEntries addObject:entry]; + [self.mainUserGlobalEntriesContainer registerGlobalEntryWithName:entryName viewControllerFutureBlock:viewControllerFutureBlock]; } - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction { - NSParameterAssert(entryName); - NSParameterAssert(rowSelectedAction); - NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); - - entryName = entryName.copy; - FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString * _Nonnull{ - return entryName; - } action:rowSelectedAction]; - - [self.userGlobalEntries addObject:entry]; + [self.mainUserGlobalEntriesContainer registerGlobalEntryWithName:entryName action:rowSelectedAction]; } - (void)clearGlobalEntries { - [self.userGlobalEntries removeAllObjects]; + [self.mainUserGlobalEntriesContainer clearGlobalEntries]; } diff --git a/Classes/Manager/FLEXManager.m b/Classes/Manager/FLEXManager.m index 669a855962..f7d8c7df37 100644 --- a/Classes/Manager/FLEXManager.m +++ b/Classes/Manager/FLEXManager.m @@ -13,6 +13,7 @@ #import "FLEXNavigationController.h" #import "FLEXObjectExplorerFactory.h" #import "FLEXFileBrowserController.h" +#import "FLEXUserGlobalEntriesContainer.h" @interface FLEXManager () @@ -21,7 +22,7 @@ @interface FLEXManager () *userGlobalEntries; +@property (nonatomic, readonly) FLEXUserGlobalEntriesContainer *mainUserGlobalEntriesContainer; @property (nonatomic, readonly) NSMutableDictionary *customContentTypeViewers; @end @@ -40,7 +41,7 @@ + (instancetype)sharedManager { - (instancetype)init { self = [super init]; if (self) { - _userGlobalEntries = [NSMutableArray new]; + _mainUserGlobalEntriesContainer = [FLEXUserGlobalEntriesContainer new]; _customContentTypeViewers = [NSMutableDictionary new]; } return self; diff --git a/Classes/Manager/Private/FLEXManager+Private.h b/Classes/Manager/Private/FLEXManager+Private.h index a4f5a913f5..9d51756ea8 100644 --- a/Classes/Manager/Private/FLEXManager+Private.h +++ b/Classes/Manager/Private/FLEXManager+Private.h @@ -9,15 +9,16 @@ #import "FLEXManager.h" #import "FLEXWindow.h" -@class FLEXGlobalsEntry, FLEXExplorerViewController; +@class FLEXUserGlobalEntriesContainer, FLEXExplorerViewController; @interface FLEXManager (Private) @property (nonatomic, readonly) FLEXWindow *explorerWindow; @property (nonatomic, readonly) FLEXExplorerViewController *explorerViewController; -/// An array of FLEXGlobalsEntry objects that have been registered by the user. -@property (nonatomic, readonly) NSMutableArray *userGlobalEntries; +/// A FLEXUserGlobalEntriesContainer object that has FLEXGlobalsEntry +/// registered by the user. +@property (nonatomic, readonly) FLEXUserGlobalEntriesContainer *mainUserGlobalEntriesContainer; @property (nonatomic, readonly) NSMutableDictionary *customContentTypeViewers; @end diff --git a/Classes/Manager/Private/FLEXUserGlobalEntriesContainer+Private.h b/Classes/Manager/Private/FLEXUserGlobalEntriesContainer+Private.h new file mode 100644 index 0000000000..f0a0f5f2a4 --- /dev/null +++ b/Classes/Manager/Private/FLEXUserGlobalEntriesContainer+Private.h @@ -0,0 +1,18 @@ +// +// FLEXUserGlobalEntriesContainer+Private.h +// FLEX +// +// Created by Iulian Onofrei on 2023-02-10. +// Copyright © 2023 FLEX Team. All rights reserved. +// + +#import "FLEXUserGlobalEntriesContainer.h" + +@class FLEXGlobalsEntry; + +@interface FLEXUserGlobalEntriesContainer (Private) + +/// An array of FLEXGlobalsEntry objects that have been registered by the user. +@property (nonatomic, readonly) NSMutableArray *userGlobalEntries; + +@end diff --git a/FLEX.podspec b/FLEX.podspec index e4f520c9a3..8306026397 100644 --- a/FLEX.podspec +++ b/FLEX.podspec @@ -54,6 +54,7 @@ Pod::Spec.new do |spec| "Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.h", "Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.h", "Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h", - "Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserController.h" + "Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserController.h", + "Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h" ] end diff --git a/generate-spm-headers.sh b/generate-spm-headers.sh index 422a35cda3..2a0c15bb9f 100755 --- a/generate-spm-headers.sh +++ b/generate-spm-headers.sh @@ -29,6 +29,7 @@ generate_headers() { # # "Classes/*.h", "Classes/Manager/*.h", "Classes/Toolbar/*.h", # "Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h", +# "Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h", # "Classes/Core/**/*.h", "Classes/Utility/Runtime/Objc/**/*.h", # "Classes/ObjectExplorers/**/*.h", "Classes/Editing/**/*.h", # "Classes/Utility/FLEXMacros.h", "Classes/Utility/Categories/*.h", @@ -63,6 +64,7 @@ makeheader "Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcut.h" makeheader "Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.h" makeheader "Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h" makeheader "Classes/GlobalStateExplorers/FileBrowser/FLEXFileBrowserController.h" +makeheader "Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h" # Print all folders in Classes for use in Package.swift for folder in `find "Classes" -type d`; do From 813272b946081542356fd561901371a8e73bca4f Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Fri, 10 Feb 2023 11:45:56 +0200 Subject: [PATCH 04/13] Remove trailing whitespace --- .../Globals/FLEXGlobalsViewController.m | 12 ++++++------ FLEX.podspec | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m index e7286ed008..f1c464449b 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m @@ -98,10 +98,10 @@ + (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row { case FLEXGlobalsRowMainThread: case FLEXGlobalsRowOperationQueue: return [FLEXObjectExplorerFactory flex_concreteGlobalsEntry:row]; - + case FLEXGlobalsRowCount: break; } - + @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Missing globals case in switch" userInfo:nil @@ -158,7 +158,7 @@ + (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row { [sections addObject:[FLEXGlobalsSection title:title rows:rowsBySection[@(i)]]]; } }); - + return sections; } @@ -172,15 +172,15 @@ - (void)viewDidLoad { self.showsSearchBar = YES; self.searchBarDebounceInterval = kFLEXDebounceInstant; self.navigationItem.backBarButtonItem = [UIBarButtonItem flex_backItemWithTitle:@"Back"]; - + _manuallyDeselectOnAppear = NSProcessInfo.processInfo.operatingSystemVersion.majorVersion < 10; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - + [self disableToolbar]; - + if (self.manuallyDeselectOnAppear) { [self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES]; } diff --git a/FLEX.podspec b/FLEX.podspec index 8306026397..9010d2f395 100644 --- a/FLEX.podspec +++ b/FLEX.podspec @@ -42,12 +42,12 @@ Pod::Spec.new do |spec| spec.compiler_flags = "-Wno-unsupported-availability-guard", "-Wno-deprecated-declarations" spec.public_header_files = [ "Classes/*.h", "Classes/Manager/*.h", "Classes/Toolbar/*.h", "Classes/Core/Controllers/*.h", "Classes/Core/Views/*.h", - "Classes/Core/Views/Cells/*.h", "Classes/Core/*.h", + "Classes/Core/Views/Cells/*.h", "Classes/Core/*.h", "Classes/Utility/Categories/*.h", "Classes/Utility/Runtime/Objc/**/*.h", "Classes/ObjectExplorers/*.h", "Classes/ObjectExplorers/Sections/*.h", - + "Classes/Utility/FLEXMacros.h", "Classes/Utility/FLEXAlert.h", "Classes/Utility/FLEXResources.h", From a0ef72cbc128ea50378fda75134a8821686218cc Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Fri, 10 Feb 2023 11:47:10 +0200 Subject: [PATCH 05/13] Simplify a property name --- .../Globals/FLEXGlobalsViewController.m | 4 ++-- .../Globals/FLEXUserGlobalEntriesContainer.m | 12 ++++++------ .../Private/FLEXUserGlobalEntriesContainer+Private.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m index f1c464449b..a2a39a4906 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m @@ -189,11 +189,11 @@ - (void)viewWillAppear:(BOOL)animated { - (NSArray *)makeSections { NSMutableArray *sections = [NSMutableArray array]; // Do we have custom sections to add? - if (FLEXManager.sharedManager.mainUserGlobalEntriesContainer.userGlobalEntries.count) { + if (FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries.count) { NSString *title = [[self class] globalsTitleForSection:FLEXGlobalsSectionCustom]; FLEXGlobalsSection *custom = [FLEXGlobalsSection title:title - rows:FLEXManager.sharedManager.mainUserGlobalEntriesContainer.userGlobalEntries + rows:FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries ]; [sections addObject:custom]; } diff --git a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m index a9d6f28b58..cfdbceb99d 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m @@ -12,7 +12,7 @@ @interface FLEXUserGlobalEntriesContainer () -@property (nonatomic, readonly) NSMutableArray *userGlobalEntries; +@property (nonatomic, readonly) NSMutableArray *entries; @end @@ -21,7 +21,7 @@ @implementation FLEXUserGlobalEntriesContainer - (instancetype)init { self = [super init]; if (self) { - _userGlobalEntries = [NSMutableArray new]; + _entries = [NSMutableArray new]; } return self; } @@ -38,7 +38,7 @@ - (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id return [FLEXObjectExplorerFactory explorerViewControllerForObject:objectFutureBlock()]; }]; - [self.userGlobalEntries addObject:entry]; + [self.entries addObject:entry]; } - (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock { @@ -55,7 +55,7 @@ - (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBl return viewController; }]; - [self.userGlobalEntries addObject:entry]; + [self.entries addObject:entry]; } - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction { @@ -68,11 +68,11 @@ - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEnt return entryName; } action:rowSelectedAction]; - [self.userGlobalEntries addObject:entry]; + [self.entries addObject:entry]; } - (void)clearGlobalEntries { - [self.userGlobalEntries removeAllObjects]; + [self.entries removeAllObjects]; } @end diff --git a/Classes/Manager/Private/FLEXUserGlobalEntriesContainer+Private.h b/Classes/Manager/Private/FLEXUserGlobalEntriesContainer+Private.h index f0a0f5f2a4..21a041f739 100644 --- a/Classes/Manager/Private/FLEXUserGlobalEntriesContainer+Private.h +++ b/Classes/Manager/Private/FLEXUserGlobalEntriesContainer+Private.h @@ -13,6 +13,6 @@ @interface FLEXUserGlobalEntriesContainer (Private) /// An array of FLEXGlobalsEntry objects that have been registered by the user. -@property (nonatomic, readonly) NSMutableArray *userGlobalEntries; +@property (nonatomic, readonly) NSMutableArray *entries; @end From d667c1fdefb7d74f3cad15a527e88d9143f8dda7 Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Fri, 10 Feb 2023 12:46:12 +0200 Subject: [PATCH 06/13] Make globals view controller's custom entries configurable --- .../ExplorerInterface/FLEXExplorerViewController.m | 6 +++++- .../ExplorerInterface/Tabs/FLEXTabsViewController.m | 12 ++++++++++-- .../Globals/FLEXGlobalsViewController.h | 3 +++ .../Globals/FLEXGlobalsViewController.m | 4 ++-- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Classes/ExplorerInterface/FLEXExplorerViewController.m b/Classes/ExplorerInterface/FLEXExplorerViewController.m index 9b4964dd43..409322ae76 100644 --- a/Classes/ExplorerInterface/FLEXExplorerViewController.m +++ b/Classes/ExplorerInterface/FLEXExplorerViewController.m @@ -21,6 +21,8 @@ #import "FLEXWindowManagerController.h" #import "FLEXViewControllersViewController.h" #import "NSUserDefaults+FLEX.h" +#import "FLEXManager+Private.h" +#import "FLEXUserGlobalEntriesContainer+Private.h" typedef NS_ENUM(NSUInteger, FLEXExplorerMode) { FLEXExplorerModeDefault, @@ -1030,7 +1032,9 @@ - (void)toggleViewsToolWithCompletion:(void(^)(void))completion { - (void)toggleMenuTool { [self toggleToolWithViewControllerProvider:^UINavigationController *{ - return [FLEXNavigationController withRootViewController:[FLEXGlobalsViewController new]]; + FLEXGlobalsViewController *controller = [FLEXGlobalsViewController new]; + controller.customEntries = FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries; + return [FLEXNavigationController withRootViewController:controller]; } completion:nil]; } diff --git a/Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m b/Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m index 9f220461e5..83d646a872 100644 --- a/Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m +++ b/Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m @@ -17,6 +17,8 @@ #import "FLEXExplorerViewController.h" #import "FLEXGlobalsViewController.h" #import "FLEXBookmarksViewController.h" +#import "FLEXManager+Private.h" +#import "FLEXUserGlobalEntriesContainer+Private.h" @interface FLEXTabsViewController () @property (nonatomic, copy) NSArray *openTabs; @@ -198,8 +200,11 @@ - (void)addTabButtonPressed:(UIBarButtonItem *)sender { [FLEXAlert makeSheet:^(FLEXAlert *make) { make.title(@"New Tab"); make.button(@"Main Menu").handler(^(NSArray *strings) { + FLEXGlobalsViewController *controller = [FLEXGlobalsViewController new]; + controller.customEntries = FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries; + [self addTabAndDismiss:[FLEXNavigationController - withRootViewController:[FLEXGlobalsViewController new] + withRootViewController:controller ]]; }); make.button(@"Choose from Bookmarks").handler(^(NSArray *strings) { @@ -210,9 +215,12 @@ - (void)addTabButtonPressed:(UIBarButtonItem *)sender { make.button(@"Cancel").cancelStyle(); } showFrom:self source:sender]; } else { + FLEXGlobalsViewController *controller = [FLEXGlobalsViewController new]; + controller.customEntries = FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries; + // No bookmarks, just open the main menu [self addTabAndDismiss:[FLEXNavigationController - withRootViewController:[FLEXGlobalsViewController new] + withRootViewController:controller ]]; } } diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h index b4b79b8c68..cdc075a4a3 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h @@ -7,6 +7,7 @@ // #import "FLEXFilteringTableViewController.h" +@class FLEXGlobalsEntry; @protocol FLEXGlobalsTableViewControllerDelegate; typedef NS_ENUM(NSUInteger, FLEXGlobalsSectionKind) { @@ -25,4 +26,6 @@ typedef NS_ENUM(NSUInteger, FLEXGlobalsSectionKind) { @interface FLEXGlobalsViewController : FLEXFilteringTableViewController +@property (nonatomic, nonnull) NSArray *customEntries; + @end diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m index a2a39a4906..176d704b43 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m @@ -189,11 +189,11 @@ - (void)viewWillAppear:(BOOL)animated { - (NSArray *)makeSections { NSMutableArray *sections = [NSMutableArray array]; // Do we have custom sections to add? - if (FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries.count) { + if (self.customEntries.count) { NSString *title = [[self class] globalsTitleForSection:FLEXGlobalsSectionCustom]; FLEXGlobalsSection *custom = [FLEXGlobalsSection title:title - rows:FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries + rows:self.customEntries ]; [sections addObject:custom]; } From 50116dfbe581d80a5f71b6f9e3172c793fdd8099 Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Fri, 10 Feb 2023 12:57:12 +0200 Subject: [PATCH 07/13] Make globals view controller's default entries state configurable --- Classes/ExplorerInterface/FLEXExplorerViewController.m | 1 + Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m | 2 ++ .../GlobalStateExplorers/Globals/FLEXGlobalsViewController.h | 1 + .../GlobalStateExplorers/Globals/FLEXGlobalsViewController.m | 4 +++- 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Classes/ExplorerInterface/FLEXExplorerViewController.m b/Classes/ExplorerInterface/FLEXExplorerViewController.m index 409322ae76..89ceda600d 100644 --- a/Classes/ExplorerInterface/FLEXExplorerViewController.m +++ b/Classes/ExplorerInterface/FLEXExplorerViewController.m @@ -1034,6 +1034,7 @@ - (void)toggleMenuTool { [self toggleToolWithViewControllerProvider:^UINavigationController *{ FLEXGlobalsViewController *controller = [FLEXGlobalsViewController new]; controller.customEntries = FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries; + controller.showsDefaultEntries = YES; return [FLEXNavigationController withRootViewController:controller]; } completion:nil]; } diff --git a/Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m b/Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m index 83d646a872..4194256bbf 100644 --- a/Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m +++ b/Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m @@ -202,6 +202,7 @@ - (void)addTabButtonPressed:(UIBarButtonItem *)sender { make.button(@"Main Menu").handler(^(NSArray *strings) { FLEXGlobalsViewController *controller = [FLEXGlobalsViewController new]; controller.customEntries = FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries; + controller.showsDefaultEntries = YES; [self addTabAndDismiss:[FLEXNavigationController withRootViewController:controller @@ -217,6 +218,7 @@ - (void)addTabButtonPressed:(UIBarButtonItem *)sender { } else { FLEXGlobalsViewController *controller = [FLEXGlobalsViewController new]; controller.customEntries = FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries; + controller.showsDefaultEntries = YES; // No bookmarks, just open the main menu [self addTabAndDismiss:[FLEXNavigationController diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h index cdc075a4a3..55250408d7 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h @@ -27,5 +27,6 @@ typedef NS_ENUM(NSUInteger, FLEXGlobalsSectionKind) { @interface FLEXGlobalsViewController : FLEXFilteringTableViewController @property (nonatomic, nonnull) NSArray *customEntries; +@property (nonatomic) BOOL showsDefaultEntries; @end diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m index 176d704b43..7962b5580c 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m @@ -198,7 +198,9 @@ - (void)viewWillAppear:(BOOL)animated { [sections addObject:custom]; } - [sections addObjectsFromArray:[self.class defaultGlobalSections]]; + if (self.showsDefaultEntries) { + [sections addObjectsFromArray:[self.class defaultGlobalSections]]; + } return sections; } From 7771063bb3b0f66d05f45c9bd945a304eade26c9 Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Fri, 10 Feb 2023 13:01:19 +0200 Subject: [PATCH 08/13] Make globals view controller's title configurable --- .../GlobalStateExplorers/Globals/FLEXGlobalsViewController.h | 1 + .../GlobalStateExplorers/Globals/FLEXGlobalsViewController.m | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h index 55250408d7..6f9016b6e6 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h @@ -26,6 +26,7 @@ typedef NS_ENUM(NSUInteger, FLEXGlobalsSectionKind) { @interface FLEXGlobalsViewController : FLEXFilteringTableViewController +@property (nonatomic, nullable) NSString *customTitle; @property (nonatomic, nonnull) NSArray *customEntries; @property (nonatomic) BOOL showsDefaultEntries; diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m index 7962b5580c..6b83245332 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m @@ -168,7 +168,7 @@ + (FLEXGlobalsEntry *)globalsEntryForRow:(FLEXGlobalsRow)row { - (void)viewDidLoad { [super viewDidLoad]; - self.title = @"💪 FLEX"; + self.title = self.customTitle ?: @"💪 FLEX"; self.showsSearchBar = YES; self.searchBarDebounceInterval = kFLEXDebounceInstant; self.navigationItem.backBarButtonItem = [UIBarButtonItem flex_backItemWithTitle:@"Back"]; From 23f06443f4d3d99e36cff364f4f1a19a503be729 Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Fri, 10 Feb 2023 13:16:31 +0200 Subject: [PATCH 09/13] Add support for nested global entries --- .../Globals/FLEXGlobalsEntry.h | 6 ++- .../Globals/FLEXUserGlobalEntriesContainer.h | 13 +++++- .../Globals/FLEXUserGlobalEntriesContainer.m | 24 ++++++++++ Classes/Manager/FLEXManager+Extensibility.h | 14 +++++- Classes/Manager/FLEXManager+Extensibility.m | 4 ++ Example/FLEXample/AppDelegate.swift | 44 ++++++++++++++++--- 6 files changed, 96 insertions(+), 9 deletions(-) diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h index c7866c05c2..d1d957893f 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h @@ -10,6 +10,8 @@ NS_ASSUME_NONNULL_BEGIN +@class FLEXUserGlobalEntriesContainer; + typedef NS_ENUM(NSUInteger, FLEXGlobalsRow) { FLEXGlobalsRowProcessInfo, FLEXGlobalsRowNetworkHistory, @@ -51,8 +53,10 @@ typedef UIViewController * _Nullable (^FLEXGlobalsEntryViewControllerFuture)(voi /// Do something like present an alert, then use the host /// view controller to present or push another view controller. typedef void (^FLEXGlobalsEntryRowAction)(__kindof UITableViewController * _Nonnull host); +/// Use the container to register nested global entries. +typedef void (^FLEXNestedGlobalEntriesHandler)(FLEXUserGlobalEntriesContainer * _Nonnull container); -/// For view controllers to conform to to indicate they support being used +/// For view controllers to conform and to indicate they support being used /// in the globals table view controller. These methods help create concrete entries. /// /// Previously, the concrete entries relied on "futures" for the view controller and title. diff --git a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h index 777f46dffa..28964d8ae6 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h +++ b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h @@ -44,10 +44,21 @@ NS_ASSUME_NONNULL_BEGIN /// with the host table view view controller. Use it to deselect the row or present an alert. /// @note This method must be called from the main thread. /// The rowSelectedAction will be invoked from the main thread. -/// @note The passed block will be copied and retain for the duration of the application, +/// @note The passed block will be copied and retained for the duration of the application, /// you may want to use __weak references as needed. - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction; +/// Adds an entry at the top of the list of Global State items. +/// @param entryName The string to be displayed in the cell. +/// @param nestedEntriesHandler When you tap on the row, this block will be invoked +/// with the container object. Use it to register nested entries. +/// @note This method must be called from the main thread. +/// The nestedEntriesHandler will be invoked from the main thread. +/// @note The passed block will be copied and retained for the duration of the application, +/// you may want to use __weak references as needed. +- (void)registerGlobalEntryWithName:(NSString *)entryName + nestedEntriesHandler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler; + /// Removes all registered global entries. - (void)clearGlobalEntries; diff --git a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m index cfdbceb99d..b6e3b1a6ff 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m @@ -9,6 +9,7 @@ #import "FLEXUserGlobalEntriesContainer.h" #import "FLEXObjectExplorerFactory.h" #import "FLEXUserGlobalEntriesContainer+Private.h" +#import "FLEXGlobalsViewController.h" @interface FLEXUserGlobalEntriesContainer () @@ -71,6 +72,29 @@ - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEnt [self.entries addObject:entry]; } +- (void)registerGlobalEntryWithName:(NSString *)entryName nestedEntriesHandler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler { + NSParameterAssert(entryName); + NSParameterAssert(nestedEntriesHandler); + NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); + + entryName = entryName.copy; + FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString * _Nonnull{ + return entryName; + } viewControllerFuture:^UIViewController * _Nullable{ + FLEXUserGlobalEntriesContainer *container = [FLEXUserGlobalEntriesContainer new]; + nestedEntriesHandler(container); + + FLEXGlobalsViewController *controller = [FLEXGlobalsViewController new]; + controller.customTitle = entryName; + controller.customEntries = container.entries; + controller.showsDefaultEntries = NO; + + return controller; + }]; + + [self.entries addObject:entry]; +} + - (void)clearGlobalEntries { [self.entries removeAllObjects]; } diff --git a/Classes/Manager/FLEXManager+Extensibility.h b/Classes/Manager/FLEXManager+Extensibility.h index 83260ed9e8..3c3d9eb7a0 100644 --- a/Classes/Manager/FLEXManager+Extensibility.h +++ b/Classes/Manager/FLEXManager+Extensibility.h @@ -8,6 +8,7 @@ #import "FLEXManager.h" #import "FLEXGlobalsEntry.h" +#import "FLEXUserGlobalEntriesContainer.h" NS_ASSUME_NONNULL_BEGIN @@ -45,10 +46,21 @@ NS_ASSUME_NONNULL_BEGIN /// with the host table view view controller. Use it to deselect the row or present an alert. /// @note This method must be called from the main thread. /// The rowSelectedAction will be invoked from the main thread. -/// @note The passed block will be copied and retain for the duration of the application, +/// @note The passed block will be copied and retained for the duration of the application, /// you may want to use __weak references as needed. - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction; +/// Adds an entry at the top of the list of Global State items. +/// @param entryName The string to be displayed in the cell. +/// @param nestedEntriesHandler When you tap on the row, this block will be invoked +/// with the container object. Use it to register nested entries. +/// @note This method must be called from the main thread. +/// The nestedEntriesHandler will be invoked from the main thread. +/// @note The passed block will be copied and retained for the duration of the application, +/// you may want to use __weak references as needed. +- (void)registerGlobalEntryWithName:(NSString *)entryName + nestedEntriesHandler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler; + /// Removes all registered global entries. - (void)clearGlobalEntries; diff --git a/Classes/Manager/FLEXManager+Extensibility.m b/Classes/Manager/FLEXManager+Extensibility.m index 1ea3648b61..827b2d42bb 100644 --- a/Classes/Manager/FLEXManager+Extensibility.m +++ b/Classes/Manager/FLEXManager+Extensibility.m @@ -38,6 +38,10 @@ - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEnt [self.mainUserGlobalEntriesContainer registerGlobalEntryWithName:entryName action:rowSelectedAction]; } +- (void)registerGlobalEntryWithName:(NSString *)entryName nestedEntriesHandler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler { + [self.mainUserGlobalEntriesContainer registerGlobalEntryWithName:entryName nestedEntriesHandler:nestedEntriesHandler]; +} + - (void)clearGlobalEntries { [self.mainUserGlobalEntriesContainer clearGlobalEntries]; } diff --git a/Example/FLEXample/AppDelegate.swift b/Example/FLEXample/AppDelegate.swift index b16bb4f90b..43359f7b5e 100644 --- a/Example/FLEXample/AppDelegate.swift +++ b/Example/FLEXample/AppDelegate.swift @@ -28,13 +28,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // To show off the global entries, register one of each type - FLEXManager.shared.registerGlobalEntry(withName: "Object") { - return "Object" + FLEXManager.shared.registerGlobalEntry(withName: "Level 1 - Object") { + return "Level 1 - Object" } - FLEXManager.shared.registerGlobalEntry(withName: "View controller") { + FLEXManager.shared.registerGlobalEntry(withName: "Level 1 - View controller") { let label = UILabel() - label.text = "View controller" + label.text = "Level 1 - View controller" label.translatesAutoresizingMaskIntoConstraints = false let controller = UIViewController() @@ -48,8 +48,40 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return controller } - FLEXManager.shared.registerGlobalEntry(withName: "Action") { host in - FLEXAlert.showQuickAlert("Action", from: host) + FLEXManager.shared.registerGlobalEntry(withName: "Level 1 - Action") { host in + FLEXAlert.showQuickAlert("Level 1 - Action", from: host) + } + + FLEXManager.shared.registerGlobalEntry(withName: "Level 1 - Nested") { container in + container.registerGlobalEntry(withName: "Level 2 - Object") { + return "Level 2 - Object" + } + + container.registerGlobalEntry(withName: "Level 2 - View controller") { + let label = UILabel() + label.text = "Level 2 - View controller" + label.translatesAutoresizingMaskIntoConstraints = false + + let controller = UIViewController() + controller.view.backgroundColor = .darkGray + controller.view.addSubview(label) + NSLayoutConstraint.activate([ + label.centerXAnchor.constraint(equalTo: controller.view.centerXAnchor), + label.centerYAnchor.constraint(equalTo: controller.view.centerYAnchor) + ]) + + return controller + } + + container.registerGlobalEntry(withName: "Level 2 - Action") { host in + FLEXAlert.showQuickAlert("Level 2 - Action", from: host) + } + + container.registerGlobalEntry(withName: "Level 2 - Nested") { level2Container in + level2Container.registerGlobalEntry(withName: "Level 3 - Action") { host in + FLEXAlert.showQuickAlert("Level 3 - Action", from: host) + } + } } // Add at least one custom user defaults key to explore From 730d6f9fc807fa4604c40c6d05f0faaa737dc578 Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Fri, 10 Feb 2023 12:47:57 +0200 Subject: [PATCH 10/13] Deprecate the old global entries methods This is so we can remove the (now) superfluous methods that only forward the same parameters to the new container object. --- .../ExplorerInterface/FLEXExplorerViewController.m | 4 ++-- .../ExplorerInterface/Tabs/FLEXTabsViewController.m | 6 +++--- Classes/Manager/FLEXManager+Extensibility.h | 13 ++++++++----- Classes/Manager/FLEXManager+Extensibility.m | 11 ++++++----- Classes/Manager/FLEXManager.m | 4 ++-- Classes/Manager/Private/FLEXManager+Private.h | 3 --- Example/FLEXample/AppDelegate.swift | 8 ++++---- 7 files changed, 25 insertions(+), 24 deletions(-) diff --git a/Classes/ExplorerInterface/FLEXExplorerViewController.m b/Classes/ExplorerInterface/FLEXExplorerViewController.m index 89ceda600d..2df05ffdb3 100644 --- a/Classes/ExplorerInterface/FLEXExplorerViewController.m +++ b/Classes/ExplorerInterface/FLEXExplorerViewController.m @@ -21,7 +21,7 @@ #import "FLEXWindowManagerController.h" #import "FLEXViewControllersViewController.h" #import "NSUserDefaults+FLEX.h" -#import "FLEXManager+Private.h" +#import "FLEXManager+Extensibility.h" #import "FLEXUserGlobalEntriesContainer+Private.h" typedef NS_ENUM(NSUInteger, FLEXExplorerMode) { @@ -1033,7 +1033,7 @@ - (void)toggleViewsToolWithCompletion:(void(^)(void))completion { - (void)toggleMenuTool { [self toggleToolWithViewControllerProvider:^UINavigationController *{ FLEXGlobalsViewController *controller = [FLEXGlobalsViewController new]; - controller.customEntries = FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries; + controller.customEntries = FLEXManager.sharedManager.globalEntriesContainer.entries; controller.showsDefaultEntries = YES; return [FLEXNavigationController withRootViewController:controller]; } completion:nil]; diff --git a/Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m b/Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m index 4194256bbf..a08c1b090b 100644 --- a/Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m +++ b/Classes/ExplorerInterface/Tabs/FLEXTabsViewController.m @@ -17,7 +17,7 @@ #import "FLEXExplorerViewController.h" #import "FLEXGlobalsViewController.h" #import "FLEXBookmarksViewController.h" -#import "FLEXManager+Private.h" +#import "FLEXManager+Extensibility.h" #import "FLEXUserGlobalEntriesContainer+Private.h" @interface FLEXTabsViewController () @@ -201,7 +201,7 @@ - (void)addTabButtonPressed:(UIBarButtonItem *)sender { make.title(@"New Tab"); make.button(@"Main Menu").handler(^(NSArray *strings) { FLEXGlobalsViewController *controller = [FLEXGlobalsViewController new]; - controller.customEntries = FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries; + controller.customEntries = FLEXManager.sharedManager.globalEntriesContainer.entries; controller.showsDefaultEntries = YES; [self addTabAndDismiss:[FLEXNavigationController @@ -217,7 +217,7 @@ - (void)addTabButtonPressed:(UIBarButtonItem *)sender { } showFrom:self source:sender]; } else { FLEXGlobalsViewController *controller = [FLEXGlobalsViewController new]; - controller.customEntries = FLEXManager.sharedManager.mainUserGlobalEntriesContainer.entries; + controller.customEntries = FLEXManager.sharedManager.globalEntriesContainer.entries; controller.showsDefaultEntries = YES; // No bookmarks, just open the main menu diff --git a/Classes/Manager/FLEXManager+Extensibility.h b/Classes/Manager/FLEXManager+Extensibility.h index 3c3d9eb7a0..bee59bf590 100644 --- a/Classes/Manager/FLEXManager+Extensibility.h +++ b/Classes/Manager/FLEXManager+Extensibility.h @@ -16,6 +16,9 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Globals Screen Entries +/// Use this property to add entries at the top of the list of Global State items. +@property (nonatomic, readonly) FLEXUserGlobalEntriesContainer *globalEntriesContainer; + /// Adds an entry at the top of the list of Global State items. /// Call this method before this view controller is displayed. /// @param entryName The string to be displayed in the cell. @@ -26,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN /// The objectFutureBlock will be invoked from the main thread and may return nil. /// @note The passed block will be copied and retain for the duration of the application, /// you may want to use __weak references. -- (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock; +- (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock __attribute((deprecated("Use the same method on the globalEntriesContainer property instead."))); /// Adds an entry at the top of the list of Global State items. /// Call this method before this view controller is displayed. @@ -38,7 +41,7 @@ NS_ASSUME_NONNULL_BEGIN /// @note The passed block will be copied and retain for the duration of the application, /// you may want to use __weak references as needed. - (void)registerGlobalEntryWithName:(NSString *)entryName - viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock; + viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock __attribute((deprecated("Use the same method on the globalEntriesContainer property instead."))); /// Adds an entry at the top of the list of Global State items. /// @param entryName The string to be displayed in the cell. @@ -48,7 +51,7 @@ NS_ASSUME_NONNULL_BEGIN /// The rowSelectedAction will be invoked from the main thread. /// @note The passed block will be copied and retained for the duration of the application, /// you may want to use __weak references as needed. -- (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction; +- (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction __attribute((deprecated("Use the same method on the globalEntriesContainer property instead."))); /// Adds an entry at the top of the list of Global State items. /// @param entryName The string to be displayed in the cell. @@ -59,10 +62,10 @@ NS_ASSUME_NONNULL_BEGIN /// @note The passed block will be copied and retained for the duration of the application, /// you may want to use __weak references as needed. - (void)registerGlobalEntryWithName:(NSString *)entryName - nestedEntriesHandler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler; + nestedEntriesHandler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler __attribute((deprecated("Use the same method on the globalEntriesContainer property instead."))); /// Removes all registered global entries. -- (void)clearGlobalEntries; +- (void)clearGlobalEntries __attribute((deprecated("Use the same method on the globalEntriesContainer property instead."))); #pragma mark - Editing diff --git a/Classes/Manager/FLEXManager+Extensibility.m b/Classes/Manager/FLEXManager+Extensibility.m index 827b2d42bb..4cdc363713 100644 --- a/Classes/Manager/FLEXManager+Extensibility.m +++ b/Classes/Manager/FLEXManager+Extensibility.m @@ -23,27 +23,28 @@ @interface FLEXManager (ExtensibilityPrivate) @end @implementation FLEXManager (Extensibility) +@dynamic globalEntriesContainer; #pragma mark - Globals Screen Entries - (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock { - [self.mainUserGlobalEntriesContainer registerGlobalEntryWithName:entryName objectFutureBlock:objectFutureBlock]; + [self.globalEntriesContainer registerGlobalEntryWithName:entryName objectFutureBlock:objectFutureBlock]; } - (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock { - [self.mainUserGlobalEntriesContainer registerGlobalEntryWithName:entryName viewControllerFutureBlock:viewControllerFutureBlock]; + [self.globalEntriesContainer registerGlobalEntryWithName:entryName viewControllerFutureBlock:viewControllerFutureBlock]; } - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction { - [self.mainUserGlobalEntriesContainer registerGlobalEntryWithName:entryName action:rowSelectedAction]; + [self.globalEntriesContainer registerGlobalEntryWithName:entryName action:rowSelectedAction]; } - (void)registerGlobalEntryWithName:(NSString *)entryName nestedEntriesHandler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler { - [self.mainUserGlobalEntriesContainer registerGlobalEntryWithName:entryName nestedEntriesHandler:nestedEntriesHandler]; + [self.globalEntriesContainer registerGlobalEntryWithName:entryName nestedEntriesHandler:nestedEntriesHandler]; } - (void)clearGlobalEntries { - [self.mainUserGlobalEntriesContainer clearGlobalEntries]; + [self.globalEntriesContainer clearGlobalEntries]; } diff --git a/Classes/Manager/FLEXManager.m b/Classes/Manager/FLEXManager.m index f7d8c7df37..27bc0dd828 100644 --- a/Classes/Manager/FLEXManager.m +++ b/Classes/Manager/FLEXManager.m @@ -22,7 +22,7 @@ @interface FLEXManager () *customContentTypeViewers; @end @@ -41,7 +41,7 @@ + (instancetype)sharedManager { - (instancetype)init { self = [super init]; if (self) { - _mainUserGlobalEntriesContainer = [FLEXUserGlobalEntriesContainer new]; + _globalEntriesContainer = [FLEXUserGlobalEntriesContainer new]; _customContentTypeViewers = [NSMutableDictionary new]; } return self; diff --git a/Classes/Manager/Private/FLEXManager+Private.h b/Classes/Manager/Private/FLEXManager+Private.h index 9d51756ea8..fda60eb4f5 100644 --- a/Classes/Manager/Private/FLEXManager+Private.h +++ b/Classes/Manager/Private/FLEXManager+Private.h @@ -16,9 +16,6 @@ @property (nonatomic, readonly) FLEXWindow *explorerWindow; @property (nonatomic, readonly) FLEXExplorerViewController *explorerViewController; -/// A FLEXUserGlobalEntriesContainer object that has FLEXGlobalsEntry -/// registered by the user. -@property (nonatomic, readonly) FLEXUserGlobalEntriesContainer *mainUserGlobalEntriesContainer; @property (nonatomic, readonly) NSMutableDictionary *customContentTypeViewers; @end diff --git a/Example/FLEXample/AppDelegate.swift b/Example/FLEXample/AppDelegate.swift index 43359f7b5e..9ce2e2d38d 100644 --- a/Example/FLEXample/AppDelegate.swift +++ b/Example/FLEXample/AppDelegate.swift @@ -28,11 +28,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // To show off the global entries, register one of each type - FLEXManager.shared.registerGlobalEntry(withName: "Level 1 - Object") { + FLEXManager.shared.globalEntriesContainer.registerGlobalEntry(withName: "Level 1 - Object") { return "Level 1 - Object" } - FLEXManager.shared.registerGlobalEntry(withName: "Level 1 - View controller") { + FLEXManager.shared.globalEntriesContainer.registerGlobalEntry(withName: "Level 1 - View controller") { let label = UILabel() label.text = "Level 1 - View controller" label.translatesAutoresizingMaskIntoConstraints = false @@ -48,11 +48,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return controller } - FLEXManager.shared.registerGlobalEntry(withName: "Level 1 - Action") { host in + FLEXManager.shared.globalEntriesContainer.registerGlobalEntry(withName: "Level 1 - Action") { host in FLEXAlert.showQuickAlert("Level 1 - Action", from: host) } - FLEXManager.shared.registerGlobalEntry(withName: "Level 1 - Nested") { container in + FLEXManager.shared.globalEntriesContainer.registerGlobalEntry(withName: "Level 1 - Nested") { container in container.registerGlobalEntry(withName: "Level 2 - Object") { return "Level 2 - Object" } From e6e9f73281e9e52ed523a7770f5c36c21972e788 Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Fri, 10 Feb 2023 14:36:06 +0200 Subject: [PATCH 11/13] Avoid ambiguous build error in Swift --- .../Globals/FLEXUserGlobalEntriesContainer.h | 3 +-- .../Globals/FLEXUserGlobalEntriesContainer.m | 2 +- Classes/Manager/FLEXManager+Extensibility.h | 4 ++-- Classes/Manager/FLEXManager+Extensibility.m | 4 ++-- Example/FLEXample/AppDelegate.swift | 4 ++-- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h index 28964d8ae6..9b08d26ce4 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h +++ b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h @@ -56,8 +56,7 @@ NS_ASSUME_NONNULL_BEGIN /// The nestedEntriesHandler will be invoked from the main thread. /// @note The passed block will be copied and retained for the duration of the application, /// you may want to use __weak references as needed. -- (void)registerGlobalEntryWithName:(NSString *)entryName - nestedEntriesHandler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler; +- (void)registerNestedGlobalEntryWithName:(NSString *)entryName handler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler; /// Removes all registered global entries. - (void)clearGlobalEntries; diff --git a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m index b6e3b1a6ff..9eff58d326 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m @@ -72,7 +72,7 @@ - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEnt [self.entries addObject:entry]; } -- (void)registerGlobalEntryWithName:(NSString *)entryName nestedEntriesHandler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler { +- (void)registerNestedGlobalEntryWithName:(NSString *)entryName handler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler { NSParameterAssert(entryName); NSParameterAssert(nestedEntriesHandler); NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); diff --git a/Classes/Manager/FLEXManager+Extensibility.h b/Classes/Manager/FLEXManager+Extensibility.h index bee59bf590..33e641b87e 100644 --- a/Classes/Manager/FLEXManager+Extensibility.h +++ b/Classes/Manager/FLEXManager+Extensibility.h @@ -61,8 +61,8 @@ NS_ASSUME_NONNULL_BEGIN /// The nestedEntriesHandler will be invoked from the main thread. /// @note The passed block will be copied and retained for the duration of the application, /// you may want to use __weak references as needed. -- (void)registerGlobalEntryWithName:(NSString *)entryName - nestedEntriesHandler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler __attribute((deprecated("Use the same method on the globalEntriesContainer property instead."))); +- (void)registerNestedGlobalEntryWithName:(NSString *)entryName + handler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler __attribute((deprecated("Use the same method on the globalEntriesContainer property instead."))); /// Removes all registered global entries. - (void)clearGlobalEntries __attribute((deprecated("Use the same method on the globalEntriesContainer property instead."))); diff --git a/Classes/Manager/FLEXManager+Extensibility.m b/Classes/Manager/FLEXManager+Extensibility.m index 4cdc363713..24df6b9080 100644 --- a/Classes/Manager/FLEXManager+Extensibility.m +++ b/Classes/Manager/FLEXManager+Extensibility.m @@ -39,8 +39,8 @@ - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEnt [self.globalEntriesContainer registerGlobalEntryWithName:entryName action:rowSelectedAction]; } -- (void)registerGlobalEntryWithName:(NSString *)entryName nestedEntriesHandler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler { - [self.globalEntriesContainer registerGlobalEntryWithName:entryName nestedEntriesHandler:nestedEntriesHandler]; +- (void)registerNestedGlobalEntryWithName:(NSString *)entryName handler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler { + [self.globalEntriesContainer registerNestedGlobalEntryWithName:entryName handler:nestedEntriesHandler]; } - (void)clearGlobalEntries { diff --git a/Example/FLEXample/AppDelegate.swift b/Example/FLEXample/AppDelegate.swift index 9ce2e2d38d..58ee03ec10 100644 --- a/Example/FLEXample/AppDelegate.swift +++ b/Example/FLEXample/AppDelegate.swift @@ -52,7 +52,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { FLEXAlert.showQuickAlert("Level 1 - Action", from: host) } - FLEXManager.shared.globalEntriesContainer.registerGlobalEntry(withName: "Level 1 - Nested") { container in + FLEXManager.shared.globalEntriesContainer.registerNestedGlobalEntry(withName: "Level 1 - Nested") { container in container.registerGlobalEntry(withName: "Level 2 - Object") { return "Level 2 - Object" } @@ -77,7 +77,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { FLEXAlert.showQuickAlert("Level 2 - Action", from: host) } - container.registerGlobalEntry(withName: "Level 2 - Nested") { level2Container in + container.registerNestedGlobalEntry(withName: "Level 2 - Nested") { level2Container in level2Container.registerGlobalEntry(withName: "Level 3 - Action") { host in FLEXAlert.showQuickAlert("Level 3 - Action", from: host) } From 377327297c76d6d0a581fc1541deb17f8a8c0aad Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Thu, 16 Mar 2023 17:29:15 +0200 Subject: [PATCH 12/13] Add support for optionally customizing the cell accessory type --- .../Globals/FLEXGlobalsEntry.h | 7 ++- .../Globals/FLEXGlobalsEntry.m | 14 ++++- .../Globals/FLEXGlobalsSection.m | 2 +- .../Globals/FLEXUserGlobalEntriesContainer.h | 55 +++++++++++++++++++ .../Globals/FLEXUserGlobalEntriesContainer.m | 42 ++++++++++++-- Example/FLEXample/AppDelegate.swift | 14 ++--- 6 files changed, 119 insertions(+), 15 deletions(-) diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h index d1d957893f..69884496f6 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h @@ -85,15 +85,20 @@ typedef void (^FLEXNestedGlobalEntriesHandler)(FLEXUserGlobalEntriesContainer * @interface FLEXGlobalsEntry : NSObject @property (nonatomic, readonly, nonnull) FLEXGlobalsEntryNameFuture entryNameFuture; +@property (nonatomic, readonly) UITableViewCellAccessoryType cellAccessoryType; @property (nonatomic, readonly, nullable) FLEXGlobalsEntryViewControllerFuture viewControllerFuture; @property (nonatomic, readonly, nullable) FLEXGlobalsEntryRowAction rowAction; -+ (instancetype)entryWithEntry:(Class)entry row:(FLEXGlobalsRow)row; ++ (instancetype)entryWithEntry:(Class)entry + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType + row:(FLEXGlobalsRow)row; + (instancetype)entryWithNameFuture:(FLEXGlobalsEntryNameFuture)nameFuture + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType viewControllerFuture:(FLEXGlobalsEntryViewControllerFuture)viewControllerFuture; + (instancetype)entryWithNameFuture:(FLEXGlobalsEntryNameFuture)nameFuture + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType action:(FLEXGlobalsEntryRowAction)rowSelectedAction; @end diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.m b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.m index b93b21422f..04e6f88574 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.m @@ -10,7 +10,9 @@ @implementation FLEXGlobalsEntry -+ (instancetype)entryWithEntry:(Class)cls row:(FLEXGlobalsRow)row { ++ (instancetype)entryWithEntry:(Class)cls + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType + row:(FLEXGlobalsRow)row { BOOL providesVCs = [cls respondsToSelector:@selector(globalsEntryViewController:)]; BOOL providesActions = [cls respondsToSelector:@selector(globalsEntryRowAction:)]; NSParameterAssert(cls); @@ -18,6 +20,7 @@ + (instancetype)entryWithEntry:(Class)cls row:(FLEXGlobalsRow) FLEXGlobalsEntry *entry = [self new]; entry->_entryNameFuture = ^{ return [cls globalsEntryTitle:row]; }; + entry->_cellAccessoryType = cellAccessoryType; if (providesVCs) { id action = providesActions ? [cls globalsEntryRowAction:row] : nil; @@ -34,24 +37,28 @@ + (instancetype)entryWithEntry:(Class)cls row:(FLEXGlobalsRow) } + (instancetype)entryWithNameFuture:(FLEXGlobalsEntryNameFuture)nameFuture + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType viewControllerFuture:(FLEXGlobalsEntryViewControllerFuture)viewControllerFuture { NSParameterAssert(nameFuture); NSParameterAssert(viewControllerFuture); FLEXGlobalsEntry *entry = [self new]; entry->_entryNameFuture = [nameFuture copy]; + entry->_cellAccessoryType = cellAccessoryType; entry->_viewControllerFuture = [viewControllerFuture copy]; return entry; } + (instancetype)entryWithNameFuture:(FLEXGlobalsEntryNameFuture)nameFuture + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType action:(FLEXGlobalsEntryRowAction)rowSelectedAction { NSParameterAssert(nameFuture); NSParameterAssert(rowSelectedAction); FLEXGlobalsEntry *entry = [self new]; entry->_entryNameFuture = [nameFuture copy]; + entry->_cellAccessoryType = cellAccessoryType; entry->_rowAction = [rowSelectedAction copy]; return entry; @@ -77,7 +84,10 @@ @implementation NSObject (FLEXGlobalsEntry) + (FLEXGlobalsEntry *)flex_concreteGlobalsEntry:(FLEXGlobalsRow)row { if ([self conformsToProtocol:@protocol(FLEXGlobalsEntry)]) { - return [FLEXGlobalsEntry entryWithEntry:self row:row]; + return [FLEXGlobalsEntry entryWithEntry:self + cellAccessoryType:UITableViewCellAccessoryDisclosureIndicator + row:row + ]; } return nil; diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsSection.m b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsSection.m index abb97ea2b4..c3548f6238 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsSection.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsSection.m @@ -69,7 +69,7 @@ - (UIViewController *)viewControllerToPushForRow:(NSInteger)row { } - (void)configureCell:(__kindof UITableViewCell *)cell forRow:(NSInteger)row { - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + cell.accessoryType = self.rows[row].cellAccessoryType; cell.textLabel.font = UIFont.flex_defaultTableCellFont; cell.textLabel.text = self.rows[row].entryNameFuture(); } diff --git a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h index 9b08d26ce4..fe15ad5bca 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h +++ b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.h @@ -26,6 +26,21 @@ NS_ASSUME_NONNULL_BEGIN /// you may want to use __weak references. - (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock; +/// Adds an entry at the top of the list of Global State items. +/// Call this method before this view controller is displayed. +/// @param entryName The string to be displayed in the cell. +/// @param cellAccessoryType The accessory type to be used for the cell. +/// @param objectFutureBlock When you tap on the row, information about the object returned +/// by this block will be displayed. Passing a block that returns an object allows you to display +/// information about an object whose actual pointer may change at runtime (e.g. +currentUser) +/// @note This method must be called from the main thread. +/// The objectFutureBlock will be invoked from the main thread and may return nil. +/// @note The passed block will be copied and retain for the duration of the application, +/// you may want to use __weak references. +- (void)registerGlobalEntryWithName:(NSString *)entryName + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType + objectFutureBlock:(id (^)(void))objectFutureBlock; + /// Adds an entry at the top of the list of Global State items. /// Call this method before this view controller is displayed. /// @param entryName The string to be displayed in the cell. @@ -38,6 +53,20 @@ NS_ASSUME_NONNULL_BEGIN - (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock; +/// Adds an entry at the top of the list of Global State items. +/// Call this method before this view controller is displayed. +/// @param entryName The string to be displayed in the cell. +/// @param cellAccessoryType The accessory type to be used for the cell. +/// @param viewControllerFutureBlock When you tap on the row, view controller returned +/// by this block will be pushed on the navigation controller stack. +/// @note This method must be called from the main thread. +/// The viewControllerFutureBlock will be invoked from the main thread and may not return nil. +/// @note The passed block will be copied and retain for the duration of the application, +/// you may want to use __weak references as needed. +- (void)registerGlobalEntryWithName:(NSString *)entryName + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType + viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock; + /// Adds an entry at the top of the list of Global State items. /// @param entryName The string to be displayed in the cell. /// @param rowSelectedAction When you tap on the row, this block will be invoked @@ -48,6 +77,19 @@ NS_ASSUME_NONNULL_BEGIN /// you may want to use __weak references as needed. - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction; +/// Adds an entry at the top of the list of Global State items. +/// @param entryName The string to be displayed in the cell. +/// @param cellAccessoryType The accessory type to be used for the cell. +/// @param rowSelectedAction When you tap on the row, this block will be invoked +/// with the host table view view controller. Use it to deselect the row or present an alert. +/// @note This method must be called from the main thread. +/// The rowSelectedAction will be invoked from the main thread. +/// @note The passed block will be copied and retained for the duration of the application, +/// you may want to use __weak references as needed. +- (void)registerGlobalEntryWithName:(NSString *)entryName + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType + action:(FLEXGlobalsEntryRowAction)rowSelectedAction; + /// Adds an entry at the top of the list of Global State items. /// @param entryName The string to be displayed in the cell. /// @param nestedEntriesHandler When you tap on the row, this block will be invoked @@ -58,6 +100,19 @@ NS_ASSUME_NONNULL_BEGIN /// you may want to use __weak references as needed. - (void)registerNestedGlobalEntryWithName:(NSString *)entryName handler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler; +/// Adds an entry at the top of the list of Global State items. +/// @param entryName The string to be displayed in the cell. +/// @param cellAccessoryType The accessory type to be used for the cell. +/// @param nestedEntriesHandler When you tap on the row, this block will be invoked +/// with the container object. Use it to register nested entries. +/// @note This method must be called from the main thread. +/// The nestedEntriesHandler will be invoked from the main thread. +/// @note The passed block will be copied and retained for the duration of the application, +/// you may want to use __weak references as needed. +- (void)registerNestedGlobalEntryWithName:(NSString *)entryName + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType + handler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler; + /// Removes all registered global entries. - (void)clearGlobalEntries; diff --git a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m index 9eff58d326..2f519086d1 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXUserGlobalEntriesContainer.m @@ -28,6 +28,13 @@ - (instancetype)init { } - (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id (^)(void))objectFutureBlock { + [self registerGlobalEntryWithName:entryName + cellAccessoryType:UITableViewCellAccessoryDisclosureIndicator + objectFutureBlock:objectFutureBlock + ]; +} + +- (void)registerGlobalEntryWithName:(NSString *)entryName cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType objectFutureBlock:(id (^)(void))objectFutureBlock { NSParameterAssert(entryName); NSParameterAssert(objectFutureBlock); NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); @@ -35,7 +42,7 @@ - (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id entryName = entryName.copy; FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString *{ return entryName; - } viewControllerFuture:^UIViewController *{ + } cellAccessoryType:cellAccessoryType viewControllerFuture:^UIViewController *{ return [FLEXObjectExplorerFactory explorerViewControllerForObject:objectFutureBlock()]; }]; @@ -43,6 +50,15 @@ - (void)registerGlobalEntryWithName:(NSString *)entryName objectFutureBlock:(id } - (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock { + [self registerGlobalEntryWithName:entryName + cellAccessoryType:UITableViewCellAccessoryDisclosureIndicator + viewControllerFutureBlock:viewControllerFutureBlock + ]; +} + +- (void)registerGlobalEntryWithName:(NSString *)entryName + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType + viewControllerFutureBlock:(UIViewController * (^)(void))viewControllerFutureBlock { NSParameterAssert(entryName); NSParameterAssert(viewControllerFutureBlock); NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); @@ -50,7 +66,7 @@ - (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBl entryName = entryName.copy; FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString *{ return entryName; - } viewControllerFuture:^UIViewController *{ + } cellAccessoryType:cellAccessoryType viewControllerFuture:^UIViewController *{ UIViewController *viewController = viewControllerFutureBlock(); NSCAssert(viewController, @"'%@' entry returned nil viewController. viewControllerFutureBlock should never return nil.", entryName); return viewController; @@ -60,6 +76,15 @@ - (void)registerGlobalEntryWithName:(NSString *)entryName viewControllerFutureBl } - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEntryRowAction)rowSelectedAction { + [self registerGlobalEntryWithName:entryName + cellAccessoryType:UITableViewCellAccessoryDisclosureIndicator + action:rowSelectedAction + ]; +} + +- (void)registerGlobalEntryWithName:(NSString *)entryName + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType + action:(FLEXGlobalsEntryRowAction)rowSelectedAction { NSParameterAssert(entryName); NSParameterAssert(rowSelectedAction); NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); @@ -67,12 +92,21 @@ - (void)registerGlobalEntryWithName:(NSString *)entryName action:(FLEXGlobalsEnt entryName = entryName.copy; FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString * _Nonnull{ return entryName; - } action:rowSelectedAction]; + } cellAccessoryType:cellAccessoryType action:rowSelectedAction]; [self.entries addObject:entry]; } - (void)registerNestedGlobalEntryWithName:(NSString *)entryName handler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler { + [self registerNestedGlobalEntryWithName:entryName + cellAccessoryType:UITableViewCellAccessoryDisclosureIndicator + handler:nestedEntriesHandler + ]; +} + +- (void)registerNestedGlobalEntryWithName:(NSString *)entryName + cellAccessoryType:(UITableViewCellAccessoryType)cellAccessoryType + handler:(FLEXNestedGlobalEntriesHandler)nestedEntriesHandler { NSParameterAssert(entryName); NSParameterAssert(nestedEntriesHandler); NSAssert(NSThread.isMainThread, @"This method must be called from the main thread."); @@ -80,7 +114,7 @@ - (void)registerNestedGlobalEntryWithName:(NSString *)entryName handler:(FLEXNes entryName = entryName.copy; FLEXGlobalsEntry *entry = [FLEXGlobalsEntry entryWithNameFuture:^NSString * _Nonnull{ return entryName; - } viewControllerFuture:^UIViewController * _Nullable{ + } cellAccessoryType:cellAccessoryType viewControllerFuture:^UIViewController * _Nullable{ FLEXUserGlobalEntriesContainer *container = [FLEXUserGlobalEntriesContainer new]; nestedEntriesHandler(container); diff --git a/Example/FLEXample/AppDelegate.swift b/Example/FLEXample/AppDelegate.swift index 58ee03ec10..60fa362aa0 100644 --- a/Example/FLEXample/AppDelegate.swift +++ b/Example/FLEXample/AppDelegate.swift @@ -28,11 +28,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // To show off the global entries, register one of each type - FLEXManager.shared.globalEntriesContainer.registerGlobalEntry(withName: "Level 1 - Object") { + FLEXManager.shared.globalEntriesContainer.registerGlobalEntry(withName: "Level 1 - Object", cellAccessoryType: .none) { return "Level 1 - Object" } - FLEXManager.shared.globalEntriesContainer.registerGlobalEntry(withName: "Level 1 - View controller") { + FLEXManager.shared.globalEntriesContainer.registerGlobalEntry(withName: "Level 1 - View controller", cellAccessoryType: .none) { let label = UILabel() label.text = "Level 1 - View controller" label.translatesAutoresizingMaskIntoConstraints = false @@ -48,16 +48,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return controller } - FLEXManager.shared.globalEntriesContainer.registerGlobalEntry(withName: "Level 1 - Action") { host in + FLEXManager.shared.globalEntriesContainer.registerGlobalEntry(withName: "Level 1 - Action", cellAccessoryType: .none) { host in FLEXAlert.showQuickAlert("Level 1 - Action", from: host) } FLEXManager.shared.globalEntriesContainer.registerNestedGlobalEntry(withName: "Level 1 - Nested") { container in - container.registerGlobalEntry(withName: "Level 2 - Object") { + container.registerGlobalEntry(withName: "Level 2 - Object", cellAccessoryType: .none) { return "Level 2 - Object" } - container.registerGlobalEntry(withName: "Level 2 - View controller") { + container.registerGlobalEntry(withName: "Level 2 - View controller", cellAccessoryType: .none) { let label = UILabel() label.text = "Level 2 - View controller" label.translatesAutoresizingMaskIntoConstraints = false @@ -73,12 +73,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return controller } - container.registerGlobalEntry(withName: "Level 2 - Action") { host in + container.registerGlobalEntry(withName: "Level 2 - Action", cellAccessoryType: .none) { host in FLEXAlert.showQuickAlert("Level 2 - Action", from: host) } container.registerNestedGlobalEntry(withName: "Level 2 - Nested") { level2Container in - level2Container.registerGlobalEntry(withName: "Level 3 - Action") { host in + level2Container.registerGlobalEntry(withName: "Level 3 - Action", cellAccessoryType: .none) { host in FLEXAlert.showQuickAlert("Level 3 - Action", from: host) } } From 94b6883ffc25c304eb631fefd8bfdd1a625f856e Mon Sep 17 00:00:00 2001 From: Iulian Onofrei <5748627+revolter@users.noreply.github.com> Date: Fri, 4 Aug 2023 15:28:39 +0300 Subject: [PATCH 13/13] Fix confusing navigation stack for nested global entries --- .../GlobalStateExplorers/Globals/FLEXGlobalsViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m index 6b83245332..8a632c1b1b 100644 --- a/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m +++ b/Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.m @@ -171,7 +171,7 @@ - (void)viewDidLoad { self.title = self.customTitle ?: @"💪 FLEX"; self.showsSearchBar = YES; self.searchBarDebounceInterval = kFLEXDebounceInstant; - self.navigationItem.backBarButtonItem = [UIBarButtonItem flex_backItemWithTitle:@"Back"]; + self.navigationItem.backBarButtonItem = [UIBarButtonItem flex_backItemWithTitle:self.showsDefaultEntries ? @"Back" : self.title]; _manuallyDeselectOnAppear = NSProcessInfo.processInfo.operatingSystemVersion.majorVersion < 10; }