diff --git a/apps/automated/src/file-system/file-system-tests.ts b/apps/automated/src/file-system/file-system-tests.ts index f7bc2bb908..559d3126cc 100644 --- a/apps/automated/src/file-system/file-system-tests.ts +++ b/apps/automated/src/file-system/file-system-tests.ts @@ -61,7 +61,7 @@ export var testFileFromPath = function () { function (error) { TKUnit.assert(false, 'Failed to read/write text'); //console.dir(error); - } + }, ); // << (hide) }, @@ -71,7 +71,7 @@ export var testFileFromPath = function () { TKUnit.assert(false, 'Failed to read/write text'); //console.dir(error); // << (hide) - } + }, ); // << file-system-create }; @@ -106,7 +106,7 @@ export var testFileWrite = function () { function (error) { TKUnit.assert(false, 'Failed to read/write text'); //console.dir(error); - } + }, ); // << (hide) }, @@ -116,7 +116,7 @@ export var testFileWrite = function () { TKUnit.assert(false, 'Failed to read/write text'); //console.dir(error); // << (hide) - } + }, ); // << file-system-write-string }; @@ -172,7 +172,7 @@ export var testFileRead = function () { TKUnit.assert(false, 'Failed to read/write text'); //console.dir(error); // << (hide) - } + }, ); }, function (error) { @@ -181,7 +181,7 @@ export var testFileRead = function () { TKUnit.assert(false, 'Failed to read/write text'); //console.dir(error); // << (hide) - } + }, ); // << file-system-example-text }; @@ -245,13 +245,13 @@ export var testFileReadWriteBinaryAsync = function () { }, function (error) { TKUnit.assert(false, 'Failed to read destination binary async'); - } + }, ); }, function (error) { // Failed to write the file. TKUnit.assert(false, 'Failed to write binary async'); - } + }, ); // << (hide) }, @@ -260,7 +260,7 @@ export var testFileReadWriteBinaryAsync = function () { // >> (hide) TKUnit.assert(false, 'Failed to read binary async'); // << (hide) - } + }, ); // << file-system-read-binary-async }; @@ -358,7 +358,7 @@ export var testGetEntities = function () { function (error) { // Failed to obtain folder's contents. // globalConsole.error(error.message); - } + }, ); // << file-system-folders-content }; @@ -493,7 +493,7 @@ export var testFileRename = function () { // >> (hide) TKUnit.assert(false, 'Failed to rename file'); // << (hide) - } + }, ); // << file-system-renaming }; @@ -517,7 +517,7 @@ export var testFolderRename = function () { // >> (hide) TKUnit.assert(false, 'Folder.rename API not working.'); // << (hide) - } + }, ); // << file-system-renaming-folder }; @@ -538,7 +538,7 @@ export var testFileRemove = function () { // >> (hide) TKUnit.assert(false, 'File.remove API not working.'); // << (hide) - } + }, ); // << file-system-remove-file }; @@ -560,7 +560,7 @@ export var testFolderRemove = function () { // >> (hide) TKUnit.assert(false, 'File.remove API not working.'); // << (hide) - } + }, ); // << file-system-remove-folder }; @@ -587,7 +587,7 @@ export var testFolderClear = function () { // >> (hide) TKUnit.assert(false, error.message); // << (hide) - } + }, ); // >> (hide) folder.getEntities().then(function (entities) { @@ -609,7 +609,7 @@ export var testKnownFolderRename = function () { }, function (error) { TKUnit.assert(true); - } + }, ); } }; @@ -625,7 +625,7 @@ export function testKnownFolderRemove(done) { }, function (error) { done(null); - } + }, ); } diff --git a/apps/automated/src/ui/activity-indicator/activity-indicator-tests.ts b/apps/automated/src/ui/activity-indicator/activity-indicator-tests.ts index 0e811cb965..2b9c32a3a4 100644 --- a/apps/automated/src/ui/activity-indicator/activity-indicator-tests.ts +++ b/apps/automated/src/ui/activity-indicator/activity-indicator-tests.ts @@ -79,7 +79,7 @@ function binding_busy_to_image() { sourceProperty: 'isLoading', targetProperty: 'busy', }, - image + image, ); // << activity-indicator-loading } diff --git a/apps/automated/src/ui/button/button-tests-native.android.ts b/apps/automated/src/ui/button/button-tests-native.android.ts index c5c03d74c8..ac63dff76a 100644 --- a/apps/automated/src/ui/button/button-tests-native.android.ts +++ b/apps/automated/src/ui/button/button-tests-native.android.ts @@ -1,4 +1,5 @@ import { Color, Button, Utils, CoreTypes } from '@nativescript/core'; +import { AndroidHelper } from '@nativescript/core/ui/core/view'; export function getNativeText(button: Button): string { return button.android.getText(); @@ -19,15 +20,7 @@ export function getNativeColor(button: Button): Color { } export function getNativeBackgroundColor(button: Button): Color { - let bg = button.android.getBackground(); - if (bg instanceof org.nativescript.widgets.BorderDrawable) { - return new Color(bg.getBackgroundColor()); - } else if (bg instanceof android.graphics.drawable.ColorDrawable) { - console.log(bg); - return new Color(bg.getColor()); - } else { - return new Color(bg.backgroundColor); - } + return AndroidHelper.getDrawableColor(button.android.getBackground()); } export function getNativeTextAlignment(button: Button): string { diff --git a/apps/automated/src/ui/label/label-tests-native.android.ts b/apps/automated/src/ui/label/label-tests-native.android.ts index 426bddf5d3..c91ea1afd1 100644 --- a/apps/automated/src/ui/label/label-tests-native.android.ts +++ b/apps/automated/src/ui/label/label-tests-native.android.ts @@ -1,6 +1,6 @@ import * as labelModule from '@nativescript/core/ui/label'; -import { CoreTypes } from '@nativescript/core'; -import * as colorModule from '@nativescript/core/color'; +import { Color, CoreTypes } from '@nativescript/core'; +import { AndroidHelper } from '@nativescript/core/ui/core/view'; export function getNativeTextAlignment(label: labelModule.Label): string { let gravity = label.android.getGravity(); @@ -20,13 +20,6 @@ export function getNativeTextAlignment(label: labelModule.Label): string { return 'unexpected value'; } -export function getNativeBackgroundColor(label: labelModule.Label): colorModule.Color { - let bg = label.android.getBackground(); - if (bg instanceof org.nativescript.widgets.BorderDrawable) { - return new colorModule.Color(bg.getBackgroundColor()); - } else if (bg instanceof android.graphics.drawable.ColorDrawable) { - return new colorModule.Color(bg.getColor()); - } else { - return new colorModule.Color(bg.backgroundColor); - } +export function getNativeBackgroundColor(label: labelModule.Label): Color { + return AndroidHelper.getDrawableColor(label.android.getBackground()); } diff --git a/apps/automated/src/ui/layouts/safe-area-tests.ts b/apps/automated/src/ui/layouts/safe-area-tests.ts index c5c979b284..a4a7048b91 100644 --- a/apps/automated/src/ui/layouts/safe-area-tests.ts +++ b/apps/automated/src/ui/layouts/safe-area-tests.ts @@ -25,7 +25,7 @@ export class SafeAreaTests extends testModule.UITest { waitUntilTestElementLayoutIsValid(ui.root); test(ui); }, - pageOptions + pageOptions, ); } @@ -116,7 +116,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_in_full_screen_test(root, pageOptions); }, - pageOptions + pageOptions, ); } @@ -151,7 +151,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBar: true } + { actionBar: true }, ); } @@ -166,7 +166,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_hidden_test(root); }, - { actionBarHidden: true } + { actionBarHidden: true }, ); } @@ -181,7 +181,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBarFlat: true } + { actionBarFlat: true }, ); } @@ -196,7 +196,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_hidden_test(root); }, - { tabBar: true } + { tabBar: true }, ); } @@ -211,7 +211,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBar: true, tabBar: true } + { actionBar: true, tabBar: true }, ); } @@ -233,7 +233,7 @@ export class SafeAreaTests extends testModule.UITest { equal(left(child0), insets.left, `${child0}.left - actual: ${left(child0)} expected: ${insets.left}`); equal(top(child0), insets.top, `${child0}.top - actual: ${top(child0)} expected: ${insets.top}`); }, - pageOptions + pageOptions, ); } @@ -274,7 +274,7 @@ export class SafeAreaTests extends testModule.UITest { isLeftAlignedWith(root, child0); isTopAlignedWith(root, child0); }, - pageOptions + pageOptions, ); } @@ -315,7 +315,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_in_full_screen_test(root, pageOptions); }, - pageOptions + pageOptions, ); } @@ -350,7 +350,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBar: true } + { actionBar: true }, ); } @@ -365,7 +365,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_hidden_test(root); }, - { actionBarHidden: true } + { actionBarHidden: true }, ); } @@ -380,7 +380,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBarFlat: true } + { actionBarFlat: true }, ); } @@ -395,7 +395,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_hidden_test(root); }, - { tabBar: true } + { tabBar: true }, ); } @@ -410,7 +410,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBar: true, tabBar: true } + { actionBar: true, tabBar: true }, ); } @@ -447,7 +447,7 @@ export class SafeAreaTests extends testModule.UITest { isRightWith(childFill, childRight, width(childRight)); isAboveWith(childFill, childBottom, height(childBottom)); }, - pageOptions + pageOptions, ); } @@ -505,7 +505,7 @@ export class SafeAreaTests extends testModule.UITest { const sumOfNestedDockWidths = width(childLeft) + width(childFill) + width(childRight); equal(width(root), sumOfNestedDockWidths, `dock width<${width(root)}> sum of nested docks width <${sumOfNestedDockWidths}>`); }, - pageOptions + pageOptions, ); } @@ -533,7 +533,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_in_full_screen_test(root, pageOptions); }, - pageOptions + pageOptions, ); } @@ -568,7 +568,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBar: true } + { actionBar: true }, ); } @@ -583,7 +583,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_hidden_test(root); }, - { actionBarHidden: true } + { actionBarHidden: true }, ); } @@ -598,7 +598,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBarFlat: true } + { actionBarFlat: true }, ); } @@ -613,7 +613,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_hidden_test(root); }, - { tabBar: true } + { tabBar: true }, ); } @@ -628,7 +628,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBar: true, tabBar: true } + { actionBar: true, tabBar: true }, ); } @@ -655,7 +655,7 @@ export class SafeAreaTests extends testModule.UITest { equal(bottom(child2), height(root) - insets.bottom, `${child2}.bottom - actual: ${bottom(child2)} expected: ${height(root) - insets.bottom}`); equal(right(child2), width(root) - insets.right, `${child2}.right - actual: ${right(child2)} expected: ${width(root) - insets.right}`); }, - pageOptions + pageOptions, ); } @@ -694,7 +694,7 @@ export class SafeAreaTests extends testModule.UITest { equal(right(child2), width(root) - insets.right, `${child2}.right - actual: ${right(child2)} expected: ${width(root) - insets.right}`); equal(bottom(child2), height(root) - insets.bottom, `${child2}.bottom - actual: ${bottom(child2)} expected: ${height(root) - insets.bottom}`); }, - pageOptions + pageOptions, ); } @@ -740,7 +740,7 @@ export class SafeAreaTests extends testModule.UITest { const sumOfChildrenHeights = height(child0) + height(child1) + height(child2); equal(height(root), sumOfChildrenHeights, `flex height <${height(root)}> is NOT equal to sum of its children's heights <${sumOfChildrenHeights}>`); }, - pageOptions + pageOptions, ); } @@ -786,7 +786,7 @@ export class SafeAreaTests extends testModule.UITest { const sumOfChildrenWidths = width(child0) + width(child1) + width(child2); equal(width(root), sumOfChildrenWidths, `flex width <${width(root)}> is NOT equal to sum of its children's width <${sumOfChildrenWidths}>`); }, - pageOptions + pageOptions, ); } @@ -828,7 +828,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_in_full_screen_test(root, pageOptions); }, - pageOptions + pageOptions, ); } @@ -863,7 +863,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBar: true } + { actionBar: true }, ); } @@ -878,7 +878,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_hidden_test(root); }, - { actionBarHidden: true } + { actionBarHidden: true }, ); } @@ -893,7 +893,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBarFlat: true } + { actionBarFlat: true }, ); } @@ -908,7 +908,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_hidden_test(root); }, - { tabBar: true } + { tabBar: true }, ); } @@ -923,7 +923,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBar: true, tabBar: true } + { actionBar: true, tabBar: true }, ); } @@ -974,7 +974,7 @@ export class SafeAreaTests extends testModule.UITest { const sumOfLabelWidthsAndInsets = insets.left + width(cells[1][0]) + width(cells[1][1]) + width(cells[1][2]) + insets.right; equal(width(grid), sumOfLabelWidthsAndInsets, `grid width<${width(grid)}> sum of nested grids width and insets<${sumOfLabelWidthsAndInsets}>`); }, - pageOptions + pageOptions, ); } @@ -1037,7 +1037,7 @@ export class SafeAreaTests extends testModule.UITest { const sumOfNestedGridWidths = width(cells[1][0]) + width(cells[1][1]) + width(cells[1][2]); equal(width(grid), sumOfNestedGridWidths, `grid width<${width(grid)}> sum of nested grids width <${sumOfNestedGridWidths}>`); }, - pageOptions + pageOptions, ); } @@ -1065,7 +1065,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_in_full_screen_test(root, pageOptions); }, - pageOptions + pageOptions, ); } @@ -1100,7 +1100,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBar: true } + { actionBar: true }, ); } @@ -1115,7 +1115,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_hidden_test(root); }, - { actionBarHidden: true } + { actionBarHidden: true }, ); } @@ -1130,7 +1130,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBarFlat: true } + { actionBarFlat: true }, ); } @@ -1145,7 +1145,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_hidden_test(root); }, - { tabBar: true } + { tabBar: true }, ); } @@ -1160,7 +1160,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBar: true, tabBar: true } + { actionBar: true, tabBar: true }, ); } @@ -1182,7 +1182,7 @@ export class SafeAreaTests extends testModule.UITest { equal(bottom(child0), height(root) - insets.bottom, `${child0}.bottom - actual: ${bottom(child0)} expected: ${height(root) - insets.bottom}`); isLeftWith(child0, child1, width(child0)); }, - pageOptions + pageOptions, ); } @@ -1216,7 +1216,7 @@ export class SafeAreaTests extends testModule.UITest { equal(right(child0), width(root) - insets.right, `${child0}.right - actual: ${right(child0)} expected: ${width(root) - insets.right}`); isBelowWith(child0, child1, height(child0)); }, - pageOptions + pageOptions, ); } @@ -1251,7 +1251,7 @@ export class SafeAreaTests extends testModule.UITest { isTopAlignedWith(root, child0); isRightAlignedWith(root, child0); }, - pageOptions + pageOptions, ); } @@ -1279,7 +1279,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_in_full_screen_test(root, pageOptions); }, - pageOptions + pageOptions, ); } @@ -1314,7 +1314,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBar: true } + { actionBar: true }, ); } @@ -1329,7 +1329,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_hidden_test(root); }, - { actionBarHidden: true } + { actionBarHidden: true }, ); } @@ -1344,7 +1344,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBarFlat: true } + { actionBarFlat: true }, ); } @@ -1359,7 +1359,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_hidden_test(root); }, - { tabBar: true } + { tabBar: true }, ); } @@ -1374,7 +1374,7 @@ export class SafeAreaTests extends testModule.UITest { ({ root }) => { this.layout_insets_top_action_bar_test(root); }, - { actionBar: true, tabBar: true } + { actionBar: true, tabBar: true }, ); } @@ -1398,7 +1398,7 @@ export class SafeAreaTests extends testModule.UITest { equal(height(child1), 0, `${child1} has been laid out, but should not`); equal(width(child1), 0, `${child1} has been laid out, but should not`); }, - pageOptions + pageOptions, ); } @@ -1434,7 +1434,7 @@ export class SafeAreaTests extends testModule.UITest { equal(height(child1), 0, `${child1} has been laid out, but should not`); equal(width(child1), 0, `${child1} has been laid out, but should not`); }, - pageOptions + pageOptions, ); } @@ -1467,7 +1467,7 @@ export class SafeAreaTests extends testModule.UITest { isTopAlignedWith(root, child0); isRightAlignedWith(root, child0); }, - pageOptions + pageOptions, ); } diff --git a/apps/automated/src/ui/segmented-bar/segmented-bar-tests-native.android.ts b/apps/automated/src/ui/segmented-bar/segmented-bar-tests-native.android.ts index b22fb4eb72..5b1ec9b90e 100644 --- a/apps/automated/src/ui/segmented-bar/segmented-bar-tests-native.android.ts +++ b/apps/automated/src/ui/segmented-bar/segmented-bar-tests-native.android.ts @@ -1,5 +1,6 @@ import * as segmentedBarModule from '@nativescript/core/ui/segmented-bar'; import { Color } from '@nativescript/core'; +import { AndroidHelper } from '@nativescript/core/ui/core/view'; export function getNativeTabWidget(bar: segmentedBarModule.SegmentedBar): android.widget.TabWidget { return (bar.android).getTabWidget(); @@ -44,7 +45,7 @@ export var checkBackgroundColorUpdatedAfterItemSelected = function (bar: segment const item = bar.items[i]; const textView = item?.nativeViewProtected; - const newDrawable = tryCloneDrawable(view.getBackground(), view.getResources()); + const newDrawable = AndroidHelper.getCopyOrDrawable(view.getBackground(), view.getResources()); newDrawable.setColorFilter(new android.graphics.Paint(bar.selectedBackgroundColor.android).getColorFilter()); if (bar.selectedIndex == i) { @@ -68,16 +69,5 @@ export var checkBackgroundColorUpdatedAfterItemSelected = function (bar: segment } } - function tryCloneDrawable(value: android.graphics.drawable.Drawable, resources: android.content.res.Resources): android.graphics.drawable.Drawable { - if (value) { - const constantState = value.getConstantState(); - if (constantState) { - return constantState.newDrawable(resources); - } - } - - return value; - } - return isValid === 0; }; diff --git a/apps/automated/src/ui/text-field/text-field-tests-native.android.ts b/apps/automated/src/ui/text-field/text-field-tests-native.android.ts index bb8114ccf3..2f4b7742aa 100644 --- a/apps/automated/src/ui/text-field/text-field-tests-native.android.ts +++ b/apps/automated/src/ui/text-field/text-field-tests-native.android.ts @@ -1,4 +1,5 @@ import { TextField, Color, Utils, CoreTypes } from '@nativescript/core'; +import { AndroidHelper } from '@nativescript/core/ui/core/view'; export function getNativeText(textField: TextField): string { return textField.android.getText().toString(); @@ -29,15 +30,7 @@ export function getNativePlaceholderColor(textField: TextField): Color { } export function getNativeBackgroundColor(textField: TextField): Color { - let bg = textField.android.getBackground(); - if (bg instanceof org.nativescript.widgets.BorderDrawable) { - return new Color(bg.getBackgroundColor()); - } else if (bg instanceof android.graphics.drawable.ColorDrawable) { - console.log(bg); - return new Color(bg.getColor()); - } else { - return new Color(bg.backgroundColor); - } + return AndroidHelper.getDrawableColor(textField.android.getBackground()); } export function getNativeTextAlignment(textField: TextField): string { diff --git a/apps/automated/src/ui/text-view/text-view-tests-native.android.ts b/apps/automated/src/ui/text-view/text-view-tests-native.android.ts index 25b28656f3..2b4c9b7d74 100644 --- a/apps/automated/src/ui/text-view/text-view-tests-native.android.ts +++ b/apps/automated/src/ui/text-view/text-view-tests-native.android.ts @@ -1,4 +1,5 @@ import { TextView, Color, Utils, CoreTypes } from '@nativescript/core'; +import { AndroidHelper } from '@nativescript/core/ui/core/view'; export function getNativeText(textView: TextView): string { return textView.android.getText().toString(); @@ -27,14 +28,7 @@ export function getNativeColor(textView: TextView): Color { } export function getNativeBackgroundColor(textView: TextView): Color { - let bg = textView.android.getBackground(); - if (bg instanceof org.nativescript.widgets.BorderDrawable) { - return new Color(bg.getBackgroundColor()); - } else if (bg instanceof android.graphics.drawable.ColorDrawable) { - return new Color(bg.getColor()); - } else { - return new Color(bg.backgroundColor); - } + return AndroidHelper.getDrawableColor(textView.android.getBackground()); } export function getNativeTextAlignment(textView: TextView): string { diff --git a/packages/core/file-system/index.ts b/packages/core/file-system/index.ts index 46d4ecd914..1ff959eed6 100644 --- a/packages/core/file-system/index.ts +++ b/packages/core/file-system/index.ts @@ -391,7 +391,7 @@ export class File extends FileSystemEntity { (error) => { reject(error); this._locked = false; - } + }, ); }); } @@ -438,7 +438,7 @@ export class File extends FileSystemEntity { (error) => { reject(error); this._locked = false; - } + }, ); }); } @@ -485,7 +485,7 @@ export class File extends FileSystemEntity { (error) => { reject(error); this._locked = false; - } + }, ); }); } @@ -532,7 +532,7 @@ export class File extends FileSystemEntity { (error) => { reject(error); this._locked = false; - } + }, ); }); } @@ -579,7 +579,7 @@ export class File extends FileSystemEntity { (error) => { reject(error); this._locked = false; - } + }, ); }); } @@ -626,7 +626,7 @@ export class File extends FileSystemEntity { (error) => { reject(error); this._locked = false; - } + }, ); }); } @@ -672,7 +672,7 @@ export class File extends FileSystemEntity { (error) => { reject(error); this._locked = false; - } + }, ); }); } diff --git a/packages/core/ui/action-bar/index.android.ts b/packages/core/ui/action-bar/index.android.ts index 994f87f852..f9b16ff340 100644 --- a/packages/core/ui/action-bar/index.android.ts +++ b/packages/core/ui/action-bar/index.android.ts @@ -1,6 +1,6 @@ import { AndroidActionItemSettings, AndroidActionBarSettings as AndroidActionBarSettingsDefinition, ActionItem as ActionItemDefinition } from '.'; import { ActionItemBase, ActionBarBase, isVisible, flatProperty, traceMissingIcon, androidContentInsetLeftProperty, androidContentInsetRightProperty } from './action-bar-common'; -import { View } from '../core/view'; +import { AndroidHelper, View } from '../core/view'; import { Color } from '../../color'; import { layout, RESOURCE_PREFIX, isFontIconURI } from '../../utils'; import { colorProperty } from '../styling/style-properties'; @@ -9,6 +9,7 @@ import { Application } from '../../application'; import { isAccessibilityServiceEnabled, updateContentDescription } from '../../accessibility'; import type { Background } from '../styling/background'; import { SDK_VERSION } from '../../utils/constants'; +import { NativeScriptAndroidView } from '../utils'; export * from './action-bar-common'; @@ -216,32 +217,6 @@ export class ActionBar extends ActionBarBase { this._updateNavigationButton(); } - public _applyBackground(background: Background, isBorderDrawable, onlyColor: boolean, backgroundDrawable: any) { - const nativeView = this.nativeViewProtected; - if (backgroundDrawable && onlyColor && SDK_VERSION >= 21) { - if (isBorderDrawable && (nativeView)._cachedDrawable) { - backgroundDrawable = (nativeView)._cachedDrawable; - // we need to duplicate the drawable or we lose the "default" cached drawable - const constantState = backgroundDrawable.getConstantState(); - if (constantState) { - try { - backgroundDrawable = constantState.newDrawable(nativeView.getResources()); - // eslint-disable-next-line no-empty - } catch {} - } - nativeView.setBackground(backgroundDrawable); - } - - const backgroundColor = ((backgroundDrawable).backgroundColor = background.color.android); - backgroundDrawable.mutate(); - backgroundDrawable.setColorFilter(backgroundColor, android.graphics.PorterDuff.Mode.SRC_IN); - backgroundDrawable.invalidateSelf(); // Make sure the drawable is invalidated. Android forgets to invalidate it in some cases: toolbar - (backgroundDrawable).backgroundColor = backgroundColor; - } else { - super._applyBackground(background, isBorderDrawable, onlyColor, backgroundDrawable); - } - } - public _onAndroidItemSelected(itemId: number): boolean { // Handle home button if (this.navigationButton && itemId === R_ID_HOME) { diff --git a/packages/core/ui/activity-indicator/index.android.ts b/packages/core/ui/activity-indicator/index.android.ts index 7d283d4ab1..ba3160cd9f 100644 --- a/packages/core/ui/activity-indicator/index.android.ts +++ b/packages/core/ui/activity-indicator/index.android.ts @@ -2,6 +2,7 @@ import { ActivityIndicatorBase, busyProperty } from './activity-indicator-common import { CoreTypes } from '../../core-types'; import { Color } from '../../color'; import { colorProperty, visibilityProperty } from '../styling/style-properties'; +import { AndroidHelper } from '../core/view'; export * from './activity-indicator-common'; @@ -51,9 +52,9 @@ export class ActivityIndicator extends ActivityIndicatorBase { const color = value instanceof Color ? value.android : value; const drawable = this.nativeViewProtected.getIndeterminateDrawable().mutate(); if (color) { - drawable.setColorFilter(color, android.graphics.PorterDuff.Mode.SRC_IN); + AndroidHelper.setDrawableColor(color, drawable); } else { - drawable.clearColorFilter(); + AndroidHelper.clearDrawableColor(drawable); } } } diff --git a/packages/core/ui/builder/index.ts b/packages/core/ui/builder/index.ts index fbf7ff0313..01ab85c198 100644 --- a/packages/core/ui/builder/index.ts +++ b/packages/core/ui/builder/index.ts @@ -244,7 +244,7 @@ function parseInternal(value: string, context: any, xmlModule?: string, moduleNa ? xml2ui.ComponentSourceTracker(xmlModule) : () => { // no-op - }; + }; (start = new xml2ui.XmlStringParser(errorFormat)).pipe(new xml2ui.PlatformFilter()).pipe(new xml2ui.XmlStateParser((ui = new xml2ui.ComponentParser(context, errorFormat, componentSourceTracker, moduleName)))); diff --git a/packages/core/ui/builder/xml2ui.ts b/packages/core/ui/builder/xml2ui.ts index 3db30d14b3..3afc99c5a2 100644 --- a/packages/core/ui/builder/xml2ui.ts +++ b/packages/core/ui/builder/xml2ui.ts @@ -58,7 +58,7 @@ export namespace xml2ui { (e, p) => { throw this.error(e, p); }, - true + true, ); if (isString(value)) { @@ -296,7 +296,10 @@ export namespace xml2ui { return this._value; } - constructor(private parent: XmlStateConsumer, private templateProperty: TemplateProperty) {} + constructor( + private parent: XmlStateConsumer, + private templateProperty: TemplateProperty, + ) {} public parse(args: xml.ParserEvent): XmlStateConsumer { if (args.eventType === xml.ParserEventType.StartElement && args.elementName === 'template') { @@ -351,7 +354,12 @@ export namespace xml2ui { private error: ErrorFormatter; private sourceTracker: SourceTracker; - constructor(context: any, errorFormat: ErrorFormatter, sourceTracker: SourceTracker, private moduleName?: string) { + constructor( + context: any, + errorFormat: ErrorFormatter, + sourceTracker: SourceTracker, + private moduleName?: string, + ) { this.context = context; this.error = errorFormat; this.sourceTracker = sourceTracker; diff --git a/packages/core/ui/button/index.android.ts b/packages/core/ui/button/index.android.ts index f46eeb63e4..e3363e35e9 100644 --- a/packages/core/ui/button/index.android.ts +++ b/packages/core/ui/button/index.android.ts @@ -1,5 +1,5 @@ import { ButtonBase } from './button-common'; -import { PseudoClassHandler } from '../core/view'; +import { AndroidHelper, PseudoClassHandler } from '../core/view'; import { paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length, zIndexProperty, minWidthProperty, minHeightProperty } from '../styling/style-properties'; import { textAlignmentProperty } from '../text-base'; import { CoreTypes } from '../../core-types'; @@ -7,8 +7,8 @@ import { profile } from '../../profiling'; import { TouchGestureEventData, TouchAction, GestureTypes } from '../gestures'; import { Device } from '../../platform'; import { SDK_VERSION } from '../../utils/constants'; -import lazy from '../../utils/lazy'; import type { Background } from '../styling/background'; +import { NativeScriptAndroidView } from '../utils'; export * from './button-common'; @@ -50,32 +50,6 @@ export class Button extends ButtonBase { private _stateListAnimator: any; private _highlightedHandler: (args: TouchGestureEventData) => void; - public _applyBackground(background: Background, isBorderDrawable, onlyColor: boolean, backgroundDrawable: any) { - const nativeView = this.nativeViewProtected; - if (backgroundDrawable && onlyColor) { - if (isBorderDrawable && (nativeView)._cachedDrawable) { - backgroundDrawable = (nativeView)._cachedDrawable; - // we need to duplicate the drawable or we lose the "default" cached drawable - const constantState = backgroundDrawable.getConstantState(); - if (constantState) { - try { - backgroundDrawable = constantState.newDrawable(nativeView.getResources()); - // eslint-disable-next-line no-empty - } catch {} - } - nativeView.setBackground(backgroundDrawable); - } - - const backgroundColor = ((backgroundDrawable).backgroundColor = background.color.android); - backgroundDrawable.mutate(); - backgroundDrawable.setColorFilter(backgroundColor, android.graphics.PorterDuff.Mode.SRC_IN); - backgroundDrawable.invalidateSelf(); // Make sure the drawable is invalidated. Android forgets to invalidate it in some cases: toolbar - (backgroundDrawable).backgroundColor = backgroundColor; - } else { - super._applyBackground(background, isBorderDrawable, onlyColor, backgroundDrawable); - } - } - @profile public createNativeView() { if (!AndroidButton) { diff --git a/packages/core/ui/core/view/index.android.ts b/packages/core/ui/core/view/index.android.ts index cad8911c1a..ab0505d33c 100644 --- a/packages/core/ui/core/view/index.android.ts +++ b/packages/core/ui/core/view/index.android.ts @@ -3,7 +3,7 @@ import type { Point, CustomLayoutView as CustomLayoutViewDefinition } from '.'; import type { GestureTypes, GestureEventData } from '../../gestures'; // Types. -import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty } from './view-common'; +import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty, AndroidHelper } from './view-common'; import { paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length } from '../../styling/style-properties'; import { layout } from '../../../utils'; import { Trace } from '../../../trace'; @@ -19,13 +19,13 @@ import { topmost } from '../../frame/frame-stack'; import { Screen } from '../../../platform'; import { AndroidActivityBackPressedEventData, Application } from '../../../application'; import { Device } from '../../../platform'; -import lazy from '../../../utils/lazy'; import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty } from '../../../accessibility/accessibility-properties'; import { AccessibilityLiveRegion, AccessibilityRole, AndroidAccessibilityEvent, isAccessibilityServiceEnabled, sendAccessibilityEvent, updateAccessibilityProperties, updateContentDescription, AccessibilityState } from '../../../accessibility'; import * as Utils from '../../../utils'; import { SDK_VERSION } from '../../../utils/constants'; import { BoxShadow } from '../../styling/box-shadow'; import { _setAndroidFragmentTransitions, _getAnimatedEntries, _updateTransitions, _reverseTransitions, _clearEntry, _clearFragment, addNativeTransitionListener } from '../../frame/fragment.transitions'; +import { NativeScriptAndroidView } from '../../utils'; export * from './view-common'; // helpers (these are okay re-exported here) @@ -57,10 +57,6 @@ const modalMap = new Map(); let TouchListener: TouchListener; let DialogFragment: DialogFragment; -interface AndroidView { - _cachedDrawable: android.graphics.drawable.Drawable.ConstantState | android.graphics.drawable.Drawable; -} - interface DialogOptions { owner: View; fullscreen: boolean; @@ -1094,21 +1090,7 @@ export class View extends ViewCommon { [backgroundInternalProperty.getDefault](): android.graphics.drawable.Drawable { const nativeView = this.nativeViewProtected; - const drawable = nativeView.getBackground(); - if (drawable) { - const constantState = drawable.getConstantState(); - if (constantState) { - try { - return constantState.newDrawable(nativeView.getResources()); - } catch (e) { - return drawable; - } - } else { - return drawable; - } - } - - return null; + return AndroidHelper.getCopyOrDrawable(nativeView.getBackground(), nativeView.getResources()); } [backgroundInternalProperty.setNative](value: android.graphics.drawable.Drawable | Background) { this._redrawNativeBackground(value); @@ -1130,29 +1112,54 @@ export class View extends ViewCommon { } } - public _applyBackground(background: Background, isBorderDrawable: boolean, onlyColor: boolean, backgroundDrawable: any) { - const nativeView = this.nativeViewProtected; - if (!isBorderDrawable && onlyColor) { - if (backgroundDrawable && backgroundDrawable.setColor) { - // android.graphics.drawable.ColorDrawable - backgroundDrawable.setColor(background.color.android); + public _applyBackground(background: Background, isBorderDrawable: boolean, onlyColor: boolean, backgroundDrawable: android.graphics.drawable.Drawable) { + const nativeView = this.nativeViewProtected; + + if (onlyColor) { + const backgroundColor = background.color.android; + + if (isBorderDrawable) { + // We need to duplicate the drawable or we lose the "default" cached drawable + backgroundDrawable = nativeView._cachedDrawable != null ? AndroidHelper.getCopyOrDrawable(nativeView._cachedDrawable, nativeView.getResources()) : null; + nativeView.setBackground(backgroundDrawable); + } + + if (backgroundDrawable) { + backgroundDrawable.mutate(); + + AndroidHelper.setDrawableColor(backgroundColor, backgroundDrawable); backgroundDrawable.invalidateSelf(); } else { - nativeView.setBackgroundColor(background.color.android); + nativeView.setBackgroundColor(backgroundColor); } - } else if (!background.isEmpty()) { - if (isBorderDrawable) { - // org.nativescript.widgets.BorderDrawable - refreshBorderDrawable(this, backgroundDrawable); + } else { + if (background.clearFlags & BackgroundClearFlags.CLEAR_BACKGROUND_COLOR) { + if (backgroundDrawable) { + backgroundDrawable.mutate(); + + AndroidHelper.clearDrawableColor(backgroundDrawable); + backgroundDrawable.invalidateSelf(); + } else { + nativeView.setBackgroundColor(-1); + } + } + + if (background.isEmpty()) { + // Reset background to default if not already set + const defaultDrawable = nativeView._cachedDrawable ?? null; + if (backgroundDrawable !== defaultDrawable) { + nativeView.setBackground(defaultDrawable); + } } else { - backgroundDrawable = new org.nativescript.widgets.BorderDrawable(layout.getDisplayDensity(), this.toString()); - refreshBorderDrawable(this, backgroundDrawable); - nativeView.setBackground(backgroundDrawable); + if (isBorderDrawable) { + // org.nativescript.widgets.BorderDrawable + refreshBorderDrawable(this, backgroundDrawable); + } else { + const borderDrawable = new org.nativescript.widgets.BorderDrawable(layout.getDisplayDensity(), this.toString()); + refreshBorderDrawable(this, borderDrawable); + nativeView.setBackground(borderDrawable); + } } - } else { - //empty background let's reset - const cachedDrawable = (nativeView)._cachedDrawable; - nativeView.setBackground(cachedDrawable); } } @@ -1191,31 +1198,26 @@ export class View extends ViewCommon { } protected onBackgroundOrBorderPropertyChanged() { - const nativeView = < - android.view.View & { - _cachedDrawable: android.graphics.drawable.Drawable.ConstantState | android.graphics.drawable.Drawable; - } - >this.nativeViewProtected; + const nativeView = this.nativeViewProtected; if (!nativeView) { return; } const background = this.style.backgroundInternal; + const drawable = nativeView.getBackground(); + const isBorderDrawable = drawable instanceof org.nativescript.widgets.BorderDrawable; - if (background.clearFlags & BackgroundClearFlags.CLEAR_BOX_SHADOW || background.clearFlags & BackgroundClearFlags.CLEAR_BACKGROUND_COLOR) { - // clear background if we're clearing the box shadow - // or the background has been removed - nativeView.setBackground(null); + // Use undefined as not set. getBackground will never return undefined only Drawable or null; + if (nativeView._cachedDrawable === undefined) { + nativeView._cachedDrawable = drawable; } - const drawable = nativeView.getBackground(); - const androidView = (this) as AndroidView; - // use undefined as not set. getBackground will never return undefined only Drawable or null; - if (androidView._cachedDrawable === undefined && drawable) { - const constantState = drawable.getConstantState(); - androidView._cachedDrawable = constantState || drawable; + if (background.clearFlags & BackgroundClearFlags.CLEAR_BOX_SHADOW) { + // Clear background if we're clearing the box shadow + if (drawable instanceof org.nativescript.widgets.BoxShadowDrawable) { + nativeView.setBackground(nativeView._cachedDrawable ?? null); + } } - const isBorderDrawable = drawable instanceof org.nativescript.widgets.BorderDrawable; // prettier-ignore const onlyColor = !background.hasBorderWidth() diff --git a/packages/core/ui/core/view/view-common.ts b/packages/core/ui/core/view/view-common.ts index 7b7561465d..c497238c05 100644 --- a/packages/core/ui/core/view/view-common.ts +++ b/packages/core/ui/core/view/view-common.ts @@ -1165,7 +1165,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition { public _redrawNativeBackground(value: any): void { // } - public _applyBackground(background, isBorderDrawable: boolean, onlyColor: boolean, backgroundDrawable: any) { + public _applyBackground(background, isBorderDrawable: boolean, onlyColor: boolean, backgroundDrawable: android.graphics.drawable.Drawable) { // } diff --git a/packages/core/ui/core/view/view-helper/index.android.ts b/packages/core/ui/core/view/view-helper/index.android.ts index 396f529cc3..efe07ecc24 100644 --- a/packages/core/ui/core/view/view-helper/index.android.ts +++ b/packages/core/ui/core/view/view-helper/index.android.ts @@ -1,2 +1,64 @@ +import { Color } from '../../../../color'; +import { Trace } from '../../../../trace'; +import { SDK_VERSION } from '../../../../utils/constants'; + export * from './view-helper-common'; export const IOSHelper = 0; + +const androidxGraphics = androidx.core.graphics; + +export class AndroidHelper { + static getDrawableColor(drawable: android.graphics.drawable.Drawable): Color { + if (!drawable) { + return null; + } + + let color: number; + + if (drawable instanceof org.nativescript.widgets.BorderDrawable) { + color = drawable.getBackgroundColor(); + } else if (drawable instanceof android.graphics.drawable.ColorDrawable) { + color = drawable.getColor(); + } else { + // This is a way to retrieve drawable color when set using color filter + color = (drawable as any)._backgroundColor; + } + + return new Color(color); + } + + static setDrawableColor(color: number, drawable: android.graphics.drawable.Drawable, blendMode?: androidx.core.graphics.BlendModeCompat): void { + // ColorDrawable is an older class that had support for setColorFilter on API 21 + if (SDK_VERSION < 21 && drawable instanceof android.graphics.drawable.ColorDrawable) { + drawable.setColor(color); + } else { + drawable.setColorFilter(androidxGraphics.BlendModeColorFilterCompat.createBlendModeColorFilterCompat(color, blendMode ?? androidxGraphics.BlendModeCompat.SRC_IN)); + + // This is a way to retrieve drawable color when set using color filter + (drawable as any)._backgroundColor = color; + } + } + + static clearDrawableColor(drawable: android.graphics.drawable.Drawable): void { + // ColorDrawable is an older class that had support for setColorFilter on API 21 + if (SDK_VERSION < 21 && drawable instanceof android.graphics.drawable.ColorDrawable) { + drawable.setColor(-1); + } else { + drawable.clearColorFilter(); + + // This is a way to retrieve drawable color when set using color filter + delete (drawable as any)._backgroundColor; + } + } + + static getCopyOrDrawable(drawable: android.graphics.drawable.Drawable, resources?: android.content.res.Resources): android.graphics.drawable.Drawable { + if (drawable) { + const constantState = drawable.getConstantState(); + if (constantState) { + return resources ? constantState.newDrawable(resources) : constantState.newDrawable(); + } + } + + return drawable; + } +} diff --git a/packages/core/ui/core/view/view-helper/index.d.ts b/packages/core/ui/core/view/view-helper/index.d.ts index 0635b7415e..e0f246f49e 100644 --- a/packages/core/ui/core/view/view-helper/index.d.ts +++ b/packages/core/ui/core/view/view-helper/index.d.ts @@ -33,6 +33,16 @@ export class ViewHelper { public static combineMeasuredStates(curState: number, newState): number; } +/** + * Various Android view helper methods + */ +export namespace AndroidHelper { + export function getDrawableColor(drawable: any /* android.graphics.drawable.Drawable */): Color; + export function setDrawableColor(color: number, drawable: any /* android.graphics.drawable.Drawable */, blendMode?: any /* androidx.core.graphics.BlendModeCompat */): void; + export function clearDrawableColor(drawable: any /* android.graphics.drawable.Drawable */): void; + export function getCopyOrDrawable(drawable: any /* android.graphics.drawable.Drawable */, resources?: any /* android.content.res.Resources */): any; /* android.graphics.drawable.Drawable */ +} + /** * Various iOS view helper methods */ diff --git a/packages/core/ui/core/view/view-helper/index.ios.ts b/packages/core/ui/core/view/view-helper/index.ios.ts index 1e926aa707..0ce7c56623 100644 --- a/packages/core/ui/core/view/view-helper/index.ios.ts +++ b/packages/core/ui/core/view/view-helper/index.ios.ts @@ -8,6 +8,7 @@ import { ios as iOSUtils, layout } from '../../../../utils'; import { Trace } from '../../../../trace'; export * from './view-helper-common'; +export const AndroidHelper = 0; @NativeClass class UILayoutViewController extends UIViewController { diff --git a/packages/core/ui/index.ts b/packages/core/ui/index.ts index 6dae8fd7c1..59d1ae4496 100644 --- a/packages/core/ui/index.ts +++ b/packages/core/ui/index.ts @@ -13,7 +13,7 @@ export type { BindingOptions } from './core/bindable'; export { ControlStateChangeListener } from './core/control-state-change'; export { ViewBase, eachDescendant, getAncestor, getViewById, booleanConverter, querySelectorAll } from './core/view-base'; export type { ShowModalOptions } from './core/view-base'; -export { View, CSSType, ContainerView, ViewHelper, IOSHelper, isUserInteractionEnabledProperty, PseudoClassHandler, CustomLayoutView } from './core/view'; +export { View, CSSType, ContainerView, ViewHelper, AndroidHelper, IOSHelper, isUserInteractionEnabledProperty, PseudoClassHandler, CustomLayoutView } from './core/view'; export type { Template, KeyedTemplate, ShownModallyData, AddArrayFromBuilder, AddChildFromBuilder, Size } from './core/view'; export { Property, CoercibleProperty, InheritedProperty, CssProperty, InheritedCssProperty, ShorthandProperty, CssAnimationProperty, unsetValue, makeParser, makeValidator } from './core/properties'; export { addWeakEventListener, removeWeakEventListener } from './core/weak-event-listener'; diff --git a/packages/core/ui/list-picker/index.android.ts b/packages/core/ui/list-picker/index.android.ts index cd4332d42f..dce59d3b27 100644 --- a/packages/core/ui/list-picker/index.android.ts +++ b/packages/core/ui/list-picker/index.android.ts @@ -2,7 +2,6 @@ import { ListPickerBase, selectedIndexProperty, itemsProperty, ItemsSource } fro import { colorProperty } from '../styling/style-properties'; import { Color } from '../../color'; import { Device } from '../../platform'; -import lazy from '../../utils/lazy'; export * from './list-picker-common'; diff --git a/packages/core/ui/progress/index.android.ts b/packages/core/ui/progress/index.android.ts index 1e14535f50..eade177023 100644 --- a/packages/core/ui/progress/index.android.ts +++ b/packages/core/ui/progress/index.android.ts @@ -1,6 +1,7 @@ import { ProgressBase, valueProperty, maxValueProperty } from './progress-common'; import { Color } from '../../color'; import { colorProperty, backgroundColorProperty, backgroundInternalProperty } from '../styling/style-properties'; +import { AndroidHelper } from '../core/view'; export * from './progress-common'; @@ -37,9 +38,9 @@ export class Progress extends ProgressBase { } if (value instanceof Color) { - progressDrawable.setColorFilter(value.android, android.graphics.PorterDuff.Mode.SRC_IN); + AndroidHelper.setDrawableColor(value.android, progressDrawable); } else { - progressDrawable.clearColorFilter(); + AndroidHelper.clearDrawableColor(progressDrawable); } } @@ -56,9 +57,9 @@ export class Progress extends ProgressBase { const backgroundDrawable = progressDrawable.getDrawable(0); if (backgroundDrawable) { if (value instanceof Color) { - backgroundDrawable.setColorFilter(value.android, android.graphics.PorterDuff.Mode.SRC_IN); + AndroidHelper.setDrawableColor(value.android, backgroundDrawable); } else { - backgroundDrawable.clearColorFilter(); + AndroidHelper.clearDrawableColor(backgroundDrawable); } } } diff --git a/packages/core/ui/segmented-bar/index.android.ts b/packages/core/ui/segmented-bar/index.android.ts index 400334cb73..99448baf56 100644 --- a/packages/core/ui/segmented-bar/index.android.ts +++ b/packages/core/ui/segmented-bar/index.android.ts @@ -1,6 +1,6 @@ import { Font } from '../styling/font'; import { SegmentedBarItemBase, SegmentedBarBase, selectedIndexProperty, itemsProperty, selectedBackgroundColorProperty, selectedTextColorProperty } from './segmented-bar-common'; -import { isEnabledProperty } from '../core/view'; +import { AndroidHelper, isEnabledProperty } from '../core/view'; import { colorProperty, fontInternalProperty, fontSizeProperty } from '../styling/style-properties'; import { Color } from '../../color'; import { layout } from '../../utils'; @@ -170,8 +170,8 @@ export class SegmentedBarItem extends SegmentedBarItemBase { const color = value.android; const backgroundDrawable = viewGroup.getBackground(); if (SDK_VERSION > 21 && backgroundDrawable) { - const newDrawable = tryCloneDrawable(backgroundDrawable, nativeView.getResources()); - newDrawable.setColorFilter(new android.graphics.Paint(color).getColorFilter()); + const newDrawable = AndroidHelper.getCopyOrDrawable(backgroundDrawable, nativeView.getResources()); + AndroidHelper.setDrawableColor(color, newDrawable); viewGroup.setBackground(newDrawable); } else { const stateDrawable = new android.graphics.drawable.StateListDrawable(); @@ -183,23 +183,12 @@ export class SegmentedBarItem extends SegmentedBarItemBase { viewGroup.setBackground(stateDrawable); } } else { - const backgroundDrawable = tryCloneDrawable(value, nativeView.getResources()); + const backgroundDrawable = AndroidHelper.getCopyOrDrawable(value, nativeView.getResources()); viewGroup.setBackground(backgroundDrawable); } } } -function tryCloneDrawable(value: android.graphics.drawable.Drawable, resources: android.content.res.Resources): android.graphics.drawable.Drawable { - if (value) { - const constantState = value.getConstantState(); - if (constantState) { - return constantState.newDrawable(resources); - } - } - - return value; -} - export class SegmentedBar extends SegmentedBarBase { nativeViewProtected: android.widget.TabHost; private _tabContentFactory: android.widget.TabHost.TabContentFactory; diff --git a/packages/core/ui/slider/index.android.ts b/packages/core/ui/slider/index.android.ts index b303f37e45..f76b283f78 100644 --- a/packages/core/ui/slider/index.android.ts +++ b/packages/core/ui/slider/index.android.ts @@ -2,6 +2,7 @@ import { Background } from '../styling/background'; import { SliderBase, valueProperty, minValueProperty, maxValueProperty } from './slider-common'; import { colorProperty, backgroundColorProperty, backgroundInternalProperty } from '../styling/style-properties'; import { Color } from '../../color'; +import { AndroidHelper } from '../core/view'; export * from './slider-common'; @@ -117,10 +118,11 @@ export class Slider extends SliderBase { return -1; } [colorProperty.setNative](value: number | Color) { + const drawable = this.nativeViewProtected.getThumb(); if (value instanceof Color) { - this.nativeViewProtected.getThumb().setColorFilter(value.android, android.graphics.PorterDuff.Mode.SRC_IN); + AndroidHelper.setDrawableColor(value.android, drawable); } else { - this.nativeViewProtected.getThumb().clearColorFilter(); + AndroidHelper.clearDrawableColor(drawable); } } @@ -128,10 +130,11 @@ export class Slider extends SliderBase { return -1; } [backgroundColorProperty.setNative](value: number | Color) { + const drawable = this.nativeViewProtected.getProgressDrawable(); if (value instanceof Color) { - this.nativeViewProtected.getProgressDrawable().setColorFilter(value.android, android.graphics.PorterDuff.Mode.SRC_IN); + AndroidHelper.setDrawableColor(value.android, drawable); } else { - this.nativeViewProtected.getProgressDrawable().clearColorFilter(); + AndroidHelper.clearDrawableColor(drawable); } } diff --git a/packages/core/ui/styling/style-scope.ts b/packages/core/ui/styling/style-scope.ts index c933383db6..4a05d575cb 100644 --- a/packages/core/ui/styling/style-scope.ts +++ b/packages/core/ui/styling/style-scope.ts @@ -87,7 +87,13 @@ const pattern = /('|")(.*?)\1/; class CSSSource { private _selectors: RuleSet[] = []; - private constructor(private _ast: SyntaxTree, private _url: string, private _file: string, private _keyframes: KeyframesMap, private _source: string) { + private constructor( + private _ast: SyntaxTree, + private _url: string, + private _file: string, + private _keyframes: KeyframesMap, + private _source: string, + ) { this.parse(); } @@ -391,7 +397,7 @@ if (Application.hasLaunched()) { cssFile: Application.getCssFileName(), }, null, - null + null, ); } else { global.NativeScriptGlobals.events.on('loadAppCss', loadAppCSS); diff --git a/packages/core/ui/switch/index.android.ts b/packages/core/ui/switch/index.android.ts index 1f9670a66d..20017170d7 100644 --- a/packages/core/ui/switch/index.android.ts +++ b/packages/core/ui/switch/index.android.ts @@ -1,6 +1,7 @@ import { SwitchBase, checkedProperty, offBackgroundColorProperty } from './switch-common'; import { colorProperty, backgroundColorProperty, backgroundInternalProperty } from '../styling/style-properties'; import { Color } from '../../color'; +import { AndroidHelper } from '../core/view'; export * from './switch-common'; @@ -60,11 +61,11 @@ export class Switch extends SwitchBase { private setNativeBackgroundColor(value: string | number | Color) { if (this.nativeViewProtected) { + const drawable = this.nativeViewProtected.getTrackDrawable(); if (value instanceof Color) { - // todo: use https://developer.android.com/reference/androidx/core/graphics/BlendModeColorFilterCompat - this.nativeViewProtected.getTrackDrawable().setColorFilter(value.android, android.graphics.PorterDuff.Mode.SRC_OVER); + AndroidHelper.setDrawableColor(value.android, drawable, androidx.core.graphics.BlendModeCompat.SRC_OVER); } else { - this.nativeViewProtected.getTrackDrawable().clearColorFilter(); + AndroidHelper.clearDrawableColor(drawable); } } } @@ -92,11 +93,11 @@ export class Switch extends SwitchBase { return -1; } [colorProperty.setNative](value: number | Color) { + const drawable = this.nativeViewProtected.getThumbDrawable(); if (value instanceof Color) { - // todo: use https://developer.android.com/reference/androidx/core/graphics/BlendModeColorFilterCompat - this.nativeViewProtected.getThumbDrawable().setColorFilter(value.android, android.graphics.PorterDuff.Mode.SRC_ATOP); + AndroidHelper.setDrawableColor(value.android, drawable, androidx.core.graphics.BlendModeCompat.SRC_ATOP); } else { - this.nativeViewProtected.getThumbDrawable().clearColorFilter(); + AndroidHelper.clearDrawableColor(drawable); } } diff --git a/packages/core/ui/tab-view/index.android.ts b/packages/core/ui/tab-view/index.android.ts index 030bfd6f94..b15dd0ce8e 100644 --- a/packages/core/ui/tab-view/index.android.ts +++ b/packages/core/ui/tab-view/index.android.ts @@ -11,6 +11,7 @@ import { fontSizeProperty, fontInternalProperty } from '../styling/style-propert import { RESOURCE_PREFIX, ad, layout } from '../../utils'; import { Frame } from '../frame'; import { Application } from '../../application'; +import { AndroidHelper } from '../core/view'; export * from './tab-view-common'; @@ -757,7 +758,7 @@ export class TabView extends TabViewBase { if (value instanceof Color) { this._tabLayout.setBackgroundColor(value.android); } else { - this._tabLayout.setBackground(tryCloneDrawable(value, this.nativeViewProtected.getResources())); + this._tabLayout.setBackground(AndroidHelper.getCopyOrDrawable(value, this.nativeViewProtected.getResources())); } } @@ -797,14 +798,3 @@ export class TabView extends TabViewBase { tabLayout.setSelectedIndicatorColors([color]); } } - -function tryCloneDrawable(value: android.graphics.drawable.Drawable, resources: android.content.res.Resources): android.graphics.drawable.Drawable { - if (value) { - const constantState = value.getConstantState(); - if (constantState) { - return constantState.newDrawable(resources); - } - } - - return value; -} diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts index fedad4df0c..fd0d42dd74 100644 --- a/packages/core/ui/text-base/index.ios.ts +++ b/packages/core/ui/text-base/index.ios.ts @@ -82,7 +82,7 @@ class UILabelClickHandlerImpl extends NSObject { location: glyphIndex, length: 1, }, - textContainer + textContainer, ); // Ensure that an actual glyph was tapped diff --git a/packages/core/ui/transition/page-transition.android.ts b/packages/core/ui/transition/page-transition.android.ts index 0a37fc7636..110cc2cb9b 100644 --- a/packages/core/ui/transition/page-transition.android.ts +++ b/packages/core/ui/transition/page-transition.android.ts @@ -77,7 +77,11 @@ function setTransitionName(view: ViewBase) { } export class PageTransition extends Transition { - constructor(duration?: number, curve?: any, private pageLoadedTimeout: number = 0) { + constructor( + duration?: number, + curve?: any, + private pageLoadedTimeout: number = 0, + ) { // disable custom curves until we can fix the issue with the animation not completing if (curve) { console.warn('PageTransition does not support custom curves at the moment. The passed in curve will be ignored.'); diff --git a/packages/core/ui/transition/shared-transition.ts b/packages/core/ui/transition/shared-transition.ts index a6e88158f1..5627341c0f 100644 --- a/packages/core/ui/transition/shared-transition.ts +++ b/packages/core/ui/transition/shared-transition.ts @@ -286,7 +286,7 @@ export class SharedTransition { */ static getSharedElements( fromPage: ViewBase, - toPage: ViewBase + toPage: ViewBase, ): { sharedElements: Array; presented: Array; diff --git a/packages/core/ui/utils.d.ts b/packages/core/ui/utils.d.ts index a48305c181..e8743f1108 100644 --- a/packages/core/ui/utils.d.ts +++ b/packages/core/ui/utils.d.ts @@ -1,4 +1,8 @@ -export interface NativeScriptUIView extends UIView { +export interface NativeScriptAndroidView extends android.view.View { + _cachedDrawable: android.graphics.drawable.Drawable; +} + +export interface NativeScriptUIView extends UIView { hasNonUniformBorder: boolean; hasNonUniformBorderColor: boolean; borderLayer: CAShapeLayer; diff --git a/packages/core/ui/utils.ios.ts b/packages/core/ui/utils.ios.ts index 2ee51bb540..8cc22a2358 100644 --- a/packages/core/ui/utils.ios.ts +++ b/packages/core/ui/utils.ios.ts @@ -1,18 +1,7 @@ import { Screen } from '../platform'; import * as utils from '../utils'; import { LinearGradient } from './styling/linear-gradient'; - -interface NativeScriptUIView extends UIView { - hasNonUniformBorder: boolean; - hasNonUniformBorderColor: boolean; - borderLayer: CAShapeLayer; - - maskType: ios.LayerMaskType; - originalMask: CALayer; - - gradientLayer: CAGradientLayer; - outerShadowContainerLayer: CALayer; -} +import { NativeScriptUIView } from './utils'; export namespace ios { export type LayerMaskType = 'BORDER' | 'CLIP_PATH'; diff --git a/packages/devtools/src/devtoolsRuntime.ts b/packages/devtools/src/devtoolsRuntime.ts index cd04ad7c08..a6156d6563 100644 --- a/packages/devtools/src/devtoolsRuntime.ts +++ b/packages/devtools/src/devtoolsRuntime.ts @@ -54,7 +54,7 @@ export class ProtocolWrapper { JSON.stringify({ method: name, params, - }) + }), ); } catch (err) { console.error(err); @@ -74,7 +74,7 @@ export class ProtocolWrapper { JSON.stringify({ id, result, - }) + }), ); } } catch (err) { diff --git a/packages/webpack5/__tests__/configuration/base.spec.ts b/packages/webpack5/__tests__/configuration/base.spec.ts index 98d431eb45..c3608705a5 100644 --- a/packages/webpack5/__tests__/configuration/base.spec.ts +++ b/packages/webpack5/__tests__/configuration/base.spec.ts @@ -58,7 +58,7 @@ describe('base configuration', () => { '__jest__/tsconfig.app.json', // ts-loader '__jest__/tsconfig.app.json', // fork-ts-checker ]); - } + }, ); }); @@ -97,7 +97,7 @@ describe('base configuration', () => { '__jest__/tsconfig.json', // ts-loader '__jest__/tsconfig.json', // fork-ts-checker ]); - } + }, ); }); @@ -126,7 +126,7 @@ describe('base configuration', () => { expect(args[0].path).toEqual('__jest__/.env'); return args; }); - } + }, ); fsSpy.mockRestore(); @@ -151,7 +151,7 @@ describe('base configuration', () => { expect(args[0].path).toEqual('__jest__/.env.prod'); return args; }); - } + }, ); fsSpy.mockRestore(); }); @@ -176,7 +176,7 @@ describe('base configuration', () => { expect(args[0].path).toEqual('__jest__/.env'); return args; }); - } + }, ); fsSpy.mockRestore(); }); @@ -226,7 +226,7 @@ describe('base configuration', () => { it('includes inspector_modules on android when @nativescript/core version is >= 8.7.0', () => { const getDependencyVersionSpy = jest.spyOn( dependenciesHelpers, - 'getDependencyVersion' + 'getDependencyVersion', ); getDependencyVersionSpy.withImplementation( (name) => { @@ -245,7 +245,7 @@ describe('base configuration', () => { expect(entry).toBeDefined(); expect(entry.values().length).toBe(1); - } + }, ); }); }); diff --git a/packages/webpack5/src/bin/index.ts b/packages/webpack5/src/bin/index.ts index 47efb946a0..5061f25671 100644 --- a/packages/webpack5/src/bin/index.ts +++ b/packages/webpack5/src/bin/index.ts @@ -11,7 +11,7 @@ import { parseEnvFlags } from '../cli/parseEnvFlags'; const defaultConfig = path.resolve( __dirname, - '../stubs/default.config.stub.js' + '../stubs/default.config.stub.js', ); const tag = `[${green('@nativescript/webpack')}]`; @@ -91,7 +91,7 @@ program const webpackCompilationCallback = ( err: webpack.WebpackError, - stats: webpack.Stats + stats: webpack.Stats, ) => { if (err) { // Do not keep cache anymore @@ -116,7 +116,7 @@ program chunks: false, colors: true, errorDetails: env.verbose, - }) + }), ); } @@ -127,18 +127,18 @@ program '', '|', `| The build profile has been written to ${yellow( - 'webpack.stats.json' + 'webpack.stats.json', )}`, `| You can analyse the stats at ${green( - 'https://webpack.github.io/analyse/' + 'https://webpack.github.io/analyse/', )}`, '|', '', - ].join('\n') + ].join('\n'), ); fs.writeFileSync( path.join(process.cwd(), 'webpack.stats.json'), - JSON.stringify(stats.toJson()) + JSON.stringify(stats.toJson()), ); } } @@ -148,15 +148,15 @@ program env.stats && console.log('webpack is watching the files...'); compiler.watch( configuration.watchOptions ?? {}, - webpackCompilationCallback + webpackCompilationCallback, ); } else { compiler.run((err, status) => { compiler.close((err2) => webpackCompilationCallback( (err || err2) as webpack.WebpackError, - status - ) + status, + ), ); }); } diff --git a/packages/webpack5/src/configuration/angular.ts b/packages/webpack5/src/configuration/angular.ts index 943e63b8f1..d17fd1feac 100644 --- a/packages/webpack5/src/configuration/angular.ts +++ b/packages/webpack5/src/configuration/angular.ts @@ -161,11 +161,11 @@ export default function (config: Config, env: IWebpackEnv = _env): Config { } if (this.pluginOptions.jitMode) { transformers.before.unshift( - require('../transformers/NativeClass').default + require('../transformers/NativeClass').default, ); } else { transformers.before.push( - require('../transformers/NativeClass').default + require('../transformers/NativeClass').default, ); } args[1] = transformers; @@ -189,7 +189,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config { }); const buildAngularVersion = getDependencyVersion( - '@angular-devkit/build-angular' + '@angular-devkit/build-angular', ); if (buildAngularVersion) { @@ -212,7 +212,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config { .rule('angular-webpack-loader') .test(/\.[cm]?[tj]sx?$/) .exclude.add( - /[/\\](?:core-js|@babel|tslib|web-animations-js|web-streams-polyfill)[/\\]/ + /[/\\](?:core-js|@babel|tslib|web-animations-js|web-streams-polyfill)[/\\]/, ) .end() .resolve.set('fullySpecified', false) @@ -226,7 +226,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config { 'build-angular-missing', ` @angular-devkit/build-angular is missing! Some features may not work as expected. Please install it manually to get rid of this warning. - ` + `, ); } } @@ -281,7 +281,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config { }, /core\/profiling/, /core\/ui\/styling/, - ]) + ]), ); config.optimization.minimizer('TerserPlugin').tap((args) => { @@ -330,10 +330,10 @@ function tryRequireResolve(path: string) { function getWebpackLoaderPath() { return ( tryRequireResolve( - '@angular-devkit/build-angular/src/babel/webpack-loader' + '@angular-devkit/build-angular/src/babel/webpack-loader', ) ?? tryRequireResolve( - '@angular-devkit/build-angular/src/tools/babel/webpack-loader' + '@angular-devkit/build-angular/src/tools/babel/webpack-loader', ) ?? // fallback to angular 16.1+ '@angular-devkit/build-angular/src/tools/babel/webpack-loader' diff --git a/packages/webpack5/src/configuration/base.ts b/packages/webpack5/src/configuration/base.ts index bb86f17960..db3cb003a9 100644 --- a/packages/webpack5/src/configuration/base.ts +++ b/packages/webpack5/src/configuration/base.ts @@ -87,7 +87,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config { const sourceMapAbsolutePath = getProjectFilePath( `./${ env.buildPath ?? 'platforms' - }/${platform}-sourceMaps/[file].map[query]` + }/${platform}-sourceMaps/[file].map[query]`, ); const sourceMapRelativePath = relative(outputPath, sourceMapAbsolutePath); config.output.sourceMapFilename(sourceMapRelativePath); @@ -273,7 +273,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config { const configFile = tsConfigPath ? { configFile: tsConfigPath, - } + } : undefined; // set up ts support @@ -452,7 +452,7 @@ export default function (config: Config, env: IWebpackEnv = _env): Config { * +-----------------------------------------------------------------------------------------+ */ /System.import\(\) is deprecated/, - ]) + ]), ); // todo: refine defaults diff --git a/packages/webpack5/src/helpers/platform.ts b/packages/webpack5/src/helpers/platform.ts index 90d0b919f9..6a28fdcc9e 100644 --- a/packages/webpack5/src/helpers/platform.ts +++ b/packages/webpack5/src/helpers/platform.ts @@ -89,7 +89,7 @@ export function getPlatformName(): Platform { Use --env.platform= or --env.android, --env.ios, --env.visionos to specify the target platform. Defaulting to "ios". - ` + `, ); return 'ios';