// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import {Constants} from 'service/constants'; import {displayUsername} from './user_utils'; import {getPreferencesByCategory} from './preference_utils'; const defaultPrefix = 'D'; // fallback for future types const typeToPrefixMap = {[Constants.OPEN_CHANNEL]: 'A', [Constants.PRIVATE_CHANNEL]: 'B', [Constants.DM_CHANNEL]: 'C'}; export function buildDisplayableChannelList(usersState, teamsState, allChannels, myPreferences) { const missingDMChannels = createMissingDirectChannels(usersState.currentId, allChannels, myPreferences); const channels = allChannels. concat(missingDMChannels). map(completeDirectChannelInfo.bind(null, usersState, myPreferences)); channels.sort((a, b) => { const locale = usersState.profiles[usersState.currentId].locale; return buildDisplayNameAndTypeComparable(a). localeCompare(buildDisplayNameAndTypeComparable(b), locale, {numeric: true}); }); const favoriteChannels = channels.filter(isFavoriteChannel.bind(null, myPreferences)); const notFavoriteChannels = channels.filter(not(isFavoriteChannel.bind(null, myPreferences))); const directChannels = notFavoriteChannels. filter( andX( isDirectChannel, isDirectChannelVisible.bind(null, usersState.currentId, myPreferences) ) ); return { favoriteChannels, publicChannels: notFavoriteChannels.filter(isOpenChannel), privateChannels: notFavoriteChannels.filter(isPrivateChannel), directChannels: directChannels.filter( isConnectedToTeamMember.bind(null, teamsState.membersInTeam[teamsState.currentId]) ), directNonTeamChannels: directChannels.filter( isNotConnectedToTeamMember.bind(null, teamsState.membersInTeam[teamsState.currentId]) ) }; } export function getDirectChannelName(id, otherId) { let handle; if (otherId > id) { handle = id + '__' + otherId; } else { handle = otherId + '__' + id; } return handle; } export function getChannelByName(channels, name) { const channelIds = Object.keys(channels); for (let i = 0; i < channelIds.length; i++) { const id = channelIds[i]; if (channels[id].name === name) { return channels[id]; } } return null; } function isOpenChannel(channel) { return channel.type === Constants.OPEN_CHANNEL; } function isPrivateChannel(channel) { return channel.type === Constants.PRIVATE_CHANNEL; } function isConnectedToTeamMember(members, channel) { return members && members.has(channel.teammate_id); } function isNotConnectedToTeamMember(members, channel) { if (!members) { return true; } return !members.has(channel.teammate_id); } function isDirectChannel(channel) { return channel.type === Constants.DM_CHANNEL; } function isDirectChannelVisible(userId, myPreferences, channel) { const channelId = getUserIdFromChannelName(userId, channel); const dm = myPreferences[`${Constants.CATEGORY_DIRECT_CHANNEL_SHOW}--${channelId}`]; return dm && dm.value === 'true'; } function isFavoriteChannel(myPreferences, channel) { const fav = myPreferences[`${Constants.CATEGORY_FAVORITE_CHANNEL}--${channel.id}`]; return fav && fav.value === 'true'; } function createMissingDirectChannels(currentUserId, allChannels, myPreferences) { const preferences = getPreferencesByCategory(myPreferences, Constants.CATEGORY_DIRECT_CHANNEL_SHOW); return Array. from(preferences). filter((entry) => entry[1] === 'true'). map((entry) => entry[0]). filter((teammateId) => !allChannels.some(isDirectChannelForUser.bind(null, currentUserId, teammateId))). map(createFakeChannelCurried(currentUserId)); } function isDirectChannelForUser(userId, otherUserId, channel) { return channel.type === Constants.DM_CHANNEL && getUserIdFromChannelName(userId, channel) === otherUserId; } export function getUserIdFromChannelName(userId, channel) { const ids = channel.name.split('__'); let otherUserId = ''; if (ids[0] === userId) { otherUserId = ids[1]; } else { otherUserId = ids[0]; } return otherUserId; } function createFakeChannel(userId, otherUserId) { return { name: getDirectChannelName(userId, otherUserId), last_post_at: 0, total_msg_count: 0, type: Constants.DM_CHANNEL, fake: true }; } function createFakeChannelCurried(userId) { return (otherUserId) => createFakeChannel(userId, otherUserId); } function completeDirectChannelInfo(usersState, myPreferences, channel) { if (!isDirectChannel(channel)) { return channel; } const dmChannelClone = JSON.parse(JSON.stringify(channel)); const teammateId = getUserIdFromChannelName(usersState.currentId, channel); return Object.assign(dmChannelClone, { display_name: displayUsername(usersState.profiles[teammateId], myPreferences), teammate_id: teammateId, status: usersState.statuses[teammateId] || 'offline' }); } export function buildDisplayNameAndTypeComparable(channel) { return (typeToPrefixMap[channel.type] || defaultPrefix) + channel.display_name + channel.name; } function not(f) { return (...args) => !f(...args); } function andX(...fns) { return (...args) => fns.every((f) => f(...args)); }