Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions app/actions/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ export function loginFailure(err) {
};
}

export function logout() {
export function logout(forcedByServer = false) {
return {
type: types.LOGOUT
type: types.LOGOUT,
forcedByServer
};
}

Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export default {
Copy: 'Copy',
Permalink: 'Permalink',
Certificate_password: 'Certificate Password',
Clear_cache: 'Clear local server cache',
Whats_the_password_for_your_certificate: 'What\'s the password for your certificate?',
Create_account: 'Create an account',
Create_Channel: 'Create Channel',
Expand Down Expand Up @@ -466,6 +467,7 @@ export default {
you_were_mentioned: 'you were mentioned',
you: 'you',
You: 'You',
Logged_out_by_server: 'You\'ve been logged out by the server. Please log in again.',
You_need_to_access_at_least_one_RocketChat_server_to_share_something: 'You need to access at least one Rocket.Chat server to share something.',
Your_certificate: 'Your Certificate',
Your_invite_link_will_expire_after__usesLeft__uses: 'Your invite link will expire after {{usesLeft}} uses.',
Expand Down
21 changes: 21 additions & 0 deletions app/lib/rocketchat.js
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,27 @@ const RocketChat = {
console.log(error);
}
},
async clearCache({ server }) {
try {
const serversDB = database.servers;
await serversDB.action(async() => {
const serverCollection = serversDB.collections.get('servers');
const serverRecord = await serverCollection.find(server);
await serverRecord.update((s) => {
s.roomsUpdatedAt = null;
});
});
} catch (e) {
// Do nothing
}

try {
const db = database.active;
await db.action(() => db.unsafeResetDatabase());
} catch (e) {
// Do nothing
}
},
registerPushToken() {
return new Promise(async(resolve) => {
const token = getDeviceToken();
Expand Down
2 changes: 2 additions & 0 deletions app/sagas/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ const start = function* start({ root }) {
yield Navigation.navigate('SetUsernameView');
} else if (root === 'outside') {
yield Navigation.navigate('OutsideStack');
} else if (root === 'loading') {
yield Navigation.navigate('AuthLoading');
}
RNBootSplash.hide();
};
Expand Down
50 changes: 31 additions & 19 deletions app/sagas/login.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
put, call, takeLatest, select, take, fork, cancel
put, call, takeLatest, select, take, fork, cancel, race, delay
} from 'redux-saga/effects';
import RNUserDefaults from 'rn-user-defaults';
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
Expand All @@ -19,8 +19,8 @@ import log from '../utils/log';
import I18n from '../i18n';
import database from '../lib/database';
import EventEmitter from '../utils/events';
import Navigation from '../lib/Navigation';
import { inviteLinksRequest } from '../actions/inviteLinks';
import { showErrorAlert } from '../utils/info';

const getServer = state => state.server.server;
const loginWithPasswordCall = args => RocketChat.loginWithPassword(args);
Expand All @@ -38,7 +38,7 @@ const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnE
return yield put(loginSuccess(result));
} catch (e) {
if (logoutOnError && (e.data && e.data.message && /you've been logged out by the server/i.test(e.data.message))) {
yield put(logout());
yield put(logout(true));
} else {
yield put(loginFailure(e));
}
Expand Down Expand Up @@ -142,27 +142,35 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) {
}
};

const handleLogout = function* handleLogout() {
Navigation.navigate('AuthLoading');
const handleLogout = function* handleLogout({ forcedByServer }) {
yield put(appStart('loading'));
const server = yield select(getServer);
if (server) {
try {
yield call(logoutCall, { server });
const serversDB = database.servers;
// all servers
const serversCollection = serversDB.collections.get('servers');
const servers = yield serversCollection.query().fetch();

// see if there're other logged in servers and selects first one
if (servers.length > 0) {
const newServer = servers[0].id;
const token = yield RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ newServer }`);
if (token) {
return yield put(selectServerRequest(newServer));

// if the user was logged out by the server
if (forcedByServer) {
yield put(appStart('outside'));
showErrorAlert(I18n.t('Logged_out_by_server'), I18n.t('Oops'));
EventEmitter.emit('NewServer', { server });
} else {
const serversDB = database.servers;
// all servers
const serversCollection = serversDB.collections.get('servers');
const servers = yield serversCollection.query().fetch();

// see if there're other logged in servers and selects first one
if (servers.length > 0) {
const newServer = servers[0].id;
const token = yield RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ newServer }`);
if (token) {
return yield put(selectServerRequest(newServer));
}
}
// if there's no servers, go outside
yield put(appStart('outside'));
}
// if there's no servers, go outside
yield put(appStart('outside'));
} catch (e) {
yield put(appStart('outside'));
log(e);
Expand All @@ -185,7 +193,11 @@ const root = function* root() {
while (true) {
const params = yield take(types.LOGIN.SUCCESS);
const loginSuccessTask = yield fork(handleLoginSuccess, params);
yield take(types.SERVER.SELECT_REQUEST);
// yield take(types.SERVER.SELECT_REQUEST);
yield race({
selectRequest: take(types.SERVER.SELECT_REQUEST),
timeout: delay(2000)
});
yield cancel(loginSuccessTask);
}
};
Expand Down
80 changes: 46 additions & 34 deletions app/views/SettingsView/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react';
import {
View, Linking, ScrollView, AsyncStorage, SafeAreaView, Switch, Text, Share, Clipboard
View, Linking, ScrollView, AsyncStorage, Switch, Text, Share, Clipboard
} from 'react-native';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { SafeAreaView } from 'react-navigation';

import { logout as logoutAction } from '../../actions/login';
import { logout as logoutAction, loginRequest as loginRequestAction } from '../../actions/login';
import { toggleMarkdown as toggleMarkdownAction } from '../../actions/markdown';
import { toggleCrashReport as toggleCrashReportAction } from '../../actions/crashReport';
import { SWITCH_TRACK_COLOR, themes } from '../../constants/colors';
Expand All @@ -15,7 +16,7 @@ import ListItem from '../../containers/ListItem';
import { DisclosureImage } from '../../containers/DisclosureIndicator';
import Separator from '../../containers/Separator';
import I18n from '../../i18n';
import { MARKDOWN_KEY, CRASH_REPORT_KEY } from '../../lib/rocketchat';
import RocketChat, { MARKDOWN_KEY, CRASH_REPORT_KEY } from '../../lib/rocketchat';
import {
getReadableVersion, getDeviceModel, isAndroid
} from '../../utils/deviceInfo';
Expand All @@ -33,6 +34,7 @@ import { withSplit } from '../../split';
import Navigation from '../../lib/Navigation';
import { LISTENER } from '../../containers/Toast';
import EventEmitter from '../../utils/events';
import { appStart as appStartAction } from '../../actions';
import { onReviewPress } from '../../utils/review';

const SectionSeparator = React.memo(({ theme }) => (
Expand Down Expand Up @@ -80,7 +82,10 @@ class SettingsView extends React.Component {
toggleCrashReport: PropTypes.func,
theme: PropTypes.string,
split: PropTypes.bool,
logout: PropTypes.func.isRequired
logout: PropTypes.func.isRequired,
loginRequest: PropTypes.func,
token: PropTypes.string,
appStart: PropTypes.func
}

logout = () => {
Expand All @@ -91,6 +96,15 @@ class SettingsView extends React.Component {
logout();
}

clearCache = async() => {
const {
server: { server }, loginRequest, token, appStart
} = this.props;
await appStart('loading');
await RocketChat.clearCache({ server });
await loginRequest({ resume: token }, true);
}

toggleMarkdown = (value) => {
AsyncStorage.setItem(MARKDOWN_KEY, JSON.stringify(value));
const { toggleMarkdown } = this.props;
Expand Down Expand Up @@ -163,25 +177,6 @@ class SettingsView extends React.Component {
return <DisclosureImage theme={theme} />;
}

renderLogout = () => {
const { theme } = this.props;
return (
<>
<Separator theme={theme} />
<ListItem
title={I18n.t('Logout')}
testID='settings-logout'
onPress={this.logout}
right={this.renderDisclosure}
color={themes[theme].dangerColor}
theme={theme}
/>
<Separator theme={theme} />
<ItemInfo theme={theme} />
</>
);
}

renderMarkdownSwitch = () => {
const { useMarkdown } = this.props;
return (
Expand Down Expand Up @@ -210,20 +205,18 @@ class SettingsView extends React.Component {
<SafeAreaView
style={[sharedStyles.container, { backgroundColor: themes[theme].auxiliaryBackground }]}
testID='settings-view'
forceInset={{ vertical: 'never' }}
>
<StatusBar theme={theme} />
<ScrollView
{...scrollPersistTaps}
contentContainerStyle={[
sharedStyles.listContentContainer,
styles.listWithoutBorderBottom,
{ borderColor: themes[theme].separatorColor }
]}
contentContainerStyle={styles.listPadding}
showsVerticalScrollIndicator={false}
testID='settings-view-list'
>
{split ? (
<>
<Separator theme={theme} />
<SidebarView theme={theme} />
<SectionSeparator theme={theme} />
<ListItem
Expand All @@ -234,10 +227,10 @@ class SettingsView extends React.Component {
right={this.renderDisclosure}
theme={theme}
/>
<Separator theme={theme} />
</>
) : null}

<Separator theme={theme} />
<ListItem
title={I18n.t('Contact_us')}
onPress={this.sendEmail}
Expand Down Expand Up @@ -319,9 +312,7 @@ class SettingsView extends React.Component {
right={() => this.renderMarkdownSwitch()}
theme={theme}
/>

<SectionSeparator theme={theme} />

<Separator theme={theme} />
<ListItem
title={I18n.t('Send_crash_report')}
testID='settings-view-crash-report'
Expand All @@ -334,7 +325,25 @@ class SettingsView extends React.Component {
theme={theme}
/>

{ split ? this.renderLogout() : null }
<Separator theme={theme} />
<ListItem
title={I18n.t('Clear_cache')}
testID='settings-clear-cache'
onPress={this.clearCache}
right={this.renderDisclosure}
color={themes[theme].dangerColor}
theme={theme}
/>
<Separator theme={theme} />
<ListItem
title={I18n.t('Logout')}
testID='settings-logout'
onPress={this.logout}
right={this.renderDisclosure}
color={themes[theme].dangerColor}
theme={theme}
/>
<Separator theme={theme} />
</ScrollView>
</SafeAreaView>
);
Expand All @@ -343,14 +352,17 @@ class SettingsView extends React.Component {

const mapStateToProps = state => ({
server: state.server,
token: state.login.user && state.login.user.token,
useMarkdown: state.markdown.useMarkdown,
allowCrashReport: state.crashReport.allowCrashReport
});

const mapDispatchToProps = dispatch => ({
logout: () => dispatch(logoutAction()),
loginRequest: (...params) => dispatch(loginRequestAction(...params)),
toggleMarkdown: params => dispatch(toggleMarkdownAction(params)),
toggleCrashReport: params => dispatch(toggleCrashReportAction(params))
toggleCrashReport: params => dispatch(toggleCrashReportAction(params)),
appStart: params => dispatch(appStartAction(params))
});

export default connect(mapStateToProps, mapDispatchToProps)(withTheme(withSplit(SettingsView)));
7 changes: 3 additions & 4 deletions app/views/SettingsView/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ export default StyleSheet.create({
...sharedStyles.separatorVertical,
height: 36
},
listWithoutBorderBottom: {
borderBottomWidth: 0
listPadding: {
paddingVertical: 36
},
infoContainer: {
padding: 15,
marginBottom: 40
padding: 15
},
infoText: {
fontSize: 14,
Expand Down
Loading