PLT-5488 Add an Unread indicator on the button to open the channel drawer (#277)
* Unread indicator in burger button * Set badge to always be red
This commit is contained in:
parent
3eb7e377cf
commit
d0209aa8c3
3 changed files with 92 additions and 16 deletions
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {View, Text, StyleSheet} from 'react-native';
|
||||
import React, {PropTypes, PureComponent} from 'react';
|
||||
import {View, Text, TouchableWithoutFeedback, StyleSheet} from 'react-native';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
|
@ -20,20 +20,22 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
export default class Badge extends React.Component {
|
||||
export default class Badge extends PureComponent {
|
||||
static defaultProps = {
|
||||
extraPaddingHorizontal: 10,
|
||||
minHeight: 0,
|
||||
minWidth: 0
|
||||
minWidth: 0,
|
||||
onPress: () => true
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
count: React.PropTypes.number.isRequired,
|
||||
extraPaddingHorizontal: React.PropTypes.number,
|
||||
count: PropTypes.number.isRequired,
|
||||
extraPaddingHorizontal: PropTypes.number,
|
||||
style: View.propTypes.style,
|
||||
countStyle: Text.propTypes.style,
|
||||
minHeight: React.PropTypes.number,
|
||||
minWidth: React.PropTypes.number
|
||||
minHeight: PropTypes.number,
|
||||
minWidth: PropTypes.number,
|
||||
onPress: PropTypes.func
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
|
|
@ -42,16 +44,25 @@ export default class Badge extends React.Component {
|
|||
}
|
||||
|
||||
renderText = () => {
|
||||
const {count} = this.props;
|
||||
let text = count.toString();
|
||||
if (count < 0) {
|
||||
text = '•';
|
||||
}
|
||||
return (
|
||||
<Text
|
||||
onLayout={this.onLayout}
|
||||
style={[styles.text, this.props.countStyle]}
|
||||
>
|
||||
{this.props.count}
|
||||
{text}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
badgeRef = (ref) => {
|
||||
this.container = ref;
|
||||
};
|
||||
|
||||
onLayout = (e) => {
|
||||
let width;
|
||||
|
||||
|
|
@ -81,12 +92,14 @@ export default class Badge extends React.Component {
|
|||
render() {
|
||||
return (
|
||||
<View
|
||||
ref={(component) => {
|
||||
this.container = component;
|
||||
}}
|
||||
ref={this.badgeRef}
|
||||
style={[styles.container, this.props.style]}
|
||||
>
|
||||
{this.renderText()}
|
||||
<TouchableWithoutFeedback onPress={this.props.onPress}>
|
||||
<View>
|
||||
{this.renderText()}
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,44 @@ import {
|
|||
View
|
||||
} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||
import Badge from 'app/components/badge';
|
||||
|
||||
import {getUnreads} from 'service/selectors/entities/channels';
|
||||
import {getTheme} from 'service/selectors/entities/preferences';
|
||||
|
||||
function ChannelDrawerButton(props) {
|
||||
let badge;
|
||||
let badgeCount = props.mentionCount;
|
||||
if (!badgeCount && props.messageCount) {
|
||||
badgeCount = -1;
|
||||
}
|
||||
|
||||
if (badgeCount !== 0) {
|
||||
const badgeStyle = {
|
||||
position: 'absolute',
|
||||
top: 5,
|
||||
left: 5,
|
||||
flexDirection: 'row',
|
||||
backgroundColor: 'rgb(214, 73, 70)'
|
||||
};
|
||||
|
||||
const mentionStyle = {
|
||||
color: '#fff',
|
||||
fontSize: 12
|
||||
};
|
||||
|
||||
badge = (
|
||||
<Badge
|
||||
style={badgeStyle}
|
||||
countStyle={mentionStyle}
|
||||
count={badgeCount}
|
||||
minHeight={5}
|
||||
minWidth={5}
|
||||
onPress={() => props.emitter('open_channel_drawer')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={{flexDirection: 'column', justifyContent: 'center', alignItems: 'center', flex: 1}}>
|
||||
<TouchableOpacity
|
||||
|
|
@ -24,23 +58,29 @@ function ChannelDrawerButton(props) {
|
|||
color={props.theme.sidebarHeaderTextColor}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
{badge}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
ChannelDrawerButton.propTypes = {
|
||||
emitter: PropTypes.func.isRequired,
|
||||
theme: PropTypes.object
|
||||
theme: PropTypes.object,
|
||||
messageCount: PropTypes.number,
|
||||
mentionCount: PropTypes.number
|
||||
};
|
||||
|
||||
ChannelDrawerButton.defaultProps = {
|
||||
currentChannel: {},
|
||||
theme: {}
|
||||
theme: {},
|
||||
messageCount: 0,
|
||||
mentionCount: 0
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
theme: getTheme(state)
|
||||
theme: getTheme(state),
|
||||
...getUnreads(state)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -101,3 +101,26 @@ export const getMoreChannels = createSelector(
|
|||
return getNotMemberChannels(Object.values(allChannels), myMembers);
|
||||
}
|
||||
);
|
||||
|
||||
export const getUnreads = createSelector(
|
||||
getAllChannels,
|
||||
getChannelMemberships,
|
||||
(channels, myMembers) => {
|
||||
let messageCount = 0;
|
||||
let mentionCount = 0;
|
||||
Object.keys(myMembers).forEach((id) => {
|
||||
const m = myMembers[id];
|
||||
const channel = channels[id];
|
||||
if (channel.type === 'D') {
|
||||
mentionCount += channel.total_msg_count - m.msg_count;
|
||||
} else if (m.mention_count > 0) {
|
||||
mentionCount += m.mention_count;
|
||||
}
|
||||
if (m.notify_props.mark_unread !== 'mention' && channel.total_msg_count - m.msg_count > 0) {
|
||||
messageCount += 1;
|
||||
}
|
||||
});
|
||||
|
||||
return {messageCount, mentionCount};
|
||||
}
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue