PLT-3077 Add group messaging (#5489)
* Implement server changes for group messaging * Majority of client-side implementation * Some server updates * Added new React multiselect component * Fix style issues * Add custom renderer for options * Fix model test * Update ENTER functionality for multiselect control * Remove buttons from multiselect UI control * Updating group messaging UI (#5524) * Move filter controls up a component level * Scroll with arrow keys * Updating mobile layout for multiselect (#5534) * Fix race condition when backspacing quickly * Hidden or new GMs show up for regular messages * Add overriding of number remaining text * Add UI filtering for team if config setting set * Add icon to channel switcher and class prop to status icon * Minor updates per feedback * Improving group messaging UI (#5563) * UX changes per feedback * Update email for group messages * UI fixes for group messaging (#5587) * Fix missing localization string * Add maximum users message when adding members to GM * Fix input clearing on Android * Updating group messaging UI (#5603) * Updating UI for group messaging (#5604)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
8c5cee9521
Коммит
3a91d4e5e4
@@ -5,7 +5,6 @@ const Preferences = Constants.Preferences;
|
||||
import * as Utils from 'utils/utils.jsx';
|
||||
|
||||
import UserStore from 'stores/user_store.jsx';
|
||||
import TeamStore from 'stores/team_store.jsx';
|
||||
import PreferenceStore from 'stores/preference_store.jsx';
|
||||
import LocalizationStore from 'stores/localization_store.jsx';
|
||||
|
||||
@@ -15,30 +14,28 @@ import LocalizationStore from 'stores/localization_store.jsx';
|
||||
* Example: {
|
||||
* publicChannels: [...],
|
||||
* privateChannels: [...],
|
||||
* directChannels: [...],
|
||||
* directNonTeamChannels: [...],
|
||||
* directAndGroupChannels: [...],
|
||||
* favoriteChannels: [...]
|
||||
* }
|
||||
*/
|
||||
export function buildDisplayableChannelList(persistentChannels) {
|
||||
const missingDMChannels = createMissingDirectChannels(persistentChannels);
|
||||
const missingDirectChannels = createMissingDirectChannels(persistentChannels);
|
||||
|
||||
const channels = persistentChannels.
|
||||
concat(missingDMChannels).
|
||||
concat(missingDirectChannels).
|
||||
map(completeDirectChannelInfo).
|
||||
filter(isNotDeletedChannel).
|
||||
sort(sortChannelsByDisplayName);
|
||||
|
||||
const favoriteChannels = channels.filter(isFavoriteChannel);
|
||||
const notFavoriteChannels = channels.filter(not(isFavoriteChannel));
|
||||
const directChannels = notFavoriteChannels.filter(andX(isDirectChannel, isDirectChannelVisible));
|
||||
const directAndGroupChannels = notFavoriteChannels.filter(orX(andX(isGroupChannel, isGroupChannelVisible), andX(isDirectChannel, isDirectChannelVisible)));
|
||||
|
||||
return {
|
||||
favoriteChannels,
|
||||
publicChannels: notFavoriteChannels.filter(isOpenChannel),
|
||||
privateChannels: notFavoriteChannels.filter(isPrivateChannel),
|
||||
directChannels: directChannels.filter(isConnectedToTeamMember),
|
||||
directNonTeamChannels: directChannels.filter(isNotConnectedToTeamMember)
|
||||
directAndGroupChannels
|
||||
};
|
||||
}
|
||||
|
||||
@@ -62,6 +59,14 @@ export function isPrivateChannel(channel) {
|
||||
return channel.type === Constants.PRIVATE_CHANNEL;
|
||||
}
|
||||
|
||||
export function isGroupChannel(channel) {
|
||||
return channel.type === Constants.GM_CHANNEL;
|
||||
}
|
||||
|
||||
export function isGroupChannelVisible(channel) {
|
||||
return PreferenceStore.getBool(Preferences.CATEGORY_GROUP_CHANNEL_SHOW, channel.id);
|
||||
}
|
||||
|
||||
export function isDirectChannel(channel) {
|
||||
return channel.type === Constants.DM_CHANNEL;
|
||||
}
|
||||
@@ -88,12 +93,12 @@ export function completeDirectChannelInfo(channel) {
|
||||
}
|
||||
|
||||
const defaultPrefix = 'D'; // fallback for future types
|
||||
const typeToPrefixMap = {[Constants.OPEN_CHANNEL]: 'A', [Constants.PRIVATE_CHANNEL]: 'B', [Constants.DM_CHANNEL]: 'C'};
|
||||
const typeToPrefixMap = {[Constants.OPEN_CHANNEL]: 'A', [Constants.PRIVATE_CHANNEL]: 'B', [Constants.DM_CHANNEL]: 'C', [Constants.GM_CHANNEL]: 'C'};
|
||||
|
||||
export function sortChannelsByDisplayName(a, b) {
|
||||
const locale = LocalizationStore.getLocale();
|
||||
|
||||
if (a.type !== b.type) {
|
||||
if (a.type !== b.type && typeToPrefixMap[a.type] !== typeToPrefixMap[b.type]) {
|
||||
return (typeToPrefixMap[a.type] || defaultPrefix).localeCompare((typeToPrefixMap[b.type] || defaultPrefix), locale);
|
||||
}
|
||||
|
||||
@@ -186,6 +191,19 @@ export function showDeleteOption(channel, isAdmin, isSystemAdmin, isChannelAdmin
|
||||
return true;
|
||||
}
|
||||
|
||||
export function buildGroupChannelName(channelId) {
|
||||
const profiles = UserStore.getProfileListInChannel(channelId, true);
|
||||
let displayName = '';
|
||||
for (let i = 0; i < profiles.length; i++) {
|
||||
displayName += Utils.displayUsernameForUser(profiles[i]);
|
||||
if (i !== profiles.length - 1) {
|
||||
displayName += ', ';
|
||||
}
|
||||
}
|
||||
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/*
|
||||
* not exported helpers
|
||||
*/
|
||||
@@ -215,22 +233,14 @@ function createFakeChannelCurried(userId) {
|
||||
return (otherUserId) => createFakeChannel(userId, otherUserId);
|
||||
}
|
||||
|
||||
function isConnectedToTeamMember(channel) {
|
||||
return isTeamMember(channel.teammate_id);
|
||||
}
|
||||
|
||||
function isTeamMember(userId) {
|
||||
return TeamStore.hasActiveMemberInTeam(TeamStore.getCurrentId(), userId);
|
||||
}
|
||||
|
||||
function isNotConnectedToTeamMember(channel) {
|
||||
return TeamStore.hasMemberNotInTeam(TeamStore.getCurrentId(), channel.teammate_id);
|
||||
}
|
||||
|
||||
function not(f) {
|
||||
return (...args) => !f(...args);
|
||||
}
|
||||
|
||||
function orX(...fns) {
|
||||
return (...args) => fns.some((f) => f(...args));
|
||||
}
|
||||
|
||||
function andX(...fns) {
|
||||
return (...args) => fns.every((f) => f(...args));
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user