diff --git a/app/init/fetch.js b/app/init/fetch.js index 293c0fe57..bb8f2fb14 100644 --- a/app/init/fetch.js +++ b/app/init/fetch.js @@ -7,7 +7,7 @@ import RNFetchBlob from 'rn-fetch-blob'; import urlParse from 'url-parse'; import {Client4} from 'mattermost-redux/client'; -import {ClientError} from 'mattermost-redux/client/client4'; +import {ClientError, HEADER_X_VERSION_ID} from 'mattermost-redux/client/client4'; import mattermostBucket from 'app/mattermost_bucket'; import mattermostManaged from 'app/mattermost_managed'; @@ -111,6 +111,13 @@ Client4.doFetchWithResponse = async (url, options) => { Client4.setToken(token); } + if (headers[HEADER_X_VERSION_ID] && !headers['Cache-Control']) { + const serverVersion = headers[HEADER_X_VERSION_ID]; + if (serverVersion && Client4.serverVersion !== serverVersion) { + Client4.serverVersion = serverVersion; /* eslint-disable-line require-atomic-updates */ + } + } + if (response.ok) { const headersMap = new Map(); Object.keys(headers).forEach((key) => { diff --git a/app/screens/select_team/index.js b/app/screens/select_team/index.js index 944e483c7..2c55c91a0 100644 --- a/app/screens/select_team/index.js +++ b/app/screens/select_team/index.js @@ -4,7 +4,7 @@ import {bindActionCreators} from 'redux'; import {connect} from 'react-redux'; -import {getTeams, joinTeam} from 'mattermost-redux/actions/teams'; +import {getTeams, addUserToTeam, joinTeam} from 'mattermost-redux/actions/teams'; import {logout} from 'mattermost-redux/actions/users'; import {getJoinableTeams} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentUser} from 'mattermost-redux/selectors/entities/users'; @@ -22,7 +22,9 @@ function mapStateToProps(state) { teamsRequest: state.requests.teams.getTeams, teams: getJoinableTeams(state), isLandscape: isLandscape(state), + currentUserId: currentUser && currentUser.id, currentUserIsGuest, + serverVersion: state.entities.general.serverVersion, }; } @@ -32,6 +34,7 @@ function mapDispatchToProps(dispatch) { getTeams, handleTeamChange, joinTeam, + addUserToTeam, logout, }, dispatch), }; diff --git a/app/screens/select_team/select_team.js b/app/screens/select_team/select_team.js index 9e34ac395..d2c65a731 100644 --- a/app/screens/select_team/select_team.js +++ b/app/screens/select_team/select_team.js @@ -14,6 +14,7 @@ import {Navigation} from 'react-native-navigation'; import {RequestStatus} from 'mattermost-redux/constants'; import EventEmitter from 'mattermost-redux/utils/event_emitter'; +import {isMinimumServerVersion} from 'mattermost-redux/utils/helpers'; import FormattedText from 'app/components/formatted_text'; import Loading from 'app/components/loading'; @@ -34,16 +35,19 @@ export default class SelectTeam extends PureComponent { getTeams: PropTypes.func.isRequired, handleTeamChange: PropTypes.func.isRequired, joinTeam: PropTypes.func.isRequired, + addUserToTeam: PropTypes.func.isRequired, logout: PropTypes.func.isRequired, }).isRequired, componentId: PropTypes.string.isRequired, currentUrl: PropTypes.string.isRequired, currentUserIsGuest: PropTypes.bool.isRequired, + currentUserId: PropTypes.string.isRequired, userWithoutTeams: PropTypes.bool, teams: PropTypes.array.isRequired, theme: PropTypes.object, teamsRequest: PropTypes.object.isRequired, isLandscape: PropTypes.bool.isRequired, + serverVersion: PropTypes.string, }; static defaultProps = { @@ -128,13 +132,21 @@ export default class SelectTeam extends PureComponent { onSelectTeam = async (team) => { this.setState({joining: true}); - const {userWithoutTeams} = this.props; + const {userWithoutTeams, currentUserId, serverVersion} = this.props; const { joinTeam, + addUserToTeam, handleTeamChange, } = this.props.actions; - const {error} = await joinTeam(team.invite_id, team.id); + let error; + if (isMinimumServerVersion(serverVersion, 5, 18)) { + const result = await addUserToTeam(team.id, currentUserId); + error = result.error; + } else { + const result = await joinTeam(team.invite_id, team.id); + error = result.error; + } if (error) { Alert.alert(error.message); this.setState({joining: false}); diff --git a/app/screens/select_team/select_team.test.js b/app/screens/select_team/select_team.test.js index 587bed05a..bd680f892 100644 --- a/app/screens/select_team/select_team.test.js +++ b/app/screens/select_team/select_team.test.js @@ -27,6 +27,7 @@ describe('SelectTeam', () => { const actions = { getTeams, handleTeamChange: jest.fn(), + addUserToTeam: jest.fn(), joinTeam: jest.fn(), logout: jest.fn(), }; @@ -35,6 +36,7 @@ describe('SelectTeam', () => { actions, currentChannelId: 'someId', currentUserIsGuest: false, + currentUserId: 'fakeid', currentUrl: 'test', userWithoutTeams: false, teams: [], @@ -44,6 +46,7 @@ describe('SelectTeam', () => { }, componentId: 'component-id', isLandscape: false, + serverVersion: '5.18', }; test('should match snapshot for fail of teams', async () => { @@ -100,4 +103,34 @@ describe('SelectTeam', () => { await getTeams(); expect(wrapper.getElement()).toMatchSnapshot(); }); + + test('should call joinTeam versions prior to 5.18', async () => { + const props = { + ...baseProps, + serverVersion: '5.17', + }; + + const wrapper = shallow( + , + ); + wrapper.instance().onSelectTeam({id: 'test_id', invite_id: 'test_invite_id'}); + + expect(props.actions.joinTeam).toBeCalledWith('test_invite_id', 'test_id'); + expect(props.actions.addUserToTeam).not.toBeCalled(); + }); + + test('should call joinTeam versions posterior to 5.18', async () => { + const props = { + ...baseProps, + serverVersion: '5.18', + }; + + const wrapper = shallow( + , + ); + wrapper.instance().onSelectTeam({id: 'test_id', invite_id: 'test_invite_id'}); + + expect(props.actions.joinTeam).not.toBeCalled(); + expect(props.actions.addUserToTeam).toBeCalledWith('test_id', 'fakeid'); + }); }); diff --git a/package-lock.json b/package-lock.json index f16826d97..090722fdb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4311,7 +4311,7 @@ "dependencies": { "json5": { "version": "0.5.1", - "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true } @@ -7217,9 +7217,10 @@ } }, "mattermost-redux": { - "version": "github:mattermost/mattermost-redux#4e3dedd8323430bf8bbd9338a2577f43b3ef5ab7", - "from": "github:mattermost/mattermost-redux#4e3dedd8323430bf8bbd9338a2577f43b3ef5ab7", + "version": "github:mattermost/mattermost-redux#01b1ec33aece728954df6d93b214dadb28e65063", + "from": "github:mattermost/mattermost-redux#01b1ec33aece728954df6d93b214dadb28e65063", "requires": { + "core-js": "3.1.4", "form-data": "2.5.1", "gfycat-sdk": "1.4.18", "isomorphic-fetch": "2.2.1", @@ -7236,6 +7237,11 @@ "shallow-equals": "1.0.0" }, "dependencies": { + "core-js": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz", + "integrity": "sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==" + }, "moment-timezone": { "version": "0.5.26", "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.26.tgz", @@ -8285,7 +8291,7 @@ } }, "mmjstool": { - "version": "github:mattermost/mattermost-utilities#ce99d7a9e82128a02fd36e44720a4aef2653810d", + "version": "github:mattermost/mattermost-utilities#b3e2e308b8b85469849a91c21958b46a89ab33ab", "from": "github:mattermost/mattermost-utilities", "dev": true, "requires": { diff --git a/package.json b/package.json index 7e32d06f3..85fd2aeeb 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "intl": "1.2.5", "jail-monkey": "2.3.0", "jsc-android": "241213.1.0", - "mattermost-redux": "github:mattermost/mattermost-redux#4e3dedd8323430bf8bbd9338a2577f43b3ef5ab7", + "mattermost-redux": "github:mattermost/mattermost-redux#01b1ec33aece728954df6d93b214dadb28e65063", "mime-db": "1.42.0", "moment-timezone": "0.5.27", "prop-types": "15.7.2",