forked from Ivasoft/mattermost-mobile
[MM-46562] Add show/hide password function for login screen (#6612)
This commit is contained in:
@@ -5,12 +5,14 @@
|
||||
|
||||
import {debounce} from 'lodash';
|
||||
import React, {useState, useEffect, useRef, useImperativeHandle, forwardRef, useMemo, useCallback} from 'react';
|
||||
import {GestureResponderEvent, LayoutChangeEvent, NativeSyntheticEvent, Platform, StyleProp, TargetedEvent, Text, TextInput, TextInputFocusEventData, TextInputProps, TextStyle, TouchableWithoutFeedback, View, ViewStyle} from 'react-native';
|
||||
import {GestureResponderEvent, LayoutChangeEvent, NativeSyntheticEvent, StyleProp, TargetedEvent, Text, TextInput, TextInputFocusEventData, TextInputProps, TextStyle, TouchableWithoutFeedback, View, ViewStyle} from 'react-native';
|
||||
import Animated, {useAnimatedStyle, withTiming, Easing} from 'react-native-reanimated';
|
||||
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
||||
import {getLabelPositions, onExecution} from './utils';
|
||||
|
||||
const DEFAULT_INPUT_HEIGHT = 48;
|
||||
const BORDER_DEFAULT_WIDTH = 1;
|
||||
const BORDER_FOCUSED_WIDTH = 2;
|
||||
@@ -36,6 +38,9 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
lineHeight: 16,
|
||||
paddingVertical: 5,
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
},
|
||||
label: {
|
||||
position: 'absolute',
|
||||
color: changeOpacity(theme.centerChannelColor, 0.64),
|
||||
@@ -52,6 +57,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
fontSize: 10,
|
||||
},
|
||||
textInput: {
|
||||
flexDirection: 'row',
|
||||
fontFamily: 'OpenSans',
|
||||
fontSize: 16,
|
||||
paddingTop: 12,
|
||||
@@ -65,29 +71,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const onExecution = (
|
||||
e: NativeSyntheticEvent<TextInputFocusEventData>,
|
||||
innerFunc?: () => void,
|
||||
outerFunc?: ((event: NativeSyntheticEvent<TargetedEvent>) => void),
|
||||
) => {
|
||||
innerFunc?.();
|
||||
outerFunc?.(e);
|
||||
};
|
||||
|
||||
const getLabelPositions = (style: TextStyle, labelStyle: TextStyle, smallLabelStyle: TextStyle) => {
|
||||
const top: number = style.paddingTop as number || 0;
|
||||
const bottom: number = style.paddingBottom as number || 0;
|
||||
|
||||
const height: number = (style.height as number || (top + bottom) || style.padding as number) || 0;
|
||||
const textInputFontSize = style.fontSize || 13;
|
||||
const labelFontSize = labelStyle.fontSize || 16;
|
||||
const smallLabelFontSize = smallLabelStyle.fontSize || 10;
|
||||
const fontSizeDiff = textInputFontSize - labelFontSize;
|
||||
const unfocused = (height * 0.5) + (fontSizeDiff * (Platform.OS === 'android' ? 0.5 : 0.6));
|
||||
const focused = -(labelFontSize + smallLabelFontSize) * 0.25;
|
||||
return [unfocused, focused];
|
||||
};
|
||||
|
||||
export type FloatingTextInputRef = {
|
||||
blur: () => void;
|
||||
focus: () => void;
|
||||
@@ -97,6 +80,7 @@ export type FloatingTextInputRef = {
|
||||
type FloatingTextInputProps = TextInputProps & {
|
||||
containerStyle?: ViewStyle;
|
||||
editable?: boolean;
|
||||
endAdornment?: React.ReactNode;
|
||||
error?: string;
|
||||
errorIcon?: string;
|
||||
isKeyboardInput?: boolean;
|
||||
@@ -120,6 +104,7 @@ const FloatingTextInput = forwardRef<FloatingTextInputRef, FloatingTextInputProp
|
||||
editable = true,
|
||||
error,
|
||||
errorIcon = 'alert-outline',
|
||||
endAdornment,
|
||||
isKeyboardInput = true,
|
||||
label = '',
|
||||
labelTextStyle,
|
||||
@@ -192,7 +177,7 @@ const FloatingTextInput = forwardRef<FloatingTextInputRef, FloatingTextInputProp
|
||||
return res;
|
||||
}, [styles, containerStyle, multiline]);
|
||||
|
||||
const combinedTextInputStyle = useMemo(() => {
|
||||
const combinedTextInputContainerStyle = useMemo(() => {
|
||||
const res: StyleProp<TextStyle> = [styles.textInput];
|
||||
if (!editable) {
|
||||
res.push(styles.readOnly);
|
||||
@@ -253,21 +238,24 @@ const FloatingTextInput = forwardRef<FloatingTextInputRef, FloatingTextInputProp
|
||||
>
|
||||
{label}
|
||||
</Animated.Text>
|
||||
<TextInput
|
||||
{...props}
|
||||
editable={isKeyboardInput && editable}
|
||||
style={combinedTextInputStyle}
|
||||
placeholder={placeholder}
|
||||
placeholderTextColor={styles.label.color}
|
||||
multiline={multiline}
|
||||
value={value}
|
||||
pointerEvents={isKeyboardInput ? 'auto' : 'none'}
|
||||
onFocus={onTextInputFocus}
|
||||
onBlur={onTextInputBlur}
|
||||
ref={inputRef}
|
||||
underlineColorAndroid='transparent'
|
||||
testID={testID}
|
||||
/>
|
||||
<View style={combinedTextInputContainerStyle}>
|
||||
<TextInput
|
||||
{...props}
|
||||
editable={isKeyboardInput && editable}
|
||||
style={styles.input}
|
||||
placeholder={placeholder}
|
||||
placeholderTextColor={styles.label.color}
|
||||
multiline={multiline}
|
||||
value={value}
|
||||
pointerEvents={isKeyboardInput ? 'auto' : 'none'}
|
||||
onFocus={onTextInputFocus}
|
||||
onBlur={onTextInputBlur}
|
||||
ref={inputRef}
|
||||
underlineColorAndroid='transparent'
|
||||
testID={testID}
|
||||
/>
|
||||
{endAdornment}
|
||||
</View>
|
||||
{Boolean(error) && (
|
||||
<View style={styles.errorContainer}>
|
||||
{showErrorIcon && errorIcon &&
|
||||
|
||||
28
app/components/floating_text_input_label/utils.ts
Normal file
28
app/components/floating_text_input_label/utils.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {NativeSyntheticEvent, Platform, TargetedEvent, TextInputFocusEventData, TextStyle} from 'react-native';
|
||||
|
||||
export const onExecution = (
|
||||
e: NativeSyntheticEvent<TextInputFocusEventData>,
|
||||
innerFunc?: () => void,
|
||||
outerFunc?: ((event: NativeSyntheticEvent<TargetedEvent>) => void),
|
||||
) => {
|
||||
innerFunc?.();
|
||||
outerFunc?.(e);
|
||||
};
|
||||
|
||||
export const getLabelPositions = (style: TextStyle, labelStyle: TextStyle, smallLabelStyle: TextStyle) => {
|
||||
const top: number = style.paddingTop as number || 0;
|
||||
const bottom: number = style.paddingBottom as number || 0;
|
||||
|
||||
const height: number = (style.height as number || (top + bottom) || style.padding as number) || 0;
|
||||
const textInputFontSize = style.fontSize || 13;
|
||||
const labelFontSize = labelStyle.fontSize || 16;
|
||||
const smallLabelFontSize = smallLabelStyle.fontSize || 10;
|
||||
const fontSizeDiff = textInputFontSize - labelFontSize;
|
||||
const unfocused = (height * 0.5) + (fontSizeDiff * (Platform.OS === 'android' ? 0.5 : 0.6));
|
||||
const focused = -(labelFontSize + smallLabelFontSize) * 0.25;
|
||||
return [unfocused, focused];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user