diff --git a/app/actions/views/channel.js b/app/actions/views/channel.js index 544a2863c..c78eb2391 100644 --- a/app/actions/views/channel.js +++ b/app/actions/views/channel.js @@ -51,7 +51,9 @@ export function loadProfilesAndTeamMembersForDMSidebar(teamId) { membersToLoad = members.filter((m) => !membersInTeam[teamId].has(m)); } - await getTeamMembersByIds(teamId, membersToLoad)(dispatch, getState); + if (membersToLoad.length) { + await getTeamMembersByIds(teamId, membersToLoad)(dispatch, getState); + } const actions = []; for (let i = 0; i < members.length; i++) { diff --git a/app/components/channel_drawer/channel_drawer.js b/app/components/channel_drawer/channel_drawer.js index 69da52264..9dbb584b9 100644 --- a/app/components/channel_drawer/channel_drawer.js +++ b/app/components/channel_drawer/channel_drawer.js @@ -17,7 +17,7 @@ export default class ChannelDrawer extends React.Component { closeChannelDrawer: React.PropTypes.func.isRequired }).isRequired, currentTeam: React.PropTypes.object, - currentChannelId: React.PropTypes.string, + currentChannel: React.PropTypes.object, channels: React.PropTypes.object, channelMembers: React.PropTypes.object, theme: React.PropTypes.object.isRequired, @@ -61,7 +61,7 @@ export default class ChannelDrawer extends React.Component { render() { const { - currentChannelId, + currentChannel, currentTeam, channels, channelMembers, @@ -85,7 +85,7 @@ export default class ChannelDrawer extends React.Component { content={ a !== b - }).cloneWithRows(props) + }).cloneWithRows(this.buildData(props)) }; } @@ -81,58 +82,71 @@ export default class ChannelList extends React.Component { } } - updateUnreadIndicators = (v) => { + 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 = data.findIndex((obj) => obj.id === this.firstUnreadChannel); - if (v.s1[index]) { - this.setState({ - showAbove: false - }); - } else if (!v.s1[index - 1]) { - this.setState({ - showAbove: true - }); + const index = this.getRowIndex(this.firstUnreadChannel); + if (index >= 0 && !v.s1[index]) { + showAbove = this.getAboveAndBelow(index).above; } } if (this.lastUnreadChannel) { - const index = data.findIndex((obj) => obj.id === this.lastUnreadChannel); - if (v.s1[index]) { - this.setState({ - showBelow: false - }); - } else if (!v.s1[index + 1]) { - this.setState({ - showBelow: true - }); + 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 { - currentChannelId, + currentChannel, currentTeam } = this.props; this.props.onSelectChannel(channel.id); - this.props.onViewChannel(currentTeam.id, channel.id, currentChannelId); + this.props.onViewChannel(currentTeam.id, channel.id, currentChannel.id); this.props.closeChannelDrawer(); }; getUnreadMessages = (channel) => { const member = this.props.channelMembers[channel.id]; - const mentions = member.mention_count; - let unreadCount = channel.total_msg_count - member.msg_count; + 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; + if (member.notify_props && member.notify_props.mark_unread === 'mention') { + unreadCount = 0; + } } - return { mentions, unreadCount @@ -145,12 +159,11 @@ export default class ChannelList extends React.Component { const {mentions, unreadCount} = this.getUnreadMessages(c); const unread = (mentions + unreadCount) > 0; - if (unread && c.id !== this.props.currentChannelId) { - if (this.firstUnreadChannel) { - this.lastUnreadChannel = c.id; - } else { - this.firstUnreadChannel = c.id; + if (unread && c.id !== this.props.currentChannel.id) { + if (!this.firstUnreadChannel) { + this.firstUnreadChannel = c.display_name; } + this.lastUnreadChannel = c.display_name; } } }); @@ -164,12 +177,11 @@ export default class ChannelList extends React.Component { return ( ); @@ -178,7 +190,7 @@ export default class ChannelList extends React.Component { buildData = (props) => { const data = []; - if (!props.currentChannelId) { + if (!props.currentChannel) { return data; } @@ -248,15 +260,15 @@ export default class ChannelList extends React.Component { return data; }; - renderRow = (rowData, sectionId, rowId) => { + renderRow = (rowData) => { if (rowData && rowData.id) { - return this.createChannelElement(rowData, sectionId, rowId); + return this.createChannelElement(rowData); } return rowData; }; render() { - if (!this.props.currentChannelId) { + if (!this.props.currentChannel) { return {'Loading'}; } diff --git a/app/initial_state.js b/app/initial_state.js new file mode 100644 index 000000000..6c7ceba5c --- /dev/null +++ b/app/initial_state.js @@ -0,0 +1,279 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import Config from 'assets/config.json'; + +const state = { + entities: { + general: { + appState: false, + credentials: {}, + config: {}, + license: {} + }, + users: { + currentId: '', + mySessions: [], + myAudits: [], + profiles: {}, + profilesInTeam: {}, + profilesInChannel: {}, + profilesNotInChannel: {}, + statuses: {} + }, + teams: { + currentId: '', + teams: {}, + myMembers: {}, + membersInTeam: {}, + stats: {}, + openTeamIds: new Set() + }, + channels: { + currentId: '', + channels: {}, + myMembers: {}, + stats: {} + }, + posts: { + posts: {}, + postsByChannel: {}, + selectedPostId: '', + currentFocusedPostId: '' + }, + preferences: { + myPreferences: {} + } + }, + requests: { + channels: { + getChannel: { + status: 'not_started', + error: null + }, + getChannels: { + status: 'not_started', + error: null + }, + myMembers: { + status: 'not_started', + error: null + }, + createChannel: { + status: 'not_started', + error: null + }, + updateChannel: { + status: 'not_started', + error: null + }, + updateChannelNotifyProps: { + status: 'not_started', + error: null + }, + leaveChannel: { + status: 'not_started', + error: null + }, + joinChannel: { + status: 'not_started', + error: null + }, + deleteChannel: { + status: 'not_started', + error: null + }, + updateLastViewedAt: { + status: 'not_started', + error: null + }, + getMoreChannels: { + status: 'not_started', + error: null + }, + getChannelStats: { + status: 'not_started', + error: null + }, + addChannelMember: { + status: 'not_started', + error: null + }, + removeChannelMember: { + status: 'not_started', + error: null + } + }, + general: { + server: { + status: 'not_started', + error: null + }, + config: { + status: 'not_started', + error: null + }, + license: { + status: 'not_started', + error: null + }, + websocket: { + status: 'not_started', + error: null + } + }, + posts: { + createPost: { + status: 'not_started', + error: null + }, + editPost: { + status: 'not_started', + error: null + }, + deletePost: { + status: 'not_started', + error: null + }, + getPost: { + status: 'not_started', + error: null + }, + getPosts: { + status: 'not_started', + error: null + }, + getPostsSince: { + status: 'not_started', + error: null + }, + getPostsBefore: { + status: 'not_started', + error: null + }, + getPostsAfter: { + status: 'not_started', + error: null + } + }, + teams: { + allTeams: { + status: 'not_started', + error: null + }, + getAllTeamListings: { + status: 'not_started', + error: null + }, + createTeam: { + status: 'not_started', + error: null + }, + updateTeam: { + status: 'not_started', + error: null + }, + getMyTeamMembers: { + status: 'not_started', + error: null + }, + getTeamMembers: { + status: 'not_started', + error: null + }, + getTeamStats: { + status: 'not_started', + error: null + }, + addUserToTeam: { + status: 'not_started', + error: null + }, + removeUserFromTeam: { + status: 'not_started', + error: null + } + }, + users: { + login: { + status: 'not_started', + error: null + }, + logout: { + status: 'not_started', + error: null + }, + getProfiles: { + status: 'not_started', + error: null + }, + getProfilesInTeam: { + status: 'not_started', + error: null + }, + getProfilesInChannel: { + status: 'not_started', + error: null + }, + getProfilesNotInChannel: { + status: 'not_started', + error: null + }, + getStatusesByIds: { + status: 'not_started', + error: null + }, + getSessions: { + status: 'not_started', + error: null + }, + revokeSession: { + status: 'not_started', + error: null + }, + getAudits: { + status: 'not_started', + error: null + } + }, + preferences: { + getMyPreferences: { + status: 'not_started', + error: null + }, + savePreferences: { + status: 'not_started', + error: null + }, + deletePreferences: { + status: 'not_started', + error: null + } + } + }, + navigation: { + index: 0, + routes: [ + { + key: 'Root' + } + ] + }, + views: { + i18n: { + locale: '' + }, + login: { + loginId: '', + password: '' + }, + selectServer: { + serverUrl: Config.DefaultServerUrl + }, + drawer: { + channel: false + } + } +}; + +export default state; diff --git a/app/scenes/channel/channel.js b/app/scenes/channel/channel.js index 36ca4666e..999a0b407 100644 --- a/app/scenes/channel/channel.js +++ b/app/scenes/channel/channel.js @@ -81,7 +81,7 @@ export default class Channel extends React.Component {