mattermost-mobile/app/components/channel_drawer/channel_list.js
enahum fdc9b5cc0e Bug fixes (#157)
* Fix team switch

* Fix getThemes

* Fix drawer unread indicators
2017-01-10 11:47:11 -05:00

333 lines
10 KiB
JavaScript

// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
import {StyleSheet, Text, View, ListView} from 'react-native';
import {buildDisplayNameAndTypeComparable} from 'service/utils/channel_utils';
import LineDivider from 'app/components/line_divider';
import ChannelItem from './channel_item';
import FormattedText from 'app/components/formatted_text';
import UnreadIndicator from './unread_indicator';
const Styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 20
},
scrollContainer: {
flex: 1
},
headerContainer: {
justifyContent: 'center',
flexDirection: 'column',
height: 50,
width: 300,
paddingLeft: 10
},
header: {
fontSize: 18,
fontWeight: 'bold'
},
title: {
paddingTop: 10,
paddingRight: 10,
paddingLeft: 10,
paddingBottom: 5,
fontSize: 15,
opacity: 0.6
},
indicatorText: {
paddingVertical: 2,
paddingHorizontal: 4,
backgroundColor: 'transparent',
fontSize: 14,
textAlign: 'center',
textAlignVertical: 'center'
}
});
export default class ChannelList extends React.Component {
static propTypes = {
currentTeam: React.PropTypes.object.isRequired,
currentChannel: React.PropTypes.object,
channels: React.PropTypes.object.isRequired,
channelMembers: React.PropTypes.object,
theme: React.PropTypes.object.isRequired,
onSelectChannel: React.PropTypes.func.isRequired,
onViewChannel: React.PropTypes.func.isRequired,
closeChannelDrawer: React.PropTypes.func.isRequired
};
constructor(props) {
super(props);
this.firstUnreadChannel = null;
this.lastUnreadChannel = null;
this.state = {
showAbove: false,
showBelow: false,
dataSource: new ListView.DataSource({
rowHasChanged: (a, b) => a !== b
}).cloneWithRows(this.buildData(props))
};
}
componentWillReceiveProps(nextProps) {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.buildData(nextProps))
});
const container = this.refs.scrollContainer;
if (container && container._visibleRows && container._visibleRows.s1) { //eslint-disable-line no-underscore-dangle
this.updateUnreadIndicators(container._visibleRows); //eslint-disable-line no-underscore-dangle
}
}
getRowIndex = (displayName) => {
const data = this.state.dataSource._dataBlob.s1; //eslint-disable-line no-underscore-dangle
return data.findIndex((obj) => obj.display_name === displayName);
};
getAboveAndBelow = (index) => {
const channel = this.state.dataSource.getRowData(0, index);
const result = buildDisplayNameAndTypeComparable(channel).localeCompare(buildDisplayNameAndTypeComparable(this.props.currentChannel));
if (result < 0) {
return {above: true, below: false};
} else if (result > 0) {
return {above: false, below: true};
}
return {above: false, below: false};
};
updateUnreadIndicators = (v) => {
let showAbove = false;
let showBelow = false;
if (this.firstUnreadChannel) {
const index = this.getRowIndex(this.firstUnreadChannel);
if (index >= 0 && !v.s1[index]) {
showAbove = this.getAboveAndBelow(index).above;
}
}
if (this.lastUnreadChannel) {
const index = this.getRowIndex(this.lastUnreadChannel);
if (index >= 0 && !v.s1[index]) {
showBelow = this.getAboveAndBelow(index).below;
}
}
this.setState({
showAbove,
showBelow
});
};
onSelectChannel = (channel) => {
console.log('clicked channel ' + channel.name); // eslint-disable-line no-console
const {
currentChannel,
currentTeam
} = this.props;
this.props.onSelectChannel(channel.id);
this.props.onViewChannel(currentTeam.id, channel.id, currentChannel.id);
this.props.closeChannelDrawer();
};
getUnreadMessages = (channel) => {
const member = this.props.channelMembers[channel.id];
let mentions = 0;
let unreadCount = 0;
if (member) {
mentions = member.mention_count;
unreadCount = channel.total_msg_count - member.msg_count;
if (member.notify_props && member.notify_props.mark_unread === 'mention') {
unreadCount = 0;
}
}
return {
mentions,
unreadCount
};
};
findUnreadChannels = (data) => {
data.forEach((c) => {
if (c.id) {
const {mentions, unreadCount} = this.getUnreadMessages(c);
const unread = (mentions + unreadCount) > 0;
if (unread && c.id !== this.props.currentChannel.id) {
if (!this.firstUnreadChannel) {
this.firstUnreadChannel = c.display_name;
}
this.lastUnreadChannel = c.display_name;
}
}
});
};
createChannelElement = (channel) => {
const {mentions, unreadCount} = this.getUnreadMessages(channel);
const msgCount = mentions + unreadCount;
const unread = msgCount > 0;
return (
<ChannelItem
ref={channel.id}
channel={channel}
hasUnread={unread}
mentions={mentions}
onSelectChannel={this.onSelectChannel}
isActive={channel.id === this.props.currentChannel.id}
theme={this.props.theme}
/>
);
};
buildData = (props) => {
const data = [];
if (!props.currentChannel) {
return data;
}
const {
theme
} = props;
const {
favoriteChannels,
publicChannels,
privateChannels,
directChannels,
directNonTeamChannels
} = props.channels;
if (favoriteChannels.length) {
data.push(
<FormattedText
style={[Styles.title, {color: theme.sidebarText}]}
id='sidebar.favorite'
defaultMessage='FAVORITES'
/>,
...favoriteChannels
);
}
data.push(
<FormattedText
style={[Styles.title, {color: theme.sidebarText}]}
id='sidebar.channels'
defaultMessage='CHANNELS'
/>,
...publicChannels
);
data.push(
<FormattedText
style={[Styles.title, {color: theme.sidebarText}]}
id='sidebar.pg'
defaultMessage='PRIVATE GROUPS'
/>,
...privateChannels
);
data.push(
<FormattedText
style={[Styles.title, {color: theme.sidebarText}]}
id='sidebar.direct'
defaultMessage='DIRECT MESSAGES'
/>,
...directChannels
);
if (directNonTeamChannels.length) {
data.push(
<LineDivider
color={theme.sidebarTextActiveBorder}
translationId='sidebar.otherMembers'
translationText='Outside this team'
/>,
...directNonTeamChannels
);
}
this.firstUnreadChannel = null;
this.lastUnreadChannel = null;
this.findUnreadChannels(data);
return data;
};
renderRow = (rowData) => {
if (rowData && rowData.id) {
return this.createChannelElement(rowData);
}
return rowData;
};
render() {
if (!this.props.currentChannel) {
return <Text>{'Loading'}</Text>;
}
const {
theme
} = this.props;
let above;
let below;
if (this.state.showAbove) {
above = (
<UnreadIndicator
style={{top: 55, backgroundColor: theme.mentionBj}}
text={(
<FormattedText
style={[Styles.indicatorText, {color: theme.mentionColor}]}
id='sidebar.unreadAbove'
defaultMessage='Unread post(s) above'
/>
)}
/>
);
}
if (this.state.showBelow) {
below = (
<UnreadIndicator
style={{bottom: 15, backgroundColor: theme.mentionBj}}
text={(
<FormattedText
style={[Styles.indicatorText, {color: theme.mentionColor}]}
id='sidebar.unreadBelow'
defaultMessage='Unread post(s) below'
/>
)}
/>
);
}
return (
<View style={[Styles.container, {backgroundColor: theme.sidebarBg}]}>
<View style={[Styles.headerContainer, {backgroundColor: theme.sidebarHeaderBg}]}>
<Text
ellipsizeMode='tail'
numberOfLines={1}
style={[Styles.header, {color: theme.sidebarHeaderTextColor}]}
>
{this.props.currentTeam.display_name}
</Text>
</View>
<ListView
ref='scrollContainer'
style={Styles.scrollContainer}
dataSource={this.state.dataSource}
renderRow={this.renderRow}
onChangeVisibleRows={this.updateUnreadIndicators}
/>
{above}
{below}
</View>
);
}
}