add: `AvatarEditView`
This commit is contained in:
parent
305f360b40
commit
98bdd552cd
|
@ -1,4 +1,4 @@
|
|||
import { IParams } from '../../IProfileViewInterfaces';
|
||||
import { IParams } from '../../../views/ProfileView/interfaces';
|
||||
import type { ITeam } from '../../ITeam';
|
||||
import type { IUser } from '../../IUser';
|
||||
import { INotificationPreferences, IUserPreferences, IUserRegistered } from '../../IUser';
|
||||
|
|
|
@ -114,6 +114,7 @@
|
|||
"Auto_Translate": "Auto-Translate",
|
||||
"Avatar_changed_successfully": "Avatar changed successfully!",
|
||||
"Avatar_Url": "Avatar URL",
|
||||
"Avatar_Url_Insert_Image": "Insert image URL here",
|
||||
"Away": "Away",
|
||||
"Back": "Back",
|
||||
"Black": "Black",
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
SubscriptionType,
|
||||
IUser
|
||||
} from '../../definitions';
|
||||
import { IAvatarSuggestion, IParams } from '../../definitions/IProfileViewInterfaces';
|
||||
import { IAvatarSuggestion, IParams } from '../../views/ProfileView/interfaces';
|
||||
import { ISpotlight } from '../../definitions/ISpotlight';
|
||||
import { TEAM_TYPE } from '../../definitions/ITeam';
|
||||
import { Encryption } from '../encryption';
|
||||
|
|
|
@ -33,6 +33,7 @@ import CannedResponseDetail from '../views/CannedResponseDetail';
|
|||
import { themes } from '../lib/constants';
|
||||
// Profile Stack
|
||||
import ProfileView from '../views/ProfileView';
|
||||
import AvatarEditView from '../views/AvatarEditView';
|
||||
import UserPreferencesView from '../views/UserPreferencesView';
|
||||
import UserNotificationPrefView from '../views/UserNotificationPreferencesView';
|
||||
// Display Preferences View
|
||||
|
@ -148,6 +149,7 @@ const ProfileStackNavigator = () => {
|
|||
<ProfileStack.Navigator
|
||||
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}>
|
||||
<ProfileStack.Screen name='ProfileView' component={ProfileView} options={ProfileView.navigationOptions} />
|
||||
<ProfileStack.Screen name='AvatarEditView' component={AvatarEditView} />
|
||||
<ProfileStack.Screen name='UserPreferencesView' component={UserPreferencesView} />
|
||||
<ProfileStack.Screen
|
||||
name='UserNotificationPrefView'
|
||||
|
|
|
@ -44,6 +44,7 @@ import UserNotificationPrefView from '../../views/UserNotificationPreferencesVie
|
|||
import SecurityPrivacyView from '../../views/SecurityPrivacyView';
|
||||
import E2EEncryptionSecurityView from '../../views/E2EEncryptionSecurityView';
|
||||
// InsideStackNavigator
|
||||
import AvatarEditView from '../../views/AvatarEditView';
|
||||
import AttachmentView from '../../views/AttachmentView';
|
||||
import ModalBlockView from '../../views/ModalBlockView';
|
||||
import JitsiMeetView from '../../views/JitsiMeetView';
|
||||
|
@ -195,6 +196,7 @@ const ModalStackNavigator = React.memo(({ navigation }: INavigation) => {
|
|||
component={ProfileView}
|
||||
options={props => ProfileView.navigationOptions!({ ...props, isMasterDetail: true })}
|
||||
/>
|
||||
<ModalStack.Screen name='AvatarEditView' component={AvatarEditView} />
|
||||
<ModalStack.Screen name='DisplayPrefsView' component={DisplayPrefsView} />
|
||||
<ModalStack.Screen
|
||||
name='AdminPanelView'
|
||||
|
|
|
@ -150,6 +150,7 @@ export type ModalStackParamList = {
|
|||
ScreenLockConfigView: undefined;
|
||||
StatusView: undefined;
|
||||
ProfileView: undefined;
|
||||
AvatarEditView: undefined;
|
||||
DisplayPrefsView: undefined;
|
||||
AdminPanelView: undefined;
|
||||
NewMessageView: undefined;
|
||||
|
|
|
@ -157,6 +157,7 @@ export type ChatsStackParamList = {
|
|||
|
||||
export type ProfileStackParamList = {
|
||||
ProfileView: undefined;
|
||||
AvatarEditView: undefined;
|
||||
UserPreferencesView: undefined;
|
||||
UserNotificationPrefView: undefined;
|
||||
PickerView: {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
import React, { useLayoutEffect, useState } from 'react';
|
||||
// import { useSelector } from 'react-redux';
|
||||
|
||||
import { ProfileStackParamList } from '../../stacks/types';
|
||||
import { IBaseScreen } from '../../definitions';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
import Button from '../../containers/Button';
|
||||
import { useTheme } from '../../theme';
|
||||
import i18n from '../../i18n';
|
||||
import RCTextInput from '../../containers/TextInput';
|
||||
// import { getUserSelector } from '../../selectors/login';
|
||||
// import Avatar from '../../containers/Avatar';
|
||||
|
||||
const AvatarEditView = ({ navigation }: IBaseScreen<ProfileStackParamList, 'AvatarEditView'>): React.ReactElement => {
|
||||
const [avatarUrl, setAvatarUrl] = useState('');
|
||||
const [saving] = useState(false);
|
||||
|
||||
// const username = useSelector((state: IApplicationState) => getUserSelector(state).username);
|
||||
// const url = useSelector((state: IApplicationState) => getUserSelector(state).username);
|
||||
|
||||
const { theme } = useTheme();
|
||||
|
||||
useLayoutEffect(() => {
|
||||
navigation.setOptions({
|
||||
title: 'Avatar'
|
||||
});
|
||||
}, []);
|
||||
return (
|
||||
<SafeAreaView>
|
||||
{/* <Avatar text={username} avatar={avatar?.url} isStatic={avatar?.url} size={120} /> */}
|
||||
<RCTextInput
|
||||
label={i18n.t('Avatar_Url')}
|
||||
placeholder={i18n.t('Avatar_Url_Insert_Image')}
|
||||
value={avatarUrl}
|
||||
onChangeText={value => setAvatarUrl(value)}
|
||||
// onSubmitEditing={this.submit}
|
||||
testID='profile-view-avatar-url'
|
||||
theme={theme}
|
||||
/>
|
||||
<Button
|
||||
title={i18n.t('Save_Changes')}
|
||||
type='primary'
|
||||
// onPress={this.submit}
|
||||
// disabled={!this.formIsChanged()}
|
||||
testID='profile-view-submit'
|
||||
loading={saving}
|
||||
theme={theme}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
export default AvatarEditView;
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Keyboard, ScrollView, View } from 'react-native';
|
||||
import { Keyboard, ScrollView, Text, View } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import prompt from 'react-native-prompt-android';
|
||||
import { sha256 } from 'js-sha256';
|
||||
|
@ -22,7 +22,6 @@ import I18n from '../../i18n';
|
|||
import Button from '../../containers/Button';
|
||||
import Avatar from '../../containers/Avatar';
|
||||
import { setUser as setUserAction } from '../../actions/login';
|
||||
import { CustomIcon } from '../../containers/CustomIcon';
|
||||
import * as HeaderButton from '../../containers/HeaderButton';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
import { themes } from '../../lib/constants';
|
||||
|
@ -30,14 +29,7 @@ import { withTheme } from '../../theme';
|
|||
import { getUserSelector } from '../../selectors/login';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
import styles from './styles';
|
||||
import {
|
||||
IAvatar,
|
||||
IAvatarButton,
|
||||
INavigationOptions,
|
||||
IParams,
|
||||
IProfileViewProps,
|
||||
IProfileViewState
|
||||
} from '../../definitions/IProfileViewInterfaces';
|
||||
import { IAvatar, IAvatarButton, IParams, IProfileViewProps, IProfileViewState } from './interfaces';
|
||||
import { IUser } from '../../definitions';
|
||||
import { Services } from '../../lib/services';
|
||||
|
||||
|
@ -48,7 +40,7 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
|||
private avatarUrl: any;
|
||||
private newPassword: any;
|
||||
|
||||
static navigationOptions = ({ navigation, isMasterDetail }: INavigationOptions) => {
|
||||
static navigationOptions = ({ navigation, isMasterDetail }: IProfileViewProps) => {
|
||||
const options: StackNavigationOptions = {
|
||||
title: I18n.t('Profile')
|
||||
};
|
||||
|
@ -319,48 +311,48 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
|||
);
|
||||
};
|
||||
|
||||
renderAvatarButtons = () => {
|
||||
const { avatarUrl, avatarSuggestions } = this.state;
|
||||
const { user, theme, Accounts_AllowUserAvatarChange } = this.props;
|
||||
// renderAvatarButtons = () => {
|
||||
// const { avatarUrl, avatarSuggestions } = this.state;
|
||||
// const { user, theme, Accounts_AllowUserAvatarChange } = this.props;
|
||||
|
||||
return (
|
||||
<View style={styles.avatarButtons}>
|
||||
{this.renderAvatarButton({
|
||||
child: <Avatar text={`@${user.username}`} size={50} />,
|
||||
onPress: () => this.resetAvatar(),
|
||||
disabled: !Accounts_AllowUserAvatarChange,
|
||||
key: 'profile-view-reset-avatar'
|
||||
})}
|
||||
{this.renderAvatarButton({
|
||||
child: <CustomIcon name='upload' size={30} color={themes[theme].bodyText} />,
|
||||
onPress: () => this.pickImage(),
|
||||
disabled: !Accounts_AllowUserAvatarChange,
|
||||
key: 'profile-view-upload-avatar'
|
||||
})}
|
||||
{this.renderAvatarButton({
|
||||
child: <CustomIcon name='link' size={30} color={themes[theme].bodyText} />,
|
||||
onPress: () => this.pickImageWithURL(avatarUrl!),
|
||||
disabled: !avatarUrl,
|
||||
key: 'profile-view-avatar-url-button'
|
||||
})}
|
||||
{Object.keys(avatarSuggestions).map(service => {
|
||||
const { url, blob, contentType } = avatarSuggestions[service];
|
||||
return this.renderAvatarButton({
|
||||
disabled: !Accounts_AllowUserAvatarChange,
|
||||
key: `profile-view-avatar-${service}`,
|
||||
child: <Avatar avatar={url} size={50} />,
|
||||
onPress: () =>
|
||||
this.setAvatar({
|
||||
url,
|
||||
data: blob,
|
||||
service,
|
||||
contentType
|
||||
})
|
||||
});
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
// return (
|
||||
// <View style={styles.avatarButtons}>
|
||||
// {this.renderAvatarButton({
|
||||
// child: <Avatar text={`@${user.username}`} size={50} />,
|
||||
// onPress: () => this.resetAvatar(),
|
||||
// disabled: !Accounts_AllowUserAvatarChange,
|
||||
// key: 'profile-view-reset-avatar'
|
||||
// })}
|
||||
// {this.renderAvatarButton({
|
||||
// child: <CustomIcon name='upload' size={30} color={themes[theme].bodyText} />,
|
||||
// onPress: () => this.pickImage(),
|
||||
// disabled: !Accounts_AllowUserAvatarChange,
|
||||
// key: 'profile-view-upload-avatar'
|
||||
// })}
|
||||
// {this.renderAvatarButton({
|
||||
// child: <CustomIcon name='link' size={30} color={themes[theme].bodyText} />,
|
||||
// onPress: () => this.pickImageWithURL(avatarUrl!),
|
||||
// disabled: !avatarUrl,
|
||||
// key: 'profile-view-avatar-url-button'
|
||||
// })}
|
||||
// {Object.keys(avatarSuggestions).map(service => {
|
||||
// const { url, blob, contentType } = avatarSuggestions[service];
|
||||
// return this.renderAvatarButton({
|
||||
// disabled: !Accounts_AllowUserAvatarChange,
|
||||
// key: `profile-view-avatar-${service}`,
|
||||
// child: <Avatar avatar={url} size={50} />,
|
||||
// onPress: () =>
|
||||
// this.setAvatar({
|
||||
// url,
|
||||
// data: blob,
|
||||
// service,
|
||||
// contentType
|
||||
// })
|
||||
// });
|
||||
// })}
|
||||
// </View>
|
||||
// );
|
||||
// };
|
||||
|
||||
renderCustomFields = () => {
|
||||
const { customFields } = this.state;
|
||||
|
@ -448,7 +440,7 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
|||
};
|
||||
|
||||
render() {
|
||||
const { name, username, email, newPassword, avatarUrl, customFields, avatar, saving } = this.state;
|
||||
const { name, username, email, newPassword, customFields, avatar, saving } = this.state;
|
||||
const {
|
||||
user,
|
||||
theme,
|
||||
|
@ -457,7 +449,8 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
|||
Accounts_AllowRealNameChange,
|
||||
Accounts_AllowUserAvatarChange,
|
||||
Accounts_AllowUsernameChange,
|
||||
Accounts_CustomFields
|
||||
Accounts_CustomFields,
|
||||
navigation
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
|
@ -469,7 +462,17 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
|||
<SafeAreaView testID='profile-view'>
|
||||
<ScrollView contentContainerStyle={sharedStyles.containerScrollView} testID='profile-view-list' {...scrollPersistTaps}>
|
||||
<View style={styles.avatarContainer} testID='profile-view-avatar'>
|
||||
<Avatar text={user.username} avatar={avatar?.url} isStatic={avatar?.url} size={100} />
|
||||
<Avatar text={user.username} avatar={avatar?.url} isStatic={avatar?.url} size={120} />
|
||||
{Accounts_AllowUserAvatarChange ? (
|
||||
<Touch
|
||||
key={'profile-view-edit-avatar'}
|
||||
testID={'profile-view-edit-avatar'}
|
||||
onPress={() => navigation.navigate('AvatarEditView')}
|
||||
style={[styles.avatarButton, { backgroundColor: themes[theme].borderColor }]}
|
||||
theme={theme}>
|
||||
<Text style={{ color: themes[theme].bodyText }}>Edit</Text>
|
||||
</Touch>
|
||||
) : null}
|
||||
</View>
|
||||
<RCTextInput
|
||||
editable={Accounts_AllowRealNameChange}
|
||||
|
@ -534,28 +537,13 @@ class ProfileView extends React.Component<IProfileViewProps, IProfileViewState>
|
|||
// @ts-ignore
|
||||
return this[Object.keys(customFields)[0]].focus();
|
||||
}
|
||||
this.avatarUrl.focus();
|
||||
this.submit();
|
||||
}}
|
||||
secureTextEntry
|
||||
testID='profile-view-new-password'
|
||||
theme={theme}
|
||||
/>
|
||||
{this.renderCustomFields()}
|
||||
<RCTextInput
|
||||
editable={Accounts_AllowUserAvatarChange}
|
||||
inputStyle={[!Accounts_AllowUserAvatarChange && styles.disabled]}
|
||||
inputRef={e => {
|
||||
this.avatarUrl = e;
|
||||
}}
|
||||
label={I18n.t('Avatar_Url')}
|
||||
placeholder={I18n.t('Avatar_Url')}
|
||||
value={avatarUrl!}
|
||||
onChangeText={value => this.setState({ avatarUrl: value })}
|
||||
onSubmitEditing={this.submit}
|
||||
testID='profile-view-avatar-url'
|
||||
theme={theme}
|
||||
/>
|
||||
{this.renderAvatarButtons()}
|
||||
<Button
|
||||
title={I18n.t('Save_Changes')}
|
||||
type='primary'
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import React from 'react';
|
||||
|
||||
import { TSupportedThemes } from '../theme';
|
||||
import { ProfileStackParamList } from '../stacks/types';
|
||||
import { IUser } from './IUser';
|
||||
import { IBaseScreen, IUser } from '../../definitions';
|
||||
import { TSupportedThemes } from '../../theme';
|
||||
import { ProfileStackParamList } from '../../stacks/types';
|
||||
|
||||
export interface IParams {
|
||||
name: string;
|
||||
|
@ -20,12 +19,7 @@ export interface IAvatarButton {
|
|||
disabled: boolean;
|
||||
}
|
||||
|
||||
export interface INavigationOptions {
|
||||
navigation: StackNavigationProp<ProfileStackParamList, 'ProfileView'>;
|
||||
isMasterDetail?: boolean;
|
||||
}
|
||||
|
||||
export interface IProfileViewProps {
|
||||
export interface IProfileViewProps extends IBaseScreen<ProfileStackParamList, 'ProfileView'> {
|
||||
user: IUser;
|
||||
baseUrl: string;
|
||||
Accounts_AllowEmailChange: boolean;
|
|
@ -16,12 +16,12 @@ export default StyleSheet.create({
|
|||
},
|
||||
avatarButton: {
|
||||
backgroundColor: '#e1e5e8',
|
||||
width: 50,
|
||||
height: 50,
|
||||
width: 48,
|
||||
height: 32,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginRight: 15,
|
||||
marginBottom: 15,
|
||||
marginTop: 16,
|
||||
marginBottom: 24,
|
||||
borderRadius: 2
|
||||
}
|
||||
});
|
||||
|
|
|
@ -32,7 +32,7 @@ import log, { events, logEvent } from '../../utils/log';
|
|||
import { MessageTypeValues } from '../../utils/messageTypes';
|
||||
import random from '../../utils/random';
|
||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||
import { IAvatar } from '../../definitions/IProfileViewInterfaces';
|
||||
import { IAvatar } from '../ProfileView/interfaces';
|
||||
import sharedStyles from '../Styles';
|
||||
import styles from './styles';
|
||||
import SwitchContainer from './SwitchContainer';
|
||||
|
|
Loading…
Reference in New Issue