Chore: Migrate SettingsView to hooks (#4542)
* migrate settings view to hooks * temp - add non-null assertion * fix options * Update app/views/SettingsView/index.tsx Co-authored-by: Reinaldo Neto <47038980+reinaldonetof@users.noreply.github.com> * Update app/views/SettingsView/index.tsx Co-authored-by: Reinaldo Neto <47038980+reinaldonetof@users.noreply.github.com> * fix options Co-authored-by: Reinaldo Neto <47038980+reinaldonetof@users.noreply.github.com>
This commit is contained in:
parent
e08ad19530
commit
b1a62b589f
|
@ -165,7 +165,7 @@ const SettingsStackNavigator = () => {
|
|||
<SettingsStack.Navigator
|
||||
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}
|
||||
>
|
||||
<SettingsStack.Screen name='SettingsView' component={SettingsView} options={SettingsView.navigationOptions} />
|
||||
<SettingsStack.Screen name='SettingsView' component={SettingsView} />
|
||||
<SettingsStack.Screen name='SecurityPrivacyView' component={SecurityPrivacyView} />
|
||||
<SettingsStack.Screen
|
||||
name='E2EEncryptionSecurityView'
|
||||
|
|
|
@ -170,11 +170,7 @@ const ModalStackNavigator = React.memo(({ navigation }: INavigation) => {
|
|||
component={ReadReceiptsView}
|
||||
options={props => ReadReceiptsView.navigationOptions!({ ...props, isMasterDetail: true })}
|
||||
/>
|
||||
<ModalStack.Screen
|
||||
name='SettingsView'
|
||||
component={SettingsView}
|
||||
options={props => SettingsView.navigationOptions!({ ...props, isMasterDetail: true })}
|
||||
/>
|
||||
<ModalStack.Screen name='SettingsView' component={SettingsView} />
|
||||
<ModalStack.Screen name='LanguageView' component={LanguageView} />
|
||||
<ModalStack.Screen name='ThemeView' component={ThemeView} />
|
||||
<ModalStack.Screen name='DefaultBrowserView' component={DefaultBrowserView} />
|
||||
|
|
|
@ -1,47 +1,51 @@
|
|||
import CookieManager from '@react-native-cookies/cookies';
|
||||
import { StackNavigationOptions } from '@react-navigation/stack';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import React from 'react';
|
||||
import { Linking, Share } from 'react-native';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import { connect } from 'react-redux';
|
||||
import CookieManager from '@react-native-cookies/cookies';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import React, { useLayoutEffect } from 'react';
|
||||
import { Linking, Share } from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { StackNavigationProp } from '@react-navigation/stack';
|
||||
|
||||
import { appStart } from '../../actions/app';
|
||||
import { logout } from '../../actions/login';
|
||||
import { selectServerRequest } from '../../actions/server';
|
||||
import { APP_STORE_LINK, FDROID_MARKET_LINK, LICENSE_LINK, PLAY_MARKET_LINK, isFDroidBuild, themes } from '../../lib/constants';
|
||||
import * as HeaderButton from '../../containers/HeaderButton';
|
||||
import * as List from '../../containers/List';
|
||||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
import { LISTENER } from '../../containers/Toast';
|
||||
import { IApplicationState, IBaseScreen, IUser, RootEnum } from '../../definitions';
|
||||
import { RootEnum } from '../../definitions';
|
||||
import I18n from '../../i18n';
|
||||
import { APP_STORE_LINK, FDROID_MARKET_LINK, isFDroidBuild, LICENSE_LINK, PLAY_MARKET_LINK } from '../../lib/constants';
|
||||
import database from '../../lib/database';
|
||||
import { IServer } from '../../reducers/server';
|
||||
import { getUserSelector } from '../../selectors/login';
|
||||
import { SettingsStackParamList } from '../../stacks/types';
|
||||
import { withTheme } from '../../theme';
|
||||
import { useAppSelector } from '../../lib/hooks';
|
||||
import { clearCache } from '../../lib/methods';
|
||||
import { deleteAllAudioFiles } from '../../lib/methods/audioFile';
|
||||
import { getDeviceModel, getReadableVersion, isAndroid } from '../../lib/methods/helpers';
|
||||
import EventEmitter from '../../lib/methods/helpers/events';
|
||||
import { showConfirmationAlert, showErrorAlert } from '../../lib/methods/helpers/info';
|
||||
import { events, logEvent } from '../../lib/methods/helpers/log';
|
||||
import openLink from '../../lib/methods/helpers/openLink';
|
||||
import { onReviewPress } from '../../lib/methods/helpers/review';
|
||||
import SidebarView from '../SidebarView';
|
||||
import { clearCache } from '../../lib/methods';
|
||||
import { Services } from '../../lib/services';
|
||||
import { deleteAllAudioFiles } from '../../lib/methods/audioFile';
|
||||
import { getUserSelector } from '../../selectors/login';
|
||||
import { SettingsStackParamList } from '../../stacks/types';
|
||||
import { useTheme } from '../../theme';
|
||||
import SidebarView from '../SidebarView';
|
||||
|
||||
type TLogScreenName = 'SE_GO_LANGUAGE' | 'SE_GO_DEFAULTBROWSER' | 'SE_GO_THEME' | 'SE_GO_PROFILE' | 'SE_GO_SECURITYPRIVACY';
|
||||
|
||||
interface ISettingsViewProps extends IBaseScreen<SettingsStackParamList, 'SettingsView'> {
|
||||
server: IServer;
|
||||
user: IUser;
|
||||
}
|
||||
const SettingsView = (): React.ReactElement => {
|
||||
const { colors, theme } = useTheme();
|
||||
const navigation = useNavigation<StackNavigationProp<SettingsStackParamList, 'SettingsView'>>();
|
||||
const dispatch = useDispatch();
|
||||
const isMasterDetail = useAppSelector(state => state.app.isMasterDetail);
|
||||
const userId = useAppSelector(state => getUserSelector(state).id);
|
||||
const { server, version } = useAppSelector(state => state.server);
|
||||
|
||||
class SettingsView extends React.Component<ISettingsViewProps> {
|
||||
static navigationOptions = ({ navigation, isMasterDetail }: ISettingsViewProps): StackNavigationOptions => ({
|
||||
useLayoutEffect(() => {
|
||||
navigation.setOptions({
|
||||
headerLeft: () =>
|
||||
isMasterDetail ? (
|
||||
<HeaderButton.CloseModal navigation={navigation} testID='settings-view-close' />
|
||||
|
@ -50,13 +54,13 @@ class SettingsView extends React.Component<ISettingsViewProps> {
|
|||
),
|
||||
title: I18n.t('Settings')
|
||||
});
|
||||
}, [navigation, isMasterDetail]);
|
||||
|
||||
checkCookiesAndLogout = async () => {
|
||||
const { dispatch, user } = this.props;
|
||||
const checkCookiesAndLogout = async () => {
|
||||
const db = database.servers;
|
||||
const usersCollection = db.get('users');
|
||||
try {
|
||||
const userRecord = await usersCollection.find(user.id);
|
||||
const userRecord = await usersCollection.find(userId);
|
||||
if (userRecord.isFromWebView) {
|
||||
showConfirmationAlert({
|
||||
title: I18n.t('Clear_cookies_alert'),
|
||||
|
@ -79,25 +83,21 @@ class SettingsView extends React.Component<ISettingsViewProps> {
|
|||
}
|
||||
};
|
||||
|
||||
handleLogout = () => {
|
||||
const handleLogout = () => {
|
||||
logEvent(events.SE_LOG_OUT);
|
||||
showConfirmationAlert({
|
||||
message: I18n.t('You_will_be_logged_out_of_this_application'),
|
||||
confirmationText: I18n.t('Logout'),
|
||||
onPress: this.checkCookiesAndLogout
|
||||
onPress: checkCookiesAndLogout
|
||||
});
|
||||
};
|
||||
|
||||
handleClearCache = () => {
|
||||
const handleClearCache = () => {
|
||||
logEvent(events.SE_CLEAR_LOCAL_SERVER_CACHE);
|
||||
showConfirmationAlert({
|
||||
message: I18n.t('This_will_clear_all_your_offline_data'),
|
||||
confirmationText: I18n.t('Clear'),
|
||||
onPress: async () => {
|
||||
const {
|
||||
server: { server },
|
||||
dispatch
|
||||
} = this.props;
|
||||
dispatch(appStart({ root: RootEnum.ROOT_LOADING, text: I18n.t('Clear_cache_loading') }));
|
||||
await deleteAllAudioFiles(server);
|
||||
await clearCache({ server });
|
||||
|
@ -109,14 +109,13 @@ class SettingsView extends React.Component<ISettingsViewProps> {
|
|||
});
|
||||
};
|
||||
|
||||
navigateToScreen = (screen: keyof SettingsStackParamList) => {
|
||||
const navigateToScreen = (screen: keyof SettingsStackParamList) => {
|
||||
const screenName = screen.replace('View', '').toUpperCase();
|
||||
logEvent(events[`SE_GO_${screenName}` as TLogScreenName]);
|
||||
const { navigation } = this.props;
|
||||
navigation.navigate(screen);
|
||||
};
|
||||
|
||||
sendEmail = async () => {
|
||||
const sendEmail = async () => {
|
||||
logEvent(events.SE_CONTACT_US);
|
||||
const subject = encodeURI('Rocket.Chat Mobile App Support');
|
||||
const email = encodeURI('support@rocket.chat');
|
||||
|
@ -132,7 +131,7 @@ class SettingsView extends React.Component<ISettingsViewProps> {
|
|||
}
|
||||
};
|
||||
|
||||
shareApp = () => {
|
||||
const shareApp = () => {
|
||||
let message;
|
||||
if (isAndroid) {
|
||||
message = PLAY_MARKET_LINK;
|
||||
|
@ -145,33 +144,27 @@ class SettingsView extends React.Component<ISettingsViewProps> {
|
|||
Share.share({ message });
|
||||
};
|
||||
|
||||
copyServerVersion = () => {
|
||||
const {
|
||||
server: { version }
|
||||
} = this.props;
|
||||
const vers = version as string;
|
||||
logEvent(events.SE_COPY_SERVER_VERSION, { serverVersion: vers });
|
||||
this.saveToClipboard(vers);
|
||||
};
|
||||
|
||||
copyAppVersion = () => {
|
||||
logEvent(events.SE_COPY_APP_VERSION, { appVersion: getReadableVersion });
|
||||
this.saveToClipboard(getReadableVersion);
|
||||
};
|
||||
|
||||
saveToClipboard = async (content: string) => {
|
||||
const saveToClipboard = async (content: string) => {
|
||||
await Clipboard.setString(content);
|
||||
EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') });
|
||||
};
|
||||
|
||||
onPressLicense = () => {
|
||||
const copyServerVersion = () => {
|
||||
const vers = version as string;
|
||||
logEvent(events.SE_COPY_SERVER_VERSION, { serverVersion: vers });
|
||||
saveToClipboard(vers);
|
||||
};
|
||||
|
||||
const copyAppVersion = () => {
|
||||
logEvent(events.SE_COPY_APP_VERSION, { appVersion: getReadableVersion });
|
||||
saveToClipboard(getReadableVersion);
|
||||
};
|
||||
|
||||
const onPressLicense = () => {
|
||||
logEvent(events.SE_READ_LICENSE);
|
||||
const { theme } = this.props;
|
||||
openLink(LICENSE_LINK, theme);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { server, isMasterDetail, theme } = this.props;
|
||||
return (
|
||||
<SafeAreaView testID='settings-view'>
|
||||
<StatusBar />
|
||||
|
@ -180,16 +173,16 @@ class SettingsView extends React.Component<ISettingsViewProps> {
|
|||
<>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<SidebarView theme={theme} />
|
||||
<SidebarView />
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item title='Display' onPress={() => this.navigateToScreen('DisplayPrefsView')} showActionIndicator />
|
||||
<List.Item title='Display' onPress={() => navigateToScreen('DisplayPrefsView')} showActionIndicator />
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Profile'
|
||||
onPress={() => this.navigateToScreen('ProfileView')}
|
||||
onPress={() => navigateToScreen('ProfileView')}
|
||||
showActionIndicator
|
||||
testID='settings-profile'
|
||||
/>
|
||||
|
@ -200,46 +193,41 @@ class SettingsView extends React.Component<ISettingsViewProps> {
|
|||
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item title='Contact_us' onPress={this.sendEmail} showActionIndicator testID='settings-view-contact' />
|
||||
<List.Item title='Contact_us' onPress={sendEmail} showActionIndicator testID='settings-view-contact' />
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Language'
|
||||
onPress={() => this.navigateToScreen('LanguageView')}
|
||||
onPress={() => navigateToScreen('LanguageView')}
|
||||
showActionIndicator
|
||||
testID='settings-view-language'
|
||||
/>
|
||||
<List.Separator />
|
||||
{!isFDroidBuild ? (
|
||||
<>
|
||||
<List.Item
|
||||
title='Review_this_app'
|
||||
showActionIndicator
|
||||
onPress={onReviewPress}
|
||||
testID='settings-view-review-app'
|
||||
/>
|
||||
<List.Item title='Review_this_app' showActionIndicator onPress={onReviewPress} testID='settings-view-review-app' />
|
||||
</>
|
||||
) : null}
|
||||
<List.Separator />
|
||||
<List.Item title='Share_this_app' showActionIndicator onPress={this.shareApp} testID='settings-view-share-app' />
|
||||
<List.Item title='Share_this_app' showActionIndicator onPress={shareApp} testID='settings-view-share-app' />
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Default_browser'
|
||||
showActionIndicator
|
||||
onPress={() => this.navigateToScreen('DefaultBrowserView')}
|
||||
onPress={() => navigateToScreen('DefaultBrowserView')}
|
||||
testID='settings-view-default-browser'
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Theme'
|
||||
showActionIndicator
|
||||
onPress={() => this.navigateToScreen('ThemeView')}
|
||||
onPress={() => navigateToScreen('ThemeView')}
|
||||
testID='settings-view-theme'
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Security_and_privacy'
|
||||
showActionIndicator
|
||||
onPress={() => this.navigateToScreen('SecurityPrivacyView')}
|
||||
onPress={() => navigateToScreen('SecurityPrivacyView')}
|
||||
testID='settings-view-security-privacy'
|
||||
/>
|
||||
<List.Separator />
|
||||
|
@ -247,19 +235,19 @@ class SettingsView extends React.Component<ISettingsViewProps> {
|
|||
|
||||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item title='License' onPress={this.onPressLicense} showActionIndicator testID='settings-view-license' />
|
||||
<List.Item title='License' onPress={onPressLicense} showActionIndicator testID='settings-view-license' />
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title={I18n.t('Version_no', { version: getReadableVersion })}
|
||||
onPress={this.copyAppVersion}
|
||||
onPress={copyAppVersion}
|
||||
testID='settings-view-version'
|
||||
translateTitle={false}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title={I18n.t('Server_version', { version: server.version })}
|
||||
onPress={this.copyServerVersion}
|
||||
subtitle={`${server.server.split('//')[1]}`}
|
||||
title={I18n.t('Server_version', { version })}
|
||||
onPress={copyServerVersion}
|
||||
subtitle={`${server.split('//')[1]}`}
|
||||
testID='settings-view-server-version'
|
||||
translateTitle={false}
|
||||
translateSubtitle={false}
|
||||
|
@ -272,30 +260,23 @@ class SettingsView extends React.Component<ISettingsViewProps> {
|
|||
<List.Item
|
||||
title='Clear_cache'
|
||||
testID='settings-view-clear-cache'
|
||||
onPress={this.handleClearCache}
|
||||
onPress={handleClearCache}
|
||||
showActionIndicator
|
||||
color={themes[theme].dangerColor}
|
||||
color={colors.dangerColor}
|
||||
/>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Logout'
|
||||
testID='settings-logout'
|
||||
onPress={this.handleLogout}
|
||||
onPress={handleLogout}
|
||||
showActionIndicator
|
||||
color={themes[theme].dangerColor}
|
||||
color={colors.dangerColor}
|
||||
/>
|
||||
<List.Separator />
|
||||
</List.Section>
|
||||
</List.Container>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const mapStateToProps = (state: IApplicationState) => ({
|
||||
server: state.server,
|
||||
user: getUserSelector(state),
|
||||
isMasterDetail: state.app.isMasterDetail
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(withTheme(SettingsView));
|
||||
export default SettingsView;
|
||||
|
|
|
@ -32,7 +32,7 @@ interface ISidebarProps {
|
|||
state?: DrawerNavigationState<DrawerParamList>;
|
||||
Site_Name: string;
|
||||
user: IUser;
|
||||
theme: TSupportedThemes;
|
||||
theme?: TSupportedThemes;
|
||||
loadingServer: boolean;
|
||||
useRealName: boolean;
|
||||
allowStatusMessage: boolean;
|
||||
|
@ -167,10 +167,10 @@ class Sidebar extends Component<ISidebarProps, ISidebarState> {
|
|||
<List.Separator />
|
||||
<SidebarItem
|
||||
text={I18n.t('Admin_Panel')}
|
||||
left={<CustomIcon name='settings' size={20} color={themes[theme].titleText} />}
|
||||
left={<CustomIcon name='settings' size={20} color={themes[theme!].titleText} />}
|
||||
onPress={() => this.sidebarNavigate(routeName)}
|
||||
testID='sidebar-admin'
|
||||
theme={theme}
|
||||
theme={theme!}
|
||||
current={this.currentItemKey === routeName}
|
||||
/>
|
||||
</>
|
||||
|
@ -183,34 +183,34 @@ class Sidebar extends Component<ISidebarProps, ISidebarState> {
|
|||
<>
|
||||
<SidebarItem
|
||||
text={I18n.t('Chats')}
|
||||
left={<CustomIcon name='message' size={20} color={themes[theme].titleText} />}
|
||||
left={<CustomIcon name='message' size={20} color={themes[theme!].titleText} />}
|
||||
onPress={() => this.sidebarNavigate('ChatsStackNavigator')}
|
||||
testID='sidebar-chats'
|
||||
theme={theme}
|
||||
theme={theme!}
|
||||
current={this.currentItemKey === 'ChatsStackNavigator'}
|
||||
/>
|
||||
<SidebarItem
|
||||
text={I18n.t('Profile')}
|
||||
left={<CustomIcon name='user' size={20} color={themes[theme].titleText} />}
|
||||
left={<CustomIcon name='user' size={20} color={themes[theme!].titleText} />}
|
||||
onPress={() => this.sidebarNavigate('ProfileStackNavigator')}
|
||||
testID='sidebar-profile'
|
||||
theme={theme}
|
||||
theme={theme!}
|
||||
current={this.currentItemKey === 'ProfileStackNavigator'}
|
||||
/>
|
||||
<SidebarItem
|
||||
text={I18n.t('Display')}
|
||||
left={<CustomIcon name='sort' size={20} color={themes[theme].titleText} />}
|
||||
left={<CustomIcon name='sort' size={20} color={themes[theme!].titleText} />}
|
||||
onPress={() => this.sidebarNavigate('DisplayPrefStackNavigator')}
|
||||
testID='sidebar-display'
|
||||
theme={theme}
|
||||
theme={theme!}
|
||||
current={this.currentItemKey === 'DisplayPrefStackNavigator'}
|
||||
/>
|
||||
<SidebarItem
|
||||
text={I18n.t('Settings')}
|
||||
left={<CustomIcon name='administration' size={20} color={themes[theme].titleText} />}
|
||||
left={<CustomIcon name='administration' size={20} color={themes[theme!].titleText} />}
|
||||
onPress={() => this.sidebarNavigate('SettingsStackNavigator')}
|
||||
testID='sidebar-settings'
|
||||
theme={theme}
|
||||
theme={theme!}
|
||||
current={this.currentItemKey === 'SettingsStackNavigator'}
|
||||
/>
|
||||
{this.renderAdmin()}
|
||||
|
@ -224,8 +224,8 @@ class Sidebar extends Component<ISidebarProps, ISidebarState> {
|
|||
<SidebarItem
|
||||
text={user.statusText || I18n.t('Edit_Status')}
|
||||
left={<Status size={24} status={user?.status} />}
|
||||
theme={theme}
|
||||
right={<CustomIcon name='edit' size={20} color={themes[theme].titleText} />}
|
||||
theme={theme!}
|
||||
right={<CustomIcon name='edit' size={20} color={themes[theme!].titleText} />}
|
||||
onPress={() => this.sidebarNavigate('StatusView')}
|
||||
testID={`sidebar-custom-status-${user.status}`}
|
||||
/>
|
||||
|
@ -239,12 +239,12 @@ class Sidebar extends Component<ISidebarProps, ISidebarState> {
|
|||
return null;
|
||||
}
|
||||
return (
|
||||
<SafeAreaView testID='sidebar-view' style={{ backgroundColor: themes[theme].focusedBackground }} vertical={isMasterDetail}>
|
||||
<SafeAreaView testID='sidebar-view' style={{ backgroundColor: themes[theme!].focusedBackground }} vertical={isMasterDetail}>
|
||||
<ScrollView
|
||||
style={[
|
||||
styles.container,
|
||||
{
|
||||
backgroundColor: isMasterDetail ? themes[theme].backgroundColor : themes[theme].focusedBackground
|
||||
backgroundColor: isMasterDetail ? themes[theme!].backgroundColor : themes[theme!].focusedBackground
|
||||
}
|
||||
]}
|
||||
{...scrollPersistTaps}
|
||||
|
@ -254,12 +254,12 @@ class Sidebar extends Component<ISidebarProps, ISidebarState> {
|
|||
<Avatar text={user.username} style={styles.avatar} size={30} />
|
||||
<View style={styles.headerTextContainer}>
|
||||
<View style={styles.headerUsername}>
|
||||
<Text numberOfLines={1} style={[styles.username, { color: themes[theme].titleText }]}>
|
||||
<Text numberOfLines={1} style={[styles.username, { color: themes[theme!].titleText }]}>
|
||||
{useRealName ? user.name : user.username}
|
||||
</Text>
|
||||
</View>
|
||||
<Text
|
||||
style={[styles.currentServerText, { color: themes[theme].titleText }]}
|
||||
style={[styles.currentServerText, { color: themes[theme!].titleText }]}
|
||||
numberOfLines={1}
|
||||
accessibilityLabel={`Connected to ${baseUrl}`}
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue