355 lines
12 KiB
JavaScript
355 lines
12 KiB
JavaScript
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
|
// See License.txt for license information.
|
|
|
|
import {batchActions} from 'redux-batched-actions';
|
|
|
|
import {ViewTypes} from 'app/constants';
|
|
import {updateStorage} from 'app/actions/storage';
|
|
|
|
import {
|
|
fetchMyChannelsAndMembers,
|
|
getChannelStats,
|
|
getMyChannelMembers,
|
|
selectChannel,
|
|
leaveChannel as serviceLeaveChannel
|
|
} from 'mattermost-redux/actions/channels';
|
|
import {getPosts, getPostsSince} from 'mattermost-redux/actions/posts';
|
|
import {getFilesForPost} from 'mattermost-redux/actions/files';
|
|
import {savePreferences, deletePreferences} from 'mattermost-redux/actions/preferences';
|
|
import {getTeamMembersByIds} from 'mattermost-redux/actions/teams';
|
|
import {getProfilesInChannel} from 'mattermost-redux/actions/users';
|
|
import {Constants, Preferences, UsersTypes} from 'mattermost-redux/constants';
|
|
import {
|
|
getChannelByName,
|
|
getDirectChannelName,
|
|
getUserIdFromChannelName,
|
|
isDirectChannelVisible,
|
|
isGroupChannelVisible,
|
|
isDirectChannel,
|
|
isGroupChannel
|
|
} from 'mattermost-redux/utils/channel_utils';
|
|
import {getPreferencesByCategory} from 'mattermost-redux/utils/preference_utils';
|
|
|
|
export function loadChannelsIfNecessary(teamId) {
|
|
return async (dispatch, getState) => {
|
|
const {channels} = getState().entities.channels;
|
|
|
|
let hasChannelsForTeam = false;
|
|
for (const channel of Object.values(channels)) {
|
|
if (channel.team_id === teamId) {
|
|
// If we have one channel, assume we have all of them
|
|
hasChannelsForTeam = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (hasChannelsForTeam) {
|
|
await getMyChannelMembers(teamId)(dispatch, getState);
|
|
} else {
|
|
await fetchMyChannelsAndMembers(teamId)(dispatch, getState);
|
|
}
|
|
};
|
|
}
|
|
|
|
export function loadProfilesAndTeamMembersForDMSidebar(teamId) {
|
|
return async (dispatch, getState) => {
|
|
const state = getState();
|
|
const {currentUserId} = state.entities.users;
|
|
const {channels, myMembers} = state.entities.channels;
|
|
const {myPreferences} = state.entities.preferences;
|
|
const {membersInTeam} = state.entities.teams;
|
|
const dmPrefs = getPreferencesByCategory(myPreferences, Preferences.CATEGORY_DIRECT_CHANNEL_SHOW);
|
|
const gmPrefs = getPreferencesByCategory(myPreferences, Preferences.CATEGORY_GROUP_CHANNEL_SHOW);
|
|
const members = [];
|
|
const loadProfilesForChannels = [];
|
|
const prefs = [];
|
|
|
|
function buildPref(name) {
|
|
return {
|
|
user_id: currentUserId,
|
|
category: Preferences.CATEGORY_DIRECT_CHANNEL_SHOW,
|
|
name,
|
|
value: 'true'
|
|
};
|
|
}
|
|
|
|
// Find DM's and GM's that need to be shown
|
|
const directChannels = Object.values(channels).filter((c) => (isDirectChannel(c) || isGroupChannel(c)));
|
|
directChannels.forEach((channel) => {
|
|
const member = myMembers[channel.id];
|
|
if (isDirectChannel(channel) && !isDirectChannelVisible(currentUserId, myPreferences, channel) && member.mention_count > 0) {
|
|
const teammateId = getUserIdFromChannelName(currentUserId, channel.name);
|
|
let pref = dmPrefs.get(teammateId);
|
|
if (pref) {
|
|
pref = {...pref, value: 'true'};
|
|
} else {
|
|
pref = buildPref(teammateId);
|
|
}
|
|
dmPrefs.set(teammateId, pref);
|
|
prefs.push(pref);
|
|
} else if (isGroupChannel(channel) && !isGroupChannelVisible(myPreferences, channel) && (member.mention_count > 0 || member.msg_count < channel.total_msg_count)) {
|
|
const id = channel.id;
|
|
let pref = gmPrefs.get(id);
|
|
if (pref) {
|
|
pref = {...pref, value: 'true'};
|
|
} else {
|
|
pref = buildPref(id);
|
|
}
|
|
gmPrefs.set(id, pref);
|
|
prefs.push(pref);
|
|
}
|
|
});
|
|
|
|
if (prefs.length) {
|
|
savePreferences(prefs)(dispatch, getState);
|
|
}
|
|
|
|
for (const [key, pref] of dmPrefs) {
|
|
if (pref.value === 'true') {
|
|
members.push(key);
|
|
}
|
|
}
|
|
|
|
for (const [key, pref] of gmPrefs) {
|
|
if (pref.value === 'true') {
|
|
loadProfilesForChannels.push(key);
|
|
}
|
|
}
|
|
|
|
if (loadProfilesForChannels.length) {
|
|
for (let i = 0; i < loadProfilesForChannels.length; i++) {
|
|
const channelId = loadProfilesForChannels[i];
|
|
getProfilesInChannel(teamId, channelId, 0)(dispatch, getState);
|
|
}
|
|
}
|
|
|
|
let membersToLoad = members;
|
|
if (membersInTeam[teamId]) {
|
|
membersToLoad = members.filter((m) => !membersInTeam[teamId].has(m));
|
|
}
|
|
|
|
if (membersToLoad.length) {
|
|
getTeamMembersByIds(teamId, membersToLoad)(dispatch, getState);
|
|
}
|
|
|
|
const actions = [];
|
|
for (let i = 0; i < members.length; i++) {
|
|
const channelName = getDirectChannelName(currentUserId, members[i]);
|
|
const channel = getChannelByName(channels, channelName);
|
|
if (channel) {
|
|
actions.push({
|
|
type: UsersTypes.RECEIVED_PROFILE_IN_CHANNEL,
|
|
data: {user_id: members[i]},
|
|
id: channel.id
|
|
});
|
|
}
|
|
}
|
|
|
|
if (actions.length) {
|
|
dispatch(batchActions(actions), getState);
|
|
}
|
|
};
|
|
}
|
|
|
|
export function loadPostsIfNecessary(channel) {
|
|
return async (dispatch, getState) => {
|
|
const state = getState();
|
|
const postsInChannel = state.entities.posts.postsByChannel[channel.id];
|
|
|
|
// Make sure we include a team id for DM channels
|
|
const teamId = channel.team_id || state.entities.teams.currentTeamId;
|
|
|
|
// Get the first page of posts if it appears we haven't gotten it yet, like the webapp
|
|
if (!postsInChannel || postsInChannel.length < Constants.POST_CHUNK_SIZE) {
|
|
return getPosts(teamId, channel.id)(dispatch, getState);
|
|
}
|
|
|
|
const latestPostInChannel = state.entities.posts.posts[postsInChannel[0]];
|
|
|
|
return getPostsSince(teamId, channel.id, latestPostInChannel.create_at)(dispatch, getState);
|
|
};
|
|
}
|
|
|
|
export function loadFilesForPostIfNecessary(post) {
|
|
return async (dispatch, getState) => {
|
|
const {files, teams} = getState().entities;
|
|
const fileIdsForPost = files.fileIdsByPostId[post.id];
|
|
|
|
if (!fileIdsForPost) {
|
|
const {currentTeamId} = teams;
|
|
await getFilesForPost(currentTeamId, post.channel_id, post.id)(dispatch, getState);
|
|
}
|
|
};
|
|
}
|
|
|
|
export function selectInitialChannel(teamId) {
|
|
return async (dispatch, getState) => {
|
|
const state = getState();
|
|
const {channels, currentChannelId, myMembers} = state.entities.channels;
|
|
const {currentUserId} = state.entities.users;
|
|
const currentChannel = channels[currentChannelId];
|
|
const {myPreferences} = state.entities.preferences;
|
|
|
|
const isDMVisible = currentChannel && currentChannel.type === Constants.DM_CHANNEL &&
|
|
isDirectChannelVisible(currentUserId, myPreferences, currentChannel);
|
|
|
|
const isGMVisible = currentChannel && currentChannel.type === Constants.GM_CHANNEL &&
|
|
isGroupChannelVisible(myPreferences, currentChannel);
|
|
|
|
if (currentChannel && myMembers[currentChannelId] &&
|
|
(currentChannel.team_id === teamId || isDMVisible || isGMVisible)) {
|
|
await handleSelectChannel(currentChannelId)(dispatch, getState);
|
|
return;
|
|
}
|
|
|
|
const channel = Object.values(channels).find((c) => c.team_id === teamId && c.name === Constants.DEFAULT_CHANNEL);
|
|
if (channel) {
|
|
await handleSelectChannel(channel.id)(dispatch, getState);
|
|
} else {
|
|
// Handle case when the default channel cannot be found
|
|
// so we need to get the first available channel of the team
|
|
const channelsInTeam = Object.values(channels).filter((c) => c.team_id === teamId);
|
|
const firstChannel = channelsInTeam[0].id;
|
|
await handleSelectChannel(firstChannel.id)(dispatch, getState);
|
|
}
|
|
};
|
|
}
|
|
|
|
export function handleSelectChannel(channelId) {
|
|
return async (dispatch, getState) => {
|
|
const {currentTeamId} = getState().entities.teams;
|
|
|
|
updateStorage(currentTeamId, {currentChannelId: channelId});
|
|
getChannelStats(currentTeamId, channelId)(dispatch, getState);
|
|
selectChannel(channelId)(dispatch, getState);
|
|
};
|
|
}
|
|
|
|
export function handlePostDraftChanged(channelId, postDraft) {
|
|
return async (dispatch, getState) => {
|
|
dispatch({
|
|
type: ViewTypes.POST_DRAFT_CHANGED,
|
|
channelId,
|
|
postDraft
|
|
}, getState);
|
|
};
|
|
}
|
|
|
|
export function toggleDMChannel(otherUserId, visible) {
|
|
return async (dispatch, getState) => {
|
|
const state = getState();
|
|
const {currentUserId} = state.entities.users;
|
|
|
|
const dm = [{
|
|
user_id: currentUserId,
|
|
category: Preferences.CATEGORY_DIRECT_CHANNEL_SHOW,
|
|
name: otherUserId,
|
|
value: visible
|
|
}];
|
|
|
|
return savePreferences(dm)(dispatch, getState);
|
|
};
|
|
}
|
|
|
|
export function toggleGMChannel(channelId, visible) {
|
|
return async (dispatch, getState) => {
|
|
const state = getState();
|
|
const {currentUserId} = state.entities.users;
|
|
|
|
const gm = [{
|
|
user_id: currentUserId,
|
|
category: Preferences.CATEGORY_GROUP_CHANNEL_SHOW,
|
|
name: channelId,
|
|
value: visible
|
|
}];
|
|
|
|
return savePreferences(gm)(dispatch, getState);
|
|
};
|
|
}
|
|
|
|
export function closeDMChannel(channel) {
|
|
return async(dispatch, getState) => {
|
|
const state = getState();
|
|
|
|
if (channel.isFavorite) {
|
|
unmarkFavorite(channel.id)(dispatch, getState);
|
|
}
|
|
|
|
toggleDMChannel(channel.teammate_id, 'false')(dispatch, getState).then(() => {
|
|
if (channel.isCurrent) {
|
|
selectInitialChannel(state.entities.teams.currentTeamId)(dispatch, getState);
|
|
}
|
|
});
|
|
};
|
|
}
|
|
|
|
export function closeGMChannel(channel) {
|
|
return async(dispatch, getState) => {
|
|
const state = getState();
|
|
|
|
if (channel.isFavorite) {
|
|
unmarkFavorite(channel.id)(dispatch, getState);
|
|
}
|
|
|
|
toggleGMChannel(channel.id, 'false')(dispatch, getState).then(() => {
|
|
if (channel.isCurrent) {
|
|
selectInitialChannel(state.entities.teams.currentTeamId)(dispatch, getState);
|
|
}
|
|
});
|
|
};
|
|
}
|
|
|
|
export function closeDirectChannel(channel) {
|
|
return async (dispatch, getState) => {
|
|
switch (channel.type) {
|
|
case Constants.DM_CHANNEL:
|
|
return closeDMChannel(channel)(dispatch, getState);
|
|
case Constants.GM_CHANNEL:
|
|
return closeGMChannel(channel)(dispatch, getState);
|
|
}
|
|
|
|
return null;
|
|
};
|
|
}
|
|
|
|
export function markFavorite(channelId) {
|
|
return async (dispatch, getState) => {
|
|
const {currentUserId} = getState().entities.users;
|
|
const fav = [{
|
|
user_id: currentUserId,
|
|
category: Constants.CATEGORY_FAVORITE_CHANNEL,
|
|
name: channelId,
|
|
value: 'true'
|
|
}];
|
|
savePreferences(fav)(dispatch, getState);
|
|
};
|
|
}
|
|
|
|
export function unmarkFavorite(channelId) {
|
|
return async (dispatch, getState) => {
|
|
const {currentUserId} = getState().entities.users;
|
|
const fav = [{
|
|
user_id: currentUserId,
|
|
category: Constants.CATEGORY_FAVORITE_CHANNEL,
|
|
name: channelId
|
|
}];
|
|
deletePreferences(fav)(dispatch, getState);
|
|
};
|
|
}
|
|
|
|
export function leaveChannel(channel, reset = false) {
|
|
return async (dispatch, getState) => {
|
|
const {currentTeamId} = getState().entities.teams;
|
|
await serviceLeaveChannel(currentTeamId, channel.id)(dispatch, getState);
|
|
if (channel.isCurrent || reset) {
|
|
await selectInitialChannel(currentTeamId)(dispatch, getState);
|
|
}
|
|
};
|
|
}
|
|
|
|
export function setChannelLoading(loading = true) {
|
|
return {
|
|
type: ViewTypes.SET_CHANNEL_LOADER,
|
|
loading
|
|
};
|
|
}
|