MM-13830 Ensure schedule of session expired notification (#2554)
* Ensure schedule of session expired notification * feedback review * passing intl instead of message
This commit is contained in:
parent
145842e19e
commit
23e58f2ea1
6 changed files with 71 additions and 76 deletions
|
|
@ -11,6 +11,7 @@ import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
|||
|
||||
import {ViewTypes} from 'app/constants';
|
||||
import {app} from 'app/mattermost';
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
import {getDeviceTimezone, isTimezoneEnabled} from 'app/utils/timezone';
|
||||
|
||||
export function handleLoginIdChanged(loginId) {
|
||||
|
|
@ -67,31 +68,46 @@ export function handleSuccessfulLogin() {
|
|||
};
|
||||
}
|
||||
|
||||
export function getSession() {
|
||||
return async (dispatch, getState) => {
|
||||
export function scheduleExpiredNotification(intl) {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const {currentUserId} = state.entities.users;
|
||||
const {deviceToken} = state.entities.general;
|
||||
const message = intl.formatMessage({
|
||||
id: 'mobile.session_expired',
|
||||
defaultMessage: 'Session Expired: Please log in to continue receiving notifications.',
|
||||
});
|
||||
|
||||
if (!currentUserId || !deviceToken) {
|
||||
return 0;
|
||||
}
|
||||
// Once the user logs in we are going to wait for 10 seconds
|
||||
// before retrieving the session that belongs to this device
|
||||
// to ensure that we get the actual session without issues
|
||||
// then we can schedule the local notification for the session expired
|
||||
setTimeout(async () => {
|
||||
let sessions;
|
||||
try {
|
||||
sessions = await dispatch(getSessions(currentUserId));
|
||||
} catch (e) {
|
||||
console.warn('Failed to get current session', e); // eslint-disable-line no-console
|
||||
return;
|
||||
}
|
||||
|
||||
let sessions;
|
||||
try {
|
||||
sessions = await dispatch(getSessions(currentUserId));
|
||||
} catch (e) {
|
||||
console.warn('Failed to get current session', e); // eslint-disable-line no-console
|
||||
return 0;
|
||||
}
|
||||
if (!Array.isArray(sessions.data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Array.isArray(sessions.data)) {
|
||||
return 0;
|
||||
}
|
||||
const session = sessions.data.find((s) => s.device_id === deviceToken);
|
||||
const expiresAt = session?.expires_at || 0; //eslint-disable-line camelcase
|
||||
|
||||
const session = sessions.data.find((s) => s.device_id === deviceToken);
|
||||
|
||||
return session && session.expires_at ? session.expires_at : 0;
|
||||
if (expiresAt) {
|
||||
PushNotifications.localNotificationSchedule({
|
||||
date: new Date(expiresAt),
|
||||
message,
|
||||
userInfo: {
|
||||
localNotification: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, 10000);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -99,5 +115,5 @@ export default {
|
|||
handleLoginIdChanged,
|
||||
handlePasswordChanged,
|
||||
handleSuccessfulLogin,
|
||||
getSession,
|
||||
scheduleExpiredNotification,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
|
|||
import ErrorText from 'app/components/error_text';
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import StatusBar from 'app/components/status_bar';
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
import {GlobalStyles} from 'app/styles';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import tracker from 'app/utils/time_tracker';
|
||||
|
|
@ -38,7 +37,7 @@ export default class Login extends PureComponent {
|
|||
handleLoginIdChanged: PropTypes.func.isRequired,
|
||||
handlePasswordChanged: PropTypes.func.isRequired,
|
||||
handleSuccessfulLogin: PropTypes.func.isRequired,
|
||||
getSession: PropTypes.func.isRequired,
|
||||
scheduleExpiredNotification: PropTypes.func.isRequired,
|
||||
checkMfa: PropTypes.func.isRequired,
|
||||
login: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
|
|
@ -68,7 +67,7 @@ export default class Login extends PureComponent {
|
|||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.loginRequest.status === RequestStatus.STARTED && nextProps.loginRequest.status === RequestStatus.SUCCESS) {
|
||||
this.props.actions.handleSuccessfulLogin().then(this.props.actions.getSession).then(this.goToChannel);
|
||||
this.props.actions.handleSuccessfulLogin().then(this.goToChannel);
|
||||
} else if (this.props.loginRequest.status !== nextProps.loginRequest.status && nextProps.loginRequest.status !== RequestStatus.STARTED) {
|
||||
this.setState({isLoading: false});
|
||||
}
|
||||
|
|
@ -78,23 +77,11 @@ export default class Login extends PureComponent {
|
|||
Dimensions.removeEventListener('change', this.orientationDidChange);
|
||||
}
|
||||
|
||||
goToChannel = (expiresAt) => {
|
||||
const {intl} = this.context;
|
||||
goToChannel = () => {
|
||||
const {navigator} = this.props;
|
||||
tracker.initialLoad = Date.now();
|
||||
|
||||
if (expiresAt) {
|
||||
PushNotifications.localNotificationSchedule({
|
||||
date: new Date(expiresAt),
|
||||
message: intl.formatMessage({
|
||||
id: 'mobile.session_expired',
|
||||
defaultMessage: 'Session Expired: Please log in to continue receiving notifications.',
|
||||
}),
|
||||
userInfo: {
|
||||
localNotification: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
this.scheduleSessionExpiredNotification();
|
||||
|
||||
navigator.resetTo({
|
||||
screen: 'Channel',
|
||||
|
|
@ -208,6 +195,13 @@ export default class Login extends PureComponent {
|
|||
});
|
||||
});
|
||||
|
||||
scheduleSessionExpiredNotification = () => {
|
||||
const {intl} = this.context;
|
||||
const {actions} = this.props;
|
||||
|
||||
actions.scheduleExpiredNotification(intl);
|
||||
};
|
||||
|
||||
signIn = () => {
|
||||
const {actions, loginId, loginRequest, password} = this.props;
|
||||
if (loginRequest.status !== RequestStatus.STARTED) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {getPing, resetPing, setServerVersion} from 'mattermost-redux/actions/gen
|
|||
import {login} from 'mattermost-redux/actions/users';
|
||||
|
||||
import {setLastUpgradeCheck} from 'app/actions/views/client_upgrade';
|
||||
import {getSession, handleSuccessfulLogin} from 'app/actions/views/login';
|
||||
import {handleSuccessfulLogin, scheduleExpiredNotification} from 'app/actions/views/login';
|
||||
import {loadConfigAndLicense} from 'app/actions/views/root';
|
||||
import {handleServerUrlChanged} from 'app/actions/views/select_server';
|
||||
import getClientUpgrade from 'app/selectors/client_upgrade';
|
||||
|
|
@ -39,7 +39,7 @@ function mapDispatchToProps(dispatch) {
|
|||
actions: bindActionCreators({
|
||||
handleSuccessfulLogin,
|
||||
getPing,
|
||||
getSession,
|
||||
scheduleExpiredNotification,
|
||||
handleServerUrlChanged,
|
||||
loadConfigAndLicense,
|
||||
login,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import FormattedText from 'app/components/formatted_text';
|
|||
import {UpgradeTypes} from 'app/constants';
|
||||
import fetchConfig from 'app/fetch_preconfig';
|
||||
import mattermostBucket from 'app/mattermost_bucket';
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
import {GlobalStyles} from 'app/styles';
|
||||
import checkUpgradeType from 'app/utils/client_upgrade';
|
||||
import {isValidUrl, stripTrailingSlashes} from 'app/utils/url';
|
||||
|
|
@ -44,7 +43,7 @@ export default class SelectServer extends PureComponent {
|
|||
getPing: PropTypes.func.isRequired,
|
||||
handleServerUrlChanged: PropTypes.func.isRequired,
|
||||
handleSuccessfulLogin: PropTypes.func.isRequired,
|
||||
getSession: PropTypes.func.isRequired,
|
||||
scheduleExpiredNotification: PropTypes.func.isRequired,
|
||||
loadConfigAndLicense: PropTypes.func.isRequired,
|
||||
login: PropTypes.func.isRequired,
|
||||
resetPing: PropTypes.func.isRequired,
|
||||
|
|
@ -283,26 +282,13 @@ export default class SelectServer extends PureComponent {
|
|||
};
|
||||
|
||||
loginWithCertificate = async () => {
|
||||
const {intl, navigator} = this.props;
|
||||
const {navigator} = this.props;
|
||||
|
||||
tracker.initialLoad = Date.now();
|
||||
|
||||
await this.props.actions.login('credential', 'password');
|
||||
await this.props.actions.handleSuccessfulLogin();
|
||||
const expiresAt = await this.props.actions.getSession();
|
||||
|
||||
if (expiresAt) {
|
||||
PushNotifications.localNotificationSchedule({
|
||||
date: new Date(expiresAt),
|
||||
message: intl.formatMessage({
|
||||
id: 'mobile.session_expired',
|
||||
defaultMessage: 'Session Expired: Please log in to continue receiving notifications.',
|
||||
}),
|
||||
userInfo: {
|
||||
localNotification: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
this.scheduleSessionExpiredNotification();
|
||||
|
||||
navigator.resetTo({
|
||||
screen: 'Channel',
|
||||
|
|
@ -380,6 +366,13 @@ export default class SelectServer extends PureComponent {
|
|||
});
|
||||
};
|
||||
|
||||
scheduleSessionExpiredNotification = () => {
|
||||
const {intl} = this.context;
|
||||
const {actions} = this.props;
|
||||
|
||||
actions.scheduleExpiredNotification(intl);
|
||||
};
|
||||
|
||||
selectCertificate = () => {
|
||||
const url = this.getUrl();
|
||||
RNFetchBlob.cba.selectCertificate((certificate) => {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {getSession, handleSuccessfulLogin} from 'app/actions/views/login';
|
||||
import {handleSuccessfulLogin, scheduleExpiredNotification} from 'app/actions/views/login';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {setStoreFromLocalData} from 'mattermost-redux/actions/general';
|
||||
|
|
@ -21,7 +21,7 @@ function mapStateToProps(state) {
|
|||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
getSession,
|
||||
scheduleExpiredNotification,
|
||||
handleSuccessfulLogin,
|
||||
setStoreFromLocalData,
|
||||
}, dispatch),
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import {Client4} from 'mattermost-redux/client';
|
|||
import {ViewTypes} from 'app/constants';
|
||||
import Loading from 'app/components/loading';
|
||||
import StatusBar from 'app/components/status_bar';
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
import tracker from 'app/utils/time_tracker';
|
||||
|
||||
|
|
@ -66,7 +65,7 @@ class SSO extends PureComponent {
|
|||
serverUrl: PropTypes.string.isRequired,
|
||||
ssoType: PropTypes.string.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
getSession: PropTypes.func.isRequired,
|
||||
scheduleExpiredNotification: PropTypes.func.isRequired,
|
||||
handleSuccessfulLogin: PropTypes.func.isRequired,
|
||||
setStoreFromLocalData: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
|
|
@ -104,22 +103,11 @@ class SSO extends PureComponent {
|
|||
});
|
||||
};
|
||||
|
||||
goToLoadTeam = (expiresAt) => {
|
||||
const {intl, navigator} = this.props;
|
||||
goToChannel = () => {
|
||||
const {navigator} = this.props;
|
||||
tracker.initialLoad = Date.now();
|
||||
|
||||
if (expiresAt) {
|
||||
PushNotifications.localNotificationSchedule({
|
||||
date: new Date(expiresAt),
|
||||
message: intl.formatMessage({
|
||||
id: 'mobile.session_expired',
|
||||
defaultMessage: 'Session Expired: Please log in to continue receiving notifications.',
|
||||
}),
|
||||
userInfo: {
|
||||
localNotification: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
this.scheduleSessionExpiredNotification();
|
||||
|
||||
navigator.resetTo({
|
||||
screen: 'Channel',
|
||||
|
|
@ -182,7 +170,6 @@ class SSO extends PureComponent {
|
|||
if (token) {
|
||||
this.setState({renderWebView: false});
|
||||
const {
|
||||
getSession,
|
||||
handleSuccessfulLogin,
|
||||
setStoreFromLocalData,
|
||||
} = this.props.actions;
|
||||
|
|
@ -190,8 +177,7 @@ class SSO extends PureComponent {
|
|||
Client4.setToken(token);
|
||||
setStoreFromLocalData({url: Client4.getUrl(), token}).
|
||||
then(handleSuccessfulLogin).
|
||||
then(getSession).
|
||||
then(this.goToLoadTeam).
|
||||
then(this.goToChannel).
|
||||
catch(this.onLoadEndError);
|
||||
} else if (this.webView && !this.state.error) {
|
||||
this.webView.injectJavaScript(postMessageJS);
|
||||
|
|
@ -205,6 +191,12 @@ class SSO extends PureComponent {
|
|||
this.setState({error: e.message});
|
||||
};
|
||||
|
||||
scheduleSessionExpiredNotification = () => {
|
||||
const {actions, intl} = this.props;
|
||||
|
||||
actions.scheduleExpiredNotification(intl);
|
||||
};
|
||||
|
||||
renderLoading = () => {
|
||||
return <Loading/>;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue