Merge branch 'master' of github.com:esteemapp/esteem-mobile into pin-code-two

This commit is contained in:
mistikk 2018-09-28 01:00:46 +03:00
commit ed4b60b2c9
23 changed files with 1072 additions and 937 deletions

View File

@ -1,22 +1,22 @@
module.exports = {
env: {
browser: true,
commonjs: true,
es6: true,
},
extends: "eslint:recommended",
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 2018,
sourceType: "module",
},
plugins: ["react"],
rules: {
indent: ["error", "space"],
"linebreak-style": ["error", "unix"],
quotes: ["error", "double"],
semi: ["error", "always"],
},
env: {
browser: true,
commonjs: true,
es6: true,
},
extends: "eslint:recommended",
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 2018,
sourceType: "module",
},
plugins: ["react"],
rules: {
indent: ["error", "space"],
"linebreak-style": ["error", "unix"],
quotes: ["error", "double"],
semi: ["error", "always"],
},
};

View File

@ -1,5 +1,5 @@
{
"tabWidth": 4,
"singleQuote": false,
"trailingComma": "es5"
}
"tabWidth": 2,
"singleQuote": false,
"trailingComma": "es5"
}

View File

@ -9,29 +9,29 @@ import {} from "react-native";
// eslint-disable-next-line
import styles from "./_styles";
/*
* Props Name Description Value
*@props --> props name here description here Value Type Here
*
*/
class ExampleView extends Component {
constructor(props) {
super(props);
this.state = {};
}
/* Props
* ------------------------------------------------ TODO: Fill fallowlines
* @prop { type } name - Description.
* @prop { type } name - Description.
*
*/
constructor(props) {
super(props);
this.state = {};
}
// Component Life Cycles
// Component Life Cycles
// Component Functions
// Component Functions
render() {
// eslint-disable-next-line
const {} = this.props;
render() {
// eslint-disable-next-line
const {} = this.props;
// eslint-disable-next-line
return <ElementName />;
}
// eslint-disable-next-line
return <ElementName />;
}
}
export default ExampleView;

View File

@ -0,0 +1,3 @@
import LineBreak from "./view/lineBreakView";
export { LineBreak };

View File

@ -0,0 +1,9 @@
import EStyleSheet from "react-native-extended-stylesheet";
export default EStyleSheet.create({
lineBreak: {
width: "$deviceWidth",
backgroundColor: "#f6f6f6",
height: 10,
},
});

View File

@ -0,0 +1,7 @@
import React from "react";
import { View } from "react-native";
import styles from "./lineBreakStyles";
const LineBreak = ({ color }) => <View style={[styles.lineBreak]} />;
export default LineBreak;

View File

@ -0,0 +1,3 @@
import GreetingHeaderButton from "./views/greetingHeaderButtonView";
export { GreetingHeaderButton };

View File

@ -0,0 +1,13 @@
import EStyleSheet from "react-native-extended-stylesheet";
export default EStyleSheet.create({
button: {
width: 54,
backgroundColor: "transparent",
height: 19,
},
buttonText: {
color: "#c1c5c7",
fontSize: 16,
},
});

View File

@ -0,0 +1,17 @@
import React, { Fragment } from "react";
import { TouchableWithoutFeedback, Text } from "react-native";
import styles from "./greetingHeaderButtonStyles";
const GreetingHeaderButtonView = ({ text, onPress, style }) => (
<Fragment>
<TouchableWithoutFeedback
style={[styles.button, style]}
onPress={() => onPress && onPress()}
>
<Text style={styles.buttonText}>{text}</Text>
</TouchableWithoutFeedback>
</Fragment>
);
export default GreetingHeaderButtonView;

View File

@ -1,12 +0,0 @@
import React from "react";
import { View, TextInput } from "react-native";
import styles from "../../styles/formInput.styles";
const FormInput = props => (
<View style={styles.container}>
<TextInput style={styles.input} {...props} />
</View>
);
export default FormInput;

View File

@ -0,0 +1,3 @@
import FormInput from "./view/formInputView";
export { FormInput };

View File

@ -0,0 +1,32 @@
import EStyleSheet from "react-native-extended-stylesheet";
export default EStyleSheet.create({
wrapper: {
borderTopLeftRadius: 8,
borderTopRightRadius: 8,
marginHorizontal: 30,
marginVertical: 20,
flexDirection: "row",
backgroundColor: "#f5f5f5",
height: 60,
borderBottomWidth: 2,
},
firstImage: {
width: 24,
height: 24,
borderRadius: 12,
top: 15,
marginLeft: 12,
},
textInput: {
height: 60,
flex: 0.7,
},
icon: {
flex: 0.15,
fontSize: 25,
top: 18,
left: 8,
color: "#c1c5c7",
},
});

View File

@ -0,0 +1,115 @@
import React, { Component } from "react";
import { View, Text, Image, TextInput } from "react-native";
import Ionicons from "react-native-vector-icons/Ionicons";
import FastImage from "react-native-fast-image";
// Constants
// Components
// Styles
import styles from "./formInputStyles";
class FormInputView extends Component {
/* Props
* ------------------------------------------------
* @prop { string } placeholder - Place holder text.
* @prop { string } type - Input type.
* @prop { boolean } isFirstImage - Render image from steem.
* @prop { boolean } isEditable - Can permission edit.
* @prop { boolean } isValid - This delegate input valit or not.
* @prop { boolean } secureTextEntry - For hiding password value.
*
*
*
*/
constructor(props) {
super(props);
this.state = {
value: "",
inputBorderColor: "#c1c5c7",
};
}
// Component Life Cycles
// Component Functions
_handleOnChange = value => {
const { onChange } = this.props;
value && this.setState({ value });
onChange && value && onChange(value);
};
render() {
const { inputBorderColor, value } = this.state;
const {
placeholder,
type,
isFirstImage,
isEditable,
isValid,
leftIconName,
rightIconName,
secureTextEntry,
} = this.props;
return (
<View
style={[
styles.wrapper,
{
borderBottomColor: isValid ? inputBorderColor : "red",
},
]}
>
{isFirstImage && value && value.length > 2 ? (
<View style={{ flex: 0.15 }}>
<FastImage
style={styles.firstImage}
source={{
uri: `https://steemitimages.com/u/${value}/avatar/small`,
priority: FastImage.priority.high,
}}
resizeMode={FastImage.resizeMode.cover}
/>
</View>
) : (
<Ionicons name={rightIconName} style={styles.icon} />
)}
<TextInput
onFocus={() =>
this.setState({
inputBorderColor: "#357ce6",
})
}
onSubmitEditing={() =>
this.setState({
inputBorderColor: "#c1c5c7",
})
}
autoCapitalize="none"
secureTextEntry={secureTextEntry}
placeholder={placeholder}
editable={isEditable || true}
textContentType={type}
onChangeText={value => {
this._handleOnChange(value);
}}
value={value}
style={styles.textInput}
/>
{value && value.length > 0 ? (
<Ionicons
onPress={() => this.setState({ value: "" })}
name={leftIconName}
style={styles.icon}
/>
) : null}
</View>
);
}
}
export default FormInputView;

View File

@ -3,6 +3,6 @@ import Comment from "./comment/comment";
import PostCard from "./post-card/postCard";
import Reply from "./reply/reply";
import Search from "./search/search";
import FormInput from "./formInput/formInput";
import { FormInput } from "./formInput";
export { Logo, Comment, PostCard, Reply, Search, FormInput };

View File

@ -0,0 +1,3 @@
import InformationArea from "./view/informationAreaView";
export { InformationArea };

View File

@ -0,0 +1,20 @@
import EStyleSheet from "react-native-extended-stylesheet";
export default EStyleSheet.create({
container: {
flexDirection: "row",
paddingLeft: 50,
paddingRight: 32,
marginTop: 10,
},
infoIcon: {
flex: 0.125,
fontSize: 20,
alignSelf: "center",
},
infoText: {
flex: 0.875,
fontSize: 12,
color: "#788187",
},
});

View File

@ -0,0 +1,41 @@
import React, { Component } from "react";
import { View, Text } from "react-native";
import Ionicons from "react-native-vector-icons/Ionicons";
// Constants
// Components
// Styles
import styles from "./informationAreaStyles";
class FormInputView extends Component {
/* Props
* ------------------------------------------------
* @prop { string } description - Description texts.
* @prop { string } iconName - For icon render name.
*
*/
constructor(props) {
super(props);
this.state = {};
}
// Component Life Cycles
// Component Functions
render() {
const { description, iconName } = this.props;
return (
<View style={styles.container}>
<Ionicons color="#c1c5c7" style={styles.infoIcon} name={iconName} />
<Text style={styles.infoText}>{description}</Text>
</View>
);
}
}
export default FormInputView;

View File

@ -0,0 +1,3 @@
import LoginHeader from "./view/loginHeaderView";
export { LoginHeader };

View File

@ -0,0 +1,58 @@
import EStyleSheet from "react-native-extended-stylesheet";
export default EStyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
height: "$deviceHeight / 3",
},
body: {
flexDirection: "row",
maxHeight: "$deviceHeight / 3",
overflow: "hidden",
backgroundColor: "$white",
},
description: {
textAlignVertical: "center",
color: "#788187",
fontSize: 14,
fontWeight: "400",
},
title: {
textAlignVertical: "center",
fontSize: 20,
fontWeight: "bold",
color: "#788187",
marginBottom: 16,
},
mascot: {
width: 217,
height: 300,
marginLeft: 50,
marginTop: 40,
},
titleText: {
flex: 0.4,
alignSelf: "center",
height: 100,
marginTop: 50,
marginLeft: 32,
},
headerRow: {
width: "$deviceWidth",
flexDirection: "row",
height: 55,
justifyContent: "space-between",
},
logo: {
width: 32,
height: 32,
marginLeft: 32,
alignSelf: "center",
},
headerButton: {
margin: 10,
marginRight: 19,
alignSelf: "center",
},
});

View File

@ -0,0 +1,60 @@
import React, { Component } from "react";
import { View, Text, Image } from "react-native";
// Constants
// Components
import { GreetingHeaderButton } from "../../buttons";
import { LineBreak } from "../../basicUIElements";
// Styles
// eslint-disable-next-line
import styles from "./loginHeaderStyles";
class LoginHeaderView extends Component {
/* Props
* ------------------------------------------------
* @prop { string } title - Title for header string.
* @prop { string } description - Description for header string.
*
*/
constructor(props) {
super(props);
this.state = {};
}
// Component Life Cycles
// Component Functions
render() {
const { description, title } = this.props;
return (
<View styles={styles.container}>
<View style={styles.headerRow}>
<Image
style={styles.logo}
source={require("../../../assets/esteem.png")}
/>
<View style={styles.headerButton}>
<GreetingHeaderButton text="Sign up" />
</View>
</View>
<View style={styles.body}>
<View style={styles.titleText}>
<Text style={styles.title}>{title}</Text>
<Text style={styles.description}>{description}</Text>
</View>
<View style={{ flex: 0.7 }}>
<Image
style={styles.mascot}
source={require("../../../assets/love_mascot.png")}
/>
</View>
</View>
<LineBreak />
</View>
);
}
}
export default LoginHeaderView;

View File

@ -4,331 +4,322 @@ import { Dimensions } from "react-native";
const deviceWidth = Dimensions.get("window").width;
export const goToAuthScreens = () =>
Navigation.setRoot({
root: {
sideMenu: {
right: {
component: {
name: "navigation.eSteem.SideMenuScreen",
passProps: {
side: "right",
},
},
},
center: {
bottomTabs: {
children: [
{
stack: {
id: "tab1Stack",
children: [
{
component: {
name: "navigation.eSteem.Home",
passProps: {
text:
"This is a side menu center screen tab 1",
},
},
},
],
options: {
bottomTab: {
iconInsets: {
top: 6,
left: 0,
bottom: -6,
right: 0,
},
icon: require("./assets/feed.png"),
iconColor: "gray",
selectedIconColor: "#222",
},
},
},
},
{
stack: {
children: [
{
component: {
name:
"navigation.eSteem.Notifications",
passProps: {
text:
"This is a side menu center screen tab 2",
},
},
},
],
options: {
bottomTab: {
iconInsets: {
top: 6,
left: 0,
bottom: -6,
right: 0,
},
icon: require("./assets/notification.png"),
iconColor: "gray",
selectedIconColor: "#222",
},
},
},
},
{
stack: {
children: [
{
component: {
name:
"navigation.eSteem.Editor",
passProps: {
text:
"This is a side menu center screen tab 3",
},
},
},
],
options: {
bottomTab: {
iconInsets: {
top: 6,
left: 0,
bottom: -6,
right: 0,
},
icon: require("./assets/add.png"),
iconColor: "gray",
selectedIconColor: "#222",
},
},
},
},
{
stack: {
children: [
{
component: {
name:
"navigation.eSteem.Wallet",
passProps: {
text:
"This is a side menu center screen tab 3",
},
},
},
],
options: {
bottomTab: {
iconInsets: {
top: 6,
left: 0,
bottom: -6,
right: 0,
},
icon: require("./assets/wallet.png"),
iconColor: "gray",
selectedIconColor: "#222",
},
},
},
},
{
stack: {
children: [
{
component: {
name:
"navigation.eSteem.Wallet",
passProps: {
text:
"This is a side menu center screen tab 3",
},
},
},
],
options: {
bottomTab: {
iconInsets: {
top: 6,
left: 0,
bottom: -6,
right: 0,
},
icon: require("./assets/wallet.png"),
iconColor: "gray",
selectedIconColor: "#222",
},
},
},
},
],
options: {
bottomTab: {
tabBarShowLabels: "hidden",
textColor: "#AED581",
iconColor: "#AED581",
selectedTextColor: "gray",
selectedIconColor: "gray",
fontFamily: "HelveticaNeue-Italic",
fontSize: 13,
},
},
},
},
options: {
topBar: {
visible: true,
animate: true, // Controls whether TopBar visibility changes should be animated
hideOnScroll: false,
elevation: 0,
noBorder: true,
rightButtons: [
{
id: "search",
icon: require("./assets/search.png"),
},
],
},
bottomTabs: {
titleDisplayMode: "alwaysHide",
visible: true,
animate: false, // Controls whether BottomTabs visibility changes should be animated
},
bottomTab: {
iconColor: "gray",
selectedIconColor: "#222",
textColor: "#1B4C77",
selectedTextColor: "#0f0",
fontFamily: "HelveticaNeue-Italic",
fontSize: 13,
},
sideMenu: {
right: {
width: deviceWidth / 1.4,
},
},
// _animations: {
// startApp: {
// y: {
// from: 1000,
// to: 0,
// duration: 500,
// interpolation: "accelerate",
// },
// alpha: {
// from: 0,
// to: 1,
// duration: 500,
// interpolation: "accelerate",
// },
// },
// push: {
// topBar: {
// id: "TEST",
// alpha: {
// from: 0,
// to: 1,
// duration: 500,
// interpolation: "accelerate",
// },
// },
// bottomTabs: {
// y: {
// from: 1000,
// to: 0,
// duration: 500,
// interpolation: "decelerate",
// },
// alpha: {
// from: 0,
// to: 1,
// duration: 500,
// interpolation: "decelerate",
// },
// },
// content: {
// y: {
// from: 1000,
// to: 0,
// duration: 500,
// interpolation: "accelerate",
// },
// alpha: {
// from: 0,
// to: 1,
// duration: 500,
// interpolation: "accelerate",
// },
// },
// waitForRender: false,
// },
// pop: {
// topBar: {
// id: "TEST",
// alpha: {
// from: 1,
// to: 0,
// duration: 500,
// interpolation: "accelerate",
// },
// },
// bottomTabs: {
// y: {
// from: 0,
// to: 100,
// duration: 500,
// interpolation: "decelerate",
// },
// alpha: {
// from: 1,
// to: 0,
// duration: 500,
// interpolation: "decelerate",
// },
// },
// content: {
// y: {
// from: 0,
// to: 1000,
// duration: 500,
// interpolation: "decelerate",
// },
// alpha: {
// from: 1,
// to: 0,
// duration: 500,
// interpolation: "decelerate",
// },
// },
// },
// },
},
Navigation.setRoot({
root: {
sideMenu: {
right: {
component: {
name: "navigation.eSteem.SideMenuScreen",
passProps: {
side: "right",
},
},
},
});
center: {
bottomTabs: {
children: [
{
stack: {
id: "tab1Stack",
children: [
{
component: {
name: "navigation.eSteem.Home",
passProps: {
text: "This is a side menu center screen tab 1",
},
},
},
],
options: {
bottomTab: {
iconInsets: {
top: 6,
left: 0,
bottom: -6,
right: 0,
},
icon: require("./assets/feed.png"),
iconColor: "gray",
selectedIconColor: "#222",
},
},
},
},
{
stack: {
children: [
{
component: {
name: "navigation.eSteem.Notifications",
passProps: {
text: "This is a side menu center screen tab 2",
},
},
},
],
options: {
bottomTab: {
iconInsets: {
top: 6,
left: 0,
bottom: -6,
right: 0,
},
icon: require("./assets/notification.png"),
iconColor: "gray",
selectedIconColor: "#222",
},
},
},
},
{
stack: {
children: [
{
component: {
name: "navigation.eSteem.Editor",
passProps: {
text: "This is a side menu center screen tab 3",
},
},
},
],
options: {
bottomTab: {
iconInsets: {
top: 6,
left: 0,
bottom: -6,
right: 0,
},
icon: require("./assets/add.png"),
iconColor: "gray",
selectedIconColor: "#222",
},
},
},
},
{
stack: {
children: [
{
component: {
name: "navigation.eSteem.Wallet",
passProps: {
text: "This is a side menu center screen tab 3",
},
},
},
],
options: {
bottomTab: {
iconInsets: {
top: 6,
left: 0,
bottom: -6,
right: 0,
},
icon: require("./assets/wallet.png"),
iconColor: "gray",
selectedIconColor: "#222",
},
},
},
},
{
stack: {
children: [
{
component: {
name: "navigation.eSteem.Wallet",
passProps: {
text: "This is a side menu center screen tab 3",
},
},
},
],
options: {
bottomTab: {
iconInsets: {
top: 6,
left: 0,
bottom: -6,
right: 0,
},
icon: require("./assets/wallet.png"),
iconColor: "gray",
selectedIconColor: "#222",
},
},
},
},
],
options: {
bottomTab: {
tabBarShowLabels: "hidden",
textColor: "#AED581",
iconColor: "#AED581",
selectedTextColor: "gray",
selectedIconColor: "gray",
fontFamily: "HelveticaNeue-Italic",
fontSize: 13,
},
},
},
},
options: {
topBar: {
visible: true,
animate: true, // Controls whether TopBar visibility changes should be animated
hideOnScroll: false,
elevation: 0,
noBorder: true,
rightButtons: [
{
id: "search",
icon: require("./assets/search.png"),
},
],
},
bottomTabs: {
titleDisplayMode: "alwaysHide",
visible: true,
animate: false, // Controls whether BottomTabs visibility changes should be animated
},
bottomTab: {
iconColor: "gray",
selectedIconColor: "#222",
textColor: "#1B4C77",
selectedTextColor: "#0f0",
fontFamily: "HelveticaNeue-Italic",
fontSize: 13,
},
sideMenu: {
right: {
width: deviceWidth / 1.4,
},
},
// _animations: {
// startApp: {
// y: {
// from: 1000,
// to: 0,
// duration: 500,
// interpolation: "accelerate",
// },
// alpha: {
// from: 0,
// to: 1,
// duration: 500,
// interpolation: "accelerate",
// },
// },
// push: {
// topBar: {
// id: "TEST",
// alpha: {
// from: 0,
// to: 1,
// duration: 500,
// interpolation: "accelerate",
// },
// },
// bottomTabs: {
// y: {
// from: 1000,
// to: 0,
// duration: 500,
// interpolation: "decelerate",
// },
// alpha: {
// from: 0,
// to: 1,
// duration: 500,
// interpolation: "decelerate",
// },
// },
// content: {
// y: {
// from: 1000,
// to: 0,
// duration: 500,
// interpolation: "accelerate",
// },
// alpha: {
// from: 0,
// to: 1,
// duration: 500,
// interpolation: "accelerate",
// },
// },
// waitForRender: false,
// },
// pop: {
// topBar: {
// id: "TEST",
// alpha: {
// from: 1,
// to: 0,
// duration: 500,
// interpolation: "accelerate",
// },
// },
// bottomTabs: {
// y: {
// from: 0,
// to: 100,
// duration: 500,
// interpolation: "decelerate",
// },
// alpha: {
// from: 1,
// to: 0,
// duration: 500,
// interpolation: "decelerate",
// },
// },
// content: {
// y: {
// from: 0,
// to: 1000,
// duration: 500,
// interpolation: "decelerate",
// },
// alpha: {
// from: 1,
// to: 0,
// duration: 500,
// interpolation: "decelerate",
// },
// },
// },
// },
},
},
},
});
export const goToNoAuthScreens = () =>
Navigation.setRoot({
root: {
stack: {
id: "LoginScreen",
children: [
{
// TODO before commit navigation.eSteem.Login
component: {
name: "navigation.eSteem.Login",
},
},
],
options: {
topBar: {
visible: true,
noBorder: true,
elevation: 0,
},
},
Navigation.setRoot({
root: {
stack: {
id: "LoginScreen",
children: [
{
// TODO before commit navigation.eSteem.Login
component: {
name: "navigation.eSteem.Login",
},
},
],
options: {
topBar: {
visible: false,
noBorder: true,
elevation: 0,
},
},
});
},
},
});

View File

@ -1,13 +1,14 @@
import React, { Component } from "react";
import {
View,
ActivityIndicator,
Text,
Image,
TouchableOpacity,
TextInput,
BackHandler,
Linking,
View,
ActivityIndicator,
Text,
Image,
TouchableOpacity,
TextInput,
BackHandler,
Linking,
StatusBar,
} from "react-native";
import { Navigation } from "react-native-navigation";
@ -15,6 +16,9 @@ import Ionicons from "react-native-vector-icons/Ionicons";
import FastImage from "react-native-fast-image";
import { TabBar } from "../../../components/tabBar";
import { LoginHeader } from "../../../components/loginHeader";
import { FormInput } from "../../../components/formInput";
import { InformationArea } from "../../../components/informationArea";
import ScrollableTabView from "@esteemapp/react-native-scrollable-tab-view";
import { Login } from "../../../providers/steem/auth";
@ -27,528 +31,294 @@ import { goToAuthScreens } from "../../../navigation";
import styles from "./loginStyles";
class LoginScreen extends Component {
static get options() {
return {
_statusBar: {
visible: true,
drawBehind: false,
},
topBar: {
animate: true,
hideOnScroll: false,
drawBehind: false,
noBorder: true,
visible: true,
elevation: 0,
leftButtons: {},
rightButtons: [
{
id: "signup",
text: "Sign Up",
color: "#a7adaf",
marginRight: 50,
},
],
},
layout: {
backgroundColor: "#f5fcff",
},
bottomTabs: {
visible: false,
drawBehind: true,
},
};
}
constructor(props) {
super(props);
Navigation.events().bindComponent(this);
this.handleUsername = this.handleUsername.bind(this);
this.state = {
username: "",
password: "",
isLoading: false,
isUsernameValid: true,
usernameBorderColor: "#c1c5c7",
passwordBorderColor: "#c1c5c7",
};
}
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", () => {
Navigation.pop(this.props.componentId);
return true;
});
Linking.getInitialURL().then(url => {
console.log(url);
});
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress");
}
doLogin = () => {
const { componentId } = this.props;
this.setState({ isLoading: true });
let password = this.state.password;
let username = this.state.username;
console.log("componentId", componentId);
Login(username, password)
.then(result => {
if (result) {
this.props.dispatch(addNewAccount(result));
Navigation.setStackRoot(componentId, {
component: {
name: "navigation.eSteem.PinCode",
options: {
topBar: {
visible: false,
},
},
},
});
}
})
.catch(err => {
alert(err);
this.setState({ isLoading: false });
});
static get options() {
return {
_statusBar: {
visible: true,
drawBehind: false,
},
topBar: {
animate: true,
hideOnScroll: false,
drawBehind: false,
noBorder: true,
visible: true,
elevation: 0,
leftButtons: {},
rightButtons: [
{
id: "signup",
text: "Sign Up",
color: "#a7adaf",
marginRight: 50,
},
],
},
layout: {
backgroundColor: "#f5fcff",
},
bottomTabs: {
visible: false,
drawBehind: true,
},
};
handleUsername = async username => {
await this.setState({ username });
let validUsers = await lookupAccounts(username);
await this.setState({ isUsernameValid: validUsers.includes(username) });
}
constructor(props) {
super(props);
Navigation.events().bindComponent(this);
this.handleUsername = this.handleUsername.bind(this);
this.state = {
username: "",
password: "",
isLoading: false,
isUsernameValid: true,
};
}
navigationButtonPressed({ buttonId }) {
if (buttonId === "signup") {
Linking.openURL("https://signup.steemit.com/?ref=esteem").catch(
err => console.error("An error occurred", err)
);
}
}
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", () => {
Navigation.pop(this.props.componentId);
return true;
});
Linking.getInitialURL().then(url => {
console.log(url);
});
}
loginwithSc2 = () => {
Navigation.push(this.props.componentId, {
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress");
}
_handleOnPressLogin = () => {
const { componentId, dispatch } = this.props;
const { password, username } = this.state;
this.setState({ isLoading: true });
Login(username, password)
.then(result => {
if (result) {
dispatch(addNewAccount(result));
Navigation.setStackRoot(componentId, {
component: {
name: "navigation.eSteem.SteemConnect",
passProps: {},
options: {
topBar: {
title: {
text: "Login via SC2",
},
},
name: "navigation.eSteem.PinCode",
options: {
topBar: {
visible: false,
},
},
},
});
};
});
}
})
.catch(err => {
alert(err);
this.setState({ isLoading: false });
});
};
render() {
return (
<View style={{ flex: 1 }}>
<ScrollableTabView
style={styles.tabView}
renderTabBar={() => (
<TabBar
style={styles.tabbar}
tabUnderlineDefaultWidth={100} // default containerWidth / (numberOfTabs * 4)
tabUnderlineScaleX={2} // default 3
activeColor={"#357ce6"}
inactiveColor={"#222"}
/>
)}
>
<View tabLabel="Sign in" style={styles.tabbarItem}>
<View
style={{
backgroundColor: "#f5f5f5",
height: 60,
borderBottomWidth: 2,
borderBottomColor: this.state.isUsernameValid
? this.state.usernameBorderColor
: "red",
borderTopLeftRadius: 8,
borderTopRightRadius: 8,
marginHorizontal: 30,
marginVertical: 20,
flexDirection: "row",
}}
>
{this.state.username.length > 2 ? (
<View style={{ flex: 0.15 }}>
<FastImage
style={{
width: 24,
height: 24,
borderRadius: 12,
top: 15,
marginLeft: 12,
}}
source={{
uri: `https://steemitimages.com/u/${
this.state.username
}/avatar/small`,
priority: FastImage.priority.high,
}}
resizeMode={FastImage.resizeMode.cover}
/>
</View>
) : (
<Ionicons
name="md-at"
style={{
flex: 0.15,
fontSize: 25,
top: 18,
left: 12,
color: "#c1c5c7",
}}
/>
)}
<TextInput
onFocus={() =>
this.setState({
usernameBorderColor: "#357ce6",
})
}
onSubmitEditing={() =>
this.setState({
usernameBorderColor: "#c1c5c7",
})
}
autoCapitalize="none"
placeholder="username"
editable={true}
textContentType="username"
onChangeText={text => {
this.handleUsername(text);
}}
value={this.state.username}
style={{
height: 60,
flex: 0.7,
}}
/>
handleUsername = async username => {
await this.setState({ username });
const validUsers = await lookupAccounts(username);
await this.setState({ isUsernameValid: validUsers.includes(username) });
};
{this.state.username.length > 0 ? (
<Ionicons
onPress={() =>
this.setState({ username: "" })
}
name="md-close-circle"
style={{
flex: 0.15,
fontSize: 25,
top: 18,
left: 8,
color: "#c1c5c7",
}}
/>
) : null}
</View>
_handleOnPasswordChange = value => {
this.setState({ password: value });
};
<View
style={{
backgroundColor: "#f5f5f5",
height: 60,
borderBottomWidth: 2,
borderBottomColor: this.state
.passwordBorderColor,
borderTopLeftRadius: 8,
borderTopRightRadius: 8,
marginHorizontal: 30,
marginVertical: 20,
flexDirection: "row",
}}
>
<Ionicons
name="md-lock"
style={{
flex: 0.15,
fontSize: 25,
top: 18,
left: 14,
color: "#c1c5c7",
}}
/>
<TextInput
onFocus={() =>
this.setState({
passwordBorderColor: "#357ce6",
})
}
onSubmitEditing={() =>
this.setState({
passwordBorderColor: "#c1c5c7",
})
}
secureTextEntry={true}
placeholder="Password or WIF"
textContentType="password"
onChangeText={text =>
this.setState({ password: text })
}
value={this.state.password}
style={{
height: 60,
flex: 0.7,
width: "100%",
}}
/>
{this.state.password.length > 0 ? (
<Ionicons
onPress={() =>
this.setState({ password: "" })
}
name="md-close-circle"
style={{
flex: 0.15,
fontSize: 25,
top: 18,
left: 8,
color: "#c1c5c7",
}}
/>
) : null}
</View>
<View
style={{
flexDirection: "row",
marginHorizontal: 30,
paddingLeft: 10,
}}
>
<Ionicons
color="#c1c5c7"
style={{
flex: 0.125,
fontSize: 25,
alignSelf: "center",
}}
name="ios-information-circle-outline"
/>
<Text style={{ flex: 0.875, color: "#788187" }}>
User credentials are kept locally on the device.
Credentials are removed upon logout!
</Text>
</View>
<View style={{ flexDirection: "row", margin: 30 }}>
<View style={{ flex: 0.6 }}>
<TouchableOpacity
onPress={goToAuthScreens}
style={{
alignContent: "center",
padding: "9%",
}}
>
<Text
style={{
color: "#788187",
alignSelf: "center",
fontWeight: "bold",
}}
>
Cancel
</Text>
</TouchableOpacity>
</View>
<TouchableOpacity
onPress={this.doLogin}
style={{
flex: 0.4,
width: 100,
height: 50,
borderRadius: 30,
backgroundColor: "#357ce6",
flexDirection: "row",
}}
>
{!this.state.isLoading ? (
<View
style={{
flex: 1,
flexDirection: "row",
}}
>
<Ionicons
color="white"
name="md-person"
style={{
alignSelf: "center",
fontSize: 25,
flex: 0.4,
left: 15,
}}
/>
<Text
style={{
color: "white",
fontWeight: "600",
alignSelf: "center",
fontSize: 16,
flex: 0.6,
}}
>
LOGIN
</Text>
</View>
) : (
<ActivityIndicator
color="white"
style={{ alignSelf: "center", flex: 1 }}
/>
)}
</TouchableOpacity>
</View>
</View>
<View
tabLabel="SteemConnect"
style={styles.steemConnectTab}
>
<View
style={{
flex: 1,
flexDirection: "row",
maxHeight: 200,
overflow: "hidden",
backgroundColor: "#ffffff",
}}
>
<View style={{ flex: 0.4 }}>
<View
style={{
alignSelf: "center",
height: 100,
top: 70,
left: 20,
}}
>
<Text
style={{
textAlign: "center",
textAlignVertical: "center",
fontSize: 20,
fontWeight: "bold",
color: "#788187",
bottom: 10,
}}
>
Sign in
</Text>
<Text
style={{
textAlign: "center",
textAlignVertical: "center",
color: "#788187",
fontSize: 14,
fontWeight: "400",
}}
>
To get all the benefits using eSteem
</Text>
</View>
</View>
<View style={{ flex: 0.6 }}>
<Image
style={{
width: 217,
height: 300,
left: 55,
top: 10,
}}
source={require("../../../assets/love_mascot.png")}
/>
</View>
</View>
<View
style={{
flex: 1,
backgroundColor: "#ffffff",
marginTop: 10,
}}
>
<View
style={{
flexDirection: "row",
marginHorizontal: 30,
paddingLeft: 10,
marginTop: 20,
}}
>
<Ionicons
color="#c1c5c7"
style={{
flex: 0.125,
fontSize: 25,
alignSelf: "center",
}}
name="ios-information-circle-outline"
/>
<Text style={{ flex: 0.875, color: "#788187" }}>
If you don't want to keep your password
encrypted and saved on your device, you can
use Steemconnect.
</Text>
</View>
</View>
<View
style={{
alignItems: "flex-end",
backgroundColor: "#ffffff",
}}
>
<TouchableOpacity
onPress={this.loginwithSc2}
style={{
width: 200,
height: 50,
borderRadius: 30,
backgroundColor: "#357ce6",
flexDirection: "row",
margin: 20,
}}
>
<View style={{ flex: 1, flexDirection: "row" }}>
<Ionicons
color="white"
name="md-person"
style={{
alignSelf: "center",
fontSize: 25,
marginHorizontal: 20,
}}
/>
<Text
style={{
color: "white",
fontWeight: "400",
alignSelf: "center",
fontSize: 16,
}}
>
steem
<Text style={{ fontWeight: "800" }}>
connect
</Text>
</Text>
</View>
</TouchableOpacity>
</View>
</View>
</ScrollableTabView>
</View>
);
navigationButtonPressed({ buttonId }) {
if (buttonId === "signup") {
Linking.openURL("https://signup.steemit.com/?ref=esteem").catch(err =>
console.error("An error occurred", err)
);
}
}
loginwithSc2 = () => {
Navigation.push(this.props.componentId, {
component: {
name: "navigation.eSteem.SteemConnect",
passProps: {},
options: {
topBar: {
title: {
text: "Login via SC2",
},
},
},
},
});
};
render() {
return (
<View style={{ flex: 1 }}>
<StatusBar hidden translucent />
<LoginHeader
title="Sign in"
description="To get all the benefits using eSteem"
/>
<ScrollableTabView
style={styles.tabView}
renderTabBar={() => (
<TabBar
style={styles.tabbar}
tabUnderlineDefaultWidth={100} // default containerWidth / (numberOfTabs * 4)
tabUnderlineScaleX={2} // default 3
activeColor={"#357ce6"}
inactiveColor={"#222"}
/>
)}
>
<View tabLabel="Sign in" style={styles.tabbarItem}>
<FormInput
rightIconName="md-at"
leftIconName="md-close-circle"
isValid={this.state.isUsernameValid}
onChange={value => this.handleUsername(value)}
placeholder="Username"
isEditable
type="username"
isFirstImage
value={this.state.username}
/>
<FormInput
rightIconName="md-lock"
leftIconName="md-close-circle"
isValid={this.state.isUsernameValid}
onChange={value => this._handleOnPasswordChange(value)}
placeholder="Password or WIF"
isEditable
secureTextEntry
type="password"
/>
<InformationArea
description="User credentials are kept locally on the device. Credentials are
removed upon logout!"
iconName="ios-information-circle-outline"
/>
<View style={{ flexDirection: "row", margin: 30 }}>
<View style={{ flex: 0.6 }}>
<TouchableOpacity
onPress={goToAuthScreens}
style={{
alignContent: "center",
padding: "9%",
}}
>
<Text
style={{
color: "#788187",
alignSelf: "center",
fontWeight: "bold",
}}
>
Cancel
</Text>
</TouchableOpacity>
</View>
<TouchableOpacity
onPress={this._handleOnPressLogin}
style={{
flex: 0.4,
width: 100,
height: 50,
borderRadius: 30,
backgroundColor: "#357ce6",
flexDirection: "row",
}}
>
{!this.state.isLoading ? (
<View
style={{
flex: 1,
flexDirection: "row",
}}
>
<Ionicons
color="white"
name="md-person"
style={{
alignSelf: "center",
fontSize: 25,
flex: 0.4,
left: 15,
}}
/>
<Text
style={{
color: "white",
fontWeight: "600",
alignSelf: "center",
fontSize: 16,
flex: 0.6,
}}
>
LOGIN
</Text>
</View>
) : (
<ActivityIndicator
color="white"
style={{ alignSelf: "center", flex: 1 }}
/>
)}
</TouchableOpacity>
</View>
</View>
<View tabLabel="SteemConnect" style={styles.steemConnectTab}>
<InformationArea
description="If you don't want to keep your password encrypted and saved on your device, you can use Steemconnect."
iconName="ios-information-circle-outline"
/>
<View
style={{
alignItems: "flex-end",
backgroundColor: "#ffffff",
}}
>
<TouchableOpacity
onPress={this.loginwithSc2}
style={{
width: 200,
height: 50,
borderRadius: 30,
backgroundColor: "#357ce6",
flexDirection: "row",
margin: 20,
}}
>
<View style={{ flex: 1, flexDirection: "row" }}>
<Ionicons
color="white"
name="md-person"
style={{
alignSelf: "center",
fontSize: 25,
marginHorizontal: 20,
}}
/>
<Text
style={{
color: "white",
fontWeight: "400",
alignSelf: "center",
fontSize: 16,
}}
>
steem
<Text style={{ fontWeight: "800" }}>connect</Text>
</Text>
</View>
</TouchableOpacity>
</View>
</View>
</ScrollableTabView>
</View>
);
}
}
export default LoginScreen;

View File

@ -1,45 +1,44 @@
import EStyleSheet from "react-native-extended-stylesheet";
export default EStyleSheet.create({
container: {
margin: 0,
padding: 0,
backgroundColor: "#f1f1f1",
flexDirection: "column",
},
header: {
flexDirection: "row",
padding: 0,
backgroundColor: "white",
marginBottom: 10,
height: 200,
flex: 0.4,
},
footer: {
flex: 0.2,
bottom: 0,
marginTop: 10,
height: 80,
backgroundColor: "white",
flexDirection: "row",
},
tabView: {
alignSelf: "center",
backgroundColor: "transparent",
},
tabbar: {
alignSelf: "center",
height: 40,
backgroundColor: "white",
},
tabbarItem: {
flex: 1,
backgroundColor: "#ffffff",
minWidth: "$deviceWidth",
},
steemConnectTab: {
flex: 1,
backgroundColor: "#e9e9e9",
minWidth: "$deviceWidth",
},
container: {
margin: 0,
padding: 0,
backgroundColor: "#f1f1f1",
flexDirection: "column",
},
header: {
flexDirection: "row",
padding: 0,
backgroundColor: "white",
marginBottom: 10,
height: 200,
flex: 0.4,
},
footer: {
flex: 0.2,
bottom: 0,
marginTop: 10,
height: 80,
backgroundColor: "white",
flexDirection: "row",
},
tabView: {
alignSelf: "center",
backgroundColor: "transparent",
},
tabbar: {
alignSelf: "center",
height: 40,
backgroundColor: "white",
},
tabbarItem: {
flex: 1,
backgroundColor: "#ffffff",
minWidth: "$deviceWidth",
},
steemConnectTab: {
backgroundColor: "#fff",
minWidth: "$deviceWidth",
},
});