Skip to content

Commit 7c68953

Browse files
author
Hristo Hristov
authored
Fix clear history transition (NativeScript#4951)
* fix: Navigation test app added * Removed native popToBackstack call. Implemented custom fragment save/restore state. When navigating back we reverse manually transitions/animations because we no longer add them to navite backstack. Fragment instance stored on entry. Animation and Transition listeners now holds reference to entry instead of fragment for easier update of fragment. Animation and Transition listeners removed when entry removed from backstack. Animation and Transition removed from fragment when fragment activity is destroyed. * Revert package.json start up entry Fixed bug where goBack took the last element in backstack while navigationQueue is not empty. Fixed bug where goBack to specific entry in the backstack was removing that entry... Removed duplicated method Refactored method name Fixed TS
1 parent 2e09d37 commit 7c68953

File tree

13 files changed

+555
-358
lines changed

13 files changed

+555
-358
lines changed

apps/app/navigation-app/app.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.btn1 {
2+
background-color: lightgreen;
3+
color: coral;
4+
font-size: 20;
5+
font-family: monospace;
6+
}
7+
8+
.btn2 {
9+
background-color: coral;
10+
color: lightgreen;
11+
font-size: 24;
12+
font-family: serif;
13+
}

apps/app/navigation-app/app.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as application from "tns-core-modules/application";
2+
import * as trace from "tns-core-modules/trace";
3+
trace.addCategories(
4+
trace.categories.Transition)
5+
// + "," +
6+
// trace.categories.NativeLifecycle + "," +
7+
// trace.categories.Navigation);
8+
trace.enable();
9+
10+
// Needed only for build infrastructure
11+
application.setCssFileName("navigation-app/app.css");
12+
application.start({ moduleName: "navigation-app/main-page" });
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { EventData } from 'tns-core-modules/data/observable';
2+
import { Page, NavigatedData } from 'tns-core-modules/ui/page';
3+
import { topmost, NavigationEntry } from 'tns-core-modules/ui/frame';
4+
5+
export function nav() {
6+
const e: NavigationEntry = {
7+
moduleName: "navigation-app/main-page"
8+
}
9+
topmost().navigate(e)
10+
}
11+
export function navClearTrans() {
12+
console.log("transition and clear")
13+
14+
const e: NavigationEntry = {
15+
transition: {
16+
name: "slideLeft",
17+
curve: "linear"
18+
},
19+
clearHistory: true,
20+
moduleName: "navigation-app/main-page"
21+
}
22+
topmost().navigate(e)
23+
}
24+
25+
export function navWithTransition() {
26+
const e: NavigationEntry = {
27+
transition: {
28+
name: "slideLeft",
29+
curve: "linear"
30+
},
31+
moduleName: "navigation-app/main-page"
32+
}
33+
topmost().navigate(e)
34+
}
35+
36+
export function navWithClear() {
37+
const e: NavigationEntry = {
38+
clearHistory: true,
39+
moduleName: "navigation-app/main-page"
40+
}
41+
topmost().navigate(e)
42+
}
43+
44+
let i = 0;
45+
const colors = ["lightgreen", "lightblue", "lightcoral"]
46+
47+
export function navigatedFrom(args: NavigatedData) {
48+
console.log(`navigatedFrom ${args.object.toString()} isBack: ${args.isBackNavigation}`)
49+
}
50+
51+
export function navigatedTo(args: NavigatedData) {
52+
console.log(`navigatedTo ${args.object.toString()} isBack: ${args.isBackNavigation}`)
53+
}
54+
55+
export function navigatingTo(args: NavigatedData) {
56+
if (!args.isBackNavigation) {
57+
(<any>args.object).page.backgroundColor = colors[(i++) % 3];
58+
const array = new Array();
59+
for (let i = 0; i < 50; i++) {
60+
array[i] = i;
61+
}
62+
(<any>args.object).page.bindingContext = array;
63+
}
64+
console.log(`navigatingTo ${args.object.toString()} isBack: ${args.isBackNavigation}`)
65+
}
66+
67+
export function navigatingFrom(args: NavigatedData) {
68+
console.log(`navigatingFrom ${args.object.toString()} isBack: ${args.isBackNavigation}`)
69+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
2+
navigatingTo="navigatingTo"
3+
navigatingFrom="navigatingFrom"
4+
navigatedTo="navigatedTo"
5+
navigatedFrom="navigatedFrom">
6+
<StackLayout>
7+
<Button text="Nav" tap="nav" />
8+
<Button text="Clear history Trans" tap="navClearTrans" />
9+
<Button text="Nav Transition" tap="navWithTransition" />
10+
<Button text="Nav Clear" tap="navWithClear" />
11+
<ListView items="{{ $value }}" />
12+
</StackLayout>
13+
</Page>

tests/app/ui/helper.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,16 @@ export function getClearCurrentPage(): Page {
152152
return page;
153153
}
154154

155-
export function waitUntilNavigatedFrom(oldPage: Page) {
155+
export function waitUntilNavigatedFrom(action: Function) {
156+
const currentPage = frame.topmost().currentPage;
156157
let completed = false;
157158
function navigatedFrom(args) {
158159
args.object.page.off("navigatedFrom", navigatedFrom);
159160
completed = true;
160161
}
161162

162-
oldPage.on("navigatedFrom", navigatedFrom);
163+
currentPage.on("navigatedFrom", navigatedFrom);
164+
action();
163165
TKUnit.waitUntilReady(() => completed);
164166
}
165167

@@ -168,22 +170,18 @@ export function waitUntilLayoutReady(view: View): void {
168170
}
169171

170172
export function navigateWithEntry(entry: frame.NavigationEntry): Page {
171-
let page = frame.resolvePageFromEntry(entry);
173+
const page = frame.resolvePageFromEntry(entry);
172174
entry.moduleName = null;
173175
entry.create = function () {
174176
return page;
175177
};
176178

177-
let currentPage = getCurrentPage();
178-
frame.topmost().navigate(entry);
179-
waitUntilNavigatedFrom(currentPage);
179+
waitUntilNavigatedFrom(() => frame.topmost().navigate(entry));
180180
return page;
181181
}
182182

183183
export function goBack() {
184-
let currentPage = getCurrentPage();
185-
frame.topmost().goBack();
186-
waitUntilNavigatedFrom(currentPage);
184+
waitUntilNavigatedFrom(() => frame.topmost().goBack());
187185
}
188186

189187
export function assertAreClose(actual: number, expected: number, message: string): void {

tests/app/ui/scroll-view/scroll-view-tests.ts

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as testModule from "../../ui-test";
55
import * as layoutHelper from "../layouts/layout-helper";
66
import { Page } from "tns-core-modules/ui/page";
77
import * as frame from "tns-core-modules/ui/frame";
8+
import * as helper from "../helper";
89

910
// >> article-require-scrollview-module
1011
import * as scrollViewModule from "tns-core-modules/ui/scroll-view";
@@ -154,15 +155,8 @@ class ScrollLayoutTest extends testModule.UITest<scrollViewModule.ScrollView> {
154155
this.testView.scrollToVerticalOffset(layoutHelper.dp(100), false);
155156
TKUnit.assertAreClose(layoutHelper.dip(this.testView.verticalOffset), 100, 0.1, "this.testView.verticalOffset before navigation");
156157

157-
let page = new Page();
158-
let createFunc = () => {
159-
return page;
160-
};
161-
162-
let entry: frame.NavigationEntry = { create: createFunc, animated: false };
163-
frame.topmost().navigate(entry);
164-
TKUnit.waitUntilReady(() => page.isLayoutValid);
165-
frame.topmost().goBack();
158+
helper.navigateWithHistory(() => new Page());
159+
helper.goBack();
166160

167161
// Wait for the page to reload.
168162
TKUnit.waitUntilReady(() => { return TKUnit.areClose(layoutHelper.dip(this.testView.verticalOffset), 100, 0.1); });
@@ -178,19 +172,8 @@ class ScrollLayoutTest extends testModule.UITest<scrollViewModule.ScrollView> {
178172
this.testView.scrollToHorizontalOffset(layoutHelper.dp(100), false);
179173

180174
TKUnit.assertAreClose(layoutHelper.dip(this.testView.horizontalOffset), 100, 0.1, "this.testView.horizontalOffset before navigation");
181-
182-
let page = new Page();
183-
let createFunc = () => {
184-
return page;
185-
};
186-
187-
let entry: frame.NavigationEntry = { create: createFunc, animated: false };
188-
frame.topmost().navigate(entry);
189-
TKUnit.waitUntilReady(() => page.isLayoutValid);
190-
frame.topmost().goBack();
191-
192-
// Wait for the page to reload.
193-
TKUnit.waitUntilReady(() => { return TKUnit.areClose(layoutHelper.dip(this.testView.horizontalOffset), 100, 0.1); });
175+
helper.navigateWithHistory(() => new Page());
176+
helper.goBack();
194177

195178
// Check verticalOffset after navigation
196179
TKUnit.assertAreClose(layoutHelper.dip(this.testView.horizontalOffset), 100, 0.1, "this.testView.horizontalOffset after navigation");

tns-core-modules/ui/frame/fragment.android.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,13 @@ class FragmentClass extends android.app.Fragment {
4646
}
4747

4848
public toString(): string {
49-
return this._callbacks.toStringOverride(this, super.toString);
49+
const callbacks = this._callbacks;
50+
if (callbacks) {
51+
return callbacks.toStringOverride(this, super.toString);
52+
} else {
53+
super.toString();
54+
}
5055
}
5156
}
5257

53-
setFragmentClass(FragmentClass);
58+
setFragmentClass(FragmentClass);

0 commit comments

Comments
 (0)