mirror of
https://github.com/SoPat712/YTLitePlus.git
synced 2025-12-27 00:37:21 -05:00
added files via upload
This commit is contained in:
78
Tweaks/FLEX/Manager/FLEXManager+Extensibility.h
Normal file
78
Tweaks/FLEX/Manager/FLEXManager+Extensibility.h
Normal 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
|
||||
272
Tweaks/FLEX/Manager/FLEXManager+Extensibility.m
Normal file
272
Tweaks/FLEX/Manager/FLEXManager+Extensibility.m
Normal 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
|
||||
40
Tweaks/FLEX/Manager/FLEXManager+Networking.h
Normal file
40
Tweaks/FLEX/Manager/FLEXManager+Networking.h
Normal 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
|
||||
68
Tweaks/FLEX/Manager/FLEXManager+Networking.m
Normal file
68
Tweaks/FLEX/Manager/FLEXManager+Networking.m
Normal 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
|
||||
47
Tweaks/FLEX/Manager/FLEXManager.h
Normal file
47
Tweaks/FLEX/Manager/FLEXManager.h
Normal 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
|
||||
145
Tweaks/FLEX/Manager/FLEXManager.m
Normal file
145
Tweaks/FLEX/Manager/FLEXManager.m
Normal 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
|
||||
23
Tweaks/FLEX/Manager/Private/FLEXManager+Private.h
Normal file
23
Tweaks/FLEX/Manager/Private/FLEXManager+Private.h
Normal 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
|
||||
Reference in New Issue
Block a user