813 lines
23 KiB
TypeScript
813 lines
23 KiB
TypeScript
import React from 'react';
|
|
import { Q } from '@nozbe/watermelondb';
|
|
import { BlockContext } from '@rocket.chat/ui-kit';
|
|
import { dequal } from 'dequal';
|
|
import isEmpty from 'lodash/isEmpty';
|
|
import { Alert, Keyboard, ScrollView, Text, TextInput, TouchableOpacity, View, StyleSheet } from 'react-native';
|
|
import ImagePicker, { Image } from 'react-native-image-crop-picker';
|
|
import { connect } from 'react-redux';
|
|
|
|
import { deleteRoom } from '../../actions/room';
|
|
import { themes } from '../../lib/constants';
|
|
import Avatar from '../../containers/Avatar';
|
|
import Loading from '../../containers/Loading';
|
|
import SafeAreaView from '../../containers/SafeAreaView';
|
|
import StatusBar from '../../containers/StatusBar';
|
|
import { FormTextInput } from '../../containers/TextInput';
|
|
import { LISTENER } from '../../containers/Toast';
|
|
import { MultiSelect } from '../../containers/UIKit/MultiSelect';
|
|
import {
|
|
IApplicationState,
|
|
IBaseScreen,
|
|
IRoomSettings,
|
|
ISubscription,
|
|
SubscriptionType,
|
|
TSubscriptionModel,
|
|
IAvatar
|
|
} from '../../definitions';
|
|
import { ERoomType } from '../../definitions/ERoomType';
|
|
import I18n from '../../i18n';
|
|
import database from '../../lib/database';
|
|
import { CustomIcon } from '../../containers/CustomIcon';
|
|
import KeyboardView from '../../containers/KeyboardView';
|
|
import { TSupportedPermissions } from '../../reducers/permissions';
|
|
import { ModalStackParamList } from '../../stacks/MasterDetailStack/types';
|
|
import { ChatsStackParamList } from '../../stacks/types';
|
|
import { withTheme } from '../../theme';
|
|
import EventEmitter from '../../lib/methods/helpers/events';
|
|
import log, { events, logEvent } from '../../lib/methods/helpers/log';
|
|
import { MessageTypeValues } from './messageTypes';
|
|
import scrollPersistTaps from '../../lib/methods/helpers/scrollPersistTaps';
|
|
import sharedStyles from '../Styles';
|
|
import styles from './styles';
|
|
import SwitchContainer from './SwitchContainer';
|
|
import {
|
|
getRoomTitle,
|
|
hasPermission,
|
|
compareServerVersion,
|
|
showConfirmationAlert,
|
|
showErrorAlert,
|
|
random
|
|
} from '../../lib/methods/helpers';
|
|
import { Services } from '../../lib/services';
|
|
|
|
interface IRoomInfoEditViewState {
|
|
room: ISubscription;
|
|
avatar: IAvatar;
|
|
permissions: { [key in TSupportedPermissions]?: boolean };
|
|
name: string;
|
|
description?: string;
|
|
topic?: string;
|
|
announcement?: string;
|
|
joinCode: string;
|
|
nameError: any;
|
|
saving: boolean;
|
|
t: boolean;
|
|
ro: boolean;
|
|
reactWhenReadOnly?: boolean;
|
|
archived: boolean;
|
|
systemMessages?: boolean | string[];
|
|
enableSysMes?: boolean | string[];
|
|
encrypted?: boolean;
|
|
}
|
|
|
|
interface IRoomInfoEditViewProps extends IBaseScreen<ChatsStackParamList | ModalStackParamList, 'RoomInfoEditView'> {
|
|
serverVersion?: string;
|
|
encryptionEnabled: boolean;
|
|
setReadOnlyPermission: string[];
|
|
setReactWhenReadOnlyPermission: string[];
|
|
archiveRoomPermission: string[];
|
|
unarchiveRoomPermission: string[];
|
|
deleteCPermission: string[];
|
|
deletePPermission: string[];
|
|
deleteTeamPermission: string[];
|
|
}
|
|
|
|
class RoomInfoEditView extends React.Component<IRoomInfoEditViewProps, IRoomInfoEditViewState> {
|
|
randomValue = random(15);
|
|
private room: TSubscriptionModel;
|
|
private name: TextInput | null | undefined;
|
|
private description: TextInput | null | undefined;
|
|
private topic: TextInput | null | undefined;
|
|
private announcement: TextInput | null | undefined;
|
|
private joinCode: TextInput | null | undefined;
|
|
|
|
static navigationOptions = () => ({
|
|
title: I18n.t('Room_Info_Edit')
|
|
});
|
|
|
|
constructor(props: IRoomInfoEditViewProps) {
|
|
super(props);
|
|
this.room = {} as TSubscriptionModel;
|
|
this.state = {
|
|
room: {} as ISubscription,
|
|
avatar: {} as IAvatar,
|
|
permissions: {},
|
|
name: '',
|
|
description: '',
|
|
topic: '',
|
|
announcement: '',
|
|
joinCode: '',
|
|
nameError: {},
|
|
saving: false,
|
|
t: false,
|
|
ro: false,
|
|
reactWhenReadOnly: false,
|
|
archived: false,
|
|
systemMessages: [],
|
|
enableSysMes: false,
|
|
encrypted: false
|
|
};
|
|
this.loadRoom();
|
|
}
|
|
|
|
loadRoom = async () => {
|
|
const {
|
|
route,
|
|
setReadOnlyPermission,
|
|
setReactWhenReadOnlyPermission,
|
|
archiveRoomPermission,
|
|
unarchiveRoomPermission,
|
|
deleteCPermission,
|
|
deletePPermission,
|
|
deleteTeamPermission
|
|
} = this.props;
|
|
const rid = route.params?.rid;
|
|
if (!rid) {
|
|
return;
|
|
}
|
|
try {
|
|
const db = database.active;
|
|
const sub = await db.get('subscriptions').find(rid);
|
|
this.room = sub;
|
|
this.init(this.room);
|
|
|
|
const result = await hasPermission(
|
|
[
|
|
setReadOnlyPermission,
|
|
setReactWhenReadOnlyPermission,
|
|
archiveRoomPermission,
|
|
unarchiveRoomPermission,
|
|
deleteCPermission,
|
|
deletePPermission,
|
|
...(this.room.teamMain ? [deleteTeamPermission] : [])
|
|
],
|
|
rid
|
|
);
|
|
|
|
this.setState({
|
|
permissions: {
|
|
'set-readonly': result[0],
|
|
'set-react-when-readonly': result[1],
|
|
'archive-room': result[2],
|
|
'unarchive-room': result[3],
|
|
'delete-c': result[4],
|
|
'delete-p': result[5],
|
|
...(this.room.teamMain && { 'delete-team': result[6] })
|
|
}
|
|
});
|
|
} catch (e) {
|
|
log(e);
|
|
}
|
|
};
|
|
|
|
init = (room: ISubscription) => {
|
|
const { description, topic, announcement, t, ro, reactWhenReadOnly, joinCodeRequired, encrypted } = room;
|
|
const sysMes = room.sysMes as string[];
|
|
// fake password just to user knows about it
|
|
this.setState({
|
|
room,
|
|
name: getRoomTitle(room),
|
|
description,
|
|
topic,
|
|
announcement,
|
|
t: t === 'p',
|
|
avatar: {} as IAvatar,
|
|
ro,
|
|
reactWhenReadOnly,
|
|
joinCode: joinCodeRequired ? this.randomValue : '',
|
|
archived: room.archived,
|
|
systemMessages: sysMes,
|
|
enableSysMes: sysMes && sysMes.length > 0,
|
|
encrypted
|
|
});
|
|
};
|
|
|
|
clearErrors = () => {
|
|
this.setState({
|
|
nameError: {}
|
|
});
|
|
};
|
|
|
|
reset = () => {
|
|
logEvent(events.RI_EDIT_RESET);
|
|
this.clearErrors();
|
|
this.init(this.room);
|
|
};
|
|
|
|
formIsChanged = () => {
|
|
const {
|
|
room,
|
|
name,
|
|
description,
|
|
topic,
|
|
announcement,
|
|
t,
|
|
ro,
|
|
reactWhenReadOnly,
|
|
joinCode,
|
|
systemMessages,
|
|
enableSysMes,
|
|
encrypted,
|
|
avatar
|
|
} = this.state;
|
|
const { joinCodeRequired } = room;
|
|
const sysMes = room.sysMes as string[];
|
|
return !(
|
|
room.name === name &&
|
|
room.description === description &&
|
|
room.topic === topic &&
|
|
room.announcement === announcement &&
|
|
(joinCodeRequired ? this.randomValue : '') === joinCode &&
|
|
(room.t === 'p') === t &&
|
|
room.ro === ro &&
|
|
room.reactWhenReadOnly === reactWhenReadOnly &&
|
|
dequal(sysMes, systemMessages) &&
|
|
enableSysMes === (sysMes && sysMes.length > 0) &&
|
|
room.encrypted === encrypted &&
|
|
isEmpty(avatar)
|
|
);
|
|
};
|
|
|
|
submit = async () => {
|
|
logEvent(events.RI_EDIT_SAVE);
|
|
Keyboard.dismiss();
|
|
const {
|
|
room,
|
|
name,
|
|
description,
|
|
topic,
|
|
announcement,
|
|
t,
|
|
ro,
|
|
reactWhenReadOnly,
|
|
joinCode,
|
|
systemMessages,
|
|
encrypted,
|
|
avatar
|
|
} = this.state;
|
|
|
|
this.setState({ saving: true });
|
|
let error = false;
|
|
|
|
if (!this.formIsChanged()) {
|
|
showErrorAlert(I18n.t('Nothing_to_save'));
|
|
return;
|
|
}
|
|
|
|
// Clear error objects
|
|
await this.clearErrors();
|
|
|
|
const params = {} as IRoomSettings;
|
|
|
|
// Name
|
|
if (room.name !== name) {
|
|
params.roomName = name;
|
|
}
|
|
// Avatar
|
|
if (!isEmpty(avatar)) {
|
|
params.roomAvatar = avatar.data as string;
|
|
}
|
|
// Description
|
|
if (room.description !== description) {
|
|
params.roomDescription = description;
|
|
}
|
|
// Topic
|
|
if (room.topic !== topic) {
|
|
params.roomTopic = topic;
|
|
}
|
|
// Announcement
|
|
if (room.announcement !== announcement) {
|
|
params.roomAnnouncement = announcement;
|
|
}
|
|
// Room Type
|
|
if ((room.t === SubscriptionType.GROUP) !== t) {
|
|
params.roomType = t ? ('p' as SubscriptionType) : ('c' as SubscriptionType);
|
|
}
|
|
// Read Only
|
|
if (room.ro !== ro) {
|
|
params.readOnly = ro;
|
|
}
|
|
// React When Read Only
|
|
if (room.reactWhenReadOnly !== reactWhenReadOnly) {
|
|
params.reactWhenReadOnly = reactWhenReadOnly;
|
|
}
|
|
|
|
if (!dequal(room.sysMes, systemMessages)) {
|
|
params.systemMessages = systemMessages as string[];
|
|
}
|
|
|
|
// Join Code
|
|
if (this.randomValue !== joinCode) {
|
|
params.joinCode = joinCode;
|
|
}
|
|
|
|
// Encrypted
|
|
if (room.encrypted !== encrypted) {
|
|
params.encrypted = encrypted;
|
|
}
|
|
|
|
try {
|
|
await Services.saveRoomSettings(room.rid, params);
|
|
} catch (e: any) {
|
|
if (e.error === 'error-invalid-room-name') {
|
|
this.setState({ nameError: e });
|
|
}
|
|
error = true;
|
|
log(e);
|
|
}
|
|
|
|
await this.setState({ saving: false });
|
|
setTimeout(() => {
|
|
if (error) {
|
|
logEvent(events.RI_EDIT_SAVE_F);
|
|
showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t('saving_settings') }));
|
|
} else {
|
|
EventEmitter.emit(LISTENER, { message: I18n.t('Settings_succesfully_changed') });
|
|
}
|
|
}, 100);
|
|
};
|
|
|
|
deleteTeam = async () => {
|
|
const { room } = this.state;
|
|
const { navigation, deleteCPermission, deletePPermission, dispatch } = this.props;
|
|
|
|
try {
|
|
const db = database.active;
|
|
const subCollection = db.get('subscriptions');
|
|
const teamChannels = await subCollection
|
|
.query(Q.where('team_id', room.teamId as string), Q.where('team_main', Q.notEq(true)))
|
|
.fetch();
|
|
|
|
const teamChannelOwner = [];
|
|
for (let i = 0; i < teamChannels.length; i += 1) {
|
|
const permissionType = teamChannels[i].t === 'c' ? deleteCPermission : deletePPermission;
|
|
// eslint-disable-next-line no-await-in-loop
|
|
const permissions = await hasPermission([permissionType], teamChannels[i].rid);
|
|
if (permissions[0]) {
|
|
teamChannelOwner.push(teamChannels[i]);
|
|
}
|
|
}
|
|
|
|
if (teamChannelOwner.length) {
|
|
navigation.navigate('SelectListView', {
|
|
title: 'Delete_Team',
|
|
data: teamChannelOwner,
|
|
infoText: 'Select_channels_to_delete',
|
|
nextAction: (selected: string[]) => {
|
|
showConfirmationAlert({
|
|
message: I18n.t('You_are_deleting_the_team', { team: getRoomTitle(room) }),
|
|
confirmationText: I18n.t('Yes_action_it', { action: I18n.t('delete') }),
|
|
onPress: () => deleteRoom(ERoomType.t, room, selected)
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
showConfirmationAlert({
|
|
message: I18n.t('You_are_deleting_the_team', { team: getRoomTitle(room) }),
|
|
confirmationText: I18n.t('Yes_action_it', { action: I18n.t('delete') }),
|
|
onPress: () => dispatch(deleteRoom(ERoomType.t, room))
|
|
});
|
|
}
|
|
} catch (e: any) {
|
|
log(e);
|
|
showErrorAlert(
|
|
e.data.error ? I18n.t(e.data.error) : I18n.t('There_was_an_error_while_action', { action: I18n.t('deleting_team') }),
|
|
I18n.t('Cannot_delete')
|
|
);
|
|
}
|
|
};
|
|
|
|
delete = () => {
|
|
const { room } = this.state;
|
|
const { dispatch } = 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: () => dispatch(deleteRoom(ERoomType.c, room))
|
|
}
|
|
],
|
|
{ cancelable: false }
|
|
);
|
|
};
|
|
|
|
toggleArchive = () => {
|
|
const { room } = this.state;
|
|
const { rid, archived, t } = room;
|
|
|
|
const action = I18n.t(`${archived ? 'un' : ''}archive`);
|
|
Alert.alert(
|
|
I18n.t('Are_you_sure_question_mark'),
|
|
I18n.t('Do_you_really_want_to_key_this_room_question_mark', { key: action }),
|
|
[
|
|
{
|
|
text: I18n.t('Cancel'),
|
|
style: 'cancel'
|
|
},
|
|
{
|
|
text: I18n.t('Yes_action_it', { action }),
|
|
style: 'destructive',
|
|
onPress: async () => {
|
|
try {
|
|
logEvent(events.RI_EDIT_TOGGLE_ARCHIVE);
|
|
await Services.toggleArchiveRoom(rid, t as SubscriptionType, !archived);
|
|
} catch (e) {
|
|
logEvent(events.RI_EDIT_TOGGLE_ARCHIVE_F);
|
|
log(e);
|
|
}
|
|
}
|
|
}
|
|
],
|
|
{ cancelable: false }
|
|
);
|
|
};
|
|
|
|
hasDeletePermission = () => {
|
|
const { room, permissions } = this.state;
|
|
|
|
if (room.teamMain) {
|
|
return permissions['delete-team'];
|
|
}
|
|
|
|
if (room.t === 'p') {
|
|
return permissions['delete-p'];
|
|
}
|
|
|
|
return permissions['delete-c'];
|
|
};
|
|
|
|
renderSystemMessages = () => {
|
|
const { systemMessages, enableSysMes } = this.state;
|
|
|
|
if (!enableSysMes) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<MultiSelect
|
|
options={MessageTypeValues.map(m => ({
|
|
value: m.value,
|
|
text: { text: I18n.t('Hide_type_messages', { type: I18n.t(m.text) }) }
|
|
}))}
|
|
onChange={({ value }: { value: boolean }) => this.setState({ systemMessages: value })}
|
|
placeholder={{ text: I18n.t('Hide_System_Messages') }}
|
|
value={systemMessages as string[]}
|
|
context={BlockContext.FORM}
|
|
multiselect
|
|
/>
|
|
);
|
|
};
|
|
|
|
changeAvatar = async () => {
|
|
const options = {
|
|
cropping: true,
|
|
compressImageQuality: 0.8,
|
|
cropperAvoidEmptySpaceAroundImage: false,
|
|
cropperChooseText: I18n.t('Choose'),
|
|
cropperCancelText: I18n.t('Cancel'),
|
|
includeBase64: true
|
|
};
|
|
|
|
try {
|
|
const response: Image = await ImagePicker.openPicker(options);
|
|
this.setState({ avatar: { url: response.path, data: `data:image/jpeg;base64,${response.data}`, service: 'upload' } });
|
|
} catch (e) {
|
|
console.log(e);
|
|
}
|
|
};
|
|
|
|
resetAvatar = () => {
|
|
this.setState({ avatar: { data: null } });
|
|
};
|
|
|
|
toggleRoomType = (value: boolean) => {
|
|
logEvent(events.RI_EDIT_TOGGLE_ROOM_TYPE);
|
|
this.setState(({ encrypted }) => ({ t: value, encrypted: value && encrypted }));
|
|
};
|
|
|
|
toggleReadOnly = (value: boolean) => {
|
|
logEvent(events.RI_EDIT_TOGGLE_READ_ONLY);
|
|
this.setState({ ro: value });
|
|
};
|
|
|
|
toggleReactions = (value: boolean) => {
|
|
logEvent(events.RI_EDIT_TOGGLE_REACTIONS);
|
|
this.setState({ reactWhenReadOnly: value });
|
|
};
|
|
|
|
toggleHideSystemMessages = (value: boolean) => {
|
|
logEvent(events.RI_EDIT_TOGGLE_SYSTEM_MSG);
|
|
this.setState(({ systemMessages }) => ({ enableSysMes: value, systemMessages: value ? systemMessages : [] }));
|
|
};
|
|
|
|
toggleEncrypted = (value: boolean) => {
|
|
logEvent(events.RI_EDIT_TOGGLE_ENCRYPTED);
|
|
this.setState({ encrypted: value });
|
|
};
|
|
|
|
render() {
|
|
const {
|
|
name,
|
|
nameError,
|
|
description,
|
|
topic,
|
|
announcement,
|
|
t,
|
|
ro,
|
|
reactWhenReadOnly,
|
|
room,
|
|
joinCode,
|
|
saving,
|
|
permissions,
|
|
archived,
|
|
enableSysMes,
|
|
encrypted,
|
|
avatar
|
|
} = this.state;
|
|
const { serverVersion, encryptionEnabled, theme } = this.props;
|
|
const { dangerColor } = themes[theme];
|
|
|
|
return (
|
|
<KeyboardView
|
|
style={{ backgroundColor: themes[theme].backgroundColor }}
|
|
contentContainerStyle={sharedStyles.container}
|
|
keyboardVerticalOffset={128}>
|
|
<StatusBar />
|
|
<SafeAreaView testID='room-info-edit-view' style={{ backgroundColor: themes[theme].backgroundColor }}>
|
|
<ScrollView
|
|
contentContainerStyle={sharedStyles.containerScrollView}
|
|
testID='room-info-edit-view-list'
|
|
{...scrollPersistTaps}>
|
|
<TouchableOpacity
|
|
style={styles.avatarContainer}
|
|
onPress={this.changeAvatar}
|
|
disabled={compareServerVersion(serverVersion || '', 'lowerThan', '3.6.0')}>
|
|
<Avatar
|
|
type={room.t}
|
|
text={room.name}
|
|
avatar={avatar?.url}
|
|
isStatic={avatar?.url}
|
|
rid={isEmpty(avatar) ? room.rid : undefined}
|
|
size={100}>
|
|
{serverVersion && compareServerVersion(serverVersion, 'lowerThan', '3.6.0') ? undefined : (
|
|
<TouchableOpacity
|
|
style={[styles.resetButton, { backgroundColor: themes[theme].dangerColor }]}
|
|
onPress={this.resetAvatar}>
|
|
<CustomIcon name='delete' color={themes[theme].backgroundColor} size={24} />
|
|
</TouchableOpacity>
|
|
)}
|
|
</Avatar>
|
|
</TouchableOpacity>
|
|
<FormTextInput
|
|
inputRef={e => {
|
|
this.name = e;
|
|
}}
|
|
label={I18n.t('Name')}
|
|
value={name}
|
|
onChangeText={value => this.setState({ name: value })}
|
|
onSubmitEditing={() => {
|
|
this.description?.focus();
|
|
}}
|
|
error={nameError}
|
|
testID='room-info-edit-view-name'
|
|
/>
|
|
<FormTextInput
|
|
inputRef={e => {
|
|
this.description = e;
|
|
}}
|
|
label={I18n.t('Description')}
|
|
value={description}
|
|
onChangeText={value => this.setState({ description: value })}
|
|
onSubmitEditing={() => {
|
|
this.topic?.focus();
|
|
}}
|
|
testID='room-info-edit-view-description'
|
|
/>
|
|
<FormTextInput
|
|
inputRef={e => {
|
|
this.topic = e;
|
|
}}
|
|
label={I18n.t('Topic')}
|
|
value={topic}
|
|
onChangeText={value => this.setState({ topic: value })}
|
|
onSubmitEditing={() => {
|
|
this.announcement?.focus();
|
|
}}
|
|
testID='room-info-edit-view-topic'
|
|
/>
|
|
<FormTextInput
|
|
inputRef={e => {
|
|
this.announcement = e;
|
|
}}
|
|
label={I18n.t('Announcement')}
|
|
value={announcement}
|
|
onChangeText={value => this.setState({ announcement: value })}
|
|
onSubmitEditing={() => {
|
|
this.joinCode?.focus();
|
|
}}
|
|
testID='room-info-edit-view-announcement'
|
|
/>
|
|
{/* This TextInput avoid appears the password fill when typing into Announcements TextInput */}
|
|
<View style={{ height: StyleSheet.hairlineWidth, overflow: 'hidden' }}>
|
|
<TextInput
|
|
style={{
|
|
height: StyleSheet.hairlineWidth
|
|
}}
|
|
/>
|
|
</View>
|
|
<FormTextInput
|
|
inputRef={e => {
|
|
this.joinCode = e;
|
|
}}
|
|
label={I18n.t('Password')}
|
|
value={joinCode}
|
|
onChangeText={value => this.setState({ joinCode: value })}
|
|
onSubmitEditing={this.submit}
|
|
secureTextEntry
|
|
testID='room-info-edit-view-password'
|
|
/>
|
|
<SwitchContainer
|
|
value={t}
|
|
leftLabelPrimary={I18n.t('Public')}
|
|
leftLabelSecondary={
|
|
room.teamMain ? I18n.t('Everyone_can_access_this_team') : I18n.t('Everyone_can_access_this_channel')
|
|
}
|
|
rightLabelPrimary={I18n.t('Private')}
|
|
rightLabelSecondary={
|
|
room.teamMain
|
|
? I18n.t('Just_invited_people_can_access_this_team')
|
|
: I18n.t('Just_invited_people_can_access_this_channel')
|
|
}
|
|
onValueChange={this.toggleRoomType}
|
|
theme={theme}
|
|
testID='room-info-edit-view-t'
|
|
/>
|
|
<SwitchContainer
|
|
value={ro}
|
|
leftLabelPrimary={I18n.t('Collaborative')}
|
|
leftLabelSecondary={
|
|
room.teamMain
|
|
? I18n.t('All_users_in_the_team_can_write_new_messages')
|
|
: I18n.t('All_users_in_the_channel_can_write_new_messages')
|
|
}
|
|
rightLabelPrimary={I18n.t('Read_Only')}
|
|
rightLabelSecondary={I18n.t('Only_authorized_users_can_write_new_messages')}
|
|
onValueChange={this.toggleReadOnly}
|
|
disabled={!permissions['set-readonly'] || room.broadcast}
|
|
theme={theme}
|
|
testID='room-info-edit-view-ro'
|
|
/>
|
|
{ro && !room.broadcast ? (
|
|
<SwitchContainer
|
|
value={reactWhenReadOnly as boolean}
|
|
leftLabelPrimary={I18n.t('No_Reactions')}
|
|
leftLabelSecondary={I18n.t('Reactions_are_disabled')}
|
|
rightLabelPrimary={I18n.t('Allow_Reactions')}
|
|
rightLabelSecondary={I18n.t('Reactions_are_enabled')}
|
|
onValueChange={this.toggleReactions}
|
|
disabled={!permissions['set-react-when-readonly']}
|
|
theme={theme}
|
|
testID='room-info-edit-view-react-when-ro'
|
|
/>
|
|
) : null}
|
|
{room.broadcast
|
|
? [
|
|
<Text style={styles.broadcast}>{I18n.t('Broadcast_Channel')}</Text>,
|
|
<View style={[styles.divider, { borderColor: themes[theme].separatorColor }]} />
|
|
]
|
|
: null}
|
|
{serverVersion && !compareServerVersion(serverVersion, 'lowerThan', '3.0.0') ? (
|
|
<SwitchContainer
|
|
value={enableSysMes as boolean}
|
|
leftLabelPrimary={I18n.t('Hide_System_Messages')}
|
|
leftLabelSecondary={
|
|
enableSysMes
|
|
? I18n.t('Overwrites_the_server_configuration_and_use_room_config')
|
|
: I18n.t('Uses_server_configuration')
|
|
}
|
|
theme={theme}
|
|
testID='room-info-edit-switch-system-messages'
|
|
onValueChange={this.toggleHideSystemMessages}
|
|
labelContainerStyle={styles.hideSystemMessages}
|
|
leftLabelStyle={styles.systemMessagesLabel}>
|
|
{this.renderSystemMessages()}
|
|
</SwitchContainer>
|
|
) : null}
|
|
{encryptionEnabled ? (
|
|
<SwitchContainer
|
|
value={encrypted as boolean}
|
|
disabled={!t}
|
|
leftLabelPrimary={I18n.t('Encrypted')}
|
|
leftLabelSecondary={I18n.t('End_to_end_encrypted_room')}
|
|
theme={theme}
|
|
testID='room-info-edit-switch-encrypted'
|
|
onValueChange={this.toggleEncrypted}
|
|
labelContainerStyle={styles.hideSystemMessages}
|
|
leftLabelStyle={styles.systemMessagesLabel}
|
|
/>
|
|
) : null}
|
|
<TouchableOpacity
|
|
style={[
|
|
styles.buttonContainer,
|
|
{ backgroundColor: themes[theme].buttonBackground },
|
|
!this.formIsChanged() && styles.buttonContainerDisabled
|
|
]}
|
|
onPress={this.submit}
|
|
disabled={!this.formIsChanged()}
|
|
testID='room-info-edit-view-submit'>
|
|
<Text style={[styles.button, { color: themes[theme].buttonText }]} accessibilityRole='button'>
|
|
{I18n.t('SAVE')}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
<View style={{ flexDirection: 'row' }}>
|
|
<TouchableOpacity
|
|
style={[
|
|
styles.buttonContainer_inverted,
|
|
styles.buttonInverted,
|
|
{ flex: 1, borderColor: themes[theme].auxiliaryText },
|
|
!this.formIsChanged() && styles.buttonContainerDisabled
|
|
]}
|
|
onPress={this.reset}
|
|
disabled={!this.formIsChanged()}
|
|
testID='room-info-edit-view-reset'>
|
|
<Text
|
|
style={[styles.button, styles.button_inverted, { color: themes[theme].bodyText }]}
|
|
accessibilityRole='button'>
|
|
{I18n.t('RESET')}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
<TouchableOpacity
|
|
style={[
|
|
styles.buttonInverted,
|
|
styles.buttonContainer_inverted,
|
|
archived
|
|
? !permissions['unarchive-room'] && sharedStyles.opacity5
|
|
: !permissions['archive-room'] && sharedStyles.opacity5,
|
|
{ flex: 1, marginLeft: 10, borderColor: dangerColor }
|
|
]}
|
|
onPress={this.toggleArchive}
|
|
disabled={archived ? !permissions['unarchive-room'] : !permissions['archive-room']}
|
|
testID={archived ? 'room-info-edit-view-unarchive' : 'room-info-edit-view-archive'}>
|
|
<Text style={[styles.button, styles.button_inverted, { color: dangerColor }]}>
|
|
{archived ? I18n.t('UNARCHIVE') : I18n.t('ARCHIVE')}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
<View style={[styles.divider, { borderColor: themes[theme].separatorColor }]} />
|
|
<TouchableOpacity
|
|
style={[
|
|
styles.buttonContainer_inverted,
|
|
styles.buttonContainerLastChild,
|
|
styles.buttonDanger,
|
|
{ borderColor: dangerColor },
|
|
!this.hasDeletePermission() && sharedStyles.opacity5
|
|
]}
|
|
onPress={room.teamMain ? this.deleteTeam : this.delete}
|
|
disabled={!this.hasDeletePermission()}
|
|
testID='room-info-edit-view-delete'>
|
|
<Text style={[styles.button, styles.button_inverted, { color: dangerColor }]} accessibilityRole='button'>
|
|
{I18n.t('DELETE')}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
<Loading visible={saving} />
|
|
</ScrollView>
|
|
</SafeAreaView>
|
|
</KeyboardView>
|
|
);
|
|
}
|
|
}
|
|
|
|
const mapStateToProps = (state: IApplicationState) => ({
|
|
serverVersion: state.server.version as string,
|
|
encryptionEnabled: state.encryption.enabled,
|
|
setReadOnlyPermission: state.permissions['set-readonly'] as string[],
|
|
setReactWhenReadOnlyPermission: state.permissions['set-react-when-readonly'] as string[],
|
|
archiveRoomPermission: state.permissions['archive-room'] as string[],
|
|
unarchiveRoomPermission: state.permissions['unarchive-room'] as string[],
|
|
deleteCPermission: state.permissions['delete-c'] as string[],
|
|
deletePPermission: state.permissions['delete-p'] as string[],
|
|
deleteTeamPermission: state.permissions['delete-team'] as string[],
|
|
isMasterDetail: state.app.isMasterDetail
|
|
});
|
|
|
|
export default connect(mapStateToProps)(withTheme(RoomInfoEditView));
|