change avatar for profile it's done, missing fix revalidate the avatar in profile and drawer
This commit is contained in:
parent
5e1f1c89da
commit
7813efbb26
|
@ -880,5 +880,9 @@
|
|||
"Upload_image": "Upload image",
|
||||
"Delete_image": "Delete image",
|
||||
"Images_uploaded": "Images uploaded",
|
||||
"Avatar": "Avatar"
|
||||
"Avatar": "Avatar",
|
||||
"insert_Avatar_URL": "insert image URL here",
|
||||
"Discard_changes":"Discard changes?",
|
||||
"Discard":"Discard",
|
||||
"Discard_changes_description":"All changes will be lost if you go back without saving."
|
||||
}
|
|
@ -2,6 +2,16 @@ import { Alert } from 'react-native';
|
|||
|
||||
import I18n from '../../../i18n';
|
||||
|
||||
export const handleError = (e: any, _func: string, action: string) => {
|
||||
if (e.data && e.data.error.includes('[error-too-many-requests]')) {
|
||||
return showErrorAlert(e.data.error);
|
||||
}
|
||||
if (I18n.isTranslated(e.error)) {
|
||||
return showErrorAlert(I18n.t(e.error));
|
||||
}
|
||||
showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t(action) }));
|
||||
};
|
||||
|
||||
export const showErrorAlert = (message: string, title?: string, onPress = () => {}): void =>
|
||||
Alert.alert(title || '', message, [{ text: 'OK', onPress }], { cancelable: true });
|
||||
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
import React from 'react';
|
||||
import { Text, View, Alert, TouchableOpacity } from 'react-native';
|
||||
import { Text, View, TouchableOpacity } from 'react-native';
|
||||
|
||||
import { IAvatar } from '../../definitions';
|
||||
import { IAvatar, IUser } from '../../definitions';
|
||||
import I18n from '../../i18n';
|
||||
import Avatar from '../../containers/Avatar';
|
||||
// import Touch from '../../containers/Touch';
|
||||
import styles from './styles';
|
||||
import { useTheme } from '../../theme';
|
||||
|
||||
const AvatarSuggestion = ({ avatarSuggestions }: { avatarSuggestions: IAvatar[] }) => {
|
||||
const Item = ({ item, onPress, text }: { item?: IAvatar; onPress: (value?: IAvatar) => void; text?: string }) => {
|
||||
const { colors } = useTheme();
|
||||
const test = [
|
||||
...avatarSuggestions,
|
||||
...avatarSuggestions,
|
||||
...avatarSuggestions,
|
||||
...avatarSuggestions,
|
||||
...avatarSuggestions,
|
||||
...avatarSuggestions,
|
||||
...avatarSuggestions,
|
||||
...avatarSuggestions,
|
||||
...avatarSuggestions,
|
||||
...avatarSuggestions,
|
||||
...avatarSuggestions,
|
||||
...avatarSuggestions
|
||||
];
|
||||
const renderItem = () =>
|
||||
test.slice(0, 8).map(item => (
|
||||
<TouchableOpacity
|
||||
key={item.service}
|
||||
testID={`${item.service}-avatar-suggestion`}
|
||||
onPress={() => Alert.alert('aqui')}
|
||||
style={[styles.avatarButton, { backgroundColor: colors.borderColor }]}
|
||||
>
|
||||
<Avatar avatar={item.url} size={64} />
|
||||
</TouchableOpacity>
|
||||
));
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1 }}>
|
||||
<Text style={styles.itemLabel}>{I18n.t('Images_uploaded')}</Text>
|
||||
<View style={styles.containerAvatarSuggestion}>{renderItem()}</View>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
key={item?.service}
|
||||
testID={`${item?.service}-avatar-suggestion`}
|
||||
onPress={() => onPress(item)}
|
||||
style={[styles.avatarButton, { backgroundColor: colors.borderColor }]}
|
||||
>
|
||||
<Avatar avatar={item?.url} text={text} size={64} />
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
const AvatarSuggestion = ({
|
||||
avatarSuggestions,
|
||||
onPress,
|
||||
user,
|
||||
resetAvatar
|
||||
}: {
|
||||
avatarSuggestions: IAvatar[];
|
||||
onPress: (value?: IAvatar) => void;
|
||||
user?: IUser;
|
||||
resetAvatar?: () => void;
|
||||
}) => (
|
||||
<View style={{ flex: 1 }}>
|
||||
<Text style={styles.itemLabel}>{I18n.t('Images_uploaded')}</Text>
|
||||
<View style={styles.containerAvatarSuggestion}>
|
||||
{user?.username && resetAvatar ? <Item text={`@${user.username}`} onPress={resetAvatar} /> : null}
|
||||
{avatarSuggestions.slice(0, 7).map(item => (
|
||||
<Item item={item} onPress={onPress} />
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
export default AvatarSuggestion;
|
||||
|
|
|
@ -17,7 +17,7 @@ const AvatarUrl = ({ submit }: { submit: (value: string) => void }) => {
|
|||
return (
|
||||
<FormTextInput
|
||||
label={I18n.t('Avatar_Url')}
|
||||
placeholder={I18n.t('Avatar_Url')}
|
||||
placeholder={I18n.t('insert_Avatar_URL')}
|
||||
onChangeText={handleChangeText}
|
||||
testID='change-avatar-view-avatar-url'
|
||||
containerStyle={{ marginBottom: 0 }}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useLayoutEffect, useState } from 'react';
|
||||
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { ScrollView, View } from 'react-native';
|
||||
import { RouteProp, useNavigation, useRoute } from '@react-navigation/native';
|
||||
import { StackNavigationProp } from '@react-navigation/stack';
|
||||
|
@ -6,6 +6,7 @@ import { StackNavigationProp } from '@react-navigation/stack';
|
|||
import KeyboardView from '../../containers/KeyboardView';
|
||||
import sharedStyles from '../Styles';
|
||||
import scrollPersistTaps from '../../lib/methods/helpers/scrollPersistTaps';
|
||||
import { showConfirmationAlert, handleError } from '../../lib/methods/helpers/info';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
import { useTheme } from '../../theme';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
|
@ -21,19 +22,49 @@ import { ChatsStackParamList } from '../../stacks/types';
|
|||
import { IAvatar } from '../../definitions';
|
||||
import { Services } from '../../lib/services';
|
||||
import AvatarSuggestion from './AvatarSuggestion';
|
||||
import log from '../../lib/methods/helpers/log';
|
||||
|
||||
const ChangeAvatarView = () => {
|
||||
const [avatarUrl, setAvatarUrl] = useState('');
|
||||
const [avatar, setAvatarState] = useState<IAvatar>();
|
||||
const [avatarSuggestions, setAvatarSuggestions] = useState<IAvatar[]>([]);
|
||||
const [textAvatar, setTextAvatar] = useState('');
|
||||
const [saving, setSaving] = useState(false);
|
||||
const { colors } = useTheme();
|
||||
const { user } = useAppSelector(state => ({
|
||||
user: getUserSelector(state),
|
||||
isMasterDetail: state.app.isMasterDetail
|
||||
}));
|
||||
|
||||
const avatarUrl = useRef<string | undefined>('');
|
||||
|
||||
const navigation = useNavigation<StackNavigationProp<ChatsStackParamList, 'ChangeAvatarView'>>();
|
||||
const { fromUser, titleHeader } = useRoute<RouteProp<ChatsStackParamList, 'ChangeAvatarView'>>().params;
|
||||
|
||||
useLayoutEffect(() => {
|
||||
titleHeader ? navigation.setOptions({ title: titleHeader }) : navigation.setOptions({ title: I18n.t('Avatar') });
|
||||
navigation.setOptions({
|
||||
title: titleHeader || I18n.t('Avatar')
|
||||
});
|
||||
}, [titleHeader, navigation]);
|
||||
|
||||
useEffect(() => {
|
||||
navigation.addListener('beforeRemove', e => {
|
||||
if (!avatarUrl.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
showConfirmationAlert({
|
||||
title: I18n.t('Discard_changes'),
|
||||
message: I18n.t('Discard_changes_description'),
|
||||
confirmationText: I18n.t('Discard'),
|
||||
onPress: () => {
|
||||
navigation.dispatch(e.data.action);
|
||||
}
|
||||
});
|
||||
});
|
||||
}, [navigation]);
|
||||
|
||||
const getAvatarSuggestion = async () => {
|
||||
const result = await Services.getAvatarSuggestion();
|
||||
const suggestions = Object.keys(result).map(service => {
|
||||
|
@ -54,7 +85,45 @@ const ChangeAvatarView = () => {
|
|||
}
|
||||
}, [fromUser]);
|
||||
|
||||
const user = useAppSelector(state => getUserSelector(state));
|
||||
const setAvatar = (value?: IAvatar) => {
|
||||
avatarUrl.current = value?.url;
|
||||
setAvatarState(value);
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
if (avatar?.url) {
|
||||
try {
|
||||
setSaving(true);
|
||||
await Services.setAvatarFromService(avatar);
|
||||
setSaving(false);
|
||||
avatarUrl.current = '';
|
||||
return navigation.goBack();
|
||||
} catch (e) {
|
||||
log(e);
|
||||
setSaving(false);
|
||||
return handleError(e, 'setAvatarFromService', 'changing_avatar');
|
||||
}
|
||||
}
|
||||
|
||||
if (textAvatar) {
|
||||
try {
|
||||
setSaving(true);
|
||||
await Services.resetAvatar(user.id);
|
||||
setSaving(false);
|
||||
avatarUrl.current = '';
|
||||
return navigation.goBack();
|
||||
} catch (e) {
|
||||
setSaving(false);
|
||||
handleError(e, 'resetAvatar', 'changing_avatar');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const resetAvatar = () => {
|
||||
setAvatar(undefined);
|
||||
setTextAvatar(`@${user.username}`);
|
||||
avatarUrl.current = `@${user.username}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<KeyboardView
|
||||
|
@ -70,27 +139,40 @@ const ChangeAvatarView = () => {
|
|||
{...scrollPersistTaps}
|
||||
>
|
||||
<View style={styles.avatarContainer} testID='change-avatar-view-avatar'>
|
||||
<Avatar text={user.username} avatar={avatarUrl} isStatic={avatarUrl} size={100} />
|
||||
<Avatar text={textAvatar || user.username} avatar={avatar?.url} isStatic={avatar?.url} size={100} />
|
||||
</View>
|
||||
<AvatarUrl submit={setAvatarUrl} />
|
||||
<AvatarUrl submit={value => setAvatar({ url: value, data: value, service: 'url' })} />
|
||||
<List.Separator style={styles.separator} />
|
||||
{fromUser && avatarSuggestions.length ? <AvatarSuggestion avatarSuggestions={avatarSuggestions} /> : null}
|
||||
{fromUser && avatarSuggestions.length ? (
|
||||
<AvatarSuggestion resetAvatar={resetAvatar} user={user} onPress={setAvatar} avatarSuggestions={avatarSuggestions} />
|
||||
) : null}
|
||||
|
||||
<Button
|
||||
title={I18n.t('Upload_image')}
|
||||
type='secondary'
|
||||
disabled={saving}
|
||||
backgroundColor={colors.chatComponentBackground}
|
||||
onPress={() => {}}
|
||||
testID='change-avatar-view-logout-other-locations'
|
||||
/>
|
||||
{!fromUser ? (
|
||||
<Button
|
||||
title={I18n.t('Delete_image')}
|
||||
type='primary'
|
||||
disabled={saving}
|
||||
backgroundColor={colors.dangerColor}
|
||||
onPress={() => {}}
|
||||
testID='change-avatar-view-delete-my-account'
|
||||
/>
|
||||
) : null}
|
||||
<Button
|
||||
title={I18n.t('Delete_image')}
|
||||
title={I18n.t('Save')}
|
||||
disabled={!avatarUrl.current || saving}
|
||||
type='primary'
|
||||
backgroundColor={colors.dangerColor}
|
||||
onPress={() => {}}
|
||||
testID='change-avatar-view-delete-my-account'
|
||||
loading={saving}
|
||||
onPress={submit}
|
||||
testID='change-avatar-view-submit'
|
||||
/>
|
||||
<Button title={I18n.t('Save')} type='primary' onPress={() => {}} testID='change-avatar-view-submit' />
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
</KeyboardView>
|
||||
|
|
|
@ -12,7 +12,7 @@ import Touch from '../../containers/Touch';
|
|||
import KeyboardView from '../../containers/KeyboardView';
|
||||
import sharedStyles from '../Styles';
|
||||
import scrollPersistTaps from '../../lib/methods/helpers/scrollPersistTaps';
|
||||
import { showConfirmationAlert, showErrorAlert } from '../../lib/methods/helpers';
|
||||
import { handleError, showConfirmationAlert } from '../../lib/methods/helpers';
|
||||
import { LISTENER } from '../../containers/Toast';
|
||||
import EventEmitter from '../../lib/methods/helpers/events';
|
||||
import { FormTextInput } from '../../containers/TextInput';
|
||||
|
@ -201,16 +201,6 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
|||
);
|
||||
};
|
||||
|
||||
handleError = (e: any, _func: string, action: string) => {
|
||||
if (e.data && e.data.error.includes('[error-too-many-requests]')) {
|
||||
return showErrorAlert(e.data.error);
|
||||
}
|
||||
if (I18n.isTranslated(e.error)) {
|
||||
return showErrorAlert(I18n.t(e.error));
|
||||
}
|
||||
showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t(action) }));
|
||||
};
|
||||
|
||||
submit = async (): Promise<void> => {
|
||||
Keyboard.dismiss();
|
||||
|
||||
|
@ -280,7 +270,7 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
|||
} catch (e) {
|
||||
logEvent(events.PROFILE_SAVE_AVATAR_F);
|
||||
this.setState({ saving: false, currentPassword: null });
|
||||
return this.handleError(e, 'setAvatarFromService', 'changing_avatar');
|
||||
return handleError(e, 'setAvatarFromService', 'changing_avatar');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,7 +307,7 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
|||
}
|
||||
logEvent(events.PROFILE_SAVE_CHANGES_F);
|
||||
this.setState({ saving: false, currentPassword: null, twoFactorCode: null });
|
||||
this.handleError(e, 'saveUserProfile', 'saving_profile');
|
||||
handleError(e, 'saveUserProfile', 'saving_profile');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -334,7 +324,7 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
|||
EventEmitter.emit(LISTENER, { message: I18n.t('Avatar_changed_successfully') });
|
||||
this.init();
|
||||
} catch (e) {
|
||||
this.handleError(e, 'resetAvatar', 'changing_avatar');
|
||||
handleError(e, 'resetAvatar', 'changing_avatar');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue