diff --git a/apps/automated/.npmrc b/apps/automated/.npmrc
new file mode 100644
index 000000000..521a9f7c0
--- /dev/null
+++ b/apps/automated/.npmrc
@@ -0,0 +1 @@
+legacy-peer-deps=true
diff --git a/apps/toolbox/.npmrc b/apps/toolbox/.npmrc
new file mode 100644
index 000000000..521a9f7c0
--- /dev/null
+++ b/apps/toolbox/.npmrc
@@ -0,0 +1 @@
+legacy-peer-deps=true
diff --git a/apps/toolbox/package.json b/apps/toolbox/package.json
index b48c530fa..179f3f333 100644
--- a/apps/toolbox/package.json
+++ b/apps/toolbox/package.json
@@ -7,13 +7,13 @@
"url": "https://github.com/NativeScript/NativeScript.git"
},
"dependencies": {
- "nativescript-theme-core": "file:../../node_modules/nativescript-theme-core",
- "@nativescript/core": "file:../../packages/core"
+ "@nativescript/core": "file:../../packages/core",
+ "nativescript-theme-core": "file:../../node_modules/nativescript-theme-core"
},
"devDependencies": {
"@nativescript/android": "7.0.1",
"@nativescript/ios": "7.2.0",
"@nativescript/webpack": "file:../../dist/packages/nativescript-webpack.tgz",
- "typescript": "file:../../node_modules/typescript"
+ "typescript": "4.0.7"
}
}
diff --git a/apps/toolbox/src/main-page.xml b/apps/toolbox/src/main-page.xml
index c5a28ba84..4701aa24a 100644
--- a/apps/toolbox/src/main-page.xml
+++ b/apps/toolbox/src/main-page.xml
@@ -10,6 +10,7 @@
+
diff --git a/apps/toolbox/src/pages/css-playground.ts b/apps/toolbox/src/pages/css-playground.ts
new file mode 100644
index 000000000..3df2441df
--- /dev/null
+++ b/apps/toolbox/src/pages/css-playground.ts
@@ -0,0 +1,41 @@
+import { Observable, EventData, Page, Label } from '@nativescript/core';
+import { addTaggedAdditionalCSS, removeTaggedAdditionalCSS } from '@nativescript/core/ui/styling/style-scope';
+
+let page: Page;
+let playLabel: Label;
+let CSSTag = 'css-playground';
+
+export function navigatingTo(args: EventData) {
+ page = args.object;
+ page.bindingContext = new CssPlaygroundModel();
+ playLabel = page.getViewById('play');
+}
+
+export class CssPlaygroundModel extends Observable {
+ currentCSS = [
+ `width: 200;`,
+ `font-size: 20;`,
+ `background: #65adf1;`,
+ `color: white;`,
+ `box-shadow: 5 5;`,
+ // `text-shadow: 2 2 red;`,
+ `padding: 16;`,
+ ].join('\n');
+
+ onTextChange(args) {
+ this.currentCSS = args.value;
+ }
+
+ resetCSS() {
+ console.log('reset css...');
+ removeTaggedAdditionalCSS(CSSTag);
+
+ playLabel._onCssStateChange();
+ }
+
+ applyCSS(args) {
+ this.resetCSS();
+ addTaggedAdditionalCSS(`#play { ${this.currentCSS}`, CSSTag);
+ playLabel._onCssStateChange();
+ }
+}
diff --git a/apps/toolbox/src/pages/css-playground.xml b/apps/toolbox/src/pages/css-playground.xml
new file mode 100644
index 000000000..cdc4aa6df
--- /dev/null
+++ b/apps/toolbox/src/pages/css-playground.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/toolbox/src/pages/root-layout.ts b/apps/toolbox/src/pages/root-layout.ts
index eeadf23d4..3760f0b1f 100644
--- a/apps/toolbox/src/pages/root-layout.ts
+++ b/apps/toolbox/src/pages/root-layout.ts
@@ -1,5 +1,4 @@
-import { EventData, Page, Observable, RootLayoutOptions, getRootLayout, StackLayout, View } from '@nativescript/core';
-import { Enums } from '@nativescript/core';
+import { EventData, Page, Observable, RootLayoutOptions, getRootLayout, StackLayout, View, CoreTypes } from '@nativescript/core';
export function navigatingTo(args: EventData) {
const page = args.object;
diff --git a/apps/ui/.npmrc b/apps/ui/.npmrc
new file mode 100644
index 000000000..521a9f7c0
--- /dev/null
+++ b/apps/ui/.npmrc
@@ -0,0 +1 @@
+legacy-peer-deps=true
diff --git a/apps/ui/src/css/text-shadow-page.ts b/apps/ui/src/css/text-shadow-page.ts
index 57769de3d..99fb5d8fc 100644
--- a/apps/ui/src/css/text-shadow-page.ts
+++ b/apps/ui/src/css/text-shadow-page.ts
@@ -12,7 +12,7 @@ const possibleValues = [
];
let currentIndex = 0;
-export function butonTap(args: EventData) {
+export function buttonTap(args: EventData) {
let page = (args.object).page;
let lbl = page.getViewById('Label');
let btn = page.getViewById('Button');
@@ -20,7 +20,7 @@ export function butonTap(args: EventData) {
let textView = page.getViewById('TextView');
let newIndex = currentIndex++ % possibleValues.length;
- let newValue = possibleValues[newIndex];
+ let newValue = possibleValues[newIndex];
lbl.textShadow = newValue;
btn.textShadow = newValue;
diff --git a/apps/ui/src/css/text-shadow-page.xml b/apps/ui/src/css/text-shadow-page.xml
index 8e118d48c..a40361b74 100644
--- a/apps/ui/src/css/text-shadow-page.xml
+++ b/apps/ui/src/css/text-shadow-page.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/packages/core/platforms/android/widgets-release.aar b/packages/core/platforms/android/widgets-release.aar
index 8e0b8af9e..0ece63e2a 100644
Binary files a/packages/core/platforms/android/widgets-release.aar and b/packages/core/platforms/android/widgets-release.aar differ
diff --git a/packages/core/ui/styling/background-common.ts b/packages/core/ui/styling/background-common.ts
index 9586c419e..c06598818 100644
--- a/packages/core/ui/styling/background-common.ts
+++ b/packages/core/ui/styling/background-common.ts
@@ -6,6 +6,21 @@ import { LinearGradient } from './linear-gradient';
import { Color } from '../../color';
import { CSSShadow } from './css-shadow';
+/**
+ * Flags used to hint the background handler if it has to clear a specific property
+ *
+ * Flags can be combined with the | operator
+ * for example: BackgroundClearFlags.CLEAR_BACKGROUND_COLOR | BackgroundClearFlags.CLEAR_BOX_SHADOW
+ *
+ * Flags can be checked for using the & operator
+ * for example: if(clearFlags & BackgroundClearFlags.CLEAR_BOX_SHADOW) { ...clear box shadow... }
+ */
+export const enum BackgroundClearFlags {
+ NONE = 0,
+ CLEAR_BACKGROUND_COLOR = 1 << 0,
+ CLEAR_BOX_SHADOW = 2 << 0,
+}
+
export class Background implements BackgroundDefinition {
public static default = new Background();
@@ -28,6 +43,7 @@ export class Background implements BackgroundDefinition {
public borderBottomRightRadius = 0;
public clipPath: string;
public boxShadow: CSSShadow;
+ public clearFlags: number = BackgroundClearFlags.NONE;
private clone(): Background {
const clone = new Background();
@@ -51,6 +67,7 @@ export class Background implements BackgroundDefinition {
clone.borderBottomLeftRadius = this.borderBottomLeftRadius;
clone.clipPath = this.clipPath;
clone.boxShadow = this.boxShadow;
+ clone.clearFlags = this.clearFlags;
return clone;
}
@@ -58,6 +75,9 @@ export class Background implements BackgroundDefinition {
public withColor(value: Color): Background {
const clone = this.clone();
clone.color = value;
+ if (!value) {
+ clone.clearFlags |= BackgroundClearFlags.CLEAR_BACKGROUND_COLOR;
+ }
return clone;
}
@@ -184,6 +204,9 @@ export class Background implements BackgroundDefinition {
public withBoxShadow(value: CSSShadow): Background {
const clone = this.clone();
clone.boxShadow = value;
+ if (!value) {
+ clone.clearFlags |= BackgroundClearFlags.CLEAR_BOX_SHADOW;
+ }
return clone;
}
@@ -229,6 +252,7 @@ export class Background implements BackgroundDefinition {
value1.borderBottomRightRadius === value2.borderBottomRightRadius &&
value1.borderBottomLeftRadius === value2.borderBottomLeftRadius &&
value1.clipPath === value2.clipPath
+ // && value1.clearFlags === value2.clearFlags
);
}
diff --git a/packages/core/ui/styling/background.android.ts b/packages/core/ui/styling/background.android.ts
index f855dcfca..2c7cca21c 100644
--- a/packages/core/ui/styling/background.android.ts
+++ b/packages/core/ui/styling/background.android.ts
@@ -8,6 +8,7 @@ import * as application from '../../application';
import { profile } from '../../profiling';
import { CSSShadow } from './css-shadow';
import { Length } from './style-properties';
+import { BackgroundClearFlags } from './background-common';
export * from './background-common';
interface AndroidView {
@@ -43,6 +44,13 @@ export namespace ad {
}
const background = view.style.backgroundInternal;
+
+ 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);
+ }
+
let drawable = nativeView.getBackground();
const androidView = (view) as AndroidView;
// use undefined as not set. getBackground will never return undefined only Drawable or null;
@@ -112,8 +120,6 @@ export namespace ad {
if (background.hasBoxShadow()) {
drawBoxShadow(nativeView, view, background.getBoxShadow());
- } else {
- clearBoxShadow(nativeView);
}
// TODO: Can we move BorderWidths as separate native setter?
@@ -124,6 +130,9 @@ export namespace ad {
const bottomPadding = Math.ceil(view.effectiveBorderBottomWidth + view.effectivePaddingBottom);
nativeView.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
+
+ // reset clear flags
+ background.clearFlags = BackgroundClearFlags.NONE;
}
}
@@ -256,10 +265,6 @@ function drawBoxShadow(nativeView: android.view.View, view: View, boxShadow: CSS
org.nativescript.widgets.Utils.drawBoxShadow(nativeView, JSON.stringify(config));
}
-function clearBoxShadow(nativeView: android.view.View) {
- org.nativescript.widgets.Utils.clearBoxShadow(nativeView);
-}
-
export enum CacheMode {
none,
memory,
diff --git a/packages/core/ui/styling/background.d.ts b/packages/core/ui/styling/background.d.ts
index 88a9db303..e5ebe0df3 100644
--- a/packages/core/ui/styling/background.d.ts
+++ b/packages/core/ui/styling/background.d.ts
@@ -31,6 +31,7 @@ export declare class Background {
public borderBottomLeftRadius: number;
public clipPath: string;
public boxShadow: string | CSSShadow;
+ public clearFlags: number;
public withColor(value: Color): Background;
public withImage(value: string | LinearGradient): Background;
diff --git a/packages/core/ui/styling/background.ios.ts b/packages/core/ui/styling/background.ios.ts
index 3c3f799da..215c57102 100644
--- a/packages/core/ui/styling/background.ios.ts
+++ b/packages/core/ui/styling/background.ios.ts
@@ -9,6 +9,7 @@ import { ImageSource } from '../../image-source';
import { CSSValue, parse as cssParse } from '../../css-value';
import { CSSShadow } from './css-shadow';
import { Length } from './style-properties';
+import { BackgroundClearFlags } from './background-common';
export * from './background-common';
@@ -48,6 +49,12 @@ export namespace ios {
const background = view.style.backgroundInternal;
const nativeView = view.nativeViewProtected;
+ if (background.clearFlags & BackgroundClearFlags.CLEAR_BOX_SHADOW) {
+ // clear box shadow if it has been removed!
+ view.setProperty('clipToBounds', true);
+ clearBoxShadow(nativeView);
+ }
+
if (nativeView.hasNonUniformBorder) {
unsubscribeFromScrollNotifications(view);
clearNonUniformBorders(nativeView);
@@ -91,10 +98,10 @@ export namespace ios {
if (background.hasBoxShadow()) {
drawBoxShadow(nativeView, view, background.getBoxShadow(), background);
- } else {
- view.setProperty('clipToBounds', true);
- clearBoxShadow(nativeView);
}
+
+ // reset clear flags
+ background.clearFlags = BackgroundClearFlags.NONE;
}
}
diff --git a/packages/core/ui/text-base/index.android.ts b/packages/core/ui/text-base/index.android.ts
index f405d7cee..08431e20c 100644
--- a/packages/core/ui/text-base/index.android.ts
+++ b/packages/core/ui/text-base/index.android.ts
@@ -390,7 +390,13 @@ export class TextBase extends TextBaseCommon {
}
[textShadowProperty.setNative](value: CSSShadow) {
- this.nativeViewProtected.setShadowLayer(Length.toDevicePixels(value.blurRadius, 0), Length.toDevicePixels(value.offsetX, 0), Length.toDevicePixels(value.offsetY, 0), value.color.android);
+ // prettier-ignore
+ this.nativeViewProtected.setShadowLayer(
+ Length.toDevicePixels(value.blurRadius, java.lang.Float.MIN_VALUE),
+ Length.toDevicePixels(value.offsetX, 0),
+ Length.toDevicePixels(value.offsetY, 0),
+ value.color.android
+ );
}
[letterSpacingProperty.getDefault](): number {
diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts
index febe06304..206b1177e 100644
--- a/packages/core/ui/text-base/index.ios.ts
+++ b/packages/core/ui/text-base/index.ios.ts
@@ -365,16 +365,17 @@ export class TextBase extends TextBaseCommon {
return;
}
- if (value.color) {
- layer.shadowOpacity = value.color.a / 255;
- layer.shadowColor = value.color.ios.CGColor;
- }
+ // shadow opacity is handled on the shadow's color instance
+ layer.shadowOpacity = value.color?.a ? value.color?.a / 255 : 1;
+ layer.shadowColor = value.color.ios.CGColor;
+ layer.shadowRadius = Length.toDevicePixels(value.blurRadius, 0.0);
- if (value.blurRadius) {
- layer.shadowRadius = Length.toDevicePixels(value.blurRadius);
- }
+ // prettier-ignore
+ layer.shadowOffset = CGSizeMake(
+ Length.toDevicePixels(value.offsetX, 0.0),
+ Length.toDevicePixels(value.offsetY, 0.0)
+ );
- layer.shadowOffset = CGSizeMake(Length.toDevicePixels(value.offsetX), Length.toDevicePixels(value.offsetY));
layer.masksToBounds = false;
// NOTE: generally should not need shouldRasterize
diff --git a/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts b/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts
index 53f51e64d..a5191ec11 100644
--- a/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts
+++ b/packages/types-android/src/lib/android/org.nativescript.widgets.d.ts
@@ -4,7 +4,6 @@
export class Utils {
public static drawBoxShadow(view: android.view.View, value: string): void;
- public static clearBoxShadow(view: android.view.View): void;
}
export class BoxShadowDrawable {
diff --git a/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java b/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java
index 7b2f421f6..924c6099d 100644
--- a/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java
+++ b/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/Utils.java
@@ -14,17 +14,28 @@ public class Utils {
}
Log.d("BoxShadowDrawable", "drawBoxShadow");
- Drawable wrap = view.getBackground();
- if(wrap == null) {
- wrap = new ColorDrawable(Color.TRANSPARENT);
- } else if(wrap instanceof BoxShadowDrawable) {
- wrap = ((BoxShadowDrawable) view.getBackground()).getWrappedDrawable();
- Log.d("BoxShadowDrawable", "already a BoxShadowDrawable, getting wrapped drawable:" + wrap.getClass().getName());
+ Drawable currentBg = view.getBackground();
+
+ if(currentBg != null) {
+ Log.d("BoxShadowDrawable", "current BG is: " + currentBg.getClass().getName());
+ }
+
+ if(currentBg == null) {
+ Log.d("BoxShadowDrawable", "view had no background!");
+ currentBg = new ColorDrawable(Color.TRANSPARENT);
+ } else if(currentBg instanceof BoxShadowDrawable) {
+ currentBg = ((BoxShadowDrawable) view.getBackground()).getWrappedDrawable();
+ Log.d("BoxShadowDrawable", "already a BoxShadowDrawable, getting wrapped drawable:" + currentBg.getClass().getName());
}
// replace background
Log.d("BoxShadowDrawable", "replacing background with new BoxShadowDrawable...");
- view.setBackground(new BoxShadowDrawable(wrap, value));
+ view.setBackground(new BoxShadowDrawable(currentBg, value));
+
+ Drawable bg = view.getBackground();
+ if(bg != null) {
+ Log.d("BoxShadowDrawable", "new current bg: " + bg.getClass().getName());
+ }
int count = 0;
while (view.getParent() != null && view.getParent() instanceof ViewGroup) {
@@ -39,17 +50,21 @@ public class Utils {
}
}
- public static void clearBoxShadow(View view) {
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
- return;
- }
- Log.d("BoxShadowDrawable", "clearBoxShadow.");
-
- Drawable bg = view.getBackground();
- if(bg instanceof BoxShadowDrawable) {
- Drawable original = ((BoxShadowDrawable) view.getBackground()).getWrappedDrawable();
- Log.d("BoxShadowDrawable", "BoxShadowDrawable found, resetting to original: " + original.getClass().getName());
- view.setBackground(original);
- }
- }
+// public static void clearBoxShadow(View view) {
+// if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
+// return;
+// }
+// Log.d("BoxShadowDrawable", "clearBoxShadow.");
+//
+// Drawable bg = view.getBackground();
+// if(bg != null) {
+// Log.d("BoxShadowDrawable", "current bg: " + bg.getClass().getName());
+// }
+// if(bg instanceof BoxShadowDrawable) {
+// Drawable original = ((BoxShadowDrawable) view.getBackground()).getWrappedDrawable();
+// Log.d("BoxShadowDrawable", "BoxShadowDrawable found, resetting to original: " + original.getClass().getName());
+// view.setBackground(null);
+//// view.setBackground(original);
+// }
+// }
}
diff --git a/packages/webpack/jasmine-config/reporter.ts b/packages/webpack/jasmine-config/reporter.ts
index 928c53f1a..5de7c4375 100644
--- a/packages/webpack/jasmine-config/reporter.ts
+++ b/packages/webpack/jasmine-config/reporter.ts
@@ -1,4 +1,6 @@
import { SpecReporter } from 'jasmine-spec-reporter';
jasmine.getEnv().clearReporters();
+
+// @ts-ignore https://github.com/bcaudan/jasmine-spec-reporter/issues/588
jasmine.getEnv().addReporter(new SpecReporter());
diff --git a/packages/webpack/package.json b/packages/webpack/package.json
index 08991b3df..eb768e24e 100644
--- a/packages/webpack/package.json
+++ b/packages/webpack/package.json
@@ -51,6 +51,7 @@
},
"dependencies": {
"@angular-devkit/core": "~10.0.0",
+ "@nativescript/hook": "~2.0.0",
"clean-webpack-plugin": "~3.0.0",
"copy-webpack-plugin": "4.6.0",
"css": "~3.0.0",
@@ -60,7 +61,6 @@
"global-modules-path": "~2.3.0",
"loader-utils": "~2.0.0",
"minimatch": "~3.0.4",
- "@nativescript/hook": "~2.0.0",
"nativescript-worker-loader": "~0.12.0",
"properties-reader": "~2.0.0",
"proxy-lib": "0.4.0",
@@ -86,7 +86,7 @@
"@istanbuljs/nyc-config-typescript": "^1.0.0",
"@ngtools/webpack": "~10.0.0",
"@types/css": "~0.0.31",
- "@types/jasmine": "^3.5.11",
+ "@types/jasmine": "3.6.6",
"@types/loader-utils": "^2.0.0",
"@types/node": "~14.0.0",
"@types/proxyquire": "~1.3.28",
@@ -94,8 +94,8 @@
"@types/semver": "^7.3.0",
"@types/webpack": "^4.41.21",
"conventional-changelog-cli": "~2.0.34",
- "jasmine": "^3.6.1",
- "jasmine-spec-reporter": "^5.0.2",
+ "jasmine": "3.6.4",
+ "jasmine-spec-reporter": "6.0.0",
"nyc": "^15.1.0",
"proxyquire": "~2.1.0",
"source-map-support": "^0.5.13",