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