Skip to content
Open
94 changes: 74 additions & 20 deletions packages/core/application/application-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { NavigationEntry } from '../ui/frame/frame-interfaces';
import type { StyleScope } from '../ui/styling/style-scope';
import type { AndroidApplication as AndroidApplicationType, iOSApplication as iOSApplicationType } from '.';
import type { ApplicationEventData, CssChangedEventData, DiscardedErrorEventData, FontScaleChangedEventData, InitRootViewEventData, LaunchEventData, LoadAppCSSEventData, NativeScriptError, OrientationChangedEventData, SystemAppearanceChangedEventData, LayoutDirectionChangedEventData, UnhandledErrorEventData } from './application-interfaces';
import { ApplicationEventNames, ApplicationEventNameType } from './application-event-names';
import { readyInitAccessibilityCssHelper, readyInitFontScale } from '../accessibility/accessibility-common';
import { getAppMainEntry, isAppInBackground, setAppInBackground, setAppMainEntry } from './helpers-common';
import { getNativeScriptGlobals } from '../globals/global-utils';
Expand Down Expand Up @@ -179,26 +180,7 @@ interface ApplicationEvents {
on(event: 'fontScaleChanged', callback: (args: FontScaleChangedEventData) => void, thisArg?: any): void;
}

export class ApplicationCommon {
readonly launchEvent = 'launch';
readonly suspendEvent = 'suspend';
readonly displayedEvent = 'displayed';
readonly backgroundEvent = 'background';
readonly foregroundEvent = 'foreground';
readonly resumeEvent = 'resume';
readonly exitEvent = 'exit';
readonly lowMemoryEvent = 'lowMemory';
readonly uncaughtErrorEvent = 'uncaughtError';
readonly discardedErrorEvent = 'discardedError';
readonly orientationChangedEvent = 'orientationChanged';
readonly systemAppearanceChangedEvent = 'systemAppearanceChanged';
readonly layoutDirectionChangedEvent = 'layoutDirectionChanged';
readonly fontScaleChangedEvent = 'fontScaleChanged';
readonly livesyncEvent = 'livesync';
readonly loadAppCssEvent = 'loadAppCss';
readonly cssChangedEvent = 'cssChanged';
readonly initRootViewEvent = 'initRootView';

export class ApplicationCommon implements ApplicationEventNameType {
// Expose statically for backwards compat on AndroidApplication.on etc.
/**
* @deprecated Use `Application.android.on()` instead.
Expand Down Expand Up @@ -277,6 +259,78 @@ export class ApplicationCommon {
};
}

get launchEvent() {
return ApplicationEventNames.launchEvent;
}

get suspendEvent() {
return ApplicationEventNames.suspendEvent;
}

get displayedEvent() {
return ApplicationEventNames.displayedEvent;
}

get backgroundEvent() {
return ApplicationEventNames.backgroundEvent;
}

get foregroundEvent() {
return ApplicationEventNames.foregroundEvent;
}

get resumeEvent() {
return ApplicationEventNames.resumeEvent;
}

get exitEvent() {
return ApplicationEventNames.exitEvent;
}

get lowMemoryEvent() {
return ApplicationEventNames.lowMemoryEvent;
}

get uncaughtErrorEvent() {
return ApplicationEventNames.uncaughtErrorEvent;
}

get discardedErrorEvent() {
return ApplicationEventNames.discardedErrorEvent;
}

get orientationChangedEvent() {
return ApplicationEventNames.orientationChangedEvent;
}

get systemAppearanceChangedEvent() {
return ApplicationEventNames.systemAppearanceChangedEvent;
}

get layoutDirectionChangedEvent() {
return ApplicationEventNames.layoutDirectionChangedEvent;
}

get fontScaleChangedEvent() {
return ApplicationEventNames.fontScaleChangedEvent;
}

get livesyncEvent() {
return ApplicationEventNames.livesyncEvent;
}

get loadAppCssEvent() {
return ApplicationEventNames.loadAppCssEvent;
}

get cssChangedEvent() {
return ApplicationEventNames.cssChangedEvent;
}

get initRootViewEvent() {
return ApplicationEventNames.initRootViewEvent;
}

/**
* @internal
*/
Expand Down
23 changes: 23 additions & 0 deletions packages/core/application/application-event-names.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export const ApplicationEventNames = Object.freeze({
launchEvent: 'launch',
suspendEvent: 'suspend',
displayedEvent: 'displayed',
backgroundEvent: 'background',
foregroundEvent: 'foreground',
resumeEvent: 'resume',
exitEvent: 'exit',
lowMemoryEvent: 'lowMemory',
uncaughtErrorEvent: 'uncaughtError',
discardedErrorEvent: 'discardedError',
orientationChangedEvent: 'orientationChanged',
systemAppearanceChangedEvent: 'systemAppearanceChanged',
layoutDirectionChangedEvent: 'layoutDirectionChanged',
fontScaleChangedEvent: 'fontScaleChanged',
livesyncEvent: 'livesync',
loadAppCssEvent: 'loadAppCss',
cssChangedEvent: 'cssChanged',
initRootViewEvent: 'initRootView',
});

export type ApplicationEventNameType = typeof ApplicationEventNames;
export type ApplicationEventName = ApplicationEventNameType[keyof ApplicationEventNameType];
14 changes: 1 addition & 13 deletions packages/core/application/application.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import {
setA11yEnabled,
} from '../accessibility/accessibility-common';
import { androidGetForegroundActivity, androidGetStartActivity, androidSetForegroundActivity, androidSetStartActivity, applyContentDescription } from './helpers';
import { getImageFetcher, getNativeApp, getRootView, initImageCache, setA11yUpdatePropertiesCallback, setApplicationPropertiesCallback, setAppMainEntry, setNativeApp, setRootView, setToggleApplicationEventListenersCallback } from './helpers-common';
import { getImageFetcher, getNativeApp, getRootView, initImageCache, setA11yUpdatePropertiesCallback, setApplicationPropertiesCallback, setAppMainEntry, setNativeApp, setRootView } from './helpers-common';
import { getNativeScriptGlobals } from '../globals/global-utils';
import type { AndroidApplication as IAndroidApplication } from './application';
import lazy from '../utils/lazy';
Expand Down Expand Up @@ -1447,18 +1447,6 @@ function setAccessibilityDelegate(view: View): void {
androidView.setAccessibilityDelegate(TNSAccessibilityDelegate);
}

const applicationEvents: string[] = [Application.orientationChangedEvent, Application.systemAppearanceChangedEvent];
function toggleApplicationEventListeners(toAdd: boolean, callback: (args: ApplicationEventData) => void) {
for (const eventName of applicationEvents) {
if (toAdd) {
Application.on(eventName, callback);
} else {
Application.off(eventName, callback);
}
}
}
setToggleApplicationEventListenersCallback(toggleApplicationEventListeners);

setApplicationPropertiesCallback(() => {
return {
orientation: Application.orientation(),
Expand Down
14 changes: 1 addition & 13 deletions packages/core/application/application.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import {
enforceArray,
} from '../accessibility/accessibility-common';
import { CoreTypes } from '../core-types';
import { getiOSWindow, setA11yUpdatePropertiesCallback, setApplicationPropertiesCallback, setAppMainEntry, setiOSWindow, setRootView, setToggleApplicationEventListenersCallback } from './helpers-common';
import { getiOSWindow, setA11yUpdatePropertiesCallback, setApplicationPropertiesCallback, setAppMainEntry, setiOSWindow, setRootView } from './helpers-common';

@NativeClass
class NotificationObserver extends NSObject {
Expand Down Expand Up @@ -1754,18 +1754,6 @@ export function initAccessibilityCssHelper(): void {
}
setInitAccessibilityCssHelper(initAccessibilityCssHelper);

const applicationEvents: string[] = [Application.orientationChangedEvent, Application.systemAppearanceChangedEvent];
function toggleApplicationEventListeners(toAdd: boolean, callback: (args: ApplicationEventData) => void) {
for (const eventName of applicationEvents) {
if (toAdd) {
Application.on(eventName, callback);
} else {
Application.off(eventName, callback);
}
}
}
setToggleApplicationEventListenersCallback(toggleApplicationEventListeners);

setApplicationPropertiesCallback(() => {
return {
orientation: Application.orientation(),
Expand Down
11 changes: 0 additions & 11 deletions packages/core/application/helpers-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,6 @@ export function setAppMainEntry(entry: any /* NavigationEntry */) {
_appMainEntry = entry;
}

// Aids avoiding circular dependencies by allowing the application event listeners to be toggled
let _toggleApplicationEventListenersHandler: (toAdd: boolean, callback: (args: any) => void) => void;
export function toggleApplicationEventListeners(toAdd: boolean, callback: (args: any) => void) {
if (_toggleApplicationEventListenersHandler) {
_toggleApplicationEventListenersHandler(toAdd, callback);
}
}
export function setToggleApplicationEventListenersCallback(callback: (toAdd: boolean, callback: (args: any) => void) => void) {
_toggleApplicationEventListenersHandler = callback;
}

// Aids avoiding circular dependencies by allowing the application properties to be retrieved
type ApplicationPropertyValues = { orientation: 'portrait' | 'landscape' | 'unknown'; systemAppearance: 'dark' | 'light' | null };
let _applicationPropertiesCallback: () => ApplicationPropertyValues;
Expand Down
1 change: 0 additions & 1 deletion packages/core/application/helpers.android.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SDK_VERSION } from '../utils/constants';
import { getNativeApp, updateA11yPropertiesCallback } from './helpers-common';
import { AccessibilityRole, AccessibilityState } from '../accessibility/accessibility-common';
import { Trace } from '../trace';
Expand Down
118 changes: 8 additions & 110 deletions packages/core/css-mediaquery/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,118 +1,16 @@
import { MediaQueryType, matchQuery, parseQuery } from '.';
import { checkIfMediaQueryMatches } from '.';
import { Screen } from '../platform';

describe('css-mediaquery', () => {
describe('parseQuery', () => {
it('should parse media queries without expressions', () => {
expect(parseQuery('screen')).toEqual([
{
inverse: false,
type: MediaQueryType.screen,
features: [],
},
]);
const { widthDIPs } = Screen.mainScreen;

expect(parseQuery('not screen')).toEqual([
{
inverse: true,
type: MediaQueryType.screen,
features: [],
},
]);
describe('checkIfMediaQueryMatches', () => {
it('should return true for a correct match', () => {
expect(checkIfMediaQueryMatches(`only screen and (max-width: ${widthDIPs})`)).toBe(true);
});

it('should throw a SyntaxError when a media query is invalid', () => {
expect(() => parseQuery('some crap')).toThrow(SyntaxError);
expect(() => parseQuery('48em')).toThrow(SyntaxError);
expect(() => parseQuery('screen and crap')).toThrow(SyntaxError);
expect(() => parseQuery('screen and (48em)')).toThrow(SyntaxError);
expect(() => parseQuery('screen and (foo:)')).toThrow(SyntaxError);
expect(() => parseQuery('()')).toThrow(SyntaxError);
expect(() => parseQuery('(foo) (bar)')).toThrow(SyntaxError);
expect(() => parseQuery('(foo:) and (bar)')).toThrow(SyntaxError);
});
});

describe('matchQuery', () => {
describe('Equality check', () => {
it('orientation: should return true for a correct match (===)', () => {
expect(matchQuery('(orientation: portrait)', { orientation: 'portrait' })).toBe(true);
});

it('orientation: should return false for an incorrect match (===)', () => {
expect(matchQuery('(orientation: landscape)', { orientation: 'portrait' })).toBe(false);
});

it('prefers-color-scheme: should return true for a correct match (===)', () => {
expect(matchQuery('(prefers-color-scheme: dark)', { 'prefers-color-scheme': 'dark' })).toBe(true);
});

it('prefers-color-scheme: should return false for an incorrect match (===)', () => {
expect(matchQuery('(prefers-color-scheme: light)', { 'prefers-color-scheme': 'dark' })).toBe(false);
});

it('width: should return true for a correct match', () => {
expect(matchQuery('(width: 800px)', { width: 800 })).toBe(true);
});

it('width: should return false for an incorrect match', () => {
expect(matchQuery('(width: 800px)', { width: 900 })).toBe(false);
});
});

describe('Type', () => {
it('should return true for a correct match', () => {
expect(matchQuery('screen', { type: MediaQueryType.screen })).toBe(true);
});

it('should return false for an incorrect match', () => {
expect(
matchQuery('screen and (orientation: portrait)', {
type: MediaQueryType.print,
orientation: 'portrait',
}),
).toBe(false);
});

it('should return false for a media query without a type when type is specified in the value object', () => {
expect(matchQuery('(min-width: 500px)', { type: MediaQueryType.screen })).toBe(false);
});

it('should return true for a media query without a type when type is not specified in the value object', () => {
expect(matchQuery('(min-width: 500px)', { width: 700 })).toBe(true);
});
});

describe('Not', () => {
it('should return false when theres a match on a `not` query', () => {
expect(
matchQuery('not screen and (orientation: portrait)', {
type: MediaQueryType.screen,
orientation: 'landscape',
}),
).toBe(false);
});

it('should not disrupt an OR query', () => {
expect(
matchQuery('not screen and (color), screen and (min-height: 48em)', {
type: MediaQueryType.screen,
height: 1000,
}),
).toBe(true);
});

it('should return false for when type === all', () => {
expect(
matchQuery('not all and (min-width: 48em)', {
type: MediaQueryType.all,
width: 1000,
}),
).toBe(false);
});

it('should return true for inverted value', () => {
expect(matchQuery('not screen and (min-width: 48px)', { width: 24 })).toBe(true);
});
it('should return false for an incorrect match', () => {
expect(checkIfMediaQueryMatches(`only screen and (max-width: ${widthDIPs - 1})`)).toBe(false);
});
});
});
Loading