forked from Ivasoft/mattermost-mobile
RN-268 Fixed teams list not always rerendering when team member changes (#970)
* RN-268 Fixed teams list not always rerendering when team member changes * Removed unused prop from ChannelDrawer * RN-268 Passed fewer props into TeamsListItem
This commit is contained in:
@@ -5,7 +5,7 @@ import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {getCurrentUrl} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getCurrentTeamId, getJoinableTeams, getTeamMemberships} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {getCurrentTeamId, getJoinableTeams} from 'mattermost-redux/selectors/entities/teams';
|
||||
|
||||
import {handleTeamChange} from 'app/actions/views/select_team';
|
||||
import {getTheme} from 'app/selectors/preferences';
|
||||
@@ -16,13 +16,11 @@ import TeamsList from './teams_list';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
return {
|
||||
canCreateTeams: false,
|
||||
joinableTeams: getJoinableTeams(state),
|
||||
currentTeamId: getCurrentTeamId(state),
|
||||
currentUrl: removeProtocol(getCurrentUrl(state)),
|
||||
teams: getMySortedTeams(state),
|
||||
theme: getTheme(state),
|
||||
myTeamMembers: getTeamMemberships(state),
|
||||
...ownProps
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,26 +11,24 @@ import {
|
||||
View
|
||||
} from 'react-native';
|
||||
import {injectIntl, intlShape} from 'react-intl';
|
||||
import IonIcon from 'react-native-vector-icons/Ionicons';
|
||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
|
||||
import Badge from 'app/components/badge';
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import {wrapWithPreventDoubleTap} from 'app/utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
import TeamsListItem from './teams_list_item';
|
||||
|
||||
class TeamsList extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
handleTeamChange: PropTypes.func.isRequired
|
||||
}).isRequired,
|
||||
canCreateTeams: PropTypes.bool.isRequired,
|
||||
closeChannelDrawer: PropTypes.func.isRequired,
|
||||
currentTeamId: PropTypes.string.isRequired,
|
||||
currentUrl: PropTypes.string.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
joinableTeams: PropTypes.object.isRequired,
|
||||
myTeamMembers: PropTypes.object.isRequired,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
teams: PropTypes.array.isRequired,
|
||||
theme: PropTypes.object.isRequired
|
||||
@@ -55,7 +53,7 @@ class TeamsList extends PureComponent {
|
||||
});
|
||||
};
|
||||
|
||||
goToSelectTeam = () => {
|
||||
goToSelectTeam = wrapWithPreventDoubleTap(() => {
|
||||
const {currentUrl, intl, navigator, theme} = this.props;
|
||||
|
||||
navigator.showModal({
|
||||
@@ -81,79 +79,18 @@ class TeamsList extends PureComponent {
|
||||
theme
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
keyExtractor = (team) => {
|
||||
return team.id;
|
||||
}
|
||||
|
||||
renderItem = ({item}) => {
|
||||
const {currentTeamId, currentUrl, myTeamMembers, theme} = this.props;
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
let current;
|
||||
let badge;
|
||||
if (item.id === currentTeamId) {
|
||||
current = (
|
||||
<View style={styles.checkmarkContainer}>
|
||||
<IonIcon
|
||||
name='md-checkmark'
|
||||
style={styles.checkmark}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const member = myTeamMembers[item.id];
|
||||
|
||||
let badgeCount = 0;
|
||||
if (member.mention_count) {
|
||||
badgeCount = member.mention_count;
|
||||
} else if (member.msg_count) {
|
||||
badgeCount = -1;
|
||||
}
|
||||
|
||||
if (badgeCount) {
|
||||
badge = (
|
||||
<Badge
|
||||
style={styles.badge}
|
||||
countStyle={styles.mention}
|
||||
count={badgeCount}
|
||||
minHeight={20}
|
||||
minWidth={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.teamWrapper}>
|
||||
<TouchableHighlight
|
||||
underlayColor={changeOpacity(theme.sidebarTextHoverBg, 0.5)}
|
||||
onPress={() => preventDoubleTap(this.selectTeam, this, item)}
|
||||
>
|
||||
<View style={styles.teamContainer}>
|
||||
<View style={styles.teamIconContainer}>
|
||||
<Text style={styles.teamIcon}>
|
||||
{item.display_name.substr(0, 2).toUpperCase()}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.teamNameContainer}>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
ellipsizeMode='tail'
|
||||
style={styles.teamName}
|
||||
>
|
||||
{item.display_name}
|
||||
</Text>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
ellipsizeMode='tail'
|
||||
style={styles.teamUrl}
|
||||
>
|
||||
{`${currentUrl}/${item.name}`}
|
||||
</Text>
|
||||
</View>
|
||||
{current}
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
{badge}
|
||||
</View>
|
||||
<TeamsListItem
|
||||
selectTeam={this.selectTeam}
|
||||
team={item}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -166,7 +103,7 @@ class TeamsList extends PureComponent {
|
||||
moreAction = (
|
||||
<TouchableHighlight
|
||||
style={styles.moreActionContainer}
|
||||
onPress={() => preventDoubleTap(this.goToSelectTeam)}
|
||||
onPress={this.goToSelectTeam}
|
||||
underlayColor={changeOpacity(theme.sidebarHeaderBg, 0.5)}
|
||||
>
|
||||
<Text
|
||||
@@ -193,7 +130,7 @@ class TeamsList extends PureComponent {
|
||||
<FlatList
|
||||
data={teams}
|
||||
renderItem={this.renderItem}
|
||||
keyExtractor={(item) => item.id}
|
||||
keyExtractor={this.keyExtractor}
|
||||
viewabilityConfig={{
|
||||
viewAreaCoveragePercentThreshold: 3,
|
||||
waitForInteraction: false
|
||||
@@ -256,64 +193,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
moreAction: {
|
||||
color: theme.sidebarHeaderTextColor,
|
||||
fontSize: 30
|
||||
},
|
||||
teamWrapper: {
|
||||
marginTop: 20
|
||||
},
|
||||
teamContainer: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
marginHorizontal: 16
|
||||
},
|
||||
teamIconContainer: {
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.sidebarText,
|
||||
borderRadius: 2,
|
||||
height: 40,
|
||||
justifyContent: 'center',
|
||||
width: 40
|
||||
},
|
||||
teamIcon: {
|
||||
color: theme.sidebarBg,
|
||||
fontFamily: 'OpenSans',
|
||||
fontSize: 18,
|
||||
fontWeight: '600'
|
||||
},
|
||||
teamNameContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
marginLeft: 10
|
||||
},
|
||||
teamName: {
|
||||
color: theme.sidebarText,
|
||||
fontSize: 18
|
||||
},
|
||||
teamUrl: {
|
||||
color: changeOpacity(theme.sidebarText, 0.5),
|
||||
fontSize: 12
|
||||
},
|
||||
checkmarkContainer: {
|
||||
alignItems: 'flex-end'
|
||||
},
|
||||
checkmark: {
|
||||
color: theme.sidebarText,
|
||||
fontSize: 20
|
||||
},
|
||||
badge: {
|
||||
backgroundColor: theme.mentionBj,
|
||||
borderColor: theme.sidebarHeaderBg,
|
||||
borderRadius: 10,
|
||||
borderWidth: 1,
|
||||
flexDirection: 'row',
|
||||
padding: 3,
|
||||
position: 'absolute',
|
||||
left: 45,
|
||||
top: -7.5
|
||||
},
|
||||
mention: {
|
||||
color: theme.mentionColor,
|
||||
fontSize: 10
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {getCurrentUrl} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentTeamId, getTeamMemberships} from 'mattermost-redux/selectors/entities/teams';
|
||||
|
||||
import {removeProtocol} from 'app/utils/url';
|
||||
|
||||
import TeamsListItem from './teams_list_item.js';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
return {
|
||||
currentTeamId: getCurrentTeamId(state),
|
||||
currentUrl: removeProtocol(getCurrentUrl(state)),
|
||||
teamMember: getTeamMemberships(state)[ownProps.team.id],
|
||||
theme: getTheme(state),
|
||||
...ownProps
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(TeamsListItem);
|
||||
@@ -0,0 +1,171 @@
|
||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
View
|
||||
} from 'react-native';
|
||||
import IonIcon from 'react-native-vector-icons/Ionicons';
|
||||
|
||||
import Badge from 'app/components/badge';
|
||||
import {wrapWithPreventDoubleTap} from 'app/utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
export default class TeamsListItem extends React.PureComponent {
|
||||
static propTypes = {
|
||||
currentTeamId: PropTypes.string.isRequired,
|
||||
currentUrl: PropTypes.string.isRequired,
|
||||
selectTeam: PropTypes.func.isRequired,
|
||||
team: PropTypes.object.isRequired,
|
||||
teamMember: PropTypes.object.isRequired,
|
||||
theme: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
selectTeam = wrapWithPreventDoubleTap(() => {
|
||||
this.props.selectTeam(this.props.team);
|
||||
});
|
||||
|
||||
render() {
|
||||
const {
|
||||
currentTeamId,
|
||||
currentUrl,
|
||||
team,
|
||||
teamMember,
|
||||
theme
|
||||
} = this.props;
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
let current;
|
||||
let badge;
|
||||
if (team.id === currentTeamId) {
|
||||
current = (
|
||||
<View style={styles.checkmarkContainer}>
|
||||
<IonIcon
|
||||
name='md-checkmark'
|
||||
style={styles.checkmark}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
let badgeCount = 0;
|
||||
if (teamMember.mention_count) {
|
||||
badgeCount = teamMember.mention_count;
|
||||
} else if (teamMember.msg_count) {
|
||||
badgeCount = -1;
|
||||
}
|
||||
|
||||
if (badgeCount) {
|
||||
badge = (
|
||||
<Badge
|
||||
style={styles.badge}
|
||||
countStyle={styles.mention}
|
||||
count={badgeCount}
|
||||
minHeight={20}
|
||||
minWidth={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.teamWrapper}>
|
||||
<TouchableHighlight
|
||||
underlayColor={changeOpacity(theme.sidebarTextHoverBg, 0.5)}
|
||||
onPress={this.selectTeam}
|
||||
>
|
||||
<View style={styles.teamContainer}>
|
||||
<View style={styles.teamIconContainer}>
|
||||
<Text style={styles.teamIcon}>
|
||||
{team.display_name.substr(0, 2).toUpperCase()}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.teamNameContainer}>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
ellipsizeMode='tail'
|
||||
style={styles.teamName}
|
||||
>
|
||||
{team.display_name}
|
||||
</Text>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
ellipsizeMode='tail'
|
||||
style={styles.teamUrl}
|
||||
>
|
||||
{`${currentUrl}/${team.name}`}
|
||||
</Text>
|
||||
</View>
|
||||
{current}
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
{badge}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
teamWrapper: {
|
||||
marginTop: 20
|
||||
},
|
||||
teamContainer: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
marginHorizontal: 16
|
||||
},
|
||||
teamIconContainer: {
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.sidebarText,
|
||||
borderRadius: 2,
|
||||
height: 40,
|
||||
justifyContent: 'center',
|
||||
width: 40
|
||||
},
|
||||
teamIcon: {
|
||||
color: theme.sidebarBg,
|
||||
fontFamily: 'OpenSans',
|
||||
fontSize: 18,
|
||||
fontWeight: '600'
|
||||
},
|
||||
teamNameContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
marginLeft: 10
|
||||
},
|
||||
teamName: {
|
||||
color: theme.sidebarText,
|
||||
fontSize: 18
|
||||
},
|
||||
teamUrl: {
|
||||
color: changeOpacity(theme.sidebarText, 0.5),
|
||||
fontSize: 12
|
||||
},
|
||||
checkmarkContainer: {
|
||||
alignItems: 'flex-end'
|
||||
},
|
||||
checkmark: {
|
||||
color: theme.sidebarText,
|
||||
fontSize: 20
|
||||
},
|
||||
badge: {
|
||||
backgroundColor: theme.mentionBj,
|
||||
borderColor: theme.sidebarHeaderBg,
|
||||
borderRadius: 10,
|
||||
borderWidth: 1,
|
||||
flexDirection: 'row',
|
||||
padding: 3,
|
||||
position: 'absolute',
|
||||
left: 45,
|
||||
top: -7.5
|
||||
},
|
||||
mention: {
|
||||
color: theme.mentionColor,
|
||||
fontSize: 10
|
||||
}
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user