feat(frame): hardware back in parent frame when back states available (#6446)

This commit is contained in:
Alexander Djenkov
2018-10-24 10:18:50 +03:00
committed by Martin Yankov
parent 9f7df1868c
commit af651d6e83
4 changed files with 94 additions and 6 deletions

View File

@ -1,9 +1,11 @@
import * as TKUnit from "../TKUnit";
import { EventData, Page, NavigatedData } from "tns-core-modules/ui/page";
import { topmost as topmostFrame, NavigationTransition } from "tns-core-modules/ui/frame";
import { StackLayout, } from "tns-core-modules/ui/layouts/stack-layout";
import { GridLayout, } from "tns-core-modules/ui/layouts/grid-layout";
import { Color } from "tns-core-modules/color";
import * as helper from "../ui/helper";
import * as frame from "tns-core-modules/ui/frame";
// Creates a random colorful page full of meaningless stuff.
let id = 0;
let pageFactory = function (): Page {
@ -51,6 +53,65 @@ export function test_backstackVisible_WithTransition() {
_test_backstackVisible({ name: "fade", duration: 10 });
}
export function test_backAndForwardParentPage_nestedFrames() {
const topmost = topmostFrame();
const mainTestPage = topmost.currentPage;
let innerFrame;
const page = (title) => {
const p = new Page();
p["tag"] = title;
return p;
};
const parentPage = (title, innerPage) => {
const parentPage = new Page();
parentPage["tag"] = title;
const stack = new StackLayout();
innerFrame = new frame.Frame();
innerFrame.navigate({ create: () => innerPage });
stack.addChild(innerFrame);
parentPage.content = stack;
return parentPage;
}
const back = pages => topmostFrame().goBack(topmostFrame().backStack[topmostFrame().backStack.length - pages]);
const currentPageMustBe = tag => TKUnit.assertEqual(topmostFrame().currentPage["tag"], tag, "Expected current page to be " + tag + " it was " + topmostFrame().currentPage["tag"] + " instead.");
let parentPage1, parentPage2, innerPage1, innerPage2;
innerPage1 = page("InnerPage1");
innerPage2 = page("InnerPage2");
parentPage1 = page("ParentPage1");
parentPage2 = parentPage("ParentPage2", innerPage1);
helper.waitUntilNavigatedTo(parentPage1, () => topmost.navigate({ create: () => parentPage1 }));
currentPageMustBe("ParentPage1");
helper.waitUntilNavigatedTo(parentPage2, () => topmost.navigate({ create: () => parentPage2 }));
currentPageMustBe("ParentPage2");
helper.waitUntilNavigatedTo(innerPage2, () => innerFrame.navigate({ create: () => innerPage2 }));
currentPageMustBe("InnerPage2");
helper.waitUntilNavigatedTo(innerPage1, () => frame.goBack());
currentPageMustBe("InnerPage1");
helper.waitUntilNavigatedTo(parentPage1, () => frame.goBack());
currentPageMustBe("ParentPage1");
helper.waitUntilNavigatedTo(parentPage2, () => topmost.navigate({ create: () => parentPage2 }));
currentPageMustBe("ParentPage2");
back(2);
TKUnit.waitUntilReady(() => topmostFrame().navigationQueueIsEmpty());
const frameStack = frame.stack();
TKUnit.assertEqual(frameStack.length, 1, "There should be only one frame left in the stack");
TKUnit.assertEqual(topmostFrame().currentPage, mainTestPage, "We should be on the main test page at the end of the test.");
}
function _test_backToEntry(transition?: NavigationTransition) {
const topmost = topmostFrame();
const page = (tag) => () => {
@ -362,10 +423,10 @@ function _test_NavigationEvents_WithClearHistory(transition?: NavigationTransiti
// Go to second page
helper.navigateWithEntry({ create: secondPageFactory, transition: transition, animated: !!transition, clearHistory: true });
const expectedMainPageEvents = [ "main-page navigatingFrom forward", "main-page navigatedFrom forward" ];
const expectedMainPageEvents = ["main-page navigatingFrom forward", "main-page navigatedFrom forward"];
TKUnit.arrayAssert(actualMainPageEvents, expectedMainPageEvents, "Actual main-page events are different from expected.");
const expectedSecondPageEvents = [ "second-page navigatingTo forward", "second-page navigatedTo forward" ];
const expectedSecondPageEvents = ["second-page navigatingTo forward", "second-page navigatedTo forward"];
TKUnit.arrayAssert(actualSecondPageEvents, expectedSecondPageEvents, "Actual main-page events are different from expected.");
TKUnit.assertEqual(topmost.currentPage, secondPage, "We should be on the second page at the end of the test.");

View File

@ -3,6 +3,7 @@ import { Frame as FrameDefinition, NavigationEntry, BackstackEntry, NavigationTr
import { Page } from "../page";
// Types.
import { getAncestor } from "../core/view/view-common";
import { View, CustomLayoutView, isIOS, isAndroid, traceEnabled, traceWrite, traceCategories, Property, CSSType } from "../core/view";
import { createViewFromEntry } from "../builder";
import { profile } from "../../profiling";
@ -215,6 +216,10 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
this._currentEntry = entry;
if (isBack) {
this._pushInFrameStack();
}
newPage.onNavigatedTo(isBack);
// Reset executing entry after NavigatedTo is raised;
@ -573,6 +578,22 @@ export function goBack(): boolean {
if (top && top.canGoBack()) {
top.goBack();
return true;
} else if (top) {
let parentFrameCanGoBack = false;
let parentFrame = <FrameBase>getAncestor(top, "Frame");
while (parentFrame && !parentFrameCanGoBack) {
if (parentFrame && parentFrame.canGoBack()) {
parentFrameCanGoBack = true;
} else {
parentFrame = <FrameBase>getAncestor(top, "Frame");
}
}
if (parentFrame && parentFrameCanGoBack) {
parentFrame.goBack();
return true;
}
}
if (frameStack.length > 1) {

View File

@ -423,6 +423,7 @@ export class Frame extends FrameBase {
}
this._android.rootViewGroup = null;
this._removeFromFrameStack();
super.disposeNativeView();
}

View File

@ -36,6 +36,11 @@ export class Frame extends FrameBase {
return this.viewController.view;
}
public disposeNativeView() {
this._removeFromFrameStack();
super.disposeNativeView();
}
public get ios(): iOSFrame {
return this._ios;
}