Skip to content

Commit dfa70dd

Browse files
authored
feat(frame): rework frame retrieval api (NativeScript#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
1 parent 45bf5b8 commit dfa70dd

File tree

7 files changed

+81
-8
lines changed

7 files changed

+81
-8
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
"tslint": "tslint --config build/tslint.json 'tns-core-modules/**/*.ts' 'tests/**/*.ts' 'apps/**/*.ts' 'e2e/**/*.ts' -e '**/node_modules/**' -e '**/platforms/**'",
8585
"madge-ios": "tsc --skipLibCheck && tns prepare ios --path tests && madge --circular tests/platforms/ios/tests/app/tns_modules/tns-core-modules",
8686
"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",
87-
"madge-android": "tsc --skipLibCheck && tns prepare android --path tests && madge --circular tests/platforms/android/src/main/assets/app/tns_modules/tns-core-modules",
88-
"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"
87+
"madge-android": "tsc --skipLibCheck && tns prepare android --path tests && madge --circular tests/platforms/android/app/src/main/assets/app/tns_modules/tns-core-modules",
88+
"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"
8989
}
9090
}

tests/app/ui/frame/frame-tests-common.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// >> frame-require
2-
import { topmost, NavigationEntry } from "tns-core-modules/ui/frame";
2+
import { Frame, getFrameById, topmost, NavigationEntry } from "tns-core-modules/ui/frame";
33
// << frame-require
44

5+
import { getRootView } from "tns-core-modules/application";
56
import { Label } from "tns-core-modules/ui/label";
67
import { Page } from "tns-core-modules/ui/page";
78
import * as helper from "../helper";
@@ -223,4 +224,40 @@ export function test_page_parent_when_navigate_back() {
223224
});
224225

225226
pages.length = 0;
227+
}
228+
229+
export function test_frame_retrieval_API_when_navigating() {
230+
const rootView = getRootView();
231+
232+
const initialFrame = new Frame();
233+
initialFrame.id = "initialFrame";
234+
initialFrame.navigate(() => new Page());
235+
236+
const initialTopmost = topmost();
237+
const initialFrameById = getFrameById("initialFrame");
238+
239+
TKUnit.assertEqual(initialTopmost, initialFrame);
240+
TKUnit.assertEqual(initialFrameById, initialFrame);
241+
242+
const newFrame = new Frame();
243+
newFrame.id = "newFrame";
244+
newFrame.navigate(() => new Page());
245+
246+
const newTopmost = topmost();
247+
const newFrameById = getFrameById("newFrame");
248+
249+
TKUnit.assertEqual(newTopmost, newFrame);
250+
TKUnit.assertEqual(newFrameById, newFrame);
251+
252+
initialFrame.navigate(() => new Page());
253+
254+
const previousTopmost = topmost();
255+
const previousFrameById = getFrameById("initialFrame");
256+
257+
TKUnit.assertEqual(previousTopmost, initialFrame);
258+
TKUnit.assertEqual(previousFrameById, initialFrame);
259+
260+
// clean up the frame stack
261+
initialFrame._removeFromFrameStack();
262+
newFrame._removeFromFrameStack();
226263
}

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -403,10 +403,15 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
403403
}
404404

405405
public _pushInFrameStack() {
406-
if (this._isInFrameStack) {
406+
if (this._isInFrameStack && frameStack[frameStack.length - 1] === this) {
407407
return;
408408
}
409409

410+
if (this._isInFrameStack) {
411+
const indexOfFrame = frameStack.indexOf(this);
412+
frameStack.splice(indexOfFrame, 1);
413+
}
414+
410415
frameStack.push(this);
411416
this._isInFrameStack = true;
412417
}
@@ -425,7 +430,7 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
425430
this._isInFrameStack = false;
426431
}
427432

428-
private _removeFromFrameStack() {
433+
public _removeFromFrameStack() {
429434
if (!this._isInFrameStack) {
430435
return;
431436
}
@@ -575,6 +580,10 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
575580
}
576581
}
577582

583+
export function getFrameById(id: string): FrameBase {
584+
return frameStack.find((frame) => frame.id && frame.id === id);
585+
}
586+
578587
export function topmost(): FrameBase {
579588
if (frameStack.length > 0) {
580589
return frameStack[frameStack.length - 1];

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ function startActivity(activity: android.app.Activity, frameId: number) {
597597
activity.startActivity(intent);
598598
}
599599

600-
function getFrameById(frameId: number): Frame {
600+
function getFrameByNumberId(frameId: number): Frame {
601601
// Find the frame for this activity.
602602
for (let i = 0; i < framesCache.length; i++) {
603603
let aliveFrame = framesCache[i].get();
@@ -676,7 +676,7 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
676676
if (!this.entry) {
677677
const args = fragment.getArguments();
678678
const frameId = args.getInt(FRAMEID);
679-
const frame = getFrameById(frameId);
679+
const frame = getFrameByNumberId(frameId);
680680
if (!frame) {
681681
throw new Error(`Cannot find Frame for ${fragment}`);
682682
}
@@ -999,7 +999,7 @@ class ActivityCallbacksImplementation implements AndroidActivityCallbacks {
999999
if (!rootView) {
10001000
// If we have frameId from extras - we are starting a new activity from navigation (e.g. new Frame().navigate()))
10011001
// Then we check if we have frameId from savedInstanceState - this happens when Activity is destroyed but app was not (e.g. suspend)
1002-
rootView = getFrameById(frameId) || new Frame();
1002+
rootView = getFrameByNumberId(frameId) || new Frame();
10031003
}
10041004

10051005
if (rootView instanceof Frame) {

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,14 @@ export class Frame extends View {
145145
* @private
146146
*/
147147
_updateBackstack(entry: BackstackEntry, isBack: boolean): void;
148+
/**
149+
* @private
150+
*/
151+
_pushInFrameStack();
152+
/**
153+
* @private
154+
*/
155+
_removeFromFrameStack();
148156
/**
149157
* @private
150158
*/
@@ -170,6 +178,11 @@ export class Frame extends View {
170178
*/
171179
export function setFragmentClass(clazz: any): void;
172180

181+
/**
182+
* Gets a frame by id.
183+
*/
184+
export function getFrameById(id: string): Frame;
185+
173186
/**
174187
* Gets the topmost frame in the frames stack. An application will typically has one frame instance. Multiple frames handle nested (hierarchical) navigation scenarios.
175188
*/
@@ -182,6 +195,7 @@ export function topmost(): Frame;
182195
export function goBack();
183196

184197
/**
198+
* Deprecated. Use getFrameById() if you want to retrieve a frame different than the topmost one.
185199
* Gets the frames stack.
186200
*/
187201
export function stack(): Array<Frame>;

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import { textTransformProperty, TextTransform, getTransformedText } from "../text-base";
1212
import { fromFileOrResource } from "../../image-source";
1313
import { RESOURCE_PREFIX, ad } from "../../utils/utils";
14+
import { Frame } from "../frame";
1415

1516
export * from "./tab-view-common";
1617

@@ -473,6 +474,12 @@ export class TabView extends TabViewBase {
473474
}
474475
});
475476

477+
const newItem = items[newIndex];
478+
const selectedView = newItem && newItem.view;
479+
if (selectedView instanceof Frame) {
480+
selectedView._pushInFrameStack();
481+
}
482+
476483
toLoad.forEach(index => {
477484
const item = items[index];
478485
if (this.isLoaded && items[index]) {

tns-core-modules/ui/tab-view/tab-view.ios.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { Page } from "../page";
1313
import { profile } from "../../profiling";
1414
import * as uiUtils from "../utils";
1515
import * as utils from "../../utils/utils";
16+
import { Frame } from "../frame";
1617

1718
export * from "./tab-view-common";
1819

@@ -253,6 +254,11 @@ export class TabView extends TabViewBase {
253254

254255
const newItem = items[newIndex];
255256
if (newItem && this.isLoaded) {
257+
const selectedView = items[newIndex].view;
258+
if (selectedView instanceof Frame) {
259+
selectedView._pushInFrameStack();
260+
}
261+
256262
newItem.loadView(newItem.view);
257263
}
258264

0 commit comments

Comments
 (0)