Skip to content

Commit

Permalink
feat(ios): return Promise from Ti.UI.Window.open()/close()
Browse files Browse the repository at this point in the history
  • Loading branch information
sgtcoolguy committed Feb 8, 2021
1 parent 91d0564 commit 5fa6258
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2013 by Appcelerator, Inc. All Rights Reserved.
* Copyright (c) 2013-Present by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/

#import "TiViewProxy.h"
#import <Foundation/Foundation.h>

@class KrollPromise;

/**
Protocol for orientation controller.
*/
Expand All @@ -24,8 +26,8 @@
*/
@protocol TiWindowProtocol <TiOrientationController>

- (void)open:(id)args;
- (void)close:(id)args;
- (KrollPromise *)open:(id)args;
- (KrollPromise *)close:(id)args;
- (BOOL)_handleOpen:(id)args;
- (BOOL)_handleClose:(id)args;
- (BOOL)opening;
Expand Down
6 changes: 5 additions & 1 deletion iphone/TitaniumKit/TitaniumKit/Sources/API/TiWindowProxy.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2009-2013 by Appcelerator, Inc. All Rights Reserved.
* Copyright (c) 2009-2021 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
Expand All @@ -10,6 +10,8 @@

#import "TiUIiOSTransitionAnimationProxy.h"

@class KrollPromise;

@interface TiWindowProxy : TiViewProxy <TiWindowProtocol, TiAnimationDelegate> {
@protected
TiViewController *controller;
Expand All @@ -28,6 +30,8 @@
TiAnimation *closeAnimation;
UIView *animatedOver;
TiUIiOSTransitionAnimationProxy *transitionProxy;
KrollPromise *openPromise;
KrollPromise *closePromise;
}

@property (nonatomic, readwrite, assign) TiViewProxy<TiTab> *tab;
Expand Down
70 changes: 53 additions & 17 deletions iphone/TitaniumKit/TitaniumKit/Sources/API/TiWindowProxy.m
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2009-2014 by Appcelerator, Inc. All Rights Reserved.
* Copyright (c) 2009-2021 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/

#import "TiWindowProxy.h"
#import "KrollPromise.h"
#import "TiApp.h"
#import "TiErrorController.h"
#import "TiUIWindow.h"
Expand Down Expand Up @@ -37,6 +38,9 @@ - (void)dealloc
RELEASE_TO_NIL(transitionProxy)
}

RELEASE_TO_NIL(openPromise);
RELEASE_TO_NIL(closePromise);

[super dealloc];
}

Expand Down Expand Up @@ -113,6 +117,10 @@ - (void)windowDidOpen
if ([self _hasListeners:@"open"]) {
[self fireEvent:@"open" withObject:nil withSource:self propagate:NO reportSuccess:NO errorCode:0 message:nil];
}
if (openPromise != nil) {
[openPromise resolve:@[]];
RELEASE_TO_NIL(openPromise);
}
if (focussed) {
[self fireFocusEvent];
}
Expand Down Expand Up @@ -140,6 +148,10 @@ - (void)windowDidClose
if ([self _hasListeners:@"close"]) {
[self fireEvent:@"close" withObject:nil withSource:self propagate:NO reportSuccess:NO errorCode:0 message:nil];
}
if (closePromise != nil) {
[closePromise resolve:@[]];
RELEASE_TO_NIL(closePromise);
}
[self forgetProxy:closeAnimation];
RELEASE_TO_NIL(closeAnimation);
if (tab == nil && !self.isManaged) {
Expand Down Expand Up @@ -202,32 +214,39 @@ - (BOOL)isRootViewAttached
}

#pragma mark - TiWindowProtocol Base Methods
- (void)open:(id)args
- (KrollPromise *)open:(id)args
{
//If an error is up, Go away
JSContext *context = [self currentContext];

// If an error is up, Go away
if ([[[[TiApp app] controller] topPresentedController] isKindOfClass:[TiErrorNavigationController class]]) {
DebugLog(@"[ERROR] ErrorController is up. ABORTING open");
return;
return [KrollPromise rejectedWithErrorMessage:@"ErrorController is up. ABORTING open" inContext:context];
}

//I am already open or will be soon. Go Away
// I am already open or will be soon. Go Away
if (opening || opened) {
return;
return [KrollPromise rejectedWithErrorMessage:@"Window is already opened or opening." inContext:context];
}

//Lets keep ourselves safe
// Lets keep ourselves safe
[self rememberSelf];

// Don't recreate if we're calling ourselves again because root view is not loaded/attached!
if (openPromise == nil) {
openPromise = [[KrollPromise alloc] initInContext:context];

This comment has been minimized.

Copy link
@hansemannn

hansemannn Mar 15, 2021

Collaborator

@sgtcoolguy Regarding TIMOB-28394, this would be my top-candidate to cause the issue, because it:

  • only lags the first time (speaks for the reusability of the object)
  • is the only operation that could glitch off the main thread / consume some memory
}

//Make sure our RootView Controller is attached
if (![self isRootViewLoaded]) {
DebugLog(@"[WARN] ROOT VIEW NOT LOADED. WAITING");
[self performSelector:@selector(open:) withObject:args afterDelay:0.1];
return;
return openPromise;
}
if (![self isRootViewAttached]) {
DebugLog(@"[WARN] ROOT VIEW NOT ATTACHED. WAITING");
[self performSelector:@selector(open:) withObject:args afterDelay:0.1];
return;
return openPromise;
}

opening = YES;
Expand Down Expand Up @@ -262,6 +281,7 @@ - (void)open:(id)args
[self openOnUIThread:args];
},
NO);
return openPromise;
}

- (void)setStatusBarStyle:(id)style
Expand All @@ -278,23 +298,26 @@ - (void)setStatusBarStyle:(id)style
}
}

- (void)close:(id)args
- (KrollPromise *)close:(id)args
{
JSContext *context = [self currentContext];

if (!opened) {
// If I've been asked to open but haven't yet, short-circuit it and tell it not to open
if (opening) {
opening = NO; // _handleOpen: should check this and abort opening
DebugLog(@"Window is not open yet. Attempting to stop it from opening...");
return;
// Should we reject or resolve here?! This feels more like "success", so maybe resolve? or do we have to wait on the end result of the openPromise to know?
return [KrollPromise resolved:@[] inContext:context];
}

DebugLog(@"Window is not open. Ignoring this close call");
return;
return [KrollPromise rejectedWithErrorMessage:@"Window is not open. Ignoring this close call" inContext:context];
}

if (closing) {
DebugLog(@"Window is already closing. Ignoring this close call.");
return;
return [KrollPromise rejectedWithErrorMessage:@"Window is already closing. Ignoring this close call." inContext:context];
}

if (tab != nil) {
Expand All @@ -303,22 +326,26 @@ - (void)close:(id)args
} else {
args = [NSArray arrayWithObject:self];
}
[tab closeWindow:args];
return;
return [tab closeWindow:args];
}

if (closePromise == nil) {
closePromise = [[KrollPromise alloc] initInContext:context];
}

closing = YES;

//TODO Argument Processing
// TODO: Argument Processing
closeAnimation = [[TiAnimation animationFromArg:args context:[self pageContext] create:NO] retain];
[self rememberProxy:closeAnimation];

//GO ahead and call close on UI thread
// GO ahead and call close on UI thread
TiThreadPerformOnMainThread(
^{
[self closeOnUIThread:args];
},
NO);
return closePromise;
}

- (NSNumber *)closed
Expand Down Expand Up @@ -595,6 +622,11 @@ - (void)openOnUIThread:(NSArray *)args
opened = NO;
[self forgetProxy:openAnimation];
RELEASE_TO_NIL(openAnimation);
// reject the openPromise!
if (openPromise != nil) {
[openPromise rejectWithErrorMessage:@"open aborted"];
RELEASE_TO_NIL(openPromise);
}
}
}

Expand All @@ -619,6 +651,10 @@ - (void)closeOnUIThread:(NSArray *)args
DebugLog(@"[WARN] CLOSE ABORTED. _handleClose returned NO");
closing = NO;
RELEASE_TO_NIL(closeAnimation);
if (closePromise != nil) {
[closePromise rejectWithErrorMessage:@"close aborted"];
RELEASE_TO_NIL(closePromise);
}
}
}

Expand Down

0 comments on commit 5fa6258

Please sign in to comment.