mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 19:26:42 +08:00
Merge remote-tracking branch 'origin/master' into release
This commit is contained in:
@ -225,8 +225,10 @@ git checkout release
|
|||||||
```
|
```
|
||||||
2. Create a PR to cut the release:
|
2. Create a PR to cut the release:
|
||||||
```
|
```
|
||||||
git checkout -b release-version
|
export RELEASE_VERSION=version
|
||||||
git push --set-upstream origin release-version
|
export BRANCH="release-${RELEASE_VERSION}"
|
||||||
|
git checkout -b ${BRANCH}
|
||||||
|
git push --set-upstream origin ${BRANCH}
|
||||||
```
|
```
|
||||||
#### Merge master in release branch or cherry-pick commits. If the commits are in release branch **skip this step**.
|
#### Merge master in release branch or cherry-pick commits. If the commits are in release branch **skip this step**.
|
||||||
```
|
```
|
||||||
@ -266,9 +268,13 @@ git push
|
|||||||
git tag release-version
|
git tag release-version
|
||||||
git push --tags
|
git push --tags
|
||||||
```
|
```
|
||||||
9. Merge PR into release branch.
|
9. Create a pull request. Replace env variables ${RELEASE_VERSION} and ${BRANCH} with their values
|
||||||
|
```
|
||||||
|
curl -d '{"title": "release: cut the ${RELEASE_VERSION} release","body": "docs: update changelog","head": "${BRANCH}","base": "release"}' -X POST https://api.github.com/repos/NativeScript/NativeScript/pulls -H "Authorization: token ${GIT_TOKEN}"
|
||||||
|
```
|
||||||
|
10. Merge PR into release branch.
|
||||||
|
|
||||||
10. If all checks has passed publish package.
|
11. If all checks has passed publish package.
|
||||||
|
|
||||||
## Merge changes from release into master
|
## Merge changes from release into master
|
||||||
|
|
||||||
@ -283,8 +289,9 @@ git pull
|
|||||||
```
|
```
|
||||||
2. Create PR to merge changes back in master and preserve history:
|
2. Create PR to merge changes back in master and preserve history:
|
||||||
```
|
```
|
||||||
git checkout -b merge-release-in-master
|
export MERGE_BRANCH='merge-release-in-master'
|
||||||
git push --set-upstream origin merge-release-in-master
|
git checkout -b ${MERGE_BRANCH}
|
||||||
|
git push --set-upstream origin ${MERGE_BRANCH}
|
||||||
git merge origin/master
|
git merge origin/master
|
||||||
```
|
```
|
||||||
3. Resolve conflicts. Choose to keep the version of master branch. If it is needed to revert versions of modules, see at the bottom.
|
3. Resolve conflicts. Choose to keep the version of master branch. If it is needed to revert versions of modules, see at the bottom.
|
||||||
@ -299,6 +306,11 @@ git commit
|
|||||||
git push
|
git push
|
||||||
```
|
```
|
||||||
|
|
||||||
|
6. Create pull request. Replace replace env ${MERGE_BRANCH} with its value
|
||||||
|
```
|
||||||
|
curl -d '{"title": "chore: merge release in master","body": "chore: merge release in master","head": "merge-release-in-master","base": "master"}' -X POST https://api.github.com/repos/NativeScript/NativeScript/pulls -H "Authorization: token ${GIT_TOKEN}"
|
||||||
|
```
|
||||||
|
|
||||||
**If needed, revert version of modules and platform declarations to take the one from master:**
|
**If needed, revert version of modules and platform declarations to take the one from master:**
|
||||||
```
|
```
|
||||||
git checkout origin/master tns-platform-declarations/package.json tns-core-modules/package.json
|
git checkout origin/master tns-platform-declarations/package.json tns-core-modules/package.json
|
||||||
|
@ -1,46 +1,61 @@
|
|||||||
import { Page } from "tns-core-modules/ui/page";
|
import { Page } from "tns-core-modules/ui/page";
|
||||||
import { Label } from "tns-core-modules/ui/label";
|
import { Label } from "tns-core-modules/ui/label";
|
||||||
|
|
||||||
|
function createCloseCallback(label: Label, context?: string): (username: string, password: string) => void {
|
||||||
|
return function (username: string, password: string) {
|
||||||
|
let result = username + "/" + password;
|
||||||
|
result = context ? context + "/" + result : result;
|
||||||
|
console.log(result);
|
||||||
|
label.text = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openModal(page: Page, label: Label, context: string) {
|
||||||
|
page.showModal("ui-tests-app/modal-view/login-page", {
|
||||||
|
context,
|
||||||
|
closeCallback: createCloseCallback(label, context),
|
||||||
|
fullscreen: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function onTap(args) {
|
export function onTap(args) {
|
||||||
const page = <Page>args.object.page;
|
const page = <Page>args.object.page;
|
||||||
const label = page.getViewById<Label>("label");
|
const label = page.getViewById<Label>("label");
|
||||||
var fullscreen = (<any>args.object).text.indexOf("(full-screen)") !== -1;
|
var fullscreen = (<any>args.object).text.indexOf("(full-screen)") !== -1;
|
||||||
page.showModal("ui-tests-app/modal-view/login-page", "context", function (username: string, password: string) {
|
|
||||||
console.log(username + "/" + password);
|
page.showModal("ui-tests-app/modal-view/login-page", {
|
||||||
label.text = username + "/" + password;
|
context: "context",
|
||||||
}, fullscreen);
|
closeCallback: createCloseCallback(label),
|
||||||
|
fullscreen
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function onTapStretched(args) {
|
export function onTapStretched(args) {
|
||||||
const page = <Page>args.object.page;
|
const page = <Page>args.object.page;
|
||||||
const label = page.getViewById<Label>("label");
|
const label = page.getViewById<Label>("label");
|
||||||
var fullscreen = false;
|
|
||||||
var stretched = true;
|
|
||||||
|
|
||||||
page.showModal("ui-tests-app/modal-view/login-page", "context", function (username: string, password: string) {
|
page.showModal("ui-tests-app/modal-view/login-page", {
|
||||||
console.log(username + "/" + password);
|
context: "context",
|
||||||
label.text = username + "/" + password;
|
closeCallback: createCloseCallback(label),
|
||||||
}, fullscreen, false, stretched);
|
fullscreen: false,
|
||||||
}
|
animated: false,
|
||||||
|
stretched: true
|
||||||
function openModal(page: Page, label: Label, context: string) {
|
});
|
||||||
page.showModal("ui-tests-app/modal-view/login-page", context, function (username: string, password: string) {
|
|
||||||
const result = context + "/" + username + "/" + password;
|
|
||||||
console.log(result);
|
|
||||||
label.text = result;
|
|
||||||
}, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function onTapSecondModalInCB(args) {
|
export function onTapSecondModalInCB(args) {
|
||||||
const page = <Page>args.object.page;
|
const page = <Page>args.object.page;
|
||||||
const label = page.getViewById<Label>("label");
|
const label = page.getViewById<Label>("label");
|
||||||
page.showModal("ui-tests-app/modal-view/login-page", "First", function (username: string, password: string) {
|
page.showModal("ui-tests-app/modal-view/login-page", {
|
||||||
|
context: "First",
|
||||||
|
closeCallback: (username: string, password: string) => {
|
||||||
const result = "First/" + username + "/" + password;
|
const result = "First/" + username + "/" + password;
|
||||||
console.log(result);
|
console.log(result);
|
||||||
label.text = result;
|
label.text = result;
|
||||||
|
|
||||||
// Open second modal in the close callback of the first one.
|
// Open second modal in the close callback of the first one.
|
||||||
openModal(page, label, "Second");
|
openModal(page, label, "Second");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// >> article-require-page-module
|
// >> article-require-page-module
|
||||||
import { Page, ShownModallyData, NavigatedData } from "tns-core-modules/ui/page";
|
import { Page, ShownModallyData, NavigatedData } from "tns-core-modules/ui/page";
|
||||||
// FrameModule is needed in order to have an option to navigate to the new page.
|
// FrameModule is needed in order to have an option to navigate to the new page.
|
||||||
import { topmost, NavigationEntry } from "tns-core-modules/ui/frame";
|
import { topmost, NavigationEntry } from "tns-core-modules/ui/frame";
|
||||||
@ -422,8 +422,7 @@ export function test_WhenPageIsNavigatedToFrameCurrentPageIsNowTheSameAsThePage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function test_WhenInnerViewCallsCloseModal_WithArguments_ShouldPassResult() {
|
export function test_WhenInnerViewCallsCloseModal_WithArguments_ShouldPassResult() {
|
||||||
_test_WhenInnerViewCallsCloseModal((args: ShownModallyData) =>
|
_test_WhenInnerViewCallsCloseModal((args: ShownModallyData) => {
|
||||||
{
|
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
const button = <Button>page.content;
|
const button = <Button>page.content;
|
||||||
return button.closeModal.bind(button);
|
return button.closeModal.bind(button);
|
||||||
@ -431,8 +430,7 @@ export function test_WhenInnerViewCallsCloseModal_WithArguments_ShouldPassResult
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function test_WhenInnerViewCallsCloseModal_WithoutArguments_ShouldWork() {
|
export function test_WhenInnerViewCallsCloseModal_WithoutArguments_ShouldWork() {
|
||||||
_test_WhenInnerViewCallsCloseModal((args: ShownModallyData) =>
|
_test_WhenInnerViewCallsCloseModal((args: ShownModallyData) => {
|
||||||
{
|
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
const button = <Button>page.content;
|
const button = <Button>page.content;
|
||||||
return button.closeModal.bind(button);
|
return button.closeModal.bind(button);
|
||||||
@ -440,15 +438,13 @@ export function test_WhenInnerViewCallsCloseModal_WithoutArguments_ShouldWork()
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function test_WhenInnerViewCallsCloseCallback_WithArguments_ShouldPassResult() {
|
export function test_WhenInnerViewCallsCloseCallback_WithArguments_ShouldPassResult() {
|
||||||
_test_WhenInnerViewCallsCloseModal((args: ShownModallyData) =>
|
_test_WhenInnerViewCallsCloseModal((args: ShownModallyData) => {
|
||||||
{
|
|
||||||
return args.closeCallback;
|
return args.closeCallback;
|
||||||
}, "return value");
|
}, "return value");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function test_WhenInnerViewCallsCloseCallback_WithoutArguments_ShouldWork() {
|
export function test_WhenInnerViewCallsCloseCallback_WithoutArguments_ShouldWork() {
|
||||||
_test_WhenInnerViewCallsCloseModal((args: ShownModallyData) =>
|
_test_WhenInnerViewCallsCloseModal((args: ShownModallyData) => {
|
||||||
{
|
|
||||||
return args.closeCallback;
|
return args.closeCallback;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -460,14 +456,14 @@ function _test_WhenInnerViewCallsCloseModal(closeModalGetter: (ShownModallyData)
|
|||||||
modalClosedWithResult = returnValue === result;
|
modalClosedWithResult = returnValue === result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const modalPageShownModallyEventHandler = function(args: ShownModallyData) {
|
const modalPageShownModallyEventHandler = function (args: ShownModallyData) {
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
page.off(View.shownModallyEvent, modalPageShownModallyEventHandler);
|
page.off(View.shownModallyEvent, modalPageShownModallyEventHandler);
|
||||||
|
|
||||||
closeModalGetter(args)(result);
|
closeModalGetter(args)(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
const hostNavigatedToEventHandler = function(args: NavigatedData) {
|
const hostNavigatedToEventHandler = function (args: NavigatedData) {
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
||||||
|
|
||||||
@ -482,7 +478,7 @@ function _test_WhenInnerViewCallsCloseModal(closeModalGetter: (ShownModallyData)
|
|||||||
(<Button>page.content).showModal(modalPage, {}, modalCloseCallback);
|
(<Button>page.content).showModal(modalPage, {}, modalCloseCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
const masterPageFactory = function(): Page {
|
const masterPageFactory = function (): Page {
|
||||||
const masterPage = new Page();
|
const masterPage = new Page();
|
||||||
masterPage.id = "masterPage_test_WhenInnerViewCallsCloseModal_WithArguments_ShouldPassResult";
|
masterPage.id = "masterPage_test_WhenInnerViewCallsCloseModal_WithArguments_ShouldPassResult";
|
||||||
masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler)
|
masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler)
|
||||||
@ -511,7 +507,7 @@ export function test_WhenViewBaseCallsShowModal_WithArguments_ShouldOpenModal()
|
|||||||
modalClosed = true;
|
modalClosed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const createTabItems = function(count: number) {
|
const createTabItems = function (count: number) {
|
||||||
var items = new Array<TabViewItem>();
|
var items = new Array<TabViewItem>();
|
||||||
|
|
||||||
for (var i = 0; i < count; i++) {
|
for (var i = 0; i < count; i++) {
|
||||||
@ -527,13 +523,13 @@ export function test_WhenViewBaseCallsShowModal_WithArguments_ShouldOpenModal()
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
const modalPageShownModallyEventHandler = function(args: ShownModallyData) {
|
const modalPageShownModallyEventHandler = function (args: ShownModallyData) {
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
page.off(View.shownModallyEvent, modalPageShownModallyEventHandler);
|
page.off(View.shownModallyEvent, modalPageShownModallyEventHandler);
|
||||||
args.closeCallback();
|
args.closeCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
const hostNavigatedToEventHandler = function(args) {
|
const hostNavigatedToEventHandler = function (args) {
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
||||||
|
|
||||||
@ -544,7 +540,7 @@ export function test_WhenViewBaseCallsShowModal_WithArguments_ShouldOpenModal()
|
|||||||
tabViewItem.showModal(modalPage, {}, modalCloseCallback, false, false);
|
tabViewItem.showModal(modalPage, {}, modalCloseCallback, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const masterPageFactory = function(): Page {
|
const masterPageFactory = function (): Page {
|
||||||
const masterPage = new Page();
|
const masterPage = new Page();
|
||||||
masterPage.id = "masterPage_test_WhenViewBaseCallsShowModal_WithArguments_ShouldOpenModal";
|
masterPage.id = "masterPage_test_WhenViewBaseCallsShowModal_WithArguments_ShouldOpenModal";
|
||||||
masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler)
|
masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler)
|
||||||
@ -566,11 +562,14 @@ export function test_WhenViewBaseCallsShowModal_WithArguments_ShouldOpenModal()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function test_WhenViewBaseCallsShowModal_WithoutArguments_ShouldThrow() {
|
export function test_WhenViewBaseCallsShowModal_WithShowModalOptionsArguments_ShouldOpenModal() {
|
||||||
let navigatedTo = false;
|
let modalClosed = false;
|
||||||
let modalThrows = false;
|
|
||||||
|
|
||||||
const createTabItems = function(count: number) {
|
const modalCloseCallback = function (returnValue: any) {
|
||||||
|
modalClosed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const createTabItems = function (count: number) {
|
||||||
var items = new Array<TabViewItem>();
|
var items = new Array<TabViewItem>();
|
||||||
|
|
||||||
for (var i = 0; i < count; i++) {
|
for (var i = 0; i < count; i++) {
|
||||||
@ -586,7 +585,66 @@ export function test_WhenViewBaseCallsShowModal_WithoutArguments_ShouldThrow() {
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hostNavigatedToEventHandler = function(args) {
|
const modalPageShownModallyEventHandler = function (args: ShownModallyData) {
|
||||||
|
const page = <Page>args.object;
|
||||||
|
page.off(View.shownModallyEvent, modalPageShownModallyEventHandler);
|
||||||
|
args.closeCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
const hostNavigatedToEventHandler = function (args) {
|
||||||
|
const page = <Page>args.object;
|
||||||
|
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
||||||
|
|
||||||
|
const modalPage = new Page();
|
||||||
|
modalPage.id = "modalPage_test_WhenViewBaseCallsShowModal_WithShowModalOptionsArguments_ShouldOpenModal";
|
||||||
|
modalPage.on(View.shownModallyEvent, modalPageShownModallyEventHandler);
|
||||||
|
const tabViewItem = (<TabView>page.content).items[0];
|
||||||
|
tabViewItem.showModal(modalPage, {
|
||||||
|
context: {},
|
||||||
|
closeCallback: modalCloseCallback,
|
||||||
|
fullscreen: false,
|
||||||
|
animated: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const masterPageFactory = function (): Page {
|
||||||
|
const masterPage = new Page();
|
||||||
|
masterPage.id = "masterPage_test_WhenViewBaseCallsShowModal_WithShowModalOptionsArguments_ShouldOpenModal";
|
||||||
|
masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler)
|
||||||
|
|
||||||
|
const tabView = new TabView();
|
||||||
|
tabView.items = createTabItems(2);
|
||||||
|
masterPage.content = tabView;
|
||||||
|
|
||||||
|
return masterPage;
|
||||||
|
};
|
||||||
|
|
||||||
|
helper.navigate(masterPageFactory);
|
||||||
|
|
||||||
|
TKUnit.waitUntilReady(() => modalClosed);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function test_WhenViewBaseCallsShowModal_WithoutArguments_ShouldThrow() {
|
||||||
|
let navigatedTo = false;
|
||||||
|
let modalThrows = false;
|
||||||
|
|
||||||
|
const createTabItems = function (count: number) {
|
||||||
|
var items = new Array<TabViewItem>();
|
||||||
|
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
var label = new Label();
|
||||||
|
label.text = "Tab " + i;
|
||||||
|
var tabEntry = new TabViewItem();
|
||||||
|
tabEntry.title = "Tab " + i;
|
||||||
|
tabEntry.view = label;
|
||||||
|
|
||||||
|
items.push(tabEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hostNavigatedToEventHandler = function (args) {
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
||||||
|
|
||||||
@ -601,7 +659,7 @@ export function test_WhenViewBaseCallsShowModal_WithoutArguments_ShouldThrow() {
|
|||||||
navigatedTo = true;
|
navigatedTo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const masterPageFactory = function(): Page {
|
const masterPageFactory = function (): Page {
|
||||||
const masterPage = new Page();
|
const masterPage = new Page();
|
||||||
masterPage.id = "masterPage_test_WhenViewBaseCallsShowModal_WithoutArguments_ShouldThrow";
|
masterPage.id = "masterPage_test_WhenViewBaseCallsShowModal_WithoutArguments_ShouldThrow";
|
||||||
masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler)
|
masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler)
|
||||||
@ -667,7 +725,7 @@ export function test_WhenRootTabViewShownModallyItCanCloseModal() {
|
|||||||
modalClosed = true;
|
modalClosed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const createTabItems = function(count: number) {
|
const createTabItems = function (count: number) {
|
||||||
var items = new Array<TabViewItem>();
|
var items = new Array<TabViewItem>();
|
||||||
|
|
||||||
for (var i = 0; i < count; i++) {
|
for (var i = 0; i < count; i++) {
|
||||||
@ -683,11 +741,11 @@ export function test_WhenRootTabViewShownModallyItCanCloseModal() {
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabViewShownModallyEventHandler = function(args: ShownModallyData) {
|
const tabViewShownModallyEventHandler = function (args: ShownModallyData) {
|
||||||
args.closeCallback("return value");
|
args.closeCallback("return value");
|
||||||
}
|
}
|
||||||
|
|
||||||
const hostNavigatedToEventHandler = function(args) {
|
const hostNavigatedToEventHandler = function (args) {
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
||||||
|
|
||||||
@ -698,7 +756,7 @@ export function test_WhenRootTabViewShownModallyItCanCloseModal() {
|
|||||||
page.showModal(tabView, {}, modalCloseCallback, false, false);
|
page.showModal(tabView, {}, modalCloseCallback, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const masterPageFactory = function(): Page {
|
const masterPageFactory = function (): Page {
|
||||||
const masterPage = new Page();
|
const masterPage = new Page();
|
||||||
masterPage.id = "masterPage_test_WhenRootTabViewShownModallyItCanCloseModal";
|
masterPage.id = "masterPage_test_WhenRootTabViewShownModallyItCanCloseModal";
|
||||||
masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
||||||
@ -832,11 +890,11 @@ export function test_WhenModalPageShownHostPageNavigationEventsShouldNotBeRaised
|
|||||||
hostNavigatedFromCount++;
|
hostNavigatedFromCount++;
|
||||||
};
|
};
|
||||||
|
|
||||||
const modalPageShownModallyEventHandler = function() {
|
const modalPageShownModallyEventHandler = function () {
|
||||||
TKUnit.assertEqual(stack().length, 1, "Single frame should be instantiated at this point!");
|
TKUnit.assertEqual(stack().length, 1, "Single frame should be instantiated at this point!");
|
||||||
}
|
}
|
||||||
|
|
||||||
const hostNavigatedToEventHandler2 = function(args: NavigatedData) {
|
const hostNavigatedToEventHandler2 = function (args: NavigatedData) {
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler2);
|
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler2);
|
||||||
|
|
||||||
@ -915,7 +973,7 @@ export function test_WhenModalPageShownModalNavigationToEventsShouldBeRaised() {
|
|||||||
modalNavigatedFromCount++;
|
modalNavigatedFromCount++;
|
||||||
};
|
};
|
||||||
|
|
||||||
const modalFrameShownModallyEventHandler = function(args) {
|
const modalFrameShownModallyEventHandler = function (args) {
|
||||||
const basePath = "ui/page/";
|
const basePath = "ui/page/";
|
||||||
const entry: NavigationEntry = {
|
const entry: NavigationEntry = {
|
||||||
moduleName: basePath + "modal-page"
|
moduleName: basePath + "modal-page"
|
||||||
@ -932,7 +990,7 @@ export function test_WhenModalPageShownModalNavigationToEventsShouldBeRaised() {
|
|||||||
|
|
||||||
let modalFrame;
|
let modalFrame;
|
||||||
|
|
||||||
const hostNavigatedToEventHandler = function(args) {
|
const hostNavigatedToEventHandler = function (args) {
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
||||||
|
|
||||||
@ -981,11 +1039,11 @@ export function test_WhenModalFrameShownModalEventsRaisedOnRootModalFrame() {
|
|||||||
ready = true;
|
ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const modalFrameShowingModallyEventHandler = function(args: ShownModallyData) {
|
const modalFrameShowingModallyEventHandler = function (args: ShownModallyData) {
|
||||||
showingModallyCount++;
|
showingModallyCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const modalFrameShownModallyEventHandler = function(args: ShownModallyData) {
|
const modalFrameShownModallyEventHandler = function (args: ShownModallyData) {
|
||||||
shownModallyCount++;
|
shownModallyCount++;
|
||||||
TKUnit.assertEqual(stack().length, 2, "Host and modal frame should be instantiated at this point!");
|
TKUnit.assertEqual(stack().length, 2, "Host and modal frame should be instantiated at this point!");
|
||||||
|
|
||||||
@ -994,7 +1052,7 @@ export function test_WhenModalFrameShownModalEventsRaisedOnRootModalFrame() {
|
|||||||
|
|
||||||
let modalFrame;
|
let modalFrame;
|
||||||
|
|
||||||
const hostNavigatedToEventHandler = function(args) {
|
const hostNavigatedToEventHandler = function (args) {
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
||||||
|
|
||||||
@ -1051,11 +1109,11 @@ export function test_WhenModalPageShownShowModalEventsRaisedOnRootModalPage() {
|
|||||||
ready = true;
|
ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const modalPageShowingModallyEventHandler = function(args: ShownModallyData) {
|
const modalPageShowingModallyEventHandler = function (args: ShownModallyData) {
|
||||||
showingModallyCount++;
|
showingModallyCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const modalPageShownModallyEventHandler = function(args: ShownModallyData) {
|
const modalPageShownModallyEventHandler = function (args: ShownModallyData) {
|
||||||
shownModallyCount++;
|
shownModallyCount++;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -1063,7 +1121,7 @@ export function test_WhenModalPageShownShowModalEventsRaisedOnRootModalPage() {
|
|||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const hostNavigatedToEventHandler = function(args) {
|
const hostNavigatedToEventHandler = function (args) {
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
||||||
|
|
||||||
@ -1114,15 +1172,15 @@ export function test_WhenModalPageShownShowModalEventsRaisedOnRootModalTabView()
|
|||||||
setTimeout(() => ready = true, 50);
|
setTimeout(() => ready = true, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
const modalTabViewShowingModallyEventHandler = function(args: ShownModallyData) {
|
const modalTabViewShowingModallyEventHandler = function (args: ShownModallyData) {
|
||||||
showingModallyCount++;
|
showingModallyCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const modalTabViewShownModallyEventHandler = function(args: ShownModallyData) {
|
const modalTabViewShownModallyEventHandler = function (args: ShownModallyData) {
|
||||||
shownModallyCount++;
|
shownModallyCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hostNavigatedToEventHandler = function(args) {
|
const hostNavigatedToEventHandler = function (args) {
|
||||||
const page = <Page>args.object;
|
const page = <Page>args.object;
|
||||||
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
||||||
|
|
||||||
@ -1139,7 +1197,7 @@ export function test_WhenModalPageShownShowModalEventsRaisedOnRootModalTabView()
|
|||||||
|
|
||||||
TKUnit.assertEqual(stack().length, 2, "Host and tab modal frame should be instantiated at this point!");
|
TKUnit.assertEqual(stack().length, 2, "Host and tab modal frame should be instantiated at this point!");
|
||||||
|
|
||||||
page.showModal(modalTabView, { }, modalCloseCallback, false, false);
|
page.showModal(modalTabView, {}, modalCloseCallback, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const masterPageFactory = function (): Page {
|
const masterPageFactory = function (): Page {
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
import * as TKUnit from "../../TKUnit";
|
import * as TKUnit from "../../TKUnit";
|
||||||
import * as helper from "../helper";
|
import * as helper from "../helper";
|
||||||
import { Page } from "tns-core-modules/ui/page";
|
import { Page } from "tns-core-modules/ui/page";
|
||||||
|
import { isAndroid } from "tns-core-modules/platform";
|
||||||
import { Frame, NavigationEntry, stack } from "tns-core-modules/ui/frame";
|
import { Frame, NavigationEntry, stack } from "tns-core-modules/ui/frame";
|
||||||
import { _resetRootView, getRootView } from "tns-core-modules/application";
|
import { _resetRootView, getRootView } from "tns-core-modules/application";
|
||||||
import { TabView, TabViewItem } from "tns-core-modules/ui/tab-view";
|
import { TabView, TabViewItem } from "tns-core-modules/ui/tab-view";
|
||||||
|
|
||||||
|
function waitUntilTabViewReady(page: Page, action: Function) {
|
||||||
|
helper.waitUntilNavigatedTo(page, action);
|
||||||
|
|
||||||
|
if (isAndroid) {
|
||||||
|
TKUnit.waitUntilReady(() => page.frame._currentEntry.fragment.isAdded());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function createTestFrameRootEntry() {
|
function createTestFrameRootEntry() {
|
||||||
const page = new Page();
|
const page = new Page();
|
||||||
const frameRoot = new Frame();
|
const frameRoot = new Frame();
|
||||||
@ -77,7 +86,7 @@ export function test_reset_frame_to_tab() {
|
|||||||
|
|
||||||
const testTabRoot = createTestTabRootEntry();
|
const testTabRoot = createTestTabRootEntry();
|
||||||
|
|
||||||
helper.waitUntilNavigatedTo(testTabRoot.page, () => _resetRootView(testTabRoot.entry));
|
waitUntilTabViewReady(testTabRoot.page, () => _resetRootView(testTabRoot.entry));
|
||||||
|
|
||||||
const rootView2 = getRootView();
|
const rootView2 = getRootView();
|
||||||
const frameStack2 = stack();
|
const frameStack2 = stack();
|
||||||
@ -88,7 +97,7 @@ export function test_reset_frame_to_tab() {
|
|||||||
export function test_reset_tab_to_frame() {
|
export function test_reset_tab_to_frame() {
|
||||||
const testTabRoot = createTestTabRootEntry();
|
const testTabRoot = createTestTabRootEntry();
|
||||||
|
|
||||||
helper.waitUntilNavigatedTo(testTabRoot.page, () => _resetRootView(testTabRoot.entry));
|
waitUntilTabViewReady(testTabRoot.page, () => _resetRootView(testTabRoot.entry));
|
||||||
|
|
||||||
const rootView2 = getRootView();
|
const rootView2 = getRootView();
|
||||||
const frameStack2 = stack();
|
const frameStack2 = stack();
|
||||||
@ -108,7 +117,7 @@ export function test_reset_tab_to_frame() {
|
|||||||
export function test_reset_tab_to_tab() {
|
export function test_reset_tab_to_tab() {
|
||||||
const testTabRoot1 = createTestTabRootEntry();
|
const testTabRoot1 = createTestTabRootEntry();
|
||||||
|
|
||||||
helper.waitUntilNavigatedTo(testTabRoot1.page, () => _resetRootView(testTabRoot1.entry));
|
waitUntilTabViewReady(testTabRoot1.page, () => _resetRootView(testTabRoot1.entry));
|
||||||
|
|
||||||
const rootView1 = getRootView();
|
const rootView1 = getRootView();
|
||||||
const frameStack1 = stack();
|
const frameStack1 = stack();
|
||||||
@ -117,7 +126,7 @@ export function test_reset_tab_to_tab() {
|
|||||||
|
|
||||||
const testTabRoot2 = createTestTabRootEntry();
|
const testTabRoot2 = createTestTabRootEntry();
|
||||||
|
|
||||||
helper.waitUntilNavigatedTo(testTabRoot2.page, () => _resetRootView(testTabRoot2.entry));
|
waitUntilTabViewReady(testTabRoot2.page, () => _resetRootView(testTabRoot2.entry));
|
||||||
|
|
||||||
const rootView2 = getRootView();
|
const rootView2 = getRootView();
|
||||||
const frameStack2 = stack();
|
const frameStack2 = stack();
|
||||||
@ -128,7 +137,7 @@ export function test_reset_tab_to_tab() {
|
|||||||
export function test_reset_during_tab_index_change() {
|
export function test_reset_during_tab_index_change() {
|
||||||
const testTabRoot = createTestTabRootEntry();
|
const testTabRoot = createTestTabRootEntry();
|
||||||
|
|
||||||
helper.waitUntilNavigatedTo(testTabRoot.page, () => _resetRootView(testTabRoot.entry));
|
waitUntilTabViewReady(testTabRoot.page, () => _resetRootView(testTabRoot.entry));
|
||||||
|
|
||||||
testTabRoot.root.selectedIndex = 1;
|
testTabRoot.root.selectedIndex = 1;
|
||||||
|
|
||||||
|
@ -18,6 +18,16 @@ function waitUntilNavigatedToMaxTimeout(pages: Page[], action: Function) {
|
|||||||
TKUnit.waitUntilReady(() => completed === pages.length, maxTimeout);
|
TKUnit.waitUntilReady(() => completed === pages.length, maxTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function waitUntilTabViewReady(page: Page, action: Function) {
|
||||||
|
action();
|
||||||
|
|
||||||
|
if (isAndroid) {
|
||||||
|
TKUnit.waitUntilReady(() => page.frame._currentEntry.fragment.isAdded());
|
||||||
|
} else {
|
||||||
|
TKUnit.waitUntilReady(() => page.isLoaded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function createPage(i: number) {
|
function createPage(i: number) {
|
||||||
const page = new Page();
|
const page = new Page();
|
||||||
page.id = `Tab${i} Frame${i} Page${i}`;
|
page.id = `Tab${i} Frame${i} Page${i}`;
|
||||||
@ -60,25 +70,21 @@ export function test_frame_topmost_matches_selectedIndex() {
|
|||||||
const items = createTabItemsWithFrames(3);
|
const items = createTabItemsWithFrames(3);
|
||||||
const tabView = new TabView();
|
const tabView = new TabView();
|
||||||
tabView.items = items.map(item => item.tabItem);
|
tabView.items = items.map(item => item.tabItem);
|
||||||
tabView.selectedIndex = 0;
|
|
||||||
|
// iOS cannot preload tab items
|
||||||
|
// Android preloads 1 tab item to the sides by default
|
||||||
|
// set this to 0, so that both platforms behave the same.
|
||||||
|
tabView.androidOffscreenTabLimit = 0;
|
||||||
|
|
||||||
const entry: NavigationEntry = {
|
const entry: NavigationEntry = {
|
||||||
create: () => tabView
|
create: () => tabView
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isAndroid) {
|
|
||||||
waitUntilNavigatedToMaxTimeout([items[0].page, items[1].page], () => _resetRootView(entry));
|
|
||||||
TKUnit.assertEqual(topmost().id, "Tab0 Frame0");
|
|
||||||
|
|
||||||
tabView.selectedIndex = 1;
|
|
||||||
TKUnit.assertEqual(topmost().id, "Tab1 Frame1");
|
|
||||||
} else {
|
|
||||||
waitUntilNavigatedToMaxTimeout([items[0].page], () => _resetRootView(entry));
|
waitUntilNavigatedToMaxTimeout([items[0].page], () => _resetRootView(entry));
|
||||||
TKUnit.assertEqual(topmost().id, "Tab0 Frame0");
|
TKUnit.assertEqual(topmost().id, "Tab0 Frame0");
|
||||||
|
|
||||||
waitUntilNavigatedToMaxTimeout([items[1].page], () => tabView.selectedIndex = 1);
|
waitUntilNavigatedToMaxTimeout([items[1].page], () => tabView.selectedIndex = 1);
|
||||||
TKUnit.assertEqual(topmost().id, "Tab1 Frame1");
|
TKUnit.assertEqual(topmost().id, "Tab1 Frame1");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function test_offset_zero_should_raise_same_events() {
|
export function test_offset_zero_should_raise_same_events() {
|
||||||
@ -159,8 +165,8 @@ export function test_offset_zero_should_raise_same_events() {
|
|||||||
TKUnit.assertDeepEqual(actualEventsRaised, expectedEventsRaisedAfterSelectThirdTab);
|
TKUnit.assertDeepEqual(actualEventsRaised, expectedEventsRaisedAfterSelectThirdTab);
|
||||||
|
|
||||||
resetActualEventsRaised();
|
resetActualEventsRaised();
|
||||||
tabView.selectedIndex = 0;
|
|
||||||
TKUnit.waitUntilReady(() => items[0].page.isLoaded);
|
waitUntilTabViewReady(items[0].page, () => tabView.selectedIndex = 0);
|
||||||
|
|
||||||
const expectedEventsRaisedAfterReturnToFirstTab = [
|
const expectedEventsRaisedAfterReturnToFirstTab = [
|
||||||
[
|
[
|
||||||
@ -256,8 +262,8 @@ export function test_android_default_offset_should_preload_1_tab_on_each_side()
|
|||||||
TKUnit.assertDeepEqual(actualEventsRaised, expectedEventsRaisedAfterSelectThirdTab);
|
TKUnit.assertDeepEqual(actualEventsRaised, expectedEventsRaisedAfterSelectThirdTab);
|
||||||
|
|
||||||
resetActualEventsRaised();
|
resetActualEventsRaised();
|
||||||
tabView.selectedIndex = 0;
|
|
||||||
TKUnit.waitUntilReady(() => items[0].page.isLoaded);
|
waitUntilTabViewReady(items[0].page, () => tabView.selectedIndex = 0);
|
||||||
|
|
||||||
const expectedEventsRaisedAfterReturnToFirstTab = [
|
const expectedEventsRaisedAfterReturnToFirstTab = [
|
||||||
[
|
[
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
"nativescript": {
|
"nativescript": {
|
||||||
"id": "org.nativescript.UnitTestApp",
|
"id": "org.nativescript.UnitTestApp",
|
||||||
"tns-ios": {
|
"tns-ios": {
|
||||||
"version": "5.0.0"
|
"version": "5.1.0"
|
||||||
},
|
},
|
||||||
"tns-android": {
|
"tns-android": {
|
||||||
"version": "5.0.0"
|
"version": "5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -21,9 +21,20 @@ import { Frame, NavigationEntry } from "../ui/frame";
|
|||||||
import * as utils from "../utils/utils";
|
import * as utils from "../utils/utils";
|
||||||
import { profile, level as profilingLevel, Level } from "../profiling";
|
import { profile, level as profilingLevel, Level } from "../profiling";
|
||||||
|
|
||||||
class Responder extends UIResponder {
|
// NOTE: UIResponder with implementation of window - related to https://github.com/NativeScript/ios-runtime/issues/430
|
||||||
//
|
// TODO: Refactor the UIResponder to use Typescript extends when this issue is resolved:
|
||||||
}
|
// https://github.com/NativeScript/ios-runtime/issues/1012
|
||||||
|
var Responder = (<any>UIResponder).extend({
|
||||||
|
get window() {
|
||||||
|
return iosApp ? iosApp.window : undefined;
|
||||||
|
},
|
||||||
|
set window(setWindow) {
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
protocols: [UIApplicationDelegate]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
class NotificationObserver extends NSObject {
|
class NotificationObserver extends NSObject {
|
||||||
private _onReceiveCallback: (notification: NSNotification) => void;
|
private _onReceiveCallback: (notification: NSNotification) => void;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "tns-core-modules",
|
"name": "tns-core-modules",
|
||||||
"description": "Telerik NativeScript Core Modules",
|
"description": "Telerik NativeScript Core Modules",
|
||||||
"version": "5.1.0",
|
"version": "5.2.0",
|
||||||
"homepage": "https://www.nativescript.org",
|
"homepage": "https://www.nativescript.org",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -26,7 +26,7 @@
|
|||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"typings": "tns-core-modules.d.ts",
|
"typings": "tns-core-modules.d.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tns-core-modules-widgets": "5.1.1",
|
"tns-core-modules-widgets": "next",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -46,6 +46,43 @@ export function isEventOrGesture(name: string, view: ViewBase): boolean;
|
|||||||
*/
|
*/
|
||||||
export function getViewById(view: ViewBase, id: string): ViewBase;
|
export function getViewById(view: ViewBase, id: string): ViewBase;
|
||||||
|
|
||||||
|
export interface ShowModalOptions {
|
||||||
|
/**
|
||||||
|
* Any context you want to pass to the modally shown view. This same context will be available in the arguments of the shownModally event handler.
|
||||||
|
*/
|
||||||
|
context: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function that will be called when the view is closed. Any arguments provided when calling ShownModallyData.closeCallback will be available here.
|
||||||
|
*/
|
||||||
|
closeCallback: Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional parameter specifying whether to show the modal view in full-screen mode.
|
||||||
|
*/
|
||||||
|
fullscreen?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional parameter specifying whether to show the modal view with animation.
|
||||||
|
*/
|
||||||
|
animated?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional parameter specifying whether to stretch the modal view when not in full-screen mode.
|
||||||
|
*/
|
||||||
|
stretched?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional parameter that specify options specific to iOS as an object.
|
||||||
|
*/
|
||||||
|
ios?: {
|
||||||
|
/**
|
||||||
|
* The UIModalPresentationStyle to be used when showing the dialog in iOS .
|
||||||
|
*/
|
||||||
|
presentationStyle: any /* UIModalPresentationStyle */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class ViewBase extends Observable {
|
export abstract class ViewBase extends Observable {
|
||||||
// Dynamic properties.
|
// Dynamic properties.
|
||||||
left: Length;
|
left: Length;
|
||||||
@ -110,6 +147,7 @@ export abstract class ViewBase extends Observable {
|
|||||||
//@endprivate
|
//@endprivate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @deprecated Use showModal with ShowModalOptions instead.
|
||||||
* Shows the View contained in moduleName as a modal view.
|
* Shows the View contained in moduleName as a modal view.
|
||||||
* @param moduleName - The name of the module to load starting from the application root.
|
* @param moduleName - The name of the module to load starting from the application root.
|
||||||
* @param context - Any context you want to pass to the modally shown view.
|
* @param context - Any context you want to pass to the modally shown view.
|
||||||
@ -123,6 +161,7 @@ export abstract class ViewBase extends Observable {
|
|||||||
showModal(moduleName: string, context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean): ViewBase;
|
showModal(moduleName: string, context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean): ViewBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @deprecated Use showModal with ShowModalOptions instead.
|
||||||
* Shows the view passed as parameter as a modal view.
|
* Shows the view passed as parameter as a modal view.
|
||||||
* @param view - View instance to be shown modally.
|
* @param view - View instance to be shown modally.
|
||||||
* @param context - Any context you want to pass to the modally shown view. This same context will be available in the arguments of the shownModally event handler.
|
* @param context - Any context you want to pass to the modally shown view. This same context will be available in the arguments of the shownModally event handler.
|
||||||
@ -133,6 +172,20 @@ export abstract class ViewBase extends Observable {
|
|||||||
*/
|
*/
|
||||||
showModal(view: ViewBase, context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean): ViewBase;
|
showModal(view: ViewBase, context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean): ViewBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the View contained in moduleName as a modal view.
|
||||||
|
* @param moduleName - The name of the module to load starting from the application root.
|
||||||
|
* @param modalOptions - A ShowModalOptions instance
|
||||||
|
*/
|
||||||
|
showModal(moduleName: string, modalOptions: ShowModalOptions): ViewBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the view passed as parameter as a modal view.
|
||||||
|
* @param view - View instance to be shown modally.
|
||||||
|
* @param modalOptions - A ShowModalOptions instance
|
||||||
|
*/
|
||||||
|
showModal(view: ViewBase, modalOptions: ShowModalOptions): ViewBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deprecated. Showing view as modal is deprecated.
|
* Deprecated. Showing view as modal is deprecated.
|
||||||
* Use showModal method with arguments.
|
* Use showModal method with arguments.
|
||||||
|
@ -7,7 +7,8 @@ import {
|
|||||||
import {
|
import {
|
||||||
ViewBase, Property, booleanConverter, EventData, layout,
|
ViewBase, Property, booleanConverter, EventData, layout,
|
||||||
getEventOrGestureName, traceEnabled, traceWrite, traceCategories,
|
getEventOrGestureName, traceEnabled, traceWrite, traceCategories,
|
||||||
InheritedProperty
|
InheritedProperty,
|
||||||
|
ShowModalOptions
|
||||||
} from "../view-base";
|
} from "../view-base";
|
||||||
|
|
||||||
import { HorizontalAlignment, VerticalAlignment, Visibility, Length, PercentLength } from "../../styling/style-properties";
|
import { HorizontalAlignment, VerticalAlignment, Visibility, Length, PercentLength } from "../../styling/style-properties";
|
||||||
@ -215,23 +216,39 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public showModal(): ViewDefinition {
|
private getModalOptions(args: IArguments): { view: ViewCommon, options: ShowModalOptions } {
|
||||||
if (arguments.length === 0) {
|
if (args.length === 0) {
|
||||||
throw new Error("showModal without parameters is deprecated. Please call showModal on a view instance instead.");
|
throw new Error("showModal without parameters is deprecated. Please call showModal on a view instance instead.");
|
||||||
} else {
|
} else {
|
||||||
const firstAgrument = arguments[0];
|
let options: ShowModalOptions = null;
|
||||||
const context: any = arguments[1];
|
|
||||||
const closeCallback: Function = arguments[2];
|
|
||||||
const fullscreen: boolean = arguments[3];
|
|
||||||
const animated = arguments[4];
|
|
||||||
const stretched = arguments[5];
|
|
||||||
|
|
||||||
const view = firstAgrument instanceof ViewCommon
|
if (args.length === 2) {
|
||||||
? firstAgrument : <ViewCommon>createViewFromEntry({ moduleName: firstAgrument });
|
options = <ShowModalOptions>args[1];
|
||||||
|
} else {
|
||||||
view._showNativeModalView(this, context, closeCallback, fullscreen, animated, stretched);
|
// TODO: Add deprecation warning
|
||||||
return view;
|
options = {
|
||||||
|
context: args[1],
|
||||||
|
closeCallback: args[2],
|
||||||
|
fullscreen: args[3],
|
||||||
|
animated: args[4],
|
||||||
|
stretched: args[5]
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const firstArgument = args[0];
|
||||||
|
const view = firstArgument instanceof ViewCommon
|
||||||
|
? firstArgument : <ViewCommon>createViewFromEntry({ moduleName: firstArgument });
|
||||||
|
|
||||||
|
return { view, options };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public showModal(): ViewDefinition {
|
||||||
|
const { view, options } = this.getModalOptions(arguments);
|
||||||
|
|
||||||
|
view._showNativeModalView(this, options);
|
||||||
|
|
||||||
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeModal(...args) {
|
public closeModal(...args) {
|
||||||
@ -250,12 +267,12 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
|||||||
return this._modal;
|
return this._modal;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _showNativeModalView(parent: ViewCommon, context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean) {
|
protected _showNativeModalView(parent: ViewCommon, options: ShowModalOptions) { //context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean, iosOpts?: any) {
|
||||||
_rootModalViews.push(this);
|
_rootModalViews.push(this);
|
||||||
|
|
||||||
parent._modal = this;
|
parent._modal = this;
|
||||||
this._modalParent = parent;
|
this._modalParent = parent;
|
||||||
this._modalContext = context;
|
this._modalContext = options.context;
|
||||||
const that = this;
|
const that = this;
|
||||||
this._closeModalCallback = function (...originalArgs) {
|
this._closeModalCallback = function (...originalArgs) {
|
||||||
if (that._closeModalCallback) {
|
if (that._closeModalCallback) {
|
||||||
@ -268,8 +285,8 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
|||||||
parent._modal = null;
|
parent._modal = null;
|
||||||
|
|
||||||
const whenClosedCallback = () => {
|
const whenClosedCallback = () => {
|
||||||
if (typeof closeCallback === "function") {
|
if (typeof options.closeCallback === "function") {
|
||||||
closeCallback.apply(undefined, originalArgs);
|
options.closeCallback.apply(undefined, originalArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty,
|
ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty,
|
||||||
traceEnabled, traceWrite, traceCategories, traceNotifyEvent,
|
traceEnabled, traceWrite, traceCategories, traceNotifyEvent,
|
||||||
paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty,
|
paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty,
|
||||||
Color, EventData
|
Color, EventData, ShowModalOptions
|
||||||
} from "./view-common";
|
} from "./view-common";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -574,9 +574,8 @@ export class View extends ViewCommon {
|
|||||||
|
|
||||||
return result | (childMeasuredState & layout.MEASURED_STATE_MASK);
|
return result | (childMeasuredState & layout.MEASURED_STATE_MASK);
|
||||||
}
|
}
|
||||||
|
protected _showNativeModalView(parent: View, options: ShowModalOptions) { //context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean, iosOpts?: any) {
|
||||||
protected _showNativeModalView(parent: View, context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean) {
|
super._showNativeModalView(parent, options);
|
||||||
super._showNativeModalView(parent, context, closeCallback, fullscreen, stretched);
|
|
||||||
if (!this.backgroundColor) {
|
if (!this.backgroundColor) {
|
||||||
this.backgroundColor = new Color("White");
|
this.backgroundColor = new Color("White");
|
||||||
}
|
}
|
||||||
@ -590,8 +589,8 @@ export class View extends ViewCommon {
|
|||||||
|
|
||||||
const dialogOptions: DialogOptions = {
|
const dialogOptions: DialogOptions = {
|
||||||
owner: this,
|
owner: this,
|
||||||
fullscreen: !!fullscreen,
|
fullscreen: !!options.fullscreen,
|
||||||
stretched: !!stretched,
|
stretched: !!options.stretched,
|
||||||
shownCallback: () => this._raiseShownModallyEvent(),
|
shownCallback: () => this._raiseShownModallyEvent(),
|
||||||
dismissCallback: () => this.closeModal()
|
dismissCallback: () => this.closeModal()
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import { booleanConverter, Property } from "../view";
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty,
|
ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty,
|
||||||
traceEnabled, traceWrite, traceCategories, traceError, traceMessageType, getAncestor
|
traceEnabled, traceWrite, traceCategories, traceError, traceMessageType, ShowModalOptions
|
||||||
} from "./view-common";
|
} from "./view-common";
|
||||||
|
|
||||||
import { ios as iosBackground, Background } from "../../styling/background";
|
import { ios as iosBackground, Background } from "../../styling/background";
|
||||||
@ -371,7 +371,7 @@ export class View extends ViewCommon {
|
|||||||
return this._suspendCATransaction || this._suspendNativeUpdatesCount;
|
return this._suspendCATransaction || this._suspendNativeUpdatesCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _showNativeModalView(parent: View, context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean) {
|
protected _showNativeModalView(parent: View, options: ShowModalOptions) { //context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean, iosOpts?: any) {
|
||||||
const parentWithController = ios.getParentWithViewController(parent);
|
const parentWithController = ios.getParentWithViewController(parent);
|
||||||
if (!parentWithController) {
|
if (!parentWithController) {
|
||||||
traceWrite(`Could not find parent with viewController for ${parent} while showing modal view.`,
|
traceWrite(`Could not find parent with viewController for ${parent} while showing modal view.`,
|
||||||
@ -394,7 +394,7 @@ export class View extends ViewCommon {
|
|||||||
|
|
||||||
this._setupAsRootView({});
|
this._setupAsRootView({});
|
||||||
|
|
||||||
super._showNativeModalView(parentWithController, context, closeCallback, fullscreen, stretched);
|
super._showNativeModalView(parentWithController, options);
|
||||||
let controller = this.viewController;
|
let controller = this.viewController;
|
||||||
if (!controller) {
|
if (!controller) {
|
||||||
const nativeView = this.ios || this.nativeViewProtected;
|
const nativeView = this.ios || this.nativeViewProtected;
|
||||||
@ -407,17 +407,31 @@ export class View extends ViewCommon {
|
|||||||
this.viewController = controller;
|
this.viewController = controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fullscreen) {
|
if (options.fullscreen) {
|
||||||
controller.modalPresentationStyle = UIModalPresentationStyle.FullScreen;
|
controller.modalPresentationStyle = UIModalPresentationStyle.FullScreen;
|
||||||
} else {
|
} else {
|
||||||
controller.modalPresentationStyle = UIModalPresentationStyle.FormSheet;
|
controller.modalPresentationStyle = UIModalPresentationStyle.FormSheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.ios && options.ios.presentationStyle) {
|
||||||
|
const presentationStyle = options.ios.presentationStyle;
|
||||||
|
controller.modalPresentationStyle = presentationStyle;
|
||||||
|
|
||||||
|
if (presentationStyle === UIModalPresentationStyle.Popover) {
|
||||||
|
const popoverPresentationController = controller.popoverPresentationController;
|
||||||
|
const view = parent.nativeViewProtected;
|
||||||
|
// Note: sourceView and sourceRect are needed to specify the anchor location for the popover.
|
||||||
|
// Note: sourceView should be the button triggering the modal. If it the Page the popover might appear "behind" the page content
|
||||||
|
popoverPresentationController.sourceView = view;
|
||||||
|
popoverPresentationController.sourceRect = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.horizontalAlignment = "stretch";
|
this.horizontalAlignment = "stretch";
|
||||||
this.verticalAlignment = "stretch";
|
this.verticalAlignment = "stretch";
|
||||||
|
|
||||||
this._raiseShowingModallyEvent();
|
this._raiseShowingModallyEvent();
|
||||||
animated = animated === undefined ? true : !!animated;
|
const animated = options.animated === undefined ? true : !!options.animated;
|
||||||
(<any>controller).animated = animated;
|
(<any>controller).animated = animated;
|
||||||
parentController.presentViewControllerAnimatedCompletion(controller, animated, null);
|
parentController.presentViewControllerAnimatedCompletion(controller, animated, null);
|
||||||
const transitionCoordinator = iosUtils.getter(parentController, parentController.transitionCoordinator);
|
const transitionCoordinator = iosUtils.getter(parentController, parentController.transitionCoordinator);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { AndroidFragmentCallbacks, setFragmentCallbacks, setFragmentClass } from "./frame";
|
import { AndroidFragmentCallbacks, setFragmentCallbacks, setFragmentClass } from "./frame";
|
||||||
|
|
||||||
@JavaProxy("com.tns.FragmentClass")
|
@JavaProxy("com.tns.FragmentClass")
|
||||||
class FragmentClass extends android.support.v4.app.Fragment {
|
class FragmentClass extends org.nativescript.widgets.FragmentBase {
|
||||||
// This field is updated in the frame module upon `new` (although hacky this eases the Fragment->callbacks association a lot)
|
// This field is updated in the frame module upon `new` (although hacky this eases the Fragment->callbacks association a lot)
|
||||||
private _callbacks: AndroidFragmentCallbacks;
|
private _callbacks: AndroidFragmentCallbacks;
|
||||||
|
|
||||||
@ -15,8 +15,7 @@ class FragmentClass extends android.support.v4.app.Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onCreateAnimator(transit: number, enter: boolean, nextAnim: number): android.animation.Animator {
|
public onCreateAnimator(transit: number, enter: boolean, nextAnim: number): android.animation.Animator {
|
||||||
let result = this._callbacks.onCreateAnimator(this, transit, enter, nextAnim, super.onCreateAnimator);
|
return this._callbacks.onCreateAnimator(this, transit, enter, nextAnim, super.onCreateAnimator);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onStop(): void {
|
public onStop(): void {
|
||||||
|
@ -86,7 +86,20 @@ export function _setAndroidFragmentTransitions(
|
|||||||
name = navigationTransition.name ? navigationTransition.name.toLowerCase() : "";
|
name = navigationTransition.name ? navigationTransition.name.toLowerCase() : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
let useLollipopTransition = name && (name.indexOf("slide") === 0 || name === "fade" || name === "explode") && sdkVersion() >= 21;
|
let useLollipopTransition = !!(name && (name.indexOf("slide") === 0 || name === "fade" || name === "explode") && sdkVersion() >= 21);
|
||||||
|
// [nested frames / fragments] force disable lollipop transitions in case nested fragments
|
||||||
|
// are detected as applying dummy animator to the nested fragment with the same duration as
|
||||||
|
// the exit animator of the removing parent fragment as a workaround for
|
||||||
|
// https://code.google.com/p/android/issues/detail?id=55228 works only if custom animations are
|
||||||
|
// used
|
||||||
|
// NOTE: this effectively means you cannot use Explode transition in nested frames scenarios as
|
||||||
|
// we have implementations only for slide, fade, and flip
|
||||||
|
if (currentFragment &&
|
||||||
|
currentFragment.getChildFragmentManager() &&
|
||||||
|
currentFragment.getChildFragmentManager().getFragments().toArray().length > 0) {
|
||||||
|
useLollipopTransition = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!animated) {
|
if (!animated) {
|
||||||
name = "none";
|
name = "none";
|
||||||
} else if (transition) {
|
} else if (transition) {
|
||||||
|
@ -457,8 +457,8 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public _onRootViewReset(): void {
|
public _onRootViewReset(): void {
|
||||||
this._removeFromFrameStack();
|
|
||||||
super._onRootViewReset();
|
super._onRootViewReset();
|
||||||
|
this._removeFromFrameStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
get _childrenCount(): number {
|
get _childrenCount(): number {
|
||||||
|
@ -209,8 +209,12 @@ export class Frame extends FrameBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public _onRootViewReset(): void {
|
public _onRootViewReset(): void {
|
||||||
this.disposeCurrentFragment();
|
|
||||||
super._onRootViewReset();
|
super._onRootViewReset();
|
||||||
|
|
||||||
|
// call this AFTER the super call to ensure descendants apply their rootview-reset logic first
|
||||||
|
// i.e. in a scenario with nested frames / frame with tabview let the descendandt cleanup the inner
|
||||||
|
// fragments first, and then cleanup the parent fragments
|
||||||
|
this.disposeCurrentFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
onUnloaded() {
|
onUnloaded() {
|
||||||
@ -223,11 +227,6 @@ export class Frame extends FrameBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private disposeCurrentFragment(): void {
|
private disposeCurrentFragment(): void {
|
||||||
// when interacting with nested fragments it seems Android is smart enough
|
|
||||||
// to automatically remove child fragments when parent fragment is removed;
|
|
||||||
// however, we must add a fragment.isAdded() guard as our logic will try to
|
|
||||||
// explicitly remove the already removed child fragment causing an
|
|
||||||
// IllegalStateException: Fragment has not been attached yet.
|
|
||||||
if (!this._currentEntry ||
|
if (!this._currentEntry ||
|
||||||
!this._currentEntry.fragment ||
|
!this._currentEntry.fragment ||
|
||||||
!this._currentEntry.fragment.isAdded()) {
|
!this._currentEntry.fragment.isAdded()) {
|
||||||
@ -742,7 +741,13 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@profile
|
@profile
|
||||||
public onCreateAnimator(fragment: android.support.v4.app.Fragment, transit: number, enter: boolean, nextAnim: number, superFunc: Function): android.animation.Animator {
|
public onCreateAnimator(fragment: org.nativescript.widgets.FragmentBase, transit: number, enter: boolean, nextAnim: number, superFunc: Function): android.animation.Animator {
|
||||||
|
// HACK: FragmentBase class MUST handle removing nested fragment scenario to workaround
|
||||||
|
// https://code.google.com/p/android/issues/detail?id=55228
|
||||||
|
if (!enter && fragment.getRemovingParentFragment()) {
|
||||||
|
return superFunc.call(fragment, transit, enter, nextAnim);
|
||||||
|
}
|
||||||
|
|
||||||
let nextAnimString: string;
|
let nextAnimString: string;
|
||||||
switch (nextAnim) {
|
switch (nextAnim) {
|
||||||
case AnimationType.enterFakeResourceId: nextAnimString = "enter"; break;
|
case AnimationType.enterFakeResourceId: nextAnimString = "enter"; break;
|
||||||
|
@ -45,7 +45,7 @@ function initializeNativeClasses() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
class TabFragmentImplementation extends android.support.v4.app.Fragment {
|
class TabFragmentImplementation extends org.nativescript.widgets.FragmentBase {
|
||||||
private tab: TabView;
|
private tab: TabView;
|
||||||
private index: number;
|
private index: number;
|
||||||
|
|
||||||
@ -55,7 +55,6 @@ function initializeNativeClasses() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static newInstance(tabId: number, index: number): TabFragmentImplementation {
|
static newInstance(tabId: number, index: number): TabFragmentImplementation {
|
||||||
|
|
||||||
const args = new android.os.Bundle();
|
const args = new android.os.Bundle();
|
||||||
args.putInt(TABID, tabId);
|
args.putInt(TABID, tabId);
|
||||||
args.putInt(INDEX, index);
|
args.putInt(INDEX, index);
|
||||||
@ -79,10 +78,6 @@ function initializeNativeClasses() {
|
|||||||
|
|
||||||
return tabItem.view.nativeViewProtected;
|
return tabItem.view.nativeViewProtected;
|
||||||
}
|
}
|
||||||
|
|
||||||
public onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const POSITION_UNCHANGED = -1;
|
const POSITION_UNCHANGED = -1;
|
||||||
@ -560,8 +555,13 @@ export class TabView extends TabViewBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public _onRootViewReset(): void {
|
public _onRootViewReset(): void {
|
||||||
this.disposeCurrentFragments();
|
|
||||||
super._onRootViewReset();
|
super._onRootViewReset();
|
||||||
|
|
||||||
|
// call this AFTER the super call to ensure descendants apply their rootview-reset logic first
|
||||||
|
// i.e. in a scenario with tab frames let the frames cleanup their fragments first, and then
|
||||||
|
// cleanup the tab fragments to avoid
|
||||||
|
// android.content.res.Resources$NotFoundException: Unable to find resource ID #0xfffffff6
|
||||||
|
this.disposeCurrentFragments();
|
||||||
}
|
}
|
||||||
|
|
||||||
private disposeCurrentFragments(): void {
|
private disposeCurrentFragments(): void {
|
||||||
|
@ -164,6 +164,12 @@
|
|||||||
public verticalAlignment: VerticalAlignment;
|
public verticalAlignment: VerticalAlignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class FragmentBase extends android.support.v4.app.Fragment {
|
||||||
|
constructor();
|
||||||
|
|
||||||
|
public getRemovingParentFragment(): android.support.v4.app.Fragment;
|
||||||
|
}
|
||||||
|
|
||||||
export enum Stretch {
|
export enum Stretch {
|
||||||
none,
|
none,
|
||||||
aspectFill,
|
aspectFill,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "tns-platform-declarations",
|
"name": "tns-platform-declarations",
|
||||||
"version": "5.1.0",
|
"version": "5.2.0",
|
||||||
"description": "Platform-specific TypeScript declarations for NativeScript for accessing native objects",
|
"description": "Platform-specific TypeScript declarations for NativeScript for accessing native objects",
|
||||||
"main": "",
|
"main": "",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
Reference in New Issue
Block a user