diff --git a/packages/core/accessibility/accessibility-service.android.ts b/packages/core/accessibility/accessibility-service.android.ts index f76ed0891..b8c166d80 100644 --- a/packages/core/accessibility/accessibility-service.android.ts +++ b/packages/core/accessibility/accessibility-service.android.ts @@ -2,6 +2,7 @@ import * as Application from '../application'; import { Observable } from '../data/observable'; import { Trace } from '../trace'; import * as Utils from '../utils'; +import { SDK_VERSION } from '../utils/constants'; import { CommonA11YServiceEnabledObservable, SharedA11YObservable } from './accessibility-service-common'; export function getAndroidAccessibilityManager(): android.view.accessibility.AccessibilityManager | null { @@ -73,7 +74,7 @@ function ensureStateListener(): SharedA11YObservable { }); accessibilityManager.addAccessibilityStateChangeListener(accessibilityStateChangeListener); - if (Utils.SDK_VERSION >= 19) { + if (SDK_VERSION >= 19) { touchExplorationStateChangeListener = new android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener({ onTouchExplorationStateChanged(enabled) { updateAccessibilityState(); diff --git a/packages/core/accessibility/index.android.ts b/packages/core/accessibility/index.android.ts index 2ebc884c1..b36f3bc77 100644 --- a/packages/core/accessibility/index.android.ts +++ b/packages/core/accessibility/index.android.ts @@ -1,6 +1,6 @@ import * as Application from '../application'; import { Trace } from '../trace'; -import { SDK_VERSION } from '../utils'; +import { SDK_VERSION } from '../utils/constants'; import type { View } from '../ui/core/view'; import { GestureTypes } from '../ui/gestures'; import { notifyAccessibilityFocusState } from './accessibility-common'; diff --git a/packages/core/connectivity/index.android.ts b/packages/core/connectivity/index.android.ts index dac342726..e3f4c7c48 100644 --- a/packages/core/connectivity/index.android.ts +++ b/packages/core/connectivity/index.android.ts @@ -1,5 +1,5 @@ import { android as androidApp, getNativeApplication } from '../application'; -import { SDK_VERSION } from '../utils'; +import { SDK_VERSION } from '../utils/constants'; export enum connectionType { none = 0, diff --git a/packages/core/file-system/file-system-access.android.ts b/packages/core/file-system/file-system-access.android.ts index 82caafafa..b70af1da0 100644 --- a/packages/core/file-system/file-system-access.android.ts +++ b/packages/core/file-system/file-system-access.android.ts @@ -1,6 +1,7 @@ import * as textModule from '../text'; import { getNativeApplication } from '../application'; -import { SDK_VERSION } from '../utils'; +import { getFileExtension } from '../utils'; +import { SDK_VERSION } from '../utils/constants'; import type { IFileSystemAccess } from './file-system-access'; @@ -529,12 +530,7 @@ export class FileSystemAccess implements IFileSystemAccess { // TODO: This method is the same as in the iOS implementation. // Make it in a separate file / module so it can be reused from both implementations. public getFileExtension(path: string): string { - const dotIndex = path.lastIndexOf('.'); - if (dotIndex && dotIndex >= 0 && dotIndex < path.length) { - return path.substring(dotIndex); - } - - return ''; + return getFileExtension(path); } private enumEntities(path: string, callback: (entity: { path: string; name: string; extension: string }) => boolean, onError?: (error) => any) { diff --git a/packages/core/file-system/index.ts b/packages/core/file-system/index.ts index 3818491a1..a92226d0c 100644 --- a/packages/core/file-system/index.ts +++ b/packages/core/file-system/index.ts @@ -1,6 +1,5 @@ import { IFileSystemAccess, FileSystemAccess, FileSystemAccess29 } from './file-system-access'; -import { Device } from '../platform'; -import { SDK_VERSION } from '../utils'; +import { SDK_VERSION } from '../utils/constants'; // The FileSystemAccess implementation, used through all the APIs. let fileAccess: IFileSystemAccess; diff --git a/packages/core/fps-meter/fps-native.android.ts b/packages/core/fps-meter/fps-native.android.ts index c71bed6a2..8025b1a38 100644 --- a/packages/core/fps-meter/fps-native.android.ts +++ b/packages/core/fps-meter/fps-native.android.ts @@ -1,5 +1,5 @@ import * as definition from './fps-native'; -import { SDK_VERSION } from '../utils'; +import { SDK_VERSION } from '../utils/constants'; export class FPSCallback implements definition.FPSCallback { private impl: android.view.Choreographer.FrameCallback | ((nanos: number) => void); diff --git a/packages/core/index.d.ts b/packages/core/index.d.ts index c92f5b7be..94f9f6f35 100644 --- a/packages/core/index.d.ts +++ b/packages/core/index.d.ts @@ -105,10 +105,12 @@ export type { InstrumentationMode, TimerInfo } from './profiling'; export { encoding } from './text'; export * from './trace'; export * from './ui'; -import { GC, isFontIconURI, isDataURI, isFileOrResourcePath, executeOnMainThread, mainThreadify, isMainThread, dispatchToMainThread, executeOnUIThread, releaseNativeObject, getModuleName, openFile, openUrl, isRealDevice, layout, ad as androidUtils, iOSNativeHelper as iosUtils, Source, escapeRegexSymbols, convertString, dismissSoftInput, dismissKeyboard, queueMacrotask, queueGC, throttle, debounce, dataSerialize, dataDeserialize, copyToClipboard } from './utils'; +import { GC, isFontIconURI, isDataURI, isFileOrResourcePath, executeOnMainThread, mainThreadify, isMainThread, dispatchToMainThread, executeOnUIThread, releaseNativeObject, getModuleName, openFile, openUrl, isRealDevice, layout, ad as androidUtils, iOSNativeHelper as iosUtils, Source, escapeRegexSymbols, convertString, dismissSoftInput, dismissKeyboard, queueMacrotask, queueGC, throttle, debounce, dataSerialize, dataDeserialize, copyToClipboard, getFileExtension } from './utils'; +import { SDK_VERSION } from './utils/constants'; import { ClassInfo, getClass, getBaseClasses, getClassInfo, isBoolean, isDefined, isFunction, isNullOrUndefined, isNumber, isObject, isString, isUndefined, toUIString, verifyCallback, numberHasDecimals, numberIs64Bit } from './utils/types'; export declare const Utils: { GC: typeof GC; + SDK_VERSION: typeof SDK_VERSION; RESOURCE_PREFIX: string; FILE_PREFIX: string; queueMacrotask: typeof queueMacrotask; @@ -118,6 +120,7 @@ export declare const Utils: { isFontIconURI: typeof isFontIconURI; isDataURI: typeof isDataURI; isFileOrResourcePath: typeof isFileOrResourcePath; + getFileExtension: typeof getFileExtension; executeOnMainThread: typeof executeOnMainThread; executeOnUIThread: typeof executeOnUIThread; mainThreadify: typeof mainThreadify; diff --git a/packages/core/index.ts b/packages/core/index.ts index 4d536133e..8ffe4069a 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -137,16 +137,19 @@ export * from './trace'; export * from './ui'; -import { GC, isFontIconURI, isDataURI, isFileOrResourcePath, executeOnMainThread, mainThreadify, isMainThread, dispatchToMainThread, executeOnUIThread, queueMacrotask, queueGC, debounce, throttle, releaseNativeObject, getModuleName, openFile, openUrl, isRealDevice, layout, ad as androidUtils, iOSNativeHelper as iosUtils, Source, RESOURCE_PREFIX, FILE_PREFIX, escapeRegexSymbols, convertString, dismissSoftInput, dismissKeyboard, dataDeserialize, dataSerialize, copyToClipboard } from './utils'; +import { GC, isFontIconURI, isDataURI, isFileOrResourcePath, executeOnMainThread, mainThreadify, isMainThread, dispatchToMainThread, executeOnUIThread, queueMacrotask, queueGC, debounce, throttle, releaseNativeObject, getModuleName, openFile, openUrl, isRealDevice, layout, ad as androidUtils, iOSNativeHelper as iosUtils, Source, RESOURCE_PREFIX, FILE_PREFIX, escapeRegexSymbols, convertString, dismissSoftInput, dismissKeyboard, dataDeserialize, dataSerialize, copyToClipboard, getFileExtension } from './utils'; +import { SDK_VERSION } from './utils/constants'; import { ClassInfo, getClass, getBaseClasses, getClassInfo, isBoolean, isDefined, isFunction, isNullOrUndefined, isNumber, isObject, isString, isUndefined, toUIString, verifyCallback, numberHasDecimals, numberIs64Bit } from './utils/types'; export const Utils = { GC, + SDK_VERSION, RESOURCE_PREFIX, FILE_PREFIX, isFontIconURI, isDataURI, isFileOrResourcePath, + getFileExtension, executeOnMainThread, executeOnUIThread, mainThreadify, diff --git a/packages/core/platform/index.android.ts b/packages/core/platform/index.android.ts index 7fc79287f..2e04be392 100644 --- a/packages/core/platform/index.android.ts +++ b/packages/core/platform/index.android.ts @@ -1,6 +1,6 @@ /* tslint:disable:class-name */ import { getNativeApplication, on, orientationChangedEvent, android as AndroidApplication } from '../application'; -import { SDK_VERSION } from '../utils'; +import { SDK_VERSION } from '../utils/constants'; const MIN_TABLET_PIXELS = 600; diff --git a/packages/core/ui/action-bar/index.android.ts b/packages/core/ui/action-bar/index.android.ts index 3e9f9915c..7cb7b7ace 100644 --- a/packages/core/ui/action-bar/index.android.ts +++ b/packages/core/ui/action-bar/index.android.ts @@ -8,7 +8,7 @@ import { ImageSource } from '../../image-source'; import * as application from '../../application'; import { isAccessibilityServiceEnabled, updateContentDescription } from '../../accessibility'; import type { Background } from '../styling/background'; -import { SDK_VERSION } from '../../utils'; +import { SDK_VERSION } from '../../utils/constants'; export * from './action-bar-common'; diff --git a/packages/core/ui/animation/index.android.ts b/packages/core/ui/animation/index.android.ts index ea57123c5..ded8386fa 100644 --- a/packages/core/ui/animation/index.android.ts +++ b/packages/core/ui/animation/index.android.ts @@ -7,7 +7,8 @@ import { AnimationBase, Properties, CubicBezierAnimationCurve } from './animatio import { Color } from '../../color'; import { Trace } from '../../trace'; import { opacityProperty, backgroundColorProperty, rotateProperty, rotateXProperty, rotateYProperty, translateXProperty, translateYProperty, scaleXProperty, scaleYProperty, heightProperty, widthProperty, PercentLength } from '../styling/style-properties'; -import { SDK_VERSION, layout } from '../../utils'; +import { layout } from '../../utils'; +import { SDK_VERSION } from '../../utils/constants'; import { Device, Screen } from '../../platform'; import lazy from '../../utils/lazy'; diff --git a/packages/core/ui/button/index.android.ts b/packages/core/ui/button/index.android.ts index 1cd0e3b13..4099c24a8 100644 --- a/packages/core/ui/button/index.android.ts +++ b/packages/core/ui/button/index.android.ts @@ -6,7 +6,7 @@ import { CoreTypes } from '../../core-types'; import { profile } from '../../profiling'; import { TouchGestureEventData, GestureTypes, TouchAction } from '../gestures'; import { Device } from '../../platform'; -import { SDK_VERSION } from '../../utils'; +import { SDK_VERSION } from '../../utils/constants'; import lazy from '../../utils/lazy'; import type { Background } from '../styling/background'; diff --git a/packages/core/ui/core/view/index.android.ts b/packages/core/ui/core/view/index.android.ts index 8f401b054..62304fd51 100644 --- a/packages/core/ui/core/view/index.android.ts +++ b/packages/core/ui/core/view/index.android.ts @@ -23,6 +23,7 @@ import lazy from '../../../utils/lazy'; import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty } from '../../../accessibility/accessibility-properties'; import { AccessibilityLiveRegion, AccessibilityRole, AndroidAccessibilityEvent, setupAccessibleView, isAccessibilityServiceEnabled, sendAccessibilityEvent, updateAccessibilityProperties, updateContentDescription, AccessibilityState } from '../../../accessibility'; import * as Utils from '../../../utils'; +import { SDK_VERSION } from '../../../utils/constants'; import { CSSShadow } from '../../styling/css-shadow'; export * from './view-common'; @@ -846,7 +847,7 @@ export class View extends ViewCommon { this.accessibilityRole = value; updateAccessibilityProperties(this); - if (Utils.SDK_VERSION >= 28) { + if (SDK_VERSION >= 28) { this.nativeViewProtected?.setAccessibilityHeading(value === AccessibilityRole.Header); } } @@ -904,7 +905,7 @@ export class View extends ViewCommon { return this.getDefaultElevation(); } [androidElevationProperty.setNative](value: number) { - if (Utils.SDK_VERSION < 21) { + if (SDK_VERSION < 21) { return; } @@ -915,7 +916,7 @@ export class View extends ViewCommon { return this.getDefaultDynamicElevationOffset(); } [androidDynamicElevationOffsetProperty.setNative](value: number) { - if (Utils.SDK_VERSION < 21) { + if (SDK_VERSION < 21) { return; } @@ -923,7 +924,7 @@ export class View extends ViewCommon { } protected getDefaultElevation(): number { - if (Utils.SDK_VERSION < 21) { + if (SDK_VERSION < 21) { return 0; } diff --git a/packages/core/ui/editable-text-base/index.android.ts b/packages/core/ui/editable-text-base/index.android.ts index f31b2bcd1..e0d0352af 100644 --- a/packages/core/ui/editable-text-base/index.android.ts +++ b/packages/core/ui/editable-text-base/index.android.ts @@ -1,7 +1,8 @@ import { EditableTextBase as EditableTextBaseCommon, autofillTypeProperty, keyboardTypeProperty, returnKeyTypeProperty, editableProperty, autocapitalizationTypeProperty, autocorrectProperty, hintProperty, placeholderColorProperty, maxLengthProperty } from './editable-text-base-common'; import { textTransformProperty, textProperty, resetSymbol } from '../text-base'; import { Color } from '../../color'; -import { SDK_VERSION, ad } from '../../utils'; +import { ad } from '../../utils'; +import { SDK_VERSION } from '../../utils/constants'; import { CoreTypes } from '../../core-types'; export * from './editable-text-base-common'; diff --git a/packages/core/ui/html-view/index.android.ts b/packages/core/ui/html-view/index.android.ts index 90e8b65ba..3865cb594 100644 --- a/packages/core/ui/html-view/index.android.ts +++ b/packages/core/ui/html-view/index.android.ts @@ -1,5 +1,5 @@ import { Color } from '../../color'; -import { SDK_VERSION } from '../../utils'; +import { SDK_VERSION } from '../../utils/constants'; import { Font } from '../styling/font'; import { colorProperty, fontSizeProperty, fontInternalProperty } from '../styling/style-properties'; import { HtmlViewBase, htmlProperty, selectableProperty, linkColorProperty } from './html-view-common'; diff --git a/packages/core/ui/page/index.android.ts b/packages/core/ui/page/index.android.ts index 793201b57..8adff9fd5 100644 --- a/packages/core/ui/page/index.android.ts +++ b/packages/core/ui/page/index.android.ts @@ -4,7 +4,7 @@ import { View } from '../core/view'; import { Color } from '../../color'; import { ActionBar } from '../action-bar'; import { GridLayout } from '../layouts/grid-layout'; -import { SDK_VERSION } from '../../utils'; +import { SDK_VERSION } from '../../utils/constants'; import { profile } from '../../profiling'; import { AndroidAccessibilityEvent, getLastFocusedViewOnPage, isAccessibilityServiceEnabled } from '../../accessibility'; diff --git a/packages/core/ui/segmented-bar/index.android.ts b/packages/core/ui/segmented-bar/index.android.ts index e43017321..bc0588330 100644 --- a/packages/core/ui/segmented-bar/index.android.ts +++ b/packages/core/ui/segmented-bar/index.android.ts @@ -3,7 +3,8 @@ import { SegmentedBarItemBase, SegmentedBarBase, selectedIndexProperty, itemsPro import { isEnabledProperty } from '../core/view'; import { colorProperty, fontInternalProperty, fontSizeProperty } from '../styling/style-properties'; import { Color } from '../../color'; -import { SDK_VERSION, layout } from '../../utils'; +import { layout } from '../../utils'; +import { SDK_VERSION } from '../../utils/constants'; export * from './segmented-bar-common'; diff --git a/packages/core/ui/styling/font.android.ts b/packages/core/ui/styling/font.android.ts index 5e08bb222..572e5a4a4 100644 --- a/packages/core/ui/styling/font.android.ts +++ b/packages/core/ui/styling/font.android.ts @@ -1,7 +1,7 @@ import { Font as FontBase, parseFontFamily, genericFontFamilies, FontWeight, FontVariationSettings } from './font-common'; import { FontStyleType, FontWeightType, FontVariationSettingsType } from './font-interfaces'; import { Trace } from '../../trace'; -import { SDK_VERSION } from '../../utils'; +import { SDK_VERSION } from '../../utils/constants'; import * as fs from '../../file-system'; import { ad } from '../../utils'; diff --git a/packages/core/ui/text-base/index.android.ts b/packages/core/ui/text-base/index.android.ts index 255ab422c..4fd681b4f 100644 --- a/packages/core/ui/text-base/index.android.ts +++ b/packages/core/ui/text-base/index.android.ts @@ -11,7 +11,8 @@ import { colorProperty, fontSizeProperty, fontInternalProperty, paddingLeftPrope import { FormattedString } from './formatted-string'; import { Span } from './span'; import { CoreTypes } from '../../core-types'; -import { SDK_VERSION, layout } from '../../utils'; +import { layout } from '../../utils'; +import { SDK_VERSION } from '../../utils/constants'; import { isString, isNullOrUndefined } from '../../utils/types'; import { accessibilityIdentifierProperty } from '../../accessibility/accessibility-properties'; import * as Utils from '../../utils'; diff --git a/packages/core/ui/time-picker/index.android.ts b/packages/core/ui/time-picker/index.android.ts index 3a8b90d0d..b64140f88 100644 --- a/packages/core/ui/time-picker/index.android.ts +++ b/packages/core/ui/time-picker/index.android.ts @@ -1,5 +1,5 @@ import { TimePickerBase, getValidTime, timeProperty, hourProperty, minuteProperty } from './time-picker-common'; -import { SDK_VERSION } from '../../utils'; +import { SDK_VERSION } from '../../utils/constants'; export * from './time-picker-common'; diff --git a/packages/core/utils/common.ts b/packages/core/utils/common.ts index aa8a843ec..a4cbc1028 100644 --- a/packages/core/utils/common.ts +++ b/packages/core/utils/common.ts @@ -74,6 +74,20 @@ export function isDataURI(uri: string): boolean { return firstSegment && firstSegment.indexOf('data:') === 0 && firstSegment.indexOf('base64') >= 0; } +/** + * Get file extension from file path + * @param path file path + * @returns file extension + */ +export function getFileExtension(path: string): string { + const dotIndex = path.lastIndexOf('.'); + if (dotIndex && dotIndex >= 0 && dotIndex < path.length) { + return path.substring(dotIndex); + } + + return ''; +} + export function mergeSort(arr, compareFunc) { if (arr.length < 2) { return arr; diff --git a/packages/core/utils/constants.android.ts b/packages/core/utils/constants.android.ts new file mode 100644 index 000000000..27e4c1a29 --- /dev/null +++ b/packages/core/utils/constants.android.ts @@ -0,0 +1 @@ +export const SDK_VERSION = android.os.Build.VERSION.SDK_INT; diff --git a/packages/core/utils/constants.d.ts b/packages/core/utils/constants.d.ts new file mode 100644 index 000000000..663c7249e --- /dev/null +++ b/packages/core/utils/constants.d.ts @@ -0,0 +1 @@ +export const SDK_VERSION: number; diff --git a/packages/core/utils/constants.ios.ts b/packages/core/utils/constants.ios.ts new file mode 100644 index 000000000..16a67a4b3 --- /dev/null +++ b/packages/core/utils/constants.ios.ts @@ -0,0 +1 @@ +export const SDK_VERSION = parseFloat(UIDevice.currentDevice.systemVersion); diff --git a/packages/core/utils/debug.ts b/packages/core/utils/debug.ts index f9cbe4d89..8b0819e21 100644 --- a/packages/core/utils/debug.ts +++ b/packages/core/utils/debug.ts @@ -6,7 +6,7 @@ let applicationRootPath: string; function ensureAppRootPath() { if (!applicationRootPath) { applicationRootPath = knownFolders.currentApp().path; - applicationRootPath = applicationRootPath.substr(0, applicationRootPath.length - 'app/'.length); + applicationRootPath = applicationRootPath.substring(0, applicationRootPath.length - 'app/'.length); } } @@ -20,8 +20,8 @@ export class Source { constructor(uri: string, line: number, column: number) { ensureAppRootPath(); - if (uri.length > applicationRootPath.length && uri.substr(0, applicationRootPath.length) === applicationRootPath) { - this._uri = 'file://' + uri.substr(applicationRootPath.length); + if (uri.length > applicationRootPath.length && uri.substring(0, applicationRootPath.length) === applicationRootPath) { + this._uri = 'file://' + uri.substring(applicationRootPath.length); } else { this._uri = uri; } diff --git a/packages/core/utils/index.android.ts b/packages/core/utils/index.android.ts index cc0714bdd..a34815a87 100644 --- a/packages/core/utils/index.android.ts +++ b/packages/core/utils/index.android.ts @@ -1,14 +1,13 @@ import { ad } from './native-helper'; -import { FileSystemAccess } from '../file-system/file-system-access'; import { Trace } from '../trace'; +import { getFileExtension } from './common'; +import { SDK_VERSION } from './constants'; export { ad, dataDeserialize, dataSerialize, iOSNativeHelper } from './native-helper'; export * from './layout-helper'; export * from './common'; export { Source } from './debug'; -export const SDK_VERSION = android.os.Build.VERSION.SDK_INT; - const MIN_URI_SHARE_RESTRICTED_APK_VERSION = 24; export function GC() { @@ -72,7 +71,7 @@ function isExternalStorageAvailable(): boolean { */ function getMimeTypeNameFromExtension(filePath: string): string { const mimeTypeMap = android.webkit.MimeTypeMap.getSingleton(); - const extension = new FileSystemAccess().getFileExtension(filePath).replace('.', '').toLowerCase(); + const extension = getFileExtension(filePath).replace('.', '').toLowerCase(); return mimeTypeMap.getMimeTypeFromExtension(extension); } diff --git a/packages/core/utils/index.d.ts b/packages/core/utils/index.d.ts index 04f8356c0..66611894c 100644 --- a/packages/core/utils/index.d.ts +++ b/packages/core/utils/index.d.ts @@ -11,8 +11,6 @@ export * from './common'; export const RESOURCE_PREFIX: string; export const FILE_PREFIX: string; -export const SDK_VERSION: number; - //@private /** * Used by various android event listener implementations. @@ -177,6 +175,13 @@ export function isFontIconURI(uri: string): boolean; */ export function isFileOrResourcePath(path: string): boolean; +/** + * Get file extension from file path + * @param path file path + * @returns file extension + */ +export function getFileExtension(path: string): string; + /** * Returns true if the specified URI is data URI (http://en.wikipedia.org/wiki/Data_URI_scheme). * @param uri The URI. diff --git a/packages/core/utils/index.ios.ts b/packages/core/utils/index.ios.ts index 9fb2a07b7..815218894 100644 --- a/packages/core/utils/index.ios.ts +++ b/packages/core/utils/index.ios.ts @@ -6,8 +6,6 @@ export * from './layout-helper'; export * from './common'; export { Source } from './debug'; -export const SDK_VERSION = parseFloat(UIDevice.currentDevice.systemVersion); - export function openFile(filePath: string): boolean { try { const appPath = iOSNativeHelper.getCurrentAppPath();