Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ios): fix various issues related to the scene migration #13981

Merged
merged 4 commits into from
Feb 11, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 85 additions & 135 deletions iphone/TitaniumKit/TitaniumKit/Sources/API/TiApp.m
Original file line number Diff line number Diff line change
Expand Up @@ -316,106 +316,10 @@ - (BOOL)application:(UIApplication *)application shouldAllowExtensionPointIdenti

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions_
{
started = [NSDate timeIntervalSinceReferenceDate];
[TiExceptionHandler defaultExceptionHandler];
if ([[TiSharedConfig defaultConfig] logServerEnabled]) {
[[TiLogServer defaultLogServer] start];
}

// Initialize the launch options to be used by the client
launchOptions = [[NSMutableDictionary alloc] initWithDictionary:launchOptions_];

// If we have a APNS-UUID, assign it
NSString *apnsUUID = [[NSUserDefaults standardUserDefaults] stringForKey:@"APNSRemoteDeviceUUID"];
if (apnsUUID != nil) {
remoteDeviceUUID = [apnsUUID copy];
}

[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];

// Get some launch options to validate before finish launching. Some of them
// need to be mapepd from native to JS-types to be used by the client
NSURL *urlOptions = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
NSString *sourceBundleId = [launchOptions objectForKey:UIApplicationLaunchOptionsSourceApplicationKey];
NSDictionary *_remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
UILocalNotification *_localNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
NSNumber *launchedLocation = [launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey];
UIApplicationShortcutItem *shortcut = [launchOptions objectForKey:UIApplicationLaunchOptionsShortcutItemKey];
NSDictionary *userActivityDictionary = launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey];

// Map user activity if exists
NSUserActivity *userActivity = userActivityDictionary[@"UIApplicationLaunchOptionsUserActivityKey"];
if (userActivity != nil && [userActivity isKindOfClass:[NSUserActivity class]]) {
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:@{ @"activityType" : [userActivity activityType] }];

if ([TiUtils isIOSVersionOrGreater:@"9.0"] && [[userActivity activityType] isEqualToString:CSSearchableItemActionType]) {
if ([userActivity userInfo] != nil) {
[dict setObject:[[userActivity userInfo] objectForKey:CSSearchableItemActivityIdentifier] forKey:@"searchableItemActivityIdentifier"];
}
}

if ([userActivity title] != nil) {
[dict setObject:[userActivity title] forKey:@"title"];
}

if ([userActivity webpageURL] != nil) {
[dict setObject:[[userActivity webpageURL] absoluteString] forKey:@"webpageURL"];
}

if ([userActivity userInfo] != nil) {
[dict setObject:[userActivity userInfo] forKey:@"userInfo"];
}

// Update launchOptions so that we send only expected values rather than NSUserActivity
[launchOptions setObject:@{ @"UIApplicationLaunchOptionsUserActivityKey" : dict }
forKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];
}

// Map background location key
if (launchedLocation != nil) {
[launchOptions setObject:launchedLocation forKey:@"launchOptionsLocationKey"];
[launchOptions removeObjectForKey:UIApplicationLaunchOptionsLocationKey];
}

// Map local notification
if (_localNotification != nil) {
localNotification = [[[self class] dictionaryWithLocalNotification:_localNotification] retain];
[launchOptions removeObjectForKey:UIApplicationLaunchOptionsLocalNotificationKey];

// Queue the "localnotificationaction" event for iOS 9 and lower.
// For iOS 10+, the "userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler" delegate handles it
if ([TiUtils isIOSVersionLower:@"9.0"]) {
[self tryToPostNotification:localNotification withNotificationName:kTiLocalNotificationAction completionHandler:nil];
}
}

// Map launched URL
if (urlOptions != nil) {
[launchOptions setObject:[urlOptions absoluteString] forKey:@"url"];
[launchOptions removeObjectForKey:UIApplicationLaunchOptionsURLKey];
}

// Map launched App-ID
if (sourceBundleId != nil) {
[launchOptions setObject:sourceBundleId forKey:@"source"];
[launchOptions removeObjectForKey:UIApplicationLaunchOptionsSourceApplicationKey];
}

// Generate remote notification of available
if (_remoteNotification != nil) {
[self generateNotification:_remoteNotification];
}
if (shortcut != nil) {
launchedShortcutItem = [shortcut retain];
}

// Queue selector for usage in modules / Hyperloop
[self tryToInvokeSelector:@selector(application:didFinishLaunchingWithOptions:)
withArguments:[NSOrderedSet orderedSetWithObjects:application, launchOptions_, nil]];

// If a "application-launch-url" is set, launch it directly
[self launchToUrl];

return YES;
}

Expand Down Expand Up @@ -445,31 +349,6 @@ - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDiction
return YES;
}

// Handle URL-schemes / iOS < 9
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
[self tryToInvokeSelector:@selector(application:sourceApplication:annotation:)
withArguments:[NSOrderedSet orderedSetWithObjects:application, sourceApplication, annotation, nil]];

[launchOptions removeObjectForKey:UIApplicationLaunchOptionsURLKey];
[launchOptions setObject:[url absoluteString] forKey:@"url"];
[launchOptions removeObjectForKey:UIApplicationLaunchOptionsSourceApplicationKey];

if (sourceApplication != nil) {
[launchOptions setObject:sourceApplication forKey:@"source"];
} else {
[launchOptions removeObjectForKey:@"source"];
}

if (appBooted) {
[[NSNotificationCenter defaultCenter] postNotificationName:kTiApplicationLaunchedFromURL object:self userInfo:launchOptions];
} else {
[[self queuedBootEvents] setObject:launchOptions forKey:kTiApplicationLaunchedFromURL];
}

return YES;
}

#pragma mark Background Fetch

#ifdef USE_TI_FETCH
Expand Down Expand Up @@ -1024,10 +903,10 @@ - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
[Webcolor flushCache];
}

- (void)applicationWillResignActive:(UIApplication *)application
- (void)sceneWillResignActive:(UIScene *)scene
{
[self tryToInvokeSelector:@selector(applicationWillResignActive:)
withArguments:[NSOrderedSet orderedSetWithObject:application]];
[self tryToInvokeSelector:@selector(sceneWillResignActive:)
withArguments:[NSOrderedSet orderedSetWithObject:scene]];

if ([self forceSplashAsSnapshot]) {
[window addSubview:[self splashScreenView]];
Expand All @@ -1039,13 +918,11 @@ - (void)applicationWillResignActive:(UIApplication *)application
[kjsBridge gc];
}

- (void)applicationDidBecomeActive:(UIApplication *)application
- (void)sceneDidBecomeActive:(UIScene *)scene
{
[self tryToInvokeSelector:@selector(applicationDidBecomeActive:)
withArguments:[NSOrderedSet orderedSetWithObject:application]];
[self tryToInvokeSelector:@selector(sceneDidBecomeActive:)
withArguments:[NSOrderedSet orderedSetWithObject:scene]];

// We should think about placing this inside "applicationWillBecomeActive" instead to make
// the UI re-useable again more quickly
if ([self forceSplashAsSnapshot] && splashScreenView != nil) {
[[self splashScreenView] removeFromSuperview];
RELEASE_TO_NIL(splashScreenView);
Expand All @@ -1059,10 +936,10 @@ - (void)applicationDidBecomeActive:(UIApplication *)application
[[ImageLoader sharedLoader] resume];
}

- (void)applicationDidEnterBackground:(UIApplication *)application
- (void)sceneDidEnterBackground:(UIScene *)scene
{
[self tryToInvokeSelector:@selector(applicationDidEnterBackground:)
withArguments:[NSOrderedSet orderedSetWithObject:application]];
[self tryToInvokeSelector:@selector(sceneDidEnterBackground:)
withArguments:[NSOrderedSet orderedSetWithObject:scene]];

[[NSNotificationCenter defaultCenter] postNotificationName:kTiPausedNotification object:self];

Expand Down Expand Up @@ -1091,10 +968,10 @@ - (void)applicationDidEnterBackground:(UIApplication *)application
});
}

- (void)applicationWillEnterForeground:(UIApplication *)application
- (void)sceneWillEnterForeground:(UIScene *)scene
{
[self tryToInvokeSelector:@selector(applicationWillEnterForeground:)
withArguments:[NSOrderedSet orderedSetWithObject:application]];
[self tryToInvokeSelector:@selector(sceneWillEnterForeground:)
withArguments:[NSOrderedSet orderedSetWithObject:scene]];

[self flushCompletionHandlerQueue];
[sessionId release];
Expand Down Expand Up @@ -1230,6 +1107,79 @@ - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session op
// Initialize the root-window
window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene];

// Initialize the launch options to be used by the client
launchOptions = [[NSMutableDictionary alloc] init];

// If we have a APNS-UUID, assign it
NSString *apnsUUID = [[NSUserDefaults standardUserDefaults] stringForKey:@"APNSRemoteDeviceUUID"];
if (apnsUUID != nil) {
remoteDeviceUUID = [apnsUUID copy];
}

[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];

// Get some launch options to validate before finish launching. Some of them
// need to be mapepd from native to JS-types to be used by the client
NSURL *urlOptions = connectionOptions.URLContexts.allObjects.firstObject.URL;
NSString *sourceBundleId = connectionOptions.sourceApplication;
UNNotificationResponse *notification = connectionOptions.notificationResponse;
UIApplicationShortcutItem *shortcut = connectionOptions.shortcutItem;

// Map user activity if exists
NSUserActivity *userActivity = connectionOptions.userActivities.allObjects.firstObject;
if (userActivity != nil) {
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:@{ @"activityType" : [userActivity activityType] }];

if ([TiUtils isIOSVersionOrGreater:@"9.0"] && [[userActivity activityType] isEqualToString:CSSearchableItemActionType]) {
if ([userActivity userInfo] != nil) {
[dict setObject:[[userActivity userInfo] objectForKey:CSSearchableItemActivityIdentifier] forKey:@"searchableItemActivityIdentifier"];
}
}

if ([userActivity title] != nil) {
[dict setObject:[userActivity title] forKey:@"title"];
}

if ([userActivity webpageURL] != nil) {
[dict setObject:[[userActivity webpageURL] absoluteString] forKey:@"webpageURL"];
}

if ([userActivity userInfo] != nil) {
[dict setObject:[userActivity userInfo] forKey:@"userInfo"];
}

// Update launchOptions so that we send only expected values rather than NSUserActivity
[launchOptions setObject:@{ @"UIApplicationLaunchOptionsUserActivityKey" : dict }
forKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];
}

// Map launched URL
if (urlOptions != nil) {
[launchOptions setObject:[urlOptions absoluteString] forKey:@"url"];
}

// Map launched App-ID
if (sourceBundleId != nil) {
[launchOptions setObject:sourceBundleId forKey:@"source"];
}

// Generate remote notification if available
if (notification != nil && [notification.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[self generateNotification:@{ @"aps" : notification.notification.request.content.userInfo }];
}

// Save shortcut item for later
if (shortcut != nil) {
launchedShortcutItem = [shortcut retain];
}

// Queue selector for usage in modules / Hyperloop
[self tryToInvokeSelector:@selector(scene:willConnectToSession:options:)
withArguments:[NSOrderedSet orderedSetWithObjects:scene, connectionOptions, nil]];

// If a "application-launch-url" is set, launch it directly
[self launchToUrl];

// Initialize the root-controller
[self initController];

Expand Down
Loading