Skip to content

Commit 70f0112

Browse files
ADjenkovSvetoslavTsenov
authored andcommitted
feat(frame): handle back navigation when common layout is used as a root element (NativeScript#5608)
* test(e2e): update modal navigation app Add layout as root. Add show modal layout. * chore(frame): move frame stack modifiers in a separate frame-stack module * feat(frame): handle back navigation when using common layout as root element
1 parent 8a1958e commit 70f0112

File tree

12 files changed

+161
-48
lines changed

12 files changed

+161
-48
lines changed

e2e/modal-navigation/app/app.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ import * as application from "tns-core-modules/application";
33

44
application.run({ moduleName: "app-root" });
55
// application.run({ moduleName: "tab-root" });
6+
// application.run({ moduleName: "layout-root" });

e2e/modal-navigation/app/home/home-page.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ export function onModalPage(args: EventData) {
4141
false);
4242
}
4343

44+
export function onModalLayout(args: EventData) {
45+
const view = args.object as View;
46+
view.showModal("modal-layout/modal-layout",
47+
"context",
48+
() => console.log("home-page modal layout closed"),
49+
false);
50+
}
51+
4452
export function onModalTabView(args: EventData) {
4553
const fullscreen = false;
4654
const animated = false;
@@ -61,7 +69,14 @@ export function onNavigate(args: EventData) {
6169
page.frame.navigate("second/second-page");
6270
}
6371

64-
export function onRootViewChange() {
65-
let rootView = application.getRootView();
66-
rootView instanceof Frame ? application._resetRootView({ moduleName: "tab-root" }) : application._resetRootView({ moduleName: "app-root" });
72+
export function onFrameRootViewReset() {
73+
application._resetRootView({ moduleName: "app-root" });
74+
}
75+
76+
export function onTabRootViewReset() {
77+
application._resetRootView({ moduleName: "tab-root" });
6778
}
79+
80+
export function onLayoutRootViewReset() {
81+
application._resetRootView({ moduleName: "layout-root" });
82+
}

e2e/modal-navigation/app/home/home-page.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212
<StackLayout>
1313
<Button text="Show Modal Page With Frame" tap="onModalFrame" />
1414
<Button text="Show Modal Page" tap="onModalPage" />
15+
<Button text="Show Modal Layout" tap="onModalLayout" />
1516
<Button text="Show Modal TabView" tap="onModalTabView" />
1617
<Button text="Navigate To Second Page" tap="onNavigate" />
17-
<Button text="Change Root View" tap="onRootViewChange" />
18+
<Button text="Reset Frame Root View" tap="onFrameRootViewReset" />
19+
<Button text="Reset Tab Root View" tap="onTabRootViewReset" />
20+
<Button text="Reset Layout Root View" tap="onLayoutRootViewReset" />
1821
</StackLayout>
1922
</Page>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<GridLayout>
2+
<Frame defaultPage="home/home-page" />
3+
</GridLayout>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export function onShowingModally() {
2+
console.log("modal-layout showingModally");
3+
}
4+
5+
export function onLoaded() {
6+
console.log("modal-layout loaded");
7+
}
8+
9+
export function onNavigatingTo() {
10+
console.log("modal-layout onNavigatingTo");
11+
}
12+
13+
export function onNavigatingFrom() {
14+
console.log("modal-layout onNavigatingFrom");
15+
}
16+
17+
export function onNavigatedTo() {
18+
console.log("modal-layout onNavigatedTo");
19+
}
20+
21+
export function onNavigatedFrom() {
22+
console.log("modal-layout onNavigatedFrom");
23+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<GridLayout backgroundColor="green" showingModally="onShowingModally" loaded="onLoaded"
2+
navigatingTo="onNavigatingTo"
3+
navigatingFrom="onNavigatingFrom"
4+
navigatedTo="onNavigatedTo"
5+
navigatedFrom="onNavigatedFrom">
6+
<Frame defaultPage="modal/modal-page"></Frame>
7+
</GridLayout>

e2e/modal-navigation/e2e/screen.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ const modalFrame = "Show Modal Page With Frame";
1212
const modalPage = "Show Modal Page";
1313
const modalTabView = "Show Modal TabView";
1414
const navToSecondPage = "Navigate To Second Page";
15-
const rootView = "Change Root View";
15+
const resetFrameRootView = "Reset Frame Root View";
16+
const resetTabRootView = "Reset Tab Root View";
17+
const resetLayoutRootView = "Reset Layout Root View";
1618

1719
const showNestedModalFrame = "Show Nested Modal Page With Frame";
1820
const showNestedModalPage = "Show Nested Modal Page";
@@ -35,9 +37,19 @@ export class Screen {
3537
console.log(home + " loaded!");
3638
}
3739

38-
changeRootView = async () => {
39-
const btnChangeRootView = await this._driver.findElementByText(rootView);
40-
await btnChangeRootView.tap();
40+
resetFrameRootView = async () => {
41+
const btnResetFrameRootView = await this._driver.findElementByText(resetFrameRootView);
42+
await btnResetFrameRootView.tap();
43+
}
44+
45+
resetTabRootView = async () => {
46+
const btnResetTabRootView = await this._driver.findElementByText(resetTabRootView);
47+
await btnResetTabRootView.tap();
48+
}
49+
50+
resetLayoutRootView = async () => {
51+
const btnResetLayoutRootView = await this._driver.findElementByText(resetLayoutRootView);
52+
await btnResetLayoutRootView.tap();
4153
}
4254

4355
loadedTabRootView = async () => {
@@ -52,7 +64,7 @@ export class Screen {
5264
try {
5365
await this.loadedTabRootView();
5466
} catch (err) {
55-
await this.changeRootView();
67+
await this.resetTabRootView();
5668
await this.loadedTabRootView();
5769
}
5870
}

tns-core-modules/ui/core/view/view-common.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
263263
that._closeModalCallback = null;
264264
that._dialogClosed();
265265
parent._modal = null;
266-
266+
267267
if (typeof closeCallback === "function") {
268268
closeCallback.apply(undefined, arguments);
269269
}
@@ -976,6 +976,18 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
976976
_onDetachedFromWindow(): void {
977977
//
978978
}
979+
980+
_hasAncestorView(ancestorView: ViewDefinition): boolean {
981+
let matcher = (view: ViewDefinition) => view === ancestorView;
982+
983+
for (let parent = this.parent; parent != null; parent = parent.parent) {
984+
if (matcher(<ViewDefinition>parent)) {
985+
return true;
986+
}
987+
}
988+
989+
return false;
990+
}
979991
}
980992

981993
export const automationTextProperty = new Property<ViewCommon, string>({ name: "automationText" });

tns-core-modules/ui/core/view/view.android.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222

2323
import { Background, ad as androidBackground } from "../../styling/background";
2424
import { profile } from "../../../profiling";
25+
import { topmost } from "../../frame/frame-stack";
2526

2627
export * from "./view-common";
2728

@@ -287,6 +288,18 @@ export class View extends ViewCommon {
287288
super.onUnloaded();
288289
}
289290

291+
public onBackPressed(): boolean {
292+
let topmostFrame = topmost();
293+
294+
// Delegate back navigation handling to the topmost Frame
295+
// when it's a child of the current View.
296+
if (topmostFrame && topmostFrame._hasAncestorView(this)) {
297+
return topmostFrame.onBackPressed();
298+
}
299+
300+
return false;
301+
}
302+
290303
private hasGestureObservers() {
291304
return this._gestureObservers && Object.keys(this._gestureObservers).length > 0
292305
}

tns-core-modules/ui/core/view/view.d.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export abstract class View extends ViewBase {
110110
* String value used when hooking to shownModally event.
111111
*/
112112
public static shownModallyEvent: string;
113-
113+
114114
/**
115115
* Gets the android-specific native instance that lies behind this proxy. Will be available if running on an Android platform.
116116
*/
@@ -705,6 +705,11 @@ export abstract class View extends ViewBase {
705705
* Called in android when native view is dettached from window.
706706
*/
707707
_onDetachedFromWindow(): void;
708+
709+
/**
710+
* Checks whether the current view has specific view for an ancestor.
711+
*/
712+
_hasAncestorView(ancestorView: View): boolean;
708713
//@endprivate
709714

710715
/**
@@ -797,7 +802,7 @@ export const isEnabledProperty: Property<View, boolean>;
797802
export const isUserInteractionEnabledProperty: Property<View, boolean>;
798803

799804
export namespace ios {
800-
export function isContentScrollable(controller: any /* UIViewController */, owner: View): boolean
805+
export function isContentScrollable(controller: any /* UIViewController */, owner: View): boolean
801806
export function updateAutoAdjustScrollInsets(controller: any /* UIViewController */, owner: View): void
802807
export function updateConstraints(controller: any /* UIViewController */, owner: View): void;
803808
export function layoutView(controller: any /* UIViewController */, owner: View): void;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy