diff --git a/__tests__/__snapshots__/Storyshots.test.js.snap b/__tests__/__snapshots__/Storyshots.test.js.snap index 7757aba8..944d06ee 100644 --- a/__tests__/__snapshots__/Storyshots.test.js.snap +++ b/__tests__/__snapshots__/Storyshots.test.js.snap @@ -219,15 +219,28 @@ exports[`Storyshots Message list 1`] = ` style={ Object { "flex": 1, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], } } > + + Simple + - Simple + Long message - Long message + Grouped messages - Grouped messages + Without header - Without header + With alias - With alias + Edited - Edited + Static avatar - Static avatar + Full name - Full name + Mentions - Mentions + Emojis - Emojis + Custom Emojis - Custom Emojis + Time format - Time format + Reactions - Reactions + Multiple reactions - Multiple reactions + Intercalated users - Intercalated users + Date and Unread separators @@ -4889,17 +4707,12 @@ exports[`Storyshots Message list 1`] = ` Object { "flex": 1, "flexDirection": "column", - "paddingHorizontal": 15, - "paddingVertical": 5, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], + "paddingHorizontal": 14, + "paddingVertical": 4, "width": "100%", }, Object { - "marginBottom": 10, + "marginTop": 10, }, undefined, undefined, @@ -4923,7 +4736,7 @@ exports[`Storyshots Message list 1`] = ` "width": 36, }, Object { - "marginTop": 5, + "marginTop": 4, }, ] } @@ -5063,14 +4876,9 @@ exports[`Storyshots Message list 1`] = ` Object { "alignItems": "center", "flexDirection": "row", - "marginBottom": 25, - "marginHorizontal": 15, - "marginTop": 15, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], + "marginBottom": 4, + "marginHorizontal": 14, + "marginTop": 16, } } > @@ -5128,13 +4936,8 @@ exports[`Storyshots Message list 1`] = ` Object { "flex": 1, "flexDirection": "column", - "paddingHorizontal": 15, - "paddingVertical": 5, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], + "paddingHorizontal": 14, + "paddingVertical": 4, "width": "100%", }, false, @@ -5219,17 +5022,12 @@ exports[`Storyshots Message list 1`] = ` Object { "flex": 1, "flexDirection": "column", - "paddingHorizontal": 15, - "paddingVertical": 5, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], + "paddingHorizontal": 14, + "paddingVertical": 4, "width": "100%", }, Object { - "marginBottom": 10, + "marginTop": 10, }, undefined, undefined, @@ -5253,7 +5051,7 @@ exports[`Storyshots Message list 1`] = ` "width": 36, }, Object { - "marginTop": 5, + "marginTop": 4, }, ] } @@ -5393,14 +5191,9 @@ exports[`Storyshots Message list 1`] = ` Object { "alignItems": "center", "flexDirection": "row", - "marginBottom": 25, - "marginHorizontal": 15, - "marginTop": 15, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], + "marginBottom": 4, + "marginHorizontal": 14, + "marginTop": 16, } } > @@ -5450,17 +5243,12 @@ exports[`Storyshots Message list 1`] = ` Object { "flex": 1, "flexDirection": "column", - "paddingHorizontal": 15, - "paddingVertical": 5, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], + "paddingHorizontal": 14, + "paddingVertical": 4, "width": "100%", }, Object { - "marginBottom": 10, + "marginTop": 10, }, undefined, undefined, @@ -5484,7 +5272,7 @@ exports[`Storyshots Message list 1`] = ` "width": 36, }, Object { - "marginTop": 5, + "marginTop": 4, }, ] } @@ -5629,18 +5417,13 @@ exports[`Storyshots Message list 1`] = ` "marginTop": 30, }, Object { - "marginBottom": 30, - "marginTop": 0, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], + "marginBottom": 0, + "marginTop": 30, }, ] } > - Date and Unread separators + With image - With image + With video - With video + With audio - With audio - - - - - - - - - - - - - - diego.mello - - - - 10:00 AM - - - - - - - Iā€™m fine! - - - - - View - - - - - - - - - - - - - - - - - diego.mello - - - - 10:00 AM - - - - - - - Iā€™m fine! - - - - - View - - - - - @@ -7678,17 +7023,12 @@ exports[`Storyshots Message list 1`] = ` Object { "flex": 1, "flexDirection": "column", - "paddingHorizontal": 15, - "paddingVertical": 5, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], + "paddingHorizontal": 14, + "paddingVertical": 4, "width": "100%", }, Object { - "marginBottom": 10, + "marginTop": 10, }, undefined, undefined, @@ -7712,7 +7052,7 @@ exports[`Storyshots Message list 1`] = ` "width": 36, }, Object { - "marginTop": 5, + "marginTop": 4, }, ] } @@ -7813,7 +7153,221 @@ exports[`Storyshots Message list 1`] = ` 10:00 AM + + + + + Iā€™m fine! + + + + View + + + + + + + + + + + + + + + + + diego.mello + + + + 10:00 AM + + + + + + + Iā€™m fine! + + + + View @@ -7829,13 +7383,8 @@ exports[`Storyshots Message list 1`] = ` "marginTop": 30, }, Object { - "marginBottom": 30, - "marginTop": 0, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], + "marginBottom": 0, + "marginTop": 30, }, ] } @@ -7862,17 +7411,12 @@ exports[`Storyshots Message list 1`] = ` Object { "flex": 1, "flexDirection": "column", - "paddingHorizontal": 15, - "paddingVertical": 5, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], + "paddingHorizontal": 14, + "paddingVertical": 4, "width": "100%", }, Object { - "marginBottom": 10, + "marginTop": 10, }, undefined, undefined, @@ -7896,7 +7440,7 @@ exports[`Storyshots Message list 1`] = ` "width": 36, }, Object { - "marginTop": 5, + "marginTop": 4, }, ] } @@ -7997,36 +7541,7 @@ exports[`Storyshots Message list 1`] = ` 10:00 AM - - - - - Message - - - - + View View @@ -8042,13 +7557,8 @@ exports[`Storyshots Message list 1`] = ` "marginTop": 30, }, Object { - "marginBottom": 30, - "marginTop": 0, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], + "marginBottom": 0, + "marginTop": 30, }, ] } @@ -8075,17 +7585,12 @@ exports[`Storyshots Message list 1`] = ` Object { "flex": 1, "flexDirection": "column", - "paddingHorizontal": 15, - "paddingVertical": 5, - "transform": Array [ - Object { - "scaleY": -1, - }, - ], + "paddingHorizontal": 14, + "paddingVertical": 4, "width": "100%", }, Object { - "marginBottom": 10, + "marginTop": 10, }, undefined, undefined, @@ -8109,7 +7614,210 @@ exports[`Storyshots Message list 1`] = ` "width": 36, }, Object { - "marginTop": 5, + "marginTop": 4, + }, + ] + } + > + + + + + + + + + diego.mello + + + + 10:00 AM + + + + + + + Message + + + + + View + + + + + + Two short custom fields + + + + + - Two short custom fields + Broadcast - Broadcast + Archived - Archived + Error - Error + Temp - Temp + Editing - Editing + Removed - Removed + Joined - Joined + Room name changed - Room name changed + Message pinned - Message pinned + Has left the channel - Has left the channel + User removed - User removed + User added - User added + User muted - User muted + User unmuted - User unmuted + Role added - Role added + Role removed - Role removed + Changed description - Changed description + Changed announcement - Changed announcement + Changed topic - Changed topic + Changed type - Changed type + Custom style - Custom style + Markdown emphasis - Markdown emphasis + Markdown headers - Markdown headers + Markdown links - Markdown links + Markdown image - Markdown image + Markdown code - Markdown code + Markdown quote - Markdown quote + Markdown table - - Markdown table - `; diff --git a/android/app/src/main/res/drawable-xxxhdpi/message_empty.png b/android/app/src/main/res/drawable-xxxhdpi/message_empty.png new file mode 100644 index 00000000..d07e5dcf Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/message_empty.png differ diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js index a3a49334..8eccf4f2 100644 --- a/app/actions/actionsTypes.js +++ b/app/actions/actionsTypes.js @@ -35,8 +35,7 @@ export const ROOM = createRequestTypes('ROOM', [ 'LEAVE', 'ERASE', 'USER_TYPING', - 'MESSAGE_RECEIVED', - 'SET_LAST_OPEN' + 'MESSAGE_RECEIVED' ]); export const APP = createRequestTypes('APP', ['START', 'READY', 'INIT']); export const MESSAGES = createRequestTypes('MESSAGES', [ diff --git a/app/actions/room.js b/app/actions/room.js index ab8b1b1e..00fcb4c7 100644 --- a/app/actions/room.js +++ b/app/actions/room.js @@ -64,10 +64,3 @@ export function roomMessageReceived(message) { message }; } - -export function setLastOpen(date = new Date()) { - return { - type: types.ROOM.SET_LAST_OPEN, - date - }; -} diff --git a/app/constants/colors.js b/app/constants/colors.js index 658bf9f4..e666dee5 100644 --- a/app/constants/colors.js +++ b/app/constants/colors.js @@ -3,7 +3,7 @@ import { isIOS } from '../utils/deviceInfo'; export const COLOR_DANGER = '#f5455c'; export const COLOR_BUTTON_PRIMARY = '#1d74f5'; export const COLOR_TEXT = '#292E35'; -export const COLOR_SEPARATOR = '#CBCED1'; +export const COLOR_SEPARATOR = '#A7A7AA'; export const STATUS_COLORS = { online: '#2de0a5', busy: COLOR_DANGER, @@ -11,6 +11,6 @@ export const STATUS_COLORS = { offline: '#cbced1' }; -export const HEADER_BACKGROUND = isIOS ? '#FFF' : '#2F343D'; +export const HEADER_BACKGROUND = isIOS ? '#f8f8f8' : '#2F343D'; export const HEADER_TITLE = isIOS ? '#0C0D0F' : '#FFF'; export const HEADER_BACK = isIOS ? '#1d74f5' : '#FFF'; diff --git a/app/containers/message/Message.js b/app/containers/message/Message.js index 940def60..6ec7efff 100644 --- a/app/containers/message/Message.js +++ b/app/containers/message/Message.js @@ -365,7 +365,7 @@ export default class Message extends PureComponent { onPress={this.onPress} > diff --git a/app/containers/message/index.js b/app/containers/message/index.js index 4da77d2a..25f283e1 100644 --- a/app/containers/message/index.js +++ b/app/containers/message/index.js @@ -101,7 +101,6 @@ export default class MessageContainer extends React.Component { return _updatedAt.toGMTString() !== nextProps._updatedAt.toGMTString(); } - onLongPress = () => { const { onLongPress } = this.props; onLongPress(this.parseMessage()); diff --git a/app/containers/message/styles.js b/app/containers/message/styles.js index a3ae5f7b..64e50679 100644 --- a/app/containers/message/styles.js +++ b/app/containers/message/styles.js @@ -5,11 +5,10 @@ export default StyleSheet.create({ flexDirection: 'row' }, container: { - paddingVertical: 5, + paddingVertical: 4, width: '100%', - paddingHorizontal: 15, + paddingHorizontal: 14, flexDirection: 'column', - transform: [{ scaleY: -1 }], flex: 1 }, messageContent: { @@ -39,8 +38,8 @@ export default StyleSheet.create({ height: 20 }, temp: { opacity: 0.3 }, - marginBottom: { - marginBottom: 10 + marginTop: { + marginTop: 10 }, reactionsContainer: { flexDirection: 'row', @@ -82,7 +81,7 @@ export default StyleSheet.create({ marginLeft: 7 }, avatar: { - marginTop: 5 + marginTop: 4 }, addReaction: { color: '#1D74F5' diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 4bf67f4c..27fdf262 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -1,4 +1,4 @@ -import { AsyncStorage } from 'react-native'; +import { AsyncStorage, InteractionManager } from 'react-native'; import foreach from 'lodash/forEach'; import semver from 'semver'; import { Rocketchat as RocketchatClient } from '@rocket.chat/sdk'; @@ -118,17 +118,17 @@ const RocketChat = { reduxStore.dispatch(setUser({ status: 'offline' })); } - if (this._setUserTimer) { - clearTimeout(this._setUserTimer); - this._setUserTimer = null; + if (!this._setUserTimer) { + this._setUserTimer = setTimeout(() => { + const batchUsers = this.activeUsers; + InteractionManager.runAfterInteractions(() => { + reduxStore.dispatch(setActiveUser(batchUsers)); + }); + this._setUserTimer = null; + return this.activeUsers = {}; + }, 10000); } - this._setUserTimer = setTimeout(() => { - reduxStore.dispatch(setActiveUser(this.activeUsers)); - this._setUserTimer = null; - return this.activeUsers = {}; - }, 2000); - const activeUser = reduxStore.getState().activeUsers[ddpMessage.id]; if (!ddpMessage.fields) { this.activeUsers[ddpMessage.id] = {}; @@ -145,11 +145,18 @@ const RocketChat = { } this.roomsSub = await this.subscribeRooms(); - this.sdk.subscribe('activeUsers'); this.sdk.subscribe('roles'); this.getPermissions(); this.getCustomEmoji(); this.registerPushToken().catch(e => console.log(e)); + + if (this.activeUsersSubTimeout) { + clearTimeout(this.activeUsersSubTimeout); + this.activeUsersSubTimeout = false; + } + this.activeUsersSubTimeout = setTimeout(() => { + this.sdk.subscribe('activeUsers'); + }, 5000); }, connect({ server, user }) { database.setActiveDB(server); @@ -330,6 +337,11 @@ const RocketChat = { this.roomsSub.stop(); } + if (this.activeUsersSubTimeout) { + clearTimeout(this.activeUsersSubTimeout); + this.activeUsersSubTimeout = false; + } + try { await this.removePushToken(); } catch (error) { diff --git a/app/presentation/RoomItem.js b/app/presentation/RoomItem.js index 8b5cdab9..47173286 100644 --- a/app/presentation/RoomItem.js +++ b/app/presentation/RoomItem.js @@ -214,7 +214,7 @@ export default class RoomItem extends React.Component { formatDate = date => moment(date).calendar(null, { lastDay: `[${ I18n.t('Yesterday') }]`, - sameDay: 'h:mm A', + sameDay: 'HH:mm', lastWeek: 'dddd', sameElse: 'MMM D' }) diff --git a/app/reducers/room.js b/app/reducers/room.js index 03b1fa89..5d20b148 100644 --- a/app/reducers/room.js +++ b/app/reducers/room.js @@ -9,18 +9,12 @@ export default function room(state = initialState, action) { case types.ROOM.OPEN: return { ...initialState, - ...action.room, - lastOpen: new Date() + ...action.room }; case types.ROOM.CLOSE: return { ...initialState }; - case types.ROOM.SET_LAST_OPEN: - return { - ...state, - lastOpen: action.date - }; case types.ROOM.ADD_USER_TYPING: return { ...state, diff --git a/app/views/LegalView.js b/app/views/LegalView.js index 313e90cb..28ae450e 100644 --- a/app/views/LegalView.js +++ b/app/views/LegalView.js @@ -13,6 +13,7 @@ import I18n from '../i18n'; import DisclosureIndicator from '../containers/DisclosureIndicator'; import { CloseModalButton } from '../containers/HeaderButton'; import StatusBar from '../containers/StatusBar'; +import { COLOR_SEPARATOR } from '../constants/colors'; const styles = StyleSheet.create({ container: { @@ -22,12 +23,12 @@ const styles = StyleSheet.create({ scroll: { marginTop: 35, backgroundColor: '#fff', - borderColor: '#cbced1', + borderColor: COLOR_SEPARATOR, borderTopWidth: StyleSheet.hairlineWidth, borderBottomWidth: StyleSheet.hairlineWidth }, separator: { - backgroundColor: '#cbced1', + backgroundColor: COLOR_SEPARATOR, height: StyleSheet.hairlineWidth, width: '100%', marginLeft: 20 diff --git a/app/views/LoginSignupView.js b/app/views/LoginSignupView.js index 5b6a3615..b40bda72 100644 --- a/app/views/LoginSignupView.js +++ b/app/views/LoginSignupView.js @@ -17,6 +17,7 @@ import Button from '../containers/Button'; import I18n from '../i18n'; import { LegalButton } from '../containers/HeaderButton'; import StatusBar from '../containers/StatusBar'; +import { COLOR_SEPARATOR } from '../constants/colors'; const styles = StyleSheet.create({ container: { @@ -72,7 +73,7 @@ const styles = StyleSheet.create({ separatorLine: { flex: 1, height: 1, - backgroundColor: '#e1e5e8' + backgroundColor: COLOR_SEPARATOR }, separatorLineLeft: { marginRight: 15 diff --git a/app/views/LoginView.js b/app/views/LoginView.js index beb2051e..134eb99e 100644 --- a/app/views/LoginView.js +++ b/app/views/LoginView.js @@ -96,7 +96,7 @@ export default class LoginView extends LoggedView { componentWillReceiveProps(nextProps) { const { Site_Name, error } = this.props; - if (Site_Name && nextProps.Site_Name !== Site_Name) { + if (nextProps.Site_Name && nextProps.Site_Name !== Site_Name) { this.setTitle(nextProps.Site_Name); } else if (nextProps.failure && !equal(error, nextProps.error)) { if (nextProps.error && nextProps.error.error === 'totp-required') { diff --git a/app/views/RoomActionsView/styles.js b/app/views/RoomActionsView/styles.js index eb6c54ad..6a0d93b1 100644 --- a/app/views/RoomActionsView/styles.js +++ b/app/views/RoomActionsView/styles.js @@ -1,4 +1,5 @@ import { StyleSheet } from 'react-native'; +import { COLOR_SEPARATOR } from '../../constants/colors'; export default StyleSheet.create({ container: { @@ -26,7 +27,7 @@ export default StyleSheet.create({ }, separator: { height: StyleSheet.hairlineWidth, - backgroundColor: '#ddd' + backgroundColor: COLOR_SEPARATOR }, sectionSeparator: { height: 10, diff --git a/app/views/RoomInfoEditView/styles.js b/app/views/RoomInfoEditView/styles.js index 3c61eece..c3b86da4 100644 --- a/app/views/RoomInfoEditView/styles.js +++ b/app/views/RoomInfoEditView/styles.js @@ -1,6 +1,6 @@ import { StyleSheet } from 'react-native'; -import { COLOR_DANGER } from '../../constants/colors'; +import { COLOR_DANGER, COLOR_SEPARATOR } from '../../constants/colors'; export default StyleSheet.create({ buttonInverted: { @@ -39,7 +39,7 @@ export default StyleSheet.create({ }, divider: { height: StyleSheet.hairlineWidth, - borderColor: '#ddd', + borderColor: COLOR_SEPARATOR, borderBottomWidth: StyleSheet.hairlineWidth, marginVertical: 20 }, diff --git a/app/views/RoomMembersView/styles.js b/app/views/RoomMembersView/styles.js index 444bbfa0..0ca648e5 100644 --- a/app/views/RoomMembersView/styles.js +++ b/app/views/RoomMembersView/styles.js @@ -1,4 +1,5 @@ import { StyleSheet } from 'react-native'; +import { COLOR_SEPARATOR } from '../../constants/colors'; export default StyleSheet.create({ list: { @@ -24,7 +25,7 @@ export default StyleSheet.create({ }, separator: { height: StyleSheet.hairlineWidth, - backgroundColor: '#E1E5E8', + backgroundColor: COLOR_SEPARATOR, marginLeft: 60 }, username: { diff --git a/app/views/RoomView/EmptyRoom.js b/app/views/RoomView/EmptyRoom.js new file mode 100644 index 00000000..9f65079d --- /dev/null +++ b/app/views/RoomView/EmptyRoom.js @@ -0,0 +1,23 @@ +import React from 'react'; +import { ImageBackground, StyleSheet } from 'react-native'; +import PropTypes from 'prop-types'; + +const styles = StyleSheet.create({ + image: { + width: '100%', + height: '100%', + position: 'absolute' + } +}); + +const EmptyRoom = React.memo(({ length }) => { + if (length === 0) { + return ; + } + return null; +}); + +EmptyRoom.propTypes = { + length: PropTypes.number.isRequired +}; +export default EmptyRoom; diff --git a/app/views/RoomView/Header/Icon.js b/app/views/RoomView/Header/Icon.js new file mode 100644 index 00000000..5c068285 --- /dev/null +++ b/app/views/RoomView/Header/Icon.js @@ -0,0 +1,50 @@ +import React from 'react'; +import { StyleSheet } from 'react-native'; +import PropTypes from 'prop-types'; + +import { STATUS_COLORS } from '../../../constants/colors'; +import { CustomIcon } from '../../../lib/Icons'; +import Status from '../../../containers/Status/Status'; +import { isIOS } from '../../../utils/deviceInfo'; + +const ICON_SIZE = 18; + +const styles = StyleSheet.create({ + type: { + width: ICON_SIZE, + height: ICON_SIZE, + marginRight: 8, + color: isIOS ? '#9EA2A8' : '#fff' + }, + status: { + marginRight: 8 + } +}); + +const Icon = React.memo(({ type, status }) => { + if (type === 'd') { + return ; + } + + const icon = type === 'c' ? 'hashtag' : 'lock'; + return ( + + ); +}); + +Icon.propTypes = { + type: PropTypes.string, + status: PropTypes.string +}; +export default Icon; diff --git a/app/views/RoomView/Header/index.js b/app/views/RoomView/Header/index.js index c6a3f158..abb934fa 100644 --- a/app/views/RoomView/Header/index.js +++ b/app/views/RoomView/Header/index.js @@ -1,52 +1,45 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { - View, Text, StyleSheet, LayoutAnimation, ScrollView + View, Text, StyleSheet, ScrollView } from 'react-native'; import { connect } from 'react-redux'; import { responsive } from 'react-native-responsive-ui'; import equal from 'deep-equal'; import I18n from '../../../i18n'; -import { STATUS_COLORS } from '../../../constants/colors'; import sharedStyles from '../../Styles'; import { isIOS } from '../../../utils/deviceInfo'; -import { CustomIcon } from '../../../lib/Icons'; -import Status from '../../../containers/Status/Status'; import { headerIconSize } from '../../../containers/HeaderButton'; +import Icon from './Icon'; const TITLE_SIZE = 18; -const ICON_SIZE = 18; const styles = StyleSheet.create({ container: { - flex: 1 + flex: 1, + height: '100%' }, titleContainer: { - flexDirection: 'row', - alignItems: 'center' + flex: 1, + flexDirection: 'row' }, title: { ...sharedStyles.textSemibold, color: isIOS ? '#0C0D0F' : '#fff', fontSize: TITLE_SIZE }, - type: { - width: ICON_SIZE, - height: ICON_SIZE, - marginRight: 8, - color: isIOS ? '#9EA2A8' : '#fff' + scroll: { + alignItems: 'center' }, typing: { ...sharedStyles.textRegular, color: isIOS ? '#9EA2A8' : '#fff', - fontSize: 12 + fontSize: 12, + marginBottom: 2 }, typingUsers: { ...sharedStyles.textSemibold, fontWeight: '600' - }, - status: { - marginRight: 8 } }); @@ -119,14 +112,14 @@ export default class RoomHeaderView extends Component { return false; } - componentDidUpdate(prevProps) { - if (isIOS) { - const { usersTyping } = this.props; - if (!equal(prevProps.usersTyping, usersTyping)) { - LayoutAnimation.easeInEaseOut(); - } - } - } + // componentDidUpdate(prevProps) { + // if (isIOS) { + // const { usersTyping } = this.props; + // if (!equal(prevProps.usersTyping, usersTyping)) { + // LayoutAnimation.easeInEaseOut(); + // } + // } + // } get typing() { const { usersTyping } = this.props; @@ -146,32 +139,9 @@ export default class RoomHeaderView extends Component { ); } - renderIcon = () => { - const { type, status } = this.props; - if (type === 'd') { - return ; - } - - const icon = type === 'c' ? 'hashtag' : 'lock'; - return ( - - ); - } - render() { const { - window, title, usersTyping + window, title, usersTyping, type, status } = this.props; const portrait = window.height > window.width; const widthScrollView = window.width - 6.5 * headerIconSize; @@ -190,8 +160,9 @@ export default class RoomHeaderView extends Component { showsHorizontalScrollIndicator={false} horizontal bounces={false} + contentContainerStyle={styles.scroll} > - {this.renderIcon()} + {title} diff --git a/app/views/RoomView/List.js b/app/views/RoomView/List.js new file mode 100644 index 00000000..4f5be429 --- /dev/null +++ b/app/views/RoomView/List.js @@ -0,0 +1,138 @@ +import React from 'react'; +import { ActivityIndicator, FlatList } from 'react-native'; +import PropTypes from 'prop-types'; +import { responsive } from 'react-native-responsive-ui'; + +import styles from './styles'; +import database from '../../lib/realm'; +import scrollPersistTaps from '../../utils/scrollPersistTaps'; +import debounce from '../../utils/debounce'; +import RocketChat from '../../lib/rocketchat'; +import log from '../../utils/log'; +import EmptyRoom from './EmptyRoom'; +import ScrollBottomButton from './ScrollBottomButton'; + +@responsive +export class List extends React.Component { + static propTypes = { + onEndReached: PropTypes.func, + renderFooter: PropTypes.func, + renderRow: PropTypes.func, + room: PropTypes.object, + window: PropTypes.object + }; + + constructor(props) { + super(props); + this.data = database + .objects('messages') + .filtered('rid = $0', props.room.rid) + .sorted('ts', true); + this.state = { + loading: true, + loadingMore: false, + end: false, + messages: this.data.slice(), + showScollToBottomButton: false + }; + this.data.addListener(this.updateState); + } + + // shouldComponentUpdate(nextProps, nextState) { + // const { + // loadingMore, loading, end, showScollToBottomButton, messages + // } = this.state; + // const { window } = this.props; + // return end !== nextState.end + // || loadingMore !== nextState.loadingMore + // || loading !== nextState.loading + // || showScollToBottomButton !== nextState.showScollToBottomButton + // // || messages.length !== nextState.messages.length + // || !equal(messages, nextState.messages) + // || window.width !== nextProps.window.width; + // } + + componentWillUnmount() { + this.data.removeAllListeners(); + this.updateState.stop(); + } + + // eslint-disable-next-line react/sort-comp + updateState = debounce(() => { + this.setState({ messages: this.data.slice(), loading: false, loadingMore: false }); + }, 300); + + onEndReached = async() => { + const { + loadingMore, loading, end, messages + } = this.state; + if (loadingMore || loading || end || messages.length < 50) { + return; + } + + this.setState({ loadingMore: true }); + const { room } = this.props; + try { + const result = await RocketChat.loadMessagesForRoom({ rid: room.rid, t: room.t, latest: this.data[this.data.length - 1].ts }); + this.setState({ end: result.length < 50 }); + } catch (e) { + this.setState({ loadingMore: false }); + log('ListView.onEndReached', e); + } + } + + scrollToBottom = () => { + requestAnimationFrame(() => { + this.list.scrollToOffset({ offset: -100 }); + }); + } + + handleScroll = (event) => { + if (event.nativeEvent.contentOffset.y > 0) { + this.setState({ showScollToBottomButton: true }); + } else { + this.setState({ showScollToBottomButton: false }); + } + } + + renderFooter = () => { + const { loadingMore, loading } = this.state; + if (loadingMore || loading) { + return ; + } + return null; + } + + render() { + const { renderRow, window } = this.props; + const { showScollToBottomButton, messages } = this.state; + return ( + + + this.list = ref} + keyExtractor={item => item._id} + data={messages} + extraData={this.state} + renderItem={({ item, index }) => renderRow(item, messages[index + 1])} + style={styles.list} + onScroll={this.handleScroll} + inverted + removeClippedSubviews + initialNumToRender={10} + onEndReached={this.onEndReached} + onEndReachedThreshold={0.5} + maxToRenderPerBatch={20} + ListFooterComponent={this.renderFooter} + {...scrollPersistTaps} + /> + window.height} + /> + + ); + } +} diff --git a/app/views/RoomView/ListView.js b/app/views/RoomView/ListView.js deleted file mode 100644 index 962cc07f..00000000 --- a/app/views/RoomView/ListView.js +++ /dev/null @@ -1,277 +0,0 @@ -import { ListView as OldList } from 'realm/react-native'; -import React from 'react'; -import { - TouchableOpacity, ScrollView, ListView as OldList2, ImageBackground, ActivityIndicator -} from 'react-native'; -import moment from 'moment'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; - -import Separator from './Separator'; -import styles from './styles'; -import database from '../../lib/realm'; -import scrollPersistTaps from '../../utils/scrollPersistTaps'; -import debounce from '../../utils/debounce'; -import RocketChat from '../../lib/rocketchat'; -import log from '../../utils/log'; -import { CustomIcon } from '../../lib/Icons'; -import { isIOS, isNotch } from '../../utils/deviceInfo'; - -const DEFAULT_SCROLL_CALLBACK_THROTTLE = 100; - -export class DataSource extends OldList.DataSource { - getRowData(sectionIndex: number, rowIndex: number): any { - const sectionID = this.sectionIdentities[sectionIndex]; - const rowID = this.rowIdentities[sectionIndex][rowIndex]; - return this._getRowData(this._dataBlob, sectionID, rowID); - } - _calculateDirtyArrays() { // eslint-disable-line - return false; - } -} - -const ds = new DataSource({ rowHasChanged: (r1, r2) => r1._id !== r2._id }); - -export class List extends React.Component { - static propTypes = { - onEndReached: PropTypes.func, - renderFooter: PropTypes.func, - renderRow: PropTypes.func, - room: PropTypes.object - }; - - constructor(props) { - super(props); - this.data = database - .objects('messages') - .filtered('rid = $0', props.room.rid) - .sorted('ts', true); - this.state = { - loading: true, - loadingMore: false, - end: false, - showScollToBottomButton: false - }; - this.dataSource = ds.cloneWithRows(this.data); - } - - componentDidMount() { - this.updateState(); - this.data.addListener(this.updateState); - } - - shouldComponentUpdate(nextProps, nextState) { - const { loadingMore, loading, end, showScollToBottomButton } = this.state; - return end !== nextState.end || loadingMore !== nextState.loadingMore || loading !== nextState.loading || showScollToBottomButton !== nextState.showScollToBottomButton; - } - - componentWillUnmount() { - this.data.removeAllListeners(); - this.updateState.stop(); - } - - // eslint-disable-next-line react/sort-comp - updateState = debounce(() => { - this.setState({ loading: true }); - this.dataSource = this.dataSource.cloneWithRows(this.data); - this.setState({ loading: false }); - }, 300); - - onEndReached = async() => { - const { loadingMore, end } = this.state; - if (loadingMore || end || this.data.length < 50) { - return; - } - - this.setState({ loadingMore: true }); - const { room } = this.props; - try { - const result = await RocketChat.loadMessagesForRoom({ rid: room.rid, t: room.t, latest: this.data[this.data.length - 1].ts }); - this.setState({ end: result.length < 50, loadingMore: false }); - } catch (e) { - this.setState({ loadingMore: false }); - log('ListView.onEndReached', e); - } - } - - scrollToBottom = () => { - this.listView.scrollTo({ x: 0, y: 0, animated: true }); - } - - handleScroll= (event) => { - if (event.nativeEvent.contentOffset.y > 0) { - this.setState({ showScollToBottomButton: true }); - } else { - this.setState({ showScollToBottomButton: false }); - } - } - - renderFooter = () => { - const { loadingMore, loading } = this.state; - if (loadingMore || loading) { - return ; - } - return null; - } - - getScrollButtonStyle = () => { - let right = 30; - if (isIOS) { - right = isNotch ? 45 : 30; - } - return ({ - position: 'absolute', - width: 42, - height: 42, - alignItems: 'center', - justifyContent: 'center', - right, - bottom: 70, - backgroundColor: '#EAF2FE', - borderRadius: 20 - }) - } - - render() { - const { renderRow } = this.props; - const { showScollToBottomButton } = this.state; - const scrollButtonStyle = this.getScrollButtonStyle(); - return ( - - this.listView = ref} - style={styles.list} - data={this.data} - keyExtractor={item => item._id} - onEndReachedThreshold={100} - renderFooter={this.renderFooter} - onEndReached={this.onEndReached} - dataSource={this.dataSource} - renderRow={(item, previousItem) => renderRow(item, previousItem)} - initialListSize={1} - pageSize={20} - onScroll={this.handleScroll} - testID='room-view-messages' - {...scrollPersistTaps} - /> - {showScollToBottomButton ? ( - - - - ) : null} - - ); - } -} - -@connect(state => ({ - lastOpen: state.room.lastOpen -}), null, null, { forwardRef: true }) -export class ListView extends OldList2 { - constructor(props) { - super(props); - this.state = { - curRenderedRowsCount: 10 - // highlightedRow: ({}: Object) - }; - } - - getInnerViewNode() { - return this.refs.listView.getInnerViewNode(); - } - - scrollTo(...args) { - this.refs.listView.scrollTo(...args); - } - - setNativeProps(props) { - this.refs.listView.setNativeProps(props); - } - - static DataSource = DataSource; - - render() { - const bodyComponents = []; - - // const stickySectionHeaderIndices = []; - - // const { renderSectionHeader } = this.props; - - const header = this.props.renderHeader ? this.props.renderHeader() : null; - const footer = this.props.renderFooter ? this.props.renderFooter() : null; - // let totalIndex = header ? 1 : 0; - - const { data } = this.props; - let count = 0; - - for (let i = 0; i < this.state.curRenderedRowsCount && i < data.length; i += 1, count += 1) { - const message = data[i]; - const previousMessage = data[i + 1]; - bodyComponents.push(this.props.renderRow(message, previousMessage)); - - - if (!previousMessage) { - bodyComponents.push(); - continue; // eslint-disable-line - } - - const showUnreadSeparator = this.props.lastOpen - && moment(message.ts).isAfter(this.props.lastOpen) - && moment(previousMessage.ts).isBefore(this.props.lastOpen); - const showDateSeparator = !moment(message.ts).isSame(previousMessage.ts, 'day'); - - if (showUnreadSeparator || showDateSeparator) { - bodyComponents.push(); - } - } - - const { ...props } = this.props; - if (!props.scrollEventThrottle) { - props.scrollEventThrottle = DEFAULT_SCROLL_CALLBACK_THROTTLE; - } - if (props.removeClippedSubviews === undefined) { - props.removeClippedSubviews = true; - } - /* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This comment - * suppresses an error found when Flow v0.54 was deployed. To see the error - * delete this comment and run Flow. */ - Object.assign(props, { - onScroll: this._onScroll, - /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This - * comment suppresses an error when upgrading Flow's support for React. - * To see the error delete this comment and run Flow. */ - // stickyHeaderIndices: this.props.stickyHeaderIndices.concat(stickySectionHeaderIndices,), - - // Do not pass these events downstream to ScrollView since they will be - // registered in ListView's own ScrollResponder.Mixin - onKeyboardWillShow: undefined, - onKeyboardWillHide: undefined, - onKeyboardDidShow: undefined, - onKeyboardDidHide: undefined - }); - - const image = data.length === 0 ? { uri: 'message_empty' } : null; - return ( - [ - , - - {header} - {bodyComponents} - {footer} - - ] - ); - } -} -ListView.DataSource = DataSource; diff --git a/app/views/RoomView/ScrollBottomButton.js b/app/views/RoomView/ScrollBottomButton.js new file mode 100644 index 00000000..ad9429d0 --- /dev/null +++ b/app/views/RoomView/ScrollBottomButton.js @@ -0,0 +1,60 @@ +import React from 'react'; +import { TouchableOpacity, StyleSheet } from 'react-native'; +import PropTypes from 'prop-types'; + +import { isNotch } from '../../utils/deviceInfo'; +import { CustomIcon } from '../../lib/Icons'; +import { COLOR_BUTTON_PRIMARY } from '../../constants/colors'; + +const styles = StyleSheet.create({ + button: { + position: 'absolute', + width: 42, + height: 42, + alignItems: 'center', + justifyContent: 'center', + backgroundColor: '#EAF2FE', + borderRadius: 21, + shadowColor: '#000', + shadowOffset: { + width: 0, + height: 1 + }, + shadowOpacity: 0.20, + shadowRadius: 1.41, + elevation: 2 + } +}); + +let right; +let bottom = 80; +if (isNotch) { + bottom = 120; +} + +const ScrollBottomButton = React.memo(({ show, onPress, landscape }) => { + if (show) { + if (landscape) { + right = 45; + } else { + right = 30; + } + return ( + + + + ); + } + return null; +}); + +ScrollBottomButton.propTypes = { + show: PropTypes.bool.isRequired, + onPress: PropTypes.func.isRequired, + landscape: PropTypes.bool +}; +export default ScrollBottomButton; diff --git a/app/views/RoomView/Separator.js b/app/views/RoomView/Separator.js index 181d87f1..17ac0471 100644 --- a/app/views/RoomView/Separator.js +++ b/app/views/RoomView/Separator.js @@ -8,10 +8,9 @@ const styles = StyleSheet.create({ container: { flexDirection: 'row', alignItems: 'center', - marginBottom: 25, - marginTop: 15, - marginHorizontal: 15, - transform: [{ scaleY: -1 }] + marginTop: 16, + marginBottom: 4, + marginHorizontal: 14 }, line: { backgroundColor: '#9ea2a8', @@ -40,7 +39,7 @@ const styles = StyleSheet.create({ } }); -const DateSeparator = ({ ts, unread }) => { +const DateSeparator = React.memo(({ ts, unread }) => { const date = ts ? moment(ts).format('MMM DD, YYYY') : null; if (ts && unread) { return ( @@ -65,7 +64,7 @@ const DateSeparator = ({ ts, unread }) => { ); -}; +}); DateSeparator.propTypes = { ts: PropTypes.instanceOf(Date), diff --git a/app/views/RoomView/UploadProgress.js b/app/views/RoomView/UploadProgress.js index f3c969c4..f4560b3b 100644 --- a/app/views/RoomView/UploadProgress.js +++ b/app/views/RoomView/UploadProgress.js @@ -11,6 +11,7 @@ import RocketChat from '../../lib/rocketchat'; import log from '../../utils/log'; import I18n from '../../i18n'; import { CustomIcon } from '../../lib/Icons'; +import { COLOR_SEPARATOR } from '../../constants/colors'; const styles = StyleSheet.create({ container: { @@ -23,7 +24,7 @@ const styles = StyleSheet.create({ backgroundColor: '#F1F2F4', height: 54, borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: '#CACED1', + borderColor: COLOR_SEPARATOR, justifyContent: 'center', paddingHorizontal: 20 }, diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index c7da383b..37aaeded 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -7,11 +7,12 @@ import { connect } from 'react-redux'; import { RectButton } from 'react-native-gesture-handler'; import { SafeAreaView } from 'react-navigation'; import equal from 'deep-equal'; +import moment from 'moment'; -import { openRoom as openRoomAction, closeRoom as closeRoomAction, setLastOpen as setLastOpenAction } from '../../actions/room'; +import { openRoom as openRoomAction, closeRoom as closeRoomAction } from '../../actions/room'; import { toggleReactionPicker as toggleReactionPickerAction, actionsShow as actionsShowAction } from '../../actions/messages'; import LoggedView from '../View'; -import { List } from './ListView'; +import { List } from './List'; import database from '../../lib/realm'; import RocketChat from '../../lib/rocketchat'; import Message from '../../containers/message'; @@ -28,6 +29,7 @@ import ConnectionBadge from '../../containers/ConnectionBadge'; import { CustomHeaderButtons, Item } from '../../containers/HeaderButton'; import RoomHeaderView from './Header'; import StatusBar from '../../containers/StatusBar'; +import Separator from './Separator'; @connect(state => ({ user: { @@ -41,7 +43,6 @@ import StatusBar from '../../containers/StatusBar'; appState: state.app.ready && state.app.foreground ? 'foreground' : 'background' }), dispatch => ({ openRoom: room => dispatch(openRoomAction(room)), - setLastOpen: date => dispatch(setLastOpenAction(date)), toggleReactionPicker: message => dispatch(toggleReactionPickerAction(message)), actionsShow: actionMessage => dispatch(actionsShowAction(actionMessage)), closeRoom: () => dispatch(closeRoomAction()) @@ -70,7 +71,6 @@ export default class RoomView extends LoggedView { static propTypes = { navigation: PropTypes.object, openRoom: PropTypes.func.isRequired, - setLastOpen: PropTypes.func.isRequired, user: PropTypes.shape({ id: PropTypes.string.isRequired, username: PropTypes.string.isRequired, @@ -92,9 +92,14 @@ export default class RoomView extends LoggedView { this.state = { loaded: false, joined: this.rooms.length > 0, - room: {} + room: {}, + lastOpen: null }; + this.beginAnimating = false; this.onReactionPress = this.onReactionPress.bind(this); + setTimeout(() => { + this.beginAnimating = true; + }, 300); } componentDidMount() { @@ -181,7 +186,7 @@ export default class RoomView extends LoggedView { }; internalSetState = (...args) => { - if (isIOS) { + if (isIOS && this.beginAnimating) { LayoutAnimation.easeInEaseOut(); } this.setState(...args); @@ -189,7 +194,7 @@ export default class RoomView extends LoggedView { // eslint-disable-next-line react/sort-comp updateRoom = () => { - const { openRoom, setLastOpen } = this.props; + const { openRoom } = this.props; if (this.rooms.length > 0) { const { room: prevRoom } = this.state; @@ -201,9 +206,9 @@ export default class RoomView extends LoggedView { ...room }); if (room.alert || room.unread || room.userMentions) { - setLastOpen(room.ls); + this.setLastOpen(room.ls); } else { - setLastOpen(null); + this.setLastOpen(null); } } } else { @@ -226,13 +231,14 @@ export default class RoomView extends LoggedView { } sendMessage = (message) => { - const { setLastOpen } = this.props; LayoutAnimation.easeInEaseOut(); RocketChat.sendMessage(this.rid, message).then(() => { - setLastOpen(null); + this.setLastOpen(null); }); }; + setLastOpen = lastOpen => this.setState({ lastOpen }); + joinRoom = async() => { try { const result = await RocketChat.joinRoom(this.rid); @@ -275,8 +281,46 @@ export default class RoomView extends LoggedView { } renderItem = (item, previousItem) => { - const { room } = this.state; + const { room, lastOpen } = this.state; const { user } = this.props; + let dateSeparator = null; + let showUnreadSeparator = false; + + if (!previousItem) { + dateSeparator = item.ts; + showUnreadSeparator = moment(item.ts).isAfter(lastOpen); + } else { + showUnreadSeparator = lastOpen + && moment(item.ts).isAfter(lastOpen) + && moment(previousItem.ts).isBefore(lastOpen); + if (!moment(item.ts).isSame(previousItem.ts, 'day')) { + dateSeparator = previousItem.ts; + } + } + + if (showUnreadSeparator || dateSeparator) { + return ( + + + + + ); + } return ( { - if (isIOS) { + const { navigation } = this.props; + if (isIOS && navigation.isFocused()) { LayoutAnimation.easeInEaseOut(); } this.setState(...args); diff --git a/app/views/RoomsListView/styles.js b/app/views/RoomsListView/styles.js index 5eea227a..862aac97 100644 --- a/app/views/RoomsListView/styles.js +++ b/app/views/RoomsListView/styles.js @@ -1,5 +1,6 @@ import { StyleSheet } from 'react-native'; import { isIOS } from '../../utils/deviceInfo'; +import { COLOR_SEPARATOR } from '../../constants/colors'; export default StyleSheet.create({ container: { @@ -8,8 +9,8 @@ export default StyleSheet.create({ }, separator: { height: StyleSheet.hairlineWidth, - backgroundColor: '#E1E5E8', - marginLeft: 78 + backgroundColor: COLOR_SEPARATOR, + marginLeft: 73 }, list: { width: '100%', @@ -36,7 +37,7 @@ export default StyleSheet.create({ dropdownContainerHeader: { height: 41, borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: '#E1E5E8', + borderColor: COLOR_SEPARATOR, alignItems: 'center', backgroundColor: isIOS ? '#fff' : '#54585E', flexDirection: 'row' @@ -79,7 +80,7 @@ export default StyleSheet.create({ }, sortSeparator: { height: StyleSheet.hairlineWidth, - backgroundColor: '#CBCED1', + backgroundColor: COLOR_SEPARATOR, marginHorizontal: 15, flex: 1 }, @@ -154,7 +155,7 @@ export default StyleSheet.create({ }, serverSeparator: { height: StyleSheet.hairlineWidth, - backgroundColor: '#E1E5E8', + backgroundColor: COLOR_SEPARATOR, marginLeft: 72 } }); diff --git a/app/views/SearchMessagesView/styles.js b/app/views/SearchMessagesView/styles.js index 97645326..4b524b73 100644 --- a/app/views/SearchMessagesView/styles.js +++ b/app/views/SearchMessagesView/styles.js @@ -1,4 +1,5 @@ import { StyleSheet } from 'react-native'; +import { COLOR_SEPARATOR } from '../../constants/colors'; export default StyleSheet.create({ container: { @@ -19,7 +20,7 @@ export default StyleSheet.create({ divider: { width: '100%', height: StyleSheet.hairlineWidth, - backgroundColor: '#E7EBF2', + backgroundColor: COLOR_SEPARATOR, marginVertical: 20 }, listEmptyContainer: { diff --git a/app/views/SidebarView/styles.js b/app/views/SidebarView/styles.js index 87c1e75a..420c66c2 100644 --- a/app/views/SidebarView/styles.js +++ b/app/views/SidebarView/styles.js @@ -1,4 +1,5 @@ import { StyleSheet } from 'react-native'; +import { COLOR_SEPARATOR } from '../../constants/colors'; export default StyleSheet.create({ container: { @@ -27,7 +28,7 @@ export default StyleSheet.create({ }, separator: { borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: '#E1E5E8', + borderColor: COLOR_SEPARATOR, marginVertical: 4 }, header: { diff --git a/e2e/07-createroom.spec.js b/e2e/07-createroom.spec.js index 98ab91e5..90767ba3 100644 --- a/e2e/07-createroom.spec.js +++ b/e2e/07-createroom.spec.js @@ -117,8 +117,8 @@ describe('Create room screen', () => { 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.text(room))).toBeVisible().withTimeout(60000); - await expect(element(by.text(room))).toBeVisible(); + await waitFor(element(by.text(room))).toExist().withTimeout(60000); + await expect(element(by.text(room))).toExist(); await tapBack(); await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000); await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toBeVisible().withTimeout(60000); @@ -141,8 +141,8 @@ describe('Create room screen', () => { 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.text(room))).toBeVisible().withTimeout(60000); - await expect(element(by.text(room))).toBeVisible(); + await waitFor(element(by.text(room))).toExist().withTimeout(60000); + await expect(element(by.text(room))).toExist(); await tapBack(); await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000); await element(by.id('rooms-list-view-search')).replaceText(room); @@ -165,8 +165,8 @@ describe('Create room screen', () => { 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.text(room))).toBeVisible().withTimeout(60000); - await expect(element(by.text(room))).toBeVisible(); + await waitFor(element(by.text(room))).toExist().withTimeout(60000); + await expect(element(by.text(room))).toExist(); await tapBack(); await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000); await element(by.id('rooms-list-view-search')).replaceText(room); diff --git a/e2e/12-broadcast.spec.js b/e2e/12-broadcast.spec.js index 018ba3c9..032001c0 100644 --- a/e2e/12-broadcast.spec.js +++ b/e2e/12-broadcast.spec.js @@ -26,8 +26,8 @@ describe('Broadcast room', () => { 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.text(`broadcast${ data.random }`))).toBeVisible().withTimeout(60000); - await expect(element(by.text(`broadcast${ data.random }`))).toBeVisible(); + await waitFor(element(by.text(`broadcast${ data.random }`))).toExist().withTimeout(60000); + await expect(element(by.text(`broadcast${ data.random }`))).toExist(); await element(by.id('room-view-header-actions')).tap(); await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000); await element(by.id('room-actions-info')).tap(); @@ -76,8 +76,8 @@ describe('Broadcast room', () => { await expect(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toExist(); await element(by.id(`rooms-list-view-item-broadcast${ data.random }`)).tap(); await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(5000); - await waitFor(element(by.text(`broadcast${ data.random }`))).toBeVisible().withTimeout(60000); - await expect(element(by.text(`broadcast${ data.random }`))).toBeVisible(); + await waitFor(element(by.text(`broadcast${ data.random }`))).toExist().withTimeout(60000); + await expect(element(by.text(`broadcast${ data.random }`))).toExist(); }); it('should not have messagebox', async() => { diff --git a/e2e/data.js b/e2e/data.js index 850d9df5..512512b5 100644 --- a/e2e/data.js +++ b/e2e/data.js @@ -7,7 +7,7 @@ const data = { password: `password${ value }`, alternateUser: 'detoxrn', alternateUserPassword: '123', - alternateUserTOTPSecret: 'KESVIUCQMZWEYNBMJJAUW4LYKRBVWYZ7HBWTIWDPIAZUOURTF4WA', + alternateUserTOTPSecret: 'I5SGETK3GBXXA7LNLMZTEJJRIN3G6LTEEE4G4PS3EQRXU4LNPU7A', email: `diego.mello+e2e${ value }@rocket.chat`, random: value } diff --git a/storybook/stories/Message.js b/storybook/stories/Message.js index 6bd0b1e8..9081b4dc 100644 --- a/storybook/stories/Message.js +++ b/storybook/stories/Message.js @@ -8,9 +8,8 @@ import MessageSeparator from '../../app/views/RoomView/Separator'; const styles = StyleSheet.create({ separator: { - transform: [{ scaleY: -1 }], - marginBottom: 30, - marginTop: 0 + marginTop: 30, + marginBottom: 0 } }); @@ -44,14 +43,15 @@ const Message = props => ( const Separator = ({ title }) => ; export default ( - + - + - + + - - + - + - + + - + - - + - + - + - + + {}} /> - + {}} /> - + - + - + - + - + - + - + - + - + - - alert('broadcast!')} /> + alert('broadcast!')} /> - + + alert('Error pressed')} header={false} /> alert('Error pressed')} /> - - + - + - + - + - + + - - + - + - + - + - + + - + - - + - + - + - + - + - + + - - + - + + - - + + - );