mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
559 lines
16 KiB
JavaScript
559 lines
16 KiB
JavaScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See License.txt for license information.
|
|
|
|
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
|
|
|
|
import ChannelStore from 'stores/channel_store.jsx';
|
|
import UserStore from 'stores/user_store.jsx';
|
|
import BrowserStore from 'stores/browser_store.jsx';
|
|
import ErrorStore from 'stores/error_store.jsx';
|
|
import TeamStore from 'stores/team_store.jsx';
|
|
import SearchStore from 'stores/search_store.jsx';
|
|
|
|
import {handleNewPost} from 'actions/post_actions.jsx';
|
|
import {loadProfilesForSidebar} from 'actions/user_actions.jsx';
|
|
import {loadChannelsForCurrentUser} from 'actions/channel_actions.jsx';
|
|
import {stopPeriodicStatusUpdates} from 'actions/status_actions.jsx';
|
|
import * as WebsocketActions from 'actions/websocket_actions.jsx';
|
|
import {trackEvent} from 'actions/diagnostics_actions.jsx';
|
|
|
|
import Constants from 'utils/constants.jsx';
|
|
const ActionTypes = Constants.ActionTypes;
|
|
import EventTypes from 'utils/event_types.jsx';
|
|
|
|
import WebSocketClient from 'client/web_websocket_client.jsx';
|
|
import {sortTeamsByDisplayName} from 'utils/team_utils.jsx';
|
|
import * as Utils from 'utils/utils.jsx';
|
|
|
|
import en from 'i18n/en.json';
|
|
import * as I18n from 'i18n/i18n.jsx';
|
|
import {browserHistory} from 'react-router/es6';
|
|
|
|
// Redux actions
|
|
import store from 'stores/redux_store.jsx';
|
|
const dispatch = store.dispatch;
|
|
const getState = store.getState;
|
|
|
|
import {Client4} from 'mattermost-redux/client';
|
|
|
|
import {removeUserFromTeam} from 'mattermost-redux/actions/teams';
|
|
import {viewChannel, getChannelStats, getMyChannelMember, getChannelAndMyMember, createDirectChannel, joinChannel} from 'mattermost-redux/actions/channels';
|
|
import {getPostThread} from 'mattermost-redux/actions/posts';
|
|
|
|
export function emitChannelClickEvent(channel) {
|
|
function userVisitedFakeChannel(chan, success, fail) {
|
|
const currentUserId = UserStore.getCurrentId();
|
|
const otherUserId = Utils.getUserIdFromChannelName(chan);
|
|
createDirectChannel(currentUserId, otherUserId)(dispatch, getState).then(
|
|
(data) => {
|
|
if (data) {
|
|
success(data);
|
|
} else {
|
|
fail();
|
|
}
|
|
}
|
|
);
|
|
}
|
|
function switchToChannel(chan) {
|
|
const channelMember = ChannelStore.getMyMember(chan.id);
|
|
const getMyChannelMemberPromise = getMyChannelMember(chan.id)(dispatch, getState);
|
|
const oldChannelId = ChannelStore.getCurrentId();
|
|
|
|
getMyChannelMemberPromise.then(() => {
|
|
getChannelStats(chan.id)(dispatch, getState);
|
|
viewChannel(chan.id, oldChannelId)(dispatch, getState);
|
|
|
|
// Mark previous and next channel as read
|
|
ChannelStore.resetCounts([chan.id, oldChannelId]);
|
|
});
|
|
|
|
// Subtract mentions for the team
|
|
const {msgs, mentions} = ChannelStore.getUnreadCounts()[chan.id] || {msgs: 0, mentions: 0};
|
|
TeamStore.subtractUnread(chan.team_id, msgs, mentions);
|
|
|
|
BrowserStore.setGlobalItem(chan.team_id, chan.id);
|
|
|
|
loadProfilesForSidebar();
|
|
|
|
AppDispatcher.handleViewAction({
|
|
type: ActionTypes.CLICK_CHANNEL,
|
|
name: chan.name,
|
|
id: chan.id,
|
|
team_id: chan.team_id,
|
|
total_msg_count: chan.total_msg_count,
|
|
channelMember,
|
|
prev: oldChannelId
|
|
});
|
|
}
|
|
|
|
if (channel.fake) {
|
|
userVisitedFakeChannel(
|
|
channel,
|
|
(data) => {
|
|
switchToChannel(data);
|
|
},
|
|
() => {
|
|
browserHistory.push('/' + this.state.currentTeam.name);
|
|
}
|
|
);
|
|
} else {
|
|
switchToChannel(channel);
|
|
}
|
|
}
|
|
|
|
export async function doFocusPost(channelId, postId, data) {
|
|
AppDispatcher.handleServerAction({
|
|
type: ActionTypes.RECEIVED_FOCUSED_POST,
|
|
postId,
|
|
channelId,
|
|
post_list: data
|
|
});
|
|
|
|
dispatch({
|
|
type: ActionTypes.RECEIVED_FOCUSED_POST,
|
|
data: postId,
|
|
channelId
|
|
});
|
|
|
|
const member = getState().entities.channels.myMembers[channelId];
|
|
if (member == null) {
|
|
await joinChannel(UserStore.getCurrentId(), null, channelId)(dispatch, getState);
|
|
}
|
|
|
|
loadChannelsForCurrentUser();
|
|
getChannelStats(channelId)(dispatch, getState);
|
|
}
|
|
|
|
export function emitPostFocusEvent(postId, onSuccess) {
|
|
loadChannelsForCurrentUser();
|
|
getPostThread(postId)(dispatch, getState).then(
|
|
(data) => {
|
|
if (data) {
|
|
const channelId = data.posts[data.order[0]].channel_id;
|
|
doFocusPost(channelId, postId, data).then(() => {
|
|
if (onSuccess) {
|
|
onSuccess();
|
|
}
|
|
});
|
|
} else {
|
|
let link = `${TeamStore.getCurrentTeamRelativeUrl()}/channels/`;
|
|
const channel = ChannelStore.getCurrent();
|
|
if (channel) {
|
|
link += channel.name;
|
|
} else {
|
|
link += 'town-square';
|
|
}
|
|
|
|
const message = encodeURIComponent(Utils.localizeMessage('permalink.error.access', 'Permalink belongs to a deleted message or to a channel to which you do not have access.'));
|
|
const title = encodeURIComponent(Utils.localizeMessage('permalink.error.title', 'Message Not Found'));
|
|
|
|
browserHistory.push('/error?message=' + message + '&title=' + title + '&link=' + encodeURIComponent(link));
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
export function emitCloseRightHandSide() {
|
|
SearchStore.storeSearchResults(null, false, false);
|
|
SearchStore.emitSearchChange();
|
|
|
|
dispatch({
|
|
type: ActionTypes.SELECT_POST,
|
|
postId: ''
|
|
});
|
|
}
|
|
|
|
export function emitPostFocusRightHandSideFromSearch(post, isMentionSearch) {
|
|
getPostThread(post.id)(dispatch, getState).then(
|
|
() => {
|
|
AppDispatcher.handleServerAction({
|
|
type: ActionTypes.RECEIVED_POST_SELECTED,
|
|
postId: Utils.getRootId(post),
|
|
from_search: SearchStore.getSearchTerm(),
|
|
from_flagged_posts: SearchStore.getIsFlaggedPosts(),
|
|
from_pinned_posts: SearchStore.getIsPinnedPosts()
|
|
});
|
|
|
|
AppDispatcher.handleServerAction({
|
|
type: ActionTypes.RECEIVED_SEARCH,
|
|
results: null,
|
|
is_mention_search: isMentionSearch
|
|
});
|
|
}
|
|
);
|
|
}
|
|
|
|
export function emitLeaveTeam() {
|
|
removeUserFromTeam(TeamStore.getCurrentId(), UserStore.getCurrentId())(dispatch, getState);
|
|
}
|
|
|
|
export function emitUserPostedEvent(post) {
|
|
AppDispatcher.handleServerAction({
|
|
type: ActionTypes.CREATE_POST,
|
|
post
|
|
});
|
|
}
|
|
|
|
export function emitUserCommentedEvent(post) {
|
|
AppDispatcher.handleServerAction({
|
|
type: ActionTypes.CREATE_COMMENT,
|
|
post
|
|
});
|
|
}
|
|
|
|
export function showAccountSettingsModal() {
|
|
AppDispatcher.handleViewAction({
|
|
type: ActionTypes.TOGGLE_ACCOUNT_SETTINGS_MODAL,
|
|
value: true
|
|
});
|
|
}
|
|
|
|
export function showDeletePostModal(post, commentCount = 0) {
|
|
AppDispatcher.handleViewAction({
|
|
type: ActionTypes.TOGGLE_DELETE_POST_MODAL,
|
|
value: true,
|
|
post,
|
|
commentCount
|
|
});
|
|
}
|
|
|
|
export function showChannelHeaderUpdateModal(channel) {
|
|
AppDispatcher.handleViewAction({
|
|
type: ActionTypes.TOGGLE_CHANNEL_HEADER_UPDATE_MODAL,
|
|
value: true,
|
|
channel
|
|
});
|
|
}
|
|
|
|
export function showGetPostLinkModal(post) {
|
|
AppDispatcher.handleViewAction({
|
|
type: ActionTypes.TOGGLE_GET_POST_LINK_MODAL,
|
|
value: true,
|
|
post
|
|
});
|
|
}
|
|
|
|
export function showGetPublicLinkModal(fileId) {
|
|
AppDispatcher.handleViewAction({
|
|
type: ActionTypes.TOGGLE_GET_PUBLIC_LINK_MODAL,
|
|
value: true,
|
|
fileId
|
|
});
|
|
}
|
|
|
|
export function showGetTeamInviteLinkModal() {
|
|
AppDispatcher.handleViewAction({
|
|
type: Constants.ActionTypes.TOGGLE_GET_TEAM_INVITE_LINK_MODAL,
|
|
value: true
|
|
});
|
|
}
|
|
|
|
export function showInviteMemberModal() {
|
|
AppDispatcher.handleViewAction({
|
|
type: ActionTypes.TOGGLE_INVITE_MEMBER_MODAL,
|
|
value: true
|
|
});
|
|
}
|
|
|
|
export function showLeaveTeamModal() {
|
|
AppDispatcher.handleViewAction({
|
|
type: ActionTypes.TOGGLE_LEAVE_TEAM_MODAL,
|
|
value: true
|
|
});
|
|
}
|
|
|
|
export function emitSuggestionPretextChanged(suggestionId, pretext) {
|
|
AppDispatcher.handleViewAction({
|
|
type: ActionTypes.SUGGESTION_PRETEXT_CHANGED,
|
|
id: suggestionId,
|
|
pretext
|
|
});
|
|
}
|
|
|
|
export function emitSelectNextSuggestion(suggestionId) {
|
|
AppDispatcher.handleViewAction({
|
|
type: ActionTypes.SUGGESTION_SELECT_NEXT,
|
|
id: suggestionId
|
|
});
|
|
}
|
|
|
|
export function emitSelectPreviousSuggestion(suggestionId) {
|
|
AppDispatcher.handleViewAction({
|
|
type: ActionTypes.SUGGESTION_SELECT_PREVIOUS,
|
|
id: suggestionId
|
|
});
|
|
}
|
|
|
|
export function emitCompleteWordSuggestion(suggestionId, term = '') {
|
|
AppDispatcher.handleViewAction({
|
|
type: Constants.ActionTypes.SUGGESTION_COMPLETE_WORD,
|
|
id: suggestionId,
|
|
term
|
|
});
|
|
}
|
|
|
|
export function emitClearSuggestions(suggestionId) {
|
|
AppDispatcher.handleViewAction({
|
|
type: Constants.ActionTypes.SUGGESTION_CLEAR_SUGGESTIONS,
|
|
id: suggestionId
|
|
});
|
|
}
|
|
|
|
export function emitPreferenceChangedEvent(preference) {
|
|
AppDispatcher.handleServerAction({
|
|
type: Constants.ActionTypes.RECEIVED_PREFERENCE,
|
|
preference
|
|
});
|
|
|
|
if (addedNewDmUser(preference)) {
|
|
loadProfilesForSidebar();
|
|
}
|
|
}
|
|
|
|
export function emitPreferencesChangedEvent(preferences) {
|
|
AppDispatcher.handleServerAction({
|
|
type: Constants.ActionTypes.RECEIVED_PREFERENCES,
|
|
preferences
|
|
});
|
|
|
|
if (preferences.findIndex(addedNewDmUser) !== -1) {
|
|
loadProfilesForSidebar();
|
|
}
|
|
}
|
|
|
|
function addedNewDmUser(preference) {
|
|
return preference.category === Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW && preference.value === 'true';
|
|
}
|
|
|
|
export function emitPreferencesDeletedEvent(preferences) {
|
|
AppDispatcher.handleServerAction({
|
|
type: Constants.ActionTypes.DELETED_PREFERENCES,
|
|
preferences
|
|
});
|
|
}
|
|
|
|
export function emitRemovePost(post) {
|
|
AppDispatcher.handleViewAction({
|
|
type: Constants.ActionTypes.REMOVE_POST,
|
|
post
|
|
});
|
|
}
|
|
|
|
export function sendEphemeralPost(message, channelId) {
|
|
const timestamp = Utils.getTimestamp();
|
|
const post = {
|
|
id: Utils.generateId(),
|
|
user_id: '0',
|
|
channel_id: channelId || ChannelStore.getCurrentId(),
|
|
message,
|
|
type: Constants.PostTypes.EPHEMERAL,
|
|
create_at: timestamp,
|
|
update_at: timestamp,
|
|
props: {}
|
|
};
|
|
|
|
handleNewPost(post);
|
|
}
|
|
|
|
export function newLocalizationSelected(locale) {
|
|
const localeInfo = I18n.getLanguageInfo(locale);
|
|
|
|
if (locale === 'en' || !localeInfo) {
|
|
AppDispatcher.handleServerAction({
|
|
type: ActionTypes.RECEIVED_LOCALE,
|
|
locale,
|
|
translations: en
|
|
});
|
|
} else {
|
|
Client4.getTranslations(localeInfo.url).then(
|
|
(data, res) => {
|
|
let translations = data;
|
|
if (!data && res.text) {
|
|
translations = JSON.parse(res.text);
|
|
}
|
|
AppDispatcher.handleServerAction({
|
|
type: ActionTypes.RECEIVED_LOCALE,
|
|
locale,
|
|
translations
|
|
});
|
|
}
|
|
).catch(
|
|
() => {} //eslint-disable-line no-empty-function
|
|
);
|
|
}
|
|
}
|
|
|
|
export function loadCurrentLocale() {
|
|
const user = UserStore.getCurrentUser();
|
|
|
|
if (user && user.locale) {
|
|
newLocalizationSelected(user.locale);
|
|
} else {
|
|
loadDefaultLocale();
|
|
}
|
|
}
|
|
|
|
export function loadDefaultLocale() {
|
|
let locale = global.window.mm_config.DefaultClientLocale;
|
|
|
|
if (!I18n.getLanguageInfo(locale)) {
|
|
locale = 'en';
|
|
}
|
|
|
|
return newLocalizationSelected(locale);
|
|
}
|
|
|
|
let lastTimeTypingSent = 0;
|
|
export function emitLocalUserTypingEvent(channelId, parentId) {
|
|
const t = Date.now();
|
|
const membersInChannel = ChannelStore.getStats(channelId).member_count;
|
|
|
|
if (((t - lastTimeTypingSent) > global.window.mm_config.TimeBetweenUserTypingUpdatesMilliseconds) && membersInChannel < global.window.mm_config.MaxNotificationsPerChannel && global.window.mm_config.EnableUserTypingMessages === 'true') {
|
|
WebSocketClient.userTyping(channelId, parentId);
|
|
lastTimeTypingSent = t;
|
|
}
|
|
}
|
|
|
|
export function emitRemoteUserTypingEvent(channelId, userId, postParentId) {
|
|
AppDispatcher.handleViewAction({
|
|
type: Constants.ActionTypes.USER_TYPING,
|
|
channelId,
|
|
userId,
|
|
postParentId
|
|
});
|
|
}
|
|
|
|
export function emitUserLoggedOutEvent(redirectTo = '/', shouldSignalLogout = true) {
|
|
Client4.logout().then(
|
|
() => {
|
|
if (shouldSignalLogout) {
|
|
BrowserStore.signalLogout();
|
|
}
|
|
|
|
clientLogout(redirectTo);
|
|
}
|
|
).catch(
|
|
() => {
|
|
browserHistory.push(redirectTo);
|
|
}
|
|
);
|
|
}
|
|
|
|
export function clientLogout(redirectTo = '/') {
|
|
BrowserStore.clear();
|
|
ErrorStore.clearLastError();
|
|
ChannelStore.clear();
|
|
stopPeriodicStatusUpdates();
|
|
WebsocketActions.close();
|
|
document.cookie = 'MMUSERID=;expires=Thu, 01 Jan 1970 00:00:01 GMT;';
|
|
window.location.href = redirectTo;
|
|
}
|
|
|
|
export function emitSearchMentionsEvent(user) {
|
|
let terms = '';
|
|
if (user.notify_props) {
|
|
const termKeys = UserStore.getMentionKeys(user.id);
|
|
|
|
if (termKeys.indexOf('@channel') !== -1) {
|
|
termKeys[termKeys.indexOf('@channel')] = '';
|
|
}
|
|
|
|
if (termKeys.indexOf('@all') !== -1) {
|
|
termKeys[termKeys.indexOf('@all')] = '';
|
|
}
|
|
|
|
terms = termKeys.join(' ');
|
|
}
|
|
|
|
trackEvent('api', 'api_posts_search_mention');
|
|
|
|
AppDispatcher.handleServerAction({
|
|
type: ActionTypes.RECEIVED_SEARCH_TERM,
|
|
term: terms,
|
|
do_search: true,
|
|
is_mention_search: true
|
|
});
|
|
}
|
|
|
|
export function toggleSideBarAction(visible) {
|
|
if (!visible) {
|
|
//Array of actions resolving in the closing of the sidebar
|
|
AppDispatcher.handleServerAction({
|
|
type: ActionTypes.RECEIVED_SEARCH,
|
|
results: null
|
|
});
|
|
|
|
AppDispatcher.handleServerAction({
|
|
type: ActionTypes.RECEIVED_SEARCH_TERM,
|
|
term: null,
|
|
do_search: false,
|
|
is_mention_search: false
|
|
});
|
|
|
|
AppDispatcher.handleServerAction({
|
|
type: ActionTypes.RECEIVED_POST_SELECTED,
|
|
postId: null
|
|
});
|
|
}
|
|
}
|
|
|
|
export function emitBrowserFocus(focus) {
|
|
AppDispatcher.handleViewAction({
|
|
type: ActionTypes.BROWSER_CHANGE_FOCUS,
|
|
focus
|
|
});
|
|
}
|
|
|
|
export function redirectUserToDefaultTeam() {
|
|
const teams = TeamStore.getAll();
|
|
const teamMembers = TeamStore.getMyTeamMembers();
|
|
let teamId = BrowserStore.getGlobalItem('team');
|
|
|
|
function redirect(teamName, channelName) {
|
|
browserHistory.push(`/${teamName}/channels/${channelName}`);
|
|
}
|
|
|
|
if (!teams[teamId] && teamMembers.length > 0) {
|
|
let myTeams = [];
|
|
for (const index in teamMembers) {
|
|
if (teamMembers.hasOwnProperty(index)) {
|
|
const teamMember = teamMembers[index];
|
|
myTeams.push(teams[teamMember.team_id]);
|
|
}
|
|
}
|
|
|
|
if (myTeams.length > 0) {
|
|
myTeams = myTeams.sort(sortTeamsByDisplayName);
|
|
teamId = myTeams[0].id;
|
|
}
|
|
}
|
|
|
|
if (teams[teamId]) {
|
|
const channelId = BrowserStore.getGlobalItem(teamId);
|
|
const channel = ChannelStore.getChannelById(channelId);
|
|
if (channel) {
|
|
redirect(teams[teamId].name, channel);
|
|
} else if (channelId) {
|
|
getChannelAndMyMember(channelId)(dispatch, getState).then(
|
|
(data) => {
|
|
if (data) {
|
|
redirect(teams[teamId].name, data.channel.name);
|
|
} else {
|
|
redirect(teams[teamId].name, 'town-square');
|
|
}
|
|
}
|
|
);
|
|
} else {
|
|
redirect(teams[teamId].name, 'town-square');
|
|
}
|
|
} else {
|
|
browserHistory.push('/select_team');
|
|
}
|
|
}
|
|
|
|
export function postListScrollChange() {
|
|
AppDispatcher.handleViewAction({
|
|
type: EventTypes.POST_LIST_SCROLL_CHANGE
|
|
});
|
|
}
|