Skip to content

Commit aa1a24e

Browse files
committed
fix(core): Application handling of nativeApp instance
1 parent 5fda9f5 commit aa1a24e

File tree

6 files changed

+142
-13
lines changed

6 files changed

+142
-13
lines changed

apps/automated/src/http/http-string-worker.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// todo: figure out why this worker is including the whole core and not just the Http module
22
// ie. tree-shaking is not working as expected here. (same setup works in a separate app)
3-
import { initGlobal } from '@nativescript/core/globals/index';
4-
initGlobal();
3+
// import { initGlobal } from '@nativescript/core/globals/index';
4+
// initGlobal();
55

6-
import { Http } from '@nativescript/core';
6+
import { getString } from '@nativescript/core/http';
77

88
declare var postMessage: any;
99

10-
Http.getString('https://httpbin.org/get').then(
10+
getString('https://httpbin.org/get').then(
1111
function (r) {
1212
postMessage(r);
1313
},

packages/core/application/index.android.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,15 @@ export class AndroidApplication extends Observable implements AndroidApplication
4646
private _systemAppearance: 'light' | 'dark';
4747
public paused: boolean;
4848
public nativeApp: android.app.Application;
49+
/**
50+
* @deprecated Use Utils.android.getApplicationContext() instead.
51+
*/
4952
public context: android.content.Context;
5053
public foregroundActivity: androidx.appcompat.app.AppCompatActivity;
5154
public startActivity: androidx.appcompat.app.AppCompatActivity;
55+
/**
56+
* @deprecated Use Utils.android.getPackageName() instead.
57+
*/
5258
public packageName: string;
5359
// we are using these property to store the callbacks to avoid early GC collection which would trigger MarkReachableObjects
5460
private callbacks: any = {};
@@ -165,7 +171,7 @@ export { androidApp as android };
165171
let mainEntry: NavigationEntry;
166172
let started = false;
167173

168-
function ensureNativeApplication() {
174+
export function ensureNativeApplication() {
169175
if (!androidApp) {
170176
androidApp = new AndroidApplication();
171177
appCommon.setApplication(androidApp);
@@ -207,6 +213,7 @@ export function addCss(cssText: string, attributeScoped?: boolean): void {
207213
const CALLBACKS = '_callbacks';
208214

209215
export function _resetRootView(entry?: NavigationEntry | string): void {
216+
ensureNativeApplication();
210217
const activity = androidApp.foregroundActivity || androidApp.startActivity;
211218
if (!activity) {
212219
throw new Error('Cannot find android activity.');
@@ -225,6 +232,7 @@ export function getMainEntry() {
225232
}
226233

227234
export function getRootView(): View {
235+
ensureNativeApplication();
228236
// Use start activity as a backup when foregroundActivity is still not set
229237
// in cases when we are getting the root view before activity.onResumed event is fired
230238
const activity = androidApp.foregroundActivity || androidApp.startActivity;
@@ -269,14 +277,17 @@ export function getNativeApplication(): android.app.Application {
269277
}
270278

271279
export function orientation(): 'portrait' | 'landscape' | 'unknown' {
280+
ensureNativeApplication();
272281
return androidApp.orientation;
273282
}
274283

275284
export function systemAppearance(): 'dark' | 'light' {
285+
ensureNativeApplication();
276286
return androidApp.systemAppearance;
277287
}
278288

279289
global.__onLiveSync = function __onLiveSync(context?: ModuleContext) {
290+
ensureNativeApplication();
280291
if (androidApp && androidApp.paused) {
281292
return;
282293
}

packages/core/application/index.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,13 @@ export function systemAppearance(): 'dark' | 'light' | null;
360360
*/
361361
export let android: AndroidApplication;
362362

363+
/**
364+
* Used internally for backwards compatibility, will be removed in the future.
365+
* Allowed Application.android.context to work (or Application.ios). Instead use Utils.android.getApplicationContext() or Utils.android.getPackageName()
366+
* @internal
367+
*/
368+
export function ensureNativeApplication(): void;
369+
363370
/**
364371
* This is the iOS-specific application object instance.
365372
* Encapsulates methods and properties specific to the iOS platform.
@@ -468,6 +475,7 @@ export class AndroidApplication extends Observable {
468475

469476
/**
470477
* The application's [android Context](http://developer.android.com/reference/android/content/Context.html) object instance.
478+
* @deprecated Use Utils.android.getApplicationContext() instead.
471479
*/
472480
context: any /* android.content.Context */;
473481

@@ -495,6 +503,7 @@ export class AndroidApplication extends Observable {
495503

496504
/**
497505
* The name of the application package.
506+
* @deprecated Use Utils.android.getPackageName() instead.
498507
*/
499508
packageName: string;
500509

packages/core/application/index.ios.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,16 @@ let iosApp: iOSApplication;
353353
/* tslint:enable */
354354
export { iosApp as ios };
355355

356+
export function ensureNativeApplication() {
357+
if (!iosApp) {
358+
iosApp = new iOSApplication();
359+
setApplication(iosApp);
360+
}
361+
}
362+
356363
// attach on global, so it can be overwritten in NativeScript Angular
357364
(<any>global).__onLiveSyncCore = function (context?: ModuleContext) {
365+
ensureNativeApplication();
358366
iosApp._onLivesync(context);
359367
};
360368

@@ -383,15 +391,13 @@ export function getMainEntry() {
383391
}
384392

385393
export function getRootView() {
394+
ensureNativeApplication();
386395
return iosApp.rootView;
387396
}
388397

389398
let started = false;
390399
export function run(entry?: string | NavigationEntry) {
391-
if (!iosApp) {
392-
iosApp = new iOSApplication();
393-
setApplication(iosApp);
394-
}
400+
ensureNativeApplication();
395401

396402
mainEntry = typeof entry === 'string' ? { moduleName: entry } : entry;
397403
started = true;
@@ -461,11 +467,13 @@ export function addCss(cssText: string, attributeScoped?: boolean): void {
461467
}
462468

463469
export function _resetRootView(entry?: NavigationEntry | string) {
470+
ensureNativeApplication();
464471
mainEntry = typeof entry === 'string' ? { moduleName: entry } : entry;
465472
iosApp.setWindowContent();
466473
}
467474

468475
export function getNativeApplication(): UIApplication {
476+
ensureNativeApplication();
469477
return iosApp.nativeApp;
470478
}
471479

@@ -506,6 +514,7 @@ function setViewControllerView(view: View): void {
506514
}
507515

508516
function setRootViewsCssClasses(rootView: View): void {
517+
ensureNativeApplication();
509518
const deviceType = Device.deviceType.toLowerCase();
510519

511520
CSSUtils.pushToSystemCssClasses(`${CSSUtils.CLASS_PREFIX}${IOS_PLATFORM}`);
@@ -518,6 +527,7 @@ function setRootViewsCssClasses(rootView: View): void {
518527
}
519528

520529
function setRootViewsSystemAppearanceCssClass(rootView: View): void {
530+
ensureNativeApplication();
521531
if (majorVersion >= 13) {
522532
const systemAppearanceCssClass = `${CSSUtils.CLASS_PREFIX}${iosApp.systemAppearance}`;
523533
CSSUtils.pushToSystemCssClasses(systemAppearanceCssClass);
@@ -526,10 +536,12 @@ function setRootViewsSystemAppearanceCssClass(rootView: View): void {
526536
}
527537

528538
export function orientation(): 'portrait' | 'landscape' | 'unknown' {
539+
ensureNativeApplication();
529540
return iosApp.orientation;
530541
}
531542

532543
export function systemAppearance(): 'dark' | 'light' {
544+
ensureNativeApplication();
533545
return iosApp.systemAppearance;
534546
}
535547

packages/core/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import './globals';
55
export { iOSApplication, AndroidApplication } from './application';
66
export type { ApplicationEventData, LaunchEventData, OrientationChangedEventData, UnhandledErrorEventData, DiscardedErrorEventData, CssChangedEventData, LoadAppCSSEventData, AndroidActivityEventData, AndroidActivityBundleEventData, AndroidActivityRequestPermissionsEventData, AndroidActivityResultEventData, AndroidActivityNewIntentEventData, AndroidActivityBackPressedEventData, SystemAppearanceChangedEventData } from './application';
77

8-
import { fontScaleChangedEvent, launchEvent, displayedEvent, uncaughtErrorEvent, discardedErrorEvent, suspendEvent, resumeEvent, exitEvent, lowMemoryEvent, orientationChangedEvent, systemAppearanceChanged, systemAppearanceChangedEvent, getMainEntry, getRootView, _resetRootView, getResources, setResources, setCssFileName, getCssFileName, loadAppCss, addCss, on, off, notify, hasListeners, run, orientation, getNativeApplication, hasLaunched, android as appAndroid, ios as iosApp, systemAppearance, setAutoSystemAppearanceChanged } from './application';
8+
import { fontScaleChangedEvent, launchEvent, displayedEvent, uncaughtErrorEvent, discardedErrorEvent, suspendEvent, resumeEvent, exitEvent, lowMemoryEvent, orientationChangedEvent, systemAppearanceChanged, systemAppearanceChangedEvent, getMainEntry, getRootView, _resetRootView, getResources, setResources, setCssFileName, getCssFileName, loadAppCss, addCss, on, off, notify, hasListeners, run, orientation, getNativeApplication, hasLaunched, android as appAndroid, ios as iosApp, systemAppearance, setAutoSystemAppearanceChanged, ensureNativeApplication } from './application';
99
export const Application = {
1010
launchEvent,
1111
displayedEvent,
@@ -40,9 +40,11 @@ export const Application = {
4040
systemAppearance,
4141
setAutoSystemAppearanceChanged,
4242
get android() {
43+
ensureNativeApplication();
4344
return appAndroid;
4445
},
4546
get ios() {
47+
ensureNativeApplication();
4648
return iosApp;
4749
},
4850
};

packages/core/ui/core/view/index.android.ts

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { GestureTypes, GestureEventData } from '../../gestures';
44

55
// Types.
66
import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty } from './view-common';
7-
import { paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty } from '../../styling/style-properties';
7+
import { paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length } from '../../styling/style-properties';
88
import { layout } from '../../../utils';
99
import { Trace } from '../../../trace';
1010
import { ShowModalOptions, hiddenProperty } from '../view-base';
@@ -14,6 +14,7 @@ import { perspectiveProperty, visibilityProperty, opacityProperty, horizontalAli
1414
import { CoreTypes } from '../../../core-types';
1515

1616
import { Background, ad as androidBackground } from '../../styling/background';
17+
import { BackgroundClearFlags, refreshBorderDrawable } from '../../styling/background.android';
1718
import { profile } from '../../../profiling';
1819
import { topmost } from '../../frame/frame-stack';
1920
import { Screen } from '../../../platform';
@@ -23,6 +24,7 @@ import lazy from '../../../utils/lazy';
2324
import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty } from '../../../accessibility/accessibility-properties';
2425
import { AccessibilityLiveRegion, AccessibilityRole, AndroidAccessibilityEvent, setupAccessibleView, isAccessibilityServiceEnabled, sendAccessibilityEvent, updateAccessibilityProperties, updateContentDescription, AccessibilityState } from '../../../accessibility';
2526
import * as Utils from '../../../utils';
27+
import { CSSShadow } from '../../styling/css-shadow';
2628

2729
export * from './view-common';
2830
// helpers (these are okay re-exported here)
@@ -56,6 +58,10 @@ const modalMap = new Map<number, DialogOptions>();
5658
let TouchListener: TouchListener;
5759
let DialogFragment: DialogFragment;
5860

61+
interface AndroidView {
62+
_cachedDrawable: android.graphics.drawable.Drawable.ConstantState | android.graphics.drawable.Drawable;
63+
}
64+
5965
interface DialogOptions {
6066
owner: View;
6167
fullscreen: boolean;
@@ -1101,9 +1107,48 @@ export class View extends ViewCommon {
11011107
}
11021108
}
11031109

1110+
public _applyBackground(background: Background, isBorderDrawable: boolean, onlyColor: boolean, backgroundDrawable: any) {
1111+
const nativeView = this.nativeViewProtected;
1112+
if (!isBorderDrawable && onlyColor) {
1113+
if (backgroundDrawable && backgroundDrawable.setColor) {
1114+
// android.graphics.drawable.ColorDrawable
1115+
backgroundDrawable.setColor(background.color.android);
1116+
backgroundDrawable.invalidateSelf();
1117+
} else {
1118+
nativeView.setBackgroundColor(background.color.android);
1119+
}
1120+
} else if (!background.isEmpty()) {
1121+
if (isBorderDrawable) {
1122+
// org.nativescript.widgets.BorderDrawable
1123+
refreshBorderDrawable(this, backgroundDrawable);
1124+
} else {
1125+
backgroundDrawable = new org.nativescript.widgets.BorderDrawable(layout.getDisplayDensity(), this.toString());
1126+
refreshBorderDrawable(this, backgroundDrawable);
1127+
nativeView.setBackground(backgroundDrawable);
1128+
}
1129+
} else {
1130+
//empty background let's reset
1131+
const cachedDrawable = (<any>nativeView)._cachedDrawable;
1132+
nativeView.setBackground(cachedDrawable);
1133+
}
1134+
}
1135+
1136+
protected _drawBoxShadow(boxShadow: CSSShadow) {
1137+
const nativeView = this.nativeViewProtected;
1138+
const config = {
1139+
shadowColor: boxShadow.color.android,
1140+
cornerRadius: Length.toDevicePixels(this.borderRadius as CoreTypes.LengthType, 0.0),
1141+
spreadRadius: Length.toDevicePixels(boxShadow.spreadRadius, 0.0),
1142+
blurRadius: Length.toDevicePixels(boxShadow.blurRadius, 0.0),
1143+
offsetX: Length.toDevicePixels(boxShadow.offsetX, 0.0),
1144+
offsetY: Length.toDevicePixels(boxShadow.offsetY, 0.0),
1145+
};
1146+
org.nativescript.widgets.Utils.drawBoxShadow(nativeView, JSON.stringify(config));
1147+
}
1148+
11041149
_redrawNativeBackground(value: android.graphics.drawable.Drawable | Background): void {
11051150
if (value instanceof Background) {
1106-
androidBackground.onBackgroundOrBorderPropertyChanged(this);
1151+
this.onBackgroundOrBorderPropertyChanged();
11071152
} else {
11081153
const nativeView = this.nativeViewProtected;
11091154
nativeView.setBackground(value);
@@ -1119,9 +1164,59 @@ export class View extends ViewCommon {
11191164
} else {
11201165
nativeView.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
11211166
}
1167+
}
1168+
}
1169+
1170+
protected onBackgroundOrBorderPropertyChanged() {
1171+
const nativeView = <android.view.View & { _cachedDrawable: android.graphics.drawable.Drawable.ConstantState | android.graphics.drawable.Drawable }>this.nativeViewProtected;
1172+
if (!nativeView) {
1173+
return;
1174+
}
1175+
1176+
const background = this.style.backgroundInternal;
1177+
1178+
if (background.clearFlags & BackgroundClearFlags.CLEAR_BOX_SHADOW || background.clearFlags & BackgroundClearFlags.CLEAR_BACKGROUND_COLOR) {
1179+
// clear background if we're clearing the box shadow
1180+
// or the background has been removed
1181+
nativeView.setBackground(null);
1182+
}
1183+
1184+
const drawable = nativeView.getBackground();
1185+
const androidView = (<any>this) as AndroidView;
1186+
// use undefined as not set. getBackground will never return undefined only Drawable or null;
1187+
if (androidView._cachedDrawable === undefined && drawable) {
1188+
const constantState = drawable.getConstantState();
1189+
androidView._cachedDrawable = constantState || drawable;
1190+
}
1191+
const isBorderDrawable = drawable instanceof org.nativescript.widgets.BorderDrawable;
1192+
1193+
// prettier-ignore
1194+
const onlyColor = !background.hasBorderWidth()
1195+
&& !background.hasBorderRadius()
1196+
&& !background.hasBoxShadow()
1197+
&& !background.clipPath
1198+
&& !background.image
1199+
&& !!background.color;
11221200

1123-
(<any>nativeView).background = undefined;
1201+
this._applyBackground(background, isBorderDrawable, onlyColor, drawable);
1202+
1203+
if (background.hasBoxShadow()) {
1204+
this._drawBoxShadow(background.getBoxShadow());
1205+
}
1206+
1207+
// TODO: Can we move BorderWidths as separate native setter?
1208+
// This way we could skip setPadding if borderWidth is not changed.
1209+
const leftPadding = Math.ceil(this.effectiveBorderLeftWidth + this.effectivePaddingLeft);
1210+
const topPadding = Math.ceil(this.effectiveBorderTopWidth + this.effectivePaddingTop);
1211+
const rightPadding = Math.ceil(this.effectiveBorderRightWidth + this.effectivePaddingRight);
1212+
const bottomPadding = Math.ceil(this.effectiveBorderBottomWidth + this.effectivePaddingBottom);
1213+
if (this._isPaddingRelative) {
1214+
nativeView.setPaddingRelative(leftPadding, topPadding, rightPadding, bottomPadding);
1215+
} else {
1216+
nativeView.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
11241217
}
1218+
// reset clear flags
1219+
background.clearFlags = BackgroundClearFlags.NONE;
11251220
}
11261221

11271222
public accessibilityAnnouncement(message = this.accessibilityLabel): void {

0 commit comments

Comments
 (0)