parent
1bd40d1a40
commit
ea3b2cabd4
7 changed files with 62 additions and 30 deletions
|
|
@ -12,12 +12,17 @@ import {
|
|||
import Client from 'service/client';
|
||||
import {displayUsername} from 'service/utils/user_utils';
|
||||
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
|
||||
import MemberListRow from './member_list_row';
|
||||
|
||||
const style = StyleSheet.create({
|
||||
listView: {
|
||||
flex: 1
|
||||
},
|
||||
loadingText: {
|
||||
opacity: 0.6
|
||||
},
|
||||
sectionContainer: {
|
||||
backgroundColor: '#eaeaea',
|
||||
paddingLeft: 10,
|
||||
|
|
@ -40,13 +45,20 @@ export default class MemberList extends PureComponent {
|
|||
onListEndReached: PropTypes.func,
|
||||
onListEndReachedThreshold: PropTypes.number,
|
||||
sections: PropTypes.bool,
|
||||
preferences: PropTypes.object
|
||||
preferences: PropTypes.object,
|
||||
loadingMembers: PropTypes.bool,
|
||||
listPageSize: PropTypes.number,
|
||||
listInitialSize: PropTypes.number,
|
||||
listScrollRenderAheadDistance: PropTypes.number
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
onListEndReached: () => true,
|
||||
onListEndThreshold: 10,
|
||||
sections: true
|
||||
onListEndThreshold: 50,
|
||||
sections: true,
|
||||
listPageSize: 10,
|
||||
listInitialSize: 10,
|
||||
listScrollRenderAheadDistance: 200
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
|
@ -73,7 +85,7 @@ export default class MemberList extends PureComponent {
|
|||
createSections = (data) => {
|
||||
const sections = {};
|
||||
data.forEach((d) => {
|
||||
const name = displayUsername(d, this.props.preferences);
|
||||
const name = d.username;
|
||||
const sectionKey = name.substring(0, 1).toUpperCase();
|
||||
|
||||
if (!sections[sectionKey]) {
|
||||
|
|
@ -87,6 +99,10 @@ export default class MemberList extends PureComponent {
|
|||
}
|
||||
|
||||
renderSectionHeader = (sectionData, sectionId) => {
|
||||
if (!this.props.sections) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={style.sectionContainer}>
|
||||
<Text style={style.sectionText}>{sectionId}</Text>
|
||||
|
|
@ -111,7 +127,7 @@ export default class MemberList extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
renderSeparator(sectionId, rowId) {
|
||||
renderSeparator = (sectionId, rowId) => {
|
||||
return (
|
||||
<View
|
||||
key={`${sectionId}-${rowId}`}
|
||||
|
|
@ -120,6 +136,24 @@ export default class MemberList extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
renderFooter = () => {
|
||||
if (!this.props.loadingMembers) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const backgroundColor = this.props.members.length > 0 ? '#fff' : '#0000';
|
||||
|
||||
return (
|
||||
<View style={{height: 70, backgroundColor, alignItems: 'center', justifyContent: 'center'}}>
|
||||
<FormattedText
|
||||
id='mobile.components.member_list.loading_members'
|
||||
defaultMessage='Loading Members...'
|
||||
style={style.loadingText}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ListView
|
||||
|
|
@ -128,9 +162,13 @@ export default class MemberList extends PureComponent {
|
|||
renderRow={this.renderRow}
|
||||
renderSectionHeader={this.renderSectionHeader}
|
||||
renderSeparator={this.renderSeparator}
|
||||
renderFooter={this.renderFooter}
|
||||
enableEmptySections={true}
|
||||
onEndReached={this.props.onListEndReached}
|
||||
onEndReachedThreshold={this.props.onListEndReachedThreshold}
|
||||
pageSize={this.props.listPageSize}
|
||||
initialListSize={this.props.listInitialSize}
|
||||
scrollRenderAheadDistance={this.props.listScrollRenderAheadDistance}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import {
|
|||
} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||
|
||||
const placeholder = require('assets/images/profile.jpg');
|
||||
|
||||
const style = StyleSheet.create({
|
||||
avatar: {
|
||||
height: 40,
|
||||
|
|
@ -96,6 +98,7 @@ function MemberListRow(props) {
|
|||
<Image
|
||||
style={style.avatar}
|
||||
source={{uri: pictureURL}}
|
||||
defaultSource={placeholder}
|
||||
/>
|
||||
<View style={[style.statusContainer, style[status]]}>
|
||||
{StatusComponent}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import React, {PropTypes, PureComponent} from 'react';
|
||||
import {
|
||||
InteractionManager,
|
||||
StyleSheet,
|
||||
View
|
||||
} from 'react-native';
|
||||
|
|
@ -19,29 +20,25 @@ export default class ChannelMembers extends PureComponent {
|
|||
static propTypes = {
|
||||
currentChannel: PropTypes.object,
|
||||
currentChannelMembers: PropTypes.array.isRequired,
|
||||
currentChannelMemberCount: PropTypes.number.isRequired,
|
||||
currentTeam: PropTypes.object,
|
||||
preferences: PropTypes.object,
|
||||
requestStatus: PropTypes.string,
|
||||
actions: PropTypes.shape({
|
||||
getProfilesInChannel: PropTypes.func.isRequired
|
||||
})
|
||||
}
|
||||
|
||||
state = {
|
||||
currentChannelMemberCount: 0
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.actions.getProfilesInChannel(this.props.currentTeam.id, this.props.currentChannel.id, 0);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState({
|
||||
currentChannelMemberCount: this.state.currentChannelMemberCount + nextProps.currentChannelMembers.length
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
this.props.actions.getProfilesInChannel(this.props.currentTeam.id, this.props.currentChannel.id, 0);
|
||||
});
|
||||
}
|
||||
|
||||
loadMoreMembers = () => {
|
||||
this.props.actions.getProfilesInChannel(this.props.currentTeam.id, this.props.currentChannel.id, this.state.currentChannelMemberCount);
|
||||
if (this.props.requestStatus !== 'started' && this.props.currentChannelMembers.length < this.props.currentChannelMemberCount) {
|
||||
this.props.actions.getProfilesInChannel(this.props.currentTeam.id, this.props.currentChannel.id, this.props.currentChannelMembers.length);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
@ -51,6 +48,7 @@ export default class ChannelMembers extends PureComponent {
|
|||
members={this.props.currentChannelMembers}
|
||||
onListEndReached={this.loadMoreMembers}
|
||||
preferences={this.props.preferences}
|
||||
loadingMembers={this.props.requestStatus === 'started'}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ function mapStateToProps(state) {
|
|||
currentChannelMembers: getProfilesInCurrentChannel(state),
|
||||
currentChannelMemberCount,
|
||||
currentTeam: getCurrentTeam(state),
|
||||
preferences: getMyPreferences(state)
|
||||
preferences: getMyPreferences(state),
|
||||
requestStatus: state.requests.users.getProfilesInChannel.status
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1492,6 +1492,7 @@
|
|||
"mobile.channel_list.privateChannel": "Private Channel",
|
||||
"mobile.channel_list.publicChannel": "Public Channel",
|
||||
"mobile.components.channels_list_view.yourChannels": "Your channels:",
|
||||
"mobile.components.member_list.loading_members": "Loading Members...",
|
||||
"mobile.components.select_server_view.enterServerUrl": "Enter Server URL",
|
||||
"mobile.components.select_server_view.continue": "Continue",
|
||||
"mobile.components.select_server_view.siteUrlPlaceholder": "https://mattermost.example.com",
|
||||
|
|
|
|||
BIN
assets/base/images/profile.jpg
Normal file
BIN
assets/base/images/profile.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
|
|
@ -5,7 +5,6 @@ import {createSelector} from 'reselect';
|
|||
|
||||
import {getCurrentChannelId} from './channels';
|
||||
import {getMyPreferences} from './preferences';
|
||||
import {displayUsername} from 'service/utils/user_utils';
|
||||
|
||||
export function getCurrentUserId(state) {
|
||||
return state.entities.users.currentId;
|
||||
|
|
@ -48,7 +47,7 @@ export const getProfilesInCurrentChannel = createSelector(
|
|||
getUserStatuses,
|
||||
getProfileSetInCurrentChannel,
|
||||
getMyPreferences,
|
||||
(profiles, statuses, currentChannelProfileSet, preferences) => {
|
||||
(profiles, statuses, currentChannelProfileSet) => {
|
||||
const currentProfiles = [];
|
||||
if (typeof currentChannelProfileSet === 'undefined') {
|
||||
return currentProfiles;
|
||||
|
|
@ -61,19 +60,11 @@ export const getProfilesInCurrentChannel = createSelector(
|
|||
});
|
||||
});
|
||||
|
||||
// We could get rid of this if server side sorting is a possibility
|
||||
const sortedCurrentProfiles = currentProfiles.sort((a, b) => {
|
||||
const nameA = displayUsername(a, preferences);
|
||||
const nameB = displayUsername(b, preferences);
|
||||
const nameA = a.username;
|
||||
const nameB = b.username;
|
||||
|
||||
if (nameA.toUpperCase() < nameB.toUpperCase()) {
|
||||
return -1;
|
||||
}
|
||||
if (nameA.toUpperCase() > nameB.toUpperCase()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return nameA.localeCompare(nameB);
|
||||
});
|
||||
|
||||
return sortedCurrentProfiles;
|
||||
|
|
|
|||
Loading…
Reference in a new issue