@nativescript/core
Version:
A JavaScript library providing an easy to use api for interacting with iOS and Android platform APIs.
496 lines • 20.7 kB
JavaScript
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 { ad } from '../../utils';
import { SDK_VERSION } from '../../utils/constants';
import * as timer from '../../timer';
export * from './editable-text-base-common';
//https://github.com/NativeScript/NativeScript/issues/2942
export let dismissKeyboardTimeoutId;
let EditTextListeners;
function clearDismissTimer() {
if (dismissKeyboardTimeoutId) {
clearTimeout(dismissKeyboardTimeoutId);
dismissKeyboardTimeoutId = null;
}
}
function dismissSoftInput(view) {
clearDismissTimer();
if (!dismissKeyboardTimeoutId) {
dismissKeyboardTimeoutId = timer.setTimeout(() => {
const activity = view._context;
dismissKeyboardTimeoutId = null;
const focused = activity && activity.getCurrentFocus();
if (focused && !(focused instanceof android.widget.EditText)) {
// warning `ad.dismissSoftInput` will actually focus the next view
// if we pass a null parameter!!!
// => focus and show keyboard again
// the fix was for where there were multiple TextField for which it would work!
// with this it will still work without breaking for single TextField
ad.dismissSoftInput(focused);
}
}, 10);
}
}
function initializeEditTextListeners() {
if (EditTextListeners) {
return;
}
var EditTextListenersImpl = /** @class */ (function (_super) {
__extends(EditTextListenersImpl, _super);
function EditTextListenersImpl(owner) {
var _this = _super.call(this) || this;
_this.owner = owner;
return global.__native(_this);
}
EditTextListenersImpl.prototype.beforeTextChanged = function (text, start, count, after) {
var _a, _b;
(_b = (_a = this.owner) === null || _a === void 0 ? void 0 : _a.get()) === null || _b === void 0 ? void 0 : _b.beforeTextChanged(text, start, count, after);
};
EditTextListenersImpl.prototype.onTextChanged = function (text, start, before, count) {
var _a, _b;
(_b = (_a = this.owner) === null || _a === void 0 ? void 0 : _a.get()) === null || _b === void 0 ? void 0 : _b.onTextChanged(text, start, before, count);
};
EditTextListenersImpl.prototype.afterTextChanged = function (editable) {
var _a, _b;
(_b = (_a = this.owner) === null || _a === void 0 ? void 0 : _a.get()) === null || _b === void 0 ? void 0 : _b.afterTextChanged(editable);
};
EditTextListenersImpl.prototype.onFocusChange = function (view, hasFocus) {
var _a, _b;
(_b = (_a = this.owner) === null || _a === void 0 ? void 0 : _a.get()) === null || _b === void 0 ? void 0 : _b.onFocusChange(view, hasFocus);
};
EditTextListenersImpl.prototype.onEditorAction = function (textView, actionId, event) {
var _a, _b;
return ((_b = (_a = this.owner) === null || _a === void 0 ? void 0 : _a.get()) === null || _b === void 0 ? void 0 : _b.onEditorAction(textView, actionId, event)) || false;
};
var _a;
EditTextListenersImpl = __decorate([
Interfaces([android.text.TextWatcher, android.view.View.OnFocusChangeListener, android.widget.TextView.OnEditorActionListener]),
__metadata("design:paramtypes", [typeof (_a = typeof WeakRef !== "undefined" && WeakRef) === "function" ? _a : Object])
], EditTextListenersImpl);
return EditTextListenersImpl;
}(java.lang.Object));
EditTextListeners = EditTextListenersImpl;
}
export class EditableTextBase extends EditableTextBaseCommon {
_onReturnPress() {
//
}
createNativeView() {
return new android.widget.EditText(this._context);
}
initNativeView() {
super.initNativeView();
const editText = this.nativeTextViewProtected;
this._configureEditText(editText);
initializeEditTextListeners();
const listeners = new EditTextListeners(new WeakRef(this));
editText.addTextChangedListener(listeners);
editText.setOnFocusChangeListener(listeners);
editText.setOnEditorActionListener(listeners);
editText.listener = listeners;
this._inputType = editText.getInputType();
}
disposeNativeView() {
const editText = this.nativeTextViewProtected;
editText.removeTextChangedListener(editText.listener);
editText.setOnFocusChangeListener(null);
editText.setOnEditorActionListener(null);
editText.listener.owner = null;
editText.listener = null;
this._keyListenerCache = null;
this._dirtyTextAccumulator = undefined;
this._inputType = 0;
super.disposeNativeView();
}
resetNativeView() {
super.resetNativeView();
this.nativeTextViewProtected.setInputType(this._inputType);
}
onUnloaded() {
this.dismissSoftInput();
super.onUnloaded();
}
dismissSoftInput() {
const nativeView = this.nativeTextViewProtected;
if (!nativeView) {
return;
}
ad.dismissSoftInput(nativeView);
}
focus() {
const nativeView = this.nativeTextViewProtected;
if (!nativeView) {
return;
}
const result = super.focus();
if (result) {
ad.showSoftInput(this.nativeTextViewProtected);
}
return result;
}
_setInputType(inputType) {
const nativeView = this.nativeTextViewProtected;
try {
this._changeFromCode = true;
nativeView.setInputType(parseInt(inputType, 10));
}
finally {
this._changeFromCode = false;
}
// setInputType will change the keyListener so we should cache it again
const listener = nativeView.getKeyListener();
if (listener) {
this._keyListenerCache = listener;
}
// clear these fields instead of clearing listener.
// this allows input Type to be changed even after editable is false.
if (!this.editable) {
nativeView.setFocusable(false);
nativeView.setFocusableInTouchMode(false);
nativeView.setLongClickable(false);
nativeView.setClickable(false);
}
}
[textProperty.getDefault]() {
return resetSymbol;
}
[textProperty.setNative](value) {
try {
this._changeFromCode = true;
this._setNativeText(value === resetSymbol);
}
finally {
this._changeFromCode = false;
}
}
[keyboardTypeProperty.getDefault]() {
return this.nativeTextViewProtected.getInputType();
}
[keyboardTypeProperty.setNative](value) {
let newInputType;
switch (value) {
case 'datetime':
newInputType = android.text.InputType.TYPE_CLASS_DATETIME | android.text.InputType.TYPE_DATETIME_VARIATION_NORMAL;
break;
case 'phone':
newInputType = android.text.InputType.TYPE_CLASS_PHONE;
break;
case 'number':
newInputType = android.text.InputType.TYPE_CLASS_NUMBER | android.text.InputType.TYPE_NUMBER_VARIATION_NORMAL | android.text.InputType.TYPE_NUMBER_FLAG_SIGNED | android.text.InputType.TYPE_NUMBER_FLAG_DECIMAL;
break;
case 'url':
newInputType = android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_VARIATION_URI;
break;
case 'email':
newInputType = android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
break;
case 'integer':
newInputType = android.text.InputType.TYPE_CLASS_NUMBER;
break;
default: {
const inputType = +value;
if (!isNaN(inputType)) {
newInputType = inputType;
}
else {
newInputType = android.text.InputType.TYPE_CLASS_TEXT;
}
break;
}
}
this._setInputType(newInputType);
}
[autofillTypeProperty.setNative](value) {
if (SDK_VERSION < 26) {
return;
}
let newOptions;
switch (value) {
case 'phone':
newOptions = 'phone'; // android.view.View.AUTOFILL_HINT_PHONE
break;
case 'postalCode':
newOptions = 'postalCode'; // android.view.View.AUTOFILL_HINT_POSTAL_CODE
break;
case 'creditCardNumber':
newOptions = 'creditCardNumber'; // android.view.View.AUTOFILL_HINT_CREDIT_CARD_NUMBER
break;
case 'email':
newOptions = 'emailAddress'; // android.view.View.AUTOFILL_HINT_EMAIL_ADDRESS
break;
case 'name':
newOptions = 'name'; // android.view.View.AUTOFILL_HINT_NAME
break;
case 'username':
newOptions = 'username'; // android.view.View.AUTOFILL_HINT_USERNAME
break;
case 'password':
newOptions = 'password'; // android.view.View.AUTOFILL_HINT_PASSWORD
break;
case 'newPassword':
newOptions = 'newPassword'; // android.view.View.AUTOFILL_HINT_NEW_PASSWORD
break;
case 'newUsername':
newOptions = 'newUsername'; // android.view.View.AUTOFILL_HINT_NEW_USERNAME
break;
case 'oneTimeCode':
newOptions = '2faAppOTPCode'; // android.view.View.AUTOFILL_HINT_2FA_APP_OTP
break;
case 'none':
newOptions = null;
break;
default: {
newOptions = value;
break;
}
}
if (newOptions) {
const array = Array.create(java.lang.String, 1);
array[0] = newOptions;
this.nativeTextViewProtected.setAutofillHints(array);
}
else {
this.nativeTextViewProtected.setAutofillHints(null);
}
}
[returnKeyTypeProperty.getDefault]() {
const ime = this.nativeTextViewProtected.getImeOptions();
switch (ime) {
case android.view.inputmethod.EditorInfo.IME_ACTION_DONE:
return 'done';
case android.view.inputmethod.EditorInfo.IME_ACTION_GO:
return 'go';
case android.view.inputmethod.EditorInfo.IME_ACTION_NEXT:
return 'next';
case android.view.inputmethod.EditorInfo.IME_ACTION_SEARCH:
return 'search';
case android.view.inputmethod.EditorInfo.IME_ACTION_SEND:
return 'send';
default:
return ime.toString();
}
}
[returnKeyTypeProperty.setNative](value) {
let newImeOptions;
switch (value) {
case 'done':
newImeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
break;
case 'go':
newImeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO;
break;
case 'next':
newImeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_NEXT;
break;
case 'search':
newImeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEARCH;
break;
case 'send':
newImeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEND;
break;
default: {
const ime = +value;
if (!isNaN(ime)) {
newImeOptions = ime;
}
else {
newImeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_UNSPECIFIED;
}
break;
}
}
this.nativeTextViewProtected.setImeOptions(newImeOptions);
}
[editableProperty.setNative](value) {
const nativeView = this.nativeTextViewProtected;
if (value) {
nativeView.setKeyListener(this._keyListenerCache);
}
else {
if (!this._keyListenerCache) {
this._keyListenerCache = nativeView.getKeyListener();
}
nativeView.setKeyListener(null);
}
}
[autocapitalizationTypeProperty.getDefault]() {
const inputType = this.nativeTextViewProtected.getInputType();
if ((inputType & android.text.InputType.TYPE_TEXT_FLAG_CAP_WORDS) === android.text.InputType.TYPE_TEXT_FLAG_CAP_WORDS) {
return 'words';
}
else if ((inputType & android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES) === android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES) {
return 'sentences';
}
else if ((inputType & android.text.InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) === android.text.InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) {
return 'allcharacters';
}
else {
return inputType.toString();
}
}
[autocapitalizationTypeProperty.setNative](value) {
let inputType = this.nativeTextViewProtected.getInputType();
inputType = inputType & ~28672; //28672 (0x00070000) 13,14,15bits (111 0000 0000 0000)
switch (value) {
case 'none':
//Do nothing, we have lowered the three bits above.
break;
case 'words':
inputType = inputType | android.text.InputType.TYPE_TEXT_FLAG_CAP_WORDS; //8192 (0x00020000) 14th bit
break;
case 'sentences':
inputType = inputType | android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES; //16384(0x00040000) 15th bit
break;
case 'allcharacters':
inputType = inputType | android.text.InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS; //4096 (0x00010000) 13th bit
break;
default: {
const number = +value;
// We set the default value.
if (!isNaN(number)) {
inputType = number;
}
else {
inputType = inputType | android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
}
break;
}
}
this._setInputType(inputType);
}
[autocorrectProperty.getDefault]() {
const autocorrect = this.nativeTextViewProtected.getInputType();
if ((autocorrect & android.text.InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) === android.text.InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) {
return true;
}
return false;
}
[autocorrectProperty.setNative](value) {
let inputType = this.nativeTextViewProtected.getInputType();
switch (value) {
case true:
inputType = inputType | android.text.InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE;
inputType = inputType | android.text.InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
inputType = inputType & ~android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
break;
case false:
inputType = inputType & ~android.text.InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE;
inputType = inputType & ~android.text.InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
inputType = inputType | android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
break;
default:
// We can't do anything.
break;
}
this._setInputType(inputType);
}
[hintProperty.getDefault]() {
return this.nativeTextViewProtected.getHint();
}
[hintProperty.setNative](value) {
const text = value === null || value === undefined ? null : value.toString();
this.nativeTextViewProtected.setHint(text);
}
[placeholderColorProperty.getDefault]() {
return this.nativeTextViewProtected.getHintTextColors();
}
[placeholderColorProperty.setNative](value) {
const color = value instanceof Color ? value.android : value;
this.nativeTextViewProtected.setHintTextColor(color);
}
[textTransformProperty.setNative](value) {
//
}
[maxLengthProperty.setNative](value) {
if (value === Number.POSITIVE_INFINITY) {
this.nativeTextViewProtected.setFilters([]);
}
else {
const lengthFilter = new android.text.InputFilter.LengthFilter(value);
const filters = this.nativeTextViewProtected.getFilters();
const newFilters = [];
// retain existing filters
for (let i = 0; i < filters.length; i++) {
const filter = filters[i];
if (!(filter instanceof android.text.InputFilter.LengthFilter)) {
newFilters.push(filter);
}
}
newFilters.push(lengthFilter);
this.nativeTextViewProtected.setFilters(newFilters);
}
}
setSelection(start, stop) {
const view = this.nativeTextViewProtected;
if (view) {
if (stop !== undefined) {
view.setSelection(start, stop);
}
else {
view.setSelection(start);
}
}
}
beforeTextChanged(text, start, count, after) {
// called by android.text.TextWatcher
}
onTextChanged(text, start, before, count) {
// called by android.text.TextWatcher
if (this.valueFormatter) {
this.text = this.valueFormatter(text.toString());
this.android.setSelection((this.text || '').length);
}
// const owner = this.owner;
// let selectionStart = owner.android.getSelectionStart();
// owner.android.removeTextChangedListener(owner._editTextListeners);
// owner.android.addTextChangedListener(owner._editTextListeners);
// owner.android.setSelection(selectionStart);
}
afterTextChanged(editable) {
// called by android.text.TextWatcher
if (this._changeFromCode) {
return;
}
switch (this.updateTextTrigger) {
case 'focusLost':
this._dirtyTextAccumulator = editable.toString();
break;
case 'textChanged':
textProperty.nativeValueChange(this, editable.toString());
break;
default:
throw new Error('Invalid updateTextTrigger: ' + this.updateTextTrigger);
}
}
onFocusChange(view, hasFocus) {
if (hasFocus) {
clearDismissTimer();
this.notify({ eventName: EditableTextBase.focusEvent });
}
else {
if (this._dirtyTextAccumulator || this._dirtyTextAccumulator === '') {
textProperty.nativeValueChange(this, this._dirtyTextAccumulator);
this._dirtyTextAccumulator = undefined;
}
this.notify({ eventName: EditableTextBase.blurEvent });
dismissSoftInput(this);
}
}
onEditorAction(textView, actionId, event) {
if (actionId === android.view.inputmethod.EditorInfo.IME_ACTION_DONE || actionId === android.view.inputmethod.EditorInfo.IME_ACTION_UNSPECIFIED || (event && event.getKeyCode() === android.view.KeyEvent.KEYCODE_ENTER)) {
// If it is TextField, close the keyboard. If it is TextView, do not close it since the TextView is multiline
// https://github.com/NativeScript/NativeScript/issues/3111
if (textView.getMaxLines() === 1) {
this.dismissSoftInput();
}
this._onReturnPress();
}
else if (actionId === android.view.inputmethod.EditorInfo.IME_ACTION_NEXT || actionId === android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS) {
// do not close keyboard for ACTION_NEXT or ACTION_PREVIOUS
this._onReturnPress();
}
return false;
}
}
//# sourceMappingURL=index.android.js.map