337 lines
No EOL
10 KiB
JavaScript
337 lines
No EOL
10 KiB
JavaScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import {batchActions} from 'redux-batched-actions';
|
|
|
|
import {UserTypes} from 'mattermost-redux/action_types';
|
|
import {
|
|
doPostAction,
|
|
getNeededAtMentionedUsernames,
|
|
receivedNewPost,
|
|
receivedPosts,
|
|
receivedPostsBefore,
|
|
receivedPostsInChannel,
|
|
receivedPostsSince,
|
|
receivedPostsInThread,
|
|
} from 'mattermost-redux/actions/posts';
|
|
import {Client4} from 'mattermost-redux/client';
|
|
import {Posts} from 'mattermost-redux/constants';
|
|
import {removeUserFromList} from 'mattermost-redux/utils/user_utils';
|
|
|
|
import {ViewTypes} from 'app/constants';
|
|
import {generateId} from 'app/utils/file';
|
|
|
|
import {getEmojisInPosts} from './emoji';
|
|
|
|
export function sendAddToChannelEphemeralPost(user, addedUsername, message, channelId, postRootId = '') {
|
|
return async (dispatch) => {
|
|
const timestamp = Date.now();
|
|
const post = {
|
|
id: generateId(),
|
|
user_id: user.id,
|
|
channel_id: channelId,
|
|
message,
|
|
type: Posts.POST_TYPES.EPHEMERAL_ADD_TO_CHANNEL,
|
|
create_at: timestamp,
|
|
update_at: timestamp,
|
|
root_id: postRootId,
|
|
parent_id: postRootId,
|
|
props: {
|
|
username: user.username,
|
|
addedUsername,
|
|
},
|
|
};
|
|
|
|
dispatch(receivedNewPost(post));
|
|
};
|
|
}
|
|
|
|
export function setAutocompleteSelector(dataSource, onSelect, options) {
|
|
return {
|
|
type: ViewTypes.SELECTED_ACTION_MENU,
|
|
data: {
|
|
dataSource,
|
|
onSelect,
|
|
options,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function selectAttachmentMenuAction(postId, actionId, text, value) {
|
|
return (dispatch) => {
|
|
dispatch({
|
|
type: ViewTypes.SUBMIT_ATTACHMENT_MENU_ACTION,
|
|
postId,
|
|
data: {
|
|
[actionId]: {
|
|
text,
|
|
value,
|
|
},
|
|
},
|
|
});
|
|
|
|
dispatch(doPostAction(postId, actionId, value));
|
|
};
|
|
}
|
|
|
|
export function getPosts(channelId, page = 0, perPage = Posts.POST_CHUNK_SIZE) {
|
|
return async (dispatch, getState) => {
|
|
try {
|
|
const state = getState();
|
|
const {postsInChannel} = state.entities.posts;
|
|
const postForChannel = postsInChannel[channelId];
|
|
const data = await Client4.getPosts(channelId, page, perPage);
|
|
const posts = Object.values(data.posts);
|
|
const actions = [];
|
|
|
|
if (posts?.length) {
|
|
actions.push(receivedPosts(data));
|
|
const additional = await dispatch(getPostsAdditionalDataBatch(posts));
|
|
if (additional.length) {
|
|
actions.push(...additional);
|
|
}
|
|
}
|
|
|
|
if (posts?.length || !postForChannel) {
|
|
actions.push(receivedPostsInChannel(data, channelId, page === 0, data.prev_post_id === ''));
|
|
}
|
|
|
|
dispatch(batchActions(actions));
|
|
|
|
return {data};
|
|
} catch (error) {
|
|
return {error};
|
|
}
|
|
};
|
|
}
|
|
|
|
export function getPostsSince(channelId, since) {
|
|
return async (dispatch) => {
|
|
try {
|
|
const data = await Client4.getPostsSince(channelId, since);
|
|
const posts = Object.values(data.posts);
|
|
|
|
if (posts?.length) {
|
|
const actions = [
|
|
receivedPosts(data),
|
|
receivedPostsSince(data, channelId),
|
|
];
|
|
|
|
const additional = await dispatch(getPostsAdditionalDataBatch(posts));
|
|
if (additional.length) {
|
|
actions.push(...additional);
|
|
}
|
|
|
|
dispatch(batchActions(actions));
|
|
}
|
|
|
|
return {data};
|
|
} catch (error) {
|
|
return {error};
|
|
}
|
|
};
|
|
}
|
|
|
|
export function getPostsBefore(channelId, postId, page = 0, perPage = Posts.POST_CHUNK_SIZE) {
|
|
return async (dispatch) => {
|
|
try {
|
|
const data = await Client4.getPostsBefore(channelId, postId, page, perPage);
|
|
const posts = Object.values(data.posts);
|
|
|
|
if (posts?.length) {
|
|
const actions = [
|
|
receivedPosts(data),
|
|
receivedPostsBefore(data, channelId, postId, data.prev_post_id === ''),
|
|
];
|
|
|
|
const additional = await dispatch(getPostsAdditionalDataBatch(posts));
|
|
if (additional.length) {
|
|
actions.push(...additional);
|
|
}
|
|
|
|
dispatch(batchActions(actions));
|
|
}
|
|
|
|
return {data};
|
|
} catch (error) {
|
|
return {error};
|
|
}
|
|
};
|
|
}
|
|
|
|
export function getPostThread(rootId) {
|
|
return async (dispatch) => {
|
|
try {
|
|
const data = await Client4.getPostThread(rootId);
|
|
const posts = Object.values(data.posts);
|
|
|
|
if (posts.length) {
|
|
const actions = [
|
|
receivedPosts(data),
|
|
receivedPostsInThread(data, rootId),
|
|
];
|
|
|
|
const additional = await dispatch(getPostsAdditionalDataBatch(posts));
|
|
if (additional.length) {
|
|
actions.push(...additional);
|
|
}
|
|
|
|
dispatch(batchActions(actions));
|
|
}
|
|
|
|
return {data};
|
|
} catch (error) {
|
|
return {error};
|
|
}
|
|
};
|
|
}
|
|
|
|
export function getPostsAround(channelId, postId, perPage = Posts.POST_CHUNK_SIZE / 2) {
|
|
return async (dispatch) => {
|
|
try {
|
|
const [before, thread, after] = await Promise.all([
|
|
Client4.getPostsBefore(channelId, postId, 0, perPage),
|
|
Client4.getPostThread(postId),
|
|
Client4.getPostsAfter(channelId, postId, 0, perPage),
|
|
]);
|
|
|
|
const data = {
|
|
posts: {
|
|
...after.posts,
|
|
...thread.posts,
|
|
...before.posts,
|
|
},
|
|
order: [ // Remember that the order is newest posts first
|
|
...after.order,
|
|
postId,
|
|
...before.order,
|
|
],
|
|
next_post_id: after.next_post_id,
|
|
prev_post_id: before.prev_post_id,
|
|
};
|
|
|
|
const posts = Object.values(data.posts);
|
|
|
|
if (posts?.length) {
|
|
const actions = [
|
|
receivedPosts(data),
|
|
receivedPostsInChannel(data, channelId, after.next_post_id === '', before.prev_post_id === ''),
|
|
];
|
|
|
|
const additional = await dispatch(getPostsAdditionalDataBatch(posts));
|
|
if (additional.length) {
|
|
actions.push(...additional);
|
|
}
|
|
|
|
dispatch(batchActions(actions));
|
|
}
|
|
|
|
return {data};
|
|
} catch (error) {
|
|
return {error};
|
|
}
|
|
};
|
|
}
|
|
|
|
function getPostsAdditionalDataBatch(posts = []) {
|
|
return async (dispatch, getState) => {
|
|
const actions = [];
|
|
|
|
if (!posts.length) {
|
|
return actions;
|
|
}
|
|
|
|
// Custom Emojis used in the posts
|
|
// Do not wait for this as they need to be loaded one by one
|
|
dispatch(getEmojisInPosts(posts));
|
|
|
|
try {
|
|
const state = getState();
|
|
const promises = [];
|
|
const promiseTrace = [];
|
|
const extra = dispatch(profilesStatusesAndToLoadFromPosts(posts));
|
|
|
|
if (extra?.userIds.length) {
|
|
promises.push(Client4.getProfilesByIds(extra.userIds));
|
|
promiseTrace.push('ids');
|
|
}
|
|
|
|
if (extra?.usernames.length) {
|
|
promises.push(Client4.getProfilesByUsernames(extra.usernames));
|
|
promiseTrace.push('usernames');
|
|
}
|
|
|
|
if (extra?.statuses.length) {
|
|
promises.push(Client4.getStatusesByIds(extra.statuses));
|
|
promiseTrace.push('statuses');
|
|
}
|
|
|
|
if (promises.length) {
|
|
const result = await Promise.all(promises);
|
|
result.forEach((p, index) => {
|
|
if (p.length) {
|
|
const type = promiseTrace[index];
|
|
switch (type) {
|
|
case 'statuses':
|
|
actions.push({
|
|
type: UserTypes.RECEIVED_STATUSES,
|
|
data: p,
|
|
});
|
|
break;
|
|
default: {
|
|
const {currentUserId} = state.entities.users;
|
|
|
|
removeUserFromList(currentUserId, p);
|
|
actions.push({
|
|
type: UserTypes.RECEIVED_PROFILES_LIST,
|
|
data: p,
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
} catch (error) {
|
|
// do nothing
|
|
}
|
|
|
|
return actions;
|
|
};
|
|
}
|
|
|
|
function profilesStatusesAndToLoadFromPosts(posts = []) {
|
|
return (dispatch, getState) => {
|
|
const state = getState();
|
|
const {currentUserId, profiles, statuses} = state.entities.users;
|
|
|
|
// Profiles of users mentioned in the posts
|
|
const usernamesToLoad = getNeededAtMentionedUsernames(state, posts);
|
|
|
|
// Statuses and profiles of the users who made the posts
|
|
const userIdsToLoad = new Set();
|
|
const statusesToLoad = new Set();
|
|
|
|
posts.forEach((post) => {
|
|
const userId = post.user_id;
|
|
|
|
if (!statuses[userId]) {
|
|
statusesToLoad.add(userId);
|
|
}
|
|
|
|
if (userId === currentUserId) {
|
|
return;
|
|
}
|
|
|
|
if (!profiles[userId]) {
|
|
userIdsToLoad.add(userId);
|
|
}
|
|
});
|
|
|
|
return {
|
|
usernames: Array.from(usernamesToLoad),
|
|
userIds: Array.from(userIdsToLoad),
|
|
statuses: Array.from(statusesToLoad),
|
|
};
|
|
};
|
|
} |