220 lines
6.3 KiB
TypeScript
220 lines
6.3 KiB
TypeScript
import React, { useCallback, useEffect, useLayoutEffect } from 'react';
|
|
import { shallowEqual, useDispatch } from 'react-redux';
|
|
import { FlatList, ScrollView, StyleSheet, Text, View } from 'react-native';
|
|
import { RouteProp, useNavigation, useRoute } from '@react-navigation/native';
|
|
import { StackNavigationProp } from '@react-navigation/stack';
|
|
import { useForm } from 'react-hook-form';
|
|
|
|
import { useAppSelector, usePermissions } from '../../lib/hooks';
|
|
import { sendLoadingEvent } from '../../containers/Loading';
|
|
import { createChannelRequest } from '../../actions/createChannel';
|
|
import { removeUser as removeUserAction } from '../../actions/selectedUsers';
|
|
import KeyboardView from '../../containers/KeyboardView';
|
|
import scrollPersistTaps from '../../lib/methods/helpers/scrollPersistTaps';
|
|
import I18n from '../../i18n';
|
|
import StatusBar from '../../containers/StatusBar';
|
|
import { useTheme } from '../../theme';
|
|
import { Review } from '../../lib/methods/helpers/review';
|
|
import SafeAreaView from '../../containers/SafeAreaView';
|
|
import sharedStyles from '../Styles';
|
|
import { ChatsStackParamList } from '../../stacks/types';
|
|
import Button from '../../containers/Button';
|
|
import { ControlledFormTextInput } from '../../containers/TextInput';
|
|
import Chip from '../../containers/Chip';
|
|
import { RoomSettings } from './RoomSettings';
|
|
import { ISelectedUser } from '../../reducers/selectedUsers';
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1
|
|
},
|
|
containerTextInput: {
|
|
paddingHorizontal: 16,
|
|
marginTop: 16
|
|
},
|
|
containerStyle: {
|
|
marginBottom: 16
|
|
},
|
|
list: {
|
|
width: '100%'
|
|
},
|
|
invitedHeader: {
|
|
marginVertical: 12,
|
|
marginHorizontal: 16,
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center'
|
|
},
|
|
invitedCount: {
|
|
fontSize: 12,
|
|
...sharedStyles.textRegular
|
|
},
|
|
invitedList: {
|
|
paddingHorizontal: 16
|
|
},
|
|
buttonCreate: {
|
|
margin: 16
|
|
}
|
|
});
|
|
|
|
export interface IFormData {
|
|
channelName: string;
|
|
type: boolean;
|
|
readOnly: boolean;
|
|
encrypted: boolean;
|
|
broadcast: boolean;
|
|
}
|
|
|
|
const CreateChannelView = () => {
|
|
const [createChannelPermission, createPrivateChannelPermission] = usePermissions(['create-c', 'create-p']);
|
|
|
|
const { isFetching, useRealName, users, e2eEnabledDefaultPrivateRooms } = useAppSelector(
|
|
state => ({
|
|
isFetching: state.createChannel.isFetching,
|
|
users: state.selectedUsers.users,
|
|
useRealName: state.settings.UI_Use_Real_Name as boolean,
|
|
e2eEnabledDefaultPrivateRooms: state.encryption.enabled && (state.settings.E2E_Enabled_Default_PrivateRooms as boolean)
|
|
}),
|
|
shallowEqual
|
|
);
|
|
|
|
const {
|
|
control,
|
|
handleSubmit,
|
|
formState: { isDirty },
|
|
setValue
|
|
} = useForm<IFormData>({
|
|
defaultValues: {
|
|
channelName: '',
|
|
broadcast: false,
|
|
encrypted: e2eEnabledDefaultPrivateRooms,
|
|
readOnly: false,
|
|
type: createPrivateChannelPermission
|
|
}
|
|
});
|
|
|
|
const navigation = useNavigation<StackNavigationProp<ChatsStackParamList, 'CreateChannelView'>>();
|
|
const { params } = useRoute<RouteProp<ChatsStackParamList, 'CreateChannelView'>>();
|
|
const isTeam = params?.isTeam || false;
|
|
const teamId = params?.teamId;
|
|
const { colors } = useTheme();
|
|
const dispatch = useDispatch();
|
|
|
|
useEffect(() => {
|
|
sendLoadingEvent({ visible: isFetching });
|
|
}, [isFetching]);
|
|
|
|
useLayoutEffect(() => {
|
|
navigation.setOptions({
|
|
title: isTeam ? I18n.t('Create_Team') : I18n.t('Create_Channel')
|
|
});
|
|
}, [isTeam, navigation]);
|
|
|
|
const removeUser = useCallback(
|
|
(user: ISelectedUser) => {
|
|
dispatch(removeUserAction(user));
|
|
},
|
|
[dispatch]
|
|
);
|
|
|
|
const submit = ({ channelName, broadcast, encrypted, readOnly, type }: IFormData) => {
|
|
if (!channelName.trim() || isFetching) {
|
|
return;
|
|
}
|
|
// transform users object into array of usernames
|
|
const usersMapped = users.map(user => user.name);
|
|
// create channel or team
|
|
const data = {
|
|
name: channelName,
|
|
users: usersMapped,
|
|
type,
|
|
readOnly,
|
|
broadcast,
|
|
encrypted,
|
|
isTeam,
|
|
teamId
|
|
};
|
|
dispatch(createChannelRequest(data));
|
|
Review.pushPositiveEvent();
|
|
};
|
|
|
|
return (
|
|
<KeyboardView
|
|
style={{ backgroundColor: colors.backgroundColor }}
|
|
contentContainerStyle={[sharedStyles.container, styles.container]}
|
|
keyboardVerticalOffset={128}
|
|
>
|
|
<StatusBar />
|
|
<SafeAreaView style={{ backgroundColor: colors.backgroundColor }} testID='create-channel-view'>
|
|
<ScrollView {...scrollPersistTaps}>
|
|
<View style={[styles.containerTextInput, { borderColor: colors.separatorColor }]}>
|
|
<ControlledFormTextInput
|
|
label={isTeam ? I18n.t('Team_Name') : I18n.t('Channel_Name')}
|
|
testID='create-channel-name'
|
|
returnKeyType='done'
|
|
containerStyle={styles.containerStyle}
|
|
name={'channelName'}
|
|
control={control}
|
|
/>
|
|
<RoomSettings
|
|
createChannelPermission={createChannelPermission}
|
|
createPrivateChannelPermission={createPrivateChannelPermission}
|
|
isTeam={isTeam}
|
|
setValue={setValue}
|
|
e2eEnabledDefaultPrivateRooms={e2eEnabledDefaultPrivateRooms}
|
|
/>
|
|
</View>
|
|
{users.length > 0 ? (
|
|
<>
|
|
<View style={styles.invitedHeader}>
|
|
<Text style={[styles.invitedCount, { color: colors.auxiliaryText }]}>
|
|
{I18n.t('N_Selected_members', { n: users.length })}
|
|
</Text>
|
|
</View>
|
|
<FlatList
|
|
data={users}
|
|
extraData={users}
|
|
keyExtractor={item => item._id}
|
|
style={[
|
|
styles.list,
|
|
{
|
|
backgroundColor: colors.backgroundColor,
|
|
borderColor: colors.separatorColor
|
|
}
|
|
]}
|
|
contentContainerStyle={styles.invitedList}
|
|
renderItem={({ item }) => {
|
|
const name = useRealName && item.fname ? item.fname : item.name;
|
|
const username = item.name;
|
|
|
|
return (
|
|
<Chip
|
|
text={name}
|
|
avatar={username}
|
|
onPress={() => removeUser(item)}
|
|
testID={`create-channel-view-item-${item.name}`}
|
|
/>
|
|
);
|
|
}}
|
|
keyboardShouldPersistTaps='always'
|
|
horizontal
|
|
/>
|
|
</>
|
|
) : null}
|
|
<Button
|
|
title={isTeam ? I18n.t('Create_Team') : I18n.t('Create_Channel')}
|
|
type='primary'
|
|
onPress={handleSubmit(submit)}
|
|
disabled={!isDirty}
|
|
testID='create-channel-submit'
|
|
loading={isFetching}
|
|
style={styles.buttonCreate}
|
|
/>
|
|
</ScrollView>
|
|
</SafeAreaView>
|
|
</KeyboardView>
|
|
);
|
|
};
|
|
|
|
export default CreateChannelView;
|