From 155df774bc5ce5356222d8e16ca395d46a2aac56 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Wed, 5 Feb 2020 12:12:40 -0300 Subject: [PATCH] [NEW] Clear cache (#1660) --- app/actions/login.js | 5 +- app/i18n/locales/en.js | 2 + app/lib/rocketchat.js | 21 +++++++++ app/sagas/init.js | 2 + app/sagas/login.js | 48 ++++++++++++------- app/views/SettingsView/index.js | 80 ++++++++++++++++++-------------- app/views/SettingsView/styles.js | 7 ++- app/views/SidebarView/index.js | 23 ++------- 8 files changed, 110 insertions(+), 78 deletions(-) diff --git a/app/actions/login.js b/app/actions/login.js index 455c4fa14..999de3e0e 100644 --- a/app/actions/login.js +++ b/app/actions/login.js @@ -22,9 +22,10 @@ export function loginFailure(err) { }; } -export function logout() { +export function logout(forcedByServer = false) { return { - type: types.LOGOUT + type: types.LOGOUT, + forcedByServer }; } diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js index ef8b2565d..6d3a3d474 100644 --- a/app/i18n/locales/en.js +++ b/app/i18n/locales/en.js @@ -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', @@ -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.', diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 7b1556fcd..75d343c54 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -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(); diff --git a/app/sagas/init.js b/app/sagas/init.js index 3ed8e136e..80aff1ee2 100644 --- a/app/sagas/init.js +++ b/app/sagas/init.js @@ -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(); }; diff --git a/app/sagas/login.js b/app/sagas/login.js index 2cfcb7498..dff0eed7d 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -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'; @@ -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); @@ -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)); } @@ -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); @@ -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); } }; diff --git a/app/views/SettingsView/index.js b/app/views/SettingsView/index.js index 93c41f507..d9e24a457 100644 --- a/app/views/SettingsView/index.js +++ b/app/views/SettingsView/index.js @@ -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'; @@ -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'; @@ -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 }) => ( @@ -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 = () => { @@ -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; @@ -163,25 +177,6 @@ class SettingsView extends React.Component { return ; } - renderLogout = () => { - const { theme } = this.props; - return ( - <> - - - - - - ); - } - renderMarkdownSwitch = () => { const { useMarkdown } = this.props; return ( @@ -210,20 +205,18 @@ class SettingsView extends React.Component { {split ? ( <> + - ) : null} + this.renderMarkdownSwitch()} theme={theme} /> - - - + - { split ? this.renderLogout() : null } + + + + + ); @@ -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))); diff --git a/app/views/SettingsView/styles.js b/app/views/SettingsView/styles.js index 64c393fe6..d1eb323c3 100644 --- a/app/views/SettingsView/styles.js +++ b/app/views/SettingsView/styles.js @@ -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, diff --git a/app/views/SidebarView/index.js b/app/views/SidebarView/index.js index 2d7d784ce..7a83fb9ef 100644 --- a/app/views/SidebarView/index.js +++ b/app/views/SidebarView/index.js @@ -8,7 +8,6 @@ import equal from 'deep-equal'; import { Q } from '@nozbe/watermelondb'; import Touch from '../../utils/touch'; -import { logout as logoutAction } from '../../actions/login'; import Avatar from '../../containers/Avatar'; import Status from '../../containers/Status/Status'; import RocketChat from '../../lib/rocketchat'; @@ -44,7 +43,6 @@ class Sidebar extends Component { navigation: PropTypes.object, Site_Name: PropTypes.string.isRequired, user: PropTypes.object, - logout: PropTypes.func.isRequired, activeItemKey: PropTypes.string, theme: PropTypes.string, loadingServer: PropTypes.bool, @@ -157,11 +155,6 @@ class Sidebar extends Component { } } - logout = () => { - const { logout } = this.props; - logout(); - } - sidebarNavigate = (route) => { const { navigation } = this.props; navigation.navigate(route); @@ -228,13 +221,6 @@ class Sidebar extends Component { current={activeItemKey === 'AdminPanelStack'} /> ) : null} - - } - onPress={this.logout} - testID='sidebar-logout' - /> ); } @@ -298,10 +284,11 @@ class Sidebar extends Component { - {!split || showStatus ? : null} + {!split ? : null} {!showStatus && !split ? this.renderNavigation() : null} {showStatus ? this.renderStatus() : null} + {!split ? : null} ); @@ -322,8 +309,4 @@ const mapStateToProps = state => ({ loadingServer: state.server.loading }); -const mapDispatchToProps = dispatch => ({ - logout: () => dispatch(logoutAction()) -}); - -export default connect(mapStateToProps, mapDispatchToProps)(withTheme(withSplit(Sidebar))); +export default connect(mapStateToProps)(withTheme(withSplit(Sidebar)));