mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
fix(ios): TextField keyboard handling with emoji, autofill, and shortcuts (#10154)
closes https://github.com/NativeScript/NativeScript/issues/10108
This commit is contained in:
3
packages/core/index.d.ts
vendored
3
packages/core/index.d.ts
vendored
@@ -105,7 +105,7 @@ 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, getFileExtension } 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, isEmoji } 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: {
|
||||
@@ -163,5 +163,6 @@ export declare const Utils: {
|
||||
dismissSoftInput: typeof dismissSoftInput;
|
||||
dismissKeyboard: typeof dismissKeyboard;
|
||||
copyToClipboard: typeof copyToClipboard;
|
||||
isEmoji: typeof isEmoji;
|
||||
};
|
||||
export { XmlParser, ParserEventType, ParserEvent } from './xml';
|
||||
|
||||
@@ -137,7 +137,7 @@ 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, getFileExtension } 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, isEmoji } 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';
|
||||
|
||||
@@ -199,6 +199,7 @@ export const Utils = {
|
||||
dismissSoftInput,
|
||||
dismissKeyboard,
|
||||
copyToClipboard,
|
||||
isEmoji,
|
||||
};
|
||||
|
||||
export { XmlParser, ParserEventType, ParserEvent } from './xml';
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"@nativescript/hook": "~2.0.0",
|
||||
"acorn": "^8.7.0",
|
||||
"css-tree": "^1.1.2",
|
||||
"emoji-regex": "^10.2.1",
|
||||
"reduce-css-calc": "^2.1.7",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ import { hintProperty, placeholderColorProperty, _updateCharactersInRangeReplace
|
||||
import { CoreTypes } from '../../core-types';
|
||||
import { Color } from '../../color';
|
||||
import { colorProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty } from '../styling/style-properties';
|
||||
import { layout } from '../../utils';
|
||||
import { layout, isEmoji } from '../../utils';
|
||||
import { profile } from '../../profiling';
|
||||
|
||||
export * from './text-field-common';
|
||||
@@ -200,7 +200,10 @@ export class TextField extends TextFieldBase {
|
||||
}
|
||||
|
||||
if (this.updateTextTrigger === 'textChanged') {
|
||||
const shouldReplaceString = (textField.secureTextEntry && this.firstEdit) || delta > 1;
|
||||
// 1. secureTextEntry with firstEdit should not replace
|
||||
// 2. emoji's should not replace value
|
||||
// 3. convenient keyboard shortcuts should not replace value (eg, '.com')
|
||||
const shouldReplaceString = (textField.secureTextEntry && this.firstEdit) || (delta > 1 && !isEmoji(replacementString) && delta !== replacementString.length);
|
||||
if (shouldReplaceString) {
|
||||
textProperty.nativeValueChange(this, replacementString);
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as types from './types';
|
||||
import { dispatchToMainThread, dispatchToUIThread, isMainThread } from './mainthread-helper';
|
||||
import { sanitizeModuleName } from '../ui/builder/module-name-sanitizer';
|
||||
import emojiRegex from 'emoji-regex';
|
||||
|
||||
import { GC } from './index';
|
||||
|
||||
@@ -203,3 +204,9 @@ export function queueGC(delay = 900, useThrottle?: boolean) {
|
||||
debouncedGC.get(delay)();
|
||||
}
|
||||
}
|
||||
|
||||
export function isEmoji(value: string): boolean {
|
||||
// TODO: In a future runtime update, we can switch to using Unicode Property Escapes:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Unicode_Property_Escapes
|
||||
return emojiRegex().test(value);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user