mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-11-29 11:12:18 +03:00
Merge pull request #2794 from ecency/sa/login-screen-update
[Improve] Login Screen UI Update
This commit is contained in:
commit
11585d50fb
50
src/assets/svgs/hive-signer-icon.tsx
Normal file
50
src/assets/svgs/hive-signer-icon.tsx
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { SvgXml } from 'react-native-svg';
|
||||||
|
|
||||||
|
const xml = `
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
id="svg639"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 110 131"
|
||||||
|
height="131px"
|
||||||
|
width="110px">
|
||||||
|
<metadata
|
||||||
|
id="metadata645">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title>steemconnect</dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs643" />
|
||||||
|
<title
|
||||||
|
id="title631">hivesigner</title>
|
||||||
|
<g
|
||||||
|
id="g637"
|
||||||
|
fillRule="evenodd"
|
||||||
|
fill="none"
|
||||||
|
strokeWidth="1"
|
||||||
|
stroke="none">
|
||||||
|
<g
|
||||||
|
style="fill:#e31337;fill-opacity:1"
|
||||||
|
id="g635"
|
||||||
|
fill="#FFFFFF">
|
||||||
|
<path
|
||||||
|
style="fill:#e31337;fill-opacity:1"
|
||||||
|
id="path633"
|
||||||
|
d="M98.5416667,69.9233063 L98.5416667,45.8870172 L0,45.8870172 L0,0 L110,0 L110,22.9435086 L98.5416667,22.9435086 L98.5416667,11.4717543 L11.4583333,11.4717543 L11.4583333,34.4152629 L110,34.4152629 L110,71.7557407 C109.814829,89.9952801 99.6177682,104.956632 82.7527664,116.860728 C76.7961987,121.065148 70.4063912,124.587232 64.0012261,127.457262 C61.7434474,128.468929 59.6383537,129.328634 57.7397369,130.039339 C56.5694641,130.477405 55.6341636,130.79975 55.217168,130.930175 L54.9939202,131 L54.770964,130.929247 C54.3038614,130.781016 53.4195598,130.475943 52.2525224,130.038871 C50.3537481,129.327755 48.2495815,128.46815 45.9926252,127.45661 C39.5881896,124.586219 33.1997658,121.06434 27.2442254,116.860148 C10.5407495,105.06867 0.379911508,90.2779437 0.0104347976,72.2720521 L0,72.2720521 L0,57.3587715 L11.4583333,57.3587715 L11.4583333,69.9233063 C11.4583333,83.7531618 18.6794796,95.3214487 31.0665488,104.779305 C35.6407321,108.271816 40.6776939,111.281674 45.8998806,113.824407 C49.3619815,115.510138 52.4791717,116.790221 55.00154,117.681377 C57.521117,116.791558 60.639999,115.510854 64.1022301,113.825035 C69.3240535,111.28244 74.3609709,108.272494 78.9351124,104.77987 C91.3219921,95.3217663 98.5416667,83.7531543 98.5416667,69.9233063 Z" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
|
export default () => <SvgXml xml={xml} width={20} height={20} />;
|
1
src/assets/svgs/index.ts
Normal file
1
src/assets/svgs/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as HiveSignerIcon } from './hive-signer-icon';
|
@ -201,7 +201,7 @@ const FormInputView = ({
|
|||||||
) : value && value.length > 0 ? (
|
) : value && value.length > 0 ? (
|
||||||
<Icon
|
<Icon
|
||||||
iconType={iconType || 'MaterialIcons'}
|
iconType={iconType || 'MaterialIcons'}
|
||||||
onPress={() => setValue('')}
|
onPress={() => _handleOnChange('')}
|
||||||
name={leftIconName}
|
name={leftIconName}
|
||||||
style={styles.icon}
|
style={styles.icon}
|
||||||
/>
|
/>
|
||||||
|
@ -103,6 +103,7 @@ import TransferAccountSelector from './transferAccountSelector/transferAccountSe
|
|||||||
import TransferAmountInputSection from './transferAmountInputSection/transferAmountInputSection';
|
import TransferAmountInputSection from './transferAmountInputSection/transferAmountInputSection';
|
||||||
import TextBoxWithCopy from './textBoxWithCopy/textBoxWithCopy';
|
import TextBoxWithCopy from './textBoxWithCopy/textBoxWithCopy';
|
||||||
import WebViewModal from './webViewModal/webViewModal';
|
import WebViewModal from './webViewModal/webViewModal';
|
||||||
|
import OrDivider from './orDivider/orDividerView';
|
||||||
|
|
||||||
// Basic UI Elements
|
// Basic UI Elements
|
||||||
import {
|
import {
|
||||||
@ -253,4 +254,5 @@ export {
|
|||||||
TransferAmountInputSection,
|
TransferAmountInputSection,
|
||||||
TextBoxWithCopy,
|
TextBoxWithCopy,
|
||||||
WebViewModal,
|
WebViewModal,
|
||||||
|
OrDivider,
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,6 @@ export default EStyleSheet.create({
|
|||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
height: '$deviceHeight / 3',
|
|
||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
},
|
},
|
||||||
safeArea: {
|
safeArea: {
|
||||||
@ -15,7 +14,7 @@ export default EStyleSheet.create({
|
|||||||
maxHeight: '$deviceHeight / 3',
|
maxHeight: '$deviceHeight / 3',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
height: '$deviceHeight / 3.9',
|
height: 120,
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
@ -37,12 +36,10 @@ export default EStyleSheet.create({
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
mascot: {
|
mascot: {
|
||||||
width: '70%',
|
width: '60%',
|
||||||
height: '70%',
|
|
||||||
},
|
},
|
||||||
titleText: {
|
titleText: {
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
marginTop: 20,
|
|
||||||
marginLeft: 32,
|
marginLeft: 32,
|
||||||
marginRight: 12,
|
marginRight: 12,
|
||||||
flex: 1,
|
flex: 1,
|
||||||
@ -54,9 +51,15 @@ export default EStyleSheet.create({
|
|||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
paddingVertical: 8,
|
paddingVertical: 8,
|
||||||
},
|
},
|
||||||
|
backIconContainer: {
|
||||||
|
marginLeft: 20,
|
||||||
|
},
|
||||||
|
backIcon: {
|
||||||
|
fontSize: 24,
|
||||||
|
color: '$iconColor',
|
||||||
|
},
|
||||||
logoContainer: {
|
logoContainer: {
|
||||||
paddingLeft: 32,
|
paddingRight: 32,
|
||||||
paddingRight: 8,
|
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
|
@ -4,11 +4,11 @@ import * as Animatable from 'react-native-animatable';
|
|||||||
// Constants
|
// Constants
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import { TextButton } from '../../buttons';
|
|
||||||
import { LineBreak } from '../../basicUIElements';
|
import { LineBreak } from '../../basicUIElements';
|
||||||
// Styles
|
// Styles
|
||||||
import styles from './loginHeaderStyles';
|
import styles from './loginHeaderStyles';
|
||||||
import getWindowDimensions from '../../../utils/getWindowDimensions';
|
import getWindowDimensions from '../../../utils/getWindowDimensions';
|
||||||
|
import { IconButton } from '../..';
|
||||||
|
|
||||||
class LoginHeaderView extends PureComponent {
|
class LoginHeaderView extends PureComponent {
|
||||||
/* Props
|
/* Props
|
||||||
@ -27,24 +27,18 @@ class LoginHeaderView extends PureComponent {
|
|||||||
// Component Functions
|
// Component Functions
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { description, isKeyboardOpen, onPress, rightButtonText, title } = this.props;
|
const { description, isKeyboardOpen, title, onBackPress } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.safeArea}>
|
<SafeAreaView style={styles.safeArea}>
|
||||||
<View styles={styles.container}>
|
<View styles={styles.container}>
|
||||||
<View style={styles.headerRow}>
|
<View style={styles.headerRow}>
|
||||||
<View style={styles.logoContainer}>
|
<View style={styles.backIconContainer}>
|
||||||
<Image
|
<IconButton
|
||||||
resizeMode="contain"
|
iconStyle={styles.backIcon}
|
||||||
style={styles.logo}
|
iconType="MaterialIcons"
|
||||||
source={require('../../../assets/ecency_logo_transparent.png')}
|
name="close"
|
||||||
/>
|
onPress={onBackPress}
|
||||||
</View>
|
|
||||||
<View style={styles.headerButton}>
|
|
||||||
<TextButton
|
|
||||||
onPress={onPress}
|
|
||||||
text={rightButtonText}
|
|
||||||
textStyle={{ color: '#357ce6' }}
|
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
@ -61,7 +55,7 @@ class LoginHeaderView extends PureComponent {
|
|||||||
<Image
|
<Image
|
||||||
resizeMode="contain"
|
resizeMode="contain"
|
||||||
style={styles.mascot}
|
style={styles.mascot}
|
||||||
source={require('../../../assets/love_mascot.png')}
|
source={require('../../../assets/ecency_logo_transparent.png')}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
@ -76,7 +70,7 @@ class LoginHeaderView extends PureComponent {
|
|||||||
export default LoginHeaderView;
|
export default LoginHeaderView;
|
||||||
|
|
||||||
const { height } = getWindowDimensions();
|
const { height } = getWindowDimensions();
|
||||||
const bodyHeight = height / 3.9;
|
const bodyHeight = 120;
|
||||||
const showAnimation = {
|
const showAnimation = {
|
||||||
from: {
|
from: {
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
|
@ -47,24 +47,28 @@ class MainButton extends Component {
|
|||||||
iconType,
|
iconType,
|
||||||
textStyle,
|
textStyle,
|
||||||
iconPosition,
|
iconPosition,
|
||||||
|
iconStyle,
|
||||||
|
renderIcon,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
this._getIndicator();
|
this._getIndicator();
|
||||||
}
|
}
|
||||||
|
|
||||||
const iconComponent = source ? (
|
const iconComponent =
|
||||||
<Image source={source} style={styles.image} resizeMode="contain" />
|
renderIcon ||
|
||||||
) : (
|
(source ? (
|
||||||
iconName && (
|
<Image source={source} style={styles.image} resizeMode="contain" />
|
||||||
<Icon
|
) : (
|
||||||
iconType={iconType || 'MaterialIcons'}
|
iconName && (
|
||||||
color={iconColor}
|
<Icon
|
||||||
name={iconName}
|
iconType={iconType || 'MaterialIcons'}
|
||||||
style={styles.icon}
|
color={iconColor}
|
||||||
/>
|
name={iconName}
|
||||||
)
|
style={[styles.icon, iconStyle]}
|
||||||
);
|
/>
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
if (text) {
|
if (text) {
|
||||||
return (
|
return (
|
||||||
@ -108,7 +112,7 @@ class MainButton extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { wrapperStyle, children, height, style, isLoading } = this.props;
|
const { wrapperStyle, children, height, style, isLoading, bodyWrapperStyle } = this.props;
|
||||||
const { isDisable } = this.state;
|
const { isDisable } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -123,7 +127,7 @@ class MainButton extends Component {
|
|||||||
style && style,
|
style && style,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<View style={styles.body}>
|
<View style={[styles.body, bodyWrapperStyle]}>
|
||||||
{isLoading ? this._getIndicator() : children || this._getBody()}
|
{isLoading ? this._getIndicator() : children || this._getBody()}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
25
src/components/orDivider/orDividerStyles.ts
Normal file
25
src/components/orDivider/orDividerStyles.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
|
|
||||||
|
export default EStyleSheet.create({
|
||||||
|
dividerContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
divider: {
|
||||||
|
borderWidth: 0.5,
|
||||||
|
flex: 1,
|
||||||
|
borderColor: '$primaryDarkGray',
|
||||||
|
},
|
||||||
|
leftDivider: {
|
||||||
|
marginLeft: 20,
|
||||||
|
},
|
||||||
|
rightDivider: {
|
||||||
|
marginRight: 20,
|
||||||
|
},
|
||||||
|
orText: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: '$primaryDarkGray',
|
||||||
|
marginHorizontal: 8,
|
||||||
|
},
|
||||||
|
});
|
24
src/components/orDivider/orDividerView.tsx
Normal file
24
src/components/orDivider/orDividerView.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { View, Text, ViewStyle } from 'react-native';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
|
import styles from './orDividerStyles';
|
||||||
|
|
||||||
|
interface OrDividerProps {
|
||||||
|
containerStyle?: ViewStyle;
|
||||||
|
}
|
||||||
|
const OrDivider = ({ containerStyle }: OrDividerProps) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
return (
|
||||||
|
<View style={[styles.dividerContainer, containerStyle]}>
|
||||||
|
<View style={[styles.divider, styles.leftDivider]} />
|
||||||
|
<Text style={styles.orText}>
|
||||||
|
{intl.formatMessage({
|
||||||
|
id: 'login.or',
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
<View style={[styles.divider, styles.rightDivider]} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OrDivider;
|
@ -377,12 +377,13 @@
|
|||||||
"no_user": "User is not found."
|
"no_user": "User is not found."
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"signin": "Sign in",
|
"signin": "Login",
|
||||||
|
"login_with_hs": "Login with hivesigner",
|
||||||
"signup": "JOIN NOW",
|
"signup": "JOIN NOW",
|
||||||
"signin_title": "To get all the benefits of using Ecency",
|
"signin_title": "To get all the benefits of using Ecency",
|
||||||
"username": "Username",
|
"username": "username",
|
||||||
"password": "Password or WIF",
|
"password": "password / private key",
|
||||||
"description": "By signing in, you agree to our Terms of Services and Privacy Policies.",
|
"description": "By logging in, you agree to our Terms of Services and Privacy Policies.",
|
||||||
"cancel": "cancel",
|
"cancel": "cancel",
|
||||||
"login": "LOGIN",
|
"login": "LOGIN",
|
||||||
"steemconnect_description": "If you don't want to keep your password encrypted and saved on your device, you can use Hivesigner.",
|
"steemconnect_description": "If you don't want to keep your password encrypted and saved on your device, you can use Hivesigner.",
|
||||||
@ -394,7 +395,10 @@
|
|||||||
"deep_login_alert_title": "Easy Login @{username}",
|
"deep_login_alert_title": "Easy Login @{username}",
|
||||||
"deep_login_alert_body":"Verify direct login using access code",
|
"deep_login_alert_body":"Verify direct login using access code",
|
||||||
"deep_login_url_expired":"Login url expired, please use private key or password to login",
|
"deep_login_url_expired":"Login url expired, please use private key or password to login",
|
||||||
"deep_login_malformed_url":"Malformed login url, please use private key or password to login"
|
"deep_login_malformed_url":"Malformed login url, please use private key or password to login",
|
||||||
|
"no_account_text": "Don't have an account?",
|
||||||
|
"signup_now": "Sign up now!",
|
||||||
|
"or": "OR"
|
||||||
},
|
},
|
||||||
"register": {
|
"register": {
|
||||||
"modal_title":"Get Hive Account",
|
"modal_title":"Get Hive Account",
|
||||||
|
@ -55,6 +55,7 @@ import { useUserActivityMutation } from '../../../providers/queries/pointQueries
|
|||||||
import { PointActivityIds } from '../../../providers/ecency/ecency.types';
|
import { PointActivityIds } from '../../../providers/ecency/ecency.types';
|
||||||
import { usePostsCachePrimer } from '../../../providers/queries/postQueries/postQueries';
|
import { usePostsCachePrimer } from '../../../providers/queries/postQueries/postQueries';
|
||||||
import { PostTypes } from '../../../constants/postTypes';
|
import { PostTypes } from '../../../constants/postTypes';
|
||||||
|
|
||||||
import { speakQueries } from '../../../providers/queries';
|
import { speakQueries } from '../../../providers/queries';
|
||||||
import {
|
import {
|
||||||
BENEFICIARY_SRC_ENCODER,
|
BENEFICIARY_SRC_ENCODER,
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { View, Platform, Keyboard } from 'react-native';
|
import { View, Platform, Keyboard, Text } from 'react-native';
|
||||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||||
import ScrollableTabView from 'react-native-scrollable-tab-view';
|
import { useIntl } from 'react-intl';
|
||||||
import { injectIntl } from 'react-intl';
|
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
@ -15,213 +14,219 @@ import {
|
|||||||
LoginHeader,
|
LoginHeader,
|
||||||
MainButton,
|
MainButton,
|
||||||
Modal,
|
Modal,
|
||||||
TabBar,
|
OrDivider,
|
||||||
TextButton,
|
|
||||||
} from '../../../components';
|
} from '../../../components';
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import { default as ROUTES } from '../../../constants/routeNames';
|
import { default as ROUTES } from '../../../constants/routeNames';
|
||||||
|
import { ECENCY_TERMS_URL } from '../../../config/ecencyApi';
|
||||||
|
|
||||||
// Styles
|
// Styles
|
||||||
import styles from './loginStyles';
|
import styles from './loginStyles';
|
||||||
import globalStyles from '../../../globalStyles';
|
import { HiveSignerIcon } from '../../../assets/svgs';
|
||||||
|
|
||||||
import STEEM_CONNECT_LOGO from '../../../assets/steem_connect.png';
|
const LoginScreen = ({
|
||||||
import { ECENCY_TERMS_URL } from '../../../config/ecencyApi';
|
initialUsername,
|
||||||
|
getAccountsWithUsername,
|
||||||
|
navigation,
|
||||||
|
handleOnPressLogin,
|
||||||
|
handleSignUp,
|
||||||
|
isLoading,
|
||||||
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const [username, setUsername] = useState(initialUsername || '');
|
||||||
|
const [password, setPassword] = useState('');
|
||||||
|
const [isUsernameValid, setIsUsernameValid] = useState(true);
|
||||||
|
const [keyboardIsOpen, setKeyboardIsOpen] = useState(false);
|
||||||
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
|
|
||||||
class LoginScreen extends PureComponent {
|
useEffect(() => {
|
||||||
constructor(props) {
|
if (initialUsername) {
|
||||||
super(props);
|
_handleUsernameChange(initialUsername);
|
||||||
|
|
||||||
this.state = {
|
|
||||||
username: props.initialUsername || '',
|
|
||||||
password: '',
|
|
||||||
isUsernameValid: true,
|
|
||||||
keyboardIsOpen: false,
|
|
||||||
isModalOpen: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
if (this.props.initialUsername) {
|
|
||||||
this._handleUsernameChange(this.props.initialUsername);
|
|
||||||
}
|
}
|
||||||
}
|
}, []);
|
||||||
|
|
||||||
componentWillUnmount() {
|
useEffect(() => {
|
||||||
this.keyboardDidShowListener.remove();
|
const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', _keyboardDidShow);
|
||||||
this.keyboardDidHideListener.remove();
|
const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', _keyboardDidHide);
|
||||||
}
|
|
||||||
|
|
||||||
_handleOnPasswordChange = (value) => {
|
return () => {
|
||||||
this.setState({ password: value });
|
keyboardDidShowListener.remove();
|
||||||
|
keyboardDidHideListener.remove();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const debouncedCheckValidity = debounce((uname) => {
|
||||||
|
_checkUsernameIsValid(uname);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (username) {
|
||||||
|
debouncedCheckValidity(username);
|
||||||
|
|
||||||
|
return () => debouncedCheckValidity.cancel();
|
||||||
|
}
|
||||||
|
}, [username]);
|
||||||
|
|
||||||
|
const _keyboardDidShow = () => {
|
||||||
|
setKeyboardIsOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleUsernameChange = (username) => {
|
const _keyboardDidHide = () => {
|
||||||
const { getAccountsWithUsername } = this.props;
|
setKeyboardIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
this.setState({ username });
|
const _handleOnPasswordChange = (value) => {
|
||||||
|
setPassword(value);
|
||||||
|
};
|
||||||
|
|
||||||
getAccountsWithUsername(username).then((res) => {
|
const _handleUsernameChange = (username) => {
|
||||||
const isValid = res.includes(username);
|
const formattedUsername = username.trim().toLowerCase();
|
||||||
|
setUsername(formattedUsername);
|
||||||
|
};
|
||||||
|
|
||||||
this.setState({ isUsernameValid: isValid });
|
const _checkUsernameIsValid = (uname) => {
|
||||||
|
getAccountsWithUsername(uname).then((res) => {
|
||||||
|
const isValid = res.includes(uname);
|
||||||
|
setIsUsernameValid(isValid);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleOnModalToggle = () => {
|
const _handleOnModalToggle = () => {
|
||||||
const { isModalOpen } = this.state;
|
setIsModalOpen(!isModalOpen);
|
||||||
this.setState({ isModalOpen: !isModalOpen });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
UNSAFE_componentWillMount() {
|
const _renderHiveicon = () => (
|
||||||
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () =>
|
<View style={styles.hsLoginBtnIconStyle}>
|
||||||
this.setState({ keyboardIsOpen: true }),
|
<HiveSignerIcon />
|
||||||
);
|
</View>
|
||||||
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () =>
|
);
|
||||||
this.setState({ keyboardIsOpen: false }),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
return (
|
||||||
const { navigation, intl, handleOnPressLogin, handleSignUp, isLoading } = this.props;
|
<View style={styles.container}>
|
||||||
const { username, isUsernameValid, keyboardIsOpen, password, isModalOpen } = this.state;
|
<LoginHeader
|
||||||
|
isKeyboardOpen={keyboardIsOpen}
|
||||||
|
title={intl.formatMessage({
|
||||||
|
id: 'login.signin',
|
||||||
|
})}
|
||||||
|
description={intl.formatMessage({
|
||||||
|
id: 'login.signin_title',
|
||||||
|
})}
|
||||||
|
onPress={() => handleSignUp()}
|
||||||
|
rightButtonText={intl.formatMessage({
|
||||||
|
id: 'login.signup',
|
||||||
|
})}
|
||||||
|
onBackPress={() => {
|
||||||
|
navigation.navigate({
|
||||||
|
name: ROUTES.DRAWER.MAIN,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
console.log('keyboardIsOpen : ', keyboardIsOpen);
|
<View
|
||||||
return (
|
tabLabel={intl.formatMessage({
|
||||||
<View style={styles.container}>
|
id: 'login.signin',
|
||||||
<LoginHeader
|
})}
|
||||||
isKeyboardOpen={keyboardIsOpen}
|
style={styles.tabbarItem}
|
||||||
title={intl.formatMessage({
|
>
|
||||||
id: 'login.signin',
|
<KeyboardAwareScrollView
|
||||||
})}
|
enableAutoAutomaticScroll={Platform.OS === 'ios'}
|
||||||
description={intl.formatMessage({
|
contentContainerStyle={styles.formWrapper}
|
||||||
id: 'login.signin_title',
|
enableOnAndroid={true}
|
||||||
})}
|
|
||||||
onPress={() => handleSignUp()}
|
|
||||||
rightButtonText={intl.formatMessage({
|
|
||||||
id: 'login.signup',
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
<ScrollableTabView
|
|
||||||
locked={isLoading}
|
|
||||||
style={globalStyles.tabView}
|
|
||||||
renderTabBar={() => (
|
|
||||||
<TabBar
|
|
||||||
style={styles.tabbar}
|
|
||||||
tabUnderlineDefaultWidth={100}
|
|
||||||
tabUnderlineScaleX={2} // default 3
|
|
||||||
activeColor="#357ce6"
|
|
||||||
inactiveColor="#222"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
<View
|
<FormInput
|
||||||
tabLabel={intl.formatMessage({
|
rightIconName="at"
|
||||||
id: 'login.signin',
|
leftIconName="close"
|
||||||
|
iconType="MaterialCommunityIcons"
|
||||||
|
isValid={isUsernameValid}
|
||||||
|
onChange={_handleUsernameChange}
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
id: 'login.username',
|
||||||
})}
|
})}
|
||||||
style={styles.tabbarItem}
|
isEditable
|
||||||
>
|
type="username"
|
||||||
<KeyboardAwareScrollView
|
isFirstImage
|
||||||
enableAutoAutomaticScroll={Platform.OS === 'ios'}
|
value={username}
|
||||||
contentContainerStyle={styles.formWrapper}
|
inputStyle={styles.input}
|
||||||
enableOnAndroid={true}
|
onBlur={() => _checkUsernameIsValid(username)}
|
||||||
>
|
/>
|
||||||
<FormInput
|
<FormInput
|
||||||
rightIconName="at"
|
rightIconName="lock"
|
||||||
leftIconName="close"
|
leftIconName="close"
|
||||||
iconType="MaterialCommunityIcons"
|
isValid={isUsernameValid}
|
||||||
isValid={isUsernameValid}
|
onChange={_handleOnPasswordChange}
|
||||||
onChange={debounce(this._handleUsernameChange, 1000)}
|
placeholder={intl.formatMessage({
|
||||||
placeholder={intl.formatMessage({
|
id: 'login.password',
|
||||||
id: 'login.username',
|
})}
|
||||||
})}
|
isEditable
|
||||||
isEditable
|
secureTextEntry
|
||||||
type="username"
|
type="password"
|
||||||
isFirstImage
|
numberOfLines={1}
|
||||||
value={username}
|
value={password}
|
||||||
inputStyle={styles.input}
|
inputStyle={styles.input}
|
||||||
/>
|
/>
|
||||||
<FormInput
|
<InformationArea
|
||||||
rightIconName="lock"
|
description={intl.formatMessage({
|
||||||
leftIconName="close"
|
id: 'login.description',
|
||||||
isValid={isUsernameValid}
|
})}
|
||||||
onChange={(value) => this._handleOnPasswordChange(value)}
|
link={ECENCY_TERMS_URL}
|
||||||
placeholder={intl.formatMessage({
|
iconName="ios-information-circle-outline"
|
||||||
id: 'login.password',
|
/>
|
||||||
})}
|
<MainButton
|
||||||
isEditable
|
onPress={() => handleOnPressLogin(username, password)}
|
||||||
secureTextEntry
|
iconName="person"
|
||||||
type="password"
|
iconColor="white"
|
||||||
numberOfLines={1}
|
text={intl.formatMessage({
|
||||||
value={password}
|
id: 'login.login',
|
||||||
inputStyle={styles.input}
|
})}
|
||||||
/>
|
textStyle={styles.mainBtnText}
|
||||||
<InformationArea
|
isDisable={!isUsernameValid || password.length < 2 || username.length < 2}
|
||||||
description={intl.formatMessage({
|
isLoading={isLoading}
|
||||||
id: 'login.description',
|
wrapperStyle={styles.loginBtnWrapper}
|
||||||
})}
|
bodyWrapperStyle={styles.loginBtnBodyWrapper}
|
||||||
link={ECENCY_TERMS_URL}
|
height={50}
|
||||||
iconName="ios-information-circle-outline"
|
iconStyle={styles.loginBtnIconStyle}
|
||||||
/>
|
/>
|
||||||
</KeyboardAwareScrollView>
|
<OrDivider />
|
||||||
|
<MainButton
|
||||||
<View style={styles.footerButtons}>
|
onPress={() => _handleOnModalToggle()}
|
||||||
<TextButton
|
renderIcon={_renderHiveicon()}
|
||||||
style={styles.cancelButton}
|
text={intl.formatMessage({
|
||||||
onPress={() =>
|
id: 'login.login_with_hs',
|
||||||
navigation.navigate({
|
})}
|
||||||
name: ROUTES.DRAWER.MAIN,
|
textStyle={styles.hsLoginBtnText}
|
||||||
})
|
wrapperStyle={styles.loginBtnWrapper}
|
||||||
}
|
bodyWrapperStyle={styles.loginBtnBodyWrapper}
|
||||||
text={intl.formatMessage({
|
height={48}
|
||||||
id: 'login.cancel',
|
style={styles.hsLoginBtnStyle}
|
||||||
})}
|
/>
|
||||||
/>
|
</KeyboardAwareScrollView>
|
||||||
<MainButton
|
<View style={styles.footerButtons}>
|
||||||
onPress={() => handleOnPressLogin(username, password)}
|
<Text style={styles.noAccountText}>
|
||||||
iconName="person"
|
{intl.formatMessage({
|
||||||
iconColor="white"
|
id: 'login.no_account_text',
|
||||||
text={intl.formatMessage({
|
})}
|
||||||
id: 'login.login',
|
</Text>
|
||||||
})}
|
<Text style={styles.signUpNowText} onPress={() => handleSignUp()}>
|
||||||
textStyle={styles.mainBtnText}
|
{intl.formatMessage({
|
||||||
isDisable={!isUsernameValid || password.length < 2 || username.length < 2}
|
id: 'login.signup_now',
|
||||||
isLoading={isLoading}
|
})}
|
||||||
/>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
|
||||||
<View tabLabel="Hivesigner" style={styles.tabbarItem}>
|
|
||||||
<InformationArea
|
|
||||||
description={intl.formatMessage({
|
|
||||||
id: 'login.steemconnect_description',
|
|
||||||
})}
|
|
||||||
iconName="ios-information-circle-outline"
|
|
||||||
link="https://hivesigner.com"
|
|
||||||
/>
|
|
||||||
<MainButton
|
|
||||||
wrapperStyle={styles.mainButtonWrapper}
|
|
||||||
onPress={() => this._handleOnModalToggle()}
|
|
||||||
source={STEEM_CONNECT_LOGO}
|
|
||||||
text="hive"
|
|
||||||
secondText="signer"
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</ScrollableTabView>
|
|
||||||
<Modal
|
|
||||||
isOpen={isModalOpen}
|
|
||||||
isFullScreen
|
|
||||||
isCloseButton
|
|
||||||
handleOnModalClose={this._handleOnModalToggle}
|
|
||||||
title={intl.formatMessage({
|
|
||||||
id: 'login.signin',
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<HiveSigner handleOnModalClose={this._handleOnModalToggle} />
|
|
||||||
</Modal>
|
|
||||||
</View>
|
</View>
|
||||||
);
|
<Modal
|
||||||
}
|
isOpen={isModalOpen}
|
||||||
}
|
isFullScreen
|
||||||
|
isCloseButton
|
||||||
|
handleOnModalClose={_handleOnModalToggle}
|
||||||
|
title={intl.formatMessage({
|
||||||
|
id: 'login.signin',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<HiveSigner handleOnModalClose={_handleOnModalToggle} />
|
||||||
|
</Modal>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default injectIntl(LoginScreen);
|
export default LoginScreen;
|
||||||
|
@ -3,7 +3,7 @@ import EStyleSheet from 'react-native-extended-stylesheet';
|
|||||||
export default EStyleSheet.create({
|
export default EStyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: '$primaryLightBackground',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
},
|
},
|
||||||
tabbar: {
|
tabbar: {
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
@ -11,10 +11,9 @@ export default EStyleSheet.create({
|
|||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
},
|
},
|
||||||
tabbarItem: {
|
tabbarItem: {
|
||||||
flex: 1,
|
// flex: 1,
|
||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
minWidth: '$deviceWidth',
|
minWidth: '$deviceWidth',
|
||||||
height: '$deviceHeight / 1.95',
|
|
||||||
},
|
},
|
||||||
mainButtonWrapper: {
|
mainButtonWrapper: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@ -22,20 +21,13 @@ export default EStyleSheet.create({
|
|||||||
bottom: 24,
|
bottom: 24,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
},
|
},
|
||||||
footerButtons: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
alignSelf: 'flex-end',
|
|
||||||
paddingRight: 24,
|
|
||||||
paddingBottom: 24,
|
|
||||||
backgroundColor: '$primaryBackgroundColor',
|
|
||||||
},
|
|
||||||
cancelButton: {
|
cancelButton: {
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
formWrapper: {
|
formWrapper: {
|
||||||
flexGrow: 1,
|
|
||||||
marginHorizontal: 30,
|
marginHorizontal: 30,
|
||||||
marginVertical: 10,
|
marginVertical: 10,
|
||||||
},
|
},
|
||||||
@ -44,6 +36,44 @@ export default EStyleSheet.create({
|
|||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
},
|
},
|
||||||
mainBtnText: {
|
mainBtnText: {
|
||||||
marginRight: 12,
|
flexGrow: 1,
|
||||||
|
},
|
||||||
|
loginBtnWrapper: {
|
||||||
|
marginVertical: 12,
|
||||||
|
},
|
||||||
|
loginBtnBodyWrapper: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
loginBtnIconStyle: {
|
||||||
|
position: 'absolute',
|
||||||
|
left: 0,
|
||||||
|
},
|
||||||
|
hsLoginBtnStyle: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: '$primaryBlue',
|
||||||
|
},
|
||||||
|
hsLoginBtnText: {
|
||||||
|
flexGrow: 1,
|
||||||
|
color: '$primaryBlue',
|
||||||
|
},
|
||||||
|
hsLoginBtnIconStyle: {
|
||||||
|
marginLeft: 20,
|
||||||
|
},
|
||||||
|
footerButtons: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingHorizontal: 24,
|
||||||
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
|
},
|
||||||
|
noAccountText: {
|
||||||
|
color: '$primaryDarkGray',
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
|
signUpNowText: {
|
||||||
|
color: '$primaryBlue',
|
||||||
|
marginLeft: 4,
|
||||||
|
fontSize: 16,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user