Merge pull request #7293 from NativeScript/mdonev/hmr-multliple-fix

fix(hmr): support for multi module replacement
This commit is contained in:
Svetoslav
2019-06-05 20:19:59 +03:00
committed by GitHub
8 changed files with 142 additions and 94 deletions

View File

@ -0,0 +1,3 @@
Button {
color: cyan;
}

View File

@ -5,7 +5,6 @@ import * as app from "tns-core-modules/application/application";
import * as frame from "tns-core-modules/ui/frame"; import * as frame from "tns-core-modules/ui/frame";
import { Color } from "tns-core-modules/color"; import { Color } from "tns-core-modules/color";
import { isAndroid } from "tns-core-modules/platform";
import { createViewFromEntry } from "tns-core-modules/ui/builder"; import { createViewFromEntry } from "tns-core-modules/ui/builder";
import { Page } from "tns-core-modules/ui/page"; import { Page } from "tns-core-modules/ui/page";
import { Frame } from "tns-core-modules/ui/frame"; import { Frame } from "tns-core-modules/ui/frame";
@ -20,6 +19,7 @@ const buttonHtmlPageFileName = "./livesync/livesync-button-page.html";
const buttonXmlPageFileName = "./livesync/livesync-button-page.xml"; const buttonXmlPageFileName = "./livesync/livesync-button-page.xml";
const buttonJsPageFileName = "./livesync/livesync-button-page.js"; const buttonJsPageFileName = "./livesync/livesync-button-page.js";
const buttonTsPageFileName = "./livesync/livesync-button-page.ts"; const buttonTsPageFileName = "./livesync/livesync-button-page.ts";
const buttonScssPageFileName = "./livesync/livesync-button-page.scss";
const labelPageModuleName = "livesync/livesync-label-page"; const labelPageModuleName = "livesync/livesync-label-page";
const green = new Color("green"); const green = new Color("green");
@ -60,6 +60,36 @@ export function test_onLiveSync_ModuleContext_Markup_XmlFile() {
_test_onLiveSync_ModuleReplace({ type: "markup", path: buttonXmlPageFileName }); _test_onLiveSync_ModuleReplace({ type: "markup", path: buttonXmlPageFileName });
} }
export function test_onLiveSync_ModuleContext_Markup_Script_XmlFile() {
_test_onLiveSync_ModuleReplace_Multiple([
{ type: "script", path: buttonTsPageFileName },
{ type: "markup", path: buttonXmlPageFileName }
]);
}
export function test_onLiveSync_ModuleContext_Markup_Script_Style_XmlFile() {
_test_onLiveSync_ModuleReplace_Multiple([
{ type: "script", path: buttonTsPageFileName },
{ type: "markup", path: buttonXmlPageFileName },
{ type: "style", path: buttonScssPageFileName }
]);
}
export function test_onLiveSync_ModuleContext_Markup_Script_HtmlFile() {
_test_onLiveSync_ModuleReplace_Multiple([
{ type: "script", path: buttonTsPageFileName },
{ type: "markup", path: buttonHtmlPageFileName }
]);
}
export function test_onLiveSync_ModuleContext_Markup_Script_Style_HtmlFile() {
_test_onLiveSync_ModuleReplace_Multiple([
{ type: "script", path: buttonTsPageFileName },
{ type: "markup", path: buttonHtmlPageFileName },
{ type: "style", path: buttonScssPageFileName }
]);
}
export function setUp() { export function setUp() {
const labelPage = <Page>createViewFromEntry(({ moduleName: labelPageModuleName })); const labelPage = <Page>createViewFromEntry(({ moduleName: labelPageModuleName }));
helper.navigate(() => labelPage); helper.navigate(() => labelPage);
@ -121,6 +151,28 @@ function _test_onLiveSync_ModuleReplace(context: { type, path }) {
TKUnit.assertEqual(pageBeforeNavigation, pageAfterBackNavigation, "Pages are different!"); TKUnit.assertEqual(pageBeforeNavigation, pageAfterBackNavigation, "Pages are different!");
} }
function _test_onLiveSync_ModuleReplace_Multiple(context: { type: string, path: string }[]) {
const pageBeforeNavigation = helper.getCurrentPage();
const buttonPage = <Page>createViewFromEntry(({ moduleName: buttonPageModuleName }));
helper.navigateWithHistory(() => buttonPage);
context.forEach(item => {
global.__onLiveSync(item);
});
const topmostFrame = frame.topmost();
waitUntilLivesyncComplete(topmostFrame);
TKUnit.assertTrue(topmostFrame.currentPage.getViewById("button").isLoaded, "Button page is NOT loaded!");
TKUnit.assertEqual(topmostFrame.backStack.length, 1, "Backstack is clean!");
TKUnit.assertTrue(topmostFrame.canGoBack(), "Can NOT go back!");
helper.goBack();
const pageAfterBackNavigation = helper.getCurrentPage();
TKUnit.assertTrue(topmostFrame.currentPage.getViewById("label").isLoaded, "Label page is NOT loaded!");
TKUnit.assertEqual(topmostFrame.backStack.length, 0, "Backstack is NOT clean!");
TKUnit.assertEqual(pageBeforeNavigation, pageAfterBackNavigation, "Pages are different!");
}
function _test_onLiveSync_ModuleContext_TypeStyle(context: { type, path }) { function _test_onLiveSync_ModuleContext_TypeStyle(context: { type, path }) {
const pageBeforeNavigation = helper.getCurrentPage(); const pageBeforeNavigation = helper.getCurrentPage();
const buttonPage = <Page>createViewFromEntry(({ moduleName: buttonPageModuleName })); const buttonPage = <Page>createViewFromEntry(({ moduleName: buttonPageModuleName }));
@ -146,5 +198,5 @@ function _test_onLiveSync_ModuleContext_TypeStyle(context: { type, path }) {
} }
function waitUntilLivesyncComplete(frame: Frame) { function waitUntilLivesyncComplete(frame: Frame) {
TKUnit.waitUntilReady(() => frame._executingEntry === null); TKUnit.waitUntilReady(() => frame.navigationQueueIsEmpty());
} }

View File

@ -724,6 +724,7 @@ function transitionOrAnimationCompleted(entry: ExpandedEntry): void {
entries.delete(entry); entries.delete(entry);
if (entries.size === 0) { if (entries.size === 0) {
const frame = entry.resolvedPage.frame; const frame = entry.resolvedPage.frame;
// We have 0 or 1 entry per frameId in completedEntries // We have 0 or 1 entry per frameId in completedEntries
// So there is no need to make it to Set like waitingQueue // So there is no need to make it to Set like waitingQueue
const previousCompletedAnimationEntry = completedEntries.get(frameId); const previousCompletedAnimationEntry = completedEntries.get(frameId);
@ -734,9 +735,8 @@ function transitionOrAnimationCompleted(entry: ExpandedEntry): void {
current = current || entry; current = current || entry;
// Will be null if Frame is shown modally... // Will be null if Frame is shown modally...
// transitionOrAnimationCompleted fires again (probably bug in android). // transitionOrAnimationCompleted fires again (probably bug in android).
if (current) { if (current && frame._executingContext) {
const navType = frame.navigationType; setTimeout(() => frame.setCurrent(current, frame._executingContext.navigationType));
setTimeout(() => frame.setCurrent(current, navType));
} }
} else { } else {
completedEntries.set(frameId, entry); completedEntries.set(frameId, entry);

View File

@ -37,7 +37,9 @@ function buildEntryFromArgs(arg: any): NavigationEntry {
export interface NavigationContext { export interface NavigationContext {
entry: BackstackEntry; entry: BackstackEntry;
// TODO: remove isBackNavigation for NativeScript 6.0
isBackNavigation: boolean; isBackNavigation: boolean;
navigationType: NavigationType
} }
@CSSType("Frame") @CSSType("Frame")
@ -51,11 +53,10 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
public actionBarVisibility: "auto" | "never" | "always"; public actionBarVisibility: "auto" | "never" | "always";
public _currentEntry: BackstackEntry; public _currentEntry: BackstackEntry;
public _executingEntry: BackstackEntry; public _executingContext: NavigationContext;
public _isInFrameStack = false; public _isInFrameStack = false;
public static defaultAnimatedNavigation = true; public static defaultAnimatedNavigation = true;
public static defaultTransition: NavigationTransition; public static defaultTransition: NavigationTransition;
public navigationType: NavigationType;
// TODO: Currently our navigation will not be synchronized in case users directly call native navigation methods like Activity.startActivity. // TODO: Currently our navigation will not be synchronized in case users directly call native navigation methods like Activity.startActivity.
@ -75,7 +76,8 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
let previousForwardNotInBackstack = false; let previousForwardNotInBackstack = false;
this._navigationQueue.forEach(item => { this._navigationQueue.forEach(item => {
const entry = item.entry; const entry = item.entry;
if (item.isBackNavigation) { const isBackNavigation = item.navigationType === NavigationType.back;
if (isBackNavigation) {
previousForwardNotInBackstack = false; previousForwardNotInBackstack = false;
if (!entry) { if (!entry) {
backstack--; backstack--;
@ -135,7 +137,8 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
const navigationContext: NavigationContext = { const navigationContext: NavigationContext = {
entry: backstackEntry, entry: backstackEntry,
isBackNavigation: true isBackNavigation: true,
navigationType: NavigationType.back
} }
this._navigationQueue.push(navigationContext); this._navigationQueue.push(navigationContext);
@ -203,7 +206,8 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
const navigationContext: NavigationContext = { const navigationContext: NavigationContext = {
entry: backstackEntry, entry: backstackEntry,
isBackNavigation: false isBackNavigation: false,
navigationType: NavigationType.forward
} }
this._navigationQueue.push(navigationContext); this._navigationQueue.push(navigationContext);
@ -232,10 +236,10 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
newPage.onNavigatedTo(isBack); newPage.onNavigatedTo(isBack);
// Reset executing entry after NavigatedTo is raised; // Reset executing context after NavigatedTo is raised;
// we do not want to execute two navigations in parallel in case // we do not want to execute two navigations in parallel in case
// additional navigation is triggered from the NavigatedTo handler. // additional navigation is triggered from the NavigatedTo handler.
this._executingEntry = null; this._executingContext = null;
} }
public _updateBackstack(entry: BackstackEntry, navigationType: NavigationType): void { public _updateBackstack(entry: BackstackEntry, navigationType: NavigationType): void {
@ -342,13 +346,14 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
} }
protected _processNextNavigationEntry() { protected _processNextNavigationEntry() {
if (!this.isLoaded || this._executingEntry) { if (!this.isLoaded || this._executingContext) {
return; return;
} }
if (this._navigationQueue.length > 0) { if (this._navigationQueue.length > 0) {
const navigationContext = this._navigationQueue[0]; const navigationContext = this._navigationQueue[0];
if (navigationContext.isBackNavigation) { const isBackNavigation = navigationContext.navigationType === NavigationType.back;
if (isBackNavigation) {
this.performGoBack(navigationContext); this.performGoBack(navigationContext);
} else { } else {
this.performNavigation(navigationContext); this.performNavigation(navigationContext);
@ -358,10 +363,12 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
@profile @profile
public performNavigation(navigationContext: NavigationContext) { public performNavigation(navigationContext: NavigationContext) {
const navContext = navigationContext.entry; this._executingContext = navigationContext;
this._executingEntry = navContext;
this._onNavigatingTo(navContext, navigationContext.isBackNavigation); const backstackEntry = navigationContext.entry;
this._navigateCore(navContext); const isBackNavigation = navigationContext.navigationType === NavigationType.back;
this._onNavigatingTo(backstackEntry, isBackNavigation);
this._navigateCore(backstackEntry);
} }
@profile @profile
@ -373,7 +380,7 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
navigationContext.entry = backstackEntry; navigationContext.entry = backstackEntry;
} }
this._executingEntry = backstackEntry; this._executingContext = navigationContext;
this._onNavigatingTo(backstackEntry, true); this._onNavigatingTo(backstackEntry, true);
this._goBackCore(backstackEntry); this._goBackCore(backstackEntry);
} }
@ -643,9 +650,6 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
} }
protected replacePage(context: ModuleContext): void { protected replacePage(context: ModuleContext): void {
// Set NavigationType.replace for HMR.
// In IOS on `viewDidAppear()` this will be set to NavigationType.forward.
this.navigationType = NavigationType.replace;
const currentBackstackEntry = this._currentEntry; const currentBackstackEntry = this._currentEntry;
const contextModuleName = getModuleName(context.path); const contextModuleName = getModuleName(context.path);
@ -658,10 +662,15 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
frameId: currentBackstackEntry.frameId frameId: currentBackstackEntry.frameId
}; };
const navContext: NavigationContext = { entry: newBackstackEntry, isBackNavigation: false }; const navigationContext: NavigationContext = {
this.performNavigation(navContext); entry: newBackstackEntry,
} isBackNavigation: false,
navigationType: NavigationType.replace
};
this._navigationQueue.push(navigationContext);
this._processNextNavigationEntry();
}
} }
export function getFrameById(id: string): FrameBase { export function getFrameById(id: string): FrameBase {

View File

@ -163,24 +163,12 @@ export class Frame extends FrameBase {
// In this case call _navigateCore in order to recreate the current fragment. // In this case call _navigateCore in order to recreate the current fragment.
// Don't call navigate because it will fire navigation events. // Don't call navigate because it will fire navigation events.
// As JS instances are alive it is already done for the current page. // As JS instances are alive it is already done for the current page.
if (!this.isLoaded || this._executingEntry || !this._attachedToWindow) { if (!this.isLoaded || this._executingContext || !this._attachedToWindow) {
return; return;
} }
const animatedEntries = _getAnimatedEntries(this._android.frameId); const animatedEntries = _getAnimatedEntries(this._android.frameId);
if (animatedEntries) { if (animatedEntries) {
// // recreate UI on the animated fragments because we have new context.
// // We need to recreate the UI because it Frame will do it only for currentPage.
// // Once currentPage is changed due to transition end we will have no UI on the
// // new Page.
// animatedEntries.forEach(entry => {
// const page = entry.resolvedPage;
// if (page._context !== this._context) {
// page._tearDownUI(true);
// page._setupUI(this._context);
// }
// });
// Wait until animations are completed. // Wait until animations are completed.
if (animatedEntries.size > 0) { if (animatedEntries.size > 0) {
return; return;
@ -212,7 +200,13 @@ export class Frame extends FrameBase {
} }
public _getChildFragmentManager() { public _getChildFragmentManager() {
const backstackEntry = this._executingEntry || this._currentEntry; let backstackEntry;
if (this._executingContext && this._executingContext.entry) {
backstackEntry = this._executingContext.entry;
} else {
backstackEntry = this._currentEntry;
}
if (backstackEntry && backstackEntry.fragment && backstackEntry.fragment.isAdded()) { if (backstackEntry && backstackEntry.fragment && backstackEntry.fragment.isAdded()) {
return backstackEntry.fragment.getChildFragmentManager(); return backstackEntry.fragment.getChildFragmentManager();
} }
@ -324,7 +318,7 @@ export class Frame extends FrameBase {
if (navigationType === NavigationType.replace) { if (navigationType === NavigationType.replace) {
_clearEntry(entry); _clearEntry(entry);
const animated = entry.entry.animated; const animated = this._getIsAnimatedNavigation(entry.entry);
const navigationTransition = this._getNavigationTransition(entry.entry); const navigationTransition = this._getNavigationTransition(entry.entry);
const currentEntry = null; const currentEntry = null;
const newEntry = entry; const newEntry = entry;
@ -353,12 +347,6 @@ export class Frame extends FrameBase {
@profile @profile
public _navigateCore(newEntry: BackstackEntry) { public _navigateCore(newEntry: BackstackEntry) {
super._navigateCore(newEntry); super._navigateCore(newEntry);
// NavigationType.replace for HMR.
// Otherwise, default to NavigationType.forward.
const isReplace = this.navigationType === NavigationType.replace;
if (!isReplace) {
this.navigationType = NavigationType.forward;
}
// set frameId here so that we could use it in fragment.transitions // set frameId here so that we could use it in fragment.transitions
newEntry.frameId = this._android.frameId; newEntry.frameId = this._android.frameId;
@ -385,6 +373,7 @@ export class Frame extends FrameBase {
navDepth = -1; navDepth = -1;
} }
const isReplace = this._executingContext && this._executingContext.navigationType === NavigationType.replace;
if (!isReplace) { if (!isReplace) {
navDepth++; navDepth++;
} }
@ -419,7 +408,6 @@ export class Frame extends FrameBase {
} }
public _goBackCore(backstackEntry: BackstackEntry) { public _goBackCore(backstackEntry: BackstackEntry) {
this.navigationType = NavigationType.back;
super._goBackCore(backstackEntry); super._goBackCore(backstackEntry);
navDepth = backstackEntry.navDepth; navDepth = backstackEntry.navDepth;
@ -477,18 +465,18 @@ export class Frame extends FrameBase {
const listener = getAttachListener(); const listener = getAttachListener();
this.nativeViewProtected.removeOnAttachStateChangeListener(listener); this.nativeViewProtected.removeOnAttachStateChangeListener(listener);
this.nativeViewProtected[ownerSymbol] = null; this.nativeViewProtected[ownerSymbol] = null;
this._tearDownPending = !!this._executingEntry; this._tearDownPending = !!this._executingContext;
const current = this._currentEntry; const current = this._currentEntry;
const executingEntry = this._executingContext ? this._executingContext.entry : null;
this.backStack.forEach(entry => { this.backStack.forEach(entry => {
// Don't destroy current and executing entries or UI will look blank. // Don't destroy current and executing entries or UI will look blank.
// We will do it in setCurrent. // We will do it in setCurrent.
if (entry !== this._executingEntry) { if (entry !== executingEntry) {
clearEntry(entry); clearEntry(entry);
} }
}); });
if (current && !this._executingEntry) { if (current && !executingEntry) {
clearEntry(current); clearEntry(current);
} }
@ -711,11 +699,11 @@ function findPageForFragment(fragment: android.support.v4.app.Fragment, frame: F
let entry: BackstackEntry; let entry: BackstackEntry;
const current = frame._currentEntry; const current = frame._currentEntry;
const navigating = frame._executingEntry; const executingContext = frame._executingContext;
if (current && current.fragmentTag === fragmentTag) { if (current && current.fragmentTag === fragmentTag) {
entry = current; entry = current;
} else if (navigating && navigating.fragmentTag === fragmentTag) { } else if (executingContext && executingContext.entry && executingContext.entry.fragmentTag === fragmentTag) {
entry = navigating; entry = executingContext.entry;
} }
let page: Page; let page: Page;

View File

@ -135,11 +135,19 @@ export class Frame extends View {
/** /**
* @private * @private
*/ */
_executingEntry: BackstackEntry; _executingContext: NavigationContext;
/** /**
* @private * @private
*/ */
_processNavigationQueue(page: Page); _processNavigationQueue(page: Page);
/**
* @private
*/
_getIsAnimatedNavigation(entry: NavigationEntry): boolean;
/**
* @private
*/
_getNavigationTransition(entry: NavigationEntry): NavigationTransition;
/** /**
* @private * @private
*/ */
@ -173,12 +181,6 @@ export class Frame extends View {
* @private * @private
*/ */
_removeFromFrameStack(); _removeFromFrameStack();
/**
* @private
* Represents the type of navigation.
*/
navigationType: NavigationType;
//@endprivate //@endprivate
/** /**
@ -289,6 +291,7 @@ export interface NavigationEntry extends ViewEntry {
export interface NavigationContext { export interface NavigationContext {
entry: BackstackEntry; entry: BackstackEntry;
isBackNavigation: boolean; isBackNavigation: boolean;
navigationType: NavigationType;
} }
/** /**

View File

@ -65,12 +65,6 @@ export class Frame extends FrameBase {
@profile @profile
public _navigateCore(backstackEntry: BackstackEntry) { public _navigateCore(backstackEntry: BackstackEntry) {
// NavigationType.replace for HMR.
// Otherwise, default to NavigationType.forward.
const isReplace = this.navigationType === NavigationType.replace;
if (!isReplace) {
this.navigationType = NavigationType.forward;
}
super._navigateCore(backstackEntry); super._navigateCore(backstackEntry);
let viewController: UIViewController = backstackEntry.resolvedPage.ios; let viewController: UIViewController = backstackEntry.resolvedPage.ios;
@ -82,6 +76,8 @@ export class Frame extends FrameBase {
if (clearHistory) { if (clearHistory) {
navDepth = -1; navDepth = -1;
} }
const isReplace = this._executingContext && this._executingContext.navigationType === NavigationType.replace;
if (!isReplace) { if (!isReplace) {
navDepth++; navDepth++;
} }
@ -187,7 +183,6 @@ export class Frame extends FrameBase {
} }
public _goBackCore(backstackEntry: BackstackEntry) { public _goBackCore(backstackEntry: BackstackEntry) {
this.navigationType = NavigationType.back;
super._goBackCore(backstackEntry); super._goBackCore(backstackEntry);
navDepth = backstackEntry[NAV_DEPTH]; navDepth = backstackEntry[NAV_DEPTH];

View File

@ -22,18 +22,25 @@ const majorVersion = iosUtils.MajorVersion;
function isBackNavigationTo(page: Page, entry): boolean { function isBackNavigationTo(page: Page, entry): boolean {
const frame = page.frame; const frame = page.frame;
if (!frame || frame.navigationType === NavigationType.replace) { if (!frame) {
return false;
}
// if executing context is null here this most probably means back navigation through iOS back button
const navigationContext = frame._executingContext || { navigationType: NavigationType.back };
const isReplace = navigationContext.navigationType === NavigationType.replace;
if (isReplace) {
return false; return false;
} }
if (frame.navigationQueueIsEmpty()) { if (frame.navigationQueueIsEmpty()) {
return true; return true;
} else { }
const navigationQueue = (<any>frame)._navigationQueue;
for (let i = 0; i < navigationQueue.length; i++) { const navigationQueue = (<any>frame)._navigationQueue;
if (navigationQueue[i].entry === entry) { for (let i = 0; i < navigationQueue.length; i++) {
return navigationQueue[i].isBackNavigation; if (navigationQueue[i].entry === entry) {
} return navigationQueue[i].navigationType === NavigationType.back;
} }
} }
@ -129,30 +136,23 @@ class UIViewControllerImpl extends UIViewController {
} }
const navigationController = this.navigationController; const navigationController = this.navigationController;
const frame = navigationController ? (<any>navigationController).owner : null; const frame: Frame = navigationController ? (<any>navigationController).owner : null;
// Skip navigation events if modal page is shown. // Skip navigation events if modal page is shown.
if (!owner._presentedViewController && frame) { if (!owner._presentedViewController && frame) {
const newEntry: BackstackEntry = this[ENTRY]; const newEntry: BackstackEntry = this[ENTRY];
let isBack: boolean; // frame.setCurrent(...) will reset executing context so retrieve it here
let navType = frame.navigationType; // if executing context is null here this most probably means back navigation through iOS back button
// We are on the current page which happens when navigation is canceled so isBack should be false. const navigationContext = frame._executingContext || { navigationType: NavigationType.back };
if (navType !== NavigationType.replace && frame.currentPage === owner && frame._navigationQueue.length === 0) { const isReplace = navigationContext.navigationType === NavigationType.replace;
isBack = false;
navType = NavigationType.forward;
} else {
isBack = isBackNavigationTo(owner, newEntry);
if (isBack) {
navType = NavigationType.back;
}
}
frame.setCurrent(newEntry, navType); frame.setCurrent(newEntry, navigationContext.navigationType);
if (frame.navigationType === NavigationType.replace) { if (isReplace) {
let controller = newEntry.resolvedPage.ios; let controller = newEntry.resolvedPage.ios;
if (controller) { if (controller) {
if (newEntry.entry.animated) { const animated = frame._getIsAnimatedNavigation(newEntry.entry);
if (animated) {
controller[TRANSITION] = frame._getNavigationTransition(newEntry.entry); controller[TRANSITION] = frame._getNavigationTransition(newEntry.entry);
} else { } else {
controller[TRANSITION] = { name: NON_ANIMATED_TRANSITION }; controller[TRANSITION] = { name: NON_ANIMATED_TRANSITION };
@ -160,8 +160,6 @@ class UIViewControllerImpl extends UIViewController {
} }
} }
frame.navigationType = isBack ? NavigationType.back : NavigationType.forward;
// If page was shown with custom animation - we need to set the navigationController.delegate to the animatedDelegate. // If page was shown with custom animation - we need to set the navigationController.delegate to the animatedDelegate.
frame.ios.controller.delegate = this[DELEGATE]; frame.ios.controller.delegate = this[DELEGATE];
@ -209,7 +207,7 @@ class UIViewControllerImpl extends UIViewController {
const willSelectViewController = tab && (<any>tab)._willSelectViewController; const willSelectViewController = tab && (<any>tab)._willSelectViewController;
if (!willSelectViewController if (!willSelectViewController
|| willSelectViewController === tab.selectedViewController) { || willSelectViewController === tab.selectedViewController) {
let isBack = isBackNavigationFrom(this, owner); const isBack = isBackNavigationFrom(this, owner);
owner.onNavigatingFrom(isBack); owner.onNavigatingFrom(isBack);
} }
} }