diff --git a/packages/core/application/application-common.ts b/packages/core/application/application-common.ts index 44ed56b8e..c271495b7 100644 --- a/packages/core/application/application-common.ts +++ b/packages/core/application/application-common.ts @@ -2,7 +2,6 @@ import { initAccessibilityCssHelper } from '../accessibility/accessibility-css-h import { initAccessibilityFontScale } from '../accessibility/font-scale'; import { CoreTypes } from '../core-types'; import { CSSUtils } from '../css/system-classes'; -import { Observable } from '../data/observable'; import { Device } from '../platform'; import { profile } from '../profiling'; import { Trace } from '../trace'; @@ -20,11 +19,13 @@ import { ApplicationEventData, CssChangedEventData, DiscardedErrorEventData, + FontScaleChangedEventData, LaunchEventData, LoadAppCSSEventData, NativeScriptError, OrientationChangedEventData, SystemAppearanceChangedEventData, + UnhandledErrorEventData, } from './application-interfaces'; const ORIENTATION_CSS_CLASSES = [ @@ -38,7 +39,21 @@ const SYSTEM_APPEARANCE_CSS_CLASSES = [ `${CSSUtils.CLASS_PREFIX}${CoreTypes.SystemAppearance.dark}`, ]; -export class ApplicationCommon extends Observable { +const globalEvents = global.NativeScriptGlobals.events; + +// helper interface to correctly type Application event handlers +interface ApplicationEvents { + on( + eventNames: string, + callback: (args: ApplicationEventData) => void, + thisArg?: any + ): void; + off(eventNames: string, callback?: any, thisArg?: any): void; + notify(eventData: T): void; + hasListeners(eventName: string): boolean; +} + +export class ApplicationCommon { readonly launchEvent = 'launch'; readonly suspendEvent = 'suspend'; readonly displayedEvent = 'displayed'; @@ -54,9 +69,14 @@ export class ApplicationCommon extends Observable { readonly fontScaleChangedEvent = 'fontScaleChanged'; readonly livesyncEvent = 'livesync'; - constructor() { - super(); + // Application events go through the global events. + readonly on: ApplicationEvents['on'] = globalEvents.on.bind(globalEvents); + readonly off: ApplicationEvents['off'] = globalEvents.off.bind(globalEvents); + readonly notify: ApplicationEvents['notify'] = globalEvents.notify.bind(globalEvents); + readonly hasListeners: ApplicationEvents['hasListeners'] = + globalEvents.hasListeners.bind(globalEvents); + constructor() { global.NativeScriptGlobals.appInstanceReady = true; global.__onUncaughtError = (error: NativeScriptError) => { @@ -345,15 +365,6 @@ export class ApplicationCommon extends Observable { } } - on = global.NativeScriptGlobals.events.on.bind(global.NativeScriptGlobals.events); - off = global.NativeScriptGlobals.events.off.bind(global.NativeScriptGlobals.events); - notify = global.NativeScriptGlobals.events.notify.bind( - global.NativeScriptGlobals.events - ); - hasListeners = global.NativeScriptGlobals.events.hasListeners.bind( - global.NativeScriptGlobals.events - ); - run(entry?: string | NavigationEntry) { throw new Error('run() Not implemented.'); } @@ -531,6 +542,3 @@ export class ApplicationCommon extends Observable { return this.ios; } } - -// export const AndroidApplication: IAndroidApplication = undefined; -// export const iOSApplication: IiOSApplication = undefined; diff --git a/packages/core/application/application-interfaces.ts b/packages/core/application/application-interfaces.ts index d6e2d49ef..861aa9066 100644 --- a/packages/core/application/application-interfaces.ts +++ b/packages/core/application/application-interfaces.ts @@ -1,6 +1,6 @@ // Types -import type { AndroidApplication, iOSApplication, ApplicationCommon } from '.'; -import type { EventData } from '../data/observable'; +import type { ApplicationCommon } from '.'; +import type { EventData, Observable } from '../data/observable'; import type { View } from '../ui/core/view'; /** @@ -16,7 +16,12 @@ export interface NativeScriptError extends Error { /** * Event data containing information for the application events. */ -export interface ApplicationEventData extends EventData { +export interface ApplicationEventData { + /** + * The name of the event. + */ + eventName: string; + /** * Gets the native iOS event arguments. Valid only when running on iOS. */ @@ -30,7 +35,7 @@ export interface ApplicationEventData extends EventData { /** * The instance that has raised the event. */ - object: ApplicationCommon; + object: ApplicationCommon | Observable; } /** diff --git a/packages/core/application/application.d.ts b/packages/core/application/application.d.ts index 2728d1f44..4a1c39b95 100644 --- a/packages/core/application/application.d.ts +++ b/packages/core/application/application.d.ts @@ -3,7 +3,128 @@ export * from './application-common'; export * from './application-interfaces'; -export const Application: ApplicationCommon; +export const Application: ApplicationCommon & ApplicationCommonEvents; + +export interface ApplicationCommonEvents { + /** + * This event is raised when application css is changed. + */ + on( + event: 'cssChanged', + callback: (args: CssChangedEventData) => void, + thisArg?: any + ): void; + + /** + * Event raised then livesync operation is performed. + */ + on( + event: 'livesync', + callback: (args: ApplicationEventData) => void, + thisArg?: any + ): void; + + /** + * This event is raised when application css is changed. + */ + on( + event: 'cssChanged', + callback: (args: CssChangedEventData) => void, + thisArg?: any + ): void; + + /** + * This event is raised on application launchEvent. + */ + on(event: 'launch', callback: (args: LaunchEventData) => void, thisArg?: any): void; + + /** + * This event is raised after the application has performed most of its startup actions. + * Its intent is to be suitable for measuring app startup times. + * @experimental + */ + on( + event: 'displayed', + callback: (args: ApplicationEventData) => void, + thisArg?: any + ): void; + + /** + * This event is raised when the Application is suspended. + */ + on( + event: 'suspend', + callback: (args: ApplicationEventData) => void, + thisArg?: any + ): void; + + /** + * This event is raised when the Application is resumed after it has been suspended. + */ + on( + event: 'resume', + callback: (args: ApplicationEventData) => void, + thisArg?: any + ): void; + + /** + * This event is raised when the Application is about to exit. + */ + on(event: 'exit', callback: (args: ApplicationEventData) => void, thisArg?: any): void; + + /** + * This event is raised when there is low memory on the target device. + */ + on( + event: 'lowMemory', + callback: (args: ApplicationEventData) => void, + thisArg?: any + ): void; + + /** + * This event is raised when an uncaught error occurs while the application is running. + */ + on( + event: 'uncaughtError', + callback: (args: UnhandledErrorEventData) => void, + thisArg?: any + ): void; + + /** + * This event is raised when an discarded error occurs while the application is running. + */ + on( + event: 'discardedError', + callback: (args: DiscardedErrorEventData) => void, + thisArg?: any + ): void; + + /** + * This event is raised when the orientation of the application changes. + */ + on( + event: 'orientationChanged', + callback: (args: OrientationChangedEventData) => void, + thisArg?: any + ): void; + + /** + * This event is raised when the operating system appearance changes + * between light and dark theme (for Android); + * between light and dark mode (for iOS) and vice versa. + */ + on( + event: 'systemAppearanceChanged', + callback: (args: SystemAppearanceChangedEventData) => void, + thisArg?: any + ): void; + + on( + event: 'fontScaleChanged', + callback: (args: FontScaleChangedEventData) => void, + thisArg?: any + ): void; +} export interface AndroidApplication extends ApplicationCommon { readonly activityCreatedEvent; @@ -36,6 +157,62 @@ export interface AndroidApplication extends ApplicationCommon { ) => void ): void; unregisterBroadcastReceiver(intentFilter: string): void; + + on( + event: 'activityCreated', + callback: (args: AndroidActivityBundleEventData) => void, + thisArg?: any + ): void; + on( + event: 'activityDestroyed', + callback: (args: AndroidActivityEventData) => void, + thisArg?: any + ): void; + on( + event: 'activityStarted', + callback: (args: AndroidActivityEventData) => void, + thisArg?: any + ): void; + on( + event: 'activityPaused', + callback: (args: AndroidActivityEventData) => void, + thisArg?: any + ): void; + on( + event: 'activityResumed', + callback: (args: AndroidActivityEventData) => void, + thisArg?: any + ): void; + on( + event: 'activityStopped', + callback: (args: AndroidActivityEventData) => void, + thisArg?: any + ): void; + on( + event: 'saveActivityState', + callback: (args: AndroidActivityBundleEventData) => void, + thisArg?: any + ): void; + on( + event: 'activityResult', + callback: (args: AndroidActivityResultEventData) => void, + thisArg?: any + ): void; + on( + event: 'activityBackPressed', + callback: (args: AndroidActivityBackPressedEventData) => void, + thisArg?: any + ): void; + on( + event: 'activityNewIntent', + callback: (args: AndroidActivityNewIntentEventData) => void, + thisArg?: any + ): void; + on( + event: 'activityRequestPermissions', + callback: (args: AndroidActivityRequestPermissionsEventData) => void, + thisArg?: any + ): void; } export interface iOSApplication extends ApplicationCommon {