added files via upload

This commit is contained in:
Balackburn
2023-06-27 09:54:41 +02:00
commit 2ff6aac218
1420 changed files with 88898 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
//
// FLEXManager+Extensibility.h
// FLEX
//
// Created by Tanner on 2/2/20.
// Copyright © 2020 FLEX Team. All rights reserved.
//
#import "FLEXManager.h"
#import "FLEXGlobalsEntry.h"
NS_ASSUME_NONNULL_BEGIN
@interface FLEXManager (Extensibility)
#pragma mark - Globals Screen Entries
/// 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;
#pragma mark - Simulator Shortcuts
/// Simulator keyboard shortcuts are enabled by default.
/// The shortcuts will not fire when there is an active text field, text view, or other responder
/// accepting key input. You can disable keyboard shortcuts if you have existing keyboard shortcuts
/// that conflict with FLEX, or if you like doing things the hard way ;)
/// Keyboard shortcuts are always disabled (and support is #if'd out) in non-simulator builds
@property (nonatomic) BOOL simulatorShortcutsEnabled;
/// Adds an action to run when the specified key & modifier combination is pressed
/// @param key A single character string matching a key on the keyboard
/// @param modifiers Modifier keys such as shift, command, or alt/option
/// @param action The block to run on the main thread when the key & modifier combination is recognized.
/// @param description Shown the the keyboard shortcut help menu, which is accessed via the '?' key.
/// @note The action block will be retained for the duration of the application. You may want to use weak references.
/// @note FLEX registers several default keyboard shortcuts. Use the '?' key to see a list of shortcuts.
- (void)registerSimulatorShortcutWithKey:(NSString *)key
modifiers:(UIKeyModifierFlags)modifiers
action:(dispatch_block_t)action
description:(NSString *)description;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,272 @@
//
// FLEXManager+Extensibility.m
// FLEX
//
// Created by Tanner on 2/2/20.
// Copyright © 2020 FLEX Team. All rights reserved.
//
#import "FLEXManager+Extensibility.h"
#import "FLEXManager+Private.h"
#import "FLEXNavigationController.h"
#import "FLEXObjectExplorerFactory.h"
#import "FLEXKeyboardShortcutManager.h"
#import "FLEXExplorerViewController.h"
#import "FLEXNetworkMITMViewController.h"
#import "FLEXKeyboardHelpViewController.h"
#import "FLEXFileBrowserController.h"
#import "FLEXUtility.h"
@interface FLEXManager (ExtensibilityPrivate)
@property (nonatomic, readonly) UIViewController *topViewController;
@end
@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];
}
- (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];
}
#pragma mark - Simulator Shortcuts
- (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description {
#if TARGET_OS_SIMULATOR
[FLEXKeyboardShortcutManager.sharedManager registerSimulatorShortcutWithKey:key modifiers:modifiers action:action description:description allowOverride:YES];
#endif
}
- (void)setSimulatorShortcutsEnabled:(BOOL)simulatorShortcutsEnabled {
#if TARGET_OS_SIMULATOR
[FLEXKeyboardShortcutManager.sharedManager setEnabled:simulatorShortcutsEnabled];
#endif
}
- (BOOL)simulatorShortcutsEnabled {
#if TARGET_OS_SIMULATOR
return FLEXKeyboardShortcutManager.sharedManager.isEnabled;
#else
return NO;
#endif
}
#pragma mark - Shortcuts Defaults
- (void)registerDefaultSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description {
#if TARGET_OS_SIMULATOR
// Don't allow override to avoid changing keys registered by the app
[FLEXKeyboardShortcutManager.sharedManager registerSimulatorShortcutWithKey:key modifiers:modifiers action:action description:description allowOverride:NO];
#endif
}
- (void)registerDefaultSimulatorShortcuts {
[self registerDefaultSimulatorShortcutWithKey:@"f" modifiers:0 action:^{
[self toggleExplorer];
} description:@"Toggle FLEX toolbar"];
[self registerDefaultSimulatorShortcutWithKey:@"g" modifiers:0 action:^{
[self showExplorerIfNeeded];
[self.explorerViewController toggleMenuTool];
} description:@"Toggle FLEX globals menu"];
[self registerDefaultSimulatorShortcutWithKey:@"v" modifiers:0 action:^{
[self showExplorerIfNeeded];
[self.explorerViewController toggleViewsTool];
} description:@"Toggle view hierarchy menu"];
[self registerDefaultSimulatorShortcutWithKey:@"s" modifiers:0 action:^{
[self showExplorerIfNeeded];
[self.explorerViewController toggleSelectTool];
} description:@"Toggle select tool"];
[self registerDefaultSimulatorShortcutWithKey:@"m" modifiers:0 action:^{
[self showExplorerIfNeeded];
[self.explorerViewController toggleMoveTool];
} description:@"Toggle move tool"];
[self registerDefaultSimulatorShortcutWithKey:@"n" modifiers:0 action:^{
[self toggleTopViewControllerOfClass:[FLEXNetworkMITMViewController class]];
} description:@"Toggle network history view"];
[self registerDefaultSimulatorShortcutWithKey:UIKeyInputDownArrow modifiers:0 action:^{
if (self.isHidden || ![self.explorerViewController handleDownArrowKeyPressed]) {
[self tryScrollDown];
}
} description:@"Cycle view selection\n\t\tMove view down\n\t\tScroll down"];
[self registerDefaultSimulatorShortcutWithKey:UIKeyInputUpArrow modifiers:0 action:^{
if (self.isHidden || ![self.explorerViewController handleUpArrowKeyPressed]) {
[self tryScrollUp];
}
} description:@"Cycle view selection\n\t\tMove view up\n\t\tScroll up"];
[self registerDefaultSimulatorShortcutWithKey:UIKeyInputRightArrow modifiers:0 action:^{
if (!self.isHidden) {
[self.explorerViewController handleRightArrowKeyPressed];
}
} description:@"Move selected view right"];
[self registerDefaultSimulatorShortcutWithKey:UIKeyInputLeftArrow modifiers:0 action:^{
if (self.isHidden) {
[self tryGoBack];
} else {
[self.explorerViewController handleLeftArrowKeyPressed];
}
} description:@"Move selected view left"];
[self registerDefaultSimulatorShortcutWithKey:@"?" modifiers:0 action:^{
[self toggleTopViewControllerOfClass:[FLEXKeyboardHelpViewController class]];
} description:@"Toggle (this) help menu"];
[self registerDefaultSimulatorShortcutWithKey:UIKeyInputEscape modifiers:0 action:^{
[[self.topViewController presentingViewController] dismissViewControllerAnimated:YES completion:nil];
} description:@"End editing text\n\t\tDismiss top view controller"];
[self registerDefaultSimulatorShortcutWithKey:@"o" modifiers:UIKeyModifierCommand|UIKeyModifierShift action:^{
[self toggleTopViewControllerOfClass:[FLEXFileBrowserController class]];
} description:@"Toggle file browser menu"];
}
+ (void)load {
dispatch_async(dispatch_get_main_queue(), ^{
[self.sharedManager registerDefaultSimulatorShortcuts];
});
}
#pragma mark - Private
- (UIEdgeInsets)contentInsetsOfScrollView:(UIScrollView *)scrollView {
if (@available(iOS 11, *)) {
return scrollView.adjustedContentInset;
}
return scrollView.contentInset;
}
- (void)tryScrollDown {
UIScrollView *scrollview = [self firstScrollView];
UIEdgeInsets insets = [self contentInsetsOfScrollView:scrollview];
CGPoint contentOffset = scrollview.contentOffset;
CGFloat maxYOffset = scrollview.contentSize.height - scrollview.bounds.size.height + insets.bottom;
contentOffset.y = MIN(contentOffset.y + 200, maxYOffset);
[scrollview setContentOffset:contentOffset animated:YES];
}
- (void)tryScrollUp {
UIScrollView *scrollview = [self firstScrollView];
UIEdgeInsets insets = [self contentInsetsOfScrollView:scrollview];
CGPoint contentOffset = scrollview.contentOffset;
contentOffset.y = MAX(contentOffset.y - 200, -insets.top);
[scrollview setContentOffset:contentOffset animated:YES];
}
- (UIScrollView *)firstScrollView {
NSMutableArray<UIView *> *views = FLEXUtility.appKeyWindow.subviews.mutableCopy;
UIScrollView *scrollView = nil;
while (views.count > 0) {
UIView *view = views.firstObject;
[views removeObjectAtIndex:0];
if ([view isKindOfClass:[UIScrollView class]]) {
scrollView = (UIScrollView *)view;
break;
} else {
[views addObjectsFromArray:view.subviews];
}
}
return scrollView;
}
- (void)tryGoBack {
UINavigationController *navigationController = nil;
UIViewController *topViewController = self.topViewController;
if ([topViewController isKindOfClass:[UINavigationController class]]) {
navigationController = (UINavigationController *)topViewController;
} else {
navigationController = topViewController.navigationController;
}
[navigationController popViewControllerAnimated:YES];
}
- (UIViewController *)topViewController {
return [FLEXUtility topViewControllerInWindow:UIApplication.sharedApplication.keyWindow];
}
- (void)toggleTopViewControllerOfClass:(Class)class {
UINavigationController *topViewController = (id)self.topViewController;
if ([topViewController isKindOfClass:[FLEXNavigationController class]]) {
if ([topViewController.topViewController isKindOfClass:[class class]]) {
if (topViewController.viewControllers.count == 1) {
// Dismiss since we are already presenting it
[topViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
} else {
// Pop since we are viewing it but it's not the only thing on the stack
[topViewController popViewControllerAnimated:YES];
}
} else {
// Push it on the existing navigation stack
[topViewController pushViewController:[class new] animated:YES];
}
} else {
// Present it in an entirely new navigation controller
[self.explorerViewController presentViewController:
[FLEXNavigationController withRootViewController:[class new]]
animated:YES completion:nil];
}
}
- (void)showExplorerIfNeeded {
if (self.isHidden) {
[self showExplorer];
}
}
@end

View File

@@ -0,0 +1,40 @@
//
// FLEXManager+Networking.h
// FLEX
//
// Created by Tanner on 2/1/20.
// Copyright © 2020 FLEX Team. All rights reserved.
//
#import "FLEXManager.h"
NS_ASSUME_NONNULL_BEGIN
@interface FLEXManager (Networking)
/// If this property is set to YES, FLEX will swizzle NSURLConnection*Delegate and NSURLSession*Delegate methods
/// on classes that conform to the protocols. This allows you to view network activity history from the main FLEX menu.
/// Full responses are kept temporarily in a size-limited cache and may be pruned under memory pressure.
@property (nonatomic, getter=isNetworkDebuggingEnabled) BOOL networkDebuggingEnabled;
/// Defaults to 25 MB if never set. Values set here are persisted across launches of the app.
/// The response cache uses an NSCache, so it may purge prior to hitting the limit when the app is under memory pressure.
@property (nonatomic) NSUInteger networkResponseCacheByteLimit;
/// Requests whose host ends with one of the excluded entries in this array will be not be recorded (eg. google.com).
/// Wildcard or subdomain entries are not required (eg. google.com will match any subdomain under google.com).
/// Useful to remove requests that are typically noisy, such as analytics requests that you aren't interested in tracking.
@property (nonatomic) NSMutableArray<NSString *> *networkRequestHostDenylist;
/// Sets custom viewer for specific content type.
/// @param contentType Mime type like application/json
/// @param viewControllerFutureBlock Viewer (view controller) creation block
/// @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.
- (void)setCustomViewerForContentType:(NSString *)contentType
viewControllerFutureBlock:(FLEXCustomContentViewerFuture)viewControllerFutureBlock;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,68 @@
//
// FLEXManager+Networking.m
// FLEX
//
// Created by Tanner on 2/1/20.
// Copyright © 2020 FLEX Team. All rights reserved.
//
#import "FLEXManager+Networking.h"
#import "FLEXManager+Private.h"
#import "FLEXNetworkObserver.h"
#import "FLEXNetworkRecorder.h"
#import "FLEXObjectExplorerFactory.h"
#import "NSUserDefaults+FLEX.h"
@implementation FLEXManager (Networking)
+ (void)load {
if (NSUserDefaults.standardUserDefaults.flex_registerDictionaryJSONViewerOnLaunch) {
dispatch_async(dispatch_get_main_queue(), ^{
// Register array/dictionary viewer for JSON responses
[self.sharedManager setCustomViewerForContentType:@"application/json"
viewControllerFutureBlock:^UIViewController *(NSData *data) {
id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if (jsonObject) {
return [FLEXObjectExplorerFactory explorerViewControllerForObject:jsonObject];
}
return nil;
}
];
});
}
}
- (BOOL)isNetworkDebuggingEnabled {
return FLEXNetworkObserver.isEnabled;
}
- (void)setNetworkDebuggingEnabled:(BOOL)networkDebuggingEnabled {
FLEXNetworkObserver.enabled = networkDebuggingEnabled;
}
- (NSUInteger)networkResponseCacheByteLimit {
return FLEXNetworkRecorder.defaultRecorder.responseCacheByteLimit;
}
- (void)setNetworkResponseCacheByteLimit:(NSUInteger)networkResponseCacheByteLimit {
FLEXNetworkRecorder.defaultRecorder.responseCacheByteLimit = networkResponseCacheByteLimit;
}
- (NSMutableArray<NSString *> *)networkRequestHostDenylist {
return FLEXNetworkRecorder.defaultRecorder.hostDenylist;
}
- (void)setNetworkRequestHostDenylist:(NSMutableArray<NSString *> *)networkRequestHostDenylist {
FLEXNetworkRecorder.defaultRecorder.hostDenylist = networkRequestHostDenylist;
}
- (void)setCustomViewerForContentType:(NSString *)contentType
viewControllerFutureBlock:(FLEXCustomContentViewerFuture)viewControllerFutureBlock {
NSParameterAssert(contentType.length);
NSParameterAssert(viewControllerFutureBlock);
NSAssert(NSThread.isMainThread, @"This method must be called from the main thread.");
self.customContentTypeViewers[contentType.lowercaseString] = viewControllerFutureBlock;
}
@end

View File

@@ -0,0 +1,47 @@
//
// FLEXManager.h
// Flipboard
//
// Created by Ryan Olson on 4/4/14.
// Copyright (c) 2020 FLEX Team. All rights reserved.
//
#import "FLEXExplorerToolbar.h"
NS_ASSUME_NONNULL_BEGIN
@interface FLEXManager : NSObject
@property (nonatomic, readonly, class) FLEXManager *sharedManager;
@property (nonatomic, readonly) BOOL isHidden;
@property (nonatomic, readonly) FLEXExplorerToolbar *toolbar;
- (void)showExplorer;
- (void)hideExplorer;
- (void)toggleExplorer;
/// Programmatically dismiss anything presented by FLEX, leaving only the toolbar visible.
- (void)dismissAnyPresentedTools:(void (^_Nullable)(void))completion;
/// Programmatically present something on top of the FLEX toolbar.
/// This method will automatically dismiss any currently presented tool,
/// so you do not need to call \c dismissAnyPresentedTools: yourself.
- (void)presentTool:(UINavigationController *(^)(void))viewControllerFuture
completion:(void (^_Nullable)(void))completion;
/// Use this to present the explorer in a specific scene when the one
/// it chooses by default is not the one you wish to display it in.
- (void)showExplorerFromScene:(UIWindowScene *)scene API_AVAILABLE(ios(13.0));
#pragma mark - Misc
/// Default database password is @c nil by default.
/// Set this to the password you want the databases to open with.
@property (copy, nonatomic) NSString *defaultSqliteDatabasePassword;
@end
typedef UIViewController * _Nullable(^FLEXCustomContentViewerFuture)(NSData *data);
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,145 @@
//
// FLEXManager.m
// Flipboard
//
// Created by Ryan Olson on 4/4/14.
// Copyright (c) 2020 FLEX Team. All rights reserved.
//
#import "FLEXManager.h"
#import "FLEXUtility.h"
#import "FLEXExplorerViewController.h"
#import "FLEXWindow.h"
#import "FLEXObjectExplorerViewController.h"
#import "FLEXFileBrowserController.h"
@interface FLEXManager () <FLEXWindowEventDelegate, FLEXExplorerViewControllerDelegate>
@property (nonatomic, readonly, getter=isHidden) BOOL hidden;
@property (nonatomic) FLEXWindow *explorerWindow;
@property (nonatomic) FLEXExplorerViewController *explorerViewController;
@property (nonatomic, readonly) NSMutableArray<FLEXGlobalsEntry *> *userGlobalEntries;
@property (nonatomic, readonly) NSMutableDictionary<NSString *, FLEXCustomContentViewerFuture> *customContentTypeViewers;
@end
@implementation FLEXManager
+ (instancetype)sharedManager {
static FLEXManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [self new];
});
return sharedManager;
}
- (instancetype)init {
self = [super init];
if (self) {
_userGlobalEntries = [NSMutableArray new];
_customContentTypeViewers = [NSMutableDictionary new];
}
return self;
}
- (FLEXWindow *)explorerWindow {
NSAssert(NSThread.isMainThread, @"You must use %@ from the main thread only.", NSStringFromClass([self class]));
if (!_explorerWindow) {
_explorerWindow = [[FLEXWindow alloc] initWithFrame:FLEXUtility.appKeyWindow.bounds];
_explorerWindow.eventDelegate = self;
_explorerWindow.rootViewController = self.explorerViewController;
}
return _explorerWindow;
}
- (FLEXExplorerViewController *)explorerViewController {
if (!_explorerViewController) {
_explorerViewController = [FLEXExplorerViewController new];
_explorerViewController.delegate = self;
}
return _explorerViewController;
}
- (void)showExplorer {
UIWindow *flex = self.explorerWindow;
flex.hidden = NO;
if (@available(iOS 13.0, *)) {
// Only look for a new scene if we don't have one
if (!flex.windowScene) {
flex.windowScene = FLEXUtility.appKeyWindow.windowScene;
}
}
}
- (void)hideExplorer {
self.explorerWindow.hidden = YES;
}
- (void)toggleExplorer {
if (self.explorerWindow.isHidden) {
if (@available(iOS 13.0, *)) {
[self showExplorerFromScene:FLEXUtility.appKeyWindow.windowScene];
} else {
[self showExplorer];
}
} else {
[self hideExplorer];
}
}
- (void)dismissAnyPresentedTools:(void (^)(void))completion {
if (self.explorerViewController.presentedViewController) {
[self.explorerViewController dismissViewControllerAnimated:YES completion:completion];
} else if (completion) {
completion();
}
}
- (void)presentTool:(UINavigationController * _Nonnull (^)(void))future completion:(void (^)(void))completion {
[self showExplorer];
[self.explorerViewController presentTool:future completion:completion];
}
- (void)showExplorerFromScene:(UIWindowScene *)scene {
if (@available(iOS 13.0, *)) {
self.explorerWindow.windowScene = scene;
}
self.explorerWindow.hidden = NO;
}
- (BOOL)isHidden {
return self.explorerWindow.isHidden;
}
- (FLEXExplorerToolbar *)toolbar {
return self.explorerViewController.explorerToolbar;
}
#pragma mark - FLEXWindowEventDelegate
- (BOOL)shouldHandleTouchAtPoint:(CGPoint)pointInWindow {
// Ask the explorer view controller
return [self.explorerViewController shouldReceiveTouchAtWindowPoint:pointInWindow];
}
- (BOOL)canBecomeKeyWindow {
// Only when the explorer view controller wants it because
// it needs to accept key input & affect the status bar.
return self.explorerViewController.wantsWindowToBecomeKey;
}
#pragma mark - FLEXExplorerViewControllerDelegate
- (void)explorerViewControllerDidFinish:(FLEXExplorerViewController *)explorerViewController {
[self hideExplorer];
}
@end

View File

@@ -0,0 +1,23 @@
//
// FLEXManager+Private.h
// PebbleApp
//
// Created by Javier Soto on 7/26/14.
// Copyright (c) 2020 FLEX Team. All rights reserved.
//
#import "FLEXManager.h"
#import "FLEXWindow.h"
@class FLEXGlobalsEntry, 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<FLEXGlobalsEntry *> *userGlobalEntries;
@property (nonatomic, readonly) NSMutableDictionary<NSString *, FLEXCustomContentViewerFuture> *customContentTypeViewers;
@end