Skip to content

Commit

Permalink
Merge pull request #961 from NativeScript/issue-779
Browse files Browse the repository at this point in the history
Fixed #779: frame.topmost().currentPage is not the same instance as t…
  • Loading branch information
hamorphis committed Oct 20, 2015
2 parents 4a8fdc7 + 4dafdf1 commit 421845e
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 4 deletions.
8 changes: 7 additions & 1 deletion CrossPlatformModules.csproj
Expand Up @@ -80,6 +80,9 @@
<DependentUpon>data-binding.xml</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="apps\tests\ui\action-bar\ActionBar_NumberAsText.ts" />
<TypeScriptCompile Include="apps\tests\ui\page\modal-page.ts">
<DependentUpon>modal-page.xml</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="apps\tests\ui\placeholder\placeholder-tests.ts" />
<TypeScriptCompile Include="apps\tests\xml-declaration\custom-code-file.ts" />
<TypeScriptCompile Include="apps\transforms\app.ts" />
Expand Down Expand Up @@ -114,6 +117,9 @@
<Content Include="apps\action-bar-demo\pages\center-view.xml" />
<Content Include="apps\action-bar-demo\pages\data-binding.xml" />
<Content Include="apps\tests\ui\action-bar\ActionBar_NumberAsText.xml" />
<Content Include="apps\tests\ui\page\modal-page.xml">
<SubType>Designer</SubType>
</Content>
<Content Include="apps\tests\xml-declaration\custom-css-file.css" />
<Content Include="apps\transforms\main-page.xml">
<SubType>Designer</SubType>
Expand Down Expand Up @@ -1992,7 +1998,7 @@
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
<UserProperties ui_2layouts_2wrap-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2grid-layout_2package_1json__JSONSchema="" ui_2layouts_2dock-layout_2package_1json__JSONSchema="" ui_2layouts_2absolute-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2web-view_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2content-view_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2gallery-app_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2absolute-layout-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2editable-text-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2scroll-view_2package_1json__JSONSchema="http://json.schemastore.org/package" />
<UserProperties ui_2scroll-view_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2editable-text-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2absolute-layout-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2gallery-app_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2content-view_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2web-view_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2absolute-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2dock-layout_2package_1json__JSONSchema="" ui_2layouts_2grid-layout_2package_1json__JSONSchema="" ui_2layouts_2wrap-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" />
</VisualStudio>
</ProjectExtensions>
</Project>
16 changes: 14 additions & 2 deletions apps/modal-views-demo/main-page.ts
@@ -1,13 +1,25 @@
import observable = require("data/observable");
import pages = require("ui/page");
import labelModule = require("ui/label");
import frame = require("ui/frame");

var page: pages.Page;
var label: labelModule.Label;

export function pageLoaded(args: observable.EventData) {
export function onLoaded(args: observable.EventData) {
console.log("main-page.onLoaded");
if (args.object !== frame.topmost().currentPage) {
throw new Error("args.object must equal frame.topmost().currentPage on page.loaded");
}
page = <pages.Page>args.object;
label = page.getViewById<labelModule.Label>("label");
label = frame.topmost().getViewById<labelModule.Label>("label");
if (!label) {
throw new Error("Could not find `label`");
}
}

export function onNavigatedTo(args: observable.EventData) {
console.log("main-page.onNavigatedTo");
}

export function onTap(args: observable.EventData) {
Expand Down
2 changes: 1 addition & 1 deletion apps/modal-views-demo/main-page.xml
@@ -1,4 +1,4 @@
<Page xmlns="http://www.nativescript.org/tns.xsd" loaded="pageLoaded" id="_mainPage" backgroundColor="Red">
<Page xmlns="http://www.nativescript.org/tns.xsd" loaded="onLoaded" navigatedTo="onNavigatedTo" id="_mainPage" backgroundColor="Red">
<StackLayout backgroundColor="PaleGreen">
<Button text="Login (small)" tap="onTap" />
<Button text="Login (full-screen)" tap="onTap" />
Expand Down
8 changes: 8 additions & 0 deletions apps/tests/ui/page/modal-page.ts
@@ -0,0 +1,8 @@
import {ShownModallyData} from "ui/page";
import TKUnit = require("../../TKUnit");

export function onShownModally(args: ShownModallyData) {
TKUnit.wait(0.350);
args.context.shownModally = true;
args.closeCallback("return value");
}
5 changes: 5 additions & 0 deletions apps/tests/ui/page/modal-page.xml
@@ -0,0 +1,5 @@
<Page shownModally="onShownModally">
<StackLayout>
<Label text="Modal Page" />
</StackLayout>
</Page>
26 changes: 26 additions & 0 deletions apps/tests/ui/page/page-tests-common.ts
Expand Up @@ -27,6 +27,7 @@ import LabelModule = require("ui/label");
import stackLayoutModule = require("ui/layouts/stack-layout");
import helper = require("../helper");
import view = require("ui/core/view");
import platform = require("platform");

export function addLabelToPage(page: PageModule.Page, text?: string) {
var label = new LabelModule.Label();
Expand Down Expand Up @@ -368,6 +369,31 @@ export function test_page_backgroundColor_is_white() {
});
}

export function test_WhenPageIsLoadedFrameCurrentPageIsTheSameInstance() {
var page;
var loadedEventHandler = function (args) {
TKUnit.assert(FrameModule.topmost().currentPage === args.object, `frame.topmost().currentPage should be equal to args.object page instance in the page.loaded event handler. Expected: ${args.object.id}; Actual: ${FrameModule.topmost().currentPage.id};`);
}

var pageFactory = function (): PageModule.Page {
page = new PageModule.Page();
page.id = "newPage";
page.on(view.View.loadedEvent, loadedEventHandler);
var label = new LabelModule.Label();
label.text = "Text";
page.content = label;
return page;
};

try {
helper.navigate(pageFactory);
page.off(view.View.loadedEvent, loadedEventHandler);
}
finally {
helper.goBack();
}
}

//export function test_ModalPage_Layout_is_Correct() {
// var testPage: PageModule.Page;
// var label: LabelModule.Label;
Expand Down
40 changes: 40 additions & 0 deletions apps/tests/ui/page/page-tests.ios.ts
Expand Up @@ -3,6 +3,7 @@ import PageModule = require("ui/page");
import TKUnit = require("../../TKUnit");
import LabelModule = require("ui/label");
import helper = require("../helper");
import view = require("ui/core/view");

global.moduleMerge(PageTestCommon, exports);

Expand All @@ -23,3 +24,42 @@ export function test_NavigateToNewPage_InnerControl() {
TKUnit.assert(label.android === undefined, "InnerControl.android should be undefined after navigate back.");
TKUnit.assert(label.isLoaded === false, "InnerControl.isLoaded should become false after navigating back");
}

export function test_WhenPageIsLoadedItCanShowAnotherPageAsModal() {
var masterPage;
var ctx = {
shownModally: false
};

var modalClosed = false;
var modalCloseCallback = function (returnValue: any) {
TKUnit.assert(ctx.shownModally, "Modal-page must be shown!");
TKUnit.assert(returnValue === "return value", "Modal-page must return value!");
TKUnit.wait(0.350);
modalClosed = true;
}

var loadedEventHandler = function (args) {
var basePath = "ui/page/";
args.object.showModal(basePath + "modal-page", ctx, modalCloseCallback, false);
};

var masterPageFactory = function (): PageModule.Page {
masterPage = new PageModule.Page();
masterPage.id = "newPage";
masterPage.on(view.View.loadedEvent, loadedEventHandler);
var label = new LabelModule.Label();
label.text = "Text";
masterPage.content = label;
return masterPage;
};

try {
helper.navigate(masterPageFactory);
TKUnit.waitUntilReady(() => { return modalClosed; });
masterPage.off(view.View.loadedEvent, loadedEventHandler);
}
finally {
helper.goBack();
}
}
8 changes: 8 additions & 0 deletions ui/frame/frame.ios.ts
Expand Up @@ -309,6 +309,14 @@ class UINavigationControllerImpl extends UINavigationController implements UINav
frame._currentEntry = newEntry;

var newPage = newEntry.resolvedPage;

// In iOS we intentionally delay the raising of the 'loaded' event so both platforms behave identically.
// The loaded event must be raised AFTER the page is part of the windows hierarchy and
// frame.topmost().currentPage is set to the page instance.
// https://github.com/NativeScript/NativeScript/issues/779
(<any>newPage)._delayLoadedEvent = false;
newPage._emit(view.View.loadedEvent);

frame._updateActionBar(newPage);

// notify the page
Expand Down
23 changes: 23 additions & 0 deletions ui/page/page.ios.ts
Expand Up @@ -6,6 +6,7 @@ import uiUtils = require("ui/utils");
import utils = require("utils/utils");
import {device} from "platform";
import {DeviceType} from "ui/enums";
import observable = require("data/observable");

global.moduleMerge(pageCommon, exports);

Expand Down Expand Up @@ -94,6 +95,15 @@ class UIViewControllerImpl extends UIViewController {
public viewWillAppear() {
trace.write(this._owner + " viewWillAppear", trace.categories.Navigation);
this._owner._enableLoadedEvents = true;

// In iOS we intentionally delay the raising of the 'loaded' event so both platforms behave identically.
// The loaded event must be raised AFTER the page is part of the windows hierarchy and
// frame.topmost().currentPage is set to the page instance.
// https://github.com/NativeScript/NativeScript/issues/779
if (!this._owner._isModal) {
this._owner._delayLoadedEvent = true;
}

this._owner.onLoaded();
this._owner._enableLoadedEvents = false;
}
Expand All @@ -111,6 +121,7 @@ export class Page extends pageCommon.Page {
public _enableLoadedEvents: boolean;
public _isModal: boolean = false;
public _UIModalPresentationFormSheet: boolean = false;
public _delayLoadedEvent;

constructor(options?: definition.Options) {
super(options);
Expand All @@ -137,6 +148,18 @@ export class Page extends pageCommon.Page {
}
}

public notify<T extends observable.EventData>(data: T) {
// In iOS we intentionally delay the raising of the 'loaded' event so both platforms behave identically.
// The loaded event must be raised AFTER the page is part of the windows hierarchy and
// frame.topmost().currentPage is set to the page instance.
// https://github.com/NativeScript/NativeScript/issues/779
if (data.eventName === View.loadedEvent && this._delayLoadedEvent) {
return;
}

super.notify(data);
}

public onUnloaded() {
// loaded/unloaded events are handled in page viewWillAppear/viewDidDisappear
if (this._enableLoadedEvents) {
Expand Down

0 comments on commit 421845e

Please sign in to comment.