diff --git a/packages/core/abortcontroller/abortsignal.ts b/packages/core/abortcontroller/abortsignal.ts index 07d0c3d8ad..dbb3ae2718 100644 --- a/packages/core/abortcontroller/abortsignal.ts +++ b/packages/core/abortcontroller/abortsignal.ts @@ -1,4 +1,3 @@ - import { Observable } from '../data/observable'; // Known Limitation @@ -6,75 +5,71 @@ import { Observable } from '../data/observable'; // to make assignable our `AbortSignal` into that. // https://github.com/Microsoft/TSJS-lib-generator/pull/623 type Events = { - abort: any // Event & Type<"abort"> -} + abort: any; // Event & Type<"abort"> +}; type EventAttributes = { - onabort: any // Event & Type<"abort"> -} + onabort: any; // Event & Type<"abort"> +}; /** * The signal class. * @see https://dom.spec.whatwg.org/#abortsignal */ export default class AbortSignal extends Observable { - /** - * AbortSignal cannot be constructed directly. - */ - public constructor() { - super() - } + /** + * AbortSignal cannot be constructed directly. + */ + public constructor() { + super(); + } - /** - * Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise. - */ - public get aborted(): boolean { - const aborted = abortedFlags.get(this) - if (typeof aborted !== "boolean") { - throw new TypeError( - `Expected 'this' to be an 'AbortSignal' object, but got ${ - this === null ? "null" : typeof this - }`, - ) - } - return aborted - } + /** + * Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise. + */ + public get aborted(): boolean { + const aborted = abortedFlags.get(this); + if (typeof aborted !== 'boolean') { + throw new TypeError(`Expected 'this' to be an 'AbortSignal' object, but got ${this === null ? 'null' : typeof this}`); + } + return aborted; + } } /** * Create an AbortSignal object. */ export function createAbortSignal(): AbortSignal { - const signal = new AbortSignal(); - abortedFlags.set(signal, false) - return signal + const signal = new AbortSignal(); + abortedFlags.set(signal, false); + return signal; } /** * Abort a given signal. */ export function abortSignal(signal: AbortSignal): void { - if (abortedFlags.get(signal) !== false) { - return - } + if (abortedFlags.get(signal) !== false) { + return; + } - abortedFlags.set(signal, true) - signal.notify({ eventName: "abort", type: "abort" }) + abortedFlags.set(signal, true); + signal.notify({ eventName: 'abort', type: 'abort' }); } /** * Aborted flag for each instances. */ -const abortedFlags = new WeakMap() +const abortedFlags = new WeakMap(); // Properties should be enumerable. Object.defineProperties(AbortSignal.prototype, { - aborted: { enumerable: true }, -}) + aborted: { enumerable: true }, +}); // `toString()` should return `"[object AbortSignal]"` -if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") { - Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, { - configurable: true, - value: "AbortSignal", - }) -} \ No newline at end of file +if (typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, { + configurable: true, + value: 'AbortSignal', + }); +} diff --git a/packages/core/accessibility/accessibility-common.ts b/packages/core/accessibility/accessibility-common.ts index 4d5cff4e94..7ca9cdfd98 100644 --- a/packages/core/accessibility/accessibility-common.ts +++ b/packages/core/accessibility/accessibility-common.ts @@ -19,7 +19,7 @@ export const accessibilityPerformEscapeEvent = 'accessibilityPerformEscape'; * @param {boolean} receivedFocus * @param {boolean} lostFocus */ -export function notifyAccessibilityFocusState(view: Partial, receivedFocus: boolean, lostFocus: boolean): void { +export function notifyAccessibilityFocusState(view: View, receivedFocus: boolean, lostFocus: boolean): void { if (!receivedFocus && !lostFocus) { return; } diff --git a/packages/core/accessibility/font-scale.android.ts b/packages/core/accessibility/font-scale.android.ts index c8112ba25f..efe18c172b 100644 --- a/packages/core/accessibility/font-scale.android.ts +++ b/packages/core/accessibility/font-scale.android.ts @@ -1,3 +1,4 @@ +import type { ApplicationEventData } from '../application'; import * as Application from '../application'; import { FontScaleCategory, getClosestValidFontScale } from './font-scale-common'; export * from './font-scale-common'; @@ -12,7 +13,7 @@ function fontScaleChanged(origFontScale: number) { eventName: Application.fontScaleChangedEvent, object: Application, newValue: currentFontScale, - }); + } as ApplicationEventData); } } diff --git a/packages/core/accessibility/index.android.ts b/packages/core/accessibility/index.android.ts index b36f3bc774..e38dc491e5 100644 --- a/packages/core/accessibility/index.android.ts +++ b/packages/core/accessibility/index.android.ts @@ -13,8 +13,8 @@ export * from './font-scale'; let clickableRolesMap = new Set(); -let lastFocusedView: WeakRef>; -function accessibilityEventHelper(view: Partial, eventType: number) { +let lastFocusedView: WeakRef; +function accessibilityEventHelper(view: View, eventType: number) { const eventName = accessibilityEventTypeMap.get(eventType); if (!isAccessibilityServiceEnabled()) { if (Trace.isEnabled()) { @@ -103,7 +103,7 @@ function accessibilityEventHelper(view: Partial, eventType: number) { let TNSAccessibilityDelegate: android.view.View.androidviewViewAccessibilityDelegate; -const androidViewToTNSView = new WeakMap>>(); +const androidViewToTNSView = new WeakMap>(); let accessibilityEventMap: Map; let accessibilityEventTypeMap: Map; @@ -438,11 +438,11 @@ export function isAccessibilityServiceEnabled(): boolean { return accessibilityServiceEnabled; } -export function setupAccessibleView(view: Partial): void { +export function setupAccessibleView(view: View): void { updateAccessibilityProperties(view); } -export function updateAccessibilityProperties(view: Partial): void { +export function updateAccessibilityProperties(view: View): void { if (!view.nativeViewProtected) { return; } @@ -538,7 +538,7 @@ export function updateContentDescription(view: View, forceUpdate?: boolean): str return applyContentDescription(view, forceUpdate); } -function setAccessibilityDelegate(view: Partial): void { +function setAccessibilityDelegate(view: View): void { if (!view.nativeViewProtected) { return; } @@ -564,7 +564,7 @@ function setAccessibilityDelegate(view: Partial): void { androidView.setAccessibilityDelegate(TNSAccessibilityDelegate); } -function applyContentDescription(view: Partial, forceUpdate?: boolean) { +function applyContentDescription(view: View, forceUpdate?: boolean) { let androidView = view.nativeViewProtected as android.view.View; if (!androidView || (androidView instanceof android.widget.TextView && !view._androidContentDescriptionUpdated)) { return null; diff --git a/packages/core/accessibility/index.d.ts b/packages/core/accessibility/index.d.ts index 2a3e783073..cb7a9d825d 100644 --- a/packages/core/accessibility/index.d.ts +++ b/packages/core/accessibility/index.d.ts @@ -9,7 +9,7 @@ export * from './font-scale'; /** * Initialize accessibility for View. This should be called on loaded-event. */ -export function setupAccessibleView(view: Partial): void; +export function setupAccessibleView(view: View): void; /** * Update accessibility properties on nativeView diff --git a/packages/core/application/application-common.ts b/packages/core/application/application-common.ts index a9bdbfd920..7e33a5aadb 100644 --- a/packages/core/application/application-common.ts +++ b/packages/core/application/application-common.ts @@ -2,9 +2,9 @@ import '../globals'; // Types +import type * as IApplication from '.'; import { AndroidApplication, iOSApplication } from '.'; import { CssChangedEventData, DiscardedErrorEventData, LoadAppCSSEventData, UnhandledErrorEventData } from './application-interfaces'; -import { EventData } from '../data/observable'; import { View } from '../ui/core/view'; // Requires @@ -50,10 +50,10 @@ export function setResources(res: any) { export const android: AndroidApplication = undefined; export const ios: iOSApplication = undefined; -export const on = global.NativeScriptGlobals.events.on.bind(global.NativeScriptGlobals.events); -export const off = global.NativeScriptGlobals.events.off.bind(global.NativeScriptGlobals.events); -export const notify = global.NativeScriptGlobals.events.notify.bind(global.NativeScriptGlobals.events); -export const hasListeners = global.NativeScriptGlobals.events.hasListeners.bind(global.NativeScriptGlobals.events); +export const on = global.NativeScriptGlobals.events.on.bind(global.NativeScriptGlobals.events) as typeof IApplication.on; +export const off = global.NativeScriptGlobals.events.off.bind(global.NativeScriptGlobals.events) as typeof IApplication.off; +export const notify = global.NativeScriptGlobals.events.notify.bind(global.NativeScriptGlobals.events) as typeof IApplication.notify; +export const hasListeners = global.NativeScriptGlobals.events.hasListeners.bind(global.NativeScriptGlobals.events) as typeof IApplication.hasListeners; let app: iOSApplication | AndroidApplication; export function setApplication(instance: iOSApplication | AndroidApplication): void { @@ -63,7 +63,7 @@ export function setApplication(instance: iOSApplication | AndroidApplication): v } export function livesync(rootView: View, context?: ModuleContext) { - global.NativeScriptGlobals.events.notify({ eventName: 'livesync', object: app }); + notify({ eventName: 'livesync', object: app }); const liveSyncCore = global.__onLiveSyncCore; let reapplyAppStyles = false; @@ -85,7 +85,7 @@ export function livesync(rootView: View, context?: ModuleContext) { export function setCssFileName(cssFileName: string) { cssFile = cssFileName; - global.NativeScriptGlobals.events.notify({ + notify({ eventName: 'cssChanged', object: app, cssFile: cssFileName, @@ -98,7 +98,7 @@ export function getCssFileName(): string { export function loadAppCss(): void { try { - global.NativeScriptGlobals.events.notify({ + notify({ eventName: 'loadAppCss', object: app, cssFile: getCssFileName(), @@ -181,7 +181,7 @@ export function setSuspended(value: boolean): void { } global.__onUncaughtError = function (error: NativeScriptError) { - global.NativeScriptGlobals.events.notify({ + notify({ eventName: uncaughtErrorEvent, object: app, android: error, @@ -191,7 +191,7 @@ global.__onUncaughtError = function (error: NativeScriptError) { }; global.__onDiscardedError = function (error: NativeScriptError) { - global.NativeScriptGlobals.events.notify({ + notify({ eventName: discardedErrorEvent, object: app, error: error, diff --git a/packages/core/application/application-interfaces.ts b/packages/core/application/application-interfaces.ts index 13ea7fa5c5..2a4524e316 100644 --- a/packages/core/application/application-interfaces.ts +++ b/packages/core/application/application-interfaces.ts @@ -13,22 +13,45 @@ export interface NativeScriptError extends Error { } export interface ApplicationEventData extends EventData { + /** + * UIApplication or undefined, unless otherwise specified. Prefer explicit + * properties where possible. + */ ios?: any; + /** + * androidx.appcompat.app.AppCompatActivity or undefined, unless otherwise + * specified. Prefer explicit properties where possible. + */ android?: any; - eventName: string; + /** + * Careful with this messy type. A significant refactor is needed to make it + * strictly extend EventData['object'], which is an Observable. It's used in + * various ways: + * - By font-scale: the Application module, typeof import('.') + * - Within index.android.ts: AndroidApplication + * - Within index.ios.ts: iOSApplication + */ object: any; } export interface LaunchEventData extends ApplicationEventData { + /** + * The value stored into didFinishLaunchingWithOptions notification's + * userInfo under 'UIApplicationLaunchOptionsLocalNotificationKey'; + * otherwise, null. + */ + ios: unknown; root?: View | null; savedInstanceState?: any /* android.os.Bundle */; } export interface OrientationChangedEventData extends ApplicationEventData { + android: any /* globalAndroid.app.Application */; newValue: 'portrait' | 'landscape' | 'unknown'; } export interface SystemAppearanceChangedEventData extends ApplicationEventData { + android: any /* globalAndroid.app.Application */; newValue: 'light' | 'dark'; } @@ -42,15 +65,14 @@ export interface DiscardedErrorEventData extends ApplicationEventData { error: NativeScriptError; } -export interface CssChangedEventData extends EventData { +export interface CssChangedEventData extends ApplicationEventData { cssFile?: string; cssText?: string; } -export interface AndroidActivityEventData { +export interface AndroidActivityEventData extends ApplicationEventData { activity: any /* androidx.appcompat.app.AppCompatActivity */; - eventName: string; - object: any; + object: any /* AndroidApplication */; } export interface AndroidActivityBundleEventData extends AndroidActivityEventData { @@ -84,6 +106,6 @@ export interface RootViewControllerImpl { contentController: any; } -export interface LoadAppCSSEventData extends EventData { +export interface LoadAppCSSEventData extends ApplicationEventData { cssFile: string; } diff --git a/packages/core/application/index.android.ts b/packages/core/application/index.android.ts index 99eecd608f..d60bb628e0 100644 --- a/packages/core/application/index.android.ts +++ b/packages/core/application/index.android.ts @@ -4,7 +4,7 @@ import { AndroidActivityBackPressedEventData, AndroidActivityBundleEventData, An // TODO: explain why we need to this or remov it // Use requires to ensure order of imports is maintained -const appCommon = require('./application-common'); +const appCommon = require('./application-common') as typeof import('./application-common'); // First reexport so that app module is initialized. export * from './application-common'; @@ -163,18 +163,18 @@ export class AndroidApplication extends Observable implements AndroidApplication // HACK: We declare all these 'on' statements, so that they can appear in the API reference // HACK: Do we need this? Is it useful? There are static fields to the AndroidApplication class for the event names. export interface AndroidApplication { - on(eventNames: string, callback: (data: AndroidActivityEventData) => void, thisArg?: any); - on(event: 'activityCreated', callback: (args: AndroidActivityBundleEventData) => void, thisArg?: any); - on(event: 'activityDestroyed', callback: (args: AndroidActivityEventData) => void, thisArg?: any); - on(event: 'activityStarted', callback: (args: AndroidActivityEventData) => void, thisArg?: any); - on(event: 'activityPaused', callback: (args: AndroidActivityEventData) => void, thisArg?: any); - on(event: 'activityResumed', callback: (args: AndroidActivityEventData) => void, thisArg?: any); - on(event: 'activityStopped', callback: (args: AndroidActivityEventData) => void, thisArg?: any); - on(event: 'saveActivityState', callback: (args: AndroidActivityBundleEventData) => void, thisArg?: any); - on(event: 'activityResult', callback: (args: AndroidActivityResultEventData) => void, thisArg?: any); - on(event: 'activityBackPressed', callback: (args: AndroidActivityBackPressedEventData) => void, thisArg?: any); - on(event: 'activityNewIntent', callback: (args: AndroidActivityNewIntentEventData) => void, thisArg?: any); - on(event: 'activityRequestPermissions', callback: (args: AndroidActivityRequestPermissionsEventData) => void, thisArg?: any); + on(eventNames: string, callback: (data: AndroidActivityEventData) => void, thisArg?: any): 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; } let androidApp: AndroidApplication; diff --git a/packages/core/application/index.d.ts b/packages/core/application/index.d.ts index 646399a0d0..74f0a2aa65 100644 --- a/packages/core/application/index.d.ts +++ b/packages/core/application/index.d.ts @@ -257,7 +257,7 @@ export function _resetRootView(entry?: NavigationEntry | string); /** * Removes listener for the specified event name. */ -export function off(eventNames: string, callback?: any, thisArg?: any); +export function off(eventNames: string, callback?: (eventData: ApplicationEventData) => void, thisArg?: any): void; /** * Shortcut alias to the removeEventListener method. @@ -265,13 +265,13 @@ export function off(eventNames: string, callback?: any, thisArg?: any); * @param callback - Callback function which will be removed. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ -export function off(eventNames: string, callback?: any, thisArg?: any); +export function off(eventNames: string, callback?: (eventData: ApplicationEventData) => void, thisArg?: any): void; /** * Notifies all the registered listeners for the event provided in the data.eventName. * @param data The data associated with the event. */ -export function notify(data: any): void; +export function notify(data: T): void; /** * Checks whether a listener is registered for the specified event name. @@ -285,83 +285,78 @@ export function hasListeners(eventName: string): boolean; * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ -export function on(eventNames: string, callback: (data: any) => void, thisArg?: any); +export function on(eventNames: string, callback: (args: EventData) => void, thisArg?: any): void; /** * This event is raised when application css is changed. */ -export function on(event: 'cssChanged', callback: (args: CssChangedEventData) => void, thisArg?: any); +export function on(event: 'cssChanged', callback: (args: CssChangedEventData) => void, thisArg?: any): void; /** * Event raised then livesync operation is performed. */ -export function on(event: 'livesync', callback: (args: EventData) => void); +export function on(event: 'livesync', callback: (args: ApplicationEventData) => void, thisArg?: any): void; /** * This event is raised when application css is changed. */ -export function on(event: 'cssChanged', callback: (args: CssChangedEventData) => void, thisArg?: any); - -/** - * Event raised then livesync operation is performed. - */ -export function on(event: 'livesync', callback: (args: EventData) => void); +export function on(event: 'cssChanged', callback: (args: CssChangedEventData) => void, thisArg?: any): void; /** * This event is raised on application launchEvent. */ -export function on(event: 'launch', callback: (args: LaunchEventData) => void, thisArg?: any); +export function 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 */ -export function on(event: 'displayed', callback: (args: EventData) => void, thisArg?: any); +export function on(event: 'displayed', callback: (args: ApplicationEventData) => void, thisArg?: any): void; /** * This event is raised when the Application is suspended. */ -export function on(event: 'suspend', callback: (args: ApplicationEventData) => void, thisArg?: any); +export function on(event: 'suspend', callback: (args: ApplicationEventData) => void, thisArg?: any): void; /** * This event is raised when the Application is resumed after it has been suspended. */ -export function on(event: 'resume', callback: (args: ApplicationEventData) => void, thisArg?: any); +export function on(event: 'resume', callback: (args: ApplicationEventData) => void, thisArg?: any): void; /** * This event is raised when the Application is about to exit. */ -export function on(event: 'exit', callback: (args: ApplicationEventData) => void, thisArg?: any); +export function on(event: 'exit', callback: (args: ApplicationEventData) => void, thisArg?: any): void; /** * This event is raised when there is low memory on the target device. */ -export function on(event: 'lowMemory', callback: (args: ApplicationEventData) => void, thisArg?: any); +export function on(event: 'lowMemory', callback: (args: ApplicationEventData) => void, thisArg?: any): void; /** * This event is raised when an uncaught error occurs while the application is running. */ -export function on(event: 'uncaughtError', callback: (args: UnhandledErrorEventData) => void, thisArg?: any); +export function on(event: 'uncaughtError', callback: (args: UnhandledErrorEventData) => void, thisArg?: any): void; /** * This event is raised when an discarded error occurs while the application is running. */ -export function on(event: 'discardedError', callback: (args: DiscardedErrorEventData) => void, thisArg?: any); +export function on(event: 'discardedError', callback: (args: DiscardedErrorEventData) => void, thisArg?: any): void; /** * This event is raised when the orientation of the application changes. */ -export function on(event: 'orientationChanged', callback: (args: OrientationChangedEventData) => void, thisArg?: any); +export function 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. */ -export function on(event: 'systemAppearanceChanged', callback: (args: SystemAppearanceChangedEventData) => void, thisArg?: any); +export function on(event: 'systemAppearanceChanged', callback: (args: SystemAppearanceChangedEventData) => void, thisArg?: any): void; -export function on(event: 'fontScaleChanged', callback: (args: FontScaleChangedEventData) => void, thisArg?: any); +export function on(event: 'fontScaleChanged', callback: (args: FontScaleChangedEventData) => void, thisArg?: any): void; /** * Gets the orientation of the application. @@ -553,62 +548,62 @@ export class AndroidApplication extends Observable { * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (data: AndroidActivityEventData) => void, thisArg?: any); + on(eventNames: string, callback: (data: AndroidActivityEventData) => void, thisArg?: any): void; /** * This event is raised on android application ActivityCreated. */ - on(event: 'activityCreated', callback: (args: AndroidActivityBundleEventData) => void, thisArg?: any); + on(event: 'activityCreated', callback: (args: AndroidActivityBundleEventData) => void, thisArg?: any): void; /** * This event is raised on android application ActivityDestroyed. */ - on(event: 'activityDestroyed', callback: (args: AndroidActivityEventData) => void, thisArg?: any); + on(event: 'activityDestroyed', callback: (args: AndroidActivityEventData) => void, thisArg?: any): void; /** * This event is raised on android application ActivityStarted. */ - on(event: 'activityStarted', callback: (args: AndroidActivityEventData) => void, thisArg?: any); + on(event: 'activityStarted', callback: (args: AndroidActivityEventData) => void, thisArg?: any): void; /** * This event is raised on android application ActivityPaused. */ - on(event: 'activityPaused', callback: (args: AndroidActivityEventData) => void, thisArg?: any); + on(event: 'activityPaused', callback: (args: AndroidActivityEventData) => void, thisArg?: any): void; /** * This event is raised on android application ActivityResumed. */ - on(event: 'activityResumed', callback: (args: AndroidActivityEventData) => void, thisArg?: any); + on(event: 'activityResumed', callback: (args: AndroidActivityEventData) => void, thisArg?: any): void; /** * This event is raised on android application ActivityStopped. */ - on(event: 'activityStopped', callback: (args: AndroidActivityEventData) => void, thisArg?: any); + on(event: 'activityStopped', callback: (args: AndroidActivityEventData) => void, thisArg?: any): void; /** * This event is raised on android application SaveActivityState. */ - on(event: 'saveActivityState', callback: (args: AndroidActivityBundleEventData) => void, thisArg?: any); + on(event: 'saveActivityState', callback: (args: AndroidActivityBundleEventData) => void, thisArg?: any): void; /** * This event is raised on android application ActivityResult. */ - on(event: 'activityResult', callback: (args: AndroidActivityResultEventData) => void, thisArg?: any); + on(event: 'activityResult', callback: (args: AndroidActivityResultEventData) => void, thisArg?: any): void; /** * This event is raised on the back button is pressed in an android application. */ - on(event: 'activityBackPressed', callback: (args: AndroidActivityBackPressedEventData) => void, thisArg?: any); + on(event: 'activityBackPressed', callback: (args: AndroidActivityBackPressedEventData) => void, thisArg?: any): void; /** * This event is raised when the Android app was launched by an Intent with data. */ - on(event: 'activityNewIntent', callback: (args: AndroidActivityNewIntentEventData) => void, thisArg?: any); + on(event: 'activityNewIntent', callback: (args: AndroidActivityNewIntentEventData) => void, thisArg?: any): void; /** * This event is raised when the Android activity requests permissions. */ - on(event: 'activityRequestPermissions', callback: (args: AndroidActivityRequestPermissionsEventData) => void, thisArg?: any); + on(event: 'activityRequestPermissions', callback: (args: AndroidActivityRequestPermissionsEventData) => void, thisArg?: any): void; /** * String value used when hooking to activityCreated event. diff --git a/packages/core/application/index.ios.ts b/packages/core/application/index.ios.ts index d00acc3023..0e5a06fd3c 100644 --- a/packages/core/application/index.ios.ts +++ b/packages/core/application/index.ios.ts @@ -4,7 +4,7 @@ import { ApplicationEventData, CssChangedEventData, LaunchEventData, LoadAppCSSE // TODO: explain why we need to this or remov it // Use requires to ensure order of imports is maintained -const { backgroundEvent, displayedEvent, exitEvent, foregroundEvent, getCssFileName, launchEvent, livesync, lowMemoryEvent, notify, on, orientationChanged, orientationChangedEvent, resumeEvent, setApplication, suspendEvent, systemAppearanceChanged, systemAppearanceChangedEvent } = require('./application-common'); +const { backgroundEvent, displayedEvent, exitEvent, foregroundEvent, getCssFileName, launchEvent, livesync, lowMemoryEvent, notify, on, orientationChanged, orientationChangedEvent, resumeEvent, setApplication, suspendEvent, systemAppearanceChanged, systemAppearanceChangedEvent } = require('./application-common') as typeof import('./application-common'); // First reexport so that app module is initialized. export * from './application-common'; @@ -12,7 +12,6 @@ import { View } from '../ui/core/view'; import { NavigationEntry } from '../ui/frame/frame-interfaces'; // TODO: Remove this and get it from global to decouple builder for angular import { Builder } from '../ui/builder'; -import { Observable } from '../data/observable'; import { CSSUtils } from '../css/system-classes'; import { IOSHelper } from '../ui/core/view/view-helper'; import { Device } from '../platform'; @@ -238,7 +237,7 @@ export class iOSApplication implements iOSApplicationDefinition { const args: LaunchEventData = { eventName: launchEvent, object: this, - ios: (notification && notification.userInfo && notification.userInfo.objectForKey('UIApplicationLaunchOptionsLocalNotificationKey')) || null, + ios: notification?.userInfo?.objectForKey('UIApplicationLaunchOptionsLocalNotificationKey') || null, }; notify(args); diff --git a/packages/core/data/observable/index.d.ts b/packages/core/data/observable/index.d.ts deleted file mode 100644 index 086aedaf88..0000000000 --- a/packages/core/data/observable/index.d.ts +++ /dev/null @@ -1,194 +0,0 @@ -/** - * Base event data. - */ -export interface EventData { - /** - * The name of the event. - */ - eventName: string; - /** - * The Observable instance that has raised the event. - */ - object: Observable; -} - -export interface NotifyData extends Partial { - eventName: string; - object?: Observable; -} - -/** - * Data for the "propertyChange" event. - */ -export interface PropertyChangeData extends EventData { - /** - * The name of the property that has changed. - */ - propertyName: string; - /** - * The new value of the property. - */ - value: any; - /** - * The previous value of the property. - */ - oldValue?: any; -} - -/** - * Helper class that is used to fire property change even when real object is the same. - * By default property change will not be fired for a same object. - * By wrapping object into a WrappedValue instance `same object restriction` will be passed. - */ -export class WrappedValue { - /** - * Property which holds the real value. - */ - wrapped: any; - - /** - * Creates an instance of WrappedValue object. - * @param value - the real value which should be wrapped. - */ - constructor(value: any); - - /** - * Gets the real value of previously wrappedValue. - * @param value - Value that should be unwraped. If there is no wrappedValue property of the value object then value will be returned. - */ - static unwrap(value: any): any; - - /** - * Returns an instance of WrappedValue. The actual instance is get from a WrappedValues pool. - * @param value - Value that should be wrapped. - */ - static wrap(value: any): WrappedValue; -} - -/** - * Observable is used when you want to be notified when a change occurs. Use on/off methods to add/remove listener. - */ -export class Observable { - /** - * Please note that should you be using the `new Observable({})` constructor, it is **obsolete** since v3.0, - * and you have to migrate to the "data/observable" `fromObject({})` or the `fromObjectRecursive({})` functions. - */ - constructor(); - - /** - * String value used when hooking to propertyChange event. - */ - static propertyChangeEvent: string; - - /** - * A basic method signature to hook an event listener (shortcut alias to the addEventListener method). - * @param eventNames - String corresponding to events (e.g. "propertyChange"). Optionally could be used more events separated by `,` (e.g. "propertyChange", "change"). - * @param callback - Callback function which will be executed when event is raised. - * @param thisArg - An optional parameter which will be used as `this` context for callback execution. - */ - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); - - static on(eventName: string, callback: any, thisArg?: any): void; - - /** - * Raised when a propertyChange occurs. - */ - on(event: 'propertyChange', callback: (data: EventData) => void, thisArg?: any); - - /** - * Adds one-time listener function for the event named `event`. - * @param event Name of the event to attach to. - * @param callback A function to be called when the specified event is raised. - * @param thisArg An optional parameter which when set will be used as "this" in callback method call. - */ - once(event: string, callback: (data: EventData) => void, thisArg?: any); - - static once(eventName: string, callback: any, thisArg?: any): void; - - /** - * Shortcut alias to the removeEventListener method. - */ - off(eventNames: string, callback?: any, thisArg?: any); - - static off(eventName: string, callback?: any, thisArg?: any): void; - - /** - * Adds a listener for the specified event name. - * @param eventNames Comma delimited names of the events to attach the listener to. - * @param callback A function to be called when some of the specified event(s) is raised. - * @param thisArg An optional parameter which when set will be used as "this" in callback method call. - */ - addEventListener(eventNames: string, callback: (data: EventData) => void, thisArg?: any); - - static addEventListener(eventName: string, callback: any, thisArg?: any): void; - - /** - * Removes listener(s) for the specified event name. - * @param eventNames Comma delimited names of the events the specified listener is associated with. - * @param callback An optional parameter pointing to a specific listener. If not defined, all listeners for the event names will be removed. - * @param thisArg An optional parameter which when set will be used to refine search of the correct callback which will be removed as event listener. - */ - removeEventListener(eventNames: string, callback?: any, thisArg?: any); - - static removeEventListener(eventName: string, callback?: any, thisArg?: any): void; - - /** - * Updates the specified property with the provided value. - */ - set(name: string, value: any): void; - - /** - * Updates the specified property with the provided value and raises a property change event and a specific change event based on the property name. - */ - setProperty(name: string, value: any): void; - - /** - * Gets the value of the specified property. - */ - get(name: string): any; - - /** - * Notifies all the registered listeners for the event provided in the data.eventName. - * @param data The data associated with the event. - */ - notify(data: T): void; - - /** - * Notifies all the registered listeners for the property change event. - */ - notifyPropertyChange(propertyName: string, value: any, oldValue?: any): void; - - /** - * Checks whether a listener is registered for the specified event name. - * @param eventName The name of the event to check for. - */ - hasListeners(eventName: string): boolean; - - public _emit(eventNames: string); - - /** - * This method is intended to be overriden by inheritors to provide additional implementation. - */ - _createPropertyChangeData(name: string, value: any, oldValue?: any): PropertyChangeData; - - //@private - /** - * Filed to use instead of instanceof ViewBase. - * @private - */ - public _isViewBase: boolean; - //@endprivate -} - -/** - * Creates an Observable instance and sets its properties according to the supplied JavaScript object. - * param obj - A JavaScript object used to initialize nativescript Observable instance. - */ -export function fromObject(obj: any): Observable; - -/** - * Creates an Observable instance and sets its properties according to the supplied JavaScript object. - * This function will create new Observable for each nested object (expect arrays and functions) from supplied JavaScript object. - * param obj - A JavaScript object used to initialize nativescript Observable instance. - */ -export function fromObjectRecursive(obj: any): Observable; diff --git a/packages/core/data/observable/index.ts b/packages/core/data/observable/index.ts index 0ad4c63fb2..5fd348d91f 100644 --- a/packages/core/data/observable/index.ts +++ b/packages/core/data/observable/index.ts @@ -1,22 +1,38 @@ -import { Observable as ObservableDefinition, WrappedValue as WrappedValueDefinition } from '.'; +import { Optional } from '../../utils/typescript-utils'; +/** + * Base event data. + */ export interface EventData { + /** + * The name of the event. + */ eventName: string; - object: Partial; + /** + * The Observable instance that has raised the event. + */ + object: Observable; } export interface EventDataValue extends EventData { value?: boolean; } -export interface NotifyData extends Partial { - eventName: string; - object?: Partial; -} - +/** + * Data for the "propertyChange" event. + */ export interface PropertyChangeData extends EventData { + /** + * The name of the property that has changed. + */ propertyName: string; + /** + * The new value of the property. + */ value: any; + /** + * The previous value of the property. + */ oldValue?: any; } @@ -28,13 +44,35 @@ interface ListenerEntry { let _wrappedIndex = 0; -export class WrappedValue implements WrappedValueDefinition { - constructor(public wrapped: any) {} - +/** + * Helper class that is used to fire property change even when real object is the same. + * By default property change will not be fired for a same object. + * By wrapping object into a WrappedValue instance `same object restriction` will be passed. + */ +export class WrappedValue { + /** + * Creates an instance of WrappedValue object. + * @param wrapped - the real value which should be wrapped. + */ + constructor( + /** + * Property which holds the real value. + */ + public wrapped: any + ) {} + + /** + * Gets the real value of previously wrappedValue. + * @param value - Value that should be unwraped. If there is no wrappedValue property of the value object then value will be returned. + */ public static unwrap(value: any): any { return value instanceof WrappedValue ? value.wrapped : value; } + /** + * Returns an instance of WrappedValue. The actual instance is get from a WrappedValues pool. + * @param value - Value that should be wrapped. + */ public static wrap(value: any): any { const w = _wrappedValues[_wrappedIndex++ % 5]; w.wrapped = value; @@ -45,13 +83,30 @@ export class WrappedValue implements WrappedValueDefinition { const _wrappedValues = [new WrappedValue(null), new WrappedValue(null), new WrappedValue(null), new WrappedValue(null), new WrappedValue(null)]; -const _globalEventHandlers = {}; - -export class Observable implements ObservableDefinition { +const _globalEventHandlers: { + [eventClass: string]: { + [eventName: string]: ListenerEntry[]; + }; +} = {}; + +/** + * Observable is used when you want to be notified when a change occurs. Use on/off methods to add/remove listener. + * Please note that should you be using the `new Observable({})` constructor, it is **obsolete** since v3.0, + * and you have to migrate to the "data/observable" `fromObject({})` or the `fromObjectRecursive({})` functions. + */ +export class Observable { + /** + * String value used when hooking to propertyChange event. + */ public static propertyChangeEvent = 'propertyChange'; + + /** + * Alternative to `instanceof ViewBase`. + * @private + */ public _isViewBase: boolean; - private _observers = {}; + private readonly _observers: { [eventName: string]: ListenerEntry[] } = {}; public get(name: string): any { return this[name]; @@ -85,10 +140,22 @@ export class Observable implements ObservableDefinition { } } + /** + * A basic method signature to hook an event listener (shortcut alias to the addEventListener method). + * @param eventNames - String corresponding to events (e.g. "propertyChange"). Optionally could be used more events separated by `,` (e.g. "propertyChange", "change"). + * @param callback - Callback function which will be executed when event is raised. + * @param thisArg - An optional parameter which will be used as `this` context for callback execution. + */ public on(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void { this.addEventListener(eventNames, callback, thisArg); } + /** + * Adds one-time listener function for the event named `event`. + * @param event Name of the event to attach to. + * @param callback A function to be called when the specified event is raised. + * @param thisArg An optional parameter which when set will be used as "this" in callback method call. + */ public once(event: string, callback: (data: EventData) => void, thisArg?: any): void { if (typeof event !== 'string') { throw new TypeError('Event must be string.'); @@ -102,10 +169,19 @@ export class Observable implements ObservableDefinition { list.push({ callback, thisArg, once: true }); } - public off(eventNames: string, callback?: any, thisArg?: any): void { + /** + * Shortcut alias to the removeEventListener method. + */ + public off(eventNames: string, callback?: (data: EventData) => void, thisArg?: any): void { this.removeEventListener(eventNames, callback, thisArg); } + /** + * Adds a listener for the specified event name. + * @param eventNames Comma delimited names of the events to attach the listener to. + * @param callback A function to be called when some of the specified event(s) is raised. + * @param thisArg An optional parameter which when set will be used as "this" in callback method call. + */ public addEventListener(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void { if (typeof eventNames !== 'string') { throw new TypeError('Events name(s) must be string.'); @@ -127,7 +203,13 @@ export class Observable implements ObservableDefinition { } } - public removeEventListener(eventNames: string, callback?: any, thisArg?: any): void { + /** + * Removes listener(s) for the specified event name. + * @param eventNames Comma delimited names of the events the specified listener is associated with. + * @param callback An optional parameter pointing to a specific listener. If not defined, all listeners for the event names will be removed. + * @param thisArg An optional parameter which when set will be used to refine search of the correct callback which will be removed as event listener. + */ + public removeEventListener(eventNames: string, callback?: (data: EventData) => void, thisArg?: any): void { if (typeof eventNames !== 'string') { throw new TypeError('Events name(s) must be string.'); } @@ -157,11 +239,11 @@ export class Observable implements ObservableDefinition { } } - public static on(eventName: string, callback: any, thisArg?: any): void { + public static on(eventName: string, callback: (data: EventData) => void, thisArg?: any): void { this.addEventListener(eventName, callback, thisArg); } - public static once(eventName: string, callback: any, thisArg?: any): void { + public static once(eventName: string, callback: (data: EventData) => void, thisArg?: any): void { if (typeof eventName !== 'string') { throw new TypeError('Event must be string.'); } @@ -180,11 +262,11 @@ export class Observable implements ObservableDefinition { _globalEventHandlers[eventClass][eventName].push({ callback, thisArg, once: true }); } - public static off(eventName: string, callback?: any, thisArg?: any): void { + public static off(eventName: string, callback?: (data: EventData) => void, thisArg?: any): void { this.removeEventListener(eventName, callback, thisArg); } - public static removeEventListener(eventName: string, callback?: any, thisArg?: any): void { + public static removeEventListener(eventName: string, callback?: (data: EventData) => void, thisArg?: any): void { if (typeof eventName !== 'string') { throw new TypeError('Event must be string.'); } @@ -232,7 +314,7 @@ export class Observable implements ObservableDefinition { } } - public static addEventListener(eventName: string, callback: any, thisArg?: any): void { + public static addEventListener(eventName: string, callback: (data: EventData) => void, thisArg?: any): void { if (typeof eventName !== 'string') { throw new TypeError('Event must be string.'); } @@ -271,18 +353,28 @@ export class Observable implements ObservableDefinition { } } - public notify(data: T): void { - const eventData = data as EventData; - eventData.object = eventData.object || this; + /** + * Notify this Observable instance with some data. This causes all event + * handlers on the Observable instance to be called, as well as any 'global' + * event handlers set on the instance's class. + * + * @param data an object that satisfies the EventData interface, though with + * an optional 'object' property. If left undefined, the 'object' property + * will implicitly be set as this Observable instance. + */ + public notify>(data: T): void { + data.object = data.object || this; + const dataWithObject = data as EventData; + const eventClass = this.constructor.name; - this._globalNotify(eventClass, 'First', eventData); + this._globalNotify(eventClass, 'First', dataWithObject); - const observers = >this._observers[data.eventName]; + const observers = this._observers[data.eventName]; if (observers) { - Observable._handleEvent(observers, eventData); + Observable._handleEvent(observers, dataWithObject); } - this._globalNotify(eventClass, '', eventData); + this._globalNotify(eventClass, '', dataWithObject); } private static _handleEvent(observers: Array, data: T): void { @@ -296,7 +388,7 @@ export class Observable implements ObservableDefinition { observers.splice(i, 1); } - let returnValue; + let returnValue: any; if (entry.thisArg) { returnValue = entry.callback.apply(entry.thisArg, [data]); } else { @@ -313,14 +405,24 @@ export class Observable implements ObservableDefinition { } } - public notifyPropertyChange(name: string, value: any, oldValue?: any) { + /** + * Notifies all the registered listeners for the property change event. + */ + public notifyPropertyChange(name: string, value: any, oldValue?: any): void { this.notify(this._createPropertyChangeData(name, value, oldValue)); } - public hasListeners(eventName: string) { + /** + * Checks whether a listener is registered for the specified event name. + * @param eventName The name of the event to check for. + */ + public hasListeners(eventName: string): boolean { return eventName in this._observers; } + /** + * This method is intended to be overriden by inheritors to provide additional implementation. + */ public _createPropertyChangeData(propertyName: string, value: any, oldValue?: any): PropertyChangeData { return { eventName: Observable.propertyChangeEvent, @@ -331,7 +433,7 @@ export class Observable implements ObservableDefinition { }; } - public _emit(eventNames: string) { + public _emit(eventNames: string): void { const events = eventNames.split(','); for (let i = 0, l = events.length; i < l; i++) { @@ -372,14 +474,39 @@ export class Observable implements ObservableDefinition { } } +export interface Observable { + /** + * Raised when a propertyChange occurs. + */ + on(event: 'propertyChange', callback: (data: EventData) => void, thisArg?: any): void; + + /** + * Updates the specified property with the provided value. + */ + set(name: string, value: any): void; + + /** + * Updates the specified property with the provided value and raises a property change event and a specific change event based on the property name. + */ + setProperty(name: string, value: any): void; + + /** + * Gets the value of the specified property. + */ + get(name: string): any; +} + class ObservableFromObject extends Observable { - public _map = {}; + public readonly _map: Record = {}; public get(name: string): any { return this._map[name]; } - public set(name: string, value: any) { + /** + * Updates the specified property with the provided value. + */ + public set(name: string, value: any): void { const currentValue = this._map[name]; if (currentValue === value) { return; @@ -404,7 +531,7 @@ function defineNewProperty(target: ObservableFromObject, propertyName: string): }); } -function addPropertiesFromObject(observable: ObservableFromObject, source: any, recursive = false) { +function addPropertiesFromObject(observable: ObservableFromObject, source: any, recursive = false): void { Object.keys(source).forEach((prop) => { let value = source[prop]; if (recursive && !Array.isArray(value) && value && typeof value === 'object' && !(value instanceof Observable)) { @@ -416,6 +543,10 @@ function addPropertiesFromObject(observable: ObservableFromObject, source: any, }); } +/** + * Creates an Observable instance and sets its properties according to the supplied JavaScript object. + * param obj - A JavaScript object used to initialize nativescript Observable instance. + */ export function fromObject(source: any): Observable { const observable = new ObservableFromObject(); addPropertiesFromObject(observable, source, false); @@ -423,6 +554,11 @@ export function fromObject(source: any): Observable { return observable; } +/** + * Creates an Observable instance and sets its properties according to the supplied JavaScript object. + * This function will create new Observable for each nested object (expect arrays and functions) from supplied JavaScript object. + * param obj - A JavaScript object used to initialize nativescript Observable instance. + */ export function fromObjectRecursive(source: any): Observable { const observable = new ObservableFromObject(); addPropertiesFromObject(observable, source, true); diff --git a/packages/core/global-types.d.ts b/packages/core/global-types.d.ts index 4a5f224c05..43bb67539c 100644 --- a/packages/core/global-types.d.ts +++ b/packages/core/global-types.d.ts @@ -25,17 +25,7 @@ declare namespace NodeJS { * Global framework event handling */ events: { - on(eventNames: string, callback: (data: any) => void, thisArg?: any); - on(event: 'propertyChange', callback: (data: any) => void, thisArg?: any); - off(eventNames: string, callback?: any, thisArg?: any); - addEventListener(eventNames: string, callback: (data: any) => void, thisArg?: any); - removeEventListener(eventNames: string, callback?: any, thisArg?: any); - set(name: string, value: any): void; - setProperty(name: string, value: any): void; - get(name: string): any; - notify(data: any): void; - notifyPropertyChange(propertyName: string, value: any, oldValue?: any): void; - hasListeners(eventName: string): boolean; + [Key in keyof import('data/observable').Observable]: import('data/observable').Observable[Key]; }; launched: boolean; // used by various classes to setup callbacks to wire up global app event handling when the app instance is ready diff --git a/packages/core/ui/action-bar/index.d.ts b/packages/core/ui/action-bar/index.d.ts index 89484c5a12..f57898b4a7 100644 --- a/packages/core/ui/action-bar/index.d.ts +++ b/packages/core/ui/action-bar/index.d.ts @@ -134,12 +134,12 @@ export class ActionItem extends ViewBase { * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (data: EventData) => void); + on(eventNames: string, callback: (data: EventData) => void): void; /** * Raised when a tap event occurs. */ - on(event: 'tap', callback: (args: EventData) => void); + on(event: 'tap', callback: (args: EventData) => void): void; //@private /** diff --git a/packages/core/ui/button/index.d.ts b/packages/core/ui/button/index.d.ts index 8560e1b68a..759307bf69 100644 --- a/packages/core/ui/button/index.d.ts +++ b/packages/core/ui/button/index.d.ts @@ -31,10 +31,10 @@ export class Button extends TextBase { * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); + on(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void; /** * Raised when a tap event occurs. */ - on(event: 'tap', callback: (args: EventData) => void, thisArg?: any); + on(event: 'tap', callback: (args: EventData) => void, thisArg?: any): void; } diff --git a/packages/core/ui/core/view/index.android.ts b/packages/core/ui/core/view/index.android.ts index af560c1011..8a0efda66e 100644 --- a/packages/core/ui/core/view/index.android.ts +++ b/packages/core/ui/core/view/index.android.ts @@ -351,7 +351,7 @@ export class View extends ViewCommon { } } - off(eventNames: string, callback?: any, thisArg?: any) { + off(eventNames: string, callback?: (data: EventData) => void, thisArg?: any) { super.off(eventNames, callback, thisArg); const isLayoutEvent = typeof eventNames === 'string' ? eventNames.indexOf(ViewCommon.layoutChangedEvent) !== -1 : false; diff --git a/packages/core/ui/core/view/view-common.ts b/packages/core/ui/core/view/view-common.ts index 437f62213d..a166daf044 100644 --- a/packages/core/ui/core/view/view-common.ts +++ b/packages/core/ui/core/view/view-common.ts @@ -293,7 +293,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition { } } - public removeEventListener(arg: string | GestureTypes, callback?: any, thisArg?: any) { + public removeEventListener(arg: string | GestureTypes, callback?: (data: EventData) => void, thisArg?: any) { if (typeof arg === 'string') { const gesture = gestureFromString(arg); if (gesture && !this._isEvent(arg)) { 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 213f915967..0635b7415e 100644 --- a/packages/core/ui/core/view/view-helper/index.d.ts +++ b/packages/core/ui/core/view/view-helper/index.d.ts @@ -46,21 +46,21 @@ export namespace IOSHelper { * Returns a view with viewController or undefined if no such found along the view's parent chain. * @param view The view form which to start the search. */ - export function getParentWithViewController(view: Partial): View; - export function updateAutoAdjustScrollInsets(controller: any /* UIViewController */, owner: Partial): void; - export function updateConstraints(controller: any /* UIViewController */, owner: Partial): void; - export function layoutView(controller: any /* UIViewController */, owner: Partial): void; + export function getParentWithViewController(view: View): View; + export function updateAutoAdjustScrollInsets(controller: any /* UIViewController */, owner: View): void; + export function updateConstraints(controller: any /* UIViewController */, owner: View): void; + export function layoutView(controller: any /* UIViewController */, owner: View): void; export function getPositionFromFrame(frame: any /* CGRect */): { left; top; right; bottom }; export function getFrameFromPosition(position: { left; top; right; bottom }, insets?: { left; top; right; bottom }): any; /* CGRect */ - export function shrinkToSafeArea(view: Partial, frame: any /* CGRect */): any; /* CGRect */ - export function expandBeyondSafeArea(view: Partial, frame: any /* CGRect */): any; /* CGRect */ + export function shrinkToSafeArea(view: View, frame: any /* CGRect */): any; /* CGRect */ + export function expandBeyondSafeArea(view: View, frame: any /* CGRect */): any; /* CGRect */ export class UILayoutViewController { - public static initWithOwner(owner: WeakRef>): UILayoutViewController; + public static initWithOwner(owner: WeakRef): UILayoutViewController; } export class UIAdaptivePresentationControllerDelegateImp { - public static initWithOwnerAndCallback(owner: WeakRef>, whenClosedCallback: Function): UIAdaptivePresentationControllerDelegateImp; + public static initWithOwnerAndCallback(owner: WeakRef, whenClosedCallback: Function): UIAdaptivePresentationControllerDelegateImp; } export class UIPopoverPresentationControllerDelegateImp { - public static initWithOwnerAndCallback(owner: WeakRef>, whenClosedCallback: Function): UIPopoverPresentationControllerDelegateImp; + public static initWithOwnerAndCallback(owner: WeakRef, whenClosedCallback: Function): UIPopoverPresentationControllerDelegateImp; } } diff --git a/packages/core/ui/core/weak-event-listener/index.ts b/packages/core/ui/core/weak-event-listener/index.ts index 21a34ebcc3..41b5ec8a36 100644 --- a/packages/core/ui/core/weak-event-listener/index.ts +++ b/packages/core/ui/core/weak-event-listener/index.ts @@ -1,7 +1,7 @@ import { Observable, EventData } from '../../../data/observable'; const handlersForEventName = new Map void>(); -const sourcesMap = new WeakMap, Map>>(); +const sourcesMap = new WeakMap>>(); class TargetHandlerPair { tagetRef: WeakRef; @@ -78,7 +78,7 @@ function validateArgs(source: Observable, eventName: string, handler: (eventData } } -export function addWeakEventListener(source: Observable, eventName: string, handler: (eventData: EventData) => void, target: any) { +export function addWeakEventListener(source: Observable, eventName: string, handler: (eventData: EventData) => void, target: any): void { validateArgs(source, eventName, handler, target); let shouldAttach = false; @@ -104,7 +104,7 @@ export function addWeakEventListener(source: Observable, eventName: string, hand } } -export function removeWeakEventListener(source: Observable, eventName: string, handler: (eventData: EventData) => void, target: any) { +export function removeWeakEventListener(source: Observable, eventName: string, handler: (eventData: EventData) => void, target: any): void { validateArgs(source, eventName, handler, target); const handlerForEventWithName = handlersForEventName.get(eventName); @@ -124,9 +124,9 @@ export function removeWeakEventListener(source: Observable, eventName: string, h } // Remove all pairs that match given target and handler or have a dead target - const targetHandlerPairsToRemove = []; - let pair; - let registeredTarget; + const targetHandlerPairsToRemove: number[] = []; + let pair: TargetHandlerPair; + let registeredTarget: Object; for (let i = 0; i < targetHandlerPairList.length; i++) { pair = targetHandlerPairList[i]; diff --git a/packages/core/ui/editable-text-base/index.android.ts b/packages/core/ui/editable-text-base/index.android.ts index 4c090a054a..48d5af0d0d 100644 --- a/packages/core/ui/editable-text-base/index.android.ts +++ b/packages/core/ui/editable-text-base/index.android.ts @@ -521,19 +521,14 @@ export abstract class EditableTextBase extends EditableTextBaseCommon { public onFocusChange(view: android.view.View, hasFocus: boolean): void { if (hasFocus) { clearDismissTimer(); - this.notify({ - eventName: EditableTextBase.focusEvent, - object: this, - }); + this.notify({ eventName: EditableTextBase.focusEvent }); } else { if (this._dirtyTextAccumulator || this._dirtyTextAccumulator === '') { textProperty.nativeValueChange(this, this._dirtyTextAccumulator); this._dirtyTextAccumulator = undefined; } - this.notify({ - eventName: EditableTextBase.blurEvent, - }); + this.notify({ eventName: EditableTextBase.blurEvent }); dismissSoftInput(this); } } diff --git a/packages/core/ui/frame/index.d.ts b/packages/core/ui/frame/index.d.ts index e541f4040a..8a91ec2c7c 100644 --- a/packages/core/ui/frame/index.d.ts +++ b/packages/core/ui/frame/index.d.ts @@ -221,17 +221,17 @@ export class Frame extends FrameBase { * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (args: EventData) => void, thisArg?: any); + on(eventNames: string, callback: (args: EventData) => void, thisArg?: any): void; /** * Raised when navigation to the page has started. */ - public on(event: 'navigatingTo', callback: (args: NavigationData) => void, thisArg?: any); + public on(event: 'navigatingTo', callback: (args: NavigationData) => void, thisArg?: any): void; /** * Raised when navigation to the page has finished. */ - public on(event: 'navigatedTo', callback: (args: NavigationData) => void, thisArg?: any); + public on(event: 'navigatedTo', callback: (args: NavigationData) => void, thisArg?: any): void; } /** diff --git a/packages/core/ui/gestures/index.d.ts b/packages/core/ui/gestures/index.d.ts index 1f67a06f84..b18e8b15cc 100644 --- a/packages/core/ui/gestures/index.d.ts +++ b/packages/core/ui/gestures/index.d.ts @@ -140,7 +140,7 @@ export interface GestureEventData extends EventData { /** * Gets the view which originates the gesture. */ - view: Partial; + view: View; /** * Gets the underlying native iOS specific [UIGestureRecognizer](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIGestureRecognizer_Class/). */ @@ -287,7 +287,7 @@ export class GesturesObserver { * @param callback - A function that will be executed when a gesture is received. * @param context - default this argument for the callbacks. */ - constructor(target: Partial, callback: (args: GestureEventData) => void, context: any); + constructor(target: View, callback: (args: GestureEventData) => void, context: any); /** * Registers a gesture observer to a view and gesture. diff --git a/packages/core/ui/image-cache/image-cache-common.ts b/packages/core/ui/image-cache/image-cache-common.ts index 7dfb0c7e0b..dfad03bb5c 100644 --- a/packages/core/ui/image-cache/image-cache-common.ts +++ b/packages/core/ui/image-cache/image-cache-common.ts @@ -1,5 +1,5 @@ import * as definition from '.'; -import * as observable from '../../data/observable'; +import { EventData, Observable } from '../../data/observable'; import * as imageSource from '../../image-source'; export interface DownloadRequest { @@ -9,7 +9,7 @@ export interface DownloadRequest { error?: (key: string) => void; } -export class Cache extends observable.Observable implements definition.Cache { +export class Cache extends Observable implements definition.Cache { public static downloadedEvent = 'downloaded'; public static downloadErrorEvent = 'downloadError'; @@ -215,7 +215,7 @@ export class Cache extends observable.Observable implements definition.Cache { } } export interface Cache { - on(eventNames: string, callback: (args: observable.EventData) => void, thisArg?: any); - on(event: 'downloaded', callback: (args: definition.DownloadedData) => void, thisArg?: any); - on(event: 'downloadError', callback: (args: definition.DownloadError) => void, thisArg?: any); + on(eventNames: string, callback: (args: EventData) => void, thisArg?: any): void; + on(event: 'downloaded', callback: (args: definition.DownloadedData) => void, thisArg?: any): void; + on(event: 'downloadError', callback: (args: definition.DownloadError) => void, thisArg?: any): void; } diff --git a/packages/core/ui/image-cache/index.d.ts b/packages/core/ui/image-cache/index.d.ts index 5bb06ad36b..774b5b11b7 100644 --- a/packages/core/ui/image-cache/index.d.ts +++ b/packages/core/ui/image-cache/index.d.ts @@ -85,17 +85,17 @@ export class Cache extends Observable { * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (args: EventData) => void, thisArg?: any); + on(eventNames: string, callback: (args: EventData) => void, thisArg?: any): void; /** * Raised when the image has been downloaded. */ - on(event: 'downloaded', callback: (args: DownloadedData) => void, thisArg?: any); + on(event: 'downloaded', callback: (args: DownloadedData) => void, thisArg?: any): void; /** * Raised if the image download errors. */ - on(event: 'downloadError', callback: (args: DownloadError) => void, thisArg?: any); + on(event: 'downloadError', callback: (args: DownloadError) => void, thisArg?: any): void; //@private /** diff --git a/packages/core/ui/list-view/index.d.ts b/packages/core/ui/list-view/index.d.ts index e1e6d85d86..6b9e96178d 100644 --- a/packages/core/ui/list-view/index.d.ts +++ b/packages/core/ui/list-view/index.d.ts @@ -108,7 +108,7 @@ export class ListView extends View { * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); + on(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void; /** * Raised when a View for the data at the specified index should be created. @@ -116,17 +116,17 @@ export class ListView extends View { * Note, that the view property of the event data can be pre-initialized with * an old instance of a view, so that it can be reused. */ - on(event: 'itemLoading', callback: (args: ItemEventData) => void, thisArg?: any); + on(event: 'itemLoading', callback: (args: ItemEventData) => void, thisArg?: any): void; /** * Raised when an item inside the ListView is tapped. */ - on(event: 'itemTap', callback: (args: ItemEventData) => void, thisArg?: any); + on(event: 'itemTap', callback: (args: ItemEventData) => void, thisArg?: any): void; /** * Raised when the ListView is scrolled so that its last item is visible. */ - on(event: 'loadMoreItems', callback: (args: EventData) => void, thisArg?: any); + on(event: 'loadMoreItems', callback: (args: EventData) => void, thisArg?: any): void; } /** @@ -164,8 +164,8 @@ export interface TemplatedItemsView { itemTemplate: string | Template; itemTemplates?: string | Array; refresh(): void; - on(event: 'itemLoading', callback: (args: ItemEventData) => void, thisArg?: any); - off(event: 'itemLoading', callback: (args: EventData) => void, thisArg?: any); + on(event: 'itemLoading', callback: (args: ItemEventData) => void, thisArg?: any): void; + off(event: 'itemLoading', callback: (args: EventData) => void, thisArg?: any): void; } /** diff --git a/packages/core/ui/page/page-common.ts b/packages/core/ui/page/page-common.ts index 6bfb4b122b..195ec71b23 100644 --- a/packages/core/ui/page/page-common.ts +++ b/packages/core/ui/page/page-common.ts @@ -172,7 +172,7 @@ export interface PageBase { on(event: 'navigatingFrom', callback: (args: NavigatedData) => void, thisArg?: any): void; on(event: 'navigatedFrom', callback: (args: NavigatedData) => void, thisArg?: any): void; on(event: 'showingModally', callback: (args: ShownModallyData) => void, thisArg?: any): void; - on(event: 'shownModally', callback: (args: ShownModallyData) => void, thisArg?: any); + on(event: 'shownModally', callback: (args: ShownModallyData) => void, thisArg?: any): void; } /** diff --git a/packages/core/ui/placeholder/index.android.ts b/packages/core/ui/placeholder/index.android.ts index 9bafa34f5d..ad7d56cf10 100644 --- a/packages/core/ui/placeholder/index.android.ts +++ b/packages/core/ui/placeholder/index.android.ts @@ -21,6 +21,6 @@ export class Placeholder extends View { } } export interface Placeholder { - on(eventNames: string, callback: (args: EventData) => void); - on(event: 'creatingView', callback: (args: CreateViewEventData) => void); + on(eventNames: string, callback: (args: EventData) => void, thisArg?: any): void; + on(event: 'creatingView', callback: (args: CreateViewEventData) => void, thisArg?: any): void; } diff --git a/packages/core/ui/placeholder/index.d.ts b/packages/core/ui/placeholder/index.d.ts index a2268c9a10..177fa46bba 100644 --- a/packages/core/ui/placeholder/index.d.ts +++ b/packages/core/ui/placeholder/index.d.ts @@ -18,12 +18,12 @@ export class Placeholder extends View { * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (args: EventData) => void); + on(eventNames: string, callback: (args: EventData) => void, thisArg?: any): void; /** * Raised when a creatingView event occurs. */ - on(event: 'creatingView', callback: (args: CreateViewEventData) => void); + on(event: 'creatingView', callback: (args: CreateViewEventData) => void, thisArg?: any): void; } /** diff --git a/packages/core/ui/placeholder/index.ts b/packages/core/ui/placeholder/index.ts index 2d6c5f05d9..edd598e4c1 100644 --- a/packages/core/ui/placeholder/index.ts +++ b/packages/core/ui/placeholder/index.ts @@ -20,6 +20,6 @@ export class Placeholder extends View { } } export interface Placeholder { - on(eventNames: string, callback: (args: EventData) => void); - on(event: 'creatingView', callback: (args: CreateViewEventData) => void); + on(eventNames: string, callback: (args: EventData) => void, thisArg?: any): void; + on(event: 'creatingView', callback: (args: CreateViewEventData) => void, thisArg?: any): void; } diff --git a/packages/core/ui/scroll-view/scroll-view-common.ts b/packages/core/ui/scroll-view/scroll-view-common.ts index 774d05b569..6e4e398066 100644 --- a/packages/core/ui/scroll-view/scroll-view-common.ts +++ b/packages/core/ui/scroll-view/scroll-view-common.ts @@ -16,7 +16,7 @@ export abstract class ScrollViewBase extends ContentView implements ScrollViewDe public scrollBarIndicatorVisible: boolean; public isScrollEnabled: boolean; - public addEventListener(arg: string, callback: any, thisArg?: any) { + public addEventListener(arg: string, callback: (data: EventData) => void, thisArg?: any): void { super.addEventListener(arg, callback, thisArg); if (arg === ScrollViewBase.scrollEvent) { @@ -25,7 +25,7 @@ export abstract class ScrollViewBase extends ContentView implements ScrollViewDe } } - public removeEventListener(arg: string, callback: any, thisArg?: any) { + public removeEventListener(arg: string, callback?: (data: EventData) => void, thisArg?: any): void { super.removeEventListener(arg, callback, thisArg); if (arg === ScrollViewBase.scrollEvent) { @@ -87,8 +87,8 @@ export abstract class ScrollViewBase extends ContentView implements ScrollViewDe public abstract _onOrientationChanged(); } export interface ScrollViewBase { - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); - on(event: 'scroll', callback: (args: ScrollEventData) => void, thisArg?: any); + on(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void; + on(event: 'scroll', callback: (args: ScrollEventData) => void, thisArg?: any): void; } const converter = makeParser(makeValidator(CoreTypes.Orientation.horizontal, CoreTypes.Orientation.vertical)); diff --git a/packages/core/ui/search-bar/index.d.ts b/packages/core/ui/search-bar/index.d.ts index 6283c5c20c..87dc902e4f 100644 --- a/packages/core/ui/search-bar/index.d.ts +++ b/packages/core/ui/search-bar/index.d.ts @@ -53,17 +53,17 @@ export class SearchBar extends View { * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); + on(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void; /** * Raised when a search bar search is submitted. */ - on(event: 'submit', callback: (args: EventData) => void, thisArg?: any); + on(event: 'submit', callback: (args: EventData) => void, thisArg?: any): void; /** * Raised when a search bar search is closed. */ - on(event: 'close', callback: (args: EventData) => void, thisArg?: any); + on(event: 'close', callback: (args: EventData) => void, thisArg?: any): void; /** * Hides the soft input method, usually a soft keyboard. diff --git a/packages/core/ui/segmented-bar/index.d.ts b/packages/core/ui/segmented-bar/index.d.ts index b3d0ed4e90..4a972513a7 100644 --- a/packages/core/ui/segmented-bar/index.d.ts +++ b/packages/core/ui/segmented-bar/index.d.ts @@ -60,12 +60,12 @@ export class SegmentedBar extends View implements AddChildFromBuilder, AddArrayF * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); + on(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void; /** * Raised when the selected index changes. */ - on(event: 'selectedIndexChanged', callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any); + on(event: 'selectedIndexChanged', callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any): void; /** * Called for every child element declared in xml. diff --git a/packages/core/ui/segmented-bar/segmented-bar-common.ts b/packages/core/ui/segmented-bar/segmented-bar-common.ts index 17026a3dd3..d486dae0c4 100644 --- a/packages/core/ui/segmented-bar/segmented-bar-common.ts +++ b/packages/core/ui/segmented-bar/segmented-bar-common.ts @@ -89,8 +89,8 @@ export abstract class SegmentedBarBase extends View implements SegmentedBarDefin } export interface SegmentedBarBase { - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); - on(event: 'selectedIndexChanged', callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any); + on(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void; + on(event: 'selectedIndexChanged', callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any): void; } SegmentedBarBase.prototype.recycleNativeView = 'auto'; diff --git a/packages/core/ui/tab-view/index.d.ts b/packages/core/ui/tab-view/index.d.ts index 8d65abe7c2..47fa963031 100644 --- a/packages/core/ui/tab-view/index.d.ts +++ b/packages/core/ui/tab-view/index.d.ts @@ -150,12 +150,12 @@ export class TabView extends View { * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); + on(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void; /** * Raised when the selected index changes. */ - on(event: 'selectedIndexChanged', callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any); + on(event: 'selectedIndexChanged', callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any): void; } export const itemsProperty: Property; diff --git a/packages/core/ui/tab-view/tab-view-common.ts b/packages/core/ui/tab-view/tab-view-common.ts index f2c880ffb3..eac13467e7 100644 --- a/packages/core/ui/tab-view/tab-view-common.ts +++ b/packages/core/ui/tab-view/tab-view-common.ts @@ -205,8 +205,8 @@ export class TabViewBase extends View implements TabViewDefinition, AddChildFrom } export interface TabViewBase { - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); - on(event: 'selectedIndexChanged', callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any); + on(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void; + on(event: 'selectedIndexChanged', callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any): void; } export function traceMissingIcon(icon: string) { diff --git a/packages/core/ui/text-base/span.ts b/packages/core/ui/text-base/span.ts index 84bbfe7ae3..da3130b256 100644 --- a/packages/core/ui/text-base/span.ts +++ b/packages/core/ui/text-base/span.ts @@ -81,12 +81,12 @@ export class Span extends ViewBase implements SpanDefinition { return this._tappable; } - addEventListener(arg: string, callback: (data: EventData) => void, thisArg?: any) { + addEventListener(arg: string, callback: (data: EventData) => void, thisArg?: any): void { super.addEventListener(arg, callback, thisArg); this._setTappable(this.hasListeners(Span.linkTapEvent)); } - removeEventListener(arg: string, callback?: any, thisArg?: any) { + removeEventListener(arg: string, callback?: (data: EventData) => void, thisArg?: any): void { super.removeEventListener(arg, callback, thisArg); this._setTappable(this.hasListeners(Span.linkTapEvent)); } diff --git a/packages/core/ui/web-view/index.d.ts b/packages/core/ui/web-view/index.d.ts index 9cd128b475..ef3a3a8106 100644 --- a/packages/core/ui/web-view/index.d.ts +++ b/packages/core/ui/web-view/index.d.ts @@ -92,17 +92,17 @@ export class WebView extends View { * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); + on(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void; /** * Raised when a loadFinished event occurs. */ - on(event: 'loadFinished', callback: (args: LoadEventData) => void, thisArg?: any); + on(event: 'loadFinished', callback: (args: LoadEventData) => void, thisArg?: any): void; /** * Raised when a loadStarted event occurs. */ - on(event: 'loadStarted', callback: (args: LoadEventData) => void, thisArg?: any); + on(event: 'loadStarted', callback: (args: LoadEventData) => void, thisArg?: any): void; } /** diff --git a/packages/core/utils/typescript-utils.d.ts b/packages/core/utils/typescript-utils.d.ts new file mode 100644 index 0000000000..2b7de2fd33 --- /dev/null +++ b/packages/core/utils/typescript-utils.d.ts @@ -0,0 +1,6 @@ +/** + * Makes the specified properties in a type optional. + * @example type NotifyData = Optional + * // returns: { eventName: string; object?: Observable } + */ +export type Optional = Omit & { [P in K]?: T[P] }; diff --git a/tools/scripts/api-reports/NativeScript.api.md b/tools/scripts/api-reports/NativeScript.api.md index 4dde08a085..54839b9541 100644 --- a/tools/scripts/api-reports/NativeScript.api.md +++ b/tools/scripts/api-reports/NativeScript.api.md @@ -1500,7 +1500,7 @@ export class Observable { notifyPropertyChange(propertyName: string, value: any, oldValue?: any): void; - off(eventNames: string, callback?: any, thisArg?: any); + off(eventNames: string, callback?: (data: EventData) => void, thisArg?: any); on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); @@ -1510,7 +1510,7 @@ export class Observable { public static propertyChangeEvent: string; - removeEventListener(eventNames: string, callback?: any, thisArg?: any); + removeEventListener(eventNames: string, callback?: (data: EventData) => void, thisArg?: any); set(name: string, value: any): void;