Added SelectListView and logic for leaving team
This commit is contained in:
parent
4bac054105
commit
4b6e691d8a
|
@ -290,6 +290,7 @@
|
|||
"last_message": "last message",
|
||||
"Leave_channel": "Leave channel",
|
||||
"leaving_room": "leaving room",
|
||||
"Leave": "Leave",
|
||||
"leave": "leave",
|
||||
"Legal": "Legal",
|
||||
"Light": "Light",
|
||||
|
@ -726,5 +727,11 @@
|
|||
"Auto-join": "Auto-join",
|
||||
"Delete_Team_Room_Warning": "Woud you like to remove this channel from the team? The channel will be moved back to the workspace",
|
||||
"Confirmation": "Confirmation",
|
||||
"invalid-room": "Invalid room"
|
||||
"invalid-room": "Invalid room",
|
||||
"You_are_leaving_the_team": "You are leaving the team '{{team}}'",
|
||||
"Leave_Team": "Leave Team",
|
||||
"Select_Teams": "Select the Team's channels you would like to leave.",
|
||||
"Cannot_leave": "Cannot leave",
|
||||
"Last_owner_team_room": "You are the last owner of this channel. Once you leave the team, the channel will be kept inside the team but you will be managing it from outside.",
|
||||
"last-owner-can-not-be-removed": "Last owner cannot be removed"
|
||||
}
|
||||
|
|
|
@ -758,6 +758,10 @@ const RocketChat = {
|
|||
// RC 3.13.0
|
||||
return this.post('teams.removeRoom', { roomId, teamId });
|
||||
},
|
||||
leaveTeam({ teamName }) {
|
||||
// RC 3.13.0
|
||||
return this.post('teams.leave', { teamName });
|
||||
},
|
||||
joinRoom(roomId, joinCode, type) {
|
||||
// TODO: join code
|
||||
// RC 0.48.0
|
||||
|
|
|
@ -73,6 +73,7 @@ import CreateDiscussionView from '../views/CreateDiscussionView';
|
|||
import QueueListView from '../ee/omnichannel/views/QueueListView';
|
||||
import AddChannelTeamView from '../views/AddChannelTeamView';
|
||||
import AddExistingChannelView from '../views/AddExistingChannelView';
|
||||
import SelectListView from '../views/SelectListView';
|
||||
|
||||
// ChatsStackNavigator
|
||||
const ChatsStack = createStackNavigator();
|
||||
|
@ -93,6 +94,11 @@ const ChatsStackNavigator = () => {
|
|||
component={RoomActionsView}
|
||||
options={RoomActionsView.navigationOptions}
|
||||
/>
|
||||
<ChatsStack.Screen
|
||||
name='SelectListView'
|
||||
component={SelectListView}
|
||||
options={SelectListView.navigationOptions}
|
||||
/>
|
||||
<ChatsStack.Screen
|
||||
name='RoomInfoView'
|
||||
component={RoomInfoView}
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
} from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import { Q } from '@nozbe/watermelondb';
|
||||
import { compareServerVersion, methods } from '../../lib/utils';
|
||||
|
||||
import Touch from '../../utils/touch';
|
||||
|
@ -412,6 +413,54 @@ class RoomActionsView extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
_leave = async(teamName) => {
|
||||
try {
|
||||
const { navigation } = this.props;
|
||||
const result = await RocketChat.leaveTeam({ teamName });
|
||||
// Add isMasterDetail
|
||||
if (result.success) {
|
||||
navigation.navigate('RoomsListView');
|
||||
}
|
||||
} catch (e) {
|
||||
log(e);
|
||||
}
|
||||
}
|
||||
|
||||
leaveTeam = async() => {
|
||||
const { room } = this.state;
|
||||
const { navigation } = this.props;
|
||||
|
||||
try {
|
||||
const db = database.active;
|
||||
const subCollection = db.get('subscriptions');
|
||||
const teamChannels = await subCollection.query(
|
||||
Q.where('team_id', Q.eq(room.teamId))
|
||||
);
|
||||
|
||||
if (teamChannels) {
|
||||
navigation.navigate('SelectListView', { title: 'Leave_Team', teamChannels, teamName: room.name });
|
||||
} else {
|
||||
Alert.alert(
|
||||
I18n.t('Confirmation'),
|
||||
I18n.t('You_are_leaving_the_team', { team: RocketChat.getRoomTitle(room) }),
|
||||
[
|
||||
{
|
||||
text: I18n.t('Cancel'),
|
||||
style: 'cancel'
|
||||
},
|
||||
{
|
||||
text: I18n.t('Yes_action_it', { action: I18n.t('leave') }),
|
||||
style: 'destructive',
|
||||
onPress: () => this._leave(room.name)
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
log(e);
|
||||
}
|
||||
}
|
||||
|
||||
renderRoomInfo = () => {
|
||||
const { room, member } = this.state;
|
||||
const {
|
||||
|
@ -568,9 +617,9 @@ class RoomActionsView extends React.Component {
|
|||
<List.Section>
|
||||
<List.Separator />
|
||||
<List.Item
|
||||
title='Leave_channel'
|
||||
title={room.teamId && room.teamMain ? 'Leave' : 'Leave_channel'}
|
||||
onPress={() => this.onPressTouchable({
|
||||
event: this.leaveChannel
|
||||
event: room.teamId && room.teamMain ? this.leaveTeam : this.leaveChannel
|
||||
})}
|
||||
testID='room-actions-leave-channel'
|
||||
left={() => <List.Icon name='logout' color={themes[theme].dangerColor} />}
|
||||
|
|
|
@ -1033,6 +1033,7 @@ class RoomView extends React.Component {
|
|||
renderActions = () => {
|
||||
const { room, readOnly } = this.state;
|
||||
const { user } = this.props;
|
||||
console.log({ room });
|
||||
return (
|
||||
<>
|
||||
<MessageActions
|
||||
|
|
|
@ -946,7 +946,6 @@ class RoomsListView extends React.Component {
|
|||
if (loading) {
|
||||
return <ActivityIndicator theme={theme} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
ref={this.getScrollRef}
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
/* eslint-disable no-mixed-spaces-and-tabs */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
View, StyleSheet, FlatList, Text, Alert, Pressable
|
||||
} from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import { HeaderBackButton } from '@react-navigation/stack';
|
||||
import * as List from '../containers/List';
|
||||
|
||||
import Touch from '../utils/touch';
|
||||
import { leaveRoom as leaveRoomAction } from '../actions/room';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import sharedStyles from './Styles';
|
||||
import I18n from '../i18n';
|
||||
import { CustomIcon } from '../lib/Icons';
|
||||
import * as HeaderButton from '../containers/HeaderButton';
|
||||
import StatusBar from '../containers/StatusBar';
|
||||
import { themes } from '../constants/colors';
|
||||
import { withTheme } from '../theme';
|
||||
import SafeAreaView from '../containers/SafeAreaView';
|
||||
import { animateNextTransition } from '../utils/layoutAnimation';
|
||||
import Loading from '../containers/Loading';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
height: 46,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center'
|
||||
},
|
||||
buttonIcon: {
|
||||
marginLeft: 18,
|
||||
marginRight: 16
|
||||
},
|
||||
buttonText: {
|
||||
fontSize: 17,
|
||||
...sharedStyles.textRegular
|
||||
},
|
||||
textContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginRight: 15
|
||||
},
|
||||
icon: {
|
||||
marginHorizontal: 15,
|
||||
alignSelf: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
class SelectListView extends React.Component {
|
||||
static propTypes = {
|
||||
navigation: PropTypes.object,
|
||||
route: PropTypes.object,
|
||||
user: PropTypes.shape({
|
||||
id: PropTypes.string,
|
||||
token: PropTypes.string
|
||||
}),
|
||||
theme: PropTypes.string,
|
||||
isMasterDetail: PropTypes.bool,
|
||||
leaveRoom: PropTypes.func
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const teamChannels = props.route?.params?.teamChannels;
|
||||
this.title = props.route?.params?.title;
|
||||
this.teamName = props.route?.params?.teamName;
|
||||
this.state = {
|
||||
data: teamChannels,
|
||||
selected: [],
|
||||
loading: false
|
||||
};
|
||||
this.setHeader();
|
||||
}
|
||||
|
||||
setHeader = () => {
|
||||
const { navigation, isMasterDetail, theme } = this.props;
|
||||
|
||||
const options = {
|
||||
headerShown: true,
|
||||
headerTitleAlign: 'center',
|
||||
headerTitle: I18n.t(this.title)
|
||||
};
|
||||
|
||||
if (isMasterDetail) {
|
||||
options.headerLeft = () => <HeaderButton.CloseModal navigation={navigation} />;
|
||||
} else {
|
||||
options.headerLeft = () => <HeaderBackButton labelVisible={false} onPress={() => navigation.pop()} tintColor={themes[theme].headerTintColor} />;
|
||||
}
|
||||
|
||||
options.headerRight = () => (
|
||||
<HeaderButton.Container>
|
||||
<HeaderButton.Item title={I18n.t('Next')} onPress={this.submit} testID='select-list-view-submit' />
|
||||
</HeaderButton.Container>
|
||||
);
|
||||
|
||||
navigation.setOptions(options);
|
||||
}
|
||||
|
||||
submit = async() => {
|
||||
const { selected } = this.state;
|
||||
const { navigation, leaveRoom } = this.props;
|
||||
|
||||
this.setState({ loading: true });
|
||||
try {
|
||||
// logEvent(events.CT_ADD_ROOM_TO_TEAM);
|
||||
const result = await RocketChat.leaveTeam({ teamName: this.teamName });
|
||||
if (selected) {
|
||||
selected.map(room => leaveRoom(room.rid, room.t));
|
||||
}
|
||||
if (result.success) {
|
||||
this.setState({ loading: false });
|
||||
navigation.navigate('RoomsListView');
|
||||
}
|
||||
} catch (e) {
|
||||
// logEvent(events.CT_ADD_ROOM_TO_TEAM_F);
|
||||
this.setState({ loading: false });
|
||||
Alert.alert(
|
||||
I18n.t('Cannot_leave'),
|
||||
I18n.t(e.data.error),
|
||||
[
|
||||
{
|
||||
text: 'OK',
|
||||
style: 'cancel'
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
renderHeader = () => {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<View style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
<Text style={[styles.buttonText, { color: themes[theme].bodyText, margin: 16 }]}>{I18n.t('Select_Teams')}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
showAlert = () => {
|
||||
Alert.alert(
|
||||
I18n.t('Cannot_leave'),
|
||||
I18n.t('Last_owner_team_room'),
|
||||
[
|
||||
{
|
||||
text: 'OK',
|
||||
style: 'cancel'
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
leaveChannel = () => {
|
||||
const { room } = this.state;
|
||||
const { leaveRoom } = this.props;
|
||||
|
||||
Alert.alert(
|
||||
I18n.t('Are_you_sure_question_mark'),
|
||||
I18n.t('Are_you_sure_you_want_to_leave_the_room', { room: RocketChat.getRoomTitle(room) }),
|
||||
[
|
||||
{
|
||||
text: I18n.t('Cancel'),
|
||||
style: 'cancel'
|
||||
},
|
||||
{
|
||||
text: I18n.t('Yes_action_it', { action: I18n.t('leave') }),
|
||||
style: 'destructive',
|
||||
onPress: () => leaveRoom(room.rid, room.t)
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
renderChannel = ({
|
||||
onPress, testID, title, icon, checked, alert
|
||||
}) => {
|
||||
const { theme } = this.props;
|
||||
|
||||
return (
|
||||
<Touch
|
||||
onPress={onPress}
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
testID={testID}
|
||||
theme={theme}
|
||||
>
|
||||
<View style={[styles.button, { borderColor: themes[theme].separatorColor, marginVertical: 4 }]}>
|
||||
<CustomIcon style={[styles.buttonIcon, { color: themes[theme].controlText }]} size={24} name={icon} />
|
||||
<View style={styles.textContainer}>
|
||||
<Text style={[styles.buttonText, { color: themes[theme].bodyText }]}>{title}</Text>
|
||||
{ alert
|
||||
? (
|
||||
<Pressable onPress={() => this.showAlert()}>
|
||||
<CustomIcon style={[styles.buttonIcon, { color: themes[theme].dangerColor, transform: [{ rotateY: '180deg' }] }]} size={24} name={alert} />
|
||||
</Pressable>
|
||||
) : null}
|
||||
</View>
|
||||
{checked ? <CustomIcon name={checked} size={22} style={[styles.icon, { color: themes[theme].actionTintColor }]} /> : null}
|
||||
</View>
|
||||
</Touch>
|
||||
);
|
||||
}
|
||||
|
||||
isChecked = (rid) => {
|
||||
const { selected } = this.state;
|
||||
return selected.includes(rid);
|
||||
}
|
||||
|
||||
toggleChannel = (rid, roles) => {
|
||||
const { selected } = this.state;
|
||||
|
||||
if (roles) {
|
||||
this.showAlert();
|
||||
return;
|
||||
}
|
||||
|
||||
animateNextTransition();
|
||||
if (!this.isChecked(rid)) {
|
||||
this.setState({ selected: [...selected, rid] }, () => this.setHeader());
|
||||
} else {
|
||||
const filterSelected = selected.filter(el => el !== rid);
|
||||
this.setState({ selected: filterSelected }, () => this.setHeader());
|
||||
}
|
||||
}
|
||||
|
||||
renderItem = ({ item }) => (
|
||||
<>
|
||||
{this.renderChannel({
|
||||
onPress: () => this.toggleChannel(item.rid, item.roles),
|
||||
title: item.name,
|
||||
icon: item.t === 'p' ? 'channel-private' : 'channel-public',
|
||||
checked: this.isChecked(item.rid, item.roles) ? 'check' : null,
|
||||
testID: 'select-list-view-item',
|
||||
alert: item.roles ? 'info' : null
|
||||
})}
|
||||
</>
|
||||
)
|
||||
|
||||
renderList = () => {
|
||||
const { data } = this.state;
|
||||
const { theme } = this.props;
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
data={data}
|
||||
extraData={this.state}
|
||||
keyExtractor={item => item._id}
|
||||
renderItem={this.renderItem}
|
||||
ListHeaderComponent={this.renderHeader}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
contentContainerStyle={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
keyboardShouldPersistTaps='always'
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { loading } = this.state;
|
||||
|
||||
return (
|
||||
<SafeAreaView testID='new-message-view'>
|
||||
<StatusBar />
|
||||
{this.renderList()}
|
||||
<Loading visible={loading} />
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
isMasterDetail: state.app.isMasterDetail
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
leaveRoom: (rid, t) => dispatch(leaveRoomAction(rid, t))
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(SelectListView));
|
Loading…
Reference in New Issue