mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 19:26:42 +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/**'",
|
"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": "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-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": "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/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
|
// >> frame-require
|
||||||
import { topmost, NavigationEntry } from "tns-core-modules/ui/frame";
|
import { Frame, getFrameById, topmost, NavigationEntry } from "tns-core-modules/ui/frame";
|
||||||
// << frame-require
|
// << frame-require
|
||||||
|
|
||||||
|
import { getRootView } from "tns-core-modules/application";
|
||||||
import { Label } from "tns-core-modules/ui/label";
|
import { Label } from "tns-core-modules/ui/label";
|
||||||
import { Page } from "tns-core-modules/ui/page";
|
import { Page } from "tns-core-modules/ui/page";
|
||||||
import * as helper from "../helper";
|
import * as helper from "../helper";
|
||||||
@ -224,3 +225,39 @@ export function test_page_parent_when_navigate_back() {
|
|||||||
|
|
||||||
pages.length = 0;
|
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() {
|
public _pushInFrameStack() {
|
||||||
if (this._isInFrameStack) {
|
if (this._isInFrameStack && frameStack[frameStack.length - 1] === this) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._isInFrameStack) {
|
||||||
|
const indexOfFrame = frameStack.indexOf(this);
|
||||||
|
frameStack.splice(indexOfFrame, 1);
|
||||||
|
}
|
||||||
|
|
||||||
frameStack.push(this);
|
frameStack.push(this);
|
||||||
this._isInFrameStack = true;
|
this._isInFrameStack = true;
|
||||||
}
|
}
|
||||||
@ -425,7 +430,7 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
|
|||||||
this._isInFrameStack = false;
|
this._isInFrameStack = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _removeFromFrameStack() {
|
public _removeFromFrameStack() {
|
||||||
if (!this._isInFrameStack) {
|
if (!this._isInFrameStack) {
|
||||||
return;
|
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 {
|
export function topmost(): FrameBase {
|
||||||
if (frameStack.length > 0) {
|
if (frameStack.length > 0) {
|
||||||
return frameStack[frameStack.length - 1];
|
return frameStack[frameStack.length - 1];
|
||||||
|
@ -597,7 +597,7 @@ function startActivity(activity: android.app.Activity, frameId: number) {
|
|||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFrameById(frameId: number): Frame {
|
function getFrameByNumberId(frameId: number): Frame {
|
||||||
// Find the frame for this activity.
|
// Find the frame for this activity.
|
||||||
for (let i = 0; i < framesCache.length; i++) {
|
for (let i = 0; i < framesCache.length; i++) {
|
||||||
let aliveFrame = framesCache[i].get();
|
let aliveFrame = framesCache[i].get();
|
||||||
@ -676,7 +676,7 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
|
|||||||
if (!this.entry) {
|
if (!this.entry) {
|
||||||
const args = fragment.getArguments();
|
const args = fragment.getArguments();
|
||||||
const frameId = args.getInt(FRAMEID);
|
const frameId = args.getInt(FRAMEID);
|
||||||
const frame = getFrameById(frameId);
|
const frame = getFrameByNumberId(frameId);
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
throw new Error(`Cannot find Frame for ${fragment}`);
|
throw new Error(`Cannot find Frame for ${fragment}`);
|
||||||
}
|
}
|
||||||
@ -999,7 +999,7 @@ class ActivityCallbacksImplementation implements AndroidActivityCallbacks {
|
|||||||
if (!rootView) {
|
if (!rootView) {
|
||||||
// If we have frameId from extras - we are starting a new activity from navigation (e.g. new Frame().navigate()))
|
// 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)
|
// 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) {
|
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
|
* @private
|
||||||
*/
|
*/
|
||||||
_updateBackstack(entry: BackstackEntry, isBack: boolean): void;
|
_updateBackstack(entry: BackstackEntry, isBack: boolean): void;
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_pushInFrameStack();
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_removeFromFrameStack();
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@ -170,6 +178,11 @@ export class Frame extends View {
|
|||||||
*/
|
*/
|
||||||
export function setFragmentClass(clazz: any): void;
|
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.
|
* 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();
|
export function goBack();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Deprecated. Use getFrameById() if you want to retrieve a frame different than the topmost one.
|
||||||
* Gets the frames stack.
|
* Gets the frames stack.
|
||||||
*/
|
*/
|
||||||
export function stack(): Array<Frame>;
|
export function stack(): Array<Frame>;
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
import { textTransformProperty, TextTransform, getTransformedText } from "../text-base";
|
import { textTransformProperty, TextTransform, getTransformedText } from "../text-base";
|
||||||
import { fromFileOrResource } from "../../image-source";
|
import { fromFileOrResource } from "../../image-source";
|
||||||
import { RESOURCE_PREFIX, ad } from "../../utils/utils";
|
import { RESOURCE_PREFIX, ad } from "../../utils/utils";
|
||||||
|
import { Frame } from "../frame";
|
||||||
|
|
||||||
export * from "./tab-view-common";
|
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 => {
|
toLoad.forEach(index => {
|
||||||
const item = items[index];
|
const item = items[index];
|
||||||
if (this.isLoaded && items[index]) {
|
if (this.isLoaded && items[index]) {
|
||||||
|
@ -13,6 +13,7 @@ import { Page } from "../page";
|
|||||||
import { profile } from "../../profiling";
|
import { profile } from "../../profiling";
|
||||||
import * as uiUtils from "../utils";
|
import * as uiUtils from "../utils";
|
||||||
import * as utils from "../../utils/utils";
|
import * as utils from "../../utils/utils";
|
||||||
|
import { Frame } from "../frame";
|
||||||
|
|
||||||
export * from "./tab-view-common";
|
export * from "./tab-view-common";
|
||||||
|
|
||||||
@ -253,6 +254,11 @@ export class TabView extends TabViewBase {
|
|||||||
|
|
||||||
const newItem = items[newIndex];
|
const newItem = items[newIndex];
|
||||||
if (newItem && this.isLoaded) {
|
if (newItem && this.isLoaded) {
|
||||||
|
const selectedView = items[newIndex].view;
|
||||||
|
if (selectedView instanceof Frame) {
|
||||||
|
selectedView._pushInFrameStack();
|
||||||
|
}
|
||||||
|
|
||||||
newItem.loadView(newItem.view);
|
newItem.loadView(newItem.view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user