[IMPROVEMENT] User status icons (#2991)
* 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>
This commit is contained in:
parent
8bc8a07e72
commit
25b71155e6
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
});
|
||||
|
@ -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') {
|
||||
|
@ -27,7 +37,7 @@ const RoomTypeIcon = React.memo(({
|
|||
icon = 'channel-public';
|
||||
} else if (type === 'd') {
|
||||
if (isGroupChat) {
|
||||
icon = 'team';
|
||||
icon = 'message';
|
||||
} else {
|
||||
icon = 'mention';
|
||||
}
|
||||
|
@ -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}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
@ -61,4 +67,4 @@ RoomTypeIcon.defaultProps = {
|
|||
size: 16
|
||||
};
|
||||
|
||||
export default RoomTypeIcon;
|
||||
export default withTheme(RoomTypeIcon);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 }));
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -78,7 +78,6 @@ const RoomItem = ({
|
|||
prid={prid}
|
||||
status={status}
|
||||
isGroupChat={isGroupChat}
|
||||
theme={theme}
|
||||
/>
|
||||
<Title
|
||||
name={name}
|
||||
|
@ -121,7 +120,6 @@ const RoomItem = ({
|
|||
prid={prid}
|
||||
status={status}
|
||||
isGroupChat={isGroupChat}
|
||||
theme={theme}
|
||||
/>
|
||||
<Title
|
||||
name={name}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -52,9 +52,7 @@ export default StyleSheet.create({
|
|||
...sharedStyles.textSemibold
|
||||
},
|
||||
status: {
|
||||
marginLeft: 4,
|
||||
marginRight: 7,
|
||||
marginTop: 3
|
||||
marginRight: 2
|
||||
},
|
||||
markdownText: {
|
||||
flex: 1,
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -48,11 +48,6 @@ export default StyleSheet.create({
|
|||
flexDirection: 'row',
|
||||
alignItems: 'center'
|
||||
},
|
||||
status: {
|
||||
borderWidth: 4,
|
||||
bottom: -4,
|
||||
right: -4
|
||||
},
|
||||
itemLabel: {
|
||||
marginBottom: 10,
|
||||
fontSize: 14,
|
||||
|
|
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
};
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { STATUS_COLORS, themes } from '../../../constants/colors';
|
||||
import { CustomIcon } from '../../../lib/Icons';
|
||||
import Status from '../../../containers/Status/Status';
|
||||
|
||||
const ICON_SIZE = 15;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
type: {
|
||||
width: ICON_SIZE,
|
||||
height: ICON_SIZE,
|
||||
marginRight: 4,
|
||||
marginLeft: -4
|
||||
},
|
||||
status: {
|
||||
marginRight: 8
|
||||
}
|
||||
});
|
||||
|
||||
const Icon = React.memo(({
|
||||
roomUserId, type, status, theme, tmid
|
||||
}) => {
|
||||
if ((type === 'd' || tmid) && roomUserId) {
|
||||
return <Status size={10} style={styles.status} status={status} />;
|
||||
}
|
||||
|
||||
let colorStyle = {};
|
||||
if (type === 'l') {
|
||||
colorStyle = { color: STATUS_COLORS[status] };
|
||||
} else {
|
||||
colorStyle = { color: themes[theme].auxiliaryText };
|
||||
}
|
||||
|
||||
let icon;
|
||||
if (type === 'discussion') {
|
||||
icon = 'discussions';
|
||||
} else if (type === 'c') {
|
||||
icon = 'channel-public';
|
||||
} else if (type === 'l') {
|
||||
icon = 'omnichannel';
|
||||
} else if (type === 'd') {
|
||||
icon = 'team';
|
||||
} else {
|
||||
icon = 'channel-private';
|
||||
}
|
||||
return (
|
||||
<CustomIcon
|
||||
name={icon}
|
||||
size={ICON_SIZE * 1}
|
||||
style={[
|
||||
styles.type,
|
||||
{
|
||||
width: ICON_SIZE * 1,
|
||||
height: ICON_SIZE * 1
|
||||
},
|
||||
colorStyle
|
||||
]}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
Icon.propTypes = {
|
||||
roomUserId: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
status: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
tmid: PropTypes.string
|
||||
};
|
||||
export default Icon;
|
|
@ -28,7 +28,8 @@ class RoomHeaderView extends Component {
|
|||
goRoomActionsView: PropTypes.func,
|
||||
width: PropTypes.number,
|
||||
height: PropTypes.number,
|
||||
parentTitle: PropTypes.string
|
||||
parentTitle: PropTypes.string,
|
||||
isGroupChat: PropTypes.bool
|
||||
};
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
|
@ -76,7 +77,24 @@ class RoomHeaderView extends Component {
|
|||
|
||||
render() {
|
||||
const {
|
||||
title, subtitle: subtitleProp, type, prid, tmid, widthOffset, status = 'offline', statusText, connecting, connected, usersTyping, goRoomActionsView, roomUserId, theme, width, height, parentTitle
|
||||
title,
|
||||
subtitle: subtitleProp,
|
||||
type,
|
||||
prid,
|
||||
tmid,
|
||||
widthOffset,
|
||||
status = 'offline',
|
||||
statusText,
|
||||
connecting,
|
||||
connected,
|
||||
usersTyping,
|
||||
goRoomActionsView,
|
||||
roomUserId,
|
||||
theme,
|
||||
width,
|
||||
height,
|
||||
parentTitle,
|
||||
isGroupChat
|
||||
} = this.props;
|
||||
|
||||
let subtitle;
|
||||
|
@ -105,6 +123,7 @@ class RoomHeaderView extends Component {
|
|||
goRoomActionsView={goRoomActionsView}
|
||||
connecting={connecting}
|
||||
parentTitle={parentTitle}
|
||||
isGroupChat={isGroupChat}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -306,6 +306,7 @@ class RoomView extends React.Component {
|
|||
} = this.props;
|
||||
const { rid, tmid } = this;
|
||||
const prid = room?.prid;
|
||||
const isGroupChat = RocketChat.isGroupChat(room);
|
||||
let title = route.params?.name;
|
||||
let parentTitle;
|
||||
if ((room.id || room.rid) && !tmid) {
|
||||
|
@ -356,6 +357,7 @@ class RoomView extends React.Component {
|
|||
type={t}
|
||||
roomUserId={roomUserId}
|
||||
visitor={visitor}
|
||||
isGroupChat={isGroupChat}
|
||||
goRoomActionsView={this.goRoomActionsView}
|
||||
/>
|
||||
),
|
||||
|
|
|
@ -196,7 +196,7 @@ class Sidebar extends Component {
|
|||
return (
|
||||
<SidebarItem
|
||||
text={user.statusText || I18n.t('Edit_Status')}
|
||||
left={<Status style={styles.status} size={12} status={user && user.status} />}
|
||||
left={<Status size={24} status={user?.status} />}
|
||||
right={<CustomIcon name='edit' size={20} color={themes[theme].titleText} />}
|
||||
onPress={() => this.sidebarNavigate('StatusView')}
|
||||
testID='sidebar-custom-status'
|
||||
|
|
|
@ -51,9 +51,6 @@ export default StyleSheet.create({
|
|||
avatar: {
|
||||
marginHorizontal: 10
|
||||
},
|
||||
status: {
|
||||
marginRight: 5
|
||||
},
|
||||
currentServerText: {
|
||||
fontSize: 14,
|
||||
...sharedStyles.textSemibold
|
||||
|
|
|
@ -41,11 +41,11 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
inputLeft: {
|
||||
position: 'absolute',
|
||||
top: 18,
|
||||
left: 14
|
||||
top: 12,
|
||||
left: 12
|
||||
},
|
||||
inputStyle: {
|
||||
paddingLeft: 40
|
||||
paddingLeft: 48
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -140,7 +140,7 @@ class StatusView extends React.Component {
|
|||
testID={`status-view-current-${ user.status }`}
|
||||
style={styles.inputLeft}
|
||||
status={user.status}
|
||||
size={12}
|
||||
size={24}
|
||||
/>
|
||||
)}
|
||||
inputStyle={styles.inputStyle}
|
||||
|
@ -174,7 +174,7 @@ class StatusView extends React.Component {
|
|||
}
|
||||
}}
|
||||
testID={`status-view-${ id }`}
|
||||
left={() => <Status size={12} status={item.id} />}
|
||||
left={() => <Status size={24} status={item.id} />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ export default StyleSheet.create({
|
|||
},
|
||||
status: {
|
||||
position: 'absolute',
|
||||
bottom: -3,
|
||||
right: -3,
|
||||
borderWidth: 3
|
||||
bottom: -2,
|
||||
right: -2,
|
||||
borderRadius: 10
|
||||
},
|
||||
textAlignCenter: {
|
||||
textAlign: 'center'
|
||||
|
|
BIN
ios/custom.ttf
BIN
ios/custom.ttf
Binary file not shown.
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { ScrollView, StyleSheet } from 'react-native';
|
||||
import { ScrollView, StyleSheet, View } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { themes } from '../../app/constants/colors';
|
||||
|
@ -9,11 +9,6 @@ import StoriesSeparator from './StoriesSeparator';
|
|||
import sharedStyles from '../../app/views/Styles';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
status: {
|
||||
borderWidth: 4,
|
||||
bottom: -4,
|
||||
right: -4
|
||||
},
|
||||
custom: {
|
||||
padding: 16
|
||||
}
|
||||
|
@ -117,11 +112,12 @@ const AvatarStories = ({ theme }) => (
|
|||
server={server}
|
||||
size={56}
|
||||
>
|
||||
<Status
|
||||
size={24}
|
||||
style={[sharedStyles.status, styles.status]}
|
||||
theme={theme}
|
||||
/>
|
||||
<View style={[sharedStyles.status, { backgroundColor: themes[theme].backgroundColor }]}>
|
||||
<Status
|
||||
size={20}
|
||||
status='online'
|
||||
/>
|
||||
</View>
|
||||
</Avatar>
|
||||
<Separator title='Wrong server' theme={theme} />
|
||||
<Avatar
|
||||
|
|
|
@ -65,6 +65,7 @@ export default ({ theme }) => {
|
|||
<RoomItem status='away' />
|
||||
<RoomItem status='busy' />
|
||||
<RoomItem status='offline' />
|
||||
<RoomItem status='loading' />
|
||||
<RoomItem status='wrong' />
|
||||
|
||||
<Separator title='Alerts' />
|
||||
|
|
Loading…
Reference in New Issue