diff --git a/app/actions/views/more_dms.js b/app/actions/views/more_dms.js index 1a3bf595e..8ae2d1d3a 100644 --- a/app/actions/views/more_dms.js +++ b/app/actions/views/more_dms.js @@ -20,11 +20,13 @@ export function makeDirectChannel(otherUserId) { if (channel && myMembers[channel.id]) { toggleDMChannel(otherUserId, 'true')(dispatch, getState); handleSelectChannel(channel.id)(dispatch, getState); - } else { - const created = await createDirectChannel(currentUserId, otherUserId)(dispatch, getState); - if (created) { - handleSelectChannel(created.id)(dispatch, getState); - } + return true; } + const created = await createDirectChannel(currentUserId, otherUserId)(dispatch, getState); + if (created) { + handleSelectChannel(created.id)(dispatch, getState); + } + + return created; }; } diff --git a/app/actions/views/user_profile.js b/app/actions/views/user_profile.js deleted file mode 100644 index 4ea6a46cd..000000000 --- a/app/actions/views/user_profile.js +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import {makeDirectChannel} from 'app/actions/views/more_dms'; - -export function handleSendMessage(otherUserId) { - return async (dispatch, getState) => { - await makeDirectChannel(otherUserId)(dispatch, getState); - }; -} diff --git a/app/components/channel_drawer/channel_drawer.js b/app/components/channel_drawer/channel_drawer.js index bedc5a1bf..434553f6c 100644 --- a/app/components/channel_drawer/channel_drawer.js +++ b/app/components/channel_drawer/channel_drawer.js @@ -11,6 +11,7 @@ import { } from 'react-native'; import Drawer from 'app/components/drawer'; +import {alertErrorWithFallback} from 'app/utils/general'; import ChannelsList from './channels_list'; import Swiper from './swiper'; @@ -29,15 +30,18 @@ export default class ChannelDrawer extends PureComponent { viewChannel: PropTypes.func.isRequired, makeDirectChannel: PropTypes.func.isRequired, markChannelAsRead: PropTypes.func.isRequired, + setChannelDisplayName: PropTypes.func.isRequired, setChannelLoading: PropTypes.func.isRequired }).isRequired, blurPostTextBox: PropTypes.func.isRequired, children: PropTypes.node, channels: PropTypes.object, currentChannel: PropTypes.object, + currentDisplayName: PropTypes.string, channelMembers: PropTypes.object, currentTeam: PropTypes.object, currentUserId: PropTypes.string.isRequired, + intl: PropTypes.object.isRequired, myTeamMembers: PropTypes.object.isRequired, navigator: PropTypes.object, theme: PropTypes.object.isRequired @@ -162,12 +166,14 @@ export default class ChannelDrawer extends PureComponent { }); }; - joinChannel = (channel) => { + joinChannel = async (channel) => { const { actions, currentChannel, + currentDisplayName, currentTeam, - currentUserId + currentUserId, + intl } = this.props; const { @@ -175,27 +181,46 @@ export default class ChannelDrawer extends PureComponent { joinChannel, makeDirectChannel, markChannelAsRead, + setChannelDisplayName, setChannelLoading, viewChannel } = actions; + markChannelAsRead(currentChannel.id); + setChannelLoading(); + viewChannel(currentChannel.id); + setChannelDisplayName(channel.display_name); + + const displayValue = {displayName: channel.display_name}; + if (channel.type === General.DM_CHANNEL) { - markChannelAsRead(currentChannel.id); - setChannelLoading(); - viewChannel(currentChannel.id); - this.closeChannelDrawer(); - InteractionManager.runAfterInteractions(() => { - makeDirectChannel(channel.id); - }); + const result = await makeDirectChannel(channel.id); + if (result.error) { + const dmFailedMessage = { + id: 'mobile.open_dm.error', + defaultMessage: "We couldn't open a direct message with {displayName}. Please check your connection and try again." + }; + setChannelDisplayName(currentDisplayName); + alertErrorWithFallback(intl, result.error, dmFailedMessage, displayValue); + } else { + this.closeChannelDrawer(); + } } else { - markChannelAsRead(currentChannel.id); - setChannelLoading(); - viewChannel(currentChannel.id); - joinChannel(currentUserId, currentTeam.id, channel.id); - this.closeChannelDrawer(); - InteractionManager.runAfterInteractions(() => { - handleSelectChannel(channel.id); - }); + const result = await joinChannel(currentUserId, currentTeam.id, channel.id); + + if (result.error) { + const joinFailedMessage = { + id: 'mobile.join_channel.error', + defaultMessage: "We couldn't join the channel {displayName}. Please check your connection and try again." + }; + setChannelDisplayName(currentDisplayName); + alertErrorWithFallback(intl, result.error, joinFailedMessage, displayValue); + } else { + this.closeChannelDrawer(); + InteractionManager.runAfterInteractions(() => { + handleSelectChannel(channel.id); + }); + } } }; diff --git a/app/components/channel_drawer/channels_list/filtered_list/filtered_list.js b/app/components/channel_drawer/channels_list/filtered_list/filtered_list.js index 2b404773c..627a9fa7b 100644 --- a/app/components/channel_drawer/channels_list/filtered_list/filtered_list.js +++ b/app/components/channel_drawer/channels_list/filtered_list/filtered_list.js @@ -27,8 +27,7 @@ class ChannelDrawerList extends Component { actions: PropTypes.shape({ makeGroupMessageVisibleIfNecessary: PropTypes.func.isRequired, searchChannels: PropTypes.func.isRequired, - searchProfiles: PropTypes.func.isRequired, - setChannelDisplayName: PropTypes.func.isRequired + searchProfiles: PropTypes.func.isRequired }).isRequired, channels: PropTypes.object.isRequired, channelMembers: PropTypes.object, @@ -40,7 +39,6 @@ class ChannelDrawerList extends Component { myPreferences: PropTypes.object, myTeamMembers: PropTypes.object.isRequired, navigator: PropTypes.object, - onJoinChannel: PropTypes.func.isRequired, onSearchEnds: PropTypes.func.isRequired, onSearchStart: PropTypes.func.isRequired, onSelectChannel: PropTypes.func.isRequired, @@ -88,12 +86,8 @@ class ChannelDrawerList extends Component { } onSelectChannel = (channel) => { - const { - makeGroupMessageVisibleIfNecessary, - setChannelDisplayName - } = this.props.actions; + const {makeGroupMessageVisibleIfNecessary} = this.props.actions; - setChannelDisplayName(channel.display_name); if (channel.type === General.GM_CHANNEL) { makeGroupMessageVisibleIfNecessary(channel.id); } diff --git a/app/components/channel_drawer/channels_list/filtered_list/index.js b/app/components/channel_drawer/channels_list/filtered_list/index.js index 9a29afcff..e985c029b 100644 --- a/app/components/channel_drawer/channels_list/filtered_list/index.js +++ b/app/components/channel_drawer/channels_list/filtered_list/index.js @@ -11,8 +11,6 @@ import {getUserIdsInChannels, getUsers, getUserStatuses} from 'mattermost-redux/ import {getGroupChannels, getOtherChannels} from 'mattermost-redux/selectors/entities/channels'; import {getMyPreferences} from 'mattermost-redux/selectors/entities/preferences'; -import {setChannelDisplayName} from 'app/actions/views/channel'; - import FilteredList from './filtered_list'; function mapStateToProps(state, ownProps) { @@ -35,8 +33,7 @@ function mapDispatchToProps(dispatch) { actions: bindActionCreators({ makeGroupMessageVisibleIfNecessary, searchChannels, - searchProfiles, - setChannelDisplayName + searchProfiles }, dispatch) }; } diff --git a/app/components/channel_drawer/index.js b/app/components/channel_drawer/index.js index 988461370..a3c48623e 100644 --- a/app/components/channel_drawer/index.js +++ b/app/components/channel_drawer/index.js @@ -9,7 +9,7 @@ import {getTeams} from 'mattermost-redux/actions/teams'; import {getChannelsWithUnreadSection, getCurrentChannel} from 'mattermost-redux/selectors/entities/channels'; import {getCurrentTeam, getTeamMemberships} from 'mattermost-redux/selectors/entities/teams'; -import {handleSelectChannel, setChannelLoading} from 'app/actions/views/channel'; +import {handleSelectChannel, setChannelDisplayName, setChannelLoading} from 'app/actions/views/channel'; import {makeDirectChannel} from 'app/actions/views/more_dms'; import {getTheme} from 'app/selectors/preferences'; @@ -22,6 +22,7 @@ function mapStateToProps(state, ownProps) { ...ownProps, currentTeam: getCurrentTeam(state), currentChannel: getCurrentChannel(state), + currentDisplayName: state.views.channel.displayName, currentUserId, channels: getChannelsWithUnreadSection(state), channelMembers: state.entities.channels.myMembers, @@ -39,6 +40,7 @@ function mapDispatchToProps(dispatch) { viewChannel, makeDirectChannel, markChannelAsRead, + setChannelDisplayName, setChannelLoading }, dispatch) }; diff --git a/app/screens/channel/channel.js b/app/screens/channel/channel.js index c5ca16cd8..ce16bb1d2 100644 --- a/app/screens/channel/channel.js +++ b/app/screens/channel/channel.js @@ -167,6 +167,7 @@ class Channel extends PureComponent { const { currentTeam, currentChannel, + intl, navigator, theme } = this.props; @@ -186,6 +187,7 @@ class Channel extends PureComponent { return ( diff --git a/app/screens/channel/channel_post_list/channel_post_list.js b/app/screens/channel/channel_post_list/channel_post_list.js index 19e88bc64..dc24fa192 100644 --- a/app/screens/channel/channel_post_list/channel_post_list.js +++ b/app/screens/channel/channel_post_list/channel_post_list.js @@ -30,7 +30,7 @@ class ChannelPostList extends PureComponent { channel: PropTypes.object.isRequired, channelIsLoading: PropTypes.bool, channelIsRefreshing: PropTypes.bool, - channelName: PropTypes.string, + currentChannelId: PropTypes.string, intl: intlShape.isRequired, loadingPosts: PropTypes.bool, myMember: PropTypes.object.isRequired, @@ -60,7 +60,7 @@ class ChannelPostList extends PureComponent { componentWillReceiveProps(nextProps) { // Show the loader if the channel names change - if (this.props.channelName !== nextProps.channelName) { + if (this.props.currentChannelId !== nextProps.currentChannelId) { this.setState({ loaderOpacity: new Animated.Value(1) }); @@ -146,7 +146,7 @@ class ChannelPostList extends PureComponent { const {channelLoaded, loaderOpacity} = this.state; let component; - if (!posts.length && channel.total_msg_count > 0 && !networkOnline) { + if (!posts.length && channel.total_msg_count > 0 && (!channelIsLoading || !networkOnline)) { // If no posts has been loaded and we are offline component = ( { - this.props.actions.deleteChannel(channel.id).then(() => { + onPressAction = async () => { + const result = await this.props.actions.deleteChannel(channel.id); + if (result.error) { + alertErrorWithFallback( + this.props.intl, + result.error, + { + id: 'mobile.channel_info.delete_failed', + defaultMessage: "We couldn't delete the channel {displayName}. Please check your connection and try again." + }, + { + displayName: channel.display_name + } + ); + } else { this.close(); - }); + } }; } diff --git a/app/screens/more_channels/index.js b/app/screens/more_channels/index.js index 58b9c891e..8cd58fb7d 100644 --- a/app/screens/more_channels/index.js +++ b/app/screens/more_channels/index.js @@ -6,7 +6,7 @@ import {connect} from 'react-redux'; import {General} from 'mattermost-redux/constants'; import {getChannels, joinChannel, searchChannels} from 'mattermost-redux/actions/channels'; -import {getOtherChannels} from 'mattermost-redux/selectors/entities/channels'; +import {getChannelsInCurrentTeam, getMyChannelMemberships} from 'mattermost-redux/selectors/entities/channels'; import {getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users'; import {showCreateOption} from 'mattermost-redux/utils/channel_utils'; import {isAdmin, isSystemAdmin} from 'mattermost-redux/utils/user_utils'; @@ -22,7 +22,10 @@ function mapStateToProps(state, ownProps) { const {getChannels: requestStatus} = state.requests.channels; const {config, license} = state.entities.general; const roles = getCurrentUserRoles(state); - const channels = getOtherChannels(state); + const myMembers = getMyChannelMemberships(state); + const channels = getChannelsInCurrentTeam(state).filter((c) => { + return (!myMembers[c.id] && c.type === General.OPEN_CHANNEL); + }); return { ...ownProps, diff --git a/app/screens/more_channels/more_channels.js b/app/screens/more_channels/more_channels.js index 028f0f62b..772cc2859 100644 --- a/app/screens/more_channels/more_channels.js +++ b/app/screens/more_channels/more_channels.js @@ -19,6 +19,7 @@ import ChannelListRow from 'app/components/custom_list/channel_list_row'; import Loading from 'app/components/loading'; import SearchBar from 'app/components/search_bar'; import StatusBar from 'app/components/status_bar'; +import {alertErrorWithFallback} from 'app/utils/general'; import {makeStyleSheetFromTheme, changeOpacity} from 'app/utils/theme'; class MoreChannels extends PureComponent { @@ -202,25 +203,42 @@ class MoreChannels extends PureComponent { }; onSelectChannel = async (id) => { - const {actions, currentTeamId, currentUserId} = this.props; + const {actions, currentTeamId, currentUserId, intl} = this.props; const {channels} = this.state; this.emitCanCreateChannel(false); this.setState({adding: true}); - await actions.joinChannel(currentUserId, currentTeamId, id); const channel = channels.find((c) => c.id === id); - if (channel) { - actions.setChannelDisplayName(channel.display_name); - } else { - actions.setChannelDisplayName(''); - } - await actions.handleSelectChannel(id); + const result = await actions.joinChannel(currentUserId, currentTeamId, id); - EventEmitter.emit('close_channel_drawer'); - InteractionManager.runAfterInteractions(() => { - this.close(); - }); + if (result.error) { + alertErrorWithFallback( + intl, + result.error, + { + id: 'mobile.join_channel.error', + defaultMessage: "We couldn't join the channel {displayName}. Please check your connection and try again." + }, + { + displayName: channel ? channel.display_name : '' + } + ); + this.emitCanCreateChannel(true); + this.setState({adding: false}); + } else { + if (channel) { + actions.setChannelDisplayName(channel.display_name); + } else { + actions.setChannelDisplayName(''); + } + await actions.handleSelectChannel(id); + + EventEmitter.emit('close_channel_drawer'); + InteractionManager.runAfterInteractions(() => { + this.close(); + }); + } }; onCreateChannel = () => { diff --git a/app/screens/more_dms/index.js b/app/screens/more_dms/index.js index 9a3a919f3..d142668e8 100644 --- a/app/screens/more_dms/index.js +++ b/app/screens/more_dms/index.js @@ -14,6 +14,7 @@ import MoreDirectMessages from './more_dms'; function mapStateToProps(state, ownProps) { const {getProfiles: requestStatus, searchProfiles: searchRequest} = state.requests.users; + const {createChannel: createChannelRequest} = state.requests.channels; function getUsers() { const {profiles, currentUserId} = state.entities.users; @@ -32,6 +33,8 @@ function mapStateToProps(state, ownProps) { preferences: getMyPreferences(state), profiles: getUsers(), theme: getTheme(state), + currentDisplayName: state.views.channel.displayName, + createChannelRequest, requestStatus, searchRequest }; diff --git a/app/screens/more_dms/more_dms.js b/app/screens/more_dms/more_dms.js index f654dadaa..594fe3c67 100644 --- a/app/screens/more_dms/more_dms.js +++ b/app/screens/more_dms/more_dms.js @@ -18,16 +18,19 @@ import Loading from 'app/components/loading'; import MemberList from 'app/components/custom_list'; import SearchBar from 'app/components/search_bar'; import StatusBar from 'app/components/status_bar'; +import {alertErrorWithFallback} from 'app/utils/general'; import {createMembersSections, loadingText, renderMemberRow} from 'app/utils/member_list'; import {makeStyleSheetFromTheme, changeOpacity} from 'app/utils/theme'; class MoreDirectMessages extends PureComponent { static propTypes = { + currentDisplayName: PropTypes.string, intl: intlShape.isRequired, navigator: PropTypes.object, preferences: PropTypes.object.isRequired, theme: PropTypes.object.isRequired, profiles: PropTypes.array, + createChannelRequest: PropTypes.object.isRequired, requestStatus: PropTypes.object.isRequired, searchRequest: PropTypes.object.isRequired, actions: PropTypes.shape({ @@ -60,11 +63,11 @@ class MoreDirectMessages extends PureComponent { nextProps.requestStatus.status === RequestStatus.SUCCESS) { const {page} = this.state; const profiles = nextProps.profiles.splice(0, (page + 1) * General.PROFILE_CHUNK_SIZE); - this.setState({profiles, showNoResults: true}); + this.setState({profiles, showNoResults: true, error: null}); } else if (this.state.searching && nextProps.searchRequest.status === RequestStatus.SUCCESS) { const results = filterProfilesMatchingTerm(nextProps.profiles, this.state.term); - this.setState({profiles: results, showNoResults: true}); + this.setState({profiles: results, showNoResults: true, error: null}); } } @@ -109,6 +112,7 @@ class MoreDirectMessages extends PureComponent { this.setState({ searching: false, term: null, + error: null, page: 0, profiles: this.props.profiles }); @@ -132,22 +136,44 @@ class MoreDirectMessages extends PureComponent { }; onSelectMember = async (id) => { - const {actions, preferences, profiles} = this.props; + const {actions, currentDisplayName, intl, preferences, profiles} = this.props; const user = profiles.find((p) => p.id === id); this.setState({adding: true}); + // save the current channel display name in case it fails + const currentChannelDisplayName = currentDisplayName; + + const userDisplayName = displayUsername(user, preferences); + if (user) { - actions.setChannelDisplayName(displayUsername(user, preferences)); + actions.setChannelDisplayName(userDisplayName); } else { actions.setChannelDisplayName(''); } - await actions.makeDirectChannel(id); - EventEmitter.emit('close_channel_drawer'); - InteractionManager.runAfterInteractions(() => { - this.close(); - }); + const result = await actions.makeDirectChannel(id); + + if (result.error) { + actions.setChannelDisplayName(currentChannelDisplayName); + alertErrorWithFallback( + intl, + result.error, + { + id: 'mobile.open_dm.error', + defaultMessage: "We couldn't open a direct message with {displayName}. Please check your connection and try again." + }, + { + displayName: userDisplayName + } + ); + this.setState({adding: false}); + } else { + EventEmitter.emit('close_channel_drawer'); + InteractionManager.runAfterInteractions(() => { + this.close(); + }); + } }; render() { diff --git a/app/screens/user_profile/index.js b/app/screens/user_profile/index.js index fc68fd798..3a85c1be7 100644 --- a/app/screens/user_profile/index.js +++ b/app/screens/user_profile/index.js @@ -5,9 +5,10 @@ import {bindActionCreators} from 'redux'; import {connect} from 'react-redux'; import {setChannelDisplayName} from 'app/actions/views/channel'; -import {handleSendMessage} from 'app/actions/views/user_profile'; +import {makeDirectChannel} from 'app/actions/views/more_dms'; import {getTheme} from 'app/selectors/preferences'; +import {getCurrentChannel} from 'mattermost-redux/selectors/entities/channels'; import {getMyPreferences} from 'mattermost-redux/selectors/entities/preferences'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; @@ -15,10 +16,14 @@ import UserProfile from './user_profile'; function mapStateToProps(state, ownProps) { const {config} = state.entities.general; + const {createChannel: createChannelRequest} = state.requests.channels; return { navigator: ownProps.navigator, config, + createChannelRequest, + currentChannel: getCurrentChannel(state), + currentDisplayName: state.views.channel.displayName, currentUserId: getCurrentUserId(state), user: state.entities.users.profiles[ownProps.userId], myPreferences: getMyPreferences(state), @@ -29,7 +34,7 @@ function mapStateToProps(state, ownProps) { function mapDispatchToProps(dispatch) { return { actions: bindActionCreators({ - handleSendMessage, + makeDirectChannel, setChannelDisplayName }, dispatch) }; diff --git a/app/screens/user_profile/user_profile.js b/app/screens/user_profile/user_profile.js index dd1348e80..4409e531d 100644 --- a/app/screens/user_profile/user_profile.js +++ b/app/screens/user_profile/user_profile.js @@ -9,28 +9,42 @@ import { Text, View } from 'react-native'; +import {injectIntl, intlShape} from 'react-intl'; + +import {getDirectChannelName} from 'mattermost-redux/utils/channel_utils'; +import {displayUsername} from 'mattermost-redux/utils/user_utils'; import ProfilePicture from 'app/components/profile_picture'; import StatusBar from 'app/components/status_bar'; +import {alertErrorWithFallback} from 'app/utils/general'; import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme'; -import {displayUsername} from 'mattermost-redux/utils/user_utils'; import UserProfileRow from './user_profile_row'; -export default class UserProfile extends PureComponent { +class UserProfile extends PureComponent { static propTypes = { actions: PropTypes.shape({ - handleSendMessage: PropTypes.func.isRequired, + makeDirectChannel: PropTypes.func.isRequired, setChannelDisplayName: PropTypes.func.isRequired }).isRequired, config: PropTypes.object.isRequired, + currentChannel: PropTypes.object.isRequired, + currentDisplayName: PropTypes.string, currentUserId: PropTypes.string.isRequired, + createChannelRequest: PropTypes.object.isRequired, + intl: intlShape.isRequired, navigator: PropTypes.object, myPreferences: PropTypes.object, theme: PropTypes.object.isRequired, user: PropTypes.object.isRequired }; + displaySendMessageOption = () => { + const {currentChannel, currentUserId, user} = this.props; + + return currentUserId !== user.id && currentChannel.name !== getDirectChannelName(currentUserId, user.id); + }; + getDisplayName = () => { const {theme, myPreferences, user} = this.props; const style = createStyleSheet(theme); @@ -60,17 +74,38 @@ export default class UserProfile extends PureComponent { return null; }; - sendMessage = () => { - const {actions, myPreferences, navigator, user} = this.props; - actions.setChannelDisplayName(displayUsername(user, myPreferences)); - actions.handleSendMessage(user.id); - navigator.pop({ - animated: true - }); + sendMessage = async () => { + const {actions, currentDisplayName, intl, myPreferences, navigator, user} = this.props; + + // save the current channel display name in case it fails + const currentChannelDisplayName = currentDisplayName; + + const userDisplayName = displayUsername(user, myPreferences); + actions.setChannelDisplayName(userDisplayName); + + const result = await actions.makeDirectChannel(user.id); + if (result.error) { + actions.setChannelDisplayName(currentChannelDisplayName); + alertErrorWithFallback( + intl, + result.error, + { + id: 'mobile.open_dm.error', + defaultMessage: "We couldn't open a direct message with {displayName}. Please check your connection and try again." + }, + { + displayName: userDisplayName + } + ); + } else { + navigator.pop({ + animated: true + }); + } }; render() { - const {config, currentUserId, theme, user} = this.props; + const {config, theme, user} = this.props; const style = createStyleSheet(theme); return ( @@ -95,14 +130,14 @@ export default class UserProfile extends PureComponent { {config.ShowEmailAddress === 'true' && this.buildDisplayBlock('email')} {this.buildDisplayBlock('position')} - {currentUserId !== user.id && - + {this.displaySendMessageOption() && + } @@ -152,3 +187,5 @@ const createStyleSheet = makeStyleSheetFromTheme((theme) => { } }); }); + +export default injectIntl(UserProfile); diff --git a/app/utils/general.js b/app/utils/general.js new file mode 100644 index 000000000..f9c0374a3 --- /dev/null +++ b/app/utils/general.js @@ -0,0 +1,12 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import {Alert} from 'react-native'; + +export function alertErrorWithFallback(intl, error, fallback, values) { + let msg = error.message; + if (!msg || msg === 'Network request failed') { + msg = intl.formatMessage(fallback, values); + } + Alert.alert('', msg); +} diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index b79fa3b11..05aa49eed 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -1691,6 +1691,7 @@ "mobile.channel_info.alertTitleDeleteChannel": "Delete {term}", "mobile.channel_info.alertTitleLeaveChannel": "Leave {term}", "mobile.channel_info.alertYes": "Yes", + "mobile.channel_info.delete_failed": "We couldn't delete the channel {displayName}. Please check your connection and try again.", "mobile.channel_info.privateChannel": "Private Channel", "mobile.channel_info.publicChannel": "Public Channel", "mobile.channel_list.alertMessageLeaveChannel": "Are you sure you want to leave the {term} {name}?", @@ -1728,6 +1729,7 @@ "mobile.intro_messages.DM": "This is the start of your direct message history with {teammate}. Direct messages and files shared here are not shown to people outside this area.", "mobile.intro_messages.default_message": "This is the first channel teammates see when they sign up - use it for posting updates everyone needs to know.", "mobile.intro_messages.default_welcome": "Welcome to {name}!", + "mobile.join_channel.error": "We couldn't join the channel {displayName}. Please check your connection and try again.", "mobile.loading_channels": "Loading Channels...", "mobile.loading_members": "Loading Members...", "mobile.loading_posts": "Loading Messages...", @@ -1736,6 +1738,7 @@ "mobile.offlineIndicator.connected": "Connected", "mobile.offlineIndicator.connecting": "Connecting...", "mobile.offlineIndicator.offline": "No internet connection", + "mobile.open_dm.error": "We couldn't open a direct message with {displayName}. Please check your connection and try again.", "mobile.post.cancel": "Cancel", "mobile.post.delete_question": "Are you sure you want to delete this post?", "mobile.post.delete_title": "Delete Post", diff --git a/yarn.lock b/yarn.lock index a9308c971..9d944ca55 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3645,7 +3645,7 @@ makeerror@1.0.x: mattermost-redux@mattermost/mattermost-redux#master: version "0.0.1" - resolved "https://codeload.github.com/mattermost/mattermost-redux/tar.gz/86454a4eafa5f5676748cfbfa883539be1e6ce90" + resolved "https://codeload.github.com/mattermost/mattermost-redux/tar.gz/b21461562fefc6abe2e31373045059652d814ad1" dependencies: deep-equal "1.0.1" harmony-reflect "1.5.1"