mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-19 19:31:54 +03:00
Merge pull request #1973 from ecency/nt/avatar-update-bug
Nt/avatar update bug
This commit is contained in:
commit
9a117c5e85
@ -2,9 +2,11 @@ import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
headerContainer: {
|
||||
height: 100,
|
||||
flexDirection: 'row',
|
||||
padding: 21,
|
||||
paddingTop: 8,
|
||||
paddingHorizontal: 24,
|
||||
paddingBottom: 24,
|
||||
alignItems: 'center',
|
||||
},
|
||||
backIcon: {
|
||||
color: '$white',
|
||||
@ -16,7 +18,7 @@ export default EStyleSheet.create({
|
||||
alignItems: 'center',
|
||||
},
|
||||
textWrapper: {
|
||||
marginLeft: 16,
|
||||
marginLeft: 24,
|
||||
},
|
||||
name: {
|
||||
color: '$white',
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { View, Text, SafeAreaView } from 'react-native';
|
||||
import { View, Text, SafeAreaView, TouchableOpacity } from 'react-native';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
|
||||
import { UserAvatar } from '../userAvatar';
|
||||
@ -16,6 +16,7 @@ const AvatarHeader = ({
|
||||
navigation,
|
||||
avatarUrl,
|
||||
showImageUploadActions,
|
||||
isUploading,
|
||||
}) => (
|
||||
<LinearGradient
|
||||
start={{ x: 0, y: 0 }}
|
||||
@ -33,15 +34,25 @@ const AvatarHeader = ({
|
||||
size={25}
|
||||
/>
|
||||
<View style={styles.wrapper}>
|
||||
<UserAvatar key={avatarUrl || username} noAction size="xl" username={username} />
|
||||
<IconButton
|
||||
iconStyle={styles.addIcon}
|
||||
style={styles.addButton}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name="plus"
|
||||
onPress={showImageUploadActions}
|
||||
size={15}
|
||||
/>
|
||||
<TouchableOpacity onPress={showImageUploadActions}>
|
||||
<UserAvatar
|
||||
key={`${avatarUrl}-${username}`}
|
||||
noAction
|
||||
size="xl"
|
||||
username={username}
|
||||
avatarUrl={avatarUrl}
|
||||
isLoading={isUploading}
|
||||
/>
|
||||
<IconButton
|
||||
iconStyle={styles.addIcon}
|
||||
style={styles.addButton}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name="plus"
|
||||
onPress={showImageUploadActions}
|
||||
size={15}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.textWrapper}>
|
||||
{!!name && <Text style={styles.name}>{name}</Text>}
|
||||
<Text style={styles.username}>{`@${username} (${reputation})`}</Text>
|
||||
|
@ -13,6 +13,7 @@ export default EStyleSheet.create({
|
||||
marginTop: 8,
|
||||
},
|
||||
label: {
|
||||
marginTop:8,
|
||||
fontSize: 14,
|
||||
color: '$primaryDarkText',
|
||||
fontWeight: '500',
|
||||
@ -25,7 +26,7 @@ export default EStyleSheet.create({
|
||||
height: 60,
|
||||
marginBottom: 12,
|
||||
alignSelf: 'stretch',
|
||||
backgroundColor: '#296CC0',
|
||||
backgroundColor: '$primaryGray',
|
||||
},
|
||||
coverImageWrapper: {},
|
||||
addIcon: {
|
||||
@ -62,13 +63,19 @@ export default EStyleSheet.create({
|
||||
},
|
||||
|
||||
input: {
|
||||
fontSize: 14,
|
||||
color: '$primaryDarkText',
|
||||
fontSize: 20,
|
||||
color: '$primaryBlack',
|
||||
alignSelf: 'flex-start',
|
||||
width: '100%',
|
||||
height: 40,
|
||||
paddingBottom:10,
|
||||
},
|
||||
contentContainer: {
|
||||
flexGrow: 1,
|
||||
},
|
||||
activityIndicator: {
|
||||
position:'absolute',
|
||||
alignSelf:'center',
|
||||
top:0,
|
||||
bottom:8
|
||||
}
|
||||
});
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { View, TouchableOpacity, Image, Text, Platform } from 'react-native';
|
||||
import { View, TouchableOpacity, Text, Platform, ActivityIndicator } from 'react-native';
|
||||
import { View as AnimatedView } from 'react-native-animatable';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
import { injectIntl } from 'react-intl';
|
||||
|
||||
@ -17,9 +18,25 @@ import { getResizedImage } from '../../utils/image';
|
||||
|
||||
// Styles
|
||||
import styles from './profileEditFormStyles';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
import { MainButton } from '../mainButton';
|
||||
|
||||
|
||||
interface ProfileEditFormProps {
|
||||
coverUrl:string;
|
||||
formData:any;
|
||||
handleOnItemChange:()=>void;
|
||||
handleOnSubmit:()=>void;
|
||||
intl:any,
|
||||
isDarkTheme:boolean,
|
||||
isLoading:boolean,
|
||||
isUploading:boolean,
|
||||
showImageUploadActions:boolean,
|
||||
saveEnabled:boolean,
|
||||
}
|
||||
|
||||
const ProfileEditFormView = ({
|
||||
avatarUrl,
|
||||
coverUrl,
|
||||
formData,
|
||||
handleOnItemChange,
|
||||
@ -27,30 +44,41 @@ const ProfileEditFormView = ({
|
||||
intl,
|
||||
isDarkTheme,
|
||||
isLoading,
|
||||
isUploading,
|
||||
showImageUploadActions,
|
||||
saveEnabled,
|
||||
...props
|
||||
}) => (
|
||||
}:ProfileEditFormProps) => (
|
||||
|
||||
<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={styles.contentContainer}
|
||||
enableOnAndroid={true}
|
||||
>
|
||||
<TouchableOpacity style={styles.coverImgWrapper} onPress={showImageUploadActions}>
|
||||
<Image
|
||||
style={styles.coverImg}
|
||||
source={{ uri: getResizedImage(coverUrl, 600) }}
|
||||
defaultSource={isDarkTheme ? DARK_COVER_IMAGE : LIGHT_COVER_IMAGE}
|
||||
/>
|
||||
|
||||
<FastImage
|
||||
style={styles.coverImg}
|
||||
source={
|
||||
coverUrl
|
||||
? { uri: getResizedImage(coverUrl, 600) }
|
||||
: isDarkTheme
|
||||
? DARK_COVER_IMAGE
|
||||
: LIGHT_COVER_IMAGE
|
||||
}
|
||||
/>
|
||||
{
|
||||
isUploading && (
|
||||
<ActivityIndicator
|
||||
style={styles.activityIndicator}
|
||||
color={EStyleSheet.value('$white')}
|
||||
size='large'
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
<IconButton
|
||||
iconStyle={styles.addIcon}
|
||||
@ -83,6 +111,22 @@ const ProfileEditFormView = ({
|
||||
</View>
|
||||
))}
|
||||
</KeyboardAwareScrollView>
|
||||
|
||||
{saveEnabled && (
|
||||
<AnimatedView style={styles.floatingContainer} animation="bounceInRight">
|
||||
<MainButton
|
||||
style={{ width: isLoading ? null : 120, marginBottom:24, alignSelf:'flex-end' }}
|
||||
onPress={handleOnSubmit}
|
||||
iconName="save"
|
||||
iconType="MaterialIcons"
|
||||
iconColor="white"
|
||||
text="SAVE"
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</AnimatedView>
|
||||
)}
|
||||
|
||||
|
||||
</View>
|
||||
);
|
||||
|
@ -6,4 +6,10 @@ export default EStyleSheet.create({
|
||||
borderColor: '$borderColor',
|
||||
backgroundColor: '$pureWhite',
|
||||
},
|
||||
activityIndicator: {
|
||||
position:'absolute',
|
||||
alignSelf:'center',
|
||||
top:0,
|
||||
bottom:0
|
||||
}
|
||||
});
|
@ -1,91 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import { TouchableOpacity } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import styles from './userAvatarStyles';
|
||||
import { navigate } from '../../../navigation/service';
|
||||
|
||||
// Constants
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
// Utils
|
||||
import { getResizedAvatar } from '../../../utils/image';
|
||||
|
||||
const DEFAULT_IMAGE = require('../../../assets/avatar_default.png');
|
||||
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
class UserAvatarView extends Component {
|
||||
// Component Life Cycles
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const { username } = this.props;
|
||||
|
||||
return nextProps.username !== username;
|
||||
}
|
||||
|
||||
// Component Functions
|
||||
_handleOnAvatarPress = (username) => {
|
||||
const {
|
||||
currentUsername: { name },
|
||||
} = this.props;
|
||||
|
||||
const routeName = name === username ? ROUTES.TABBAR.PROFILE : ROUTES.SCREENS.PROFILE;
|
||||
|
||||
navigate({
|
||||
routeName,
|
||||
params: {
|
||||
username,
|
||||
},
|
||||
key: username,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
username,
|
||||
size,
|
||||
style,
|
||||
disableSize,
|
||||
noAction,
|
||||
currentUsername: { name, avatar },
|
||||
} = this.props;
|
||||
const imageSize = 'large';
|
||||
let _size;
|
||||
const _avatar = username
|
||||
? {
|
||||
uri: getResizedAvatar(username, imageSize),
|
||||
}
|
||||
: DEFAULT_IMAGE;
|
||||
|
||||
if (!disableSize) {
|
||||
_size = 32;
|
||||
|
||||
if (size === 'xl') {
|
||||
_size = 64;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableOpacity disabled={noAction} onPress={() => this._handleOnAvatarPress(username)}>
|
||||
<FastImage
|
||||
style={[
|
||||
styles.avatar,
|
||||
style,
|
||||
!disableSize && { width: _size, height: _size, borderRadius: _size / 2 },
|
||||
]}
|
||||
source={_avatar}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
currentUsername: state.account.currentAccount,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(UserAvatarView);
|
98
src/components/userAvatar/view/userAvatarView.tsx
Normal file
98
src/components/userAvatar/view/userAvatarView.tsx
Normal file
@ -0,0 +1,98 @@
|
||||
import React, { Component } from 'react';
|
||||
import { ActivityIndicator, TouchableOpacity, ViewStyle } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import styles from './userAvatarStyles';
|
||||
import { navigate } from '../../../navigation/service';
|
||||
|
||||
// Constants
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
// Utils
|
||||
import { getResizedAvatar } from '../../../utils/image';
|
||||
import { useAppSelector } from '../../../hooks';
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
const DEFAULT_IMAGE = require('../../../assets/avatar_default.png');
|
||||
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
|
||||
interface UserAvatarProps {
|
||||
username:string;
|
||||
avatarUrl?:string;
|
||||
size?:'xl';
|
||||
style?:ViewStyle;
|
||||
disableSize?:boolean;
|
||||
noAction?:boolean;
|
||||
isLoading?:boolean;
|
||||
}
|
||||
|
||||
const UserAvatarView = ({
|
||||
username,
|
||||
avatarUrl,
|
||||
size,
|
||||
style,
|
||||
disableSize,
|
||||
noAction,
|
||||
isLoading
|
||||
}:UserAvatarProps) => {
|
||||
|
||||
const curUsername = useAppSelector(state=>state.account.currentAccount.name);
|
||||
const avatarCacheStamp = useAppSelector(state=>state.ui.avatarCacheStamp);
|
||||
|
||||
// Component Functions
|
||||
const _handleOnAvatarPress = (username:string) => {
|
||||
const routeName = curUsername === username ? ROUTES.TABBAR.PROFILE : ROUTES.SCREENS.PROFILE;
|
||||
navigate({
|
||||
routeName,
|
||||
params: {
|
||||
username,
|
||||
},
|
||||
key: username,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const uri = avatarUrl ? avatarUrl : getResizedAvatar(username, 'large');
|
||||
|
||||
const _avatar = username
|
||||
? { uri : `${uri}?stamp=${avatarCacheStamp}` }
|
||||
: DEFAULT_IMAGE;
|
||||
|
||||
let _size:number;
|
||||
if (!disableSize) {
|
||||
_size = 32;
|
||||
if (size === 'xl') {
|
||||
_size = 64;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<TouchableOpacity disabled={noAction} onPress={() => _handleOnAvatarPress(username)}>
|
||||
<FastImage
|
||||
style={[
|
||||
styles.avatar,
|
||||
style,
|
||||
!disableSize && { width: _size, height: _size, borderRadius: _size / 2 },
|
||||
]}
|
||||
source={_avatar}
|
||||
/>
|
||||
{
|
||||
isLoading && (
|
||||
<ActivityIndicator
|
||||
style={styles.activityIndicator}
|
||||
size='large'
|
||||
color={EStyleSheet.value('$white')}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
export default UserAvatarView;
|
@ -10,6 +10,7 @@ import { uploadImage } from '../providers/ecency/ecency';
|
||||
|
||||
import { profileUpdate, signImage } from '../providers/hive/dhive';
|
||||
import { updateCurrentAccount } from '../redux/actions/accountAction';
|
||||
import { setAvatarCacheStamp } from '../redux/actions/uiAction';
|
||||
|
||||
// import ROUTES from '../constants/routeNames';
|
||||
|
||||
@ -50,6 +51,8 @@ class ProfileEditContainer extends Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
isLoading: false,
|
||||
isUploading: false,
|
||||
saveEnabled: false,
|
||||
about: get(props.currentAccount, 'about.profile.about'),
|
||||
name: get(props.currentAccount, 'about.profile.name'),
|
||||
location: get(props.currentAccount, 'about.profile.location'),
|
||||
@ -64,20 +67,20 @@ class ProfileEditContainer extends Component {
|
||||
// Component Functions
|
||||
|
||||
_handleOnItemChange = (val, item) => {
|
||||
this.setState({ [item]: val });
|
||||
this.setState({ [item]: val, saveEnabled: true });
|
||||
};
|
||||
|
||||
_uploadImage = async (media, action) => {
|
||||
const { intl, currentAccount, pinCode } = this.props;
|
||||
|
||||
this.setState({ isLoading: true });
|
||||
this.setState({ isUploading: true });
|
||||
|
||||
let sign = await signImage(media, currentAccount, pinCode);
|
||||
|
||||
uploadImage(media, currentAccount.name, sign)
|
||||
.then((res) => {
|
||||
if (res.data && res.data.url) {
|
||||
this.setState({ [action]: res.data.url, isLoading: false });
|
||||
this.setState({ [action]: res.data.url, isUploading: false, saveEnabled: true });
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
@ -89,7 +92,7 @@ class ProfileEditContainer extends Component {
|
||||
error.message || error.toString(),
|
||||
);
|
||||
}
|
||||
this.setState({ isLoading: false });
|
||||
this.setState({ isUploading: false });
|
||||
});
|
||||
};
|
||||
|
||||
@ -102,11 +105,11 @@ class ProfileEditContainer extends Component {
|
||||
};
|
||||
|
||||
_handleOpenImagePicker = (action) => {
|
||||
ImagePicker.openPicker({
|
||||
includeBase64: true,
|
||||
})
|
||||
.then((image) => {
|
||||
this._handleMediaOnSelected(image, action);
|
||||
ImagePicker.openPicker(
|
||||
action == 'avatarUrl' ? IMAGE_PICKER_AVATAR_OPTIONS : IMAGE_PICKER_COVER_OPTIONS,
|
||||
)
|
||||
.then((media) => {
|
||||
this._uploadImage(media, action);
|
||||
})
|
||||
.catch((e) => {
|
||||
this._handleMediaOnSelectFailure(e);
|
||||
@ -114,23 +117,17 @@ class ProfileEditContainer extends Component {
|
||||
};
|
||||
|
||||
_handleOpenCamera = (action) => {
|
||||
ImagePicker.openCamera({
|
||||
includeBase64: true,
|
||||
})
|
||||
.then((image) => {
|
||||
this._handleMediaOnSelected(image, action);
|
||||
ImagePicker.openCamera(
|
||||
action == 'avatarUrl' ? IMAGE_PICKER_AVATAR_OPTIONS : IMAGE_PICKER_COVER_OPTIONS,
|
||||
)
|
||||
.then((media) => {
|
||||
this._uploadImage(media, action);
|
||||
})
|
||||
.catch((e) => {
|
||||
this._handleMediaOnSelectFailure(e);
|
||||
});
|
||||
};
|
||||
|
||||
_handleMediaOnSelected = (media, action) => {
|
||||
this.setState({ isLoading: true }, () => {
|
||||
this._uploadImage(media, action);
|
||||
});
|
||||
};
|
||||
|
||||
_handleMediaOnSelectFailure = (error) => {
|
||||
const { intl } = this.props;
|
||||
|
||||
@ -150,7 +147,7 @@ class ProfileEditContainer extends Component {
|
||||
const { currentAccount, pinCode, dispatch, navigation, intl } = this.props;
|
||||
const { name, location, website, about, coverUrl, avatarUrl } = this.state;
|
||||
|
||||
await this.setState({ isLoading: true });
|
||||
this.setState({ isLoading: true });
|
||||
|
||||
const params = {
|
||||
profile_image: avatarUrl,
|
||||
@ -161,31 +158,42 @@ class ProfileEditContainer extends Component {
|
||||
location,
|
||||
version: 2,
|
||||
};
|
||||
await profileUpdate(params, pinCode, currentAccount)
|
||||
.then(async () => {
|
||||
const _currentAccount = { ...currentAccount, display_name: name, avatar: avatarUrl };
|
||||
_currentAccount.about.profile = { ...params };
|
||||
|
||||
dispatch(updateCurrentAccount(_currentAccount));
|
||||
try {
|
||||
await profileUpdate(params, pinCode, currentAccount);
|
||||
|
||||
navigation.state.params.fetchUser();
|
||||
navigation.goBack();
|
||||
})
|
||||
.catch((error) => {
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
id: 'alert.fail',
|
||||
}),
|
||||
get(error, 'message', error.toString()),
|
||||
);
|
||||
});
|
||||
const _currentAccount = { ...currentAccount, display_name: name, avatar: avatarUrl };
|
||||
_currentAccount.about.profile = { ...params };
|
||||
|
||||
this.setState({ isLoading: false });
|
||||
dispatch(updateCurrentAccount(_currentAccount));
|
||||
dispatch(setAvatarCacheStamp(new Date().getTime()));
|
||||
this.setState({ isLoading: false });
|
||||
navigation.state.params.fetchUser();
|
||||
navigation.goBack();
|
||||
} catch (err) {
|
||||
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;
|
||||
const {
|
||||
isLoading,
|
||||
isUploading,
|
||||
name,
|
||||
location,
|
||||
website,
|
||||
about,
|
||||
coverUrl,
|
||||
avatarUrl,
|
||||
saveEnabled,
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
children &&
|
||||
@ -200,9 +208,11 @@ class ProfileEditContainer extends Component {
|
||||
handleOnSubmit: this._handleOnSubmit,
|
||||
isDarkTheme,
|
||||
isLoading,
|
||||
isUploading,
|
||||
location,
|
||||
name,
|
||||
website,
|
||||
saveEnabled,
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -215,3 +225,14 @@ const mapStateToProps = (state) => ({
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(injectIntl(withNavigation(ProfileEditContainer)));
|
||||
|
||||
const IMAGE_PICKER_AVATAR_OPTIONS = {
|
||||
includeBase64: true,
|
||||
cropping: true,
|
||||
width: 512,
|
||||
height: 512,
|
||||
};
|
||||
|
||||
const IMAGE_PICKER_COVER_OPTIONS = {
|
||||
includeBase64: true,
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { ButtonProps } from 'react-native';
|
||||
import {
|
||||
TOAST_NOTIFICATION,
|
||||
UPDATE_ACTIVE_BOTTOM_TAB,
|
||||
@ -6,19 +7,20 @@ import {
|
||||
TOGGLE_ACCOUNTS_BOTTOM_SHEET,
|
||||
SHOW_ACTION_MODAL,
|
||||
HIDE_ACTION_MODAL,
|
||||
SET_AVATAR_CACHE_STAMP,
|
||||
} from '../constants/constants';
|
||||
|
||||
export const updateActiveBottomTab = (payload) => ({
|
||||
export const updateActiveBottomTab = (payload:string) => ({
|
||||
payload,
|
||||
type: UPDATE_ACTIVE_BOTTOM_TAB,
|
||||
});
|
||||
|
||||
export const toastNotification = (payload) => ({
|
||||
export const toastNotification = (payload:string) => ({
|
||||
payload,
|
||||
type: TOAST_NOTIFICATION,
|
||||
});
|
||||
|
||||
export const showActionModal = (title, body, buttons, headerImage, onClosed) => ({
|
||||
export const showActionModal = (title:string, body:string, buttons:ButtonProps[], headerImage:any, onClosed:()=>void) => ({
|
||||
payload: {
|
||||
actionModalVisible: true,
|
||||
actionModalData: {
|
||||
@ -36,17 +38,22 @@ export const hideActionModal = () => ({
|
||||
type: HIDE_ACTION_MODAL,
|
||||
});
|
||||
|
||||
export const setRcOffer = (payload) => ({
|
||||
export const setRcOffer = (payload:boolean) => ({
|
||||
payload,
|
||||
type: RC_OFFER,
|
||||
});
|
||||
|
||||
export const hidePostsThumbnails = (payload) => ({
|
||||
export const hidePostsThumbnails = (payload:boolean) => ({
|
||||
payload,
|
||||
type: HIDE_POSTS_THUMBNAILS,
|
||||
});
|
||||
|
||||
export const toggleAccountsBottomSheet = (payload) => ({
|
||||
export const toggleAccountsBottomSheet = (payload:boolean) => ({
|
||||
payload,
|
||||
type: TOGGLE_ACCOUNTS_BOTTOM_SHEET,
|
||||
});
|
||||
|
||||
export const setAvatarCacheStamp = (payload:number) => ({
|
||||
payload,
|
||||
type:SET_AVATAR_CACHE_STAMP
|
||||
})
|
@ -54,6 +54,7 @@ export const RC_OFFER = 'RC_OFFER';
|
||||
export const TOGGLE_ACCOUNTS_BOTTOM_SHEET = 'TOGGLE_ACCOUNTS_BOTTOM_SHEET';
|
||||
export const SHOW_ACTION_MODAL = 'SHOW_ACTION_MODAL';
|
||||
export const HIDE_ACTION_MODAL = 'HIDE_ACTION_MODAL';
|
||||
export const SET_AVATAR_CACHE_STAMP = 'SET_AVATAR_CACHE_STAMP';
|
||||
|
||||
// POSTS
|
||||
export const SET_FEED_POSTS = 'SET_FEED_POSTS';
|
||||
|
@ -6,9 +6,21 @@ import {
|
||||
TOGGLE_ACCOUNTS_BOTTOM_SHEET,
|
||||
SHOW_ACTION_MODAL,
|
||||
HIDE_ACTION_MODAL,
|
||||
SET_AVATAR_CACHE_STAMP,
|
||||
} from '../constants/constants';
|
||||
|
||||
const initialState = {
|
||||
interface UiState {
|
||||
activeBottomTab:string;
|
||||
toastNotification:string;
|
||||
hidePostsThumbnails:boolean;
|
||||
rcOffer:boolean;
|
||||
isVisibleAccountsBottomSheet:boolean;
|
||||
actionModalVisible:boolean;
|
||||
actionModalData:any;
|
||||
avatarCacheStamp:number
|
||||
}
|
||||
|
||||
const initialState:UiState = {
|
||||
activeBottomTab: 'HomeTabbar',
|
||||
toastNotification: '',
|
||||
hidePostsThumbnails: false,
|
||||
@ -16,6 +28,7 @@ const initialState = {
|
||||
isVisibleAccountsBottomSheet: false,
|
||||
actionModalVisible: false,
|
||||
actionModalData: null,
|
||||
avatarCacheStamp: 0
|
||||
};
|
||||
|
||||
export default function (state = initialState, action) {
|
||||
@ -65,6 +78,11 @@ export default function (state = initialState, action) {
|
||||
...state,
|
||||
isVisibleAccountsBottomSheet: action.payload,
|
||||
};
|
||||
case SET_AVATAR_CACHE_STAMP:
|
||||
return {
|
||||
...state,
|
||||
avatarCacheStamp: action.payload
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
@ -77,6 +77,7 @@ import {
|
||||
} from '../../../redux/actions/applicationActions';
|
||||
import {
|
||||
hideActionModal,
|
||||
setAvatarCacheStamp,
|
||||
setRcOffer,
|
||||
toastNotification,
|
||||
updateActiveBottomTab,
|
||||
@ -126,7 +127,6 @@ class ApplicationContainer extends Component {
|
||||
this._setNetworkListener();
|
||||
|
||||
Linking.addEventListener('url', this._handleOpenURL);
|
||||
|
||||
Linking.getInitialURL().then((url) => {
|
||||
this._handleDeepLink(url);
|
||||
});
|
||||
@ -145,6 +145,9 @@ class ApplicationContainer extends Component {
|
||||
|
||||
if (!isIos) BackHandler.addEventListener('hardwareBackPress', this._onBackPress);
|
||||
|
||||
//set avatar cache stamp to invalidate previous session avatars
|
||||
dispatch(setAvatarCacheStamp(new Date().getTime()));
|
||||
|
||||
getVersionForWelcomeModal().then((version) => {
|
||||
if (version < parseVersionNumber(appVersion)) {
|
||||
getUserData().then((accounts) => {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { PureComponent, Fragment } from 'react';
|
||||
import { StatusBar } from 'react-native';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import get from 'lodash/get';
|
||||
import ActionSheet from 'react-native-actionsheet';
|
||||
@ -25,9 +26,10 @@ class ProfileEditScreen extends PureComponent {
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
_showImageUploadActions = async (action) => {
|
||||
await this.setState({ selectedUploadAction: action });
|
||||
this.galleryRef.current.show();
|
||||
_showImageUploadActions = (action) => {
|
||||
this.setState({ selectedUploadAction: action }, () => {
|
||||
this.galleryRef.current.show();
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
@ -49,15 +51,19 @@ class ProfileEditScreen extends PureComponent {
|
||||
avatarUrl,
|
||||
coverUrl,
|
||||
isLoading,
|
||||
isUploading,
|
||||
saveEnabled,
|
||||
handleOnSubmit,
|
||||
}) => (
|
||||
<Fragment>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<AvatarHeader
|
||||
username={get(currentAccount, 'name')}
|
||||
name={name}
|
||||
reputation={get(currentAccount, 'reputation')}
|
||||
avatarUrl={avatarUrl}
|
||||
showImageUploadActions={() => this._showImageUploadActions('avatarUrl')}
|
||||
isUploading={isUploading && selectedUploadAction === 'avatarUrl'}
|
||||
/>
|
||||
<ProfileEditForm
|
||||
formData={formData}
|
||||
@ -70,8 +76,11 @@ class ProfileEditScreen extends PureComponent {
|
||||
showImageUploadActions={() => this._showImageUploadActions('coverUrl')}
|
||||
handleOnItemChange={handleOnItemChange}
|
||||
isLoading={isLoading}
|
||||
isUploading={isUploading && selectedUploadAction === 'coverUrl'}
|
||||
saveEnabled={saveEnabled}
|
||||
handleOnSubmit={handleOnSubmit}
|
||||
/>
|
||||
|
||||
<ActionSheet
|
||||
ref={this.galleryRef}
|
||||
options={[
|
||||
|
Loading…
Reference in New Issue
Block a user