diff --git a/__tests__/__snapshots__/Storyshots.test.js.snap b/__tests__/__snapshots__/Storyshots.test.js.snap
index d5d1d912..286e506e 100644
--- a/__tests__/__snapshots__/Storyshots.test.js.snap
+++ b/__tests__/__snapshots__/Storyshots.test.js.snap
@@ -1055,6 +1055,533 @@ exports[`Storyshots Avatar list Avatar 1`] = `
`;
+exports[`Storyshots BackgroundContainer basic 1`] = `
+
+
+
+
+
+`;
+
+exports[`Storyshots BackgroundContainer black theme - loading 1`] = `
+
+
+
+
+
+
+`;
+
+exports[`Storyshots BackgroundContainer black theme - text 1`] = `
+
+
+
+
+
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries
+
+
+`;
+
+exports[`Storyshots BackgroundContainer dark theme - loading 1`] = `
+
+
+
+
+
+
+`;
+
+exports[`Storyshots BackgroundContainer dark theme - text 1`] = `
+
+
+
+
+
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries
+
+
+`;
+
+exports[`Storyshots BackgroundContainer loading 1`] = `
+
+
+
+
+
+
+`;
+
+exports[`Storyshots BackgroundContainer long text 1`] = `
+
+
+
+
+
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries
+
+
+`;
+
+exports[`Storyshots BackgroundContainer text 1`] = `
+
+
+
+
+
+ Text here
+
+
+`;
+
exports[`Storyshots Header Buttons badge 1`] = `
`;
+exports[`Storyshots RoomHeader icons 1`] = `
+Array [
+
+
+
+
+
+
+
+
+
+ private channel
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ public channel
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ discussion
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ omnichannel
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ private team
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ public team
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ group dm
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ online dm
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ away dm
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ busy dm
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ loading dm
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ offline dm
+
+
+
+
+
+ ,
+]
+`;
+
+exports[`Storyshots RoomHeader landscape 1`] = `
+Array [
+
+
+
+
+
+
+
+
+
+ title
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ title
+
+
+
+ subtitle
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries
+
+
+
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries
+
+
+
+
+ ,
+]
+`;
+
+exports[`Storyshots RoomHeader themes 1`] = `
+Array [
+
+
+
+
+
+
+
+
+
+ title
+
+
+
+ subtitle
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ title
+
+
+
+ subtitle
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ title
+
+
+
+ subtitle
+
+
+
+
+ ,
+]
+`;
+
+exports[`Storyshots RoomHeader thread 1`] = `
+Array [
+
+
+
+
+
+
+ title
+
+
+
+
+
+
+
+ parent title
+
+
+
+
+
+ ,
+
+
+
+
+
+
+ markdown preview #3 4 5
+
+
+
+
+
+
+
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries
+
+
+
+
+
+ ,
+]
+`;
+
+exports[`Storyshots RoomHeader title and subtitle 1`] = `
+Array [
+
+
+
+
+
+
+
+
+
+ title
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ title
+
+
+
+ subtitle
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ title
+
+
+
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries
+
+
+
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries
+
+
+
+
+ ,
+]
+`;
+
+exports[`Storyshots RoomHeader typing 1`] = `
+Array [
+
+
+
+
+
+
+
+
+
+ title
+
+
+
+
+ user 1
+
+
+ is typing
+ ...
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ title
+
+
+
+
+ user 1 and user 2
+
+
+ are typing
+ ...
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ title
+
+
+
+
+ user 1, user 2, user 3, user 4, user 5
+
+
+ are typing
+ ...
+
+
+
+
+ ,
+]
+`;
+
exports[`Storyshots RoomItem list roomitem 1`] = `
(
+const BackgroundContainer = ({ theme, text, loading }) => (
- {text}
+ {text ? {text} : null}
+ {loading ? : null}
);
-EmptyRoom.propTypes = {
+BackgroundContainer.propTypes = {
text: PropTypes.string,
- theme: PropTypes.string
+ theme: PropTypes.string,
+ loading: PropTypes.bool
};
-export default withTheme(EmptyRoom);
+export default withTheme(BackgroundContainer);
diff --git a/app/containers/BackgroundContainer/index.stories.js b/app/containers/BackgroundContainer/index.stories.js
new file mode 100644
index 00000000..0b6c9a1c
--- /dev/null
+++ b/app/containers/BackgroundContainer/index.stories.js
@@ -0,0 +1,49 @@
+/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions, react/prop-types */
+import React from 'react';
+import { storiesOf } from '@storybook/react-native';
+
+import BackgroundContainer from '.';
+import { ThemeContext } from '../../theme';
+import { longText } from '../../../storybook/utils';
+
+const stories = storiesOf('BackgroundContainer', module);
+
+stories.add('basic', () => (
+
+));
+
+stories.add('loading', () => (
+
+));
+
+stories.add('text', () => (
+
+));
+
+stories.add('long text', () => (
+
+));
+
+const ThemeStory = ({ theme, ...props }) => (
+
+
+
+);
+
+stories.add('dark theme - loading', () => (
+
+));
+
+stories.add('dark theme - text', () => (
+
+));
+
+stories.add('black theme - loading', () => (
+
+));
+
+stories.add('black theme - text', () => (
+
+));
diff --git a/app/views/RoomView/Header/Header.js b/app/containers/RoomHeader/RoomHeader.js
similarity index 65%
rename from app/views/RoomView/Header/Header.js
rename to app/containers/RoomHeader/RoomHeader.js
index 4cdccca8..6715fc13 100644
--- a/app/views/RoomView/Header/Header.js
+++ b/app/containers/RoomHeader/RoomHeader.js
@@ -4,16 +4,21 @@ import {
View, Text, StyleSheet, TouchableOpacity
} from 'react-native';
-import I18n from '../../../i18n';
-import sharedStyles from '../../Styles';
-import { themes } from '../../../constants/colors';
-import Markdown from '../../../containers/markdown';
-import RoomTypeIcon from '../../../containers/RoomTypeIcon';
+import I18n from '../../i18n';
+import sharedStyles from '../../views/Styles';
+import { themes } from '../../constants/colors';
+import Markdown from '../markdown';
+import RoomTypeIcon from '../RoomTypeIcon';
+import { withTheme } from '../../theme';
const HIT_SLOP = {
top: 5, right: 5, bottom: 5, left: 5
};
const TITLE_SIZE = 16;
+const SUBTITLE_SIZE = 12;
+
+const getSubTitleSize = scale => SUBTITLE_SIZE * scale;
+
const styles = StyleSheet.create({
container: {
flex: 1,
@@ -24,12 +29,12 @@ const styles = StyleSheet.create({
flexDirection: 'row'
},
title: {
- ...sharedStyles.textSemibold,
- fontSize: TITLE_SIZE
+ flexShrink: 1,
+ ...sharedStyles.textSemibold
},
subtitle: {
- ...sharedStyles.textRegular,
- fontSize: 12
+ flexShrink: 1,
+ ...sharedStyles.textRegular
},
typingUsers: {
...sharedStyles.textSemibold
@@ -37,8 +42,9 @@ const styles = StyleSheet.create({
});
const SubTitle = React.memo(({
- usersTyping, subtitle, renderFunc, theme
+ usersTyping, subtitle, renderFunc, theme, scale
}) => {
+ const fontSize = getSubTitleSize(scale);
// typing
if (usersTyping.length) {
let usersText;
@@ -48,7 +54,7 @@ const SubTitle = React.memo(({
usersText = usersTyping.join(', ');
}
return (
-
+
{usersText}
{ usersTyping.length > 1 ? I18n.t('are_typing') : I18n.t('is_typing') }...
@@ -66,7 +72,7 @@ const SubTitle = React.memo(({
@@ -80,18 +86,20 @@ SubTitle.propTypes = {
usersTyping: PropTypes.array,
theme: PropTypes.string,
subtitle: PropTypes.string,
- renderFunc: PropTypes.func
+ renderFunc: PropTypes.func,
+ scale: PropTypes.number
};
const HeaderTitle = React.memo(({
- title, tmid, prid, scale, theme
+ title, tmid, prid, scale, theme, testID
}) => {
+ const titleStyle = { fontSize: TITLE_SIZE * scale, color: themes[theme].headerTitleColor };
if (!tmid && !prid) {
return (
{title}
@@ -102,10 +110,10 @@ const HeaderTitle = React.memo(({
);
});
@@ -115,11 +123,12 @@ HeaderTitle.propTypes = {
tmid: PropTypes.string,
prid: PropTypes.string,
scale: PropTypes.number,
- theme: PropTypes.string
+ theme: PropTypes.string,
+ testID: PropTypes.string
};
const Header = React.memo(({
- title, subtitle, parentTitle, type, status, usersTyping, width, height, prid, tmid, connecting, goRoomActionsView, theme, isGroupChat
+ title, subtitle, parentTitle, type, status, usersTyping, width, height, prid, tmid, onPress, theme, isGroupChat, teamMain, testID
}) => {
const portrait = height > width;
let scale = 1;
@@ -130,13 +139,11 @@ const Header = React.memo(({
}
}
- const onPress = () => goRoomActionsView();
-
let renderFunc;
if (tmid) {
renderFunc = () => (
-
+
{parentTitle}
);
@@ -144,7 +151,7 @@ const Header = React.memo(({
return (
- {tmid ? null : }
+ {tmid ? null : }
-
+
);
});
@@ -175,17 +188,18 @@ Header.propTypes = {
height: PropTypes.number.isRequired,
prid: PropTypes.string,
tmid: PropTypes.string,
+ teamMain: PropTypes.bool,
status: PropTypes.string,
theme: PropTypes.string,
usersTyping: PropTypes.array,
- connecting: PropTypes.bool,
isGroupChat: PropTypes.bool,
parentTitle: PropTypes.string,
- goRoomActionsView: PropTypes.func
+ onPress: PropTypes.func,
+ testID: PropTypes.string
};
Header.defaultProps = {
usersTyping: []
};
-export default Header;
+export default withTheme(Header);
diff --git a/app/containers/RoomHeader/RoomHeader.stories.js b/app/containers/RoomHeader/RoomHeader.stories.js
new file mode 100644
index 00000000..bfea5e27
--- /dev/null
+++ b/app/containers/RoomHeader/RoomHeader.stories.js
@@ -0,0 +1,94 @@
+/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions, react/prop-types, react/destructuring-assignment */
+import React from 'react';
+import { View, Dimensions } from 'react-native';
+import { storiesOf } from '@storybook/react-native';
+
+import RoomHeaderComponent from './RoomHeader';
+import Header from '../Header';
+import { longText } from '../../../storybook/utils';
+import { ThemeContext } from '../../theme';
+
+const stories = storiesOf('RoomHeader', module);
+
+// TODO: refactor after react-navigation v6
+const HeaderExample = ({ title }) => (
+ (
+
+ {title()}
+
+ )}
+ />
+);
+
+const { width, height } = Dimensions.get('window');
+
+const RoomHeader = ({ ...props }) => (
+ alert('header pressed!')} {...props} />
+);
+
+stories.add('title and subtitle', () => (
+ <>
+ } />
+ } />
+ } />
+ } />
+ } />
+ >
+));
+
+stories.add('icons', () => (
+ <>
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ >
+));
+
+stories.add('typing', () => (
+ <>
+ } />
+ } />
+ } />
+ >
+));
+
+stories.add('landscape', () => (
+ <>
+ } />
+ } />
+ } />
+ >
+));
+
+stories.add('thread', () => (
+ <>
+ } />
+ } />
+ >
+));
+
+const ThemeStory = ({ theme }) => (
+
+ } />
+
+);
+
+stories.add('themes', () => (
+ <>
+
+
+
+ >
+));
diff --git a/app/views/RoomView/Header/index.js b/app/containers/RoomHeader/index.js
similarity index 77%
rename from app/views/RoomView/Header/index.js
rename to app/containers/RoomHeader/index.js
index a66f21a4..4eeab701 100644
--- a/app/views/RoomView/Header/index.js
+++ b/app/containers/RoomHeader/index.js
@@ -3,42 +3,37 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { dequal } from 'dequal';
-import Header from './Header';
-import LeftButtons from './LeftButtons';
-import RightButtons from './RightButtons';
-import { withTheme } from '../../../theme';
-import { withDimensions } from '../../../dimensions';
-import I18n from '../../../i18n';
+import RoomHeader from './RoomHeader';
+import { withDimensions } from '../../dimensions';
+import I18n from '../../i18n';
-class RoomHeaderView extends Component {
+class RoomHeaderContainer extends Component {
static propTypes = {
title: PropTypes.string,
subtitle: PropTypes.string,
type: PropTypes.string,
prid: PropTypes.string,
tmid: PropTypes.string,
+ teamMain: PropTypes.bool,
usersTyping: PropTypes.string,
status: PropTypes.string,
statusText: PropTypes.string,
connecting: PropTypes.bool,
connected: PropTypes.bool,
- theme: PropTypes.string,
roomUserId: PropTypes.string,
widthOffset: PropTypes.number,
- goRoomActionsView: PropTypes.func,
+ onPress: PropTypes.func,
width: PropTypes.number,
height: PropTypes.number,
parentTitle: PropTypes.string,
- isGroupChat: PropTypes.bool
+ isGroupChat: PropTypes.bool,
+ testID: PropTypes.string
};
shouldComponentUpdate(nextProps) {
const {
- type, title, subtitle, status, statusText, connecting, connected, goRoomActionsView, usersTyping, theme, width, height
+ type, title, subtitle, status, statusText, connecting, connected, onPress, usersTyping, width, height
} = this.props;
- if (nextProps.theme !== theme) {
- return true;
- }
if (nextProps.type !== type) {
return true;
}
@@ -69,7 +64,7 @@ class RoomHeaderView extends Component {
if (!dequal(nextProps.usersTyping, usersTyping)) {
return true;
}
- if (nextProps.goRoomActionsView !== goRoomActionsView) {
+ if (nextProps.onPress !== onPress) {
return true;
}
return false;
@@ -80,6 +75,7 @@ class RoomHeaderView extends Component {
title,
subtitle: subtitleProp,
type,
+ teamMain,
prid,
tmid,
widthOffset,
@@ -88,13 +84,13 @@ class RoomHeaderView extends Component {
connecting,
connected,
usersTyping,
- goRoomActionsView,
+ onPress,
roomUserId,
- theme,
width,
height,
parentTitle,
- isGroupChat
+ isGroupChat,
+ testID
} = this.props;
let subtitle;
@@ -107,23 +103,24 @@ class RoomHeaderView extends Component {
}
return (
-
);
}
@@ -153,6 +150,4 @@ const mapStateToProps = (state, ownProps) => {
};
};
-export default connect(mapStateToProps)(withDimensions(withTheme(RoomHeaderView)));
-
-export { RightButtons, LeftButtons };
+export default connect(mapStateToProps)(withDimensions(RoomHeaderContainer));
diff --git a/app/containers/RoomTypeIcon.js b/app/containers/RoomTypeIcon.js
index 44044f33..55294310 100644
--- a/app/containers/RoomTypeIcon.js
+++ b/app/containers/RoomTypeIcon.js
@@ -13,7 +13,7 @@ const styles = StyleSheet.create({
});
const RoomTypeIcon = React.memo(({
- type, size, isGroupChat, status, style, theme
+ type, size, isGroupChat, status, style, theme, teamMain
}) => {
if (!type) {
return null;
@@ -31,7 +31,9 @@ const RoomTypeIcon = React.memo(({
}
let icon = 'channel-private';
- if (type === 'discussion') {
+ if (teamMain) {
+ icon = `teams${ type === 'p' ? '-private' : '' }`;
+ } else if (type === 'discussion') {
icon = 'discussions';
} else if (type === 'c') {
icon = 'channel-public';
@@ -58,6 +60,7 @@ RoomTypeIcon.propTypes = {
theme: PropTypes.string,
type: PropTypes.string,
isGroupChat: PropTypes.bool,
+ teamMain: PropTypes.bool,
status: PropTypes.string,
size: PropTypes.number,
style: PropTypes.object
diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json
index ce4243c4..ec289d27 100644
--- a/app/i18n/locales/en.json
+++ b/app/i18n/locales/en.json
@@ -706,5 +706,8 @@
"Enter_workspace_URL": "Enter workspace URL",
"Workspace_URL_Example": "Ex. your-company.rocket.chat",
"This_room_encryption_has_been_enabled_by__username_": "This room's encryption has been enabled by {{username}}",
- "This_room_encryption_has_been_disabled_by__username_": "This room's encryption has been disabled by {{username}}"
+ "This_room_encryption_has_been_disabled_by__username_": "This room's encryption has been disabled by {{username}}",
+ "Teams": "Teams",
+ "No_team_channels_found": "No channels found",
+ "Team_not_found": "Team not found"
}
\ No newline at end of file
diff --git a/app/i18n/locales/pt-BR.json b/app/i18n/locales/pt-BR.json
index 3d52af4a..4002b2d6 100644
--- a/app/i18n/locales/pt-BR.json
+++ b/app/i18n/locales/pt-BR.json
@@ -656,5 +656,8 @@
"This_room_encryption_has_been_disabled_by__username_": "A criptografia para essa sala foi desabilitada por {{username}}",
"Apply_Your_Certificate": "Aplicar certificado",
"Do_you_have_a_certificate": "Você tem um certificado?",
- "Your_certificate": "Seu certificado"
+ "Your_certificate": "Seu certificado",
+ "Teams": "Times",
+ "No_team_channels_found": "Nenhum canal encontrado",
+ "Team_not_found": "Time não encontrado"
}
\ No newline at end of file
diff --git a/app/lib/database/model/Subscription.js b/app/lib/database/model/Subscription.js
index 378c9759..5b1ebd14 100644
--- a/app/lib/database/model/Subscription.js
+++ b/app/lib/database/model/Subscription.js
@@ -125,4 +125,8 @@ export default class Subscription extends Model {
@field('e2e_key_id') e2eKeyId;
@field('avatar_etag') avatarETag;
+
+ @field('team_id') teamId;
+
+ @field('team_main') teamMain;
}
diff --git a/app/lib/database/model/migrations.js b/app/lib/database/model/migrations.js
index c8f3d449..cdc65ef0 100644
--- a/app/lib/database/model/migrations.js
+++ b/app/lib/database/model/migrations.js
@@ -212,6 +212,18 @@ export default schemaMigrations({
]
})
]
+ },
+ {
+ toVersion: 13,
+ steps: [
+ addColumns({
+ table: 'subscriptions',
+ columns: [
+ { name: 'team_id', type: 'string', isIndexed: true },
+ { name: 'team_main', type: 'boolean', isOptional: true }
+ ]
+ })
+ ]
}
]
});
diff --git a/app/lib/database/schema/app.js b/app/lib/database/schema/app.js
index 055b8f64..883e6dfd 100644
--- a/app/lib/database/schema/app.js
+++ b/app/lib/database/schema/app.js
@@ -1,7 +1,7 @@
import { appSchema, tableSchema } from '@nozbe/watermelondb';
export default appSchema({
- version: 12,
+ version: 13,
tables: [
tableSchema({
name: 'subscriptions',
@@ -57,7 +57,9 @@ export default appSchema({
{ name: 'e2e_key', type: 'string', isOptional: true },
{ name: 'encrypted', type: 'boolean', isOptional: true },
{ name: 'e2e_key_id', type: 'string', isOptional: true },
- { name: 'avatar_etag', type: 'string', isOptional: true }
+ { name: 'avatar_etag', type: 'string', isOptional: true },
+ { name: 'team_id', type: 'string', isIndexed: true },
+ { name: 'team_main', type: 'boolean', isOptional: true }
]
}),
tableSchema({
diff --git a/app/lib/methods/helpers/mergeSubscriptionsRooms.js b/app/lib/methods/helpers/mergeSubscriptionsRooms.js
index 895f2a8a..82dfc4c6 100644
--- a/app/lib/methods/helpers/mergeSubscriptionsRooms.js
+++ b/app/lib/methods/helpers/mergeSubscriptionsRooms.js
@@ -42,6 +42,8 @@ export const merge = (subscription, room) => {
subscription.encrypted = room.encrypted;
subscription.e2eKeyId = room.e2eKeyId;
subscription.avatarETag = room.avatarETag;
+ subscription.teamId = room.teamId;
+ subscription.teamMain = room.teamMain;
if (!subscription.roles || !subscription.roles.length) {
subscription.roles = [];
}
diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js
index 26298392..3cce8ed0 100644
--- a/app/lib/rocketchat.js
+++ b/app/lib/rocketchat.js
@@ -931,6 +931,19 @@ const RocketChat = {
// RC 2.3.0
return this.sdk.get('livechat/visitors.info', { visitorId });
},
+ getTeamListRoom({
+ teamId, count, offset, type, filter
+ }) {
+ const params = {
+ teamId, count, offset, type
+ };
+
+ if (filter) {
+ params.filter = filter;
+ }
+ // RC 3.13.0
+ return this.sdk.get('teams.listRooms', params);
+ },
closeLivechat(rid, comment) {
// RC 0.29.0
return this.methodCallWrapper('livechat:closeRoom', rid, comment, { clientAction: true });
diff --git a/app/presentation/RoomItem/RoomItem.js b/app/presentation/RoomItem/RoomItem.js
index 27cf9f37..b3922787 100644
--- a/app/presentation/RoomItem/RoomItem.js
+++ b/app/presentation/RoomItem/RoomItem.js
@@ -44,7 +44,8 @@ const RoomItem = ({
onPress,
toggleFav,
toggleRead,
- hideChannel
+ hideChannel,
+ teamMain
}) => (
);
+ type, prid, status, isGroupChat, teamMain
+}) => );
TypeIcon.propTypes = {
type: PropTypes.string,
status: PropTypes.string,
prid: PropTypes.string,
- isGroupChat: PropTypes.bool
+ isGroupChat: PropTypes.bool,
+ teamMain: PropTypes.bool
};
export default TypeIcon;
diff --git a/app/presentation/RoomItem/index.js b/app/presentation/RoomItem/index.js
index 1f5bb9e7..80bcf063 100644
--- a/app/presentation/RoomItem/index.js
+++ b/app/presentation/RoomItem/index.js
@@ -188,6 +188,7 @@ class RoomItemContainer extends React.Component {
tunreadUser={item.tunreadUser}
tunreadGroup={item.tunreadGroup}
swipeEnabled={swipeEnabled}
+ teamMain={item.teamMain}
/>
);
}
diff --git a/app/sagas/rooms.js b/app/sagas/rooms.js
index f963a294..4b0047a1 100644
--- a/app/sagas/rooms.js
+++ b/app/sagas/rooms.js
@@ -12,6 +12,7 @@ import mergeSubscriptionsRooms from '../lib/methods/helpers/mergeSubscriptionsRo
import RocketChat from '../lib/rocketchat';
import buildMessage from '../lib/methods/helpers/buildMessage';
import protectedFunction from '../lib/methods/helpers/protectedFunction';
+import UserPreferences from '../lib/userPreferences';
const updateRooms = function* updateRooms({ server, newRoomsUpdatedAt }) {
const serversDB = database.servers;
@@ -47,6 +48,16 @@ const handleRoomsRequest = function* handleRoomsRequest({ params }) {
// Server not found
}
}
+
+ // Force fetch all subscriptions to update columns related to Teams feature
+ // TODO: remove it a couple of releases
+ const teamsMigrationKey = `${ server }_TEAMS_MIGRATION`;
+ const teamsMigration = yield UserPreferences.getBoolAsync(teamsMigrationKey);
+ if (!teamsMigration) {
+ roomsUpdatedAt = null;
+ UserPreferences.setBoolAsync(teamsMigrationKey, true);
+ }
+
const [subscriptionsResult, roomsResult] = yield RocketChat.getRooms(roomsUpdatedAt);
const { subscriptions } = yield mergeSubscriptionsRooms(subscriptionsResult, roomsResult);
diff --git a/app/stacks/InsideStack.js b/app/stacks/InsideStack.js
index a0af9617..bda56f0d 100644
--- a/app/stacks/InsideStack.js
+++ b/app/stacks/InsideStack.js
@@ -29,6 +29,7 @@ import ForwardLivechatView from '../views/ForwardLivechatView';
import LivechatEditView from '../views/LivechatEditView';
import PickerView from '../views/PickerView';
import ThreadMessagesView from '../views/ThreadMessagesView';
+import TeamChannelsView from '../views/TeamChannelsView';
import MarkdownTableView from '../views/MarkdownTableView';
import ReadReceiptsView from '../views/ReadReceiptView';
import { themes } from '../constants/colors';
@@ -168,6 +169,11 @@ const ChatsStackNavigator = () => {
component={ThreadMessagesView}
options={ThreadMessagesView.navigationOptions}
/>
+
{
name='ThreadMessagesView'
component={ThreadMessagesView}
/>
+
{
- let navigationMethod = Navigation.navigate;
+ let navigationMethod = props.navigationMethod ?? Navigation.navigate;
if (isMasterDetail) {
navigationMethod = Navigation.replace;
diff --git a/app/utils/log/events.js b/app/utils/log/events.js
index 2e1e8f9a..fc8d7042 100644
--- a/app/utils/log/events.js
+++ b/app/utils/log/events.js
@@ -212,6 +212,7 @@ export default {
ROOM_JOIN: 'room_join',
ROOM_GO_RA: 'room_go_ra',
ROOM_TOGGLE_FOLLOW_THREADS: 'room_toggle_follow_threads',
+ ROOM_GO_TEAM_CHANNELS: 'room_go_team_channels',
ROOM_GO_SEARCH: 'room_go_search',
ROOM_GO_THREADS: 'room_go_threads',
ROOM_GO_ROOM_INFO: 'room_go_room_info',
@@ -310,5 +311,11 @@ export default {
// E2E ENCRYPTION SECURITY VIEW
E2E_SEC_CHANGE_PASSWORD: 'e2e_sec_change_password',
- E2E_SEC_RESET_OWN_KEY: 'e2e_sec_reset_own_key'
+ E2E_SEC_RESET_OWN_KEY: 'e2e_sec_reset_own_key',
+
+ // TEAM CHANNELS VIEW
+ TC_SEARCH: 'tc_search',
+ TC_CANCEL_SEARCH: 'tc_cancel_search',
+ TC_GO_ACTIONS: 'tc_go_actions',
+ TC_GO_ROOM: 'tc_go_room'
};
diff --git a/app/views/NewMessageView.js b/app/views/NewMessageView.js
index 7e2aa232..78178c4c 100644
--- a/app/views/NewMessageView.js
+++ b/app/views/NewMessageView.js
@@ -175,7 +175,7 @@ class NewMessageView extends React.Component {
{maxUsers > 2 ? this.renderButton({
onPress: this.createGroupChat,
title: I18n.t('Create_Direct_Messages'),
- icon: 'team',
+ icon: 'message',
testID: 'new-message-view-create-direct-message'
}) : null}
{this.renderButton({
diff --git a/app/views/RoomActionsView/index.js b/app/views/RoomActionsView/index.js
index 2686b60e..89bc5f22 100644
--- a/app/views/RoomActionsView/index.js
+++ b/app/views/RoomActionsView/index.js
@@ -461,7 +461,7 @@ class RoomActionsView extends React.Component {
? {room.fname}
: (
-
+
{RocketChat.getRoomTitle(room)}
)
diff --git a/app/views/RoomInfoView/index.js b/app/views/RoomInfoView/index.js
index 5966f312..a49aab5b 100644
--- a/app/views/RoomInfoView/index.js
+++ b/app/views/RoomInfoView/index.js
@@ -41,7 +41,7 @@ const getRoomTitle = (room, type, name, username, statusText, theme) => (type ==
)
: (
-
+
{RocketChat.getRoomTitle(room)}
)
diff --git a/app/views/RoomView/Header/LeftButtons.js b/app/views/RoomView/LeftButtons.js
similarity index 93%
rename from app/views/RoomView/Header/LeftButtons.js
rename to app/views/RoomView/LeftButtons.js
index 68ad9b08..089c284d 100644
--- a/app/views/RoomView/Header/LeftButtons.js
+++ b/app/views/RoomView/LeftButtons.js
@@ -3,8 +3,8 @@ import PropTypes from 'prop-types';
import { StyleSheet } from 'react-native';
import { HeaderBackButton } from '@react-navigation/stack';
-import { themes } from '../../../constants/colors';
-import Avatar from '../../../containers/Avatar';
+import { themes } from '../../constants/colors';
+import Avatar from '../../containers/Avatar';
const styles = StyleSheet.create({
avatar: {
diff --git a/app/views/RoomView/Header/RightButtons.js b/app/views/RoomView/RightButtons.js
similarity index 85%
rename from app/views/RoomView/Header/RightButtons.js
rename to app/views/RoomView/RightButtons.js
index 37939b1e..debc3edb 100644
--- a/app/views/RoomView/Header/RightButtons.js
+++ b/app/views/RoomView/RightButtons.js
@@ -3,10 +3,10 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { dequal } from 'dequal';
-import * as HeaderButton from '../../../containers/HeaderButton';
-import database from '../../../lib/database';
-import { getUserSelector } from '../../../selectors/login';
-import { logEvent, events } from '../../../utils/log';
+import * as HeaderButton from '../../containers/HeaderButton';
+import database from '../../lib/database';
+import { getUserSelector } from '../../selectors/login';
+import { logEvent, events } from '../../utils/log';
class RightButtonsContainer extends Component {
static propTypes = {
@@ -15,6 +15,7 @@ class RightButtonsContainer extends Component {
rid: PropTypes.string,
t: PropTypes.string,
tmid: PropTypes.string,
+ teamId: PropTypes.bool,
navigation: PropTypes.object,
isMasterDetail: PropTypes.bool,
toggleFollowThread: PropTypes.func
@@ -109,6 +110,21 @@ class RightButtonsContainer extends Component {
});
}
+ goTeamChannels = () => {
+ logEvent(events.ROOM_GO_TEAM_CHANNELS);
+ const {
+ navigation, isMasterDetail, teamId
+ } = this.props;
+ if (isMasterDetail) {
+ navigation.navigate('ModalStackNavigator', {
+ screen: 'TeamChannelsView',
+ params: { teamId }
+ });
+ } else {
+ navigation.navigate('TeamChannelsView', { teamId });
+ }
+ }
+
goThreadsView = () => {
logEvent(events.ROOM_GO_THREADS);
const {
@@ -146,7 +162,9 @@ class RightButtonsContainer extends Component {
const {
isFollowingThread, tunread, tunreadUser, tunreadGroup
} = this.state;
- const { t, tmid, threadsEnabled } = this.props;
+ const {
+ t, tmid, threadsEnabled, teamId
+ } = this.props;
if (t === 'l') {
return null;
}
@@ -163,6 +181,13 @@ class RightButtonsContainer extends Component {
}
return (
+ {teamId ? (
+
+ ) : null}
{threadsEnabled ? (
),
headerTitle: () => (
-
),
headerRight: () => (
(s.unread > 0 || s.tunread?.length > 0 || s.alert) && !s.hideUnreadStatus;
const filterIsFavorite = s => s.f;
const filterIsOmnichannel = s => s.t === 'l';
+const filterIsTeam = s => s.teamMain;
+const filterIsDiscussion = s => s.prid;
const shouldUpdateProps = [
'searchText',
@@ -475,10 +478,12 @@ class RoomsListView extends React.Component {
// type
if (groupByType) {
- const discussions = chats.filter(s => s.prid);
- const channels = chats.filter(s => s.t === 'c' && !s.prid);
- const privateGroup = chats.filter(s => s.t === 'p' && !s.prid);
- const direct = chats.filter(s => s.t === 'd' && !s.prid);
+ const teams = chats.filter(s => filterIsTeam(s));
+ const discussions = chats.filter(s => filterIsDiscussion(s));
+ const channels = chats.filter(s => s.t === 'c' && !filterIsDiscussion(s) && !filterIsTeam(s));
+ const privateGroup = chats.filter(s => s.t === 'p' && !filterIsDiscussion(s) && !filterIsTeam(s));
+ const direct = chats.filter(s => s.t === 'd' && !filterIsDiscussion(s) && !filterIsTeam(s));
+ tempChats = this.addRoomsGroup(teams, TEAMS_HEADER, tempChats);
tempChats = this.addRoomsGroup(discussions, DISCUSSIONS_HEADER, tempChats);
tempChats = this.addRoomsGroup(channels, CHANNELS_HEADER, tempChats);
tempChats = this.addRoomsGroup(privateGroup, GROUPS_HEADER, tempChats);
diff --git a/app/views/TeamChannelsView.js b/app/views/TeamChannelsView.js
new file mode 100644
index 00000000..ab8d261e
--- /dev/null
+++ b/app/views/TeamChannelsView.js
@@ -0,0 +1,369 @@
+import React from 'react';
+import { Keyboard } from 'react-native';
+import PropTypes from 'prop-types';
+import { Q } from '@nozbe/watermelondb';
+import { withSafeAreaInsets } from 'react-native-safe-area-context';
+import { connect } from 'react-redux';
+import { FlatList } from 'react-native-gesture-handler';
+import { HeaderBackButton } from '@react-navigation/stack';
+
+import StatusBar from '../containers/StatusBar';
+import RoomHeader from '../containers/RoomHeader';
+import { withTheme } from '../theme';
+import SearchHeader from './ThreadMessagesView/SearchHeader';
+import log, { events, logEvent } from '../utils/log';
+import database from '../lib/database';
+import { getUserSelector } from '../selectors/login';
+import { getHeaderTitlePosition } from '../containers/Header';
+import * as HeaderButton from '../containers/HeaderButton';
+import BackgroundContainer from '../containers/BackgroundContainer';
+import SafeAreaView from '../containers/SafeAreaView';
+import ActivityIndicator from '../containers/ActivityIndicator';
+import RoomItem, { ROW_HEIGHT } from '../presentation/RoomItem';
+import RocketChat from '../lib/rocketchat';
+import { withDimensions } from '../dimensions';
+import { isIOS } from '../utils/deviceInfo';
+import { themes } from '../constants/colors';
+import debounce from '../utils/debounce';
+import { showErrorAlert } from '../utils/info';
+import { goRoom } from '../utils/goRoom';
+import I18n from '../i18n';
+
+const API_FETCH_COUNT = 50;
+
+const getItemLayout = (data, index) => ({
+ length: data.length,
+ offset: ROW_HEIGHT * index,
+ index
+});
+const keyExtractor = item => item._id;
+
+class TeamChannelsView extends React.Component {
+ static propTypes = {
+ route: PropTypes.object,
+ navigation: PropTypes.object,
+ isMasterDetail: PropTypes.bool,
+ insets: PropTypes.object,
+ theme: PropTypes.string,
+ useRealName: PropTypes.bool,
+ width: PropTypes.number,
+ StoreLastMessage: PropTypes.bool
+ }
+
+ constructor(props) {
+ super(props);
+ this.teamId = props.route.params?.teamId;
+ this.state = {
+ loading: true,
+ loadingMore: false,
+ data: [],
+ total: -1,
+ isSearching: false,
+ searchText: '',
+ search: []
+ };
+ this.loadTeam();
+ }
+
+ componentDidMount() {
+ this.load();
+ }
+
+ loadTeam = async() => {
+ const db = database.active;
+ try {
+ const subCollection = db.get('subscriptions');
+ this.teamChannels = await subCollection.query(
+ Q.where('team_id', Q.eq(this.teamId))
+ );
+ this.team = this.teamChannels?.find(channel => channel.teamMain);
+ this.setHeader();
+
+ if (!this.team) {
+ throw new Error();
+ }
+ } catch {
+ const { navigation } = this.props;
+ navigation.pop();
+ showErrorAlert(I18n.t('Team_not_found'));
+ }
+ }
+
+ load = debounce(async() => {
+ const {
+ loadingMore, total, data, search, isSearching, searchText
+ } = this.state;
+
+ const length = isSearching ? search.length : data.length;
+ if (loadingMore || length === total) {
+ return;
+ }
+
+ this.setState({ loadingMore: true });
+ try {
+ const result = await RocketChat.getTeamListRoom({
+ teamId: this.teamId,
+ offset: length,
+ count: API_FETCH_COUNT,
+ type: 'all',
+ filter: searchText
+ });
+
+ if (result.success) {
+ const newState = {
+ loading: false,
+ loadingMore: false,
+ total: result.total
+ };
+ const rooms = result.rooms.map((room) => {
+ const record = this.teamChannels?.find(c => c.rid === room._id);
+ return record ?? room;
+ });
+ if (isSearching) {
+ newState.search = [...search, ...rooms];
+ } else {
+ newState.data = [...data, ...rooms];
+ }
+
+ this.setState(newState);
+ } else {
+ this.setState({ loading: false, loadingMore: false });
+ }
+ } catch (e) {
+ log(e);
+ this.setState({ loading: false, loadingMore: false });
+ }
+ }, 300)
+
+ getHeader = () => {
+ const { isSearching } = this.state;
+ const {
+ navigation, isMasterDetail, insets, theme
+ } = this.props;
+
+ const { team } = this;
+ if (!team) {
+ return;
+ }
+
+ const headerTitlePosition = getHeaderTitlePosition({ insets, numIconsRight: 1 });
+
+ if (isSearching) {
+ return {
+ headerTitleAlign: 'left',
+ headerLeft: () => (
+
+
+
+ ),
+ headerTitle: () => ,
+ headerTitleContainerStyle: {
+ left: headerTitlePosition.left,
+ right: headerTitlePosition.right
+ },
+ headerRight: () => null
+ };
+ }
+
+ const options = {
+ headerShown: true,
+ headerTitleAlign: 'left',
+ headerTitleContainerStyle: {
+ left: headerTitlePosition.left,
+ right: headerTitlePosition.right
+ },
+ headerTitle: () => (
+
+ )
+ };
+
+ if (isMasterDetail) {
+ options.headerLeft = () => ;
+ } else {
+ options.headerLeft = () => (
+ navigation.pop()}
+ tintColor={themes[theme].headerTintColor}
+ />
+ );
+ }
+
+ options.headerRight = () => (
+
+
+
+ );
+ return options;
+ }
+
+ setHeader = () => {
+ const { navigation } = this.props;
+ const options = this.getHeader();
+ navigation.setOptions(options);
+ }
+
+ onSearchPress = () => {
+ logEvent(events.TC_SEARCH);
+ this.setState({ isSearching: true }, () => this.setHeader());
+ }
+
+ onSearchChangeText = debounce((searchText) => {
+ this.setState({
+ searchText, search: [], loading: !!searchText, loadingMore: false, total: -1
+ }, () => {
+ if (searchText) {
+ this.load();
+ }
+ });
+ }, 300)
+
+ onCancelSearchPress = () => {
+ logEvent(events.TC_CANCEL_SEARCH);
+ const { isSearching } = this.state;
+ if (!isSearching) {
+ return;
+ }
+ Keyboard.dismiss();
+ this.setState({ isSearching: false, search: [] }, () => {
+ this.setHeader();
+ });
+ };
+
+ goRoomActionsView = (screen) => {
+ logEvent(events.TC_GO_ACTIONS);
+ const { team } = this;
+ const {
+ navigation, isMasterDetail
+ } = this.props;
+ if (isMasterDetail) {
+ navigation.navigate('ModalStackNavigator', {
+ screen: screen ?? 'RoomActionsView',
+ params: {
+ rid: team.rid, t: team.t, room: team, showCloseModal: false
+ }
+ });
+ } else {
+ navigation.navigate('RoomActionsView', {
+ rid: team.rid, t: team.t, room: team
+ });
+ }
+ }
+
+ getRoomTitle = item => RocketChat.getRoomTitle(item)
+
+ getRoomAvatar = item => RocketChat.getRoomAvatar(item)
+
+ onPressItem = debounce(async(item) => {
+ logEvent(events.TC_GO_ROOM);
+ const { navigation, isMasterDetail } = this.props;
+ try {
+ let params = {};
+ if (item.rid) {
+ params = item;
+ } else {
+ const { room } = await RocketChat.getRoomInfo(item._id);
+ params = {
+ rid: item._id, name: RocketChat.getRoomTitle(room), joinCodeRequired: room.joinCodeRequired, t: room.t, teamId: room.teamId
+ };
+ }
+ if (isMasterDetail) {
+ navigation.pop();
+ }
+ goRoom({ item: params, isMasterDetail, navigationMethod: navigation.push });
+ } catch (e) {
+ // do nothing
+ }
+ }, 1000, true);
+
+ renderItem = ({ item }) => {
+ const {
+ StoreLastMessage,
+ useRealName,
+ theme,
+ width
+ } = this.props;
+ return (
+
+ );
+ };
+
+ renderFooter = () => {
+ const { loadingMore } = this.state;
+ const { theme } = this.props;
+ if (loadingMore) {
+ return ;
+ }
+ return null;
+ }
+
+ renderScroll = () => {
+ const {
+ loading, data, search, isSearching, searchText
+ } = this.state;
+ if (loading) {
+ return ;
+ }
+ if (isSearching && !search.length) {
+ return ;
+ }
+ if (!isSearching && !data.length) {
+ return ;
+ }
+
+ return (
+ this.load()}
+ onEndReachedThreshold={0.5}
+ ListFooterComponent={this.renderFooter}
+ />
+ );
+ };
+
+ render() {
+ console.count(`${ this.constructor.name }.render calls`);
+ return (
+
+
+ {this.renderScroll()}
+
+ );
+ }
+}
+
+const mapStateToProps = state => ({
+ baseUrl: state.server.server,
+ user: getUserSelector(state),
+ useRealName: state.settings.UI_Use_Real_Name,
+ isMasterDetail: state.app.isMasterDetail,
+ StoreLastMessage: state.settings.Store_Last_Message
+});
+
+export default connect(mapStateToProps)(withDimensions(withSafeAreaInsets(withTheme(TeamChannelsView))));
diff --git a/app/views/ThreadMessagesView/index.js b/app/views/ThreadMessagesView/index.js
index 417c1032..48cab9c9 100644
--- a/app/views/ThreadMessagesView/index.js
+++ b/app/views/ThreadMessagesView/index.js
@@ -28,7 +28,7 @@ import * as List from '../../containers/List';
import Dropdown from './Dropdown';
import DropdownItemHeader from './Dropdown/DropdownItemHeader';
import { FILTER } from './filters';
-import NoDataFound from './NoDataFound';
+import BackgroundContainer from '../../containers/BackgroundContainer';
import { isIOS } from '../../utils/deviceInfo';
import { getBadgeColor, makeThreadName } from '../../utils/room';
import { getHeaderTitlePosition } from '../../containers/Header';
@@ -463,7 +463,7 @@ class ThreadMessagesView extends React.Component {
return (
<>
{this.renderHeader()}
-
+
>
);
}
diff --git a/e2e/tests/assorted/02-broadcast.spec.js b/e2e/tests/assorted/02-broadcast.spec.js
index 9e87c5e1..97e5783c 100644
--- a/e2e/tests/assorted/02-broadcast.spec.js
+++ b/e2e/tests/assorted/02-broadcast.spec.js
@@ -32,7 +32,7 @@ describe('Broadcast room', () => {
await element(by.id('create-channel-submit')).tap();
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(60000);
await waitFor(element(by.id(`room-view-title-broadcast${ data.random }`))).toBeVisible().withTimeout(60000);
- await element(by.id('room-view-header-actions')).tap();
+ await element(by.id('room-header')).tap();
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
await element(by.id('room-actions-info')).tap();
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
diff --git a/e2e/tests/assorted/05-joinpublicroom.spec.js b/e2e/tests/assorted/05-joinpublicroom.spec.js
index 90707f9f..1cf9a7fd 100644
--- a/e2e/tests/assorted/05-joinpublicroom.spec.js
+++ b/e2e/tests/assorted/05-joinpublicroom.spec.js
@@ -15,7 +15,7 @@ async function navigateToRoom() {
}
async function navigateToRoomActions() {
- await element(by.id('room-view-header-actions')).tap();
+ await element(by.id('room-header')).tap();
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
}
@@ -39,7 +39,7 @@ describe('Join public room', () => {
// Render - Header
describe('Header', async() => {
it('should have actions button ', async() => {
- await expect(element(by.id('room-view-header-actions'))).toBeVisible();
+ await expect(element(by.id('room-header'))).toBeVisible();
});
});
diff --git a/e2e/tests/assorted/08-joinprotectedroom.spec.js b/e2e/tests/assorted/08-joinprotectedroom.spec.js
index 32b23e9b..965af00a 100644
--- a/e2e/tests/assorted/08-joinprotectedroom.spec.js
+++ b/e2e/tests/assorted/08-joinprotectedroom.spec.js
@@ -16,7 +16,7 @@ async function navigateToRoom() {
}
async function navigateToRoomActions() {
- await element(by.id('room-view-header-actions')).tap();
+ await element(by.id('room-header')).tap();
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
}
diff --git a/e2e/tests/room/02-room.spec.js b/e2e/tests/room/02-room.spec.js
index 228c340b..e5fb4292 100644
--- a/e2e/tests/room/02-room.spec.js
+++ b/e2e/tests/room/02-room.spec.js
@@ -30,7 +30,7 @@ describe('Room screen', () => {
// Render - Header
describe('Header', async() => {
it('should have actions button ', async() => {
- await expect(element(by.id('room-view-header-actions'))).toExist();
+ await expect(element(by.id('room-header'))).toExist();
});
it('should have threads button ', async() => {
diff --git a/e2e/tests/room/03-roomactions.spec.js b/e2e/tests/room/03-roomactions.spec.js
index 74b3114b..494a8e39 100644
--- a/e2e/tests/room/03-roomactions.spec.js
+++ b/e2e/tests/room/03-roomactions.spec.js
@@ -16,7 +16,7 @@ async function navigateToRoomActions(type) {
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000);
await element(by.id(`rooms-list-view-item-${ room }`)).tap();
await waitFor(element(by.id('room-view'))).toExist().withTimeout(2000);
- await element(by.id('room-view-header-actions')).tap();
+ await element(by.id('room-header')).tap();
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
}
@@ -218,7 +218,7 @@ describe('Room actions screen', () => {
await starMessage('messageToStar')
//Back into Room Actions
- await element(by.id('room-view-header-actions')).tap();
+ await element(by.id('room-header')).tap();
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
//Go to starred messages
@@ -246,7 +246,7 @@ describe('Room actions screen', () => {
await pinMessage('messageToPin')
//Back into Room Actions
- await element(by.id('room-view-header-actions')).tap();
+ await element(by.id('room-header')).tap();
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
await element(by.type('UIScrollView')).atIndex(1).scrollTo('bottom');
await waitFor(element(by.id('room-actions-pinned'))).toExist();
@@ -270,7 +270,7 @@ describe('Room actions screen', () => {
await mockMessage('messageToFind');
//Back into Room Actions
- await element(by.id('room-view-header-actions')).tap();
+ await element(by.id('room-header')).tap();
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
await element(by.id('room-actions-search')).tap();
@@ -499,7 +499,7 @@ describe('Room actions screen', () => {
});
it('should navigate to direct message', async() => {
- await element(by.id('room-view-header-actions')).tap();
+ await element(by.id('room-header')).tap();
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
await element(by.id('room-actions-members')).tap();
await waitFor(element(by.id('room-members-view'))).toExist().withTimeout(2000);
diff --git a/e2e/tests/room/04-discussion.spec.js b/e2e/tests/room/04-discussion.spec.js
index 55ee40ab..d1686840 100644
--- a/e2e/tests/room/04-discussion.spec.js
+++ b/e2e/tests/room/04-discussion.spec.js
@@ -74,8 +74,8 @@ describe('Discussion', () => {
describe('Check RoomActionsView render', async() => {
it('should navigete to RoomActionsView', async() => {
- await waitFor(element(by.id('room-view-header-actions'))).toBeVisible().withTimeout(5000);
- await element(by.id('room-view-header-actions')).tap();
+ await waitFor(element(by.id('room-header'))).toBeVisible().withTimeout(5000);
+ await element(by.id('room-header')).tap();
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
});
diff --git a/e2e/tests/room/05-threads.spec.js b/e2e/tests/room/05-threads.spec.js
index 349c5d6d..1b7c64b8 100644
--- a/e2e/tests/room/05-threads.spec.js
+++ b/e2e/tests/room/05-threads.spec.js
@@ -30,7 +30,7 @@ describe('Threads', () => {
// Render - Header
describe('Header', async() => {
it('should have actions button ', async() => {
- await expect(element(by.id('room-view-header-actions'))).toExist();
+ await expect(element(by.id('room-header'))).toExist();
});
it('should have threads button ', async() => {
@@ -105,8 +105,8 @@ describe('Threads', () => {
const messageText = 'threadonly';
await mockMessage(messageText);
await tapBack();
- await waitFor(element(by.id('room-view-header-actions').and(by.label(`${ mainRoom }`)))).toBeVisible().withTimeout(2000);
- await waitFor(element(by.id('room-view-header-actions').and(by.label(`${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
+ await waitFor(element(by.id('room-header').and(by.label(`${ mainRoom }`)))).toBeVisible().withTimeout(2000);
+ await waitFor(element(by.id('room-header').and(by.label(`${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
await sleep(500) //TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :(
await waitFor(element(by.label(`${ data.random }${ messageText }`)).atIndex(0)).toNotExist().withTimeout(2000);
});
@@ -118,8 +118,8 @@ describe('Threads', () => {
await element(by.id('messagebox-send-to-channel')).tap();
await element(by.id('messagebox-send-message')).tap();
await tapBack();
- await waitFor(element(by.id('room-view-header-actions').and(by.label(`${ mainRoom }`)))).toBeVisible().withTimeout(2000);
- await waitFor(element(by.id('room-view-header-actions').and(by.label(`${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
+ await waitFor(element(by.id('room-header').and(by.label(`${ mainRoom }`)))).toBeVisible().withTimeout(2000);
+ await waitFor(element(by.id('room-header').and(by.label(`${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
await sleep(500) //TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :(
await waitFor(element(by.label(messageText)).atIndex(0)).toExist().withTimeout(2000);
});
@@ -133,8 +133,8 @@ describe('Threads', () => {
await element(by.id('messagebox-send-to-channel')).tap();
await element(by.id('messagebox-send-message')).tap();
await tapBack();
- await waitFor(element(by.id('room-view-header-actions').and(by.label(`${ mainRoom }`)))).toBeVisible().withTimeout(2000);
- await waitFor(element(by.id('room-view-header-actions').and(by.label(`${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
+ await waitFor(element(by.id('room-header').and(by.label(`${ mainRoom }`)))).toBeVisible().withTimeout(2000);
+ await waitFor(element(by.id('room-header').and(by.label(`${ data.random }thread`)))).toBeNotVisible().withTimeout(2000);
await sleep(500) //TODO: Find a better way to wait for the animation to finish and the messagebox-input to be available and usable :(
await element(by.id(`message-thread-replied-on-${ thread }`)).tap();
diff --git a/e2e/tests/room/08-roominfo.spec.js b/e2e/tests/room/08-roominfo.spec.js
index 9fd9aebb..b172935c 100644
--- a/e2e/tests/room/08-roominfo.spec.js
+++ b/e2e/tests/room/08-roominfo.spec.js
@@ -17,7 +17,7 @@ async function navigateToRoomInfo(type) {
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(60000);
await element(by.id(`rooms-list-view-item-${ room }`)).tap();
await waitFor(element(by.id('room-view'))).toExist().withTimeout(2000);
- await element(by.id('room-view-header-actions')).tap();
+ await element(by.id('room-header')).tap();
await waitFor(element(by.id('room-actions-view'))).toExist().withTimeout(5000);
await element(by.id('room-actions-info')).tap();
await waitFor(element(by.id('room-info-view'))).toExist().withTimeout(2000);
diff --git a/storybook/stories/RoomViewHeader.js b/storybook/stories/RoomViewHeader.js
deleted file mode 100644
index cce19f67..00000000
--- a/storybook/stories/RoomViewHeader.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import React from 'react';
-import { ScrollView, View, StyleSheet } from 'react-native';
-import { HeaderBackButton } from '@react-navigation/stack';
-
-import HeaderComponent from '../../app/views/RoomView/Header/Header';
-// import { CustomHeaderButtons, Item } from '../../app/containers/HeaderButton';
-import StoriesSeparator from './StoriesSeparator';
-import { isIOS } from '../../app/utils/deviceInfo';
-import { themes } from '../../app/constants/colors';
-
-let _theme = 'light';
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- flexDirection: 'row',
- height: isIOS ? 44 : 56,
- borderTopWidth: 1,
- borderBottomWidth: 1,
- marginVertical: 6
- }
-});
-
-const Header = props => (
-
-
-
- {/* not working because we use withTheme */}
- {/*
-
-
-
-
- */}
-
-);
-
-// eslint-disable-next-line react/prop-types
-export default ({ theme }) => {
- _theme = theme;
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/storybook/stories/index.js b/storybook/stories/index.js
index 8edb159b..cd84085c 100644
--- a/storybook/stories/index.js
+++ b/storybook/stories/index.js
@@ -14,6 +14,8 @@ import Markdown from './Markdown';
import './HeaderButtons';
import './UnreadBadge';
import '../../app/views/ThreadMessagesView/Item.stories.js';
+import '../../app/containers/BackgroundContainer/index.stories.js';
+import '../../app/containers/RoomHeader/RoomHeader.stories.js';
import Avatar from './Avatar';
// import RoomViewHeader from './RoomViewHeader';