mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 11:01:21 +08:00
feat(frame): rework frame retrieval api (#5527)
Rework the frame api to support working with multiple Frames. * frameModule.topmost() - now returns the last navigated Frame or the currently selected tab item's Frame if the tab item's view is a Frame. * frameModule.getFrameById(id: string) - returns a navigated Frame by id. * args.object.page.frame - can be used in page elements event handlers. Returns the Frame of the current element's page. * chore: Update madge-android npm script path
This commit is contained in:
@ -84,7 +84,7 @@
|
||||
"tslint": "tslint --config build/tslint.json 'tns-core-modules/**/*.ts' 'tests/**/*.ts' 'apps/**/*.ts' 'e2e/**/*.ts' -e '**/node_modules/**' -e '**/platforms/**'",
|
||||
"madge-ios": "tsc --skipLibCheck && tns prepare ios --path tests && madge --circular tests/platforms/ios/tests/app/tns_modules/tns-core-modules",
|
||||
"madge-ios-image": "tsc --skipLibCheck && tns prepare ios --path tests && madge --image graph-tests-ios.svg tests/platforms/ios/tests/app/tns_modules/tns-core-modules",
|
||||
"madge-android": "tsc --skipLibCheck && tns prepare android --path tests && madge --circular tests/platforms/android/src/main/assets/app/tns_modules/tns-core-modules",
|
||||
"madge-android-image": "tsc --skipLibCheck && tns prepare android --path tests && madge --image graph-tests-android.svg tests/platforms/android/src/main/assets/app/tns_modules/tns-core-modules"
|
||||
"madge-android": "tsc --skipLibCheck && tns prepare android --path tests && madge --circular tests/platforms/android/app/src/main/assets/app/tns_modules/tns-core-modules",
|
||||
"madge-android-image": "tsc --skipLibCheck && tns prepare android --path tests && madge --image graph-tests-android.svg tests/platforms/android/app/src/main/assets/app/tns_modules/tns-core-modules"
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
// >> frame-require
|
||||
import { topmost, NavigationEntry } from "tns-core-modules/ui/frame";
|
||||
import { Frame, getFrameById, topmost, NavigationEntry } from "tns-core-modules/ui/frame";
|
||||
// << frame-require
|
||||
|
||||
import { getRootView } from "tns-core-modules/application";
|
||||
import { Label } from "tns-core-modules/ui/label";
|
||||
import { Page } from "tns-core-modules/ui/page";
|
||||
import * as helper from "../helper";
|
||||
@ -223,4 +224,40 @@ export function test_page_parent_when_navigate_back() {
|
||||
});
|
||||
|
||||
pages.length = 0;
|
||||
}
|
||||
|
||||
export function test_frame_retrieval_API_when_navigating() {
|
||||
const rootView = getRootView();
|
||||
|
||||
const initialFrame = new Frame();
|
||||
initialFrame.id = "initialFrame";
|
||||
initialFrame.navigate(() => new Page());
|
||||
|
||||
const initialTopmost = topmost();
|
||||
const initialFrameById = getFrameById("initialFrame");
|
||||
|
||||
TKUnit.assertEqual(initialTopmost, initialFrame);
|
||||
TKUnit.assertEqual(initialFrameById, initialFrame);
|
||||
|
||||
const newFrame = new Frame();
|
||||
newFrame.id = "newFrame";
|
||||
newFrame.navigate(() => new Page());
|
||||
|
||||
const newTopmost = topmost();
|
||||
const newFrameById = getFrameById("newFrame");
|
||||
|
||||
TKUnit.assertEqual(newTopmost, newFrame);
|
||||
TKUnit.assertEqual(newFrameById, newFrame);
|
||||
|
||||
initialFrame.navigate(() => new Page());
|
||||
|
||||
const previousTopmost = topmost();
|
||||
const previousFrameById = getFrameById("initialFrame");
|
||||
|
||||
TKUnit.assertEqual(previousTopmost, initialFrame);
|
||||
TKUnit.assertEqual(previousFrameById, initialFrame);
|
||||
|
||||
// clean up the frame stack
|
||||
initialFrame._removeFromFrameStack();
|
||||
newFrame._removeFromFrameStack();
|
||||
}
|
@ -403,10 +403,15 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
|
||||
}
|
||||
|
||||
public _pushInFrameStack() {
|
||||
if (this._isInFrameStack) {
|
||||
if (this._isInFrameStack && frameStack[frameStack.length - 1] === this) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._isInFrameStack) {
|
||||
const indexOfFrame = frameStack.indexOf(this);
|
||||
frameStack.splice(indexOfFrame, 1);
|
||||
}
|
||||
|
||||
frameStack.push(this);
|
||||
this._isInFrameStack = true;
|
||||
}
|
||||
@ -425,7 +430,7 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
|
||||
this._isInFrameStack = false;
|
||||
}
|
||||
|
||||
private _removeFromFrameStack() {
|
||||
public _removeFromFrameStack() {
|
||||
if (!this._isInFrameStack) {
|
||||
return;
|
||||
}
|
||||
@ -575,6 +580,10 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
export function getFrameById(id: string): FrameBase {
|
||||
return frameStack.find((frame) => frame.id && frame.id === id);
|
||||
}
|
||||
|
||||
export function topmost(): FrameBase {
|
||||
if (frameStack.length > 0) {
|
||||
return frameStack[frameStack.length - 1];
|
||||
|
@ -597,7 +597,7 @@ function startActivity(activity: android.app.Activity, frameId: number) {
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
function getFrameById(frameId: number): Frame {
|
||||
function getFrameByNumberId(frameId: number): Frame {
|
||||
// Find the frame for this activity.
|
||||
for (let i = 0; i < framesCache.length; i++) {
|
||||
let aliveFrame = framesCache[i].get();
|
||||
@ -676,7 +676,7 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
|
||||
if (!this.entry) {
|
||||
const args = fragment.getArguments();
|
||||
const frameId = args.getInt(FRAMEID);
|
||||
const frame = getFrameById(frameId);
|
||||
const frame = getFrameByNumberId(frameId);
|
||||
if (!frame) {
|
||||
throw new Error(`Cannot find Frame for ${fragment}`);
|
||||
}
|
||||
@ -999,7 +999,7 @@ class ActivityCallbacksImplementation implements AndroidActivityCallbacks {
|
||||
if (!rootView) {
|
||||
// If we have frameId from extras - we are starting a new activity from navigation (e.g. new Frame().navigate()))
|
||||
// Then we check if we have frameId from savedInstanceState - this happens when Activity is destroyed but app was not (e.g. suspend)
|
||||
rootView = getFrameById(frameId) || new Frame();
|
||||
rootView = getFrameByNumberId(frameId) || new Frame();
|
||||
}
|
||||
|
||||
if (rootView instanceof Frame) {
|
||||
|
14
tns-core-modules/ui/frame/frame.d.ts
vendored
14
tns-core-modules/ui/frame/frame.d.ts
vendored
@ -145,6 +145,14 @@ export class Frame extends View {
|
||||
* @private
|
||||
*/
|
||||
_updateBackstack(entry: BackstackEntry, isBack: boolean): void;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_pushInFrameStack();
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_removeFromFrameStack();
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@ -170,6 +178,11 @@ export class Frame extends View {
|
||||
*/
|
||||
export function setFragmentClass(clazz: any): void;
|
||||
|
||||
/**
|
||||
* Gets a frame by id.
|
||||
*/
|
||||
export function getFrameById(id: string): Frame;
|
||||
|
||||
/**
|
||||
* Gets the topmost frame in the frames stack. An application will typically has one frame instance. Multiple frames handle nested (hierarchical) navigation scenarios.
|
||||
*/
|
||||
@ -182,6 +195,7 @@ export function topmost(): Frame;
|
||||
export function goBack();
|
||||
|
||||
/**
|
||||
* Deprecated. Use getFrameById() if you want to retrieve a frame different than the topmost one.
|
||||
* Gets the frames stack.
|
||||
*/
|
||||
export function stack(): Array<Frame>;
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
import { textTransformProperty, TextTransform, getTransformedText } from "../text-base";
|
||||
import { fromFileOrResource } from "../../image-source";
|
||||
import { RESOURCE_PREFIX, ad } from "../../utils/utils";
|
||||
import { Frame } from "../frame";
|
||||
|
||||
export * from "./tab-view-common";
|
||||
|
||||
@ -473,6 +474,12 @@ export class TabView extends TabViewBase {
|
||||
}
|
||||
});
|
||||
|
||||
const newItem = items[newIndex];
|
||||
const selectedView = newItem && newItem.view;
|
||||
if (selectedView instanceof Frame) {
|
||||
selectedView._pushInFrameStack();
|
||||
}
|
||||
|
||||
toLoad.forEach(index => {
|
||||
const item = items[index];
|
||||
if (this.isLoaded && items[index]) {
|
||||
|
@ -13,6 +13,7 @@ import { Page } from "../page";
|
||||
import { profile } from "../../profiling";
|
||||
import * as uiUtils from "../utils";
|
||||
import * as utils from "../../utils/utils";
|
||||
import { Frame } from "../frame";
|
||||
|
||||
export * from "./tab-view-common";
|
||||
|
||||
@ -253,6 +254,11 @@ export class TabView extends TabViewBase {
|
||||
|
||||
const newItem = items[newIndex];
|
||||
if (newItem && this.isLoaded) {
|
||||
const selectedView = items[newIndex].view;
|
||||
if (selectedView instanceof Frame) {
|
||||
selectedView._pushInFrameStack();
|
||||
}
|
||||
|
||||
newItem.loadView(newItem.view);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user