mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
Merge branch 'main' into fix/safe-area-layout-fixes
This commit is contained in:
4
.github/workflows/apps_automated.yml
vendored
4
.github/workflows/apps_automated.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
java-version: '11'
|
||||
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@v1
|
||||
uses: actions/setup-python@v4
|
||||
|
||||
- name: Install NativeScript
|
||||
run: |
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
|
||||
- name: Start iOS Simulator
|
||||
if: ${{ always() && !cancelled() }} # run iOS tests even if Android tests failed
|
||||
uses: futureware-tech/simulator-action@v1
|
||||
uses: futureware-tech/simulator-action@v2
|
||||
with:
|
||||
model: 'iPhone 13 Pro Max'
|
||||
os_version: '>=15.0'
|
||||
|
||||
28
README.md
28
README.md
@@ -7,7 +7,7 @@
|
||||
<p>
|
||||
|
||||
[](https://github.com/NativeScript/NativeScript/actions/workflows/apps_automated.yml)
|
||||
[](https://github.com/NativeScript/NativeScript/blob/master/LICENSE)
|
||||
[](https://github.com/NativeScript/NativeScript/blob/main/LICENSE)
|
||||
[](https://www.npmjs.com/@nativescript/core)
|
||||
[](https://nativescript.org/discord)
|
||||
|
||||
@@ -32,23 +32,23 @@ $ npm run setup
|
||||
$ npm start
|
||||
```
|
||||
|
||||
We love you and your pull requests 🤗. Please follow our [contributing guide](https://github.com/NativeScript/NativeScript/blob/master/tools/notes/CONTRIBUTING.md) and see [our code of governance](https://github.com/NativeScript/management/blob/master/nativescript-governance.md) to become as involved as you want to be.
|
||||
We love you and your pull requests 🤗. Please follow our [contributing guide](https://github.com/NativeScript/NativeScript/blob/main/tools/notes/CONTRIBUTING.md) and see [our code of governance](https://github.com/NativeScript/management/blob/master/nativescript-governance.md) to become as involved as you want to be.
|
||||
|
||||
## @nativescript/*
|
||||
|
||||
* [@nativescript/core](https://github.com/NativeScript/NativeScript/tree/master/packages/core)
|
||||
* [@nativescript/core](https://github.com/NativeScript/NativeScript/tree/main/packages/core)
|
||||
* Core iOS/Android for NativeScript.
|
||||
* [@nativescript/types](https://www.npmjs.com/package/@nativescript/types)
|
||||
* Types for both iOS/Android below wrapped up as a convenience. *Most commonly used.*
|
||||
* [@nativescript/types-ios](https://github.com/NativeScript/NativeScript/tree/master/packages/types-ios)
|
||||
* [@nativescript/types-ios](https://github.com/NativeScript/NativeScript/tree/main/packages/types-ios)
|
||||
* Types for iOS.
|
||||
* [@nativescript/types-android](https://github.com/NativeScript/NativeScript/tree/master/packages/types-android)
|
||||
* [@nativescript/types-android](https://github.com/NativeScript/NativeScript/tree/main/packages/types-android)
|
||||
* Types for Android.
|
||||
* [@nativescript/types-minimal](https://github.com/NativeScript/NativeScript/tree/master/packages/types-minimal)
|
||||
* [@nativescript/types-minimal](https://github.com/NativeScript/NativeScript/tree/main/packages/types-minimal)
|
||||
* A very minimal set of types for only the latest Android and iOS sdks. Most commonly used to optimize Web-based IDE's which auto load all type declarations from node_modules.
|
||||
* [@nativescript/ui-mobile-base](https://github.com/NativeScript/NativeScript/tree/master/packages/ui-mobile-base)
|
||||
* [@nativescript/ui-mobile-base](https://github.com/NativeScript/NativeScript/tree/main/packages/ui-mobile-base)
|
||||
* UI mobile base native classes used by core.
|
||||
* [@nativescript/webpack](https://github.com/NativeScript/NativeScript/tree/master/packages/webpack)
|
||||
* [@nativescript/webpack](https://github.com/NativeScript/NativeScript/tree/main/packages/webpack5)
|
||||
* Webpack build utilities and configs used by NativeScript apps.
|
||||
|
||||
## Quick Links
|
||||
@@ -78,7 +78,15 @@ Outside the source centralized in this repo, NativeScript consists of a few othe
|
||||
- This repo contains the NativeScript command-line interface, which lets you create, build, and run apps using NativeScript. The CLI is written in TypeScript.
|
||||
- **[Docs](//github.com/NativeScript/docs-new)**
|
||||
- This repo contains NativeScript documentation, which is available at <http://docs.nativescript.org/>. The docs are written in Markdown.
|
||||
- **[Official Plugins](https://github.com/NativeScript/plugins)
|
||||
- This repo contains a [plugin workspace](https://docs.nativescript.org/plugins/plugin-workspace-guide.html) the TSC (Technical Steering Committee) maintains offering several often useful plugins.
|
||||
- **[Plugins](https://github.com/NativeScript/plugins)**
|
||||
- This repo contains a [plugin workspace](https://docs.nativescript.org/plugins/plugin-workspace-guide.html) with several often useful plugins.
|
||||
- **[Firebase](https://github.com/NativeScript/firebase)**
|
||||
- Modular Firebase 🔥 implementation for iOS & Android.
|
||||
- **[ML Kit](https://github.com/NativeScript/mlkit)**
|
||||
- Google's [ML Kit SDKs for iOS and Android](https://developers.google.com/ml-kit).
|
||||
- **[Payments](https://github.com/NativeScript/payments)**
|
||||
- In-App Purchase, Subscriptions, Google Pay and Apple Pay.
|
||||
- **[Artwork](https://github.com/NativeScript/artwork)**
|
||||
- Want to use our logo or colors? This repo contains ready to use media material.
|
||||
|
||||
<h3 align="center">Made with ❤️</h3>
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
legacy-peer-deps=true
|
||||
|
||||
# npm 9+ this defaults to `true` meaning `file:` dependencies are packed and then installed
|
||||
# but since we want to link the source files in this case, we disable this behavior and
|
||||
# opt to link the dependency as-is instead. (eg. @nativescript/core)
|
||||
install-links=false
|
||||
|
||||
@@ -8,7 +8,7 @@ export var test_fetch_defined = function () {
|
||||
|
||||
export var test_fetch = function (done: (err: Error, res?: string) => void) {
|
||||
// >> fetch-response
|
||||
fetch('https://httpbin.org/get')
|
||||
fetch('https://http-echo.nativescript.org/get')
|
||||
.then(function (r) {
|
||||
// Argument (r) is Response!
|
||||
// >> (hide)
|
||||
@@ -22,7 +22,7 @@ export var test_fetch = function (done: (err: Error, res?: string) => void) {
|
||||
|
||||
export var test_fetch_text = function (done: (err: Error, res?: string) => void) {
|
||||
// >> fetch-string
|
||||
fetch('https://httpbin.org/get')
|
||||
fetch('https://http-echo.nativescript.org/get')
|
||||
.then((response) => response.text())
|
||||
.then(function (r) {
|
||||
// Argument (r) is string!
|
||||
@@ -37,7 +37,7 @@ export var test_fetch_text = function (done: (err: Error, res?: string) => void)
|
||||
|
||||
export var test_fetch_json = function (done: (err: Error, res?: string) => void) {
|
||||
// >> fetch-json
|
||||
fetch('https://httpbin.org/get')
|
||||
fetch('https://http-echo.nativescript.org/get')
|
||||
.then((response) => response.json())
|
||||
.then(function (r) {
|
||||
// Argument (r) is JSON object!
|
||||
@@ -52,7 +52,7 @@ export var test_fetch_json = function (done: (err: Error, res?: string) => void)
|
||||
|
||||
export var test_fetch_formData = function (done: (err: Error, res?: string) => void) {
|
||||
// >> fetch-formdata
|
||||
fetch('https://httpbin.org/get')
|
||||
fetch('https://http-echo.nativescript.org/get')
|
||||
.then((response) => response.formData())
|
||||
.then(function (r) {
|
||||
// Argument (r) is FormData object!
|
||||
@@ -67,7 +67,7 @@ export var test_fetch_formData = function (done: (err: Error, res?: string) => v
|
||||
|
||||
export var test_fetch_blob = function (done: (err: Error, res?: string) => void) {
|
||||
// >> fetch-blob
|
||||
fetch('https://httpbin.org/get')
|
||||
fetch('https://http-echo.nativescript.org/get')
|
||||
.then((response) => response.blob())
|
||||
.then(function (r) {
|
||||
// Argument (r) is Blob object!
|
||||
@@ -82,7 +82,7 @@ export var test_fetch_blob = function (done: (err: Error, res?: string) => void)
|
||||
|
||||
export var test_fetch_arraybuffer = function (done: (err: Error, res?: string) => void) {
|
||||
// >> fetch-arraybuffer
|
||||
fetch('https://httpbin.org/get')
|
||||
fetch('https://http-echo.nativescript.org/get')
|
||||
.then((response) => response.arrayBuffer())
|
||||
.then(function (r) {
|
||||
// Argument (r) is ArrayBuffer object!
|
||||
@@ -101,7 +101,7 @@ export var test_fetch_fail_invalid_url = function (done) {
|
||||
return completed;
|
||||
};
|
||||
|
||||
fetch('hgfttp://httpbin.org/get')
|
||||
fetch('hgfttp://http-echo.nativescript.org/get')
|
||||
.catch(function (e) {
|
||||
completed = true;
|
||||
done(null);
|
||||
@@ -111,7 +111,7 @@ export var test_fetch_fail_invalid_url = function (done) {
|
||||
|
||||
// Note: fetch is unable to do url validation
|
||||
// export var test_fetch_invalid_url_fail_message = function (done) {
|
||||
// fetch("hgfttp://httpbin.org/get").catch(function (e: TypeError) {
|
||||
// fetch("hgfttp://http-echo.nativescript.org/get").catch(function (e: TypeError) {
|
||||
// TKUnit.assert(e.message.match(/Network request failed:.{2,}/), "Failure message should contain details on the failure. Actual message was: " + e.message);
|
||||
// done(null);
|
||||
// }).catch(failOnError(done));
|
||||
@@ -119,7 +119,7 @@ export var test_fetch_fail_invalid_url = function (done) {
|
||||
|
||||
export var test_fetch_response_status = function (done) {
|
||||
// >> fetch-status-response
|
||||
fetch('https://httpbin.org/get')
|
||||
fetch('https://http-echo.nativescript.org/get')
|
||||
.then(function (response) {
|
||||
// Argument (response) is Response!
|
||||
var statusCode = response.status;
|
||||
@@ -134,7 +134,7 @@ export var test_fetch_response_status = function (done) {
|
||||
|
||||
export var test_fetch_response_headers = function (done) {
|
||||
// >> fetch-headers-response
|
||||
fetch('https://httpbin.org/get')
|
||||
fetch('https://http-echo.nativescript.org/get')
|
||||
.then(function (response) {
|
||||
// Argument (response) is Response!
|
||||
// var all = response.headers.getAll();
|
||||
@@ -148,7 +148,7 @@ export var test_fetch_response_headers = function (done) {
|
||||
};
|
||||
|
||||
export var test_fetch_headers_sent = function (done) {
|
||||
fetch('https://httpbin.org/get', {
|
||||
fetch('https://http-echo.nativescript.org/get', {
|
||||
method: 'GET',
|
||||
headers: new Headers({ 'Content-Type': 'application/json' }),
|
||||
})
|
||||
@@ -165,7 +165,7 @@ export var test_fetch_post_form_data = function (done) {
|
||||
data.append('MyVariableOne', 'ValueOne');
|
||||
data.append('MyVariableTwo', 'ValueTwo');
|
||||
|
||||
fetch('https://httpbin.org/post', {
|
||||
fetch('https://http-echo.nativescript.org/post', {
|
||||
method: 'POST',
|
||||
headers: new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' }),
|
||||
body: data,
|
||||
@@ -182,7 +182,7 @@ export var test_fetch_post_form_data = function (done) {
|
||||
|
||||
export var test_fetch_post_json = function (done) {
|
||||
// >> fetch-post-json
|
||||
fetch('https://httpbin.org/post', {
|
||||
fetch('https://http-echo.nativescript.org/post', {
|
||||
method: 'POST',
|
||||
headers: new Headers({ 'Content-Type': 'application/json' }),
|
||||
body: JSON.stringify({ MyVariableOne: 'ValueOne', MyVariableTwo: 'ValueTwo' }),
|
||||
|
||||
@@ -5,7 +5,7 @@ postMessage('stub');
|
||||
//
|
||||
// import { getString } from '@nativescript/core/http';
|
||||
//
|
||||
// getString('https://httpbin.org/get').then(
|
||||
// getString('https://http-echo.nativescript.org/get').then(
|
||||
// function (r) {
|
||||
// postMessage(r);
|
||||
// },
|
||||
|
||||
@@ -9,7 +9,7 @@ export var test_getString_isDefined = function () {
|
||||
};
|
||||
|
||||
export var test_getString = function (done: (err: Error, res?: string) => void) {
|
||||
http.getString('https://httpbin.org/get').then(
|
||||
http.getString('https://http-echo.nativescript.org/get').then(
|
||||
function (r) {
|
||||
//// Argument (r) is string!
|
||||
done(null);
|
||||
@@ -22,7 +22,7 @@ export var test_getString = function (done: (err: Error, res?: string) => void)
|
||||
};
|
||||
|
||||
export var test_getString_fail = function (done) {
|
||||
http.getString({ url: 'hgfttp://httpbin.org/get', method: 'GET', timeout: 2000 }).catch(function (e) {
|
||||
http.getString({ url: 'hgfttps://http-echo.nativescript.org/get', method: 'GET', timeout: 2000 }).catch(function (e) {
|
||||
done(null);
|
||||
});
|
||||
};
|
||||
@@ -31,7 +31,7 @@ export var test_getString_fail = function (done) {
|
||||
// export var test_getString_fail_when_result_is_not_string = function (done) {
|
||||
// var result;
|
||||
|
||||
// http.getString({ url: "https://httpbin.org/image/png", method: "GET" }).then(function (e) {
|
||||
// http.getString({ url: "https://http-echo.nativescript.org/image/png/logo.png", method: "GET" }).then(function (e) {
|
||||
// result = e;
|
||||
// try {
|
||||
// TKUnit.assert(result instanceof Error, "Result from getString().catch() should be Error! Current type is " + typeof result);
|
||||
@@ -50,7 +50,7 @@ export var test_getJSON_isDefined = function () {
|
||||
export var test_getJSON = function (done) {
|
||||
var result;
|
||||
|
||||
http.getJSON('https://httpbin.org/get').then(
|
||||
http.getJSON('https://http-echo.nativescript.org/get').then(
|
||||
function (r) {
|
||||
//// Argument (r) is JSON!
|
||||
//completed = true;
|
||||
@@ -74,7 +74,7 @@ export var test_getJSON = function (done) {
|
||||
export var test_getJSON_fail = function (done) {
|
||||
var result;
|
||||
|
||||
http.getJSON({ url: 'hgfttp://httpbin.org/get', method: 'GET', timeout: 2000 }).catch(function (e) {
|
||||
http.getJSON({ url: 'hgfttps://http-echo.nativescript.org/', method: 'GET', timeout: 2000 }).catch(function (e) {
|
||||
result = e;
|
||||
try {
|
||||
TKUnit.assert(result instanceof Error, 'Result from getJSON().catch() should be Error! Current type is ' + typeof result);
|
||||
@@ -88,7 +88,7 @@ export var test_getJSON_fail = function (done) {
|
||||
export var test_getJSON_fail_when_result_is_not_JSON = function (done) {
|
||||
var result;
|
||||
|
||||
http.getJSON({ url: 'https://httpbin.org/html', method: 'GET' }).catch(function (e) {
|
||||
http.getJSON({ url: 'https://http-echo.nativescript.org/html', method: 'GET' }).catch(function (e) {
|
||||
result = e;
|
||||
try {
|
||||
TKUnit.assert(result instanceof Error, 'Result from getJSON().catch() should be Error! Current type is ' + typeof result);
|
||||
@@ -102,7 +102,7 @@ export var test_getJSON_fail_when_result_is_not_JSON = function (done) {
|
||||
export var test_getJSONP = function (done) {
|
||||
var result;
|
||||
|
||||
http.getJSON('https://jsfiddle.net/echo/jsonp/').then(
|
||||
http.getJSON('https://http-echo.nativescript.org/jsonp').then(
|
||||
function (r) {
|
||||
result = r;
|
||||
try {
|
||||
@@ -122,7 +122,7 @@ export var test_getJSONP = function (done) {
|
||||
export var test_getJSON_fail_when_result_is_not_JSONP = function (done) {
|
||||
var result;
|
||||
|
||||
http.getJSON({ url: 'https://httpbin.org/html', method: 'GET' }).catch(function (e) {
|
||||
http.getJSON({ url: 'https://http-echo.nativescript.org/html', method: 'GET' }).catch(function (e) {
|
||||
result = e;
|
||||
try {
|
||||
TKUnit.assert(result instanceof Error, 'Result from getJSON().catch() should be Error! Current type is ' + typeof result);
|
||||
@@ -138,7 +138,7 @@ export var test_gzip_request_explicit = function (done) {
|
||||
|
||||
http
|
||||
.request({
|
||||
url: 'https://postman-echo.com/gzip',
|
||||
url: 'https://http-echo.nativescript.org/gzip',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept-Encoding': 'gzip',
|
||||
@@ -165,7 +165,7 @@ export var test_gzip_request_implicit = function (done) {
|
||||
|
||||
http
|
||||
.request({
|
||||
url: 'https://postman-echo.com/gzip',
|
||||
url: 'https://http-echo.nativescript.org/gzip',
|
||||
method: 'GET',
|
||||
})
|
||||
.then(
|
||||
@@ -191,7 +191,7 @@ export var test_getImage_isDefined = function () {
|
||||
export var test_getImage = function (done) {
|
||||
var result;
|
||||
|
||||
http.getImage('https://httpbin.org/image/png').then(
|
||||
http.getImage('https://http-echo.nativescript.org/image/png/logo.png').then(
|
||||
(r) => {
|
||||
// Argument (r) is ImageSource!
|
||||
result = r;
|
||||
@@ -226,7 +226,7 @@ export var test_getImage_fail = function (done) {
|
||||
export var test_getImage_fail_when_result_is_not_image = function (done) {
|
||||
var result;
|
||||
|
||||
http.getImage({ url: 'https://httpbin.org/html', method: 'GET' }).catch(function (e) {
|
||||
http.getImage({ url: 'https://http-echo.nativescript.org/html', method: 'GET' }).catch(function (e) {
|
||||
result = e;
|
||||
try {
|
||||
TKUnit.assert(result instanceof Error, 'Result from getImage().catch() should be Error! Current type is ' + typeof result);
|
||||
@@ -266,7 +266,7 @@ export var test_getContentAsFile = function (done) {
|
||||
var result;
|
||||
|
||||
var filePath = fs.path.join(fs.knownFolders.documents().path, 'test.png');
|
||||
http.getFile('https://httpbin.org/image/png?testQuery=query&anotherParam=param', filePath).then(
|
||||
http.getFile('https://http-echo.nativescript.org/image/png/logo.png?testQuery=query&anotherParam=param', filePath).then(
|
||||
function (r) {
|
||||
//// Argument (r) is File!
|
||||
result = r;
|
||||
@@ -332,7 +332,7 @@ export var test_request_requestShouldTimeout = function (done) {
|
||||
export var test_request_responseStatusCodeShouldBeDefined = function (done) {
|
||||
var result: http.HttpResponse;
|
||||
|
||||
http.request({ url: 'https://httpbin.org/get', method: 'GET' }).then(
|
||||
http.request({ url: 'https://http-echo.nativescript.org/get', method: 'GET' }).then(
|
||||
function (response) {
|
||||
//// Argument (response) is HttpResponse!
|
||||
var statusCode = response.statusCode;
|
||||
@@ -352,7 +352,7 @@ export var test_request_responseStatusCodeShouldBeDefined = function (done) {
|
||||
};
|
||||
|
||||
export var test_headRequest_responseStatusCodeShouldBeDefined = function (done) {
|
||||
http.request({ url: 'https://httpbin.org/get', method: 'HEAD' }).then(
|
||||
http.request({ url: 'https://http-echo.nativescript.org/get', method: 'HEAD' }).then(
|
||||
function (response) {
|
||||
try {
|
||||
TKUnit.assert(typeof response.statusCode !== 'undefined', 'response.statusCode should be defined!');
|
||||
@@ -370,7 +370,7 @@ export var test_headRequest_responseStatusCodeShouldBeDefined = function (done)
|
||||
export var test_request_responseHeadersShouldBeDefined = function (done) {
|
||||
var result: http.HttpResponse;
|
||||
|
||||
http.request({ url: 'https://httpbin.org/get', method: 'GET' }).then(
|
||||
http.request({ url: 'https://http-echo.nativescript.org/get', method: 'GET' }).then(
|
||||
function (response) {
|
||||
//// Argument (response) is HttpResponse!
|
||||
//for (var header in response.headers) {
|
||||
@@ -394,7 +394,7 @@ export var test_request_responseHeadersShouldBeDefined = function (done) {
|
||||
export var test_request_responseContentShouldBeDefined = function (done) {
|
||||
var result: http.HttpResponse;
|
||||
|
||||
http.request({ url: 'https://httpbin.org/get', method: 'GET' }).then(
|
||||
http.request({ url: 'https://http-echo.nativescript.org/get', method: 'GET' }).then(
|
||||
function (response) {
|
||||
//// Argument (response) is HttpResponse!
|
||||
//// Content property of the response is HttpContent!
|
||||
@@ -416,7 +416,7 @@ export var test_request_responseContentShouldBeDefined = function (done) {
|
||||
export var test_request_responseContentToStringShouldReturnString = function (done) {
|
||||
var result;
|
||||
|
||||
http.request({ url: 'https://httpbin.org/get', method: 'GET' }).then(
|
||||
http.request({ url: 'https://http-echo.nativescript.org/get', method: 'GET' }).then(
|
||||
function (response) {
|
||||
result = response.content.toString();
|
||||
try {
|
||||
@@ -435,7 +435,7 @@ export var test_request_responseContentToStringShouldReturnString = function (do
|
||||
export var test_request_responseContentToJSONShouldReturnJSON = function (done) {
|
||||
var result;
|
||||
|
||||
http.request({ url: 'https://httpbin.org/get', method: 'GET' }).then(
|
||||
http.request({ url: 'https://http-echo.nativescript.org/get', method: 'GET' }).then(
|
||||
function (response) {
|
||||
result = response.content.toJSON();
|
||||
try {
|
||||
@@ -454,7 +454,7 @@ export var test_request_responseContentToJSONShouldReturnJSON = function (done)
|
||||
export var test_request_responseContentToImageShouldReturnCorrectImage = function (done) {
|
||||
var result;
|
||||
|
||||
http.request({ url: 'https://httpbin.org/image/png', method: 'GET' }).then(
|
||||
http.request({ url: 'https://http-echo.nativescript.org/image/png/logo.png', method: 'GET' }).then(
|
||||
function (response) {
|
||||
response.content.toImage().then((source) => {
|
||||
result = source;
|
||||
@@ -475,7 +475,7 @@ export var test_request_responseContentToImageShouldReturnCorrectImage = functio
|
||||
export var test_request_responseContentToFileFromUrlShouldReturnCorrectFile = function (done) {
|
||||
var result;
|
||||
|
||||
http.request({ url: 'https://raw.githubusercontent.com/NativeScript/NativeScript/master/tests/app/logo.png', method: 'GET' }).then(
|
||||
http.request({ url: 'https://http-echo.nativescript.org/image/png/logo.png', method: 'GET' }).then(
|
||||
function (response) {
|
||||
result = response.content.toFile();
|
||||
try {
|
||||
@@ -491,9 +491,9 @@ export var test_request_responseContentToFileFromUrlShouldReturnCorrectFile = fu
|
||||
);
|
||||
};
|
||||
export var test_request_responseContentToFileFromUrlShouldReturnCorrectFileAndCreateDirPathIfNecesary = function (done) {
|
||||
var result;
|
||||
var result: fs.File;
|
||||
|
||||
http.request({ url: 'https://raw.githubusercontent.com/NativeScript/NativeScript/master/tests/app/logo.png', method: 'GET' }).then(
|
||||
http.request({ url: 'https://http-echo.nativescript.org/image/png/logo.png', method: 'GET' }).then(
|
||||
function (response) {
|
||||
const filePath = fs.path.join(fs.knownFolders.temp().path, 'test', 'some', 'path', 'logo.png');
|
||||
result = response.content.toFile(filePath);
|
||||
@@ -514,7 +514,7 @@ export var test_request_responseContentToFileFromUrlShouldReturnCorrectFileAndCr
|
||||
export var test_request_responseContentToFileFromContentShouldReturnCorrectFile = function (done) {
|
||||
var result;
|
||||
|
||||
http.request({ url: 'https://httpbin.org/image/png?queryString=param&another=anotherParam', method: 'GET' }).then(
|
||||
http.request({ url: 'https://http-echo.nativescript.org/image/png/logo.png?queryString=param&another=anotherParam', method: 'GET' }).then(
|
||||
function (response) {
|
||||
result = response.content.toFile();
|
||||
try {
|
||||
@@ -535,7 +535,7 @@ export var test_request_headersSentAndReceivedProperly = function (done) {
|
||||
|
||||
http
|
||||
.request({
|
||||
url: 'https://httpbin.org/get',
|
||||
url: 'https://http-echo.nativescript.org/get',
|
||||
method: 'GET',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
@@ -580,7 +580,7 @@ export var test_request_contentSentAndReceivedProperly = function (done) {
|
||||
|
||||
http
|
||||
.request({
|
||||
url: 'https://httpbin.org/post',
|
||||
url: 'https://http-echo.nativescript.org/post',
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
content: 'MyVariableOne=ValueOne&MyVariableTwo=ValueTwo',
|
||||
@@ -610,7 +610,7 @@ export var test_request_FormDataContentSentAndReceivedProperly = function (done)
|
||||
|
||||
http
|
||||
.request({
|
||||
url: 'https://httpbin.org/post',
|
||||
url: 'https://http-echo.nativescript.org/post',
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
content: data,
|
||||
@@ -638,7 +638,7 @@ export var test_request_NonStringHeadersSentAndReceivedProperly = function (done
|
||||
|
||||
http
|
||||
.request({
|
||||
url: 'https://httpbin.org/post',
|
||||
url: 'https://http-echo.nativescript.org/post',
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': postData.length },
|
||||
content: postData,
|
||||
@@ -664,7 +664,7 @@ export var test_request_jsonAsContentSentAndReceivedProperly = function (done) {
|
||||
|
||||
http
|
||||
.request({
|
||||
url: 'https://httpbin.org/post',
|
||||
url: 'https://http-echo.nativescript.org/post',
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
content: JSON.stringify({ MyVariableOne: 'ValueOne', MyVariableTwo: 'ValueTwo' }),
|
||||
|
||||
@@ -43,11 +43,13 @@ import * as xhrTests from './xhr/xhr-tests';
|
||||
import * as fetchTests from './fetch/fetch-tests';
|
||||
import * as timerTests from './timer/timer-tests';
|
||||
import * as profilingTests from './profiling/profiling-tests';
|
||||
|
||||
allTests['HTTP'] = httpTests;
|
||||
allTests['XHR'] = xhrTests;
|
||||
allTests['FETCH'] = fetchTests;
|
||||
|
||||
// don't run these on CI as they are flaky
|
||||
if (!__CI__) {
|
||||
allTests['HTTP'] = httpTests;
|
||||
allTests['XHR'] = xhrTests;
|
||||
allTests['FETCH'] = fetchTests;
|
||||
allTests['TIMER'] = timerTests;
|
||||
allTests['PROFILING'] = profilingTests;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ export var test_XMLHttpRequest_readyStateShouldChange = function (done) {
|
||||
// </hide>
|
||||
};
|
||||
|
||||
xhr.open('GET', 'https://httpbin.org/get');
|
||||
xhr.open('GET', 'https://http-echo.nativescript.org/get');
|
||||
xhr.send();
|
||||
// ```
|
||||
// </snippet>
|
||||
@@ -87,7 +87,7 @@ export var test_XMLHttpRequest_headersSentAndReceivedProperly = function (done)
|
||||
// ### Send/receive headers
|
||||
// ``` JavaScript
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'https://httpbin.org/get');
|
||||
xhr.open('GET', 'https://http-echo.nativescript.org/get');
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState > 1) {
|
||||
@@ -112,7 +112,7 @@ export var test_XMLHttpRequest_contentSentAndReceivedProperly = function (done)
|
||||
// ### Send/receive JSON
|
||||
// ``` JavaScript
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'https://httpbin.org/post');
|
||||
xhr.open('POST', 'https://http-echo.nativescript.org/post');
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.responseType = 'json';
|
||||
xhr.onreadystatechange = function () {
|
||||
@@ -137,7 +137,7 @@ export var test_XMLHttpRequest_FormDataContentSentAndReceivedProperly = function
|
||||
// ### Send/receive FormData
|
||||
// ``` JavaScript
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'https://httpbin.org/post');
|
||||
xhr.open('POST', 'https://http-echo.nativescript.org/post');
|
||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState > 3) {
|
||||
@@ -169,7 +169,7 @@ export var test_XMLHttpRequest_abortShouldCancelonreadystatechange = function (d
|
||||
// ### Abort request
|
||||
// ``` JavaScript
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'https://httpbin.org/post');
|
||||
xhr.open('POST', 'https://http-echo.nativescript.org/post');
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
// <hide>
|
||||
xhr.onreadystatechange = function () {
|
||||
@@ -186,7 +186,7 @@ export var test_XMLHttpRequest_abortShouldCancelonreadystatechange = function (d
|
||||
|
||||
export var test_XMLHttpRequest_requestShouldBePossibleAfterAbortedOpen = function (done) {
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'https://httpbin.org/post');
|
||||
xhr.open('POST', 'https://http-echo.nativescript.org/post');
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState > 3) {
|
||||
@@ -207,7 +207,7 @@ export var test_XMLHttpRequest_requestShouldBePossibleAfterAbortedOpen = functio
|
||||
|
||||
export var test_XMLHttpRequest_requestShouldntBePossibleAfterAbortedSentRequest = function () {
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'https://httpbin.org/post');
|
||||
xhr.open('POST', 'https://http-echo.nativescript.org/post');
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.send(JSON.stringify({ MyVariableOne: 'ValueOne', MyVariableTwo: 'ValueTwo' }));
|
||||
xhr.abort();
|
||||
@@ -217,7 +217,7 @@ export var test_XMLHttpRequest_requestShouldntBePossibleAfterAbortedSentRequest
|
||||
|
||||
export function test_ignore_zero_length_request_body() {
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'https://httpbin.org/get');
|
||||
xhr.open('GET', 'https://http-echo.nativescript.org/get');
|
||||
|
||||
xhr.send('');
|
||||
}
|
||||
@@ -227,7 +227,7 @@ export function test_raises_onload_Event(done) {
|
||||
xhr.onload = () => {
|
||||
done(null);
|
||||
};
|
||||
xhr.open('GET', 'https://httpbin.org/get');
|
||||
xhr.open('GET', 'https://http-echo.nativescript.org/get');
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
@@ -356,7 +356,7 @@ export function test_sets_status_and_statusText(done) {
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.open('GET', 'https://httpbin.org/get');
|
||||
xhr.open('GET', 'https://http-echo.nativescript.org/get');
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ export function test_raises_onerror_Event(done) {
|
||||
xhr.onerror = () => {
|
||||
done(null);
|
||||
};
|
||||
xhr.open('GET', 'https://no-such-domain-httpbin.org');
|
||||
xhr.open('GET', 'https://no-such-domain.nativescript.org');
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
@@ -405,15 +405,15 @@ export var test_XMLHttpRequest_contentReceivedArrayBufferProperly = function (do
|
||||
// ### Receive Blob
|
||||
// ``` JavaScript
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'https://httpbin.org/image/jpeg');
|
||||
xhr.open('GET', 'https://http-echo.nativescript.org/image/jpeg');
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState > 3) {
|
||||
// <hide>
|
||||
try {
|
||||
TKUnit.assertEqual(xhr.getResponseHeader('Content-Length'), '35588');
|
||||
TKUnit.assertEqual(xhr.getResponseHeader('Content-Length'), '7911');
|
||||
TKUnit.assertEqual(xhr.getResponseHeader('Content-Type'), 'image/jpeg');
|
||||
TKUnit.assertEqual((xhr.response as ArrayBuffer).byteLength, 35588);
|
||||
TKUnit.assertEqual((xhr.response as ArrayBuffer).byteLength, 7911);
|
||||
done(null);
|
||||
} catch (err) {
|
||||
done(err);
|
||||
@@ -431,15 +431,15 @@ export var test_XMLHttpRequest_contentReceivedBlobProperly = function (done) {
|
||||
// ### Receive Blob
|
||||
// ``` JavaScript
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'https://httpbin.org/image/jpeg');
|
||||
xhr.open('GET', 'https://http-echo.nativescript.org/image/jpeg');
|
||||
xhr.responseType = 'blob';
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState > 3) {
|
||||
// <hide>
|
||||
try {
|
||||
TKUnit.assertEqual(xhr.getResponseHeader('Content-Length'), '35588');
|
||||
TKUnit.assertEqual(xhr.getResponseHeader('Content-Length'), '7911');
|
||||
TKUnit.assertEqual(xhr.getResponseHeader('Content-Type'), 'image/jpeg');
|
||||
TKUnit.assertEqual((xhr.response as Blob).size, 35588);
|
||||
TKUnit.assertEqual((xhr.response as Blob).size, 7911);
|
||||
TKUnit.assertEqual((xhr.response as Blob).type, 'image/jpeg');
|
||||
done(null);
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { Application, Utils } from '@nativescript/core';
|
||||
import { Application } from '@nativescript/core';
|
||||
|
||||
Application.run({ moduleName: 'app-root' });
|
||||
|
||||
@@ -5,7 +5,16 @@
|
||||
</Page.actionBar>
|
||||
<ScrollView>
|
||||
<StackLayout padding="20">
|
||||
<Label text="maxLines 2" fontWeight="bold" />
|
||||
<GridLayout borderWidth="1" borderColor="#efefef" height="60" paddingLeft="5">
|
||||
<Label text="Test Label 1: should be aligned middle" />
|
||||
</GridLayout>
|
||||
<GridLayout marginTop="10" borderWidth="1" borderColor="#efefef" height="60" paddingLeft="5">
|
||||
<Label text="Test Label 2: should be aligned bottom" verticalAlignment="bottom" />
|
||||
</GridLayout>
|
||||
<GridLayout marginTop="10" borderWidth="1" borderColor="#efefef" height="60" paddingLeft="5">
|
||||
<Label text="Test Label 3: should be aligned top" verticalAlignment="top" />
|
||||
</GridLayout>
|
||||
<Label text="maxLines 2" fontWeight="bold" marginTop="10" />
|
||||
<Label
|
||||
text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
|
||||
textWrap="true"
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
const nxPreset = require('@nrwl/jest/preset').default;
|
||||
|
||||
module.exports = { ...nxPreset };
|
||||
module.exports = {
|
||||
...nxPreset,
|
||||
/* TODO: Update to latest Jest snapshotFormat
|
||||
* By default Nx has kept the older style of Jest Snapshot formats
|
||||
* to prevent breaking of any existing tests with snapshots.
|
||||
* It's recommend you update to the latest format.
|
||||
* You can do this by removing snapshotFormat property
|
||||
* and running tests with --update-snapshot flag.
|
||||
* Example: "nx affected --targets=test --update-snapshot"
|
||||
* More info: https://jestjs.io/docs/upgrading-to-jest29#snapshot-format
|
||||
*/
|
||||
snapshotFormat: { escapeString: true, printBasicPrototype: true },
|
||||
};
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"migrations": [
|
||||
{
|
||||
"version": "15.7.0-beta.0",
|
||||
"description": "Split global configuration files into individual project.json files. This migration has been added automatically to the beginning of your migration set to retroactively make them work with the new version of Nx.",
|
||||
"cli": "nx",
|
||||
"implementation": "./src/migrations/update-15-7-0/split-configuration-into-project-json-files",
|
||||
"package": "@nrwl/workspace",
|
||||
"name": "15-7-0-split-configuration-into-project-json-files"
|
||||
},
|
||||
{
|
||||
"version": "15.7.0-beta.0",
|
||||
"description": "Split global configuration files (e.g., workspace.json) into individual project.json files.",
|
||||
"cli": "nx",
|
||||
"implementation": "./src/migrations/update-15-7-0/split-configuration-into-project-json-files",
|
||||
"package": "@nrwl/workspace",
|
||||
"name": "15-7-0-split-configuration-into-project-json-files"
|
||||
}
|
||||
]
|
||||
}
|
||||
16
package.json
16
package.json
@@ -18,17 +18,17 @@
|
||||
"url": "https://github.com/NativeScript/NativeScript.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nrwl/nx-cloud": "15.0.3",
|
||||
"@nrwl/nx-cloud": "15.1.1",
|
||||
"nativescript-theme-core": "^1.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nativescript/hook": "^2.0.0",
|
||||
"@nativescript/nx": "~4.2.0",
|
||||
"@nrwl/cli": "15.7.0",
|
||||
"@nrwl/eslint-plugin-nx": "15.7.0",
|
||||
"@nrwl/jest": "15.7.0",
|
||||
"@nrwl/node": "15.7.0",
|
||||
"@nrwl/workspace": "15.7.0",
|
||||
"@nrwl/cli": "15.8.3",
|
||||
"@nrwl/eslint-plugin-nx": "15.8.3",
|
||||
"@nrwl/jest": "15.8.3",
|
||||
"@nrwl/node": "15.8.3",
|
||||
"@nrwl/workspace": "15.8.3",
|
||||
"@nstudio/focus": "^15.0.0",
|
||||
"@nstudio/nps-i": "~2.0.0",
|
||||
"@prettier/plugin-xml": "^2.2.0",
|
||||
@@ -46,12 +46,12 @@
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"gonzales": "^1.0.7",
|
||||
"husky": "^8.0.1",
|
||||
"jest": "29.4.1",
|
||||
"jest": "29.4.3",
|
||||
"lint-staged": "^13.1.0",
|
||||
"module-alias": "^2.2.2",
|
||||
"nativescript": "~8.4.0",
|
||||
"nativescript-typedoc-theme": "1.1.0",
|
||||
"nx": "15.7.0",
|
||||
"nx": "15.8.3",
|
||||
"parse-css": "git+https://github.com/tabatkins/parse-css.git",
|
||||
"parserlib": "^1.1.1",
|
||||
"prettier": "^2.6.2",
|
||||
|
||||
@@ -206,6 +206,19 @@ export class iOSApplication implements iOSApplicationDefinition {
|
||||
return this._rootView;
|
||||
}
|
||||
|
||||
public setSystemAppearance(value: 'light' | 'dark' | null) {
|
||||
if (this.systemAppearance !== value) {
|
||||
this._systemAppearance = value;
|
||||
systemAppearanceChanged(this.rootView, value);
|
||||
notify(<SystemAppearanceChangedEventData>{
|
||||
eventName: systemAppearanceChangedEvent,
|
||||
ios: this,
|
||||
newValue: iosApp.systemAppearance,
|
||||
object: this,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public addNotificationObserver(notificationName: string, onReceiveCallback: (notification: NSNotification) => void): NotificationObserver {
|
||||
const observer = NotificationObserver.initWithCallback(onReceiveCallback);
|
||||
NSNotificationCenter.defaultCenter.addObserverSelectorNameObject(observer, 'onReceive', notificationName, null);
|
||||
@@ -376,17 +389,7 @@ export class iOSApplication implements iOSApplicationDefinition {
|
||||
const userInterfaceStyle = controller.traitCollection.userInterfaceStyle;
|
||||
const newSystemAppearance = getSystemAppearanceValue(userInterfaceStyle);
|
||||
|
||||
if (this._systemAppearance !== newSystemAppearance) {
|
||||
this._systemAppearance = newSystemAppearance;
|
||||
systemAppearanceChanged(rootView, newSystemAppearance);
|
||||
|
||||
notify(<SystemAppearanceChangedEventData>{
|
||||
eventName: systemAppearanceChangedEvent,
|
||||
ios: this,
|
||||
newValue: this._systemAppearance,
|
||||
object: this,
|
||||
});
|
||||
}
|
||||
this.setSystemAppearance(newSystemAppearance);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -461,6 +464,7 @@ export function run(entry?: string | NavigationEntry) {
|
||||
rootView._setupAsRootView({});
|
||||
const embedderDelegate = NativeScriptEmbedder.sharedInstance().delegate;
|
||||
if (embedderDelegate) {
|
||||
setViewControllerView(rootView);
|
||||
embedderDelegate.presentNativeScriptApp(controller);
|
||||
} else {
|
||||
const visibleVC = getVisibleViewController(rootController);
|
||||
@@ -474,16 +478,7 @@ export function run(entry?: string | NavigationEntry) {
|
||||
const userInterfaceStyle = controller.traitCollection.userInterfaceStyle;
|
||||
const newSystemAppearance = getSystemAppearanceValue(userInterfaceStyle);
|
||||
|
||||
if (this._systemAppearance !== newSystemAppearance) {
|
||||
this._systemAppearance = newSystemAppearance;
|
||||
|
||||
notify(<SystemAppearanceChangedEventData>{
|
||||
eventName: systemAppearanceChangedEvent,
|
||||
ios: this,
|
||||
newValue: this._systemAppearance,
|
||||
object: this,
|
||||
});
|
||||
}
|
||||
iosApp.setSystemAppearance(newSystemAppearance);
|
||||
});
|
||||
iosApp.notifyAppStarted();
|
||||
}
|
||||
|
||||
2
packages/core/index.d.ts
vendored
2
packages/core/index.d.ts
vendored
@@ -17,6 +17,8 @@ export declare const Application: {
|
||||
suspendEvent: string;
|
||||
resumeEvent: string;
|
||||
exitEvent: string;
|
||||
foregroundEvent: string;
|
||||
backgroundEvent: string;
|
||||
lowMemoryEvent: string;
|
||||
orientationChangedEvent: string;
|
||||
systemAppearanceChangedEvent: string;
|
||||
|
||||
@@ -6,7 +6,7 @@ export { iOSApplication, AndroidApplication } from './application';
|
||||
export type { ApplicationEventData, LaunchEventData, OrientationChangedEventData, UnhandledErrorEventData, DiscardedErrorEventData, CssChangedEventData, LoadAppCSSEventData, AndroidActivityEventData, AndroidActivityBundleEventData, AndroidActivityRequestPermissionsEventData, AndroidActivityResultEventData, AndroidActivityNewIntentEventData, AndroidActivityBackPressedEventData, SystemAppearanceChangedEventData } from './application';
|
||||
|
||||
import { fontScaleChangedEvent, launchEvent, displayedEvent, uncaughtErrorEvent, discardedErrorEvent, suspendEvent, resumeEvent, exitEvent, lowMemoryEvent, orientationChangedEvent, systemAppearanceChanged, systemAppearanceChangedEvent, getMainEntry, getRootView, _resetRootView, getResources, setResources, setCssFileName, getCssFileName, loadAppCss, addCss, on, off, notify, hasListeners, run, orientation, getNativeApplication, hasLaunched, android as appAndroid, ios as iosApp, systemAppearance, setAutoSystemAppearanceChanged, ensureNativeApplication, setMaxRefreshRate } from './application';
|
||||
import { inBackground, suspended } from './application/application-common';
|
||||
import { inBackground, suspended, foregroundEvent, backgroundEvent } from './application/application-common';
|
||||
|
||||
export const Application = {
|
||||
launchEvent,
|
||||
@@ -16,6 +16,8 @@ export const Application = {
|
||||
suspendEvent,
|
||||
resumeEvent,
|
||||
exitEvent,
|
||||
foregroundEvent,
|
||||
backgroundEvent,
|
||||
lowMemoryEvent,
|
||||
orientationChangedEvent,
|
||||
systemAppearanceChangedEvent,
|
||||
|
||||
Binary file not shown.
@@ -254,6 +254,7 @@ function applySelectors<T extends View>(view: T, callback: (view: T) => void) {
|
||||
if (currentPage) {
|
||||
const styleScope = currentPage._styleScope;
|
||||
if (styleScope) {
|
||||
view.parent = currentPage;
|
||||
view._inheritStyleScope(styleScope);
|
||||
view.onLoaded();
|
||||
callback(view);
|
||||
|
||||
@@ -51,9 +51,7 @@ placeholderColorProperty.register(Style);
|
||||
|
||||
const keyboardTypeConverter = makeParser<CoreTypes.KeyboardInputType>(makeValidator<CoreTypes.KeyboardInputType>(CoreTypes.KeyboardType.datetime, CoreTypes.KeyboardType.phone, CoreTypes.KeyboardType.number, CoreTypes.KeyboardType.url, CoreTypes.KeyboardType.email, CoreTypes.KeyboardType.integer), true);
|
||||
|
||||
const autofillTypeConverter = makeParser<CoreTypes.AutofillType>(makeValidator<CoreTypes.AutofillType>(CoreTypes.AutofillType.username, CoreTypes.AutofillType.password, CoreTypes.AutofillType.none), true);
|
||||
|
||||
export const autofillTypeProperty = new Property<EditableTextBase, CoreTypes.AutofillType>({ name: 'autofillType', valueConverter: autofillTypeConverter });
|
||||
export const autofillTypeProperty = new Property<EditableTextBase, CoreTypes.AutofillType>({ name: 'autofillType' });
|
||||
autofillTypeProperty.register(EditableTextBase);
|
||||
|
||||
export const keyboardTypeProperty = new Property<EditableTextBase, CoreTypes.KeyboardInputType>({ name: 'keyboardType', valueConverter: keyboardTypeConverter });
|
||||
|
||||
@@ -43,6 +43,14 @@ export class FrameBase extends CustomLayoutView {
|
||||
|
||||
public actionBarVisibility: 'auto' | 'never' | 'always';
|
||||
public _currentEntry: BackstackEntry;
|
||||
|
||||
/**
|
||||
* A reference of current page that is set earlier than current entry.
|
||||
* Using this property, methods like 'eachChildView' and '_childrenCount' gain access to page view
|
||||
* just in time for calls like '_addView' to perform view-tree iterations.
|
||||
*/
|
||||
public _resolvedPage: Page;
|
||||
|
||||
public _animationInProgress = false;
|
||||
public _executingContext: NavigationContext;
|
||||
public _isInFrameStack = false;
|
||||
@@ -238,6 +246,8 @@ export class FrameBase extends CustomLayoutView {
|
||||
// In case we navigated forward to a page that was in the backstack
|
||||
// with clearHistory: true
|
||||
if (!newPage.frame) {
|
||||
this._resolvedPage = newPage;
|
||||
|
||||
this._addView(newPage);
|
||||
newPage._frame = this;
|
||||
}
|
||||
@@ -456,7 +466,6 @@ export class FrameBase extends CustomLayoutView {
|
||||
if (this._currentEntry) {
|
||||
return this._currentEntry.resolvedPage;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -508,7 +517,7 @@ export class FrameBase extends CustomLayoutView {
|
||||
}
|
||||
|
||||
get _childrenCount(): number {
|
||||
if (this.currentPage) {
|
||||
if (this._resolvedPage) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -516,7 +525,7 @@ export class FrameBase extends CustomLayoutView {
|
||||
}
|
||||
|
||||
public eachChildView(callback: (child: View) => boolean) {
|
||||
const page = this.currentPage;
|
||||
const page = this._resolvedPage;
|
||||
if (page) {
|
||||
callback(page);
|
||||
}
|
||||
|
||||
@@ -913,6 +913,8 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
|
||||
return null;
|
||||
}
|
||||
|
||||
frame._resolvedPage = page;
|
||||
|
||||
if (page.parent === frame) {
|
||||
// If we are navigating to a page that was destroyed
|
||||
// reinitialize its UI.
|
||||
@@ -920,6 +922,10 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
|
||||
const context = (container && container.getContext()) || (inflater && inflater.getContext());
|
||||
page._setupUI(context);
|
||||
}
|
||||
|
||||
if (frame.isLoaded && !page.isLoaded) {
|
||||
page.callLoaded();
|
||||
}
|
||||
} else {
|
||||
if (!frame._styleScope) {
|
||||
// Make sure page will have styleScope even if parents don't.
|
||||
@@ -929,10 +935,6 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
|
||||
frame._addView(page);
|
||||
}
|
||||
|
||||
if (frame.isLoaded && !page.isLoaded) {
|
||||
page.callLoaded();
|
||||
}
|
||||
|
||||
const savedState = entry.viewSavedState;
|
||||
if (savedState) {
|
||||
(<android.view.View>page.nativeViewProtected).restoreHierarchyState(savedState);
|
||||
|
||||
@@ -39,6 +39,7 @@ export class Label extends TextBase implements LabelDefinition {
|
||||
const textView = this.nativeTextViewProtected;
|
||||
textView.setSingleLine(true);
|
||||
textView.setEllipsize(android.text.TextUtils.TruncateAt.END);
|
||||
textView.setGravity(android.view.Gravity.CENTER_VERTICAL);
|
||||
}
|
||||
|
||||
[whiteSpaceProperty.setNative](value: CoreTypes.WhiteSpaceType) {
|
||||
|
||||
@@ -42,7 +42,9 @@ export class RootLayoutBase extends GridLayout {
|
||||
|
||||
// ability to add any view instance to composite views like layers
|
||||
open(view: View, options: RootLayoutOptions = {}): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const enterAnimationDefinition = options.animation ? options.animation.enterFrom : null;
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (!(view instanceof View)) {
|
||||
return reject(new Error(`Invalid open view: ${view}`));
|
||||
}
|
||||
@@ -51,46 +53,57 @@ export class RootLayoutBase extends GridLayout {
|
||||
return reject(new Error(`${view} has already been added`));
|
||||
}
|
||||
|
||||
const enterAnimationDefinition = options.animation ? options.animation.enterFrom : null;
|
||||
resolve();
|
||||
})
|
||||
.then(() => {
|
||||
// keep track of the views locally to be able to use their options later
|
||||
this.popupViews.push({ view: view, options: options });
|
||||
|
||||
// keep track of the views locally to be able to use their options later
|
||||
this.popupViews.push({ view: view, options: options });
|
||||
|
||||
if (options.shadeCover) {
|
||||
// perf optimization note: we only need 1 layer of shade cover
|
||||
// we just update properties if needed by additional overlaid views
|
||||
if (this.shadeCover) {
|
||||
// overwrite current shadeCover options if topmost popupview has additional shadeCover configurations
|
||||
this.updateShadeCover(this.shadeCover, options.shadeCover);
|
||||
} else {
|
||||
this.openShadeCover(options.shadeCover);
|
||||
if (options.shadeCover) {
|
||||
// perf optimization note: we only need 1 layer of shade cover
|
||||
// we just update properties if needed by additional overlaid views
|
||||
if (this.shadeCover) {
|
||||
// overwrite current shadeCover options if topmost popupview has additional shadeCover configurations
|
||||
return this.updateShadeCover(this.shadeCover, options.shadeCover);
|
||||
}
|
||||
return this.openShadeCover(options.shadeCover);
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
view.opacity = 0; // always begin with view invisible when adding dynamically
|
||||
this.insertChild(view, this.getChildrenCount() + 1);
|
||||
|
||||
view.opacity = 0; // always begin with view invisible when adding dynamically
|
||||
this.insertChild(view, this.getChildrenCount() + 1);
|
||||
|
||||
setTimeout(() => {
|
||||
// only apply initial state and animate after the first tick - ensures safe areas and other measurements apply correctly
|
||||
this.applyInitialState(view, enterAnimationDefinition);
|
||||
this.getEnterAnimation(view, enterAnimationDefinition)
|
||||
.play()
|
||||
.then(() => {
|
||||
this.applyDefaultState(view);
|
||||
view.notify({ eventName: 'opened', object: view });
|
||||
resolve();
|
||||
})
|
||||
.catch((ex) => {
|
||||
reject(new Error(`Error playing enter animation: ${ex}`));
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
// only apply initial state and animate after the first tick - ensures safe areas and other measurements apply correctly
|
||||
this.applyInitialState(view, enterAnimationDefinition);
|
||||
this.getEnterAnimation(view, enterAnimationDefinition)
|
||||
.play()
|
||||
.then(() => {
|
||||
this.applyDefaultState(view);
|
||||
view.notify({ eventName: 'opened', object: view });
|
||||
resolve();
|
||||
})
|
||||
.catch((ex) => {
|
||||
reject(new Error(`Error playing enter animation: ${ex}`));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// optional animation parameter to overwrite close animation declared when opening popup
|
||||
// ability to remove any view instance from composite views
|
||||
close(view: View, exitTo?: TransitionAnimation): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const cleanupAndFinish = () => {
|
||||
view.notify({ eventName: 'closed', object: view });
|
||||
this.removeChild(view);
|
||||
};
|
||||
|
||||
// use exitAnimation that is passed in and fallback to the exitAnimation passed in when opening
|
||||
let exitAnimationDefinition = exitTo;
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (!(view instanceof View)) {
|
||||
return reject(new Error(`Invalid close view: ${view}`));
|
||||
}
|
||||
@@ -99,51 +112,51 @@ export class RootLayoutBase extends GridLayout {
|
||||
return reject(new Error(`Unable to close popup. ${view} not found`));
|
||||
}
|
||||
|
||||
const popupIndex = this.getPopupIndex(view);
|
||||
const poppedView = this.popupViews[popupIndex];
|
||||
const cleanupAndFinish = () => {
|
||||
view.notify({ eventName: 'closed', object: view });
|
||||
this.removeChild(view);
|
||||
resolve();
|
||||
};
|
||||
// use exitAnimation that is passed in and fallback to the exitAnimation passed in when opening
|
||||
const exitAnimationDefinition = exitTo || poppedView?.options?.animation?.exitTo;
|
||||
resolve();
|
||||
})
|
||||
.then(() => {
|
||||
const popupIndex = this.getPopupIndex(view);
|
||||
const poppedView = this.popupViews[popupIndex];
|
||||
|
||||
// Remove view from tracked popupviews
|
||||
this.popupViews.splice(popupIndex, 1);
|
||||
if (!exitAnimationDefinition) {
|
||||
exitAnimationDefinition = poppedView?.options?.animation?.exitTo;
|
||||
}
|
||||
|
||||
if (this.shadeCover) {
|
||||
// update shade cover with the topmost popupView options (if not specifically told to ignore)
|
||||
if (!poppedView?.options?.shadeCover?.ignoreShadeRestore) {
|
||||
const shadeCoverOptions = this.popupViews[this.popupViews.length - 1]?.options?.shadeCover;
|
||||
if (shadeCoverOptions) {
|
||||
this.updateShadeCover(this.shadeCover, shadeCoverOptions);
|
||||
// Remove view from tracked popupviews
|
||||
this.popupViews.splice(popupIndex, 1);
|
||||
|
||||
if (this.shadeCover) {
|
||||
// update shade cover with the topmost popupView options (if not specifically told to ignore)
|
||||
if (!poppedView?.options?.shadeCover?.ignoreShadeRestore) {
|
||||
const shadeCoverOptions = this.popupViews[this.popupViews.length - 1]?.options?.shadeCover;
|
||||
if (shadeCoverOptions) {
|
||||
return this.updateShadeCover(this.shadeCover, shadeCoverOptions);
|
||||
}
|
||||
}
|
||||
// remove shade cover animation if this is the last opened popup view
|
||||
if (this.popupViews.length === 0) {
|
||||
return this.closeShadeCover(poppedView?.options?.shadeCover);
|
||||
}
|
||||
}
|
||||
// remove shade cover animation if this is the last opened popup view
|
||||
if (this.popupViews.length === 0) {
|
||||
this.closeShadeCover(poppedView?.options?.shadeCover);
|
||||
})
|
||||
.then(() => {
|
||||
if (exitAnimationDefinition) {
|
||||
return this.getExitAnimation(view, exitAnimationDefinition)
|
||||
.play()
|
||||
.then(cleanupAndFinish.bind(this))
|
||||
.catch((ex) => Promise.reject(new Error(`Error playing exit animation: ${ex}`)));
|
||||
}
|
||||
}
|
||||
|
||||
if (exitAnimationDefinition) {
|
||||
this.getExitAnimation(view, exitAnimationDefinition)
|
||||
.play()
|
||||
.then(cleanupAndFinish.bind(this))
|
||||
.catch((ex) => {
|
||||
reject(new Error(`Error playing exit animation: ${ex}`));
|
||||
});
|
||||
} else {
|
||||
cleanupAndFinish();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
closeAll(): Promise<void[]> {
|
||||
const toClose = [];
|
||||
const views = this.popupViews.map((popupView) => popupView.view);
|
||||
|
||||
// Close all views at the same time and wait for all of them
|
||||
while (this.popupViews.length > 0) {
|
||||
toClose.push(this.close(this.popupViews[this.popupViews.length - 1].view));
|
||||
for (const view of views) {
|
||||
toClose.push(this.close(view));
|
||||
}
|
||||
return Promise.all(toClose);
|
||||
}
|
||||
@@ -342,7 +355,7 @@ export class RootLayoutBase extends GridLayout {
|
||||
return shadeCover;
|
||||
}
|
||||
|
||||
private updateShadeCover(shade: View, shadeOptions: ShadeCoverOptions = {}): void {
|
||||
private updateShadeCover(shade: View, shadeOptions: ShadeCoverOptions = {}): Promise<void> {
|
||||
if (shadeOptions.tapToClose !== undefined && shadeOptions.tapToClose !== null) {
|
||||
shade.off('tap');
|
||||
if (shadeOptions.tapToClose) {
|
||||
@@ -351,7 +364,7 @@ export class RootLayoutBase extends GridLayout {
|
||||
});
|
||||
}
|
||||
}
|
||||
this._updateShadeCover(shade, shadeOptions);
|
||||
return this._updateShadeCover(shade, shadeOptions);
|
||||
}
|
||||
|
||||
private hasChild(view: View): boolean {
|
||||
|
||||
@@ -139,7 +139,7 @@ class UIViewControllerImpl extends UIViewController {
|
||||
return;
|
||||
}
|
||||
|
||||
const frame = this.navigationController ? (<any>this.navigationController).owner : null;
|
||||
const frame: Frame = this.navigationController ? (<any>this.navigationController).owner : null;
|
||||
const newEntry = this[ENTRY];
|
||||
|
||||
// Don't raise event if currentPage was showing modal page.
|
||||
@@ -149,6 +149,8 @@ class UIViewControllerImpl extends UIViewController {
|
||||
}
|
||||
|
||||
if (frame) {
|
||||
frame._resolvedPage = owner;
|
||||
|
||||
if (!owner.parent) {
|
||||
owner._frame = frame;
|
||||
if (!frame._styleScope) {
|
||||
|
||||
82
packages/core/utils/index.d.ts
vendored
82
packages/core/utils/index.d.ts
vendored
@@ -21,88 +21,6 @@ interface Owned {
|
||||
}
|
||||
//@endprivate
|
||||
|
||||
/**
|
||||
* Module with android specific utilities.
|
||||
*/
|
||||
export namespace ad {
|
||||
/**
|
||||
* Gets the native Android application instance.
|
||||
*/
|
||||
export function getApplication(): any; /* android.app.Application */
|
||||
|
||||
/**
|
||||
* Gets the Android application context.
|
||||
*/
|
||||
export function getApplicationContext(): any; /* android.content.Context */
|
||||
|
||||
/**
|
||||
* Gets the native Android input method manager.
|
||||
*/
|
||||
export function getInputMethodManager(): any; /* android.view.inputmethod.InputMethodManager */
|
||||
|
||||
/**
|
||||
* Hides the soft input method, usually a soft keyboard.
|
||||
*/
|
||||
export function dismissSoftInput(nativeView?: any /* android.view.View */): void;
|
||||
|
||||
/**
|
||||
* Shows the soft input method, usually a soft keyboard.
|
||||
*/
|
||||
export function showSoftInput(nativeView: any /* android.view.View */): void;
|
||||
|
||||
/**
|
||||
* Utility module dealing with some android collections.
|
||||
*/
|
||||
namespace collections {
|
||||
/**
|
||||
* Converts string array into a String [hash set](http://developer.android.com/reference/java/util/HashSet.html).
|
||||
* @param str - An array of strings to convert.
|
||||
*/
|
||||
export function stringArrayToStringSet(str: string[]): any;
|
||||
|
||||
/**
|
||||
* Converts string hash set into array of strings.
|
||||
* @param stringSet - A string hash set to convert.
|
||||
*/
|
||||
export function stringSetToStringArray(stringSet: any): string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility module related to android resources.
|
||||
*/
|
||||
export namespace resources {
|
||||
/**
|
||||
* Gets the drawable id from a given name.
|
||||
* @param name - Name of the resource.
|
||||
*/
|
||||
export function getDrawableId(name);
|
||||
|
||||
/**
|
||||
* Gets the string id from a given name.
|
||||
* @param name - Name of the resource.
|
||||
*/
|
||||
export function getStringId(name);
|
||||
|
||||
/**
|
||||
* Gets the id from a given name.
|
||||
* @param name - Name of the resource.
|
||||
*/
|
||||
export function getId(name: string): number;
|
||||
|
||||
/**
|
||||
* [Obsolete - please use getPaletteColor] Gets a color from current theme.
|
||||
* @param name - Name of the color
|
||||
*/
|
||||
export function getPalleteColor();
|
||||
|
||||
/**
|
||||
* Gets a color from the current theme.
|
||||
* @param name - Name of the color resource.
|
||||
*/
|
||||
export function getPaletteColor(name: string, context: any /* android.content.Context */): number;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An utility function that invokes garbage collection on the JavaScript side.
|
||||
*/
|
||||
|
||||
2
packages/types-android/src/lib/android.d.ts
vendored
2
packages/types-android/src/lib/android.d.ts
vendored
@@ -1 +1 @@
|
||||
/// <reference path="./android-17.d.ts" />
|
||||
/// <reference path="./android-31.d.ts" />
|
||||
@@ -17,6 +17,7 @@ import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
@@ -276,6 +277,44 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RectF backgroundBoundsF = new RectF();
|
||||
Path backgroundPath = new Path();
|
||||
RectF backgroundRect = new RectF();
|
||||
Paint backgroundColorPaint = new Paint();
|
||||
Path backgroundNoRepeatPath = new Path();
|
||||
Paint backgroundImagePaint = new Paint();
|
||||
Paint backgroundGradientPaint = new Paint();
|
||||
Paint borderPaint = new Paint();
|
||||
Path borderPath = new Path();
|
||||
RectF borderOuterRect = new RectF();
|
||||
RectF borderInnerRect = new RectF();
|
||||
|
||||
PointF lto = new PointF(); // left-top-outside
|
||||
PointF lti = new PointF(); // left-top-inside
|
||||
|
||||
PointF rto = new PointF(); // right-top-outside
|
||||
PointF rti = new PointF(); // right-top-outside
|
||||
|
||||
PointF rbo = new PointF(); // right-bottom-outside
|
||||
PointF rbi = new PointF(); // right-bottom-inside
|
||||
|
||||
PointF lbo = new PointF(); // left-bottom-outside
|
||||
PointF lbi = new PointF(); // left-bottom-inside
|
||||
|
||||
|
||||
Paint topBorderPaint = new Paint();
|
||||
Path topBorderPath = new Path();
|
||||
|
||||
Paint rightBorderPaint = new Paint();
|
||||
Path rightBorderPath = new Path();
|
||||
|
||||
Paint bottomBorderPaint = new Paint();
|
||||
Path bottomBorderPath = new Path();
|
||||
|
||||
Paint leftBorderPaint = new Paint();
|
||||
Path leftBorderPath = new Path();
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
Rect bounds = this.getBounds();
|
||||
@@ -287,7 +326,7 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
return;
|
||||
}
|
||||
|
||||
RectF backgroundBoundsF = new RectF(bounds.left, bounds.top, bounds.right, bounds.bottom);
|
||||
backgroundBoundsF.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
|
||||
|
||||
float topBackoffAntialias = calculateBackoffAntialias(this.borderTopColor, this.borderTopWidth);
|
||||
float rightBackoffAntialias = calculateBackoffAntialias(this.borderRightColor, this.borderRightWidth);
|
||||
@@ -301,18 +340,18 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
Math.max(0, borderBottomLeftRadius + leftBackoffAntialias), Math.max(0, borderBottomLeftRadius + bottomBackoffAntialias)
|
||||
};
|
||||
|
||||
Path backgroundPath = new Path();
|
||||
RectF backgroundRect = new RectF(
|
||||
leftBackoffAntialias,
|
||||
backgroundPath.reset();
|
||||
|
||||
backgroundRect.set(leftBackoffAntialias,
|
||||
topBackoffAntialias,
|
||||
width - rightBackoffAntialias,
|
||||
height - bottomBackoffAntialias
|
||||
);
|
||||
height - bottomBackoffAntialias);
|
||||
|
||||
backgroundPath.addRoundRect(backgroundRect, backgroundRadii, Path.Direction.CW);
|
||||
|
||||
// draw background
|
||||
if (this.backgroundColor != 0) {
|
||||
Paint backgroundColorPaint = new Paint();
|
||||
backgroundColorPaint.reset();
|
||||
backgroundColorPaint.setStyle(Paint.Style.FILL);
|
||||
backgroundColorPaint.setColor(this.backgroundColor);
|
||||
backgroundColorPaint.setAntiAlias(true);
|
||||
@@ -337,7 +376,9 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
}
|
||||
transform.postTranslate(params.posX, params.posY);
|
||||
|
||||
Paint backgroundImagePaint = new Paint();
|
||||
|
||||
backgroundImagePaint.reset();
|
||||
|
||||
BitmapShader shader = new BitmapShader(
|
||||
this.backgroundBitmap,
|
||||
params.repeatX ? Shader.TileMode.REPEAT : Shader.TileMode.CLAMP,
|
||||
@@ -358,7 +399,7 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
} else {
|
||||
boolean supportsPathOp = android.os.Build.VERSION.SDK_INT >= 19;
|
||||
if (supportsPathOp) {
|
||||
Path backgroundNoRepeatPath = new Path();
|
||||
backgroundNoRepeatPath.reset();
|
||||
backgroundNoRepeatPath.addRect(params.posX, params.posY, params.posX + imageWidth, params.posY + imageHeight, Path.Direction.CCW);
|
||||
intersect(backgroundNoRepeatPath, backgroundPath);
|
||||
canvas.drawPath(backgroundNoRepeatPath, backgroundImagePaint);
|
||||
@@ -374,7 +415,9 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
|
||||
if (this.backgroundGradient != null) {
|
||||
LinearGradientDefinition def = this.backgroundGradient;
|
||||
Paint backgroundGradientPaint = new Paint();
|
||||
|
||||
backgroundGradientPaint.reset();
|
||||
|
||||
LinearGradient shader = new LinearGradient(
|
||||
def.getStartX() * width, def.getStartY() * height,
|
||||
def.getEndX() * width, def.getEndY() * height,
|
||||
@@ -394,7 +437,7 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
if (this.clipPath != null && !this.clipPath.isEmpty()) {
|
||||
float borderWidth = this.getUniformBorderWidth();
|
||||
if (borderWidth > 0) {
|
||||
Paint borderPaint = new Paint();
|
||||
borderPaint.reset();
|
||||
borderPaint.setColor(this.getUniformBorderColor());
|
||||
borderPaint.setStyle(Paint.Style.STROKE);
|
||||
borderPaint.setStrokeWidth(borderWidth);
|
||||
@@ -405,13 +448,15 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
} else if (this.hasUniformBorderColor()) {
|
||||
// iOS and browsers use black when no color is specified.
|
||||
if (borderLeftWidth > 0 || borderTopWidth > 0 || borderRightWidth > 0 || borderBottomWidth > 0) {
|
||||
Paint borderPaint = new Paint();
|
||||
borderPaint.reset();
|
||||
borderPaint.setColor(this.getUniformBorderColor());
|
||||
borderPaint.setStyle(Paint.Style.FILL);
|
||||
borderPaint.setAntiAlias(true);
|
||||
Path borderPath = new Path();
|
||||
|
||||
RectF borderOuterRect = new RectF(0, 0, width, height);
|
||||
borderPath.reset();
|
||||
|
||||
borderOuterRect.set(0, 0, width, height);
|
||||
|
||||
float[] borderOuterRadii = {
|
||||
borderTopLeftRadius, borderTopLeftRadius,
|
||||
borderTopRightRadius, borderTopRightRadius,
|
||||
@@ -420,7 +465,7 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
};
|
||||
borderPath.addRoundRect(borderOuterRect, borderOuterRadii, Path.Direction.CW);
|
||||
|
||||
RectF borderInnerRect = new RectF(
|
||||
borderInnerRect.set(
|
||||
borderLeftWidth,
|
||||
borderTopWidth,
|
||||
width - borderRightWidth,
|
||||
@@ -453,23 +498,25 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
// +---------------------+
|
||||
//lbo rbo
|
||||
|
||||
PointF lto = new PointF(0, 0); // left-top-outside
|
||||
PointF lti = new PointF(left, top); // left-top-inside
|
||||
lto.set(0, 0); // left-top-outside
|
||||
lti.set(left, top); // left-top-inside
|
||||
|
||||
PointF rto = new PointF(bounds.right, 0); // right-top-outside
|
||||
PointF rti = new PointF(bounds.right - right, top); // right-top-outside
|
||||
rto.set(bounds.right, 0); // right-top-outside
|
||||
rti.set(bounds.right - right, top); // right-top-outside
|
||||
|
||||
PointF rbo = new PointF(bounds.right, bounds.bottom); // right-bottom-outside
|
||||
PointF rbi = new PointF(bounds.right - right, bounds.bottom - bottom); // right-bottom-inside
|
||||
rbo.set(bounds.right, bounds.bottom); // right-bottom-outside
|
||||
rbi.set(bounds.right - right, bounds.bottom - bottom); // right-bottom-inside
|
||||
|
||||
lbo.set(0, bounds.bottom); // left-bottom-outside
|
||||
lbi.set(left, bounds.bottom - bottom); // left-bottom-inside
|
||||
|
||||
PointF lbo = new PointF(0, bounds.bottom); // left-bottom-outside
|
||||
PointF lbi = new PointF(left, bounds.bottom - bottom); // left-bottom-inside
|
||||
|
||||
if (this.borderTopWidth > 0) {
|
||||
Paint topBorderPaint = new Paint();
|
||||
topBorderPaint.reset();
|
||||
topBorderPaint.setColor(this.borderTopColor);
|
||||
topBorderPaint.setAntiAlias(true);
|
||||
Path topBorderPath = new Path();
|
||||
|
||||
topBorderPath.reset();
|
||||
topBorderPath.setFillType(Path.FillType.EVEN_ODD);
|
||||
topBorderPath.moveTo(lto.x, lto.y);
|
||||
topBorderPath.lineTo(rto.x, rto.y);
|
||||
@@ -480,10 +527,12 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
}
|
||||
|
||||
if (this.borderRightWidth > 0) {
|
||||
Paint rightBorderPaint = new Paint();
|
||||
|
||||
rightBorderPaint.reset();
|
||||
rightBorderPaint.setColor(this.borderRightColor);
|
||||
rightBorderPaint.setAntiAlias(true);
|
||||
Path rightBorderPath = new Path();
|
||||
|
||||
rightBorderPath.reset();
|
||||
rightBorderPath.setFillType(Path.FillType.EVEN_ODD);
|
||||
rightBorderPath.moveTo(rto.x, rto.y);
|
||||
rightBorderPath.lineTo(rbo.x, rbo.y);
|
||||
@@ -494,10 +543,12 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
}
|
||||
|
||||
if (this.borderBottomWidth > 0) {
|
||||
Paint bottomBorderPaint = new Paint();
|
||||
|
||||
bottomBorderPaint.reset();
|
||||
bottomBorderPaint.setColor(this.borderBottomColor);
|
||||
bottomBorderPaint.setAntiAlias(true);
|
||||
Path bottomBorderPath = new Path();
|
||||
|
||||
bottomBorderPath.reset();
|
||||
bottomBorderPath.setFillType(Path.FillType.EVEN_ODD);
|
||||
bottomBorderPath.moveTo(rbo.x, rbo.y);
|
||||
bottomBorderPath.lineTo(lbo.x, lbo.y);
|
||||
@@ -508,10 +559,11 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
}
|
||||
|
||||
if (this.borderLeftWidth > 0) {
|
||||
Paint leftBorderPaint = new Paint();
|
||||
leftBorderPaint.reset();
|
||||
leftBorderPaint.setColor(this.borderLeftColor);
|
||||
leftBorderPaint.setAntiAlias(true);
|
||||
Path leftBorderPath = new Path();
|
||||
|
||||
leftBorderPath.reset();
|
||||
leftBorderPath.setFillType(Path.FillType.EVEN_ODD);
|
||||
leftBorderPath.moveTo(lbo.x, lbo.y);
|
||||
leftBorderPath.lineTo(lto.x, lto.y);
|
||||
@@ -606,7 +658,12 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
top = cY - rY;
|
||||
right = (rX * 2) + left;
|
||||
bottom = (rY * 2) + top;
|
||||
canvas.drawOval(new RectF(left, top, right, bottom), paint);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
canvas.drawOval(left, top, right, bottom, paint);
|
||||
} else {
|
||||
canvas.drawOval(new RectF(left, top, right, bottom), paint);
|
||||
}
|
||||
break;
|
||||
case "polygon":
|
||||
Path path = new Path();
|
||||
@@ -832,18 +889,31 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
return drawable;
|
||||
}
|
||||
|
||||
|
||||
private final Path outlineBackgroundPath = new Path();
|
||||
private final RectF outlineRectF = new RectF();
|
||||
|
||||
@Override
|
||||
public void getOutline(@NonNull Outline outline) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= 21) {
|
||||
Path backgroundPath = new Path();
|
||||
outlineBackgroundPath.reset();
|
||||
float[] backgroundRadii = {
|
||||
Math.max(0, borderTopLeftRadius), Math.max(0, borderTopLeftRadius),
|
||||
Math.max(0, borderTopRightRadius), Math.max(0, borderTopRightRadius),
|
||||
Math.max(0, borderBottomRightRadius), Math.max(0, borderBottomRightRadius),
|
||||
Math.max(0, borderBottomLeftRadius), Math.max(0, borderBottomLeftRadius)
|
||||
};
|
||||
backgroundPath.addRoundRect(new RectF(getBounds()), backgroundRadii, Path.Direction.CW);
|
||||
outline.setConvexPath(backgroundPath);
|
||||
outlineRectF.setEmpty();
|
||||
outlineRectF.set(getBounds());
|
||||
outlineBackgroundPath.addRoundRect(outlineRectF, backgroundRadii, Path.Direction.CW);
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
// see setConvexPath notes
|
||||
outline.setPath(outlineBackgroundPath);
|
||||
} else {
|
||||
outline.setConvexPath(outlineBackgroundPath);
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new IllegalStateException("Method supported on API 21 or higher");
|
||||
}
|
||||
|
||||
@@ -223,8 +223,9 @@ public class GridLayout extends LayoutBase {
|
||||
}
|
||||
|
||||
private void removeFromMap(View child) {
|
||||
this.map.get(child).child = null;
|
||||
this.map.remove(child);
|
||||
if (this.map.containsKey(child)) {
|
||||
this.map.remove(child).child = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,17 +2,13 @@ package org.nativescript.widgets;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* @author hhristov
|
||||
*/
|
||||
@@ -23,7 +19,7 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
|
||||
private int contentMeasuredWidth = 0;
|
||||
private int contentMeasuredHeight = 0;
|
||||
private int scrollableLength = 0;
|
||||
private SavedState mSavedState;
|
||||
private ScrollSavedState mSavedState;
|
||||
private boolean isFirstLayout = true;
|
||||
private boolean scrollEnabled = true;
|
||||
|
||||
@@ -180,7 +176,7 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
|
||||
|
||||
this.mIsLayoutDirty = false;
|
||||
// Give a child focus if it needs it
|
||||
if (this.mChildToScrollTo != null && isViewDescendantOf(this.mChildToScrollTo, this)) {
|
||||
if (this.mChildToScrollTo != null && Utils.isViewDescendantOf(this.mChildToScrollTo, this)) {
|
||||
this.scrollToChild(this.mChildToScrollTo);
|
||||
}
|
||||
|
||||
@@ -194,7 +190,7 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
|
||||
|
||||
final int scrollRange = Math.max(0, childWidth - (right - left - this.getPaddingLeft() - this.getPaddingRight()));
|
||||
if (this.mSavedState != null) {
|
||||
scrollX = (this.isLayoutRtl() == mSavedState.isLayoutRtl) ? mSavedState.scrollPosition : (scrollRange - this.mSavedState.scrollPosition);
|
||||
scrollX = this.isLayoutRtl() ? scrollRange - mSavedState.scrollOffsetFromStart : mSavedState.scrollOffsetFromStart;
|
||||
mSavedState = null;
|
||||
} else {
|
||||
if (this.isLayoutRtl()) {
|
||||
@@ -228,7 +224,7 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
SavedState ss = (SavedState) state;
|
||||
ScrollSavedState ss = (ScrollSavedState) state;
|
||||
super.onRestoreInstanceState(ss.getSuperState());
|
||||
this.mSavedState = ss;
|
||||
this.requestLayout();
|
||||
@@ -237,9 +233,8 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState() {
|
||||
Parcelable superState = super.onSaveInstanceState();
|
||||
SavedState ss = new SavedState(superState);
|
||||
ss.scrollPosition = this.getScrollX();
|
||||
ss.isLayoutRtl = this.isLayoutRtl();
|
||||
ScrollSavedState ss = new ScrollSavedState(superState);
|
||||
ss.scrollOffsetFromStart = isLayoutRtl() ? -this.getScrollX() : this.getScrollX();
|
||||
return ss;
|
||||
}
|
||||
|
||||
@@ -258,58 +253,4 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
|
||||
private boolean isLayoutRtl() {
|
||||
return (this.getLayoutDirection() == LAYOUT_DIRECTION_RTL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if child is a descendant of parent, (or equal to the parent).
|
||||
*/
|
||||
static boolean isViewDescendantOf(View child, View parent) {
|
||||
if (child == parent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final ViewParent theParent = child.getParent();
|
||||
return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent);
|
||||
}
|
||||
|
||||
static class SavedState extends BaseSavedState {
|
||||
public int scrollPosition;
|
||||
public boolean isLayoutRtl;
|
||||
|
||||
SavedState(Parcelable superState) {
|
||||
super(superState);
|
||||
}
|
||||
|
||||
public SavedState(Parcel source) {
|
||||
super(source);
|
||||
scrollPosition = source.readInt();
|
||||
isLayoutRtl = source.readInt() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeInt(scrollPosition);
|
||||
dest.writeInt(isLayoutRtl ? 1 : 0);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HorizontalScrollView.SavedState{"
|
||||
+ Integer.toHexString(System.identityHashCode(this))
|
||||
+ " scrollPosition=" + scrollPosition
|
||||
+ " isLayoutRtl=" + isLayoutRtl + "}";
|
||||
}
|
||||
|
||||
public static final Creator<SavedState> CREATOR
|
||||
= new Creator<SavedState>() {
|
||||
public SavedState createFromParcel(Parcel in) {
|
||||
return new SavedState(in);
|
||||
}
|
||||
|
||||
public SavedState[] newArray(int size) {
|
||||
return new SavedState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,14 @@ import android.graphics.ColorFilter;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
|
||||
import org.nativescript.widgets.image.BitmapOwner;
|
||||
@@ -26,6 +30,7 @@ public class ImageView extends androidx.appcompat.widget.AppCompatImageView impl
|
||||
|
||||
private final Path path = new Path();
|
||||
private final RectF rect = new RectF();
|
||||
private final Paint paint = new Paint();
|
||||
|
||||
private double scaleW = 1;
|
||||
private double scaleH = 1;
|
||||
@@ -209,6 +214,8 @@ public class ImageView extends androidx.appcompat.widget.AppCompatImageView impl
|
||||
}
|
||||
}
|
||||
|
||||
private boolean mSettingBitmap = false;
|
||||
|
||||
@Override
|
||||
public void setImageBitmap(Bitmap bm) {
|
||||
Fetcher fetcher = Fetcher.getInstance(this.getContext());
|
||||
@@ -217,11 +224,75 @@ public class ImageView extends androidx.appcompat.widget.AppCompatImageView impl
|
||||
if (mUseCache && mUri != null && mBitmap != null && fetcher != null) {
|
||||
fetcher.removeBitmap(mUri);
|
||||
}
|
||||
|
||||
mSettingBitmap = true;
|
||||
super.setImageBitmap(bm);
|
||||
this.mBitmap = bm;
|
||||
if (bm != null) {
|
||||
bitmapWidth = bm.getWidth();
|
||||
bitmapHeight = bm.getHeight();
|
||||
bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||
} else {
|
||||
bitmapWidth = -1;
|
||||
bitmapHeight = -1;
|
||||
}
|
||||
mSettingBitmap = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageDrawable(@Nullable Drawable drawable) {
|
||||
super.setImageDrawable(drawable);
|
||||
setBitmapShader();
|
||||
}
|
||||
|
||||
|
||||
private final Canvas canvas = new Canvas();
|
||||
private BitmapShader bitmapShader = null;
|
||||
private int bitmapWidth = -1;
|
||||
private int bitmapHeight = -1;
|
||||
|
||||
private void setBitmapShader() {
|
||||
if (mSettingBitmap) {
|
||||
return;
|
||||
}
|
||||
Bitmap mBitmap = null;
|
||||
Drawable drawable = getDrawable();
|
||||
if (drawable != null) {
|
||||
|
||||
if (drawable instanceof BitmapDrawable) {
|
||||
mBitmap = ((BitmapDrawable) drawable).getBitmap();
|
||||
} else {
|
||||
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
||||
canvas.setBitmap(bitmap);
|
||||
Rect previousBounds = null;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
previousBounds = drawable.getBounds();
|
||||
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
|
||||
}
|
||||
|
||||
drawable.draw(canvas);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
drawable.setBounds(previousBounds);
|
||||
}
|
||||
mBitmap = bitmap;
|
||||
}
|
||||
} else {
|
||||
bitmapShader = null;
|
||||
}
|
||||
|
||||
if (mBitmap != null) {
|
||||
bitmapWidth = mBitmap.getWidth();
|
||||
bitmapHeight = mBitmap.getHeight();
|
||||
bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||
} else {
|
||||
bitmapWidth = -1;
|
||||
bitmapHeight = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
BorderDrawable background = this.getBackground() instanceof BorderDrawable ? (BorderDrawable) this.getBackground() : null;
|
||||
@@ -257,17 +328,21 @@ public class ImageView extends androidx.appcompat.widget.AppCompatImageView impl
|
||||
innerHeight = this.getHeight() - borderTopWidth - borderBottomWidth;
|
||||
|
||||
// TODO: Capture all created objects here in locals and update them instead...
|
||||
Path path = new Path();
|
||||
path.reset();
|
||||
paint.reset();
|
||||
|
||||
float[] radii = {
|
||||
Math.max(0, borderTopLeftRadius - borderLeftWidth), Math.max(0, borderTopLeftRadius - borderTopWidth),
|
||||
Math.max(0, borderTopRightRadius - borderRightWidth), Math.max(0, borderTopRightRadius - borderTopWidth),
|
||||
Math.max(0, borderBottomRightRadius - borderRightWidth), Math.max(0, borderBottomRightRadius - borderBottomWidth),
|
||||
Math.max(0, borderBottomLeftRadius - borderLeftWidth), Math.max(0, borderBottomLeftRadius - borderBottomWidth)
|
||||
};
|
||||
path.addRoundRect(new RectF(borderLeftWidth, borderTopWidth, borderLeftWidth + innerWidth, borderTopWidth + innerHeight), radii, Path.Direction.CW);
|
||||
|
||||
Paint paint = new Paint();
|
||||
BitmapShader bitmapShader = new BitmapShader(this.mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||
rect.setEmpty();
|
||||
rect.set(borderLeftWidth, borderTopWidth, borderLeftWidth + innerWidth, borderTopWidth + innerHeight);
|
||||
|
||||
path.addRoundRect(rect, radii, Path.Direction.CW);
|
||||
|
||||
|
||||
float bitmapWidth = (float) mBitmap.getWidth();
|
||||
float bitmapHeight = (float) mBitmap.getHeight();
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.nativescript.widgets;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.view.View.BaseSavedState;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
/**
|
||||
* @author CatchABus
|
||||
*/
|
||||
class ScrollSavedState extends BaseSavedState {
|
||||
public int scrollOffsetFromStart;
|
||||
|
||||
ScrollSavedState(Parcelable superState) {
|
||||
super(superState);
|
||||
}
|
||||
|
||||
public ScrollSavedState(Parcel source) {
|
||||
super(source);
|
||||
scrollOffsetFromStart = source.readInt();
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
public ScrollSavedState(Parcel source, ClassLoader loader) {
|
||||
super(source, loader);
|
||||
scrollOffsetFromStart = source.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeInt(scrollOffsetFromStart);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ScrollSavedState{"
|
||||
+ Integer.toHexString(System.identityHashCode(this))
|
||||
+ " scrollPosition=" + scrollOffsetFromStart
|
||||
+ "}";
|
||||
}
|
||||
|
||||
public static final Creator<ScrollSavedState> CREATOR = new ClassLoaderCreator<ScrollSavedState>() {
|
||||
public ScrollSavedState createFromParcel(Parcel in, ClassLoader loader)
|
||||
{
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? new ScrollSavedState(in, loader) : new ScrollSavedState(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScrollSavedState createFromParcel(Parcel in)
|
||||
{
|
||||
return createFromParcel(in, null);
|
||||
}
|
||||
|
||||
public ScrollSavedState[] newArray(int size) {
|
||||
return new ScrollSavedState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.core.view.ViewCompat;
|
||||
@@ -512,6 +513,18 @@ public class Utils {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if child is a descendant of parent, (or equal to the parent).
|
||||
*/
|
||||
static boolean isViewDescendantOf(View child, View parent) {
|
||||
if (child == parent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final ViewParent childParent = child.getParent();
|
||||
return (childParent instanceof ViewGroup) && isViewDescendantOf((View) childParent, parent);
|
||||
}
|
||||
|
||||
// public static void clearBoxShadow(View view) {
|
||||
// if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
|
||||
// return;
|
||||
|
||||
@@ -10,8 +10,6 @@ import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import androidx.core.widget.NestedScrollView;
|
||||
|
||||
import org.nativescript.widgets.HorizontalScrollView.SavedState;
|
||||
|
||||
/**
|
||||
* @author hhristov
|
||||
*/
|
||||
@@ -22,7 +20,7 @@ public class VerticalScrollView extends NestedScrollView {
|
||||
private int contentMeasuredWidth = 0;
|
||||
private int contentMeasuredHeight = 0;
|
||||
private int scrollableLength = 0;
|
||||
private SavedState mSavedState;
|
||||
private ScrollSavedState mSavedState;
|
||||
private boolean isFirstLayout = true;
|
||||
private boolean scrollEnabled = true;
|
||||
|
||||
@@ -186,7 +184,7 @@ public class VerticalScrollView extends NestedScrollView {
|
||||
|
||||
this.mIsLayoutDirty = false;
|
||||
// Give a child focus if it needs it
|
||||
if (this.mChildToScrollTo != null && HorizontalScrollView.isViewDescendantOf(this.mChildToScrollTo, this)) {
|
||||
if (this.mChildToScrollTo != null && Utils.isViewDescendantOf(this.mChildToScrollTo, this)) {
|
||||
this.scrollToChild(this.mChildToScrollTo);
|
||||
}
|
||||
|
||||
@@ -200,7 +198,7 @@ public class VerticalScrollView extends NestedScrollView {
|
||||
final int scrollRange = Math.max(0,
|
||||
childHeight - (bottom - top - this.getPaddingTop() - this.getPaddingBottom()));
|
||||
if (this.mSavedState != null) {
|
||||
scrollY = mSavedState.scrollPosition;
|
||||
scrollY = mSavedState.scrollOffsetFromStart;
|
||||
mSavedState = null;
|
||||
}
|
||||
|
||||
@@ -232,7 +230,7 @@ public class VerticalScrollView extends NestedScrollView {
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
SavedState ss = (SavedState) state;
|
||||
ScrollSavedState ss = (ScrollSavedState) state;
|
||||
super.onRestoreInstanceState(ss.getSuperState());
|
||||
this.mSavedState = ss;
|
||||
this.requestLayout();
|
||||
@@ -241,8 +239,8 @@ public class VerticalScrollView extends NestedScrollView {
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState() {
|
||||
Parcelable superState = super.onSaveInstanceState();
|
||||
SavedState ss = new SavedState(superState);
|
||||
ss.scrollPosition = this.getScrollY();
|
||||
ScrollSavedState ss = new ScrollSavedState(superState);
|
||||
ss.scrollOffsetFromStart = this.getScrollY();
|
||||
return ss;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ Passing an `Error` to the `done()` callback will cause the test to fail:
|
||||
|
||||
```typescript
|
||||
export function test_getJSON(done) {
|
||||
http.getJSON("https://httpbin.org/get").then(
|
||||
http.getJSON("https://http-echo.nativescript.org/get").then(
|
||||
(result) => { done(); }, // success
|
||||
(error) => { done(error); }); // fail
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ const spawned_process = spawn(
|
||||
"run",
|
||||
`apps-automated:${platform}`,
|
||||
// "--log=trace",
|
||||
// `--flags="--log=trace"`,
|
||||
"--timeout=600" // 10 minutes, booting avds on CI is very slow...
|
||||
],
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user