| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- //
- // 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"
- #import "NSObject+FLEX_Reflection.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:UIScreen.mainScreen.bounds];
- _explorerWindow.eventDelegate = self;
- _explorerWindow.rootViewController = self.explorerViewController;
- }
-
- return _explorerWindow;
- }
- - (void)showHintsIfNecessary {
- BOOL dontShowHints = [[NSUserDefaults standardUserDefaults] boolForKey:@"DontShowHintsOnLaunch"];
- if (!dontShowHints){
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- [self showHintsAlert];
- });
- }
- }
- - (void)showHintsAlert {
-
- UIAlertController *alertController = [UIAlertController
- alertControllerWithTitle:@"Usage Guide"
- message:@"Triple tap 'Play/Pause' to hide or show the explorer view.\nIn selection mode 'Menu' will exit to the toolbar, and a long press on 'Select' or 'Play/Pause' will bring up a contextual menu for view info & movement.\nWhen browsing view/object details a long press on 'Select' will bring up the controller to edit view details.\n If you inject into HeadBoard the siri remote will NOT work for navigation and you will need to use something like AirMagic to navigate."
- preferredStyle:UIAlertControllerStyleAlert];
-
- UIAlertAction *hideForeverAction = [UIAlertAction
- actionWithTitle:@"Don't Show This Again"
- style:UIAlertActionStyleDestructive
- handler:^(UIAlertAction *action)
- {
- [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"DontShowHintsOnLaunch"];
- [[NSUserDefaults standardUserDefaults] synchronize];
- [self showExplorer];
- }];
- UIAlertAction *showForeverAction = [UIAlertAction
- actionWithTitle:@"Always Show On Launch"
- style:UIAlertActionStyleDestructive
- handler:^(UIAlertAction *action)
- {
- [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"DontShowHintsOnLaunch"];
- [[NSUserDefaults standardUserDefaults] synchronize];
- [self showExplorer];
- }];
- UIAlertAction *cancelAction = [UIAlertAction
- actionWithTitle:@"Dismiss"
- style:UIAlertActionStyleCancel
- handler:^(UIAlertAction *action)
- {
- [self showExplorer];
- }];
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DontShowHintsOnLaunch"]) {
- [alertController addAction:showForeverAction];
- }
- else {
- [alertController addAction:hideForeverAction];
- }
- [alertController addAction:cancelAction];
-
- #if TARGET_OS_TV
- [[self topViewController] presentViewController:alertController animated:YES completion:nil];
- #endif
- }
- - (void)tripleTap:(UITapGestureRecognizer *)tapRecognizer {
- FXLog(@"triple tap!");
- if ([self isHidden]){
- [self showExplorer];
- } else {
- [self hideExplorer];
- }
- }
- - (void)_addTVOSGestureRecognizer:(UIViewController *)explorer {
- UITapGestureRecognizer *tripleTaps = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tripleTap:)];
- tripleTaps.allowedPressTypes = @[[NSNumber numberWithInteger:UIPressTypePlayPause]];
- tripleTaps.numberOfTapsRequired = 3;
- [explorer.view addGestureRecognizer:tripleTaps];
- }
- - (FLEXExplorerViewController *)explorerViewController {
- if (!_explorerViewController) {
- _explorerViewController = [FLEXExplorerViewController new];
- _explorerViewController.delegate = self;
- #if TARGET_OS_TV
- [self _addTVOSGestureRecognizer:_explorerViewController];
- #endif
- }
- return _explorerViewController;
- }
- - (void)showExplorer {
- UIWindow *flex = self.explorerWindow;
- flex.hidden = NO;
- #if TARGET_OS_TV
- FLEXWindow *exp = [self explorerWindow];
- [exp makeKeyWindow];
- #endif
- #if FLEX_AT_LEAST_IOS13_SDK
- if (@available(iOS 13.0, *)) {
- // Only look for a new scene if we don't have one
- if (!flex.windowScene) {
- flex.windowScene = FLEXUtility.activeScene;
- }
- }
- #endif
- }
- - (void)hideExplorer {
- self.explorerWindow.hidden = YES;
- }
- - (void)toggleExplorer {
- if (self.explorerWindow.isHidden) {
- [self showExplorer];
- } else {
- [self hideExplorer];
- }
- }
- - (void)showExplorerFromScene:(UIWindowScene *)scene {
- #if FLEX_AT_LEAST_IOS13_SDK
- if (@available(iOS 13.0, *)) {
- self.explorerWindow.windowScene = scene;
- }
- #endif
- 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
|