Added permissions, translations strings for teams, deleteTeamRoom and addTeamRooms, AddExistingChannelView, updated CreateChannelView, TeamChannelsView
This commit is contained in:
parent
37421d395a
commit
bb0632b689
File diff suppressed because it is too large
Load Diff
|
@ -719,5 +719,8 @@
|
|||
"team-name-already-exists": "A team with that name already exists",
|
||||
"Add_Channel_to_Team": "Add Channel to Team",
|
||||
"Create_New": "Create New",
|
||||
"Add_Existing": "Add Existing"
|
||||
"Add_Existing": "Add Existing",
|
||||
"Add_Existing_Channel": "Add Existing Channel",
|
||||
"Remove_from_Team": "Remove from Team",
|
||||
"Auto-join": "Auto-join"
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ const PERMISSIONS = [
|
|||
'add-user-to-any-c-room',
|
||||
'add-user-to-any-p-room',
|
||||
'add-user-to-joined-room',
|
||||
'add-team-channel',
|
||||
'archive-room',
|
||||
'auto-translate',
|
||||
'create-invite-links',
|
||||
|
@ -21,11 +22,13 @@ const PERMISSIONS = [
|
|||
'delete-p',
|
||||
'edit-message',
|
||||
'edit-room',
|
||||
'edit-team-channel',
|
||||
'force-delete-message',
|
||||
'mute-user',
|
||||
'pin-message',
|
||||
'post-readonly',
|
||||
'remove-user',
|
||||
'remove-team-channel',
|
||||
'set-leader',
|
||||
'set-moderator',
|
||||
'set-owner',
|
||||
|
@ -38,7 +41,9 @@ const PERMISSIONS = [
|
|||
'view-privileged-setting',
|
||||
'view-room-administration',
|
||||
'view-statistics',
|
||||
'view-user-administration'
|
||||
'view-user-administration',
|
||||
'view-all-teams',
|
||||
'view-all-team-channels'
|
||||
];
|
||||
|
||||
export async function setPermissions() {
|
||||
|
|
|
@ -734,7 +734,7 @@ const RocketChat = {
|
|||
const params = {
|
||||
name,
|
||||
users,
|
||||
type: type ? 1 : 0,
|
||||
type,
|
||||
room: {
|
||||
readOnly,
|
||||
extraData: {
|
||||
|
@ -746,6 +746,22 @@ const RocketChat = {
|
|||
// RC 3.13.0
|
||||
return this.post('teams.create', params);
|
||||
},
|
||||
addTeamRooms({ rooms, teamId }) {
|
||||
const params = {
|
||||
rooms: rooms.length ? [...rooms] : [rooms],
|
||||
teamId
|
||||
};
|
||||
// RC 3.13.0
|
||||
return this.post('teams.addRooms', params);
|
||||
},
|
||||
deleteTeamRoom({ rid, teamId }) {
|
||||
const params = {
|
||||
roomId: rid,
|
||||
teamId
|
||||
};
|
||||
// RC 3.13.0
|
||||
return this.post('teams.removeRoom', params);
|
||||
},
|
||||
joinRoom(roomId, joinCode, type) {
|
||||
// TODO: join code
|
||||
// RC 0.48.0
|
||||
|
|
|
@ -42,6 +42,7 @@ const RoomItem = ({
|
|||
testID,
|
||||
swipeEnabled,
|
||||
onPress,
|
||||
onLongPress,
|
||||
toggleFav,
|
||||
toggleRead,
|
||||
hideChannel,
|
||||
|
@ -49,6 +50,7 @@ const RoomItem = ({
|
|||
}) => (
|
||||
<Touchable
|
||||
onPress={onPress}
|
||||
onLongPress={onLongPress}
|
||||
width={width}
|
||||
favorite={favorite}
|
||||
toggleFav={toggleFav}
|
||||
|
@ -181,6 +183,7 @@ RoomItem.propTypes = {
|
|||
toggleFav: PropTypes.func,
|
||||
toggleRead: PropTypes.func,
|
||||
onPress: PropTypes.func,
|
||||
onLongPress: PropTypes.func,
|
||||
hideChannel: PropTypes.func
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Animated } from 'react-native';
|
||||
import { Animated, Pressable } from 'react-native';
|
||||
import { PanGestureHandler, State } from 'react-native-gesture-handler';
|
||||
|
||||
import Touch from '../../utils/touch';
|
||||
import {
|
||||
ACTION_WIDTH,
|
||||
SMALL_SWIPE,
|
||||
|
@ -17,6 +16,7 @@ class Touchable extends React.Component {
|
|||
static propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
onPress: PropTypes.func,
|
||||
onLongPress: PropTypes.func,
|
||||
testID: PropTypes.string,
|
||||
width: PropTypes.number,
|
||||
favorite: PropTypes.bool,
|
||||
|
@ -203,6 +203,18 @@ class Touchable extends React.Component {
|
|||
}
|
||||
};
|
||||
|
||||
onLongPress = () => {
|
||||
const { rowState } = this.state;
|
||||
if (rowState !== 0) {
|
||||
this.close();
|
||||
return;
|
||||
}
|
||||
const { onLongPress } = this.props;
|
||||
if (onLongPress) {
|
||||
onLongPress();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
testID, isRead, width, favorite, children, theme, isFocused, swipeEnabled
|
||||
|
@ -237,8 +249,9 @@ class Touchable extends React.Component {
|
|||
transform: [{ translateX: this.transX }]
|
||||
}}
|
||||
>
|
||||
<Touch
|
||||
<Pressable
|
||||
onPress={this.onPress}
|
||||
onLongPress={this.onLongPress}
|
||||
theme={theme}
|
||||
testID={testID}
|
||||
style={{
|
||||
|
@ -246,7 +259,7 @@ class Touchable extends React.Component {
|
|||
}}
|
||||
>
|
||||
{children}
|
||||
</Touch>
|
||||
</Pressable>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ class RoomItemContainer extends React.Component {
|
|||
showLastMessage: PropTypes.bool,
|
||||
id: PropTypes.string,
|
||||
onPress: PropTypes.func,
|
||||
onLongPress: PropTypes.func,
|
||||
username: PropTypes.string,
|
||||
avatarSize: PropTypes.number,
|
||||
width: PropTypes.number,
|
||||
|
@ -112,6 +113,11 @@ class RoomItemContainer extends React.Component {
|
|||
return onPress(item);
|
||||
}
|
||||
|
||||
onLongPress = () => {
|
||||
const { item, onLongPress } = this.props;
|
||||
return onLongPress(item);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
item,
|
||||
|
@ -160,6 +166,7 @@ class RoomItemContainer extends React.Component {
|
|||
isGroupChat={this.isGroupChat}
|
||||
isRead={isRead}
|
||||
onPress={this.onPress}
|
||||
onLongPress={this.onLongPress}
|
||||
date={date}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
width={width}
|
||||
|
|
|
@ -25,6 +25,10 @@ const createTeam = function createTeam(data) {
|
|||
return RocketChat.createTeam(data);
|
||||
};
|
||||
|
||||
const addTeamRoom = function addRoomToTeam(params) {
|
||||
return RocketChat.addTeamRoom(params);
|
||||
};
|
||||
|
||||
const handleRequest = function* handleRequest({ data }) {
|
||||
try {
|
||||
const auth = yield select(state => state.login.isAuthenticated);
|
||||
|
@ -40,6 +44,7 @@ const handleRequest = function* handleRequest({ data }) {
|
|||
broadcast,
|
||||
encrypted
|
||||
} = data;
|
||||
// TODO: Create event CT_CREATE
|
||||
logEvent(events.CR_CREATE, {
|
||||
type,
|
||||
readOnly,
|
||||
|
@ -67,14 +72,22 @@ const handleRequest = function* handleRequest({ data }) {
|
|||
encrypted
|
||||
});
|
||||
sub = yield call(createChannel, data);
|
||||
}
|
||||
|
||||
if (data.teamId) {
|
||||
// TODO: Log when adding room to team
|
||||
const channels = yield call(addTeamRoom, { rooms: sub.rid, teamId: data.teamId });
|
||||
if (channels.success) {
|
||||
sub.teamId = channels.teamId;
|
||||
sub.isTeamChannel = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
const db = database.active;
|
||||
const subCollection = db.get('subscriptions');
|
||||
yield db.action(async() => {
|
||||
await subCollection.create((s) => {
|
||||
s._raw = sanitizedRaw({ id: sub.team ? sub.team.roomId : sub.rid }, subCollection.schema);
|
||||
s._raw = sanitizedRaw({ id: sub.team ? sub.team.roomId : sub.rid, team_id: sub.teamId }, subCollection.schema);
|
||||
Object.assign(s, sub);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -72,6 +72,7 @@ import CreateDiscussionView from '../views/CreateDiscussionView';
|
|||
|
||||
import QueueListView from '../ee/omnichannel/views/QueueListView';
|
||||
import AddChannelTeamView from '../views/AddChannelTeamView';
|
||||
import AddExistingChannelView from '../views/AddExistingChannelView';
|
||||
|
||||
// ChatsStackNavigator
|
||||
const ChatsStack = createStackNavigator();
|
||||
|
@ -180,6 +181,11 @@ const ChatsStackNavigator = () => {
|
|||
component={AddChannelTeamView}
|
||||
options={AddChannelTeamView.navigationOptions}
|
||||
/>
|
||||
<ChatsStack.Screen
|
||||
name='AddExistingChannelView'
|
||||
component={AddExistingChannelView}
|
||||
options={AddExistingChannelView.navigationOptions}
|
||||
/>
|
||||
<ChatsStack.Screen
|
||||
name='MarkdownTableView'
|
||||
component={MarkdownTableView}
|
||||
|
|
|
@ -8,17 +8,34 @@ const navigate = ({ item, isMasterDetail, ...props }) => {
|
|||
navigationMethod = Navigation.replace;
|
||||
}
|
||||
|
||||
navigationMethod('RoomView', {
|
||||
rid: item.roomId || item.rid,
|
||||
name: RocketChat.getRoomTitle(item),
|
||||
t: item.type ? 'p' : item.t,
|
||||
prid: item.prid,
|
||||
room: item,
|
||||
search: item.search,
|
||||
visitor: item.visitor,
|
||||
roomUserId: RocketChat.getUidDirectMessage(item),
|
||||
...props
|
||||
});
|
||||
if (item.isTeamChannel) {
|
||||
// TODO: Refactor
|
||||
Navigation.navigate('TeamChannelsView');
|
||||
Navigation.push('RoomView', {
|
||||
rid: item.roomId || item.rid,
|
||||
name: RocketChat.getRoomTitle(item),
|
||||
t: item.type ? 'p' : item.t,
|
||||
prid: item.prid,
|
||||
room: item,
|
||||
search: item.search,
|
||||
visitor: item.visitor,
|
||||
roomUserId: RocketChat.getUidDirectMessage(item),
|
||||
teamId: item.teamId,
|
||||
...props
|
||||
});
|
||||
} else {
|
||||
navigationMethod('RoomView', {
|
||||
rid: item.roomId || item.rid,
|
||||
name: RocketChat.getRoomTitle(item),
|
||||
t: item.type ? 'p' : item.t,
|
||||
prid: item.prid,
|
||||
room: item,
|
||||
search: item.search,
|
||||
visitor: item.visitor,
|
||||
roomUserId: RocketChat.getUidDirectMessage(item),
|
||||
...props
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const goRoom = async({ item = {}, isMasterDetail = false, ...props }) => {
|
||||
|
|
|
@ -15,13 +15,14 @@ class Touch extends React.Component {
|
|||
|
||||
render() {
|
||||
const {
|
||||
children, onPress, theme, underlayColor, ...props
|
||||
children, onPress, onLongPress, theme, underlayColor, ...props
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<RectButton
|
||||
ref={this.getRef}
|
||||
onPress={onPress}
|
||||
onLongPress={onLongPress}
|
||||
activeOpacity={1}
|
||||
underlayColor={underlayColor || themes[theme].bannerBackground}
|
||||
rippleColor={themes[theme].bannerBackground}
|
||||
|
@ -36,6 +37,7 @@ class Touch extends React.Component {
|
|||
Touch.propTypes = {
|
||||
children: PropTypes.node,
|
||||
onPress: PropTypes.func,
|
||||
onLongPress: PropTypes.func,
|
||||
theme: PropTypes.string,
|
||||
underlayColor: PropTypes.string
|
||||
};
|
||||
|
|
|
@ -7,7 +7,6 @@ import sharedStyles from './Styles';
|
|||
import { CustomIcon } from '../lib/Icons';
|
||||
import Touch from '../utils/touch';
|
||||
import StatusBar from '../containers/StatusBar';
|
||||
import RoomHeader from '../containers/RoomHeader';
|
||||
import { withTheme } from '../theme';
|
||||
import * as HeaderButton from '../containers/HeaderButton';
|
||||
import SafeAreaView from '../containers/SafeAreaView';
|
||||
|
@ -47,9 +46,7 @@ class AddChannelTeamView extends React.Component {
|
|||
const options = {
|
||||
headerShown: true,
|
||||
headerTitleAlign: 'center',
|
||||
headerTitle: () => (
|
||||
<RoomHeader title={I18n.t('Add_Channel_to_Team')} />
|
||||
)
|
||||
headerTitle: I18n.t('Add_Channel_to_Team')
|
||||
};
|
||||
|
||||
if (isMasterDetail) {
|
||||
|
@ -74,7 +71,7 @@ class AddChannelTeamView extends React.Component {
|
|||
|
||||
return (
|
||||
<Touch
|
||||
onPress={() => onPress()}
|
||||
onPress={onPress}
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}
|
||||
testID={testID}
|
||||
theme={theme}
|
||||
|
@ -88,21 +85,22 @@ class AddChannelTeamView extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { navigation } = this.props;
|
||||
const { navigation, route } = this.props;
|
||||
const { teamChannels } = route?.params;
|
||||
|
||||
return (
|
||||
<SafeAreaView testID='add-channel-team-view'>
|
||||
<StatusBar />
|
||||
<View style={styles.buttonContainer}>
|
||||
{this.renderButton({
|
||||
onPress: navigation.navigate('NewMessageStackNavigator', { screen: 'CreateChannelView', isTeam: false }),
|
||||
onPress: () => navigation.navigate('NewMessageStackNavigator', { screen: 'SelectedUsersViewCreateChannel', params: { nextAction: () => navigation.navigate('CreateChannelView', { teamId: this.teamId }) } }),
|
||||
title: I18n.t('Create_New'),
|
||||
icon: 'channel-public',
|
||||
testID: 'add-channel-team-view-create-channel',
|
||||
first: true
|
||||
})}
|
||||
{this.renderButton({
|
||||
// onPress: navigation.navigate('AddExistingChannelView'),
|
||||
onPress: () => navigation.navigate('AddExistingChannelView', { teamId: this.teamId, teamChannels }),
|
||||
title: I18n.t('Add_Existing'),
|
||||
icon: 'team',
|
||||
testID: 'add-channel-team-view-create-channel'
|
||||
|
|
|
@ -0,0 +1,256 @@
|
|||
/* eslint-disable no-mixed-spaces-and-tabs */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
View, StyleSheet, FlatList, Text
|
||||
} from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import { Q } from '@nozbe/watermelondb';
|
||||
import { HeaderBackButton } from '@react-navigation/stack';
|
||||
import * as List from '../containers/List';
|
||||
|
||||
import Touch from '../utils/touch';
|
||||
import database from '../lib/database';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import sharedStyles from './Styles';
|
||||
import I18n from '../i18n';
|
||||
import log from '../utils/log';
|
||||
import SearchBox from '../containers/SearchBox';
|
||||
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 { goRoom } from '../utils/goRoom';
|
||||
import Loading from '../containers/Loading';
|
||||
|
||||
const QUERY_SIZE = 15;
|
||||
|
||||
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: 'column',
|
||||
justifyContent: 'center',
|
||||
marginRight: 15
|
||||
},
|
||||
icon: {
|
||||
marginHorizontal: 15,
|
||||
alignSelf: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
class AddExistingChannelView 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
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.init();
|
||||
this.teamId = props.route?.params?.teamId;
|
||||
this.state = {
|
||||
search: [],
|
||||
channels: [],
|
||||
selected: [],
|
||||
loading: false
|
||||
};
|
||||
this.setHeader();
|
||||
}
|
||||
|
||||
setHeader = () => {
|
||||
const { navigation, isMasterDetail, theme } = this.props;
|
||||
const { selected } = this.state;
|
||||
|
||||
const options = {
|
||||
headerShown: true,
|
||||
headerTitleAlign: 'center',
|
||||
headerTitle: I18n.t('Add_Existing_Channel')
|
||||
};
|
||||
|
||||
if (isMasterDetail) {
|
||||
options.headerLeft = () => <HeaderButton.CloseModal navigation={navigation} />;
|
||||
} else {
|
||||
options.headerLeft = () => <HeaderBackButton labelVisible={false} onPress={() => navigation.pop()} tintColor={themes[theme].headerTintColor} />;
|
||||
}
|
||||
|
||||
options.headerRight = () => selected.length > 0 && (
|
||||
<HeaderButton.Container>
|
||||
<HeaderButton.Item title={I18n.t('Create')} onPress={this.submit} testID='add-existing-channel-view-submit' />
|
||||
</HeaderButton.Container>
|
||||
);
|
||||
|
||||
navigation.setOptions(options);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/sort-comp
|
||||
init = async() => {
|
||||
try {
|
||||
const db = database.active;
|
||||
const channels = await db.collections
|
||||
.get('subscriptions')
|
||||
.query(
|
||||
Q.where('t', 'p'),
|
||||
Q.where('team_id', ''),
|
||||
Q.experimentalTake(QUERY_SIZE),
|
||||
Q.experimentalSortBy('room_updated_at', Q.desc)
|
||||
)
|
||||
.fetch();
|
||||
this.setState({ channels });
|
||||
} catch (e) {
|
||||
log(e);
|
||||
}
|
||||
}
|
||||
|
||||
onSearchChangeText(text) {
|
||||
this.search(text);
|
||||
}
|
||||
|
||||
dismiss = () => {
|
||||
const { navigation } = this.props;
|
||||
return navigation.pop();
|
||||
}
|
||||
|
||||
search = async(text) => {
|
||||
const result = await RocketChat.search({ text, filterUsers: false });
|
||||
this.setState({
|
||||
search: result
|
||||
});
|
||||
}
|
||||
|
||||
submit = async() => {
|
||||
const { selected } = this.state;
|
||||
const { isMasterDetail } = this.props;
|
||||
|
||||
this.setState({ loading: true });
|
||||
try {
|
||||
// TODO: Log request
|
||||
const result = await RocketChat.addTeamRooms({ rooms: selected, teamId: this.teamId });
|
||||
if (result.success) {
|
||||
this.setState({ loading: false });
|
||||
goRoom(result, isMasterDetail);
|
||||
}
|
||||
} catch (e) {
|
||||
// TODO: Log error
|
||||
this.setState({ loading: false });
|
||||
}
|
||||
}
|
||||
|
||||
renderChannel = ({
|
||||
onPress, testID, title, icon, checked
|
||||
}) => {
|
||||
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>
|
||||
</View>
|
||||
{checked ? <CustomIcon name={checked} size={22} style={[styles.icon, { color: themes[theme].actionTintColor }]} /> : null}
|
||||
</View>
|
||||
</Touch>
|
||||
);
|
||||
}
|
||||
|
||||
renderHeader = () => {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<View style={{ backgroundColor: themes[theme].auxiliaryBackground }}>
|
||||
<SearchBox onChangeText={text => this.onSearchChangeText(text)} testID='add-existing-channel-view-search' />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
isChecked = (rid) => {
|
||||
const { selected } = this.state;
|
||||
return selected.includes(rid);
|
||||
}
|
||||
|
||||
toggleChannel = (rid) => {
|
||||
const { selected } = this.state;
|
||||
|
||||
animateNextTransition();
|
||||
if (!this.isChecked(rid)) {
|
||||
// logEvent(events.SELECTED_USERS_ADD_USER);
|
||||
this.setState({ selected: [...selected, rid] }, () => this.setHeader());
|
||||
} else {
|
||||
// logEvent(events.SELECTED_USERS_REMOVE_USER);
|
||||
const filterSelected = selected.filter(el => el !== rid);
|
||||
this.setState({ selected: filterSelected }, () => this.setHeader());
|
||||
}
|
||||
}
|
||||
|
||||
renderItem = ({ item }) => (
|
||||
<>
|
||||
{this.renderChannel({
|
||||
onPress: () => this.toggleChannel(item.rid),
|
||||
title: item.name,
|
||||
icon: item.t === 'p' && !item.teamId ? 'channel-private' : 'channel-public',
|
||||
checked: this.isChecked(item.rid) ? 'check' : null,
|
||||
testID: 'add-existing-channel-view-item'
|
||||
})}
|
||||
</>
|
||||
)
|
||||
|
||||
renderList = () => {
|
||||
const { search, channels } = this.state;
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<FlatList
|
||||
data={search.length > 0 ? search : channels}
|
||||
extraData={this.state}
|
||||
keyExtractor={item => item._id}
|
||||
ListHeaderComponent={this.renderHeader}
|
||||
renderItem={this.renderItem}
|
||||
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
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, null)(withTheme(AddExistingChannelView));
|
|
@ -87,13 +87,15 @@ class CreateChannelView extends React.Component {
|
|||
id: PropTypes.string,
|
||||
token: PropTypes.string
|
||||
}),
|
||||
theme: PropTypes.string
|
||||
theme: PropTypes.string,
|
||||
teamId: PropTypes.string
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { route } = this.props;
|
||||
this.isTeam = route?.params?.isTeam || false;
|
||||
this.teamId = route?.params?.teamId;
|
||||
this.state = {
|
||||
channelName: '',
|
||||
type: true,
|
||||
|
@ -173,7 +175,7 @@ class CreateChannelView extends React.Component {
|
|||
|
||||
// create channel or team
|
||||
create({
|
||||
name: channelName, users, type, readOnly, broadcast, encrypted, isTeam: this.isTeam
|
||||
name: channelName, users, type, readOnly, broadcast, encrypted, isTeam: this.isTeam, teamId: this.teamId
|
||||
});
|
||||
|
||||
Review.pushPositiveEvent();
|
||||
|
|
|
@ -114,7 +114,7 @@ class RightButtonsContainer extends Component {
|
|||
goTeamChannels = () => {
|
||||
logEvent(events.ROOM_GO_TEAM_CHANNELS);
|
||||
const {
|
||||
navigation, isMasterDetail, teamId
|
||||
navigation, isMasterDetail, teamId, rid
|
||||
} = this.props;
|
||||
if (isMasterDetail) {
|
||||
navigation.navigate('ModalStackNavigator', {
|
||||
|
@ -122,7 +122,7 @@ class RightButtonsContainer extends Component {
|
|||
params: { teamId }
|
||||
});
|
||||
} else {
|
||||
navigation.navigate('TeamChannelsView', { teamId });
|
||||
navigation.navigate('TeamChannelsView', { teamId, rid });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Keyboard } from 'react-native';
|
||||
import { Keyboard, Alert } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Q } from '@nozbe/watermelondb';
|
||||
import { withSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
|
@ -28,6 +28,8 @@ import debounce from '../utils/debounce';
|
|||
import { showErrorAlert } from '../utils/info';
|
||||
import { goRoom } from '../utils/goRoom';
|
||||
import I18n from '../i18n';
|
||||
import { withActionSheet } from '../containers/ActionSheet';
|
||||
import { deleteRoom as deleteRoomAction } from '../actions/room';
|
||||
|
||||
const API_FETCH_COUNT = 25;
|
||||
|
||||
|
@ -47,12 +49,16 @@ class TeamChannelsView extends React.Component {
|
|||
theme: PropTypes.string,
|
||||
useRealName: PropTypes.bool,
|
||||
width: PropTypes.number,
|
||||
StoreLastMessage: PropTypes.bool
|
||||
StoreLastMessage: PropTypes.bool,
|
||||
addTeamChannelPermission: PropTypes.array,
|
||||
showActionSheet: PropTypes.func,
|
||||
deleteRoom: PropTypes.func
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.teamId = props.route.params?.teamId;
|
||||
this.rid = props.route.params?.rid;
|
||||
this.state = {
|
||||
loading: true,
|
||||
loadingMore: false,
|
||||
|
@ -60,9 +66,11 @@ class TeamChannelsView extends React.Component {
|
|||
isSearching: false,
|
||||
searchText: '',
|
||||
search: [],
|
||||
end: false
|
||||
end: false,
|
||||
showCreate: false
|
||||
};
|
||||
this.loadTeam();
|
||||
this.setHeader();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -70,6 +78,7 @@ class TeamChannelsView extends React.Component {
|
|||
}
|
||||
|
||||
loadTeam = async() => {
|
||||
const { addTeamChannelPermission } = this.props;
|
||||
const db = database.active;
|
||||
try {
|
||||
const subCollection = db.get('subscriptions');
|
||||
|
@ -82,6 +91,11 @@ class TeamChannelsView extends React.Component {
|
|||
if (!this.team) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
const permissions = await RocketChat.hasPermission([addTeamChannelPermission], this.team.rid);
|
||||
if (permissions[0]) {
|
||||
this.setState({ showCreate: true }, () => this.setHeader());
|
||||
}
|
||||
} catch {
|
||||
const { navigation } = this.props;
|
||||
navigation.pop();
|
||||
|
@ -135,8 +149,8 @@ class TeamChannelsView extends React.Component {
|
|||
}
|
||||
}, 300)
|
||||
|
||||
getHeader = () => {
|
||||
const { isSearching } = this.state;
|
||||
setHeader = () => {
|
||||
const { isSearching, showCreate, data } = this.state;
|
||||
const {
|
||||
navigation, isMasterDetail, insets, theme
|
||||
} = this.props;
|
||||
|
@ -201,15 +215,11 @@ class TeamChannelsView extends React.Component {
|
|||
options.headerRight = () => (
|
||||
<HeaderButton.Container>
|
||||
<HeaderButton.Item iconName='search' onPress={this.onSearchPress} />
|
||||
<HeaderButton.Item iconName='create' onPress={() => navigation.navigate('AddChannelTeamView')} />
|
||||
{ showCreate
|
||||
? <HeaderButton.Item iconName='create' onPress={() => navigation.navigate('AddChannelTeamView', { teamId: this.teamId, teamChannels: data })} />
|
||||
: null}
|
||||
</HeaderButton.Container>
|
||||
);
|
||||
return options;
|
||||
}
|
||||
|
||||
setHeader = () => {
|
||||
const { navigation } = this.props;
|
||||
const options = this.getHeader();
|
||||
navigation.setOptions(options);
|
||||
}
|
||||
|
||||
|
@ -288,6 +298,54 @@ class TeamChannelsView extends React.Component {
|
|||
}
|
||||
}, 1000, true);
|
||||
|
||||
options = item => ([
|
||||
{
|
||||
title: I18n.t('Auto-join'),
|
||||
icon: item.t === 'p' ? 'channel-private' : 'channel-public'
|
||||
// onPress: this.autoJoin
|
||||
},
|
||||
{
|
||||
title: I18n.t('Remove_from_Team'),
|
||||
icon: 'close',
|
||||
danger: true,
|
||||
onPress: this.removeFromTeam(item.id, this.teamId)
|
||||
},
|
||||
{
|
||||
title: I18n.t('Delete'),
|
||||
icon: 'delete',
|
||||
danger: true,
|
||||
onPress: this.delete
|
||||
}
|
||||
])
|
||||
|
||||
delete = () => {
|
||||
const { room } = this.state;
|
||||
const { deleteRoom } = this.props;
|
||||
|
||||
Alert.alert(
|
||||
I18n.t('Are_you_sure_question_mark'),
|
||||
I18n.t('Delete_Room_Warning'),
|
||||
[
|
||||
{
|
||||
text: I18n.t('Cancel'),
|
||||
style: 'cancel'
|
||||
},
|
||||
{
|
||||
text: I18n.t('Yes_action_it', { action: I18n.t('delete') }),
|
||||
style: 'destructive',
|
||||
onPress: () => deleteRoom(room.rid, room.t)
|
||||
}
|
||||
],
|
||||
{ cancelable: false }
|
||||
);
|
||||
}
|
||||
|
||||
showChannelActions = (item) => {
|
||||
logEvent(events.ROOM_SHOW_BOX_ACTIONS);
|
||||
const { showActionSheet } = this.props;
|
||||
showActionSheet({ options: this.options(item) });
|
||||
}
|
||||
|
||||
renderItem = ({ item }) => {
|
||||
const {
|
||||
StoreLastMessage,
|
||||
|
@ -303,6 +361,7 @@ class TeamChannelsView extends React.Component {
|
|||
showLastMessage={StoreLastMessage}
|
||||
onPress={this.onPressItem}
|
||||
width={width}
|
||||
onLongPress={this.showChannelActions}
|
||||
useRealName={useRealName}
|
||||
getRoomTitle={this.getRoomTitle}
|
||||
getRoomAvatar={this.getRoomAvatar}
|
||||
|
@ -366,7 +425,12 @@ const mapStateToProps = state => ({
|
|||
user: getUserSelector(state),
|
||||
useRealName: state.settings.UI_Use_Real_Name,
|
||||
isMasterDetail: state.app.isMasterDetail,
|
||||
StoreLastMessage: state.settings.Store_Last_Message
|
||||
StoreLastMessage: state.settings.Store_Last_Message,
|
||||
addTeamChannelPermission: state.permissions['add-team-channel']
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(withDimensions(withSafeAreaInsets(withTheme(TeamChannelsView))));
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
deleteRoom: (rid, t) => dispatch(deleteRoomAction(rid, t))
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(withDimensions(withSafeAreaInsets(withTheme(withActionSheet(TeamChannelsView)))));
|
||||
|
|
Loading…
Reference in New Issue