Skip to content

Commit f5db584

Browse files
rigor789NathanWalker
authored andcommitted
fix: safeguards against invalid values
1 parent 1dfa5a6 commit f5db584

6 files changed

Lines changed: 154 additions & 54 deletions

File tree

apps/toolbox/src/box-shadow.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@ export class BoxShadowModel extends Observable {
1111
private _selectedBackgroundType: string;
1212
private _selectedBorderType: string;
1313
private _selectedAnimation: string;
14-
private _boxShadow: string;
14+
private _boxShadow: string = '5 5 1 1 rgba(255, 0, 0, .9)';
1515

1616
background: string;
1717
borderWidth: number;
1818
borderRadius: number;
1919
appliedBoxShadow: string;
2020

21+
get boxShadow(): string {
22+
return this._boxShadow;
23+
}
24+
2125
constructor() {
2226
super();
2327
}

apps/toolbox/src/box-shadow.xml

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
<!-- layouts -->
1010
<ScrollView height="100%" visibility="{{ selectedComponentType === 'layouts' ? 'visible' : 'collapsed' }}">
1111
<StackLayout>
12-
<StackLayout
12+
<StackLayout
1313
width="300"
1414
height="100"
1515
class="demo-component"
1616
boxShadow="{{ appliedBoxShadow }}"
1717
borderWidth="{{ borderWidth }}"
1818
borderRadius="{{ borderRadius }}"
19-
backgroundColor="{{ background }}"
19+
background="{{ background }}"
2020
tap="{{ toggleAnimation }}"
2121
>
2222
<Label text="StackLayout"></Label>
@@ -29,7 +29,7 @@
2929
boxShadow="{{ appliedBoxShadow }}"
3030
borderWidth="{{ borderWidth }}"
3131
borderRadius="{{ borderRadius }}"
32-
backgroundColor="{{ background }}"
32+
background="{{ background }}"
3333
tap="{{ toggleAnimation }}"
3434
>
3535
<Label text="GridLayout"></Label>
@@ -42,7 +42,7 @@
4242
boxShadow="{{ appliedBoxShadow }}"
4343
borderWidth="{{ borderWidth }}"
4444
borderRadius="{{ borderRadius }}"
45-
backgroundColor="{{ background }}"
45+
background="{{ background }}"
4646
tap="{{ toggleAnimation }}"
4747
>
4848
<Label text="AbsoluteLayout"></Label>
@@ -55,7 +55,7 @@
5555
boxShadow="{{ appliedBoxShadow }}"
5656
borderWidth="{{ borderWidth }}"
5757
borderRadius="{{ borderRadius }}"
58-
backgroundColor="{{ background }}"
58+
background="{{ background }}"
5959
tap="{{ toggleAnimation }}"
6060
>
6161
<Label text="DockLayout"></Label>
@@ -68,17 +68,33 @@
6868
boxShadow="{{ appliedBoxShadow }}"
6969
borderWidth="{{ borderWidth }}"
7070
borderRadius="{{ borderRadius }}"
71-
backgroundColor="{{ background }}"
71+
background="{{ background }}"
7272
tap="{{ toggleAnimation }}"
7373
>
7474
<Label text="FlexboxLayout"></Label>
7575
</FlexboxLayout>
7676

77+
<GridLayout
78+
width="300"
79+
height="100"
80+
padding="4"
81+
boxShadow="{{ appliedBoxShadow }}"
82+
tap="{{ toggleAnimation }}"
83+
>
84+
<StackLayout
85+
borderWidth="4"
86+
borderRadius="20"
87+
backgroundColor="white"
88+
>
89+
<Label text="BorderRadius + BoxShadow on parent container"></Label>
90+
</StackLayout>
91+
</GridLayout>
92+
7793
</StackLayout>
7894
</ScrollView>
7995

8096
<!-- labels -->
81-
<GridLayout
97+
<GridLayout
8298
rows="*"
8399
height="100%"
84100
visibility="{{ selectedComponentType === 'labels' ? 'visible' : 'collapsed' }}">
@@ -90,32 +106,53 @@
90106
boxShadow="{{ appliedBoxShadow }}"
91107
borderWidth="{{ borderWidth }}"
92108
borderRadius="{{ borderRadius }}"
93-
backgroundColor="{{ background }}"
109+
background="{{ background }}"
94110
tap="{{ toggleAnimation }}"
95111
text="Label"></Label>
96112

97113
</GridLayout>
98114

99115
<!-- buttons -->
100-
<GridLayout
116+
<GridLayout
101117
rows="*"
102118
height="100%"
103119
visibility="{{ selectedComponentType === 'buttons' ? 'visible' : 'collapsed' }}">
104120

105-
<Button
121+
<Button
106122
horizontalAlignment="center"
107123
verticalAlignment="center"
108124
class="demo-component"
109125
boxShadow="{{ appliedBoxShadow }}"
110126
borderWidth="{{ borderWidth }}"
111127
borderRadius="{{ borderRadius }}"
112-
backgroundColor="{{ background }}"
128+
background="{{ background }}"
113129
tap="{{ toggleAnimation }}"
114130
text="button"
115131
></Button>
116132

117133
</GridLayout>
118134

135+
<!-- images -->
136+
<GridLayout
137+
rows="*"
138+
height="100%"
139+
visibility="{{ selectedComponentType === 'images' ? 'visible' : 'collapsed' }}">
140+
141+
<ContentView width="100"
142+
height="100"
143+
horizontalAlignment="center"
144+
verticalAlignment="center"
145+
class="demo-component"
146+
boxShadow="{{ appliedBoxShadow }}"
147+
borderWidth="{{ borderWidth }}"
148+
borderRadius="{{ borderRadius }}"
149+
tap="{{ toggleAnimation }}">
150+
<Image src="https://raw.githubusercontent.com/NativeScript/artwork/main/logo/export/NativeScript_Logo_Blue_Transparent.png"></Image>
151+
</ContentView>
152+
153+
154+
</GridLayout>
155+
119156
</StackLayout>
120157

121158
<GridLayout
@@ -130,6 +167,7 @@
130167
<TextField
131168
col="1"
132169
placeholder="box-shadow"
170+
text="{{ boxShadow }}"
133171
textChange="{{ textChange }}"
134172
>
135173
</TextField>
@@ -146,6 +184,7 @@
146184
<Button text="Layouts" componentType="layouts" tap="{{ selectComponentType }}"></Button>
147185
<Button text="Labels" componentType="labels" selectedAttr="{{ selectedComponentType }}" tap="{{ selectComponentType }}"></Button>
148186
<Button text="Buttons" componentType="buttons" selectedAttr="{{ selectedComponentType == 'buttons' }}" tap="{{ selectComponentType }}"></Button>
187+
<Button text="Images" componentType="images" selectedAttr="{{ selectedComponentType == 'images' }}" tap="{{ selectComponentType }}"></Button>
149188
</FlexboxLayout>
150189

151190
<Label text="Background"></Label>
@@ -172,7 +211,7 @@
172211
<Button text="Scale" animationType="scale" tap="{{ selectAnimationType }}"></Button>
173212
<Button text="Rotate" animationType="rotate" tap="{{ selectAnimationType }}"></Button>
174213
</FlexboxLayout>
175-
214+
176215
</StackLayout>
177216
</ScrollView>
178217
</GridLayout>

packages/core/ui/styling/background.ios.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ function unsubscribeFromScrollNotifications(view: View) {
134134
view.off('scroll', onScroll);
135135
}
136136
}
137+
137138
function subscribeForScrollNotifications(view: View) {
138139
if (view.nativeViewProtected instanceof UIScrollView) {
139140
view.on('scroll', onScroll);
@@ -170,6 +171,7 @@ function clearNonUniformBorders(nativeView: NativeView): void {
170171
}
171172

172173
const pattern = /url\(('|")(.*?)\1\)/;
174+
173175
function setUIColorFromImage(view: View, nativeView: UIView, callback: (uiColor: UIColor) => void, flip?: boolean): void {
174176
const frame = nativeView.frame;
175177
const boundsWidth = view.scaleX ? frame.size.width / view.scaleX : frame.size.width;
@@ -733,23 +735,35 @@ function drawBoxShadow(nativeView: NativeView, view: View, boxShadow: CSSShadow,
733735
}
734736
// shadow opacity is handled on the shadow's color instance
735737
layer.shadowOpacity = boxShadow.color?.a ? boxShadow.color?.a / 255 : 1;
736-
layer.shadowRadius = Length.toDevicePixels(boxShadow.blurRadius);
738+
layer.shadowRadius = Length.toDevicePixels(boxShadow.blurRadius, 0.0);
737739
layer.shadowColor = boxShadow.color.ios.CGColor;
738-
layer.shadowOffset = CGSizeMake(Length.toDevicePixels(boxShadow.offsetX), Length.toDevicePixels(boxShadow.offsetY));
740+
741+
// prettier-ignore
742+
layer.shadowOffset = CGSizeMake(
743+
Length.toDevicePixels(boxShadow.offsetX, 0.0),
744+
Length.toDevicePixels(boxShadow.offsetY, 0.0)
745+
);
739746

740747
// this should match the view's border radius
741-
const cornerRadius = Length.toDevicePixels(<LengthType>view.style.borderRadius);
748+
const cornerRadius = Length.toDevicePixels(<LengthType>view.style.borderRadius, 0.0);
742749

743750
// apply spreadRadius by expanding shadow layer bounds
744-
const bounds = boxShadow.spreadRadius ? CGRectInset(nativeView.bounds, -Length.toDevicePixels(boxShadow.spreadRadius), -Length.toDevicePixels(boxShadow.spreadRadius)) : nativeView.bounds;
751+
// prettier-ignore
752+
const bounds = CGRectInset(nativeView.bounds,
753+
-Length.toDevicePixels(boxShadow.spreadRadius, 0.0),
754+
-Length.toDevicePixels(boxShadow.spreadRadius, 0.0)
755+
);
745756

746757
// This has the nice glow with box shadow of 0,0
747758
layer.shadowPath = UIBezierPath.bezierPathWithRoundedRectCornerRadius(bounds, cornerRadius).CGPath;
748759
}
749760

750761
function clearBoxShadow(nativeView: NativeView) {
751762
nativeView.clipsToBounds = true;
752-
const layer: CALayer = iOSNativeHelper.getShadowLayer(nativeView, 'ns-box-shadow');
763+
const layer: CALayer = iOSNativeHelper.getShadowLayer(nativeView, 'ns-box-shadow', false);
764+
if (!layer) {
765+
return;
766+
}
753767
layer.masksToBounds = true;
754768
layer.shadowOffset = CGSizeMake(0, 0);
755769
layer.shadowColor = UIColor.clearColor.CGColor;

packages/core/ui/styling/css-shadow.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const isLength = (v) => v === '0' || LENGTH_RE.test(v);
3434
* @param value
3535
*/
3636
export function parseCSSShadow(value: string): CSSShadow {
37-
const parts = value.split(PARTS_RE);
37+
const parts = value.trim().split(PARTS_RE);
3838
const inset = parts.includes('inset');
3939
const first = parts[0];
4040
const last = parts[parts.length - 1];

packages/core/utils/native-helper.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,9 @@ export namespace iOSNativeHelper {
171171
/**
172172
* @param nativeView UIView to find shadow layer with
173173
* @param name Name of the shadow layer if looking for specifically named layer
174+
* @param create should we create a new layer if not found
174175
*/
175-
export function getShadowLayer(nativeView: any /* UIView */, name?: string): any; /* CALayer */
176+
export function getShadowLayer(nativeView: any /* UIView */, name?: string, create?: boolean): any; /* CALayer */
176177

177178
/**
178179
* Create a UIDocumentInteractionControllerDelegate implementation for use with UIDocumentInteractionController

packages/core/utils/native-helper.ios.ts

Lines changed: 76 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -120,44 +120,86 @@ export namespace iOSNativeHelper {
120120
return transform;
121121
}
122122

123-
export function getShadowLayer(nativeView: UIView, name?: string): CALayer {
124-
let layer: CALayer;
125-
name = name || 'ns-shadow-layer';
126-
if (nativeView) {
127-
if (nativeView.layer) {
128-
if (nativeView.layer.name === name) {
129-
console.log('- found shadow layer - reusing.');
130-
return nativeView.layer;
131-
} else {
132-
if (nativeView.layer.sublayers && nativeView.layer.sublayers.count) {
133-
console.log('nativeView.layer.sublayers.count:', nativeView.layer.sublayers.count);
134-
for (let i = 0; i < nativeView.layer.sublayers.count; i++) {
135-
console.log(`layer ${i}:`, nativeView.layer.sublayers.objectAtIndex(i));
136-
console.log(`layer ${i} name:`, nativeView.layer.sublayers.objectAtIndex(i).name);
137-
if (nativeView.layer.sublayers.objectAtIndex(i).name === name) {
138-
return nativeView.layer.sublayers.objectAtIndex(i);
139-
}
140-
}
141-
if (nativeView instanceof UITextView) {
142-
layer = nativeView.layer.sublayers.objectAtIndex(1);
143-
} else {
144-
layer = nativeView.layer.sublayers.objectAtIndex(nativeView.layer.sublayers.count - 1);
145-
}
146-
} else {
147-
layer = nativeView.layer;
148-
}
123+
export function getShadowLayer(nativeView: UIView, name: string = 'ns-shadow-layer', create: boolean = true): CALayer {
124+
return nativeView.layer;
125+
126+
console.log(`--- ${create ? 'CREATE' : 'READ'}`);
127+
128+
/**
129+
* UIView
130+
* -> Shadow
131+
*
132+
*
133+
* UIView
134+
* -> UIView
135+
* -> Shadow
136+
*/
137+
138+
if (!nativeView) {
139+
return null;
140+
}
141+
142+
if (!nativeView.layer) {
143+
// should never hit this?
144+
console.log('- no layer! -');
145+
return null;
146+
}
147+
148+
// if the nativeView's layer is the shadow layer?
149+
if (nativeView.layer.name === name) {
150+
console.log('- found shadow layer - reusing.');
151+
return nativeView.layer;
152+
}
153+
154+
console.log('>> layer :', nativeView.layer);
155+
if (nativeView.layer.sublayers?.count) {
156+
const count = nativeView.layer.sublayers.count;
157+
for (let i = 0; i < count; i++) {
158+
const subLayer = nativeView.layer.sublayers.objectAtIndex(i);
159+
160+
console.log(`>> subLayer ${i + 1}/${count} :`, subLayer);
161+
console.log(`>> subLayer ${i + 1}/${count} name :`, subLayer.name);
162+
163+
if (subLayer.name === name) {
164+
console.log('- found shadow sublayer - reusing.');
165+
return subLayer;
149166
}
150-
} else {
151-
// could this occur?
152-
console.log('no layer!');
153167
}
168+
// if (nativeView instanceof UITextView) {
169+
// return nativeView.layer.sublayers.objectAtIndex(1);
170+
// } else {
171+
// return nativeView.layer.sublayers.objectAtIndex(nativeView.layer.sublayers.count - 1);
172+
// }
154173
}
155-
console.log('layer.name:', layer.name);
156-
if (!layer.name) {
157-
// only explicitly name if the developer had not named it themselves and/or some other integration
158-
layer.name = name;
174+
// else {
175+
// layer = nativeView.layer;
176+
// }
177+
178+
// we're not interested in creating a new layer
179+
if (!create) {
180+
return null;
159181
}
160-
return layer;
182+
183+
console.log(`- adding a new layer for - ${name}`);
184+
185+
const viewLayer = nativeView.layer;
186+
const newLayer = CALayer.layer();
187+
188+
newLayer.name = name;
189+
newLayer.zPosition = 0.0;
190+
// nativeView.layer.insertSublayerBelow(newLayer, nativeView.layer)
191+
// newLayer.insertSublayerAtIndex(nativeView.layer, 0)
192+
// nativeView.layer.zPosition = 1.0;
193+
// nativeView.layer.addSublayer(newLayer);
194+
195+
// nativeView.layer = CALayer.layer()
196+
197+
nativeView.layer.insertSublayerAtIndex(newLayer, 0);
198+
// nativeView.layer.insertSublayerAtIndex(viewLayer, 1)
199+
200+
// nativeView.layer.replaceSublayerWith(newLayer, nativeView.layer);
201+
202+
return newLayer;
161203
}
162204

163205
export function createUIDocumentInteractionControllerDelegate(): NSObject {

0 commit comments

Comments
 (0)