Skip to content

Commit

Permalink
[IMPROVEMENT] User status icons (#2991)
Browse files Browse the repository at this point in the history
* Add status and teams

* Update icons, icon size and getUsersPresence

* Minor changes

* Refactor RoomTypeIcon

* Minor tweaks

* Update unit tests

* Minor fixes

* Fix styles

* Small refactor

* Update jest

Co-authored-by: Diego Mello <diegolmello@gmail.com>
  • Loading branch information
gerzonc and diegolmello authored Mar 31, 2021
1 parent 8bc8a07 commit 25b7115
Show file tree
Hide file tree
Showing 26 changed files with 1,465 additions and 549 deletions.
1,702 changes: 1,345 additions & 357 deletions __tests__/__snapshots__/Storyshots.test.js.snap

Large diffs are not rendered by default.

Binary file modified android/app/src/main/assets/fonts/custom.ttf
Binary file not shown.
3 changes: 2 additions & 1 deletion app/constants/colors.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ export const STATUS_COLORS = {
online: '#2de0a5',
busy: '#f5455c',
away: '#ffd21f',
offline: '#cbced1'
offline: '#cbced1',
loading: '#9ea2a8'
};

export const SWITCH_TRACK_COLOR = {
Expand Down
24 changes: 15 additions & 9 deletions app/containers/RoomTypeIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
import { CustomIcon } from '../lib/Icons';
import { STATUS_COLORS, themes } from '../constants/colors';
import Status from './Status/Status';
import { withTheme } from '../theme';

const styles = StyleSheet.create({
icon: {
marginTop: 3,
marginRight: 4
}
});
Expand All @@ -18,7 +19,16 @@ const RoomTypeIcon = React.memo(({
return null;
}

const color = themes[theme].auxiliaryText;
const color = themes[theme].titleText;
const iconStyle = [
styles.icon,
{ color },
style
];

if (type === 'd' && !isGroupChat) {
return <Status style={[iconStyle, { color: STATUS_COLORS[status] ?? STATUS_COLORS.offline }]} size={size} status={status} />;
}

let icon = 'channel-private';
if (type === 'discussion') {
Expand All @@ -27,7 +37,7 @@ const RoomTypeIcon = React.memo(({
icon = 'channel-public';
} else if (type === 'd') {
if (isGroupChat) {
icon = 'team';
icon = 'message';
} else {
icon = 'mention';
}
Expand All @@ -39,11 +49,7 @@ const RoomTypeIcon = React.memo(({
<CustomIcon
name={icon}
size={size}
style={[
type === 'l' && status ? { color: STATUS_COLORS[status] } : { color },
styles.icon,
style
]}
style={iconStyle}
/>
);
});
Expand All @@ -61,4 +67,4 @@ RoomTypeIcon.defaultProps = {
size: 16
};

export default RoomTypeIcon;
export default withTheme(RoomTypeIcon);
47 changes: 24 additions & 23 deletions app/containers/Status/Status.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
import React from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';
import { STATUS_COLORS, themes } from '../../constants/colors';
import { CustomIcon } from '../../lib/Icons';
import { STATUS_COLORS } from '../../constants/colors';

const Status = React.memo(({
status, size, style, theme, ...props
}) => (
<View
style={
[
style,
{
borderRadius: size,
width: size,
height: size,
backgroundColor: STATUS_COLORS[status] ?? STATUS_COLORS.offline,
borderColor: themes[theme].backgroundColor
}
]}
{...props}
/>
));
status, size, style, ...props
}) => {
const name = `status-${ status }`;
const isNameValid = CustomIcon.hasIcon(name);
const iconName = isNameValid ? name : 'status-offline';
const calculatedStyle = [{
width: size, height: size, textAlignVertical: 'center'
}, style];

return (
<CustomIcon
style={calculatedStyle}
size={size}
name={iconName}
color={STATUS_COLORS[status] ?? STATUS_COLORS.offline}
{...props}
/>
);
});

Status.propTypes = {
status: PropTypes.string,
size: PropTypes.number,
style: PropTypes.any,
theme: PropTypes.string
style: PropTypes.any
};
Status.defaultProps = {
status: 'offline',
size: 16,
theme: 'light'
size: 32
};

export default Status;
31 changes: 9 additions & 22 deletions app/containers/Status/index.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,19 @@
import React from 'react';
import React, { memo } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

import Status from './Status';
import { withTheme } from '../../theme';

class StatusContainer extends React.PureComponent {
static propTypes = {
style: PropTypes.any,
size: PropTypes.number,
status: PropTypes.string,
theme: PropTypes.string
};
const StatusContainer = memo(({ style, size = 32, status }) => <Status size={size} style={style} status={status} />);

static defaultProps = {
size: 16
}

render() {
const {
style, size, status, theme
} = this.props;
return <Status size={size} style={style} status={status} theme={theme} />;
}
}
StatusContainer.propTypes = {
style: PropTypes.any,
size: PropTypes.number,
status: PropTypes.string
};

const mapStateToProps = (state, ownProps) => ({
status: state.meteor.connected ? (state.activeUsers[ownProps.id] && state.activeUsers[ownProps.id].status) : 'offline'
status: state.meteor.connected ? (state.activeUsers[ownProps.id] && state.activeUsers[ownProps.id].status) : 'loading'
});

export default connect(mapStateToProps)(withTheme(StatusContainer));
export default connect(mapStateToProps)(StatusContainer);
5 changes: 3 additions & 2 deletions app/lib/methods/getUsersPresence.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ export default async function getUsersPresence() {
if (result.success) {
const { users } = result;

const activeUsers = users.reduce((ret, item) => {
const { _id, status, statusText } = item;
const activeUsers = ids.reduce((ret, id) => {
const user = users.find(u => u._id === id) ?? { _id: id, status: 'offline' };
const { _id, status, statusText } = user;

if (loggedUser && loggedUser.id === _id) {
reduxStore.dispatch(setUser({ status, statusText }));
Expand Down
2 changes: 1 addition & 1 deletion app/lib/selection.json

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions app/presentation/RoomItem/RoomItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ const RoomItem = ({
prid={prid}
status={status}
isGroupChat={isGroupChat}
theme={theme}
/>
<Title
name={name}
Expand Down Expand Up @@ -121,7 +120,6 @@ const RoomItem = ({
prid={prid}
status={status}
isGroupChat={isGroupChat}
theme={theme}
/>
<Title
name={name}
Expand Down
12 changes: 2 additions & 10 deletions app/presentation/RoomItem/TypeIcon.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
import React from 'react';
import PropTypes from 'prop-types';

import Status from '../../containers/Status/Status';
import RoomTypeIcon from '../../containers/RoomTypeIcon';
import styles from './styles';

const TypeIcon = React.memo(({
theme, type, prid, status, isGroupChat
}) => {
if (type === 'd' && !isGroupChat) {
return <Status style={styles.status} size={10} status={status} />;
}
return <RoomTypeIcon theme={theme} type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} />;
});
type, prid, status, isGroupChat
}) => <RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} />);

TypeIcon.propTypes = {
theme: PropTypes.string,
type: PropTypes.string,
status: PropTypes.string,
prid: PropTypes.string,
Expand Down
4 changes: 2 additions & 2 deletions app/presentation/RoomItem/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,11 @@ class RoomItemContainer extends React.Component {
}

const mapStateToProps = (state, ownProps) => {
let status = 'offline';
let status = 'loading';
const { id, type, visitor = {} } = ownProps;
if (state.meteor.connected) {
if (type === 'd') {
status = state.activeUsers[id]?.status || 'offline';
status = state.activeUsers[id]?.status || 'loading';
} else if (type === 'l' && visitor?.status) {
({ status } = visitor);
}
Expand Down
4 changes: 1 addition & 3 deletions app/presentation/RoomItem/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,7 @@ export default StyleSheet.create({
...sharedStyles.textSemibold
},
status: {
marginLeft: 4,
marginRight: 7,
marginTop: 3
marginRight: 2
},
markdownText: {
flex: 1,
Expand Down
10 changes: 8 additions & 2 deletions app/views/RoomActionsView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,14 +448,20 @@ class RoomActionsView extends React.Component {
type={t}
rid={rid}
>
{t === 'd' && member._id ? <Status style={sharedStyles.status} id={member._id} /> : null }
{t === 'd' && member._id
? (
<View style={[sharedStyles.status, { backgroundColor: themes[theme].backgroundColor }]}>
<Status size={16} id={member._id} />
</View>
) : null
}
</Avatar>
<View style={styles.roomTitleContainer}>
{room.t === 'd'
? <Text style={[styles.roomTitle, { color: themes[theme].titleText }]} numberOfLines={1}>{room.fname}</Text>
: (
<View style={styles.roomTitleRow}>
<RoomTypeIcon type={room.prid ? 'discussion' : room.t} status={room.visitor?.status} theme={theme} />
<RoomTypeIcon type={room.prid ? 'discussion' : room.t} status={room.visitor?.status} />
<Text style={[styles.roomTitle, { color: themes[theme].titleText }]} numberOfLines={1}>{RocketChat.getRoomTitle(room)}</Text>
</View>
)
Expand Down
10 changes: 8 additions & 2 deletions app/views/RoomInfoView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const getRoomTitle = (room, type, name, username, statusText, theme) => (type ==
)
: (
<View style={styles.roomTitleRow}>
<RoomTypeIcon type={room.prid ? 'discussion' : room.t} key='room-info-type' status={room.visitor?.status} theme={theme} />
<RoomTypeIcon type={room.prid ? 'discussion' : room.t} key='room-info-type' status={room.visitor?.status} />
<Text testID='room-info-view-name' style={[styles.roomTitle, { color: themes[theme].titleText }]} key='room-info-name'>{RocketChat.getRoomTitle(room)}</Text>
</View>
)
Expand Down Expand Up @@ -290,7 +290,13 @@ class RoomInfoView extends React.Component {
size={100}
rid={room?.rid}
>
{this.t === 'd' && roomUser._id ? <Status style={[sharedStyles.status, styles.status]} theme={theme} size={24} id={roomUser._id} /> : null}
{this.t === 'd' && roomUser._id
? (
<View style={[sharedStyles.status, { backgroundColor: themes[theme].auxiliaryBackground }]}>
<Status size={20} id={roomUser._id} />
</View>
)
: null}
</Avatar>
);
}
Expand Down
5 changes: 0 additions & 5 deletions app/views/RoomInfoView/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ export default StyleSheet.create({
flexDirection: 'row',
alignItems: 'center'
},
status: {
borderWidth: 4,
bottom: -4,
right: -4
},
itemLabel: {
marginBottom: 10,
fontSize: 14,
Expand Down
16 changes: 5 additions & 11 deletions app/views/RoomView/Header/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import {

import I18n from '../../../i18n';
import sharedStyles from '../../Styles';
import Icon from './Icon';
import { themes } from '../../../constants/colors';
import Markdown from '../../../containers/markdown';
import RoomTypeIcon from '../../../containers/RoomTypeIcon';

const HIT_SLOP = {
top: 5, right: 5, bottom: 5, left: 5
Expand Down Expand Up @@ -119,7 +119,7 @@ HeaderTitle.propTypes = {
};

const Header = React.memo(({
title, subtitle, parentTitle, type, status, usersTyping, width, height, prid, tmid, connecting, goRoomActionsView, roomUserId, theme
title, subtitle, parentTitle, type, status, usersTyping, width, height, prid, tmid, connecting, goRoomActionsView, theme, isGroupChat
}) => {
const portrait = height > width;
let scale = 1;
Expand All @@ -136,13 +136,7 @@ const Header = React.memo(({
if (tmid) {
renderFunc = () => (
<View style={styles.titleContainer}>
<Icon
type={prid ? 'discussion' : type}
tmid={tmid}
status={status}
roomUserId={roomUserId}
theme={theme}
/>
<RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} />
<Text style={[styles.subtitle, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>{parentTitle}</Text>
</View>
);
Expand All @@ -158,7 +152,7 @@ const Header = React.memo(({
hitSlop={HIT_SLOP}
>
<View style={styles.titleContainer}>
{tmid ? null : <Icon type={prid ? 'discussion' : type} status={status} roomUserId={roomUserId} theme={theme} />}
{tmid ? null : <RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} />}
<HeaderTitle
title={title}
tmid={tmid}
Expand All @@ -185,7 +179,7 @@ Header.propTypes = {
theme: PropTypes.string,
usersTyping: PropTypes.array,
connecting: PropTypes.bool,
roomUserId: PropTypes.string,
isGroupChat: PropTypes.bool,
parentTitle: PropTypes.string,
goRoomActionsView: PropTypes.func
};
Expand Down
Loading

0 comments on commit 25b7115

Please sign in to comment.