Skip to content

Commit 2dc9827

Browse files
author
vakrilov
committed
FIX: Wrong isBackNavigation value
1 parent 6997f14 commit 2dc9827

File tree

3 files changed

+81
-10
lines changed

3 files changed

+81
-10
lines changed

tests/app/navigation/navigation-tests.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,4 +382,50 @@ export function test_NavigationEvents_WithBackstackVisibile_False_Forward_Forwar
382382
export function test_NavigationEvents_WithBackstackVisibile_False_Forward_Forward_WithTransition() {
383383
androidGC();
384384
_test_NavigationEvents_WithBackstackVisibile_False_Forward_Forward({ name: "fade" });
385+
}
386+
387+
function _test_NavigationEvents_WithClearHistory(transition?: NavigationTransition) {
388+
const topmost = topmostFrame();
389+
const mainTestPage = topmost.currentPage;
390+
391+
mainTestPage.id = "main-page";
392+
let actualMainPageEvents = new Array<string>();
393+
attachEventListeners(mainTestPage, actualMainPageEvents);
394+
395+
let actualSecondPageEvents = new Array<string>();
396+
const secondPage = new Page();
397+
let secondPageFactory = function (): Page {
398+
secondPage.actionBarHidden = true;
399+
secondPage.id = "second-page";
400+
attachEventListeners(secondPage, actualSecondPageEvents);
401+
secondPage.style.backgroundColor = new Color(255, Math.round(Math.random() * 255), Math.round(Math.random() * 255), Math.round(Math.random() * 255));
402+
return secondPage;
403+
};
404+
405+
// Go to second page
406+
helper.navigateWithEntry({ create: secondPageFactory, transition: transition, animated: true, clearHistory: true });
407+
408+
let expectedMainPageEvents = [
409+
"main-page navigatingFrom forward",
410+
"main-page navigatedFrom forward"
411+
];
412+
TKUnit.arrayAssert(actualMainPageEvents, expectedMainPageEvents, "Actual main-page events are different from expected.");
413+
414+
let expectedSecondPageEvents = [
415+
"second-page navigatingTo forward",
416+
"second-page navigatedTo forward",
417+
];
418+
TKUnit.arrayAssert(actualSecondPageEvents, expectedSecondPageEvents, "Actual main-page events are different from expected.");
419+
420+
TKUnit.assertEqual(topmost.currentPage, secondPage, "We should be on the second page at the end of the test.");
421+
}
422+
423+
export function test_NavigationEvents_WithClearHistory() {
424+
androidGC();
425+
_test_NavigationEvents_WithClearHistory();
426+
}
427+
428+
export function test_NavigationEvents_WithClearHistory_WithTransition() {
429+
androidGC();
430+
_test_NavigationEvents_WithClearHistory({ name: "fade" });
385431
}

tns-core-modules/ui/frame/frame.ios.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,13 @@ export class Frame extends frameCommon.Frame {
125125
viewController.navigationItem.hidesBackButton = true;
126126
let newControllers = NSMutableArray.alloc().initWithCapacity(1);
127127
newControllers.addObject(viewController);
128+
129+
// Mark all previous ViewControllers as cleared
130+
const oldControllers = this._ios.controller.viewControllers;
131+
for (let i = 0; i < oldControllers.count; i++) {
132+
oldControllers.objectAtIndex(i).isBackstackCleared = true;
133+
}
134+
128135
this._ios.controller.setViewControllersAnimated(newControllers, animated);
129136
if (trace.enabled) {
130137
trace.write(`${this}.setViewControllersAnimated([${viewController}], ${animated}); depth = ${navDepth}`, trace.categories.Navigation);

tns-core-modules/ui/page/page.ios.ts

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import {device} from "platform";
77
import {DeviceType} from "ui/enums";
88

99
global.moduleMerge(pageCommon, exports);
10-
var ENTRY = "_entry";
11-
var DELEGATE = "_delegate";
10+
const ENTRY = "_entry";
11+
const DELEGATE = "_delegate";
1212

13-
function isBackNavigation(page: Page, entry): boolean {
13+
function isBackNavigationTo(page: Page, entry): boolean {
1414
let frame = page.frame;
1515
if (!frame) {
1616
return false;
@@ -21,7 +21,7 @@ function isBackNavigation(page: Page, entry): boolean {
2121
}
2222
else {
2323
let navigationQueue = (<any>frame)._navigationQueue;
24-
for (var i = 0; i < navigationQueue.length; i++) {
24+
for (let i = 0; i < navigationQueue.length; i++) {
2525
if (navigationQueue[i].entry === entry) {
2626
return navigationQueue[i].isBackNavigation;
2727
}
@@ -31,11 +31,29 @@ function isBackNavigation(page: Page, entry): boolean {
3131
return false;
3232
}
3333

34+
function isBackNavigationFrom(controller: UIViewControllerImpl, page: Page): boolean {
35+
if (!page.frame) {
36+
return false;
37+
}
38+
39+
// Controller is cleared or backstack skipped
40+
if (controller.isBackstackCleared || controller.isBackstackSkipped) {
41+
return false;
42+
}
43+
44+
if (controller.navigationController && controller.navigationController.viewControllers.containsObject(controller)) {
45+
return false;
46+
}
47+
48+
return true;
49+
}
50+
3451
class UIViewControllerImpl extends UIViewController {
3552

3653
private _owner: WeakRef<Page>;
3754

3855
public isBackstackSkipped: boolean;
56+
public isBackstackCleared: boolean;
3957

4058
public static initWithOwner(owner: WeakRef<Page>): UIViewControllerImpl {
4159
let controller = <UIViewControllerImpl>UIViewControllerImpl.new();
@@ -130,7 +148,7 @@ class UIViewControllerImpl extends UIViewController {
130148

131149
// Don't raise event if currentPage was showing modal page.
132150
if (!page._presentedViewController && newEntry && (!frame || frame.currentPage !== page)) {
133-
let isBack = isBackNavigation(page, newEntry)
151+
let isBack = isBackNavigationTo(page, newEntry);
134152
page.onNavigatingTo(newEntry.entry.context, isBack, newEntry.entry.bindingContext);
135153
}
136154

@@ -179,7 +197,7 @@ class UIViewControllerImpl extends UIViewController {
179197
// Skip navigation events if modal page is shown.
180198
if (!page._presentedViewController && frame) {
181199
let newEntry = this[ENTRY];
182-
let isBack = isBackNavigation(page, newEntry);
200+
let isBack = isBackNavigationTo(page, newEntry);
183201
// We are on the current page which happens when navigation is canceled so isBack should be false.
184202
if (frame.currentPage === page && frame._navigationQueue.length === 0) {
185203
isBack = false;
@@ -224,10 +242,10 @@ class UIViewControllerImpl extends UIViewController {
224242
page._presentedViewController = this.presentedViewController;
225243
}
226244

227-
var frame = page.frame;
245+
const frame = page.frame;
228246
// Skip navigation events if we are hiding because we are about to show modal page.
229247
if (!page._presentedViewController && frame && frame.currentPage === page) {
230-
let isBack = page.frame && (!this.navigationController || !this.navigationController.viewControllers.containsObject(this)) && !this.isBackstackSkipped;
248+
let isBack = isBackNavigationFrom(this, page);
231249
page.onNavigatingFrom(isBack);
232250
}
233251

@@ -267,7 +285,7 @@ class UIViewControllerImpl extends UIViewController {
267285

268286
// Remove from parent if page was in frame and we navigated back.
269287
// Showing page modally will not pass isBack check so currentPage won't be removed from Frame.
270-
let isBack = frame && (!this.navigationController || !this.navigationController.viewControllers.containsObject(this)) && !this.isBackstackSkipped;
288+
let isBack = isBackNavigationFrom(this, page);
271289
if (isBack) {
272290
// Remove parent when navigating back.
273291
frame._removeView(page);
@@ -398,7 +416,7 @@ export class Page extends pageCommon.Page {
398416
}
399417

400418
public _updateActionBar(hidden: boolean) {
401-
var frame = this.frame;
419+
const frame = this.frame;
402420
if (frame) {
403421
frame._updateActionBar(this);
404422
}

0 commit comments

Comments
 (0)