From d1eb7b45a2420a9b89b002f21763a574c3bc6434 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 3 Nov 2019 13:38:52 -0800 Subject: [PATCH] Add quick action shortcuts to open paired PCs --- Limelight/AppDelegate.h | 2 + Limelight/AppDelegate.m | 13 +++- .../ViewControllers/MainFrameViewController.m | 67 +++++++++++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/Limelight/AppDelegate.h b/Limelight/AppDelegate.h index 0985139..90deb40 100644 --- a/Limelight/AppDelegate.h +++ b/Limelight/AppDelegate.h @@ -11,6 +11,8 @@ @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; +@property (strong, nonatomic) NSString *pcUuidToLoad; +@property (strong, nonatomic) void (^shortcutCompletionHandler)(BOOL); @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; diff --git a/Limelight/AppDelegate.m b/Limelight/AppDelegate.m index 65c97cf..916bac8 100644 --- a/Limelight/AppDelegate.m +++ b/Limelight/AppDelegate.m @@ -22,12 +22,19 @@ static NSString* DB_NAME = @"Moonlight_tvOS.bin"; static NSString* DB_NAME = @"Limelight_iOS.sqlite"; #endif -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + UIApplicationShortcutItem* shortcut = [launchOptions valueForKey:UIApplicationLaunchOptionsShortcutItemKey]; + if (shortcut != nil) { + _pcUuidToLoad = (NSString*)[shortcut.userInfo objectForKey:@"UUID"]; + } return YES; } +- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL succeeded))completionHandler { + _pcUuidToLoad = (NSString*)[shortcutItem.userInfo objectForKey:@"UUID"]; + _shortcutCompletionHandler = completionHandler; +} + - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m index 49054b6..79d914a 100644 --- a/Limelight/ViewControllers/MainFrameViewController.m +++ b/Limelight/ViewControllers/MainFrameViewController.m @@ -244,6 +244,10 @@ static NSMutableSet* hostList; } while (appWasRemoved); [database updateAppsForExistingHost:host]; + + // This host may be eligible for a shortcut now that the app list + // has been populated + [self updateHostShortcuts]; } - (void)showHostSelectionView { @@ -809,11 +813,44 @@ static NSMutableSet* hostList; } } +-(void)handlePendingShortcutAction +{ + // Check if we have a pending shortcut action + AppDelegate* delegate = (AppDelegate*)[UIApplication sharedApplication].delegate; + if (delegate.pcUuidToLoad != nil) { + // Find the host it corresponds to + TemporaryHost* matchingHost = nil; + for (TemporaryHost* host in hostList) { + if ([host.uuid isEqualToString:delegate.pcUuidToLoad]) { + matchingHost = host; + break; + } + } + + // Clear the pending shortcut action + delegate.pcUuidToLoad = nil; + + // Complete the request + if (delegate.shortcutCompletionHandler != nil) { + delegate.shortcutCompletionHandler(matchingHost != nil); + delegate.shortcutCompletionHandler = nil; + } + + if (matchingHost != nil && _selectedHost != matchingHost) { + // Navigate to the host page + [self hostClicked:matchingHost view:nil]; + } + } +} + -(void)handleReturnToForeground { _background = NO; [self beginForegroundRefresh: YES]; + + // Check for a pending shortcut action when returning to foreground + [self handlePendingShortcutAction]; } -(void)handleEnterBackground @@ -838,6 +875,9 @@ static NSMutableSet* hostList; [self.navigationController.navigationBar setShadowImage:fakeImage]; [self.navigationController.navigationBar setBackgroundImage:fakeImage forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault]; + // Check for a pending shortcut action when appearing + [self handlePendingShortcutAction]; + [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(handleReturnToForeground) name: UIApplicationDidBecomeActiveNotification @@ -926,6 +966,30 @@ static NSMutableSet* hostList; }); } +- (void)updateHostShortcuts { + if (@available(iOS 9.0, *)) { + NSMutableArray* quickActions = [[NSMutableArray alloc] init]; + + @synchronized (hostList) { + for (TemporaryHost* host in hostList) { + // Pair state may be unknown if we haven't polled it yet, but the app list + // count will persist from paired PCs + if ([host.appList count] > 0) { + UIApplicationShortcutItem* shortcut = [[UIApplicationShortcutItem alloc] + initWithType:@"PC" + localizedTitle:host.name + localizedSubtitle:nil + icon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypePlay] + userInfo:[NSDictionary dictionaryWithObject:host.uuid forKey:@"UUID"]]; + [quickActions addObject: shortcut]; + } + } + } + + [UIApplication sharedApplication].shortcutItems = quickActions; + } +} + - (void)updateHosts { Log(LOG_I, @"Updating hosts..."); [[hostScrollView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; @@ -950,6 +1014,9 @@ static NSMutableSet* hostList; } } + // Create or delete host shortcuts as needed + [self updateHostShortcuts]; + prevEdge = [self getCompViewX:addComp addComp:addComp prevEdge:prevEdge]; addComp.center = CGPointMake(prevEdge, hostScrollView.frame.size.height / 2);