Handle bad state (#1903)
* Upgrade mattermost-redux * Check if url start with http before pinging * Remove required status prop in settings sidebar * Prevent the app to get into a bad state and if that happens try and recover
This commit is contained in:
parent
360c8cd2e3
commit
01792f2b54
9 changed files with 69 additions and 17 deletions
22
app/app.js
22
app/app.js
|
|
@ -91,12 +91,17 @@ export default class App {
|
|||
const [deviceToken, currentUserId] = usernameParsed;
|
||||
const [token, url] = passwordParsed;
|
||||
|
||||
this.deviceToken = deviceToken;
|
||||
this.currentUserId = currentUserId;
|
||||
this.token = token;
|
||||
this.url = url;
|
||||
Client4.setUrl(url);
|
||||
Client4.setToken(token);
|
||||
// if for any case the url and the token aren't valid proceed with re-hydration
|
||||
if (url && url !== 'undefined' && token && token !== 'undefined') {
|
||||
this.deviceToken = deviceToken;
|
||||
this.currentUserId = currentUserId;
|
||||
this.token = token;
|
||||
this.url = url;
|
||||
Client4.setUrl(url);
|
||||
Client4.setToken(token);
|
||||
} else {
|
||||
this.waitForRehydration = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -161,7 +166,10 @@ export default class App {
|
|||
this.url = url;
|
||||
}
|
||||
|
||||
setGenericPassword(username, password);
|
||||
// Only save to keychain if the url and token are set
|
||||
if (url && token) {
|
||||
setGenericPassword(username, password);
|
||||
}
|
||||
};
|
||||
|
||||
setStartupThemes = (toolbarBackground, toolbarTextColor, appBackground) => {
|
||||
|
|
|
|||
|
|
@ -41,12 +41,13 @@ export default class SettingsDrawer extends PureComponent {
|
|||
currentUser: PropTypes.object.isRequired,
|
||||
deviceWidth: PropTypes.number.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
status: PropTypes.string.isRequired,
|
||||
status: PropTypes.string,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
currentUser: {},
|
||||
status: 'offline',
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import React, {PureComponent} from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import {intlShape} from 'react-intl';
|
||||
import {
|
||||
Alert,
|
||||
AppState,
|
||||
Dimensions,
|
||||
Platform,
|
||||
|
|
@ -22,6 +23,7 @@ import KeyboardLayout from 'app/components/layout/keyboard_layout';
|
|||
import OfflineIndicator from 'app/components/offline_indicator';
|
||||
import SafeAreaView from 'app/components/safe_area_view';
|
||||
import StatusBar from 'app/components/status_bar';
|
||||
import {ViewTypes} from 'app/constants';
|
||||
import mattermostBucket from 'app/mattermost_bucket';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import {makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
|
@ -33,7 +35,6 @@ import LocalConfig from 'assets/config';
|
|||
import ChannelNavBar from './channel_nav_bar';
|
||||
import ChannelPostList from './channel_post_list';
|
||||
|
||||
import {ViewTypes} from 'app/constants';
|
||||
const {
|
||||
ANDROID_TOP_LANDSCAPE,
|
||||
ANDROID_TOP_PORTRAIT,
|
||||
|
|
@ -50,6 +51,7 @@ export default class Channel extends PureComponent {
|
|||
connection: PropTypes.func.isRequired,
|
||||
loadChannelsIfNecessary: PropTypes.func.isRequired,
|
||||
loadProfilesAndTeamMembersForDMSidebar: PropTypes.func.isRequired,
|
||||
logout: PropTypes.func.isRequired,
|
||||
selectDefaultTeam: PropTypes.func.isRequired,
|
||||
selectInitialChannel: PropTypes.func.isRequired,
|
||||
initWebSocket: PropTypes.func.isRequired,
|
||||
|
|
@ -236,8 +238,12 @@ export default class Channel extends PureComponent {
|
|||
handleConnectionChange = (isConnected) => {
|
||||
const {connection} = this.props.actions;
|
||||
|
||||
this.handleWebSocket(isConnected);
|
||||
connection(isConnected);
|
||||
// Prevent for being called more than once.
|
||||
if (this.isConnected !== isConnected) {
|
||||
this.isConnected = isConnected;
|
||||
this.handleWebSocket(isConnected);
|
||||
connection(isConnected);
|
||||
}
|
||||
};
|
||||
|
||||
handleLeaveTeam = () => {
|
||||
|
|
@ -245,6 +251,7 @@ export default class Channel extends PureComponent {
|
|||
};
|
||||
|
||||
initializeWebSocket = async () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {actions} = this.props;
|
||||
const {initWebSocket} = actions;
|
||||
const platform = Platform.OS;
|
||||
|
|
@ -253,7 +260,25 @@ export default class Channel extends PureComponent {
|
|||
certificate = await mattermostBucket.getPreference('cert', LocalConfig.AppGroupId);
|
||||
}
|
||||
|
||||
initWebSocket(platform, null, null, null, {certificate});
|
||||
initWebSocket(platform, null, null, null, {certificate}).catch(() => {
|
||||
// we should dispatch a failure and show the app as disconnected
|
||||
Alert.alert(
|
||||
formatMessage({id: 'mobile.authentication_error.title', defaultMessage: 'Authentication Error'}),
|
||||
formatMessage({
|
||||
id: 'mobile.authentication_error.message',
|
||||
defaultMessage: 'Mattermost has encountered an error. Please re-authenticate to start a new session.',
|
||||
}),
|
||||
[{
|
||||
text: formatMessage({
|
||||
id: 'navbar_dropdown.logout',
|
||||
defaultMessage: 'Logout',
|
||||
}),
|
||||
onPress: actions.logout,
|
||||
}],
|
||||
{cancelable: false}
|
||||
);
|
||||
this.props.actions.closeWebSocket(true);
|
||||
});
|
||||
};
|
||||
|
||||
loadChannels = (teamId) => {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {startPeriodicStatusUpdates, stopPeriodicStatusUpdates} from 'mattermost-redux/actions/users';
|
||||
import {startPeriodicStatusUpdates, stopPeriodicStatusUpdates, logout} from 'mattermost-redux/actions/users';
|
||||
import {init as initWebSocket, close as closeWebSocket} from 'mattermost-redux/actions/websocket';
|
||||
import {RequestStatus} from 'mattermost-redux/constants';
|
||||
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
|
||||
|
|
@ -41,6 +41,7 @@ function mapDispatchToProps(dispatch) {
|
|||
connection,
|
||||
loadChannelsIfNecessary,
|
||||
loadProfilesAndTeamMembersForDMSidebar,
|
||||
logout,
|
||||
selectDefaultTeam,
|
||||
selectInitialChannel,
|
||||
initWebSocket,
|
||||
|
|
|
|||
|
|
@ -111,6 +111,20 @@ function resetStateForNewVersion(action) {
|
|||
lastTeamId = payload.views.team.lastTeamId;
|
||||
}
|
||||
|
||||
const currentChannelId = lastChannelForTeam[lastTeamId] && lastChannelForTeam[lastTeamId].length ? lastChannelForTeam[lastTeamId][0] : '';
|
||||
let channels = initialState.entities.channels;
|
||||
if (payload.entities.channels && currentChannelId) {
|
||||
channels = {
|
||||
currentChannelId,
|
||||
channels: {
|
||||
[currentChannelId]: payload.entities.channels.channels[currentChannelId],
|
||||
},
|
||||
myMembers: {
|
||||
[currentChannelId]: payload.entities.channels.myMembers[currentChannelId],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
let threadDrafts = initialState.views.thread.drafts;
|
||||
if (payload.views.thread && payload.views.thread.drafts) {
|
||||
threadDrafts = payload.views.thread.drafts;
|
||||
|
|
@ -132,6 +146,7 @@ function resetStateForNewVersion(action) {
|
|||
version: DeviceInfo.getVersion(),
|
||||
},
|
||||
entities: {
|
||||
channels,
|
||||
general,
|
||||
teams,
|
||||
users,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {Client4} from 'mattermost-redux/client';
|
|||
const PING_TIMEOUT = 10000;
|
||||
|
||||
export async function checkConnection(isConnected) {
|
||||
if (Client4.getBaseRoute() === '/api/v4') {
|
||||
if (!Client4.getBaseRoute().startsWith('http')) {
|
||||
// If we don't have a server yet, return the default implementation
|
||||
return isConnected;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2309,6 +2309,8 @@
|
|||
"mobile.announcement_banner.dismiss": "Dismiss",
|
||||
"mobile.announcement_banner.ok": "OK",
|
||||
"mobile.announcement_banner.title": "Announcement",
|
||||
"mobile.authentication_error.title": "Authentication Error",
|
||||
"mobile.authentication_error.message": "Mattermost has encountered an error. Please re-authenticate to start a new session.",
|
||||
"mobile.channel.markAsRead": "Mark As Read",
|
||||
"mobile.channel_drawer.search": "Jump to...",
|
||||
"mobile.channel_info.alertMessageDeleteChannel": "Are you sure you want to archive the {term} {name}?",
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -10100,8 +10100,8 @@
|
|||
}
|
||||
},
|
||||
"mattermost-redux": {
|
||||
"version": "github:mattermost/mattermost-redux#9d922ba3f3ed1264f192cbe3c7f0030d249756e3",
|
||||
"from": "github:mattermost/mattermost-redux#9d922ba3f3ed1264f192cbe3c7f0030d249756e3",
|
||||
"version": "github:mattermost/mattermost-redux#ade5924a6e509ea76757bd78a2cc193043a584ce",
|
||||
"from": "github:mattermost/mattermost-redux#ade5924a6e509ea76757bd78a2cc193043a584ce",
|
||||
"requires": {
|
||||
"deep-equal": "1.0.1",
|
||||
"eslint-plugin-header": "1.2.0",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
"intl": "1.2.5",
|
||||
"jail-monkey": "1.0.0",
|
||||
"jsc-android": "216113.0.3",
|
||||
"mattermost-redux": "github:mattermost/mattermost-redux#9d922ba3f3ed1264f192cbe3c7f0030d249756e3",
|
||||
"mattermost-redux": "github:mattermost/mattermost-redux#ade5924a6e509ea76757bd78a2cc193043a584ce",
|
||||
"mime-db": "1.33.0",
|
||||
"prop-types": "15.6.1",
|
||||
"react": "16.3.2",
|
||||
|
|
|
|||
Loading…
Reference in a new issue