parent
8f90565e55
commit
061c313e3f
|
@ -71,7 +71,8 @@ export const MESSAGES = createRequestTypes('MESSAGES', [
|
|||
'TOGGLE_PIN_FAILURE',
|
||||
'SET_INPUT',
|
||||
'CLEAR_INPUT',
|
||||
'TOGGLE_REACTION_PICKER'
|
||||
'TOGGLE_REACTION_PICKER',
|
||||
'REPLY_BROADCAST'
|
||||
]);
|
||||
export const CREATE_CHANNEL = createRequestTypes('CREATE_CHANNEL', [...defaultTypes]);
|
||||
export const SELECTED_USERS = createRequestTypes('SELECTED_USERS', ['ADD_USER', 'REMOVE_USER', 'RESET', 'SET_LOADING']);
|
||||
|
|
|
@ -183,3 +183,10 @@ export function toggleReactionPicker(message) {
|
|||
message
|
||||
};
|
||||
}
|
||||
|
||||
export function replyBroadcast(message) {
|
||||
return {
|
||||
type: types.MESSAGES.REPLY_BROADCAST,
|
||||
message
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,6 +11,10 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
const RoomTypeIcon = ({ type, size }) => {
|
||||
if (!type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const icon = {
|
||||
c: 'pound',
|
||||
p: 'lock',
|
||||
|
@ -21,7 +25,7 @@ const RoomTypeIcon = ({ type, size }) => {
|
|||
};
|
||||
|
||||
RoomTypeIcon.propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
type: PropTypes.string,
|
||||
size: PropTypes.number
|
||||
};
|
||||
|
||||
|
|
|
@ -18,10 +18,28 @@ import Reply from './Reply';
|
|||
import ReactionsModal from './ReactionsModal';
|
||||
import Emoji from './Emoji';
|
||||
import styles from './styles';
|
||||
import { actionsShow, errorActionsShow, toggleReactionPicker } from '../../actions/messages';
|
||||
import { actionsShow, errorActionsShow, toggleReactionPicker, replyBroadcast } from '../../actions/messages';
|
||||
import messagesStatus from '../../constants/messagesStatus';
|
||||
import Touch from '../../utils/touch';
|
||||
|
||||
const SYSTEM_MESSAGES = [
|
||||
'r',
|
||||
'au',
|
||||
'ru',
|
||||
'ul',
|
||||
'uj',
|
||||
'rm',
|
||||
'user-muted',
|
||||
'user-unmuted',
|
||||
'message_pinned',
|
||||
'subscription-role-added',
|
||||
'subscription-role-removed',
|
||||
'room_changed_description',
|
||||
'room_changed_announcement',
|
||||
'room_changed_topic',
|
||||
'room_changed_privacy'
|
||||
];
|
||||
|
||||
const getInfoMessage = ({
|
||||
t, role, msg, u
|
||||
}) => {
|
||||
|
@ -68,7 +86,8 @@ const getInfoMessage = ({
|
|||
}), dispatch => ({
|
||||
actionsShow: actionMessage => dispatch(actionsShow(actionMessage)),
|
||||
errorActionsShow: actionMessage => dispatch(errorActionsShow(actionMessage)),
|
||||
toggleReactionPicker: message => dispatch(toggleReactionPicker(message))
|
||||
toggleReactionPicker: message => dispatch(toggleReactionPicker(message)),
|
||||
replyBroadcast: message => dispatch(replyBroadcast(message))
|
||||
}))
|
||||
export default class Message extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -83,17 +102,20 @@ export default class Message extends React.Component {
|
|||
editing: PropTypes.bool,
|
||||
errorActionsShow: PropTypes.func,
|
||||
toggleReactionPicker: PropTypes.func,
|
||||
replyBroadcast: PropTypes.func,
|
||||
onReactionPress: PropTypes.func,
|
||||
style: ViewPropTypes.style,
|
||||
onLongPress: PropTypes.func,
|
||||
_updatedAt: PropTypes.instanceOf(Date),
|
||||
archived: PropTypes.bool
|
||||
archived: PropTypes.bool,
|
||||
broadcast: PropTypes.bool
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
onLongPress: () => {},
|
||||
_updatedAt: new Date(),
|
||||
archived: false
|
||||
archived: false,
|
||||
broadcast: false
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
@ -116,6 +138,9 @@ export default class Message extends React.Component {
|
|||
if (!equal(this.props.reactions, nextProps.reactions)) {
|
||||
return true;
|
||||
}
|
||||
if (this.props.broadcast !== nextProps.broadcast) {
|
||||
return true;
|
||||
}
|
||||
return this.props._updatedAt.toGMTString() !== nextProps._updatedAt.toGMTString();
|
||||
}
|
||||
|
||||
|
@ -150,25 +175,11 @@ export default class Message extends React.Component {
|
|||
parseMessage = () => JSON.parse(JSON.stringify(this.props.item));
|
||||
|
||||
isInfoMessage() {
|
||||
return [
|
||||
'r',
|
||||
'au',
|
||||
'ru',
|
||||
'ul',
|
||||
'uj',
|
||||
'rm',
|
||||
'user-muted',
|
||||
'user-unmuted',
|
||||
'message_pinned',
|
||||
'subscription-role-added',
|
||||
'subscription-role-removed',
|
||||
'room_changed_description',
|
||||
'room_changed_announcement',
|
||||
'room_changed_topic',
|
||||
'room_changed_privacy'
|
||||
].includes(this.props.item.t);
|
||||
return SYSTEM_MESSAGES.includes(this.props.item.t);
|
||||
}
|
||||
|
||||
isOwn = () => this.props.item.u && this.props.item.u._id === this.props.user.id;
|
||||
|
||||
isDeleted() {
|
||||
return this.props.item.t === 'rm';
|
||||
}
|
||||
|
@ -187,7 +198,7 @@ export default class Message extends React.Component {
|
|||
if (previousItem && (
|
||||
(previousItem.ts.toDateString() === item.ts.toDateString()) &&
|
||||
(previousItem.u.username === item.u.username) &&
|
||||
!(previousItem.groupable === false || item.groupable === false) &&
|
||||
!(previousItem.groupable === false || item.groupable === false || this.props.broadcast === true) &&
|
||||
(previousItem.status === item.status) &&
|
||||
(item.ts - previousItem.ts < this.props.Message_GroupingPeriod * 1000)
|
||||
)) {
|
||||
|
@ -303,6 +314,20 @@ export default class Message extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
renderBroadcastReply() {
|
||||
if (!this.props.broadcast || this.isOwn()) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={styles.broadcastButton}
|
||||
onPress={() => this.props.replyBroadcast(this.parseMessage())}
|
||||
>
|
||||
<Text style={styles.broadcastButtonText}>Reply</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
item, message, editing, style, archived
|
||||
|
@ -329,6 +354,7 @@ export default class Message extends React.Component {
|
|||
{this.renderAttachment()}
|
||||
{this.renderUrl()}
|
||||
{this.renderReactions()}
|
||||
{this.renderBroadcastReply()}
|
||||
</View>
|
||||
</View>
|
||||
{this.state.reactionsModal &&
|
||||
|
|
|
@ -84,5 +84,18 @@ export default StyleSheet.create({
|
|||
padding: 10,
|
||||
paddingRight: 12,
|
||||
paddingLeft: 0
|
||||
},
|
||||
broadcastButton: {
|
||||
borderColor: '#1d74f5',
|
||||
borderWidth: 2,
|
||||
borderRadius: 2,
|
||||
paddingVertical: 10,
|
||||
width: 100,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginTop: 6
|
||||
},
|
||||
broadcastButtonText: {
|
||||
color: '#1d74f5'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,6 +4,9 @@ import normalizeMessage from './normalizeMessage';
|
|||
export const merge = (subscription, room) => {
|
||||
subscription.muted = [];
|
||||
if (room) {
|
||||
if (room.rid) {
|
||||
subscription.rid = room.rid;
|
||||
}
|
||||
subscription.roomUpdatedAt = room._updatedAt;
|
||||
subscription.lastMessage = normalizeMessage(room.lastMessage);
|
||||
subscription.ro = room.ro;
|
||||
|
@ -13,6 +16,7 @@ export const merge = (subscription, room) => {
|
|||
subscription.reactWhenReadOnly = room.reactWhenReadOnly;
|
||||
subscription.archived = room.archived;
|
||||
subscription.joinCodeRequired = room.joinCodeRequired;
|
||||
subscription.broadcast = room.broadcast;
|
||||
|
||||
if (room.muted && room.muted.length) {
|
||||
subscription.muted = room.muted.filter(user => user).map(user => ({ value: user }));
|
||||
|
@ -28,7 +32,8 @@ export const merge = (subscription, room) => {
|
|||
subscription.notifications = false;
|
||||
}
|
||||
|
||||
subscription.blocked = !!subscription.blocker;
|
||||
subscription.blocker = !!subscription.blocker;
|
||||
subscription.blocked = !!subscription.blocked;
|
||||
return subscription;
|
||||
};
|
||||
|
||||
|
|
|
@ -51,16 +51,24 @@ export default async function subscribeRooms(id) {
|
|||
const [type, data] = ddpMessage.fields.args;
|
||||
const [, ev] = ddpMessage.fields.eventName.split('/');
|
||||
if (/subscriptions/.test(ev)) {
|
||||
const tpm = merge(data);
|
||||
const rooms = database.objects('rooms').filtered('_id == $0', data.rid);
|
||||
const tpm = merge(data, rooms[0]);
|
||||
database.write(() => {
|
||||
database.create('subscriptions', tpm, true);
|
||||
database.delete(rooms);
|
||||
});
|
||||
}
|
||||
if (/rooms/.test(ev) && type === 'updated') {
|
||||
if (/rooms/.test(ev)) {
|
||||
if (type === 'updated') {
|
||||
const [sub] = database.objects('subscriptions').filtered('rid == $0', data._id);
|
||||
database.write(() => {
|
||||
merge(sub, data);
|
||||
});
|
||||
} else if (type === 'inserted') {
|
||||
database.write(() => {
|
||||
database.create('rooms', data, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (/message/.test(ev)) {
|
||||
const [args] = ddpMessage.fields.args;
|
||||
|
|
|
@ -49,10 +49,7 @@ const roomsSchema = {
|
|||
primaryKey: '_id',
|
||||
properties: {
|
||||
_id: 'string',
|
||||
t: 'string',
|
||||
lastMessage: 'messages',
|
||||
description: { type: 'string', optional: true },
|
||||
_updatedAt: { type: 'date', optional: true }
|
||||
broadcast: { type: 'bool', optional: true }
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -97,11 +94,13 @@ const subscriptionSchema = {
|
|||
announcement: { type: 'string', optional: true },
|
||||
topic: { type: 'string', optional: true },
|
||||
blocked: { type: 'bool', optional: true },
|
||||
blocker: { type: 'bool', optional: true },
|
||||
reactWhenReadOnly: { type: 'bool', optional: true },
|
||||
archived: { type: 'bool', optional: true },
|
||||
joinCodeRequired: { type: 'bool', optional: true },
|
||||
notifications: { type: 'bool', optional: true },
|
||||
muted: { type: 'list', objectType: 'usersMuted' }
|
||||
muted: { type: 'list', objectType: 'usersMuted' },
|
||||
broadcast: { type: 'bool', optional: true }
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -49,8 +49,10 @@ const RocketChat = {
|
|||
subscribeRooms,
|
||||
subscribeRoom,
|
||||
canOpenRoom,
|
||||
createChannel({ name, users, type }) {
|
||||
return call(type ? 'createChannel' : 'createPrivateGroup', name, users, type);
|
||||
createChannel({
|
||||
name, users, type, readOnly, broadcast
|
||||
}) {
|
||||
return call(type ? 'createPrivateGroup' : 'createChannel', name, users, readOnly, {}, { broadcast });
|
||||
},
|
||||
async createDirectMessageAndWait(username) {
|
||||
const room = await RocketChat.createDirectMessage(username);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { takeLatest, put, call } from 'redux-saga/effects';
|
||||
import { delay } from 'redux-saga';
|
||||
import { takeLatest, put, call, select } from 'redux-saga/effects';
|
||||
import { MESSAGES } from '../actions/actionsTypes';
|
||||
import {
|
||||
messagesSuccess,
|
||||
|
@ -12,9 +13,13 @@ import {
|
|||
permalinkSuccess,
|
||||
permalinkFailure,
|
||||
togglePinSuccess,
|
||||
togglePinFailure
|
||||
togglePinFailure,
|
||||
setInput
|
||||
} from '../actions/messages';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import database from '../lib/realm';
|
||||
import { goRoom } from '../containers/routes/NavigationService';
|
||||
import log from '../utils/log';
|
||||
|
||||
const deleteMessage = message => RocketChat.deleteMessage(message);
|
||||
const editMessage = message => RocketChat.editMessage(message);
|
||||
|
@ -81,6 +86,25 @@ const handleTogglePinRequest = function* handleTogglePinRequest({ message }) {
|
|||
}
|
||||
};
|
||||
|
||||
const handleReplyBroadcast = function* handleReplyBroadcast({ message }) {
|
||||
try {
|
||||
const { username } = message.u;
|
||||
const subscriptions = database.objects('subscriptions').filtered('name = $0', username);
|
||||
if (subscriptions.length) {
|
||||
goRoom({ rid: subscriptions[0].rid, name: subscriptions[0].name });
|
||||
} else {
|
||||
const room = yield RocketChat.createDirectMessage(username);
|
||||
goRoom({ rid: room.rid, name: username });
|
||||
}
|
||||
yield delay(100);
|
||||
const server = yield select(state => state.server.server);
|
||||
const msg = `[ ](${ server }/direct/${ username }?msg=${ message._id })`;
|
||||
yield put(setInput({ msg }));
|
||||
} catch (e) {
|
||||
log('handleReplyBroadcast', e);
|
||||
}
|
||||
};
|
||||
|
||||
const root = function* root() {
|
||||
yield takeLatest(MESSAGES.REQUEST, get);
|
||||
yield takeLatest(MESSAGES.DELETE_REQUEST, handleDeleteRequest);
|
||||
|
@ -88,5 +112,6 @@ const root = function* root() {
|
|||
yield takeLatest(MESSAGES.TOGGLE_STAR_REQUEST, handleToggleStarRequest);
|
||||
yield takeLatest(MESSAGES.PERMALINK_REQUEST, handlePermalinkRequest);
|
||||
yield takeLatest(MESSAGES.TOGGLE_PIN_REQUEST, handleTogglePinRequest);
|
||||
yield takeLatest(MESSAGES.REPLY_BROADCAST, handleReplyBroadcast);
|
||||
};
|
||||
export default root;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, Text, Switch, TouchableOpacity, SafeAreaView, ScrollView } from 'react-native';
|
||||
import { View, Text, Switch, SafeAreaView, ScrollView, Platform } from 'react-native';
|
||||
|
||||
import RCTextInput from '../containers/TextInput';
|
||||
import Loading from '../containers/Loading';
|
||||
|
@ -10,6 +10,7 @@ import { createChannelRequest } from '../actions/createChannel';
|
|||
import styles from './Styles';
|
||||
import KeyboardView from '../presentation/KeyboardView';
|
||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||
import Button from '../containers/Button';
|
||||
|
||||
@connect(
|
||||
state => ({
|
||||
|
@ -35,22 +36,28 @@ export default class CreateChannelView extends LoggedView {
|
|||
super('CreateChannelView', props);
|
||||
this.state = {
|
||||
channelName: '',
|
||||
type: true
|
||||
type: true,
|
||||
readOnly: false,
|
||||
broadcast: false
|
||||
};
|
||||
}
|
||||
|
||||
submit() {
|
||||
submit = () => {
|
||||
if (!this.state.channelName.trim() || this.props.createChannel.isFetching) {
|
||||
return;
|
||||
}
|
||||
const { channelName, type = true } = this.state;
|
||||
const {
|
||||
channelName, type, readOnly, broadcast
|
||||
} = this.state;
|
||||
let { users } = this.props;
|
||||
|
||||
// transform users object into array of usernames
|
||||
users = users.map(user => user.name);
|
||||
|
||||
// create channel
|
||||
this.props.create({ name: channelName, users, type });
|
||||
this.props.create({
|
||||
name: channelName, users, type, readOnly, broadcast
|
||||
});
|
||||
}
|
||||
|
||||
renderChannelNameError() {
|
||||
|
@ -68,20 +75,62 @@ export default class CreateChannelView extends LoggedView {
|
|||
);
|
||||
}
|
||||
|
||||
renderTypeSwitch() {
|
||||
return (
|
||||
<View style={[styles.view_white, styles.switchContainer]}>
|
||||
renderSwitch = ({
|
||||
id, value, label, description, onValueChange, disabled = false
|
||||
}) => (
|
||||
<View style={{ marginBottom: 15 }}>
|
||||
<View style={styles.switchContainer}>
|
||||
<Switch
|
||||
style={[{ flexGrow: 0, flexShrink: 1 }]}
|
||||
value={this.state.type}
|
||||
onValueChange={type => this.setState({ type })}
|
||||
testID='create-channel-type'
|
||||
value={value}
|
||||
onValueChange={onValueChange}
|
||||
testID={`create-channel-${ id }`}
|
||||
onTintColor='#2de0a5'
|
||||
tintColor={Platform.OS === 'android' ? '#f5455c' : null}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Text style={[styles.label_white, styles.switchLabel]}>
|
||||
{this.state.type ? 'Public' : 'Private'}
|
||||
</Text>
|
||||
<Text style={styles.switchLabel}>{label}</Text>
|
||||
</View>
|
||||
<Text style={styles.switchDescription}>{description}</Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
renderType() {
|
||||
const { type } = this.state;
|
||||
return this.renderSwitch({
|
||||
id: 'type',
|
||||
value: type,
|
||||
label: type ? 'Private Channel' : 'Public Channel',
|
||||
description: type ? 'Just invited people can access this channel' : 'Everyone can access this channel',
|
||||
onValueChange: value => this.setState({ type: value })
|
||||
});
|
||||
}
|
||||
|
||||
renderReadOnly() {
|
||||
const { readOnly, broadcast } = this.state;
|
||||
return this.renderSwitch({
|
||||
id: 'readonly',
|
||||
value: readOnly,
|
||||
label: 'Read Only Channel',
|
||||
description: readOnly ? 'Only authorized users can write new messages' : 'All users in the channel can write new messages',
|
||||
onValueChange: value => this.setState({ readOnly: value }),
|
||||
disabled: broadcast
|
||||
});
|
||||
}
|
||||
|
||||
renderBroadcast() {
|
||||
const { broadcast, readOnly } = this.state;
|
||||
return this.renderSwitch({
|
||||
id: 'broadcast',
|
||||
value: broadcast,
|
||||
label: 'Broadcast Channel',
|
||||
description: 'Only authorized users can write new messages, but the other users will be able to reply',
|
||||
onValueChange: (value) => {
|
||||
this.setState({
|
||||
broadcast: value,
|
||||
readOnly: value ? true : readOnly
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -102,36 +151,18 @@ export default class CreateChannelView extends LoggedView {
|
|||
testID='create-channel-name'
|
||||
/>
|
||||
{this.renderChannelNameError()}
|
||||
{this.renderTypeSwitch()}
|
||||
<Text
|
||||
style={[
|
||||
styles.label_white,
|
||||
{
|
||||
color: '#9ea2a8',
|
||||
flexGrow: 1,
|
||||
paddingHorizontal: 0,
|
||||
marginBottom: 20
|
||||
}
|
||||
]}
|
||||
>
|
||||
{this.state.type ? (
|
||||
'Everyone can access this channel'
|
||||
) : (
|
||||
'Just invited people can access this channel'
|
||||
)}
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
onPress={() => this.submit()}
|
||||
style={[
|
||||
styles.buttonContainer_white,
|
||||
this.state.channelName.length === 0 || this.props.createChannel.isFetching
|
||||
? styles.disabledButton
|
||||
: styles.enabledButton
|
||||
]}
|
||||
{this.renderType()}
|
||||
{this.renderReadOnly()}
|
||||
{this.renderBroadcast()}
|
||||
<View style={styles.alignItemsFlexStart}>
|
||||
<Button
|
||||
title='Create'
|
||||
type='primary'
|
||||
onPress={this.submit}
|
||||
disabled={this.state.channelName.length === 0 || this.props.createChannel.isFetching}
|
||||
testID='create-channel-submit'
|
||||
>
|
||||
<Text style={styles.button_white}>CREATE</Text>
|
||||
</TouchableOpacity>
|
||||
/>
|
||||
</View>
|
||||
<Loading visible={this.props.createChannel.isFetching} />
|
||||
</SafeAreaView>
|
||||
</ScrollView>
|
||||
|
|
|
@ -71,6 +71,11 @@ export default class RoomActionsView extends LoggedView {
|
|||
|
||||
updateRoomMembers = async() => {
|
||||
const { t } = this.state.room;
|
||||
|
||||
if (!this.canViewMembers) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (t === 'c' || t === 'p') {
|
||||
let onlineMembers = [];
|
||||
let allMembers = [];
|
||||
|
@ -123,9 +128,20 @@ export default class RoomActionsView extends LoggedView {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
get canViewMembers() {
|
||||
const { rid, t, broadcast } = this.state.room;
|
||||
if (broadcast) {
|
||||
const viewBroadcastMemberListPermission = 'view-broadcast-member-list';
|
||||
const permissions = RocketChat.hasPermission([viewBroadcastMemberListPermission], rid);
|
||||
if (!permissions[viewBroadcastMemberListPermission]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (t === 'c' || t === 'p');
|
||||
}
|
||||
get sections() {
|
||||
const {
|
||||
rid, t, blocked, notifications
|
||||
rid, t, blocker, notifications
|
||||
} = this.room;
|
||||
const { onlineMembers } = this.state;
|
||||
|
||||
|
@ -219,7 +235,7 @@ export default class RoomActionsView extends LoggedView {
|
|||
data: [
|
||||
{
|
||||
icon: 'block',
|
||||
name: `${ blocked ? 'Unblock' : 'Block' } user`,
|
||||
name: `${ blocker ? 'Unblock' : 'Block' } user`,
|
||||
type: 'danger',
|
||||
event: () => this.toggleBlockUser(),
|
||||
testID: 'room-actions-block-user'
|
||||
|
@ -228,14 +244,18 @@ export default class RoomActionsView extends LoggedView {
|
|||
renderItem: this.renderItem
|
||||
});
|
||||
} else if (t === 'c' || t === 'p') {
|
||||
const actions = [{
|
||||
const actions = [];
|
||||
|
||||
if (this.canViewMembers) {
|
||||
actions.push({
|
||||
icon: 'ios-people',
|
||||
name: 'Members',
|
||||
description: (onlineMembers.length === 1 ? `${ onlineMembers.length } member` : `${ onlineMembers.length } members`),
|
||||
route: 'RoomMembers',
|
||||
params: { rid, members: onlineMembers },
|
||||
testID: 'room-actions-members'
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
if (this.canAddUser) {
|
||||
actions.push({
|
||||
|
@ -276,10 +296,10 @@ export default class RoomActionsView extends LoggedView {
|
|||
}
|
||||
|
||||
toggleBlockUser = async() => {
|
||||
const { rid, blocked } = this.state.room;
|
||||
const { rid, blocker } = this.state.room;
|
||||
const { member } = this.state;
|
||||
try {
|
||||
RocketChat.toggleBlockUser(rid, member._id, !blocked);
|
||||
RocketChat.toggleBlockUser(rid, member._id, !blocker);
|
||||
} catch (e) {
|
||||
log('toggleBlockUser', e);
|
||||
}
|
||||
|
|
|
@ -324,10 +324,10 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
rightLabelPrimary='Read Only'
|
||||
rightLabelSecondary='Only authorized users can write new messages'
|
||||
onValueChange={value => this.setState({ ro: value })}
|
||||
disabled={!this.permissions[PERMISSION_SET_READONLY]}
|
||||
disabled={!this.permissions[PERMISSION_SET_READONLY] || room.broadcast}
|
||||
testID='room-info-edit-view-ro'
|
||||
/>
|
||||
{ro &&
|
||||
{ro && !room.broadcast &&
|
||||
<SwitchContainer
|
||||
value={reactWhenReadOnly}
|
||||
leftLabelPrimary='No Reactions'
|
||||
|
@ -339,6 +339,12 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
testID='room-info-edit-view-react-when-ro'
|
||||
/>
|
||||
}
|
||||
{room.broadcast &&
|
||||
[
|
||||
<Text style={styles.broadcast}>Broadcast channel</Text>,
|
||||
<View style={styles.divider} />
|
||||
]
|
||||
}
|
||||
<TouchableOpacity
|
||||
style={[sharedStyles.buttonContainer, !this.formIsChanged() && styles.buttonContainerDisabled]}
|
||||
onPress={this.submit}
|
||||
|
|
|
@ -42,5 +42,9 @@ export default StyleSheet.create({
|
|||
borderColor: '#ddd',
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
marginVertical: 20
|
||||
},
|
||||
broadcast: {
|
||||
fontWeight: 'bold',
|
||||
textAlign: 'center'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -21,8 +21,11 @@ const PERMISSION_EDIT_ROOM = 'edit-room';
|
|||
|
||||
const camelize = str => str.replace(/^(.)/, (match, chr) => chr.toUpperCase());
|
||||
const getRoomTitle = room => (room.t === 'd' ?
|
||||
<Text testID='room-info-view-name'>{room.fname}</Text> :
|
||||
[<RoomTypeIcon type={room.t} />, <Text testID='room-info-view-name'>{room.name}</Text>]
|
||||
<Text testID='room-info-view-name' style={styles.roomTitle}>{room.fname}</Text> :
|
||||
[
|
||||
<RoomTypeIcon type={room.t} key='room-info-type' />,
|
||||
<Text testID='room-info-view-name' style={styles.roomTitle} key='room-info-name'>{room.name}</Text>
|
||||
]
|
||||
);
|
||||
@connect(state => ({
|
||||
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
||||
|
@ -184,6 +187,17 @@ export default class RoomInfoView extends LoggedView {
|
|||
</Avatar>
|
||||
)
|
||||
|
||||
renderBroadcast = () => (
|
||||
<View style={styles.item}>
|
||||
<Text style={styles.itemLabel}>Broadcast Channel</Text>
|
||||
<Text
|
||||
style={styles.itemContent}
|
||||
testID='room-info-view-broadcast'
|
||||
>Only authorized users can write new messages, but the other users will be able to reply
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
|
||||
render() {
|
||||
const { room, roomUser } = this.state;
|
||||
if (!room) {
|
||||
|
@ -193,13 +207,14 @@ export default class RoomInfoView extends LoggedView {
|
|||
<ScrollView style={styles.container}>
|
||||
<View style={styles.avatarContainer} testID='room-info-view'>
|
||||
{this.renderAvatar(room, roomUser)}
|
||||
<View style={styles.roomTitle}>{ getRoomTitle(room) }</View>
|
||||
<View style={styles.roomTitleContainer}>{ getRoomTitle(room) }</View>
|
||||
</View>
|
||||
{!this.isDirect() && this.renderItem('description', room)}
|
||||
{!this.isDirect() && this.renderItem('topic', room)}
|
||||
{!this.isDirect() && this.renderItem('announcement', room)}
|
||||
{this.isDirect() && this.renderRoles()}
|
||||
{this.isDirect() && this.renderTimezone(roomUser._id)}
|
||||
{room.broadcast && this.renderBroadcast()}
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -29,11 +29,13 @@ export default StyleSheet.create({
|
|||
avatar: {
|
||||
marginHorizontal: 10
|
||||
},
|
||||
roomTitle: {
|
||||
fontSize: 18,
|
||||
roomTitleContainer: {
|
||||
paddingTop: 20,
|
||||
flexDirection: 'row'
|
||||
},
|
||||
roomTitle: {
|
||||
fontSize: 18
|
||||
},
|
||||
roomDescription: {
|
||||
fontSize: 14,
|
||||
color: '#ccc',
|
||||
|
|
|
@ -153,6 +153,22 @@ export default class RoomView extends LoggedView {
|
|||
}
|
||||
};
|
||||
|
||||
isOwner = () => this.state.room && this.state.room.roles && Array.from(Object.keys(this.state.room.roles), i => this.state.room.roles[i].value).includes('owner');
|
||||
|
||||
isMuted = () => this.state.room && this.state.room.muted && Array.from(Object.keys(this.state.room.muted), i => this.state.room.muted[i].value).includes(this.props.user.username);
|
||||
|
||||
isReadOnly = () => this.state.room.ro && this.isMuted() && !this.isOwner();
|
||||
|
||||
isBlocked = () => {
|
||||
if (this.state.room) {
|
||||
const { t, blocked, blocker } = this.state.room;
|
||||
if (t === 'd' && (blocked || blocker)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
renderItem = (item, previousItem) => (
|
||||
<Message
|
||||
key={item._id}
|
||||
|
@ -164,6 +180,7 @@ export default class RoomView extends LoggedView {
|
|||
onReactionPress={this.onReactionPress}
|
||||
onLongPress={this.onMessageLongPress}
|
||||
archived={this.state.room.archived}
|
||||
broadcast={this.state.room.broadcast}
|
||||
previousItem={previousItem}
|
||||
/>
|
||||
);
|
||||
|
@ -179,13 +196,20 @@ export default class RoomView extends LoggedView {
|
|||
</View>
|
||||
);
|
||||
}
|
||||
if (this.state.room.ro || this.state.room.archived) {
|
||||
if (this.state.room.archived || this.isReadOnly()) {
|
||||
return (
|
||||
<View style={styles.readOnly}>
|
||||
<Text>This room is read only</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
if (this.isBlocked()) {
|
||||
return (
|
||||
<View style={styles.blockedOrBlocker}>
|
||||
<Text>This room is blocked</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
return <MessageBox onSubmit={this.sendMessage} rid={this.rid} />;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@ export default StyleSheet.create({
|
|||
readOnly: {
|
||||
padding: 10
|
||||
},
|
||||
blockedOrBlocker: {
|
||||
padding: 10
|
||||
},
|
||||
reactionPickerContainer: {
|
||||
// width: width - 20,
|
||||
// height: width - 20,
|
||||
|
|
|
@ -80,12 +80,18 @@ export default StyleSheet.create({
|
|||
flexDirection: 'row',
|
||||
justifyContent: 'flex-start',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 0
|
||||
paddingHorizontal: 0,
|
||||
paddingBottom: 5
|
||||
},
|
||||
switchLabel: {
|
||||
flexGrow: 1,
|
||||
fontSize: 16,
|
||||
color: '#2f343d',
|
||||
paddingHorizontal: 10
|
||||
},
|
||||
switchDescription: {
|
||||
fontSize: 16,
|
||||
color: '#9ea2a8'
|
||||
},
|
||||
disabledButton: {
|
||||
backgroundColor: '#e1e5e8'
|
||||
},
|
||||
|
|
|
@ -59,7 +59,9 @@ describe('Create room screen', () => {
|
|||
await expect(element(by.id('create-channel-view'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-name'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-type'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-submit'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-readonly'))).toBeVisible();
|
||||
await expect(element(by.id('create-channel-broadcast'))).toExist();
|
||||
await expect(element(by.id('create-channel-submit'))).toExist();
|
||||
});
|
||||
|
||||
it('should get invalid room', async() => {
|
||||
|
@ -69,28 +71,9 @@ describe('Create room screen', () => {
|
|||
await expect(element(by.id('create-channel-error'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should create private room', async() => {
|
||||
await element(by.id('create-channel-name')).replaceText(`private${ data.random }`);
|
||||
await element(by.id('create-channel-type')).tap();
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.id('room-view-title'))).toHaveText(`private${ data.random }`).withTimeout(60000);
|
||||
await expect(element(by.id('room-view-title'))).toHaveText(`private${ data.random }`);
|
||||
await element(by.id('header-back')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should create public room', async() => {
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('select-users-view-item-rocket.cat')).tap();
|
||||
await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('selected-users-view-submit')).tap();
|
||||
await waitFor(element(by.id('create-channel-view'))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('create-channel-name')).replaceText(`public${ data.random }`);
|
||||
await element(by.id('create-channel-type')).tap();
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
|
@ -102,6 +85,25 @@ describe('Create room screen', () => {
|
|||
await expect(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should create private room', async() => {
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('select-users-view-item-rocket.cat')).tap();
|
||||
await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('selected-users-view-submit')).tap();
|
||||
await waitFor(element(by.id('create-channel-view'))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('create-channel-name')).replaceText(`private${ data.random }`);
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.id('room-view-title'))).toHaveText(`private${ data.random }`).withTimeout(60000);
|
||||
await expect(element(by.id('room-view-title'))).toHaveText(`private${ data.random }`);
|
||||
await element(by.id('header-back')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible();
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
|
|
|
@ -176,12 +176,6 @@ describe('Room screen', () => {
|
|||
});
|
||||
|
||||
describe('Message', async() => {
|
||||
before(async() => {
|
||||
await mockMessage('reply');
|
||||
await mockMessage('edit');
|
||||
await mockMessage('quote');
|
||||
});
|
||||
|
||||
it('should show message actions', async() => {
|
||||
await element(by.text(`${ data.random }message`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
|
@ -190,27 +184,6 @@ describe('Room screen', () => {
|
|||
await waitFor(element(by.text('Cancel'))).toBeNotVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
it('should reply message', async() => {
|
||||
await element(by.text(`${ data.random }reply`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Reply')).tap();
|
||||
await element(by.id('messagebox-input')).typeText('replied');
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
// TODO: test if reply was sent
|
||||
});
|
||||
|
||||
it('should edit message', async() => {
|
||||
await element(by.text(`${ data.random }edit`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Edit')).tap();
|
||||
await element(by.id('messagebox-input')).typeText('ed');
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
await waitFor(element(by.text(`${ data.random }edited`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }edited`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should copy permalink', async() => {
|
||||
await element(by.text(`${ data.random }message`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
|
@ -232,16 +205,6 @@ describe('Room screen', () => {
|
|||
// TODO: test clipboard
|
||||
});
|
||||
|
||||
it('should quote message', async() => {
|
||||
await element(by.text(`${ data.random }quote`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Quote')).tap();
|
||||
await element(by.id('messagebox-input')).typeText(`${ data.random }quoted`);
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
// TODO: test if quote was sent
|
||||
});
|
||||
|
||||
it('should star message', async() => {
|
||||
await element(by.text(`${ data.random }message`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
|
@ -288,6 +251,40 @@ describe('Room screen', () => {
|
|||
await expect(element(by.id('message-reaction-:grinning:'))).toBeNotVisible();
|
||||
});
|
||||
|
||||
it('should reply message', async() => {
|
||||
await mockMessage('reply');
|
||||
await element(by.text(`${ data.random }reply`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Reply')).tap();
|
||||
await element(by.id('messagebox-input')).typeText('replied');
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
// TODO: test if reply was sent
|
||||
});
|
||||
|
||||
it('should edit message', async() => {
|
||||
await mockMessage('edit');
|
||||
await element(by.text(`${ data.random }edit`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Edit')).tap();
|
||||
await element(by.id('messagebox-input')).typeText('ed');
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
await waitFor(element(by.text(`${ data.random }edited`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }edited`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should quote message', async() => {
|
||||
await mockMessage('quote');
|
||||
await element(by.text(`${ data.random }quote`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.text('Messages actions'))).toBeVisible();
|
||||
await element(by.text('Quote')).tap();
|
||||
await element(by.id('messagebox-input')).typeText(`${ data.random }quoted`);
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
// TODO: test if quote was sent
|
||||
});
|
||||
|
||||
it('should pin message', async() => {
|
||||
await element(by.text(`${ data.random }edited`)).longPress();
|
||||
await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
const {
|
||||
device, expect, element, by, waitFor
|
||||
} = require('detox');
|
||||
const { takeScreenshot } = require('./helpers/screenshot');
|
||||
const { logout, navigateToLogin } = require('./helpers/app');
|
||||
const data = require('./data');
|
||||
|
||||
describe('Broadcast room', () => {
|
||||
before(async() => {
|
||||
await device.reloadReactNative();
|
||||
});
|
||||
|
||||
it('should create broadcast room', async() => {
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
await waitFor(element(by.id('select-users-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id(`select-users-view-item-${ data.alternateUser }`)).tap();
|
||||
await waitFor(element(by.id(`selected-user-${ data.alternateUser }`))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('selected-users-view-submit')).tap();
|
||||
await waitFor(element(by.id('create-channel-view'))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('create-channel-name')).replaceText(`broadcast${ data.random }`);
|
||||
await element(by.id('create-channel-broadcast')).tap();
|
||||
await element(by.id('create-channel-submit')).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.id('room-view-title'))).toHaveText(`broadcast${ data.random }`).withTimeout(60000);
|
||||
await expect(element(by.id('room-view-title'))).toHaveText(`broadcast${ data.random }`);
|
||||
await element(by.id('room-view-title')).tap();
|
||||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('room-info-view-broadcast'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('room-info-view-broadcast'))).toBeVisible();
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('header-back')).atIndex(0).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should send message', async() => {
|
||||
await element(by.id(`rooms-list-view-item-broadcast${ data.random }`)).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(5000);
|
||||
await element(by.id('messagebox-input')).tap();
|
||||
await element(by.id('messagebox-input')).typeText(`${ data.random }message`);
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
await waitFor(element(by.text(`${ data.random }message`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }message`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should login as user without write message authorization and enter room', async() => {
|
||||
await element(by.id('header-back')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await logout();
|
||||
await navigateToLogin();
|
||||
await element(by.id('login-view-email')).replaceText(data.alternateUser);
|
||||
await element(by.id('login-view-password')).replaceText(data.alternateUserPassword);
|
||||
await element(by.id('login-view-submit')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toBeVisible();
|
||||
await element(by.id(`rooms-list-view-item-broadcast${ data.random }`)).tap();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(5000);
|
||||
await expect(element(by.id('room-view-title'))).toHaveText(`broadcast${ data.random }`);
|
||||
});
|
||||
|
||||
it('should not have messagebox', async() => {
|
||||
await expect(element(by.id('messagebox'))).toBeNotVisible();
|
||||
});
|
||||
|
||||
it('should be read only', async() => {
|
||||
await expect(element(by.text('This room is read only'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have the message created earlier', async() => {
|
||||
await waitFor(element(by.text(`${ data.random }message`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }message`))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should have reply button', async() => {
|
||||
await expect(element(by.text('Reply'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('should tap on reply button and navigate to direct room', async() => {
|
||||
await element(by.text('Reply')).tap();
|
||||
await waitFor(element(by.id('room-view-title'))).toHaveText(data.user).withTimeout(60000);
|
||||
await expect(element(by.id('room-view-title'))).toHaveText(data.user);
|
||||
});
|
||||
|
||||
it('should reply broadcasted message', async() => {
|
||||
await element(by.id('messagebox-input')).tap();
|
||||
await element(by.id('messagebox-input')).typeText(`${ data.random }broadcastreply`);
|
||||
await element(by.id('messagebox-send-message')).tap();
|
||||
await waitFor(element(by.text(`${ data.random }message`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`${ data.random }message`))).toBeVisible(); // broadcasted message
|
||||
await expect(element(by.text(` ${ data.random }broadcastreply`))).toBeVisible(); // reply
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
takeScreenshot();
|
||||
});
|
||||
});
|
|
@ -1,10 +1,12 @@
|
|||
const random = require('./helpers/random');
|
||||
const value = random(20);
|
||||
const data = {
|
||||
server: 'https://unstable.rocket.chat',
|
||||
alternateServer: 'https://stable.rocket.chat',
|
||||
server: 'https://stable.rocket.chat',
|
||||
alternateServer: 'https://unstable.rocket.chat',
|
||||
user: `user${ value }`,
|
||||
password: `password${ value }`,
|
||||
alternateUser: 'detoxrn',
|
||||
alternateUserPassword: '123',
|
||||
email: `detoxrn+${ value }@rocket.chat`,
|
||||
random: value
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue