mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-21 12:21:31 +03:00
Merge pull request #1146 from esteemapp/feature/profile-edit
Feature/profile edit
This commit is contained in:
commit
43aacb970e
46
src/components/avatarHeader/avatarHeaderStyles.js
Normal file
46
src/components/avatarHeader/avatarHeaderStyles.js
Normal file
@ -0,0 +1,46 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
headerContainer: {
|
||||
height: 100,
|
||||
flexDirection: 'row',
|
||||
padding: 21,
|
||||
},
|
||||
backIcon: {
|
||||
color: '$white',
|
||||
},
|
||||
wrapper: {
|
||||
marginLeft: 16,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
textWrapper: {
|
||||
marginLeft: 16,
|
||||
},
|
||||
name: {
|
||||
color: '$white',
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
username: {
|
||||
color: '$white',
|
||||
fontSize: 12,
|
||||
marginTop: 4,
|
||||
},
|
||||
addIcon: {
|
||||
color: '$white',
|
||||
textAlign: 'center',
|
||||
},
|
||||
addButton: {
|
||||
backgroundColor: '$iconColor',
|
||||
width: 20,
|
||||
height: 20,
|
||||
borderRadius: 20 / 2,
|
||||
borderColor: '$white',
|
||||
borderWidth: 1,
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 45,
|
||||
},
|
||||
});
|
59
src/components/avatarHeader/avatarHeaderView.js
Normal file
59
src/components/avatarHeader/avatarHeaderView.js
Normal file
@ -0,0 +1,59 @@
|
||||
import React from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { View, Text } from 'react-native';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
|
||||
import { UserAvatar } from '../userAvatar';
|
||||
import { IconButton } from '../iconButton';
|
||||
|
||||
// Styles
|
||||
import styles from './avatarHeaderStyles';
|
||||
|
||||
const AvatarHeader = ({
|
||||
username,
|
||||
name,
|
||||
reputation,
|
||||
navigation,
|
||||
avatarUrl,
|
||||
showImageUploadActions,
|
||||
}) => (
|
||||
<LinearGradient
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 0 }}
|
||||
colors={['#357ce6', '#2d5aa0']}
|
||||
style={styles.headerView}
|
||||
>
|
||||
<View style={styles.headerContainer}>
|
||||
<IconButton
|
||||
iconStyle={styles.backIcon}
|
||||
iconType="MaterialIcons"
|
||||
name="arrow-back"
|
||||
onPress={navigation.goBack}
|
||||
size={25}
|
||||
/>
|
||||
<View style={styles.wrapper}>
|
||||
<UserAvatar
|
||||
key={avatarUrl || username}
|
||||
noAction
|
||||
size="xl"
|
||||
username={username}
|
||||
avatarUrl={avatarUrl}
|
||||
/>
|
||||
<IconButton
|
||||
iconStyle={styles.addIcon}
|
||||
style={styles.addButton}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name="plus"
|
||||
onPress={showImageUploadActions}
|
||||
size={15}
|
||||
/>
|
||||
<View style={styles.textWrapper}>
|
||||
{!!name && <Text style={styles.name}>{name}</Text>}
|
||||
<Text style={styles.username}>{`@${username} (${reputation})`}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</LinearGradient>
|
||||
);
|
||||
|
||||
export default withNavigation(AvatarHeader);
|
3
src/components/avatarHeader/index.js
Normal file
3
src/components/avatarHeader/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
import AvatarHeader from './avatarHeaderView';
|
||||
|
||||
export { AvatarHeader };
|
@ -100,7 +100,7 @@ class BasicHeaderView extends Component {
|
||||
<IconButton
|
||||
iconStyle={[styles.backIcon, isModalHeader && styles.closeIcon]}
|
||||
iconType="MaterialIcons"
|
||||
name={isModalHeader ? 'arrow-back' : 'arrow-back'}
|
||||
name="arrow-back"
|
||||
onPress={() => (isModalHeader ? handleOnPressClose() : handleOnPressBackButton())}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
@ -4,8 +4,7 @@ export default EStyleSheet.create({
|
||||
wrapper: {
|
||||
borderTopLeftRadius: 8,
|
||||
borderTopRightRadius: 8,
|
||||
marginHorizontal: 30,
|
||||
marginVertical: 10,
|
||||
marginTop: 16,
|
||||
flexDirection: 'row',
|
||||
backgroundColor: '$primaryGray',
|
||||
height: 60,
|
||||
@ -21,7 +20,6 @@ export default EStyleSheet.create({
|
||||
textInput: {
|
||||
flex: 0.7,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
icon: {
|
||||
flex: 0.15,
|
||||
|
@ -1,12 +1,11 @@
|
||||
import React, { Component } from 'react';
|
||||
import { View } from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import { Icon } from '../../icon';
|
||||
|
||||
// Constants
|
||||
|
||||
// Components
|
||||
import { TextInput } from '../../textInput';
|
||||
import { Icon } from '../../icon';
|
||||
|
||||
// Styles
|
||||
import styles from './formInputStyles';
|
||||
|
||||
@ -19,28 +18,18 @@ class FormInputView extends Component {
|
||||
* @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',
|
||||
value: props.value || '',
|
||||
inputBorderColor: '#e7e7e7',
|
||||
isValid: true,
|
||||
formInputWidth: '99%',
|
||||
};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
componentWillMount() {
|
||||
setTimeout(() => {
|
||||
this.setState({ formInputWidth: '100%' });
|
||||
}, 100);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { isValid } = this.props;
|
||||
|
||||
@ -54,18 +43,15 @@ class FormInputView extends Component {
|
||||
const { onChange } = this.props;
|
||||
|
||||
this.setState({ value });
|
||||
onChange && onChange(value);
|
||||
if (onChange) onChange(value);
|
||||
};
|
||||
|
||||
_handleOnFocus = () => {
|
||||
const { inputBorderColor } = this.state;
|
||||
if (inputBorderColor !== '#357ce6') {
|
||||
this.setState({ inputBorderColor: '#357ce6' });
|
||||
}
|
||||
this.setState({ inputBorderColor: '#357ce6' });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { inputBorderColor, isValid, value, formInputWidth } = this.state;
|
||||
const { inputBorderColor, isValid, value } = this.state;
|
||||
const {
|
||||
placeholder,
|
||||
type,
|
||||
@ -75,6 +61,9 @@ class FormInputView extends Component {
|
||||
rightIconName,
|
||||
secureTextEntry,
|
||||
iconType,
|
||||
wrapperStyle,
|
||||
height,
|
||||
inputStyle,
|
||||
} = this.props;
|
||||
return (
|
||||
<View
|
||||
@ -83,6 +72,7 @@ class FormInputView extends Component {
|
||||
{
|
||||
borderBottomColor: isValid ? inputBorderColor : 'red',
|
||||
},
|
||||
wrapperStyle,
|
||||
]}
|
||||
>
|
||||
{isFirstImage && value && value.length > 2 ? (
|
||||
@ -97,19 +87,23 @@ class FormInputView extends Component {
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<Icon iconType={iconType || 'MaterialIcons'} name={rightIconName} style={styles.icon} />
|
||||
rightIconName && (
|
||||
<Icon iconType={iconType || 'MaterialIcons'} name={rightIconName} style={styles.icon} />
|
||||
)
|
||||
)}
|
||||
<View style={styles.textInput}>
|
||||
<TextInput
|
||||
onFocus={() => this._handleOnFocus()}
|
||||
style={inputStyle}
|
||||
onFocus={() => this.setState({ inputBorderColor: '#357ce6' })}
|
||||
onBlur={() => this.setState({ inputBorderColor: '#e7e7e7' })}
|
||||
autoCapitalize="none"
|
||||
secureTextEntry={secureTextEntry}
|
||||
height={height}
|
||||
placeholder={placeholder}
|
||||
editable={isEditable || true}
|
||||
textContentType={type}
|
||||
onChangeText={val => this._handleOnChange(val)}
|
||||
onChangeText={this._handleOnChange}
|
||||
value={value}
|
||||
style={{ width: formInputWidth }}
|
||||
/>
|
||||
</View>
|
||||
|
||||
|
@ -1,12 +1,7 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
// Services and Actions
|
||||
|
||||
// Middleware
|
||||
|
||||
// Constants
|
||||
import { get, has } from 'lodash';
|
||||
|
||||
// Component
|
||||
import HeaderView from '../view/headerView';
|
||||
@ -30,7 +25,7 @@ class HeaderContainer extends PureComponent {
|
||||
_handleOpenDrawer = () => {
|
||||
const { navigation } = this.props;
|
||||
|
||||
if (navigation && navigation.openDrawer && typeof navigation.openDrawer === 'function') {
|
||||
if (has(navigation, 'openDrawer') && typeof get(navigation, 'openDrawer') === 'function') {
|
||||
navigation.openDrawer();
|
||||
}
|
||||
};
|
||||
@ -52,19 +47,11 @@ class HeaderContainer extends PureComponent {
|
||||
isLoginDone,
|
||||
isDarkTheme,
|
||||
} = this.props;
|
||||
let displayName;
|
||||
let username;
|
||||
let reputation;
|
||||
const _user = isReverse && selectedUser ? selectedUser : currentAccount;
|
||||
|
||||
if (isReverse && selectedUser) {
|
||||
displayName = selectedUser.display_name;
|
||||
username = selectedUser.name;
|
||||
reputation = selectedUser.reputation;
|
||||
} else if (!isReverse) {
|
||||
displayName = currentAccount.display_name;
|
||||
username = currentAccount.name;
|
||||
reputation = currentAccount.reputation;
|
||||
}
|
||||
const displayName = get(_user, 'display_name');
|
||||
const username = get(_user, 'name');
|
||||
const reputation = get(_user, 'reputation');
|
||||
|
||||
return (
|
||||
<HeaderView
|
||||
|
@ -34,19 +34,20 @@ class HeaderView extends Component {
|
||||
|
||||
render() {
|
||||
const {
|
||||
avatarUrl,
|
||||
displayName,
|
||||
handleOnPressBackButton,
|
||||
handleOpenDrawer,
|
||||
intl,
|
||||
isDarkTheme,
|
||||
isLoggedIn,
|
||||
isLoginDone,
|
||||
isReverse,
|
||||
reputation,
|
||||
username,
|
||||
isDarkTheme,
|
||||
} = this.props;
|
||||
const { isSearchModalOpen } = this.state;
|
||||
let gredientColor = isDarkTheme ? ['#081c36', '#43638e'] : ['#2d5aa0', '#357ce6'];
|
||||
let gredientColor;
|
||||
|
||||
if (isReverse) {
|
||||
gredientColor = isDarkTheme ? ['#43638e', '#081c36'] : ['#357ce6', '#2d5aa0'];
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { TouchableHighlight } from 'react-native';
|
||||
import { TouchableHighlight, ActivityIndicator } from 'react-native';
|
||||
import { Icon } from '../../icon';
|
||||
|
||||
import styles from './iconButtonStyles';
|
||||
@ -22,28 +22,33 @@ const IconButton = ({
|
||||
onPress,
|
||||
size,
|
||||
style,
|
||||
isLoading,
|
||||
}) => (
|
||||
<Fragment>
|
||||
<TouchableHighlight
|
||||
style={[styles.iconButton, style]}
|
||||
onPress={() => onPress && onPress()}
|
||||
onPress={() => !isLoading && onPress && onPress()}
|
||||
underlayColor={backgroundColor || 'white'}
|
||||
disabled={disabled}
|
||||
>
|
||||
<Icon
|
||||
style={[
|
||||
color && { color },
|
||||
backgroundColor && { backgroundColor },
|
||||
styles.icon,
|
||||
iconStyle && iconStyle,
|
||||
]}
|
||||
badgeTextStyle={badgeTextStyle}
|
||||
name={name}
|
||||
badgeStyle={badgeStyle}
|
||||
size={size}
|
||||
iconType={iconType}
|
||||
badgeCount={badgeCount}
|
||||
/>
|
||||
{!isLoading ? (
|
||||
<Icon
|
||||
style={[
|
||||
color && { color },
|
||||
backgroundColor && { backgroundColor },
|
||||
styles.icon,
|
||||
iconStyle && iconStyle,
|
||||
]}
|
||||
badgeTextStyle={badgeTextStyle}
|
||||
name={name}
|
||||
badgeStyle={badgeStyle}
|
||||
size={size}
|
||||
iconType={iconType}
|
||||
badgeCount={badgeCount}
|
||||
/>
|
||||
) : (
|
||||
<ActivityIndicator color="white" style={styles.activityIndicator} />
|
||||
)}
|
||||
</TouchableHighlight>
|
||||
</Fragment>
|
||||
);
|
||||
|
@ -3,15 +3,16 @@ import { FormInput } from './formInput';
|
||||
import { NumericKeyboard } from './numericKeyboard';
|
||||
import { PinAnimatedInput } from './pinAnimatedInput';
|
||||
import { SideMenu } from './sideMenu';
|
||||
import { TextInput } from './textInput';
|
||||
import Icon from './icon';
|
||||
import Logo from './logo/logo';
|
||||
import Modal from './modal';
|
||||
import { TextInput } from './textInput';
|
||||
import PostBoost from './postBoost/postBoostView';
|
||||
import PostButton from './postButton/postButtonView';
|
||||
import ProfileEditForm from './profileEditForm/profileEditFormView';
|
||||
import Promote from './promote/promoteView';
|
||||
import ScaleSlider from './scaleSlider/scaleSliderView';
|
||||
import UserListItem from './basicUIElements/view/userListItem/userListItem';
|
||||
import PostButton from './postButton/postButtonView';
|
||||
import Promote from './promote/promoteView';
|
||||
import PostBoost from './postBoost/postBoostView';
|
||||
|
||||
export {
|
||||
CircularButton,
|
||||
@ -22,12 +23,13 @@ export {
|
||||
Modal,
|
||||
NumericKeyboard,
|
||||
PinAnimatedInput,
|
||||
PostButton,
|
||||
ProfileEditForm,
|
||||
ScaleSlider,
|
||||
SideMenu,
|
||||
TextButton,
|
||||
TextInput,
|
||||
UserListItem,
|
||||
PostButton,
|
||||
Promote,
|
||||
PostBoost,
|
||||
};
|
||||
|
71
src/components/profileEditForm/profileEditFormStyles.js
Normal file
71
src/components/profileEditForm/profileEditFormStyles.js
Normal file
@ -0,0 +1,71 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
paddingHorizontal: 32,
|
||||
paddingVertical: 16,
|
||||
backgroundColor: '$primaryBackgroundColor',
|
||||
flex: 1,
|
||||
},
|
||||
formStyle: {
|
||||
backgroundColor: '$white',
|
||||
height: 30,
|
||||
marginTop: 8,
|
||||
},
|
||||
label: {
|
||||
fontSize: 14,
|
||||
color: '$primaryDarkText',
|
||||
fontWeight: '500',
|
||||
},
|
||||
formItem: {
|
||||
marginBottom: 24,
|
||||
},
|
||||
coverImg: {
|
||||
borderRadius: 5,
|
||||
height: 60,
|
||||
marginBottom: 12,
|
||||
alignSelf: 'stretch',
|
||||
backgroundColor: '#296CC0',
|
||||
},
|
||||
coverImageWrapper: {},
|
||||
addIcon: {
|
||||
color: '$white',
|
||||
textAlign: 'center',
|
||||
},
|
||||
addButton: {
|
||||
backgroundColor: '$iconColor',
|
||||
width: 20,
|
||||
height: 20,
|
||||
borderRadius: 20 / 2,
|
||||
borderColor: '$white',
|
||||
borderWidth: 1,
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
right: 10,
|
||||
},
|
||||
|
||||
saveButton: {
|
||||
backgroundColor: '$primaryBlue',
|
||||
width: 55,
|
||||
height: 55,
|
||||
borderRadius: 55 / 2,
|
||||
position: 'absolute',
|
||||
top: -25,
|
||||
right: 10,
|
||||
zIndex: 999,
|
||||
borderWidth: 2,
|
||||
borderColor: '$white',
|
||||
},
|
||||
saveIcon: {
|
||||
color: '$white',
|
||||
textAlign: 'center',
|
||||
},
|
||||
|
||||
input: {
|
||||
fontSize: 14,
|
||||
color: '$primaryDarkText',
|
||||
alignSelf: 'flex-start',
|
||||
width: '100%',
|
||||
height: 30,
|
||||
},
|
||||
});
|
88
src/components/profileEditForm/profileEditFormView.js
Normal file
88
src/components/profileEditForm/profileEditFormView.js
Normal file
@ -0,0 +1,88 @@
|
||||
import React from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { View, TouchableOpacity, Image, Text, Platform } from 'react-native';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
import { injectIntl } from 'react-intl';
|
||||
|
||||
// Images
|
||||
import LIGHT_COVER_IMAGE from '../../assets/default_cover_image.png';
|
||||
import DARK_COVER_IMAGE from '../../assets/dark_cover_image.png';
|
||||
|
||||
// Components
|
||||
import { FormInput } from '../formInput';
|
||||
import { IconButton } from '../iconButton';
|
||||
|
||||
// Utils
|
||||
import { getResizedImage } from '../../utils/image';
|
||||
|
||||
// Styles
|
||||
import styles from './profileEditFormStyles';
|
||||
|
||||
const ProfileEditFormView = ({
|
||||
avatarUrl,
|
||||
coverUrl,
|
||||
formData,
|
||||
handleOnItemChange,
|
||||
handleOnSubmit,
|
||||
intl,
|
||||
isDarkTheme,
|
||||
isLoading,
|
||||
showImageUploadActions,
|
||||
...props
|
||||
}) => (
|
||||
<View style={styles.container}>
|
||||
<IconButton
|
||||
iconStyle={styles.saveIcon}
|
||||
style={styles.saveButton}
|
||||
iconType="MaterialIcons"
|
||||
name="save"
|
||||
onPress={handleOnSubmit}
|
||||
size={30}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<KeyboardAwareScrollView
|
||||
enableAutoAutomaticScroll={Platform.OS === 'ios'}
|
||||
contentContainerStyle={{ flexGrow: 1 }}
|
||||
>
|
||||
<TouchableOpacity style={styles.coverImgWrapper} onPress={showImageUploadActions}>
|
||||
<Image
|
||||
style={styles.coverImg}
|
||||
source={{ uri: getResizedImage(coverUrl, 400) }}
|
||||
defaultSource={isDarkTheme ? DARK_COVER_IMAGE : LIGHT_COVER_IMAGE}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
iconStyle={styles.addIcon}
|
||||
style={styles.addButton}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name="plus"
|
||||
onPress={showImageUploadActions}
|
||||
size={15}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
|
||||
{formData.map(item => (
|
||||
<View style={styles.formItem} key={item.valueKey}>
|
||||
<Text style={styles.label}>
|
||||
{intl.formatMessage({
|
||||
id: `profile.edit.${item.label}`,
|
||||
})}
|
||||
</Text>
|
||||
<FormInput
|
||||
wrapperStyle={styles.formStyle}
|
||||
isValid
|
||||
height={30}
|
||||
onChange={value => handleOnItemChange(value, item.valueKey)}
|
||||
placeholder={item.placeholder}
|
||||
isEditable
|
||||
type="none"
|
||||
value={props[item.valueKey]}
|
||||
inputStyle={styles.input}
|
||||
/>
|
||||
</View>
|
||||
))}
|
||||
</KeyboardAwareScrollView>
|
||||
</View>
|
||||
);
|
||||
|
||||
export default injectIntl(withNavigation(ProfileEditFormView));
|
@ -21,6 +21,7 @@ import { DropdownButton } from '../../dropdownButton';
|
||||
|
||||
// Utils
|
||||
import { makeCountFriendly } from '../../../utils/formatter';
|
||||
import { getResizedImage } from '../../../utils/image';
|
||||
|
||||
// Styles
|
||||
import styles from './profileSummaryStyles';
|
||||
@ -67,6 +68,7 @@ class ProfileSummaryView extends PureComponent {
|
||||
handleFollowUnfollowUser,
|
||||
handleOnFavoritePress,
|
||||
handleOnFollowsPress,
|
||||
handleOnPressProfileEdit,
|
||||
handleUIChange,
|
||||
hoursRC,
|
||||
hoursVP,
|
||||
@ -94,7 +96,7 @@ class ProfileSummaryView extends PureComponent {
|
||||
const isColumn = rowLength && DEVICE_WIDTH / rowLength <= 7.3;
|
||||
|
||||
const followButtonIcon = !isFollowing ? 'account-plus' : 'account-minus';
|
||||
const coverImageUrl = `https://steemitimages.com/400x0/${coverImage}`;
|
||||
const coverImageUrl = getResizedImage(coverImage, 400);
|
||||
|
||||
dropdownOpions.push(!isMuted ? 'MUTE' : 'UNMUTE');
|
||||
|
||||
@ -184,7 +186,7 @@ class ProfileSummaryView extends PureComponent {
|
||||
</TouchableOpacity>
|
||||
</Fragment>
|
||||
</View>
|
||||
{isLoggedIn && !isOwnProfile && (
|
||||
{isLoggedIn && !isOwnProfile ? (
|
||||
<View style={styles.rightIcons}>
|
||||
<IconButton
|
||||
backgroundColor="transparent"
|
||||
@ -221,6 +223,19 @@ class ProfileSummaryView extends PureComponent {
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
) : (
|
||||
isOwnProfile && (
|
||||
<Fragment>
|
||||
<IconButton
|
||||
backgroundColor="transparent"
|
||||
color="#c1c5c7"
|
||||
iconType="MaterialCommunityIcons"
|
||||
name="pencil"
|
||||
onPress={handleOnPressProfileEdit}
|
||||
size={20}
|
||||
/>
|
||||
</Fragment>
|
||||
)
|
||||
)}
|
||||
</View>
|
||||
</Fragment>
|
||||
|
@ -5,9 +5,9 @@ import { connect } from 'react-redux';
|
||||
// Styles
|
||||
import styles from './textInputStyles';
|
||||
|
||||
const TextInputView = ({ isDarkTheme, innerRef, ...props }) => (
|
||||
const TextInputView = ({ isDarkTheme, innerRef, height, ...props }) => (
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
style={[styles.input, { minHeight: height }]}
|
||||
ref={innerRef}
|
||||
keyboardAppearance={isDarkTheme ? 'dark' : 'light'}
|
||||
{...props}
|
||||
|
@ -26,9 +26,12 @@ class UserAvatarView extends Component {
|
||||
|
||||
// Component Functions
|
||||
_handleOnAvatarPress = username => {
|
||||
const { dispatch, currentUsername } = this.props;
|
||||
const {
|
||||
dispatch,
|
||||
currentUsername: { name },
|
||||
} = this.props;
|
||||
|
||||
const routeName = currentUsername === username ? ROUTES.TABBAR.PROFILE : ROUTES.SCREENS.PROFILE;
|
||||
const routeName = name === username ? ROUTES.TABBAR.PROFILE : ROUTES.SCREENS.PROFILE;
|
||||
|
||||
const navigateAction = NavigationActions.navigate({
|
||||
routeName,
|
||||
@ -42,11 +45,25 @@ class UserAvatarView extends Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { username, size, style, disableSize, noAction } = this.props;
|
||||
const {
|
||||
username,
|
||||
size,
|
||||
style,
|
||||
disableSize,
|
||||
noAction,
|
||||
avatarUrl,
|
||||
currentUsername: { name, avatar },
|
||||
} = this.props;
|
||||
const imageSize = size === 'xl' ? 'large' : 'small';
|
||||
let _size;
|
||||
const _avatar = username
|
||||
? { uri: `https://steemitimages.com/u/${username}/avatar/${imageSize}` }
|
||||
? {
|
||||
uri:
|
||||
avatarUrl ||
|
||||
(name === username
|
||||
? avatar
|
||||
: `https://steemitimages.com/u/${username}/avatar/${imageSize}`),
|
||||
}
|
||||
: DEFAULT_IMAGE;
|
||||
|
||||
if (!disableSize) {
|
||||
@ -73,7 +90,7 @@ class UserAvatarView extends Component {
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
currentUsername: state.account.currentAccount.name,
|
||||
currentUsername: state.account.currentAccount,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(UserAvatarView);
|
||||
|
@ -97,7 +97,13 @@
|
||||
"days": "days",
|
||||
"day": "day",
|
||||
"steem_dollars": "Steem Dollars",
|
||||
"savings": "Savings"
|
||||
"savings": "Savings",
|
||||
"edit": {
|
||||
"display_name": "Display Name",
|
||||
"about": "About",
|
||||
"location": "Location",
|
||||
"website": "Website"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"settings": "Settings",
|
||||
|
@ -15,15 +15,15 @@ export default {
|
||||
LOGIN: `Login${SCREEN_SUFFIX}`,
|
||||
PINCODE: `PinCode${SCREEN_SUFFIX}`,
|
||||
POST: `Post${SCREEN_SUFFIX}`,
|
||||
PROFILE_EDIT: `ProfileEdit${SCREEN_SUFFIX}`,
|
||||
PROFILE: `Profile${SCREEN_SUFFIX}`,
|
||||
PROMOTE: `Promote${SCREEN_SUFFIX}`,
|
||||
REBLOGS: `Reblogs${SCREEN_SUFFIX}`,
|
||||
REDEEM: `Redeem${SCREEN_SUFFIX}`,
|
||||
SEARCH_RESULT: `SearchResult${SCREEN_SUFFIX}`,
|
||||
SETTINGS: `Settings${SCREEN_SUFFIX}`,
|
||||
STEEM_CONNECT: `SteemConnect${SCREEN_SUFFIX}`,
|
||||
TRANSFER: `Transfer${SCREEN_SUFFIX}`,
|
||||
VOTERS: `Voters${SCREEN_SUFFIX}`,
|
||||
REDEEM: `Redeem${SCREEN_SUFFIX}`,
|
||||
},
|
||||
DRAWER: {
|
||||
MAIN: `Main${DRAWER_SUFFIX}`,
|
||||
|
@ -1,6 +1,7 @@
|
||||
export const steemConnectOptions = {
|
||||
base_url: 'https://app.steemconnect.com/',
|
||||
client_id: 'esteemapp',
|
||||
redirect_uri: 'http://127.0.0.1:3415/', // http://127.0.0.1:3415
|
||||
scope: 'vote,comment,delete_comment,comment_options,custom_json,claim_reward_balance,offline',
|
||||
redirect_uri: 'http://127.0.0.1:3415/',
|
||||
scope:
|
||||
'vote,comment,delete_comment,comment_options,custom_json,claim_reward_balance,account_update,offline',
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
import PointsContainer from './pointsContainer';
|
||||
import TransferContainer from './transferContainer';
|
||||
import ProfileEditContainer from './profileEditContainer';
|
||||
import RedeemContainer from './redeemContainer';
|
||||
import TransferContainer from './transferContainer';
|
||||
|
||||
export { PointsContainer, TransferContainer, RedeemContainer };
|
||||
export { PointsContainer, ProfileEditContainer, RedeemContainer, TransferContainer };
|
||||
|
214
src/containers/profileEditContainer.js
Normal file
214
src/containers/profileEditContainer.js
Normal file
@ -0,0 +1,214 @@
|
||||
import { Component } from 'react';
|
||||
import { Alert } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import ImagePicker from 'react-native-image-crop-picker';
|
||||
import get from 'lodash/get';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
|
||||
import { uploadImage } from '../providers/esteem/esteem';
|
||||
|
||||
import { profileUpdate } from '../providers/steem/dsteem';
|
||||
import { updateCurrentAccount } from '../redux/actions/accountAction';
|
||||
|
||||
// import ROUTES from '../constants/routeNames';
|
||||
|
||||
const FORM_DATA = [
|
||||
{
|
||||
valueKey: 'name',
|
||||
type: 'text',
|
||||
label: 'display_name',
|
||||
placeholder: '',
|
||||
},
|
||||
{
|
||||
valueKey: 'about',
|
||||
type: 'text',
|
||||
label: 'about',
|
||||
placeholder: '',
|
||||
},
|
||||
{
|
||||
valueKey: 'location',
|
||||
type: 'text',
|
||||
label: 'location',
|
||||
placeholder: '',
|
||||
},
|
||||
{
|
||||
valueKey: 'website',
|
||||
type: 'text',
|
||||
label: 'website',
|
||||
placeholder: '',
|
||||
},
|
||||
];
|
||||
|
||||
class ProfileEditContainer extends Component {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isLoading: false,
|
||||
about: get(props.currentAccount, 'about.profile.about'),
|
||||
name: get(props.currentAccount, 'about.profile.name'),
|
||||
location: get(props.currentAccount, 'about.profile.location'),
|
||||
website: get(props.currentAccount, 'about.profile.website'),
|
||||
coverUrl: get(props.currentAccount, 'about.profile.cover_image'),
|
||||
avatarUrl: get(props.currentAccount, 'avatar'),
|
||||
};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
|
||||
_handleOnItemChange = (val, item) => {
|
||||
this.setState({ [item]: val });
|
||||
};
|
||||
|
||||
_uploadImage = (media, action) => {
|
||||
const { intl } = this.props;
|
||||
|
||||
this.setState({ isLoading: true });
|
||||
uploadImage(media)
|
||||
.then(res => {
|
||||
if (res.data && res.data.url) {
|
||||
this.setState({ [action]: res.data.url, isLoading: false });
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (error) {
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
id: 'alert.fail',
|
||||
}),
|
||||
error.message || error.toString(),
|
||||
);
|
||||
}
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
};
|
||||
|
||||
_handleMediaAction = (type, uploadAction) => {
|
||||
if (type === 'camera') {
|
||||
this._handleOpenCamera(uploadAction);
|
||||
} else if (type === 'image') {
|
||||
this._handleOpenImagePicker(uploadAction);
|
||||
}
|
||||
};
|
||||
|
||||
_handleOpenImagePicker = action => {
|
||||
ImagePicker.openPicker({
|
||||
includeBase64: true,
|
||||
})
|
||||
.then(image => {
|
||||
this._handleMediaOnSelected(image, action);
|
||||
})
|
||||
.catch(e => {
|
||||
this._handleMediaOnSelectFailure(e);
|
||||
});
|
||||
};
|
||||
|
||||
_handleOpenCamera = action => {
|
||||
ImagePicker.openCamera({
|
||||
includeBase64: true,
|
||||
})
|
||||
.then(image => {
|
||||
this._handleMediaOnSelected(image, action);
|
||||
})
|
||||
.catch(e => {
|
||||
this._handleMediaOnSelectFailure(e);
|
||||
});
|
||||
};
|
||||
|
||||
_handleMediaOnSelected = (media, action) => {
|
||||
this.setState({ isLoading: true }, () => {
|
||||
this._uploadImage(media, action);
|
||||
});
|
||||
};
|
||||
|
||||
_handleMediaOnSelectFailure = error => {
|
||||
const { intl } = this.props;
|
||||
|
||||
if (get(error, 'code') === 'E_PERMISSION_MISSING') {
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
id: 'alert.permission_denied',
|
||||
}),
|
||||
intl.formatMessage({
|
||||
id: 'alert.permission_text',
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
_handleOnSubmit = async () => {
|
||||
const { currentAccount, pinCode, dispatch, navigation, intl } = this.props;
|
||||
const { name, location, website, about, coverUrl, avatarUrl } = this.state;
|
||||
|
||||
await this.setState({ isLoading: true });
|
||||
|
||||
const params = {
|
||||
profile_image: avatarUrl,
|
||||
cover_image: coverUrl,
|
||||
name,
|
||||
website,
|
||||
about,
|
||||
location,
|
||||
};
|
||||
|
||||
await profileUpdate(params, pinCode, currentAccount)
|
||||
.then(async () => {
|
||||
const _currentAccount = { ...currentAccount, display_name: name, avatar: avatarUrl };
|
||||
_currentAccount.about.profile = { ...params };
|
||||
|
||||
dispatch(updateCurrentAccount(_currentAccount));
|
||||
|
||||
navigation.state.params.fetchUser();
|
||||
navigation.goBack();
|
||||
})
|
||||
.catch(error => {
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
id: 'alert.fail',
|
||||
}),
|
||||
get(error, 'message', error.toString()),
|
||||
);
|
||||
});
|
||||
|
||||
this.setState({ isLoading: false });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { children, currentAccount, isDarkTheme } = this.props;
|
||||
const { isLoading, name, location, website, about, coverUrl, avatarUrl } = this.state;
|
||||
|
||||
return (
|
||||
children &&
|
||||
children({
|
||||
about,
|
||||
avatarUrl,
|
||||
coverUrl,
|
||||
currentAccount,
|
||||
formData: FORM_DATA,
|
||||
handleMediaAction: this._handleMediaAction,
|
||||
handleOnItemChange: this._handleOnItemChange,
|
||||
handleOnSubmit: this._handleOnSubmit,
|
||||
isDarkTheme,
|
||||
isLoading,
|
||||
location,
|
||||
name,
|
||||
website,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
currentAccount: state.account.currentAccount,
|
||||
isDarkTheme: state.application.isDarkTheme,
|
||||
pinCode: state.application.pin,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(injectIntl(withNavigation(ProfileEditContainer)));
|
@ -18,6 +18,7 @@ import {
|
||||
PinCode,
|
||||
Post,
|
||||
Profile,
|
||||
ProfileEdit,
|
||||
Reblogs,
|
||||
Redeem,
|
||||
SearchResult,
|
||||
@ -55,6 +56,12 @@ const stackNavigatior = createStackNavigator(
|
||||
header: () => null,
|
||||
},
|
||||
},
|
||||
[ROUTES.SCREENS.PROFILE_EDIT]: {
|
||||
screen: ProfileEdit,
|
||||
navigationOptions: {
|
||||
header: () => null,
|
||||
},
|
||||
},
|
||||
[ROUTES.SCREENS.POST]: {
|
||||
screen: Post,
|
||||
navigationOptions: {
|
||||
|
@ -300,7 +300,14 @@ export const getImages = username => api.get(`api/images/${username}`).then(resp
|
||||
|
||||
export const addMyImage = (user, url) => api.post('/image', { username: user, image_url: url });
|
||||
|
||||
export const uploadImage = file => {
|
||||
export const uploadImage = media => {
|
||||
const file = {
|
||||
uri: media.path,
|
||||
type: media.mime,
|
||||
name: media.filename || `IMG_${Math.random()}.JPG`,
|
||||
size: media.size,
|
||||
};
|
||||
|
||||
const fData = new FormData();
|
||||
fData.append('postimage', file);
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable camelcase */
|
||||
import { Client, PrivateKey } from 'dsteem';
|
||||
import steemconnect from 'steemconnect';
|
||||
import Config from 'react-native-config';
|
||||
@ -1167,6 +1168,63 @@ export const boost = (currentAccount, pinCode, point, permlink, author) => {
|
||||
return Promise.reject(new Error('Something went wrong!'));
|
||||
};
|
||||
|
||||
export const profileUpdate = async (params, pin, currentAccount) => {
|
||||
const digitPinCode = getDigitPinCode(pin);
|
||||
const key = getActiveKey(get(currentAccount, 'local'), digitPinCode);
|
||||
|
||||
if (get(currentAccount, 'local.authType') === AUTH_TYPE.STEEM_CONNECT) {
|
||||
const token = decryptKey(get(currentAccount, 'local.accessToken'), digitPinCode);
|
||||
const api = new steemconnect.Client({
|
||||
accessToken: token,
|
||||
});
|
||||
|
||||
const _params = {
|
||||
account: get(currentAccount, 'name'),
|
||||
memo_key: get(currentAccount, 'memo_key'),
|
||||
json_metadata: jsonStringify(params),
|
||||
};
|
||||
|
||||
const opArray = [['account_update', _params]];
|
||||
|
||||
return api
|
||||
.broadcast(opArray)
|
||||
.then(resp => resp.result)
|
||||
.catch(error => console.log(error));
|
||||
}
|
||||
|
||||
if (key) {
|
||||
const opArray = [
|
||||
[
|
||||
'account_update',
|
||||
{
|
||||
account: get(currentAccount, 'name'),
|
||||
memo_key: get(currentAccount, 'memo_key'),
|
||||
json_metadata: jsonStringify({ profile: params }),
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
const privateKey = PrivateKey.fromString(key);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
client.broadcast
|
||||
.sendOperations(opArray, privateKey)
|
||||
.then(result => {
|
||||
resolve(result);
|
||||
})
|
||||
.catch(error => {
|
||||
if (get(error, 'jse_info.code') === 4030100) {
|
||||
error.message =
|
||||
'We noticed that your device has incorrect date or time. Please fix Date & Time or Set Automatically and try again.';
|
||||
}
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new Error('You dont have permission!'));
|
||||
};
|
||||
|
||||
// HELPERS
|
||||
|
||||
const getAnyPrivateKey = (local, pin) => {
|
||||
|
@ -487,13 +487,6 @@ class ApplicationContainer extends Component {
|
||||
const isExistUser = await getExistUser();
|
||||
|
||||
realmObject[0].name = currentUsername;
|
||||
dispatch(
|
||||
updateCurrentAccount({
|
||||
name: realmObject[0].username,
|
||||
avatar: realmObject[0].avatar,
|
||||
authType: realmObject[0].authType,
|
||||
}),
|
||||
);
|
||||
// If in dev mode pin code does not show
|
||||
if ((!isExistUser || !pinCode) && _isPinCodeOpen) {
|
||||
dispatch(openPinCodeModal());
|
||||
|
@ -42,7 +42,6 @@ class EditorContainer extends Component {
|
||||
autoFocusText: false,
|
||||
draftId: null,
|
||||
draftPost: null,
|
||||
isCameraOrPickerOpen: false,
|
||||
isDraftSaved: false,
|
||||
isDraftSaving: false,
|
||||
isEdit: false,
|
||||
@ -141,8 +140,6 @@ class EditorContainer extends Component {
|
||||
};
|
||||
|
||||
_handleRoutingAction = routingAction => {
|
||||
this.setState({ isCameraOrPickerOpen: true });
|
||||
|
||||
if (routingAction === 'camera') {
|
||||
this._handleOpenCamera();
|
||||
} else if (routingAction === 'image') {
|
||||
@ -175,7 +172,7 @@ class EditorContainer extends Component {
|
||||
};
|
||||
|
||||
_handleMediaOnSelected = media => {
|
||||
this.setState({ isCameraOrPickerOpen: false, isUploading: true }, () => {
|
||||
this.setState({ isUploading: true }, () => {
|
||||
this._uploadImage(media);
|
||||
});
|
||||
// For new image api
|
||||
@ -189,33 +186,27 @@ class EditorContainer extends Component {
|
||||
_uploadImage = media => {
|
||||
const { intl } = this.props;
|
||||
|
||||
const file = {
|
||||
uri: media.path,
|
||||
type: media.mime,
|
||||
name: media.filename || `IMG_${Math.random()}.JPG`,
|
||||
size: media.size,
|
||||
};
|
||||
|
||||
uploadImage(file)
|
||||
uploadImage(media)
|
||||
.then(res => {
|
||||
if (res.data && res.data.url) {
|
||||
this.setState({ uploadedImage: res.data, isUploading: false });
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
id: 'alert.fail',
|
||||
}),
|
||||
error.message || error.toString(),
|
||||
);
|
||||
if (error) {
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
id: 'alert.fail',
|
||||
}),
|
||||
error.message || error.toString(),
|
||||
);
|
||||
}
|
||||
this.setState({ isUploading: false });
|
||||
});
|
||||
};
|
||||
|
||||
_handleMediaOnSelectFailure = error => {
|
||||
const { intl } = this.props;
|
||||
this.setState({ isCameraOrPickerOpen: false });
|
||||
|
||||
if (get(error, 'code') === 'E_PERMISSION_MISSING') {
|
||||
Alert.alert(
|
||||
@ -567,7 +558,6 @@ class EditorContainer extends Component {
|
||||
const {
|
||||
autoFocusText,
|
||||
draftPost,
|
||||
isCameraOrPickerOpen,
|
||||
isDraftSaved,
|
||||
isDraftSaving,
|
||||
isEdit,
|
||||
@ -589,7 +579,6 @@ class EditorContainer extends Component {
|
||||
handleOnImagePicker={this._handleRoutingAction}
|
||||
handleOnSubmit={this._handleSubmit}
|
||||
initialEditor={this._initialEditor}
|
||||
isCameraOrPickerOpen={isCameraOrPickerOpen}
|
||||
isDarkTheme={isDarkTheme}
|
||||
isDraftSaved={isDraftSaved}
|
||||
isDraftSaving={isDraftSaving}
|
||||
|
@ -23,8 +23,6 @@ class HomeScreen extends PureComponent {
|
||||
render() {
|
||||
const { currentAccount, intl, isLoggedIn } = this.props;
|
||||
|
||||
let tag;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Header />
|
||||
@ -50,7 +48,7 @@ class HomeScreen extends PureComponent {
|
||||
<Posts
|
||||
filterOptions={PROFILE_FILTERS}
|
||||
getFor={PROFILE_FILTERS[1].toLowerCase()}
|
||||
tag={tag || currentAccount.name}
|
||||
tag={currentAccount.name}
|
||||
selectedOptionIndex={1}
|
||||
/>
|
||||
</View>
|
||||
|
@ -14,16 +14,15 @@ import { Profile } from './profile';
|
||||
import { SearchResult } from './searchResult';
|
||||
import { Settings } from './settings';
|
||||
import Voters from './voters';
|
||||
import BoostPost from './boostPost/screen/boostPostScreen';
|
||||
import SteemConnect from './steem-connect/steemConnect';
|
||||
import Transfer from './transfer';
|
||||
import Reblogs from './reblogs';
|
||||
import ProfileEdit from './profileEdit/screen/profileEditScreen';
|
||||
import Redeem from './redeem/screen/redeemScreen';
|
||||
|
||||
export {
|
||||
Bookmarks,
|
||||
Boost,
|
||||
BoostPost,
|
||||
Drafts,
|
||||
Editor,
|
||||
Follows,
|
||||
@ -35,11 +34,12 @@ export {
|
||||
Points,
|
||||
Post,
|
||||
Profile,
|
||||
ProfileEdit,
|
||||
Reblogs,
|
||||
SearchResult,
|
||||
Settings,
|
||||
SteemConnect,
|
||||
Transfer,
|
||||
Voters,
|
||||
Reblogs,
|
||||
Redeem,
|
||||
};
|
||||
|
@ -102,7 +102,7 @@ class LoginScreen extends PureComponent {
|
||||
onKeyboardWillShow={() => this.setState({ keyboardIsOpen: true })}
|
||||
onKeyboardWillHide={() => this.setState({ keyboardIsOpen: false })}
|
||||
enableAutoAutomaticScroll={Platform.OS === 'ios'}
|
||||
contentContainerStyle={{ flexGrow: 1 }}
|
||||
contentContainerStyle={styles.formWrapper}
|
||||
>
|
||||
<FormInput
|
||||
rightIconName="at"
|
||||
|
@ -34,4 +34,9 @@ export default EStyleSheet.create({
|
||||
cancelButton: {
|
||||
marginRight: 10,
|
||||
},
|
||||
formWrapper: {
|
||||
flexGrow: 1,
|
||||
marginHorizontal: 30,
|
||||
marginVertical: 10,
|
||||
},
|
||||
});
|
||||
|
@ -343,6 +343,17 @@ class ProfileContainer extends Component {
|
||||
this.setState({ forceLoadPost: value });
|
||||
};
|
||||
|
||||
_handleOnPressProfileEdit = () => {
|
||||
const { navigation, currentAccount } = this.props;
|
||||
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.PROFILE_EDIT,
|
||||
params: {
|
||||
fetchUser: () => this.setState({ user: currentAccount }),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
avatar,
|
||||
@ -368,16 +379,19 @@ class ProfileContainer extends Component {
|
||||
about={get(user, 'about.profile')}
|
||||
activePage={activePage}
|
||||
avatar={avatar}
|
||||
changeForceLoadPostState={this._changeForceLoadPostState}
|
||||
comments={comments}
|
||||
currency={currency}
|
||||
error={error}
|
||||
follows={follows}
|
||||
forceLoadPost={forceLoadPost}
|
||||
getReplies={() => this._getReplies(username)}
|
||||
handleFollowUnfollowUser={this._handleFollowUnfollowUser}
|
||||
handleMuteUnmuteUser={this._handleMuteUnmuteUser}
|
||||
handleOnBackPress={this._handleOnBackPress}
|
||||
handleOnFavoritePress={this._handleOnFavoritePress}
|
||||
handleOnFollowsPress={this._handleFollowsPress}
|
||||
handleOnPressProfileEdit={this._handleOnPressProfileEdit}
|
||||
isDarkTheme={isDarkTheme}
|
||||
isFavorite={isFavorite}
|
||||
isFollowing={isFollowing}
|
||||
@ -389,8 +403,6 @@ class ProfileContainer extends Component {
|
||||
selectedQuickProfile={selectedQuickProfile}
|
||||
selectedUser={user}
|
||||
username={username}
|
||||
forceLoadPost={forceLoadPost}
|
||||
changeForceLoadPostState={this._changeForceLoadPostState}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -62,15 +62,19 @@ class ProfileScreen extends PureComponent {
|
||||
render() {
|
||||
const {
|
||||
about,
|
||||
activePage,
|
||||
changeForceLoadPostState,
|
||||
comments,
|
||||
currency,
|
||||
follows,
|
||||
forceLoadPost,
|
||||
getReplies,
|
||||
handleFollowUnfollowUser,
|
||||
handleMuteUnmuteUser,
|
||||
handleOnBackPress,
|
||||
handleOnFavoritePress,
|
||||
handleOnFollowsPress,
|
||||
handleOnPressProfileEdit,
|
||||
intl,
|
||||
isDarkTheme,
|
||||
isFavorite,
|
||||
@ -83,9 +87,6 @@ class ProfileScreen extends PureComponent {
|
||||
selectedQuickProfile,
|
||||
selectedUser,
|
||||
username,
|
||||
activePage,
|
||||
forceLoadPost,
|
||||
changeForceLoadPostState,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
@ -175,6 +176,7 @@ class ProfileScreen extends PureComponent {
|
||||
location={location}
|
||||
percentRC={resourceCredits}
|
||||
percentVP={votingPower}
|
||||
handleOnPressProfileEdit={handleOnPressProfileEdit}
|
||||
/>
|
||||
</CollapsibleCard>
|
||||
)}
|
||||
|
104
src/screens/profileEdit/screen/profileEditScreen.js
Normal file
104
src/screens/profileEdit/screen/profileEditScreen.js
Normal file
@ -0,0 +1,104 @@
|
||||
import React, { PureComponent, Fragment } from 'react';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import get from 'lodash/get';
|
||||
import ActionSheet from 'react-native-actionsheet';
|
||||
|
||||
import { ProfileEditContainer } from '../../../containers';
|
||||
|
||||
import AvatarHeader from '../../../components/avatarHeader/avatarHeaderView';
|
||||
import ProfileEditForm from '../../../components/profileEditForm/profileEditFormView';
|
||||
|
||||
class ProfileEditScreen extends PureComponent {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
selectedUploadAction: '',
|
||||
};
|
||||
|
||||
this.galleryRef = React.createRef();
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
_showImageUploadActions = async action => {
|
||||
await this.setState({ selectedUploadAction: action });
|
||||
this.galleryRef.current.show();
|
||||
};
|
||||
|
||||
render() {
|
||||
const { intl } = this.props;
|
||||
const { selectedUploadAction } = this.state;
|
||||
|
||||
return (
|
||||
<ProfileEditContainer>
|
||||
{({
|
||||
currentAccount,
|
||||
isDarkTheme,
|
||||
formData,
|
||||
handleOnItemChange,
|
||||
handleMediaAction,
|
||||
name,
|
||||
location,
|
||||
website,
|
||||
about,
|
||||
avatarUrl,
|
||||
coverUrl,
|
||||
isLoading,
|
||||
handleOnSubmit,
|
||||
}) => (
|
||||
<Fragment>
|
||||
<AvatarHeader
|
||||
username={get(currentAccount, 'name')}
|
||||
name={name}
|
||||
reputation={get(currentAccount, 'reputation')}
|
||||
avatarUrl={avatarUrl}
|
||||
showImageUploadActions={() => this._showImageUploadActions('avatarUrl')}
|
||||
/>
|
||||
<ProfileEditForm
|
||||
formData={formData}
|
||||
isDarkTheme={isDarkTheme}
|
||||
about={about}
|
||||
name={name}
|
||||
location={location}
|
||||
website={website}
|
||||
coverUrl={coverUrl}
|
||||
showImageUploadActions={() => this._showImageUploadActions('coverUrl')}
|
||||
handleOnItemChange={handleOnItemChange}
|
||||
isLoading={isLoading}
|
||||
handleOnSubmit={handleOnSubmit}
|
||||
/>
|
||||
<ActionSheet
|
||||
ref={this.galleryRef}
|
||||
options={[
|
||||
intl.formatMessage({
|
||||
id: 'editor.open_gallery',
|
||||
}),
|
||||
intl.formatMessage({
|
||||
id: 'editor.capture_photo',
|
||||
}),
|
||||
intl.formatMessage({
|
||||
id: 'alert.cancel',
|
||||
}),
|
||||
]}
|
||||
cancelButtonIndex={2}
|
||||
onPress={index => {
|
||||
handleMediaAction(
|
||||
index === 0 ? 'image' : index === 1 && 'camera',
|
||||
selectedUploadAction,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</ProfileEditContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(ProfileEditScreen);
|
@ -84,15 +84,6 @@ class SettingsScreen extends PureComponent {
|
||||
})}
|
||||
titleStyle={styles.cardTitle}
|
||||
/>
|
||||
<SettingsItem
|
||||
title={intl.formatMessage({
|
||||
id: 'settings.dark_theme',
|
||||
})}
|
||||
type="toggle"
|
||||
actionType="theme"
|
||||
isOn={isDarkTheme}
|
||||
handleOnChange={handleOnChange}
|
||||
/>
|
||||
<SettingsItem
|
||||
title={intl.formatMessage({
|
||||
id: 'settings.currency',
|
||||
@ -143,6 +134,15 @@ class SettingsScreen extends PureComponent {
|
||||
selectedOptionIndex={parseInt(nsfw, 10)}
|
||||
handleOnChange={handleOnChange}
|
||||
/>
|
||||
<SettingsItem
|
||||
title={intl.formatMessage({
|
||||
id: 'settings.dark_theme',
|
||||
})}
|
||||
type="toggle"
|
||||
actionType="theme"
|
||||
isOn={isDarkTheme}
|
||||
handleOnChange={handleOnChange}
|
||||
/>
|
||||
{!!isLoggedIn && (
|
||||
<SettingsItem
|
||||
title={intl.formatMessage({
|
||||
|
@ -1,6 +0,0 @@
|
||||
export const steemConnectOptions = {
|
||||
base_url: 'https://steemconnect.com/oauth2/authorize',
|
||||
client_id: 'esteem-app',
|
||||
redirect_uri: 'http://127.0.0.1:3415/', // http://127.0.0.1:3415
|
||||
scope: 'vote,comment,delete_comment,comment_options,custom_json,claim_reward_balance,offline',
|
||||
};
|
@ -5,7 +5,7 @@ import { injectIntl } from 'react-intl';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
|
||||
import { loginWithSC2 } from '../../providers/steem/auth';
|
||||
import { steemConnectOptions } from './config';
|
||||
import { steemConnectOptions } from '../../constants/steemConnectOptions';
|
||||
|
||||
// Actions
|
||||
import { addOtherAccount, updateCurrentAccount } from '../../redux/actions/accountAction';
|
||||
@ -79,7 +79,7 @@ class SteemConnect extends PureComponent {
|
||||
<View style={{ flex: 1 }}>
|
||||
<WebView
|
||||
source={{
|
||||
uri: `${steemConnectOptions.base_url}?client_id=${
|
||||
uri: `${steemConnectOptions.base_url}oauth2/authorize?client_id=${
|
||||
steemConnectOptions.client_id
|
||||
}&redirect_uri=${encodeURIComponent(
|
||||
steemConnectOptions.redirect_uri,
|
||||
|
@ -63,3 +63,12 @@ export const catchDraftImage = body => {
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const getResizedImage = (url, size) => {
|
||||
if (!url) return '';
|
||||
const _size = size || 400;
|
||||
|
||||
if (url.includes('img.esteem')) return `https://img.esteem.ws/${_size}x0/${url}`;
|
||||
|
||||
return `https://steemitimages.com/${size}x0/${url}`;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user