Improve Redux types part 5/Replace DispatchFunc (#26004)

* Remove non-functional code from Login component

* Remove remaining usage of useDispatch<DispatchFunc>

* Remove usage of DispatchFunc from actions/file_actions

* actions/global_actions

* Remove usage of DispatchFunc from actions/marketplace

* Remove DispatchFunc from actions/post_actions

* Remove DispatchFunc from actions/storage

* Remove DispatchFunc from actions/user_actions

* Remove DispatchFunc from actions/views/channel

* Remove DispatchFunc from actions/views/channel_sidebar

* Remove DispatchFunc from actions/views/create_comment

* Remove DispatchFunc from actions/views/lhs.ts

* Remove DispatchFunc from actions/views/rhs.ts

* Remove DispatchFunc from actions/views/onboarding_tasks

* Remove DispatchFunc from actions/views/root

* Remove DispatchFunc from components/logged_in

* Remove DispatchFunc from components/msg_typing

* Remove DispatchFunc from components/permalink_view

* Remove DispatchFunc from components/suggestion

* Remove DispatchFunc from mattermost-redux/actions/posts

* Remove DispatchFunc from mattermost-redux/actions/roles

* Remove DispatchFunc from mattermost-redux/actions/threads

* Remove DispatchFunc from mattermost-redux/actions/timezone

* Remove DispatchFunc from plugins/products

* Make DispatchFunc into Dispatch

* Fix how dispatch is mocked in test for toggleSideBarRightMenuAction
Этот коммит содержится в:
Harrison Healey
2024-01-24 10:28:38 -05:00
коммит произвёл GitHub
родитель d8e11fe292
Коммит 8e165c7685
72 изменённых файлов: 450 добавлений и 539 удалений

Просмотреть файл

@@ -10,7 +10,7 @@ import {FileTypes} from 'mattermost-redux/action_types';
import {getLogErrorAction} from 'mattermost-redux/actions/errors'; import {getLogErrorAction} from 'mattermost-redux/actions/errors';
import {forceLogoutIfNecessary} from 'mattermost-redux/actions/helpers'; import {forceLogoutIfNecessary} from 'mattermost-redux/actions/helpers';
import {Client4} from 'mattermost-redux/client'; import {Client4} from 'mattermost-redux/client';
import type {DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions'; import type {ThunkActionFunc} from 'mattermost-redux/types/actions';
import type {FilePreviewInfo} from 'components/file_preview/file_preview'; import type {FilePreviewInfo} from 'components/file_preview/file_preview';
@@ -28,8 +28,8 @@ export interface UploadFile {
onError: (err: string | ServerError, clientId: string, channelId: string, rootId: string) => void; onError: (err: string | ServerError, clientId: string, channelId: string, rootId: string) => void;
} }
export function uploadFile({file, name, type, rootId, channelId, clientId, onProgress, onSuccess, onError}: UploadFile) { export function uploadFile({file, name, type, rootId, channelId, clientId, onProgress, onSuccess, onError}: UploadFile): ThunkActionFunc<XMLHttpRequest> {
return (dispatch: DispatchFunc, getState: GetStateFunc): XMLHttpRequest => { return (dispatch, getState) => {
dispatch({type: FileTypes.UPLOAD_FILES_REQUEST}); dispatch({type: FileTypes.UPLOAD_FILES_REQUEST});
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();

Просмотреть файл

@@ -575,10 +575,12 @@ describe('actions/global_actions', () => {
}); });
test('toggleSideBarRightMenuAction', () => { test('toggleSideBarRightMenuAction', () => {
const dispatchMock = async () => { const dispatchMock = (arg: any) => {
return {data: true}; if (typeof arg === 'function') {
arg(dispatchMock);
}
}; };
toggleSideBarRightMenuAction()(dispatchMock); dispatchMock(toggleSideBarRightMenuAction());
expect(closeRhsMenu).toHaveBeenCalled(); expect(closeRhsMenu).toHaveBeenCalled();
expect(closeRightHandSide).toHaveBeenCalled(); expect(closeRightHandSide).toHaveBeenCalled();
expect(closeLhs).toHaveBeenCalled(); expect(closeLhs).toHaveBeenCalled();

Просмотреть файл

@@ -24,7 +24,7 @@ import {getConfig, isPerformanceDebuggingEnabled} from 'mattermost-redux/selecto
import {getBool, getIsOnboardingFlowEnabled, isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {getBool, getIsOnboardingFlowEnabled, isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamId, getMyTeams, getTeam, getMyTeamMember, getTeamMemberships, getActiveTeamsList} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeamId, getMyTeams, getTeam, getMyTeamMember, getTeamMemberships, getActiveTeamsList} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUser, getCurrentUserId, isFirstAdmin} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUser, getCurrentUserId, isFirstAdmin} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc, GetStateFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions'; import type {NewActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {calculateUnreadCount} from 'mattermost-redux/utils/channel_utils'; import {calculateUnreadCount} from 'mattermost-redux/utils/channel_utils';
import {handleNewPost} from 'actions/post_actions'; import {handleNewPost} from 'actions/post_actions';
@@ -229,7 +229,7 @@ export function sendAddToChannelEphemeralPost(user: UserProfile, addedUsername:
let lastTimeTypingSent = 0; let lastTimeTypingSent = 0;
export function emitLocalUserTypingEvent(channelId: string, parentPostId: string) { export function emitLocalUserTypingEvent(channelId: string, parentPostId: string) {
const userTyping = async (actionDispatch: DispatchFunc, actionGetState: GetStateFunc) => { const userTyping: NewActionFuncAsync = async (actionDispatch, actionGetState) => {
const state = actionGetState(); const state = actionGetState();
const config = getConfig(state); const config = getConfig(state);
@@ -282,8 +282,8 @@ export function emitUserLoggedOutEvent(redirectTo = '/', shouldSignalLogout = tr
}); });
} }
export function toggleSideBarRightMenuAction() { export function toggleSideBarRightMenuAction(): ThunkActionFunc<void> {
return (doDispatch: DispatchFunc) => { return (doDispatch) => {
doDispatch(closeRightHandSide()); doDispatch(closeRightHandSide());
doDispatch(closeLhs()); doDispatch(closeLhs());
doDispatch(closeRhsMenu()); doDispatch(closeRhsMenu());

Просмотреть файл

@@ -9,7 +9,7 @@ import {AppBindingLocations, AppCallResponseTypes} from 'mattermost-redux/consta
import {appsEnabled} from 'mattermost-redux/selectors/entities/apps'; import {appsEnabled} from 'mattermost-redux/selectors/entities/apps';
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels'; import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import type {DispatchFunc, GetStateFunc, NewActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions'; import type {NewActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {getFilter, getPlugin} from 'selectors/views/marketplace'; import {getFilter, getPlugin} from 'selectors/views/marketplace';
@@ -142,8 +142,8 @@ export function installPlugin(id: string): ThunkActionFunc<void, GlobalState> {
// installApp installed an App using a given URL a call to the `/install-listed` call path. // installApp installed an App using a given URL a call to the `/install-listed` call path.
// //
// On success, it also requests the current state of the apps to reflect the newly installed app. // On success, it also requests the current state of the apps to reflect the newly installed app.
export function installApp(id: string): ThunkActionFunc<Promise<boolean>> { export function installApp(id: string): ThunkActionFunc<Promise<boolean>, GlobalState> {
return async (dispatch: DispatchFunc, getState: GetStateFunc): Promise<boolean> => { return async (dispatch, getState) => {
dispatch({ dispatch({
type: ActionTypes.INSTALLING_MARKETPLACE_ITEM, type: ActionTypes.INSTALLING_MARKETPLACE_ITEM,
id, id,

Просмотреть файл

@@ -15,7 +15,7 @@ import * as PostSelectors from 'mattermost-redux/selectors/entities/posts';
import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUserId, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUserId, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc, GetStateFunc, NewActionFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions'; import type {DispatchFunc, NewActionFunc, NewActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {canEditPost, comparePosts} from 'mattermost-redux/utils/post_utils'; import {canEditPost, comparePosts} from 'mattermost-redux/utils/post_utils';
import {addRecentEmoji, addRecentEmojis} from 'actions/emoji_actions'; import {addRecentEmoji, addRecentEmojis} from 'actions/emoji_actions';
@@ -78,8 +78,8 @@ export function handleNewPost(post: Post, msg?: {data?: NewPostMessageProps & Gr
const getPostsForIds = PostSelectors.makeGetPostsForIds(); const getPostsForIds = PostSelectors.makeGetPostsForIds();
export function flagPost(postId: string) { export function flagPost(postId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
await dispatch(PostActions.flagPost(postId)); await dispatch(PostActions.flagPost(postId));
const state = getState() as GlobalState; const state = getState() as GlobalState;
const rhsState = getRhsState(state); const rhsState = getRhsState(state);
@@ -92,8 +92,8 @@ export function flagPost(postId: string) {
}; };
} }
export function unflagPost(postId: string) { export function unflagPost(postId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
await dispatch(PostActions.unflagPost(postId)); await dispatch(PostActions.unflagPost(postId));
const state = getState() as GlobalState; const state = getState() as GlobalState;
const rhsState = getRhsState(state); const rhsState = getRhsState(state);
@@ -106,8 +106,8 @@ export function unflagPost(postId: string) {
}; };
} }
export function createPost(post: Post, files: FileInfo[]) { export function createPost(post: Post, files: FileInfo[]): NewActionFuncAsync {
return async (dispatch: DispatchFunc) => { return async (dispatch) => {
// parse message and emit emoji event // parse message and emit emoji event
const emojis = matchEmoticons(post.message); const emojis = matchEmoticons(post.message);
if (emojis) { if (emojis) {
@@ -132,15 +132,15 @@ export function createPost(post: Post, files: FileInfo[]) {
}; };
} }
function storeDraft(channelId: string, draft: null) { function storeDraft(channelId: string, draft: null): NewActionFunc {
return (dispatch: DispatchFunc) => { return (dispatch) => {
dispatch(StorageActions.setGlobalItem('draft_' + channelId, draft)); dispatch(StorageActions.setGlobalItem('draft_' + channelId, draft));
return {data: true}; return {data: true};
}; };
} }
function storeCommentDraft(rootPostId: string, draft: null) { function storeCommentDraft(rootPostId: string, draft: null): NewActionFunc {
return (dispatch: DispatchFunc) => { return (dispatch) => {
dispatch(StorageActions.setGlobalItem('comment_draft_' + rootPostId, draft)); dispatch(StorageActions.setGlobalItem('comment_draft_' + rootPostId, draft));
return {data: true}; return {data: true};
}; };
@@ -202,16 +202,16 @@ export function addReaction(postId: string, emojiName: string): NewActionFunc {
}; };
} }
export function searchForTerm(term: string) { export function searchForTerm(term: string): NewActionFunc<boolean, GlobalState> {
return (dispatch: DispatchFunc) => { return (dispatch) => {
dispatch(RhsActions.updateSearchTerms(term)); dispatch(RhsActions.updateSearchTerms(term));
dispatch(RhsActions.showSearchResults()); dispatch(RhsActions.showSearchResults());
return {data: true}; return {data: true};
}; };
} }
function addPostToSearchResults(postId: string) { function addPostToSearchResults(postId: string): NewActionFunc {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const results = state.entities.search.results; const results = state.entities.search.results;
const index = results.indexOf(postId); const index = results.indexOf(postId);
@@ -251,10 +251,10 @@ function removePostFromSearchResults(postId: string, state: GlobalState, dispatc
} }
} }
export function pinPost(postId: string) { export function pinPost(postId: string): NewActionFuncAsync<boolean, GlobalState> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
await dispatch(PostActions.pinPost(postId)); await dispatch(PostActions.pinPost(postId));
const state = getState() as GlobalState; const state = getState();
const rhsState = getRhsState(state); const rhsState = getRhsState(state);
if (rhsState === RHSStates.PIN) { if (rhsState === RHSStates.PIN) {
@@ -264,10 +264,10 @@ export function pinPost(postId: string) {
}; };
} }
export function unpinPost(postId: string) { export function unpinPost(postId: string): NewActionFuncAsync<boolean, GlobalState> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
await dispatch(PostActions.unpinPost(postId)); await dispatch(PostActions.unpinPost(postId));
const state = getState() as GlobalState; const state = getState();
const rhsState = getRhsState(state); const rhsState = getRhsState(state);
if (rhsState === RHSStates.PIN) { if (rhsState === RHSStates.PIN) {
@@ -337,8 +337,8 @@ export function markPostAsUnread(post: Post, location?: string): NewActionFuncAs
}; };
} }
export function markMostRecentPostInChannelAsUnread(channelId: string) { export function markMostRecentPostInChannelAsUnread(channelId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let state = getState(); let state = getState();
let postId = PostSelectors.getMostRecentPostIdInChannel(state, channelId); let postId = PostSelectors.getMostRecentPostIdInChannel(state, channelId);
if (!postId) { if (!postId) {
@@ -392,11 +392,11 @@ export function deleteAndRemovePost(post: Post): NewActionFuncAsync<boolean, Glo
}; };
} }
export function toggleEmbedVisibility(postId: string) { export function toggleEmbedVisibility(postId: string): ThunkActionFunc<void, GlobalState> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const currentUserId = getCurrentUserId(state); const currentUserId = getCurrentUserId(state);
const visible = isEmbedVisible(state as GlobalState, postId); const visible = isEmbedVisible(state, postId);
dispatch(StorageActions.setGlobalItem(StoragePrefixes.EMBED_VISIBLE + currentUserId + '_' + postId, !visible)); dispatch(StorageActions.setGlobalItem(StoragePrefixes.EMBED_VISIBLE + currentUserId + '_' + postId, !visible));
}; };
@@ -406,11 +406,11 @@ export function resetEmbedVisibility() {
return StorageActions.actionOnGlobalItemsWithPrefix(StoragePrefixes.EMBED_VISIBLE, () => null); return StorageActions.actionOnGlobalItemsWithPrefix(StoragePrefixes.EMBED_VISIBLE, () => null);
} }
export function toggleInlineImageVisibility(postId: string, imageKey: string) { export function toggleInlineImageVisibility(postId: string, imageKey: string): ThunkActionFunc<void, GlobalState> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const currentUserId = getCurrentUserId(state); const currentUserId = getCurrentUserId(state);
const visible = isInlineImageVisible(state as GlobalState, postId, imageKey); const visible = isInlineImageVisible(state, postId, imageKey);
dispatch(StorageActions.setGlobalItem(StoragePrefixes.INLINE_IMAGE_VISIBLE + currentUserId + '_' + postId + '_' + imageKey, !visible)); dispatch(StorageActions.setGlobalItem(StoragePrefixes.INLINE_IMAGE_VISIBLE + currentUserId + '_' + postId + '_' + imageKey, !visible));
}; };

Просмотреть файл

@@ -66,7 +66,7 @@ export function loadStatusesForProfilesList(users: UserProfile[] | null): NewAct
}; };
} }
export function loadStatusesForProfilesMap(users: Record<string, UserProfile> | null): NewActionFunc { export function loadStatusesForProfilesMap(users: Record<string, UserProfile> | UserProfile[] | null): NewActionFunc {
return (dispatch) => { return (dispatch) => {
if (users == null) { if (users == null) {
return {data: false}; return {data: false};

Просмотреть файл

@@ -1,13 +1,13 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import type {DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions'; import type {NewActionFunc} from 'mattermost-redux/types/actions';
import {StorageTypes} from 'utils/constants'; import {StorageTypes} from 'utils/constants';
import {getPrefix} from 'utils/storage_utils'; import {getPrefix} from 'utils/storage_utils';
export function setItem(name: string, value: string) { export function setItem(name: string, value: string): NewActionFunc {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const prefix = getPrefix(state); const prefix = getPrefix(state);
dispatch({ dispatch({
@@ -18,8 +18,8 @@ export function setItem(name: string, value: string) {
}; };
} }
export function removeItem(name: string) { export function removeItem(name: string): NewActionFunc { // HARRISONTODO unused
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const prefix = getPrefix(state); const prefix = getPrefix(state);
dispatch({ dispatch({
@@ -37,8 +37,8 @@ export function setGlobalItem(name: string, value: any) {
}; };
} }
export function removeGlobalItem(name: string) { export function removeGlobalItem(name: string): NewActionFunc {
return (dispatch: DispatchFunc) => { return (dispatch) => {
dispatch({ dispatch({
type: StorageTypes.REMOVE_GLOBAL_ITEM, type: StorageTypes.REMOVE_GLOBAL_ITEM,
data: {name}, data: {name},

Просмотреть файл

@@ -3,6 +3,7 @@
import PQueue from 'p-queue'; import PQueue from 'p-queue';
import type {UserAutocomplete} from '@mattermost/types/autocomplete';
import type {Channel} from '@mattermost/types/channels'; import type {Channel} from '@mattermost/types/channels';
import type {UserProfile, UserStatus} from '@mattermost/types/users'; import type {UserProfile, UserStatus} from '@mattermost/types/users';
@@ -22,7 +23,7 @@ import {
import {getBool, isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {getBool, isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamId, getTeamMember} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeamId, getTeamMember} from 'mattermost-redux/selectors/entities/teams';
import * as Selectors from 'mattermost-redux/selectors/entities/users'; import * as Selectors from 'mattermost-redux/selectors/entities/users';
import type {ActionResult, DispatchFunc, GetStateFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions'; import type {ActionResult, NewActionFunc, NewActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {calculateUnreadCount} from 'mattermost-redux/utils/channel_utils'; import {calculateUnreadCount} from 'mattermost-redux/utils/channel_utils';
import {loadCustomEmojisForCustomStatusesByUserIds} from 'actions/emoji_actions'; import {loadCustomEmojisForCustomStatusesByUserIds} from 'actions/emoji_actions';
@@ -39,8 +40,8 @@ export const queue = new PQueue({concurrency: 4});
const dispatch = store.dispatch; const dispatch = store.dispatch;
const getState = store.getState; const getState = store.getState;
export function loadProfilesAndStatusesInChannel(channelId: string, page = 0, perPage: number = General.PROFILE_CHUNK_SIZE, sort = '', options = {}) { export function loadProfilesAndStatusesInChannel(channelId: string, page = 0, perPage: number = General.PROFILE_CHUNK_SIZE, sort = '', options = {}): NewActionFuncAsync { // HARRISONTODO unused
return async (doDispatch: DispatchFunc) => { return async (doDispatch) => {
const {data} = await doDispatch(UserActions.getProfilesInChannel(channelId, page, perPage, sort, options)); const {data} = await doDispatch(UserActions.getProfilesInChannel(channelId, page, perPage, sort, options));
if (data) { if (data) {
doDispatch(loadStatusesForProfilesList(data)); doDispatch(loadStatusesForProfilesList(data));
@@ -49,8 +50,8 @@ export function loadProfilesAndStatusesInChannel(channelId: string, page = 0, pe
}; };
} }
export function loadProfilesAndReloadTeamMembers(page: number, perPage: number, teamId: string, options = {}) { export function loadProfilesAndReloadTeamMembers(page: number, perPage: number, teamId: string, options = {}): NewActionFuncAsync {
return async (doDispatch: DispatchFunc, doGetState: GetStateFunc) => { return async (doDispatch, doGetState) => {
const newTeamId = teamId || getCurrentTeamId(doGetState()); const newTeamId = teamId || getCurrentTeamId(doGetState());
const {data} = await doDispatch(UserActions.getProfilesInTeam(newTeamId, page, perPage, '', options)); const {data} = await doDispatch(UserActions.getProfilesInTeam(newTeamId, page, perPage, '', options));
if (data) { if (data) {
@@ -64,8 +65,8 @@ export function loadProfilesAndReloadTeamMembers(page: number, perPage: number,
}; };
} }
export function loadProfilesAndReloadChannelMembers(page: number, perPage?: number, channelId?: string, sort = '', options = {}) { export function loadProfilesAndReloadChannelMembers(page: number, perPage?: number, channelId?: string, sort = '', options = {}): NewActionFuncAsync {
return async (doDispatch: DispatchFunc, doGetState: GetStateFunc) => { return async (doDispatch, doGetState) => {
const newChannelId = channelId || getCurrentChannelId(doGetState()); const newChannelId = channelId || getCurrentChannelId(doGetState());
const {data} = await doDispatch(UserActions.getProfilesInChannel(newChannelId, page, perPage, sort, options)); const {data} = await doDispatch(UserActions.getProfilesInChannel(newChannelId, page, perPage, sort, options));
if (data) { if (data) {
@@ -92,8 +93,8 @@ export function loadProfilesAndTeamMembers(page: number, perPage: number, teamId
}; };
} }
export function searchProfilesAndTeamMembers(term = '', options: Record<string, any> = {}) { export function searchProfilesAndTeamMembers(term = '', options: Record<string, any> = {}): NewActionFuncAsync {
return async (doDispatch: DispatchFunc, doGetState: GetStateFunc) => { return async (doDispatch, doGetState) => {
const newTeamId = options.team_id || getCurrentTeamId(doGetState()); const newTeamId = options.team_id || getCurrentTeamId(doGetState());
const {data} = await doDispatch(UserActions.searchProfiles(term, options)); const {data} = await doDispatch(UserActions.searchProfiles(term, options));
if (data) { if (data) {
@@ -107,8 +108,8 @@ export function searchProfilesAndTeamMembers(term = '', options: Record<string,
}; };
} }
export function searchProfilesAndChannelMembers(term: string, options: Record<string, any> = {}) { export function searchProfilesAndChannelMembers(term: string, options: Record<string, any> = {}): NewActionFuncAsync {
return async (doDispatch: DispatchFunc, doGetState: GetStateFunc) => { return async (doDispatch, doGetState) => {
const newChannelId = options.in_channel_id || getCurrentChannelId(doGetState()); const newChannelId = options.in_channel_id || getCurrentChannelId(doGetState());
const {data} = await doDispatch(UserActions.searchProfiles(term, options)); const {data} = await doDispatch(UserActions.searchProfiles(term, options));
if (data) { if (data) {
@@ -140,8 +141,8 @@ export function loadProfilesAndTeamMembersAndChannelMembers(page: number, perPag
}; };
} }
export function loadTeamMembersForProfilesList(profiles: UserProfile[], teamId: string, reloadAllMembers = false) { export function loadTeamMembersForProfilesList(profiles: UserProfile[], teamId: string, reloadAllMembers = false): NewActionFuncAsync {
return async (doDispatch: DispatchFunc, doGetState: GetStateFunc) => { return async (doDispatch, doGetState) => {
const state = doGetState(); const state = doGetState();
const teamIdParam = teamId || getCurrentTeamId(state); const teamIdParam = teamId || getCurrentTeamId(state);
const membersToLoad: Record<string, true> = {}; const membersToLoad: Record<string, true> = {};
@@ -164,18 +165,18 @@ export function loadTeamMembersForProfilesList(profiles: UserProfile[], teamId:
}; };
} }
export function loadProfilesWithoutTeam(page: number, perPage: number, options?: Record<string, any>) { export function loadProfilesWithoutTeam(page: number, perPage: number, options?: Record<string, any>): NewActionFuncAsync {
return async (doDispatch: DispatchFunc) => { return async (doDispatch) => {
const {data} = await doDispatch(UserActions.getProfilesWithoutTeam(page, perPage, options)); const {data} = await doDispatch(UserActions.getProfilesWithoutTeam(page, perPage, options));
doDispatch(loadStatusesForProfilesMap(data)); doDispatch(loadStatusesForProfilesMap(data!));
return data; return {data};
}; };
} }
export function loadTeamMembersAndChannelMembersForProfilesList(profiles: UserProfile[], teamId: string, channelId: string) { export function loadTeamMembersAndChannelMembersForProfilesList(profiles: UserProfile[], teamId: string, channelId: string): NewActionFuncAsync {
return async (doDispatch: DispatchFunc, doGetState: GetStateFunc) => { return async (doDispatch, doGetState) => {
const state = doGetState(); const state = doGetState();
const teamIdParam = teamId || getCurrentTeamId(state); const teamIdParam = teamId || getCurrentTeamId(state);
const channelIdParam = channelId || getCurrentChannelId(state); const channelIdParam = channelId || getCurrentChannelId(state);
@@ -188,8 +189,8 @@ export function loadTeamMembersAndChannelMembersForProfilesList(profiles: UserPr
}; };
} }
export function loadChannelMembersForProfilesList(profiles: UserProfile[], channelId: string, reloadAllMembers = false) { export function loadChannelMembersForProfilesList(profiles: UserProfile[], channelId: string, reloadAllMembers = false): NewActionFuncAsync {
return async (doDispatch: DispatchFunc, doGetState: GetStateFunc) => { return async (doDispatch, doGetState) => {
const state = doGetState(); const state = doGetState();
const channelIdParam = channelId || getCurrentChannelId(state); const channelIdParam = channelId || getCurrentChannelId(state);
const membersToLoad: Record<string, boolean> = {}; const membersToLoad: Record<string, boolean> = {};
@@ -212,8 +213,8 @@ export function loadChannelMembersForProfilesList(profiles: UserProfile[], chann
}; };
} }
export function loadNewDMIfNeeded(channelId: string) { export function loadNewDMIfNeeded(channelId: string): NewActionFuncAsync {
return async (doDispatch: DispatchFunc, doGetState: GetStateFunc) => { return async (doDispatch, doGetState) => {
const state = doGetState(); const state = doGetState();
const currentUserId = Selectors.getCurrentUserId(state); const currentUserId = Selectors.getCurrentUserId(state);
@@ -252,8 +253,8 @@ export function loadNewDMIfNeeded(channelId: string) {
}; };
} }
export function loadNewGMIfNeeded(channelId: string) { export function loadNewGMIfNeeded(channelId: string): NewActionFuncAsync {
return async (doDispatch: DispatchFunc, doGetState: GetStateFunc) => { return async (doDispatch, doGetState) => {
const state = doGetState(); const state = doGetState();
const currentUserId = Selectors.getCurrentUserId(state); const currentUserId = Selectors.getCurrentUserId(state);
@@ -275,8 +276,8 @@ export function loadNewGMIfNeeded(channelId: string) {
}; };
} }
export function loadProfilesForGroupChannels(groupChannels: Channel[]) { export function loadProfilesForGroupChannels(groupChannels: Channel[]): NewActionFunc {
return (doDispatch: DispatchFunc, doGetState: GetStateFunc) => { return (doDispatch, doGetState) => {
const state = doGetState(); const state = doGetState();
const userIdsInChannels = Selectors.getUserIdsInChannels(state); const userIdsInChannels = Selectors.getUserIdsInChannels(state);
@@ -415,27 +416,27 @@ export async function loadProfilesForDM() {
await dispatch(loadCustomEmojisForCustomStatusesByUserIds(profileIds)); await dispatch(loadCustomEmojisForCustomStatusesByUserIds(profileIds));
} }
export function autocompleteUsersInTeam(username: string) { export function autocompleteUsersInTeam(username: string): ThunkActionFunc<Promise<UserAutocomplete>> {
return async (doDispatch: DispatchFunc, doGetState: GetStateFunc) => { return async (doDispatch, doGetState) => {
const currentTeamId = getCurrentTeamId(doGetState()); const currentTeamId = getCurrentTeamId(doGetState());
const {data} = await doDispatch(UserActions.autocompleteUsers(username, currentTeamId)); const {data} = await doDispatch(UserActions.autocompleteUsers(username, currentTeamId));
return data; return data!;
}; };
} }
export function autocompleteUsers(username: string) { export function autocompleteUsers(username: string): ThunkActionFunc<Promise<UserAutocomplete>> {
return async (doDispatch: DispatchFunc) => { return async (doDispatch) => {
const {data} = await doDispatch(UserActions.autocompleteUsers(username)); const {data} = await doDispatch(UserActions.autocompleteUsers(username));
return data; return data!;
}; };
} }
export function autoResetStatus() { export function autoResetStatus(): NewActionFuncAsync<UserStatus> {
return async (doDispatch: DispatchFunc): Promise<{data: UserStatus}> => { return async (doDispatch) => {
const {currentUserId} = getState().entities.users; const {currentUserId} = getState().entities.users;
const {data: userStatus} = await doDispatch(UserActions.getStatus(currentUserId)); const {data: userStatus} = await doDispatch(UserActions.getStatus(currentUserId));
if (userStatus.status === UserStatuses.OUT_OF_OFFICE || !userStatus.manual) { if (userStatus!.status === UserStatuses.OUT_OF_OFFICE || !userStatus!.manual) {
return {data: userStatus}; return {data: userStatus};
} }

Просмотреть файл

@@ -4,6 +4,7 @@
import type {AnyAction} from 'redux'; import type {AnyAction} from 'redux';
import {batchActions} from 'redux-batched-actions'; import {batchActions} from 'redux-batched-actions';
import type {UserAutocomplete} from '@mattermost/types/autocomplete';
import type {Channel} from '@mattermost/types/channels'; import type {Channel} from '@mattermost/types/channels';
import {TeamTypes} from 'mattermost-redux/action_types'; import {TeamTypes} from 'mattermost-redux/action_types';
@@ -41,7 +42,7 @@ import {
} from 'mattermost-redux/selectors/entities/teams'; } from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUserId, getUserByUsername} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUserId, getUserByUsername} from 'mattermost-redux/selectors/entities/users';
import {makeAddLastViewAtToProfiles} from 'mattermost-redux/selectors/entities/utils'; import {makeAddLastViewAtToProfiles} from 'mattermost-redux/selectors/entities/utils';
import type {DispatchFunc, GetStateFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions'; import type {NewActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {getChannelByName} from 'mattermost-redux/utils/channel_utils'; import {getChannelByName} from 'mattermost-redux/utils/channel_utils';
import EventEmitter from 'mattermost-redux/utils/event_emitter'; import EventEmitter from 'mattermost-redux/utils/event_emitter';
@@ -60,8 +61,8 @@ import {Constants, ActionTypes, EventTypes, PostRequestTypes} from 'utils/consta
import type {GlobalState} from 'types/store'; import type {GlobalState} from 'types/store';
export function goToLastViewedChannel() { export function goToLastViewedChannel(): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState(); const state = getState();
const currentChannel = getCurrentChannel(state) || {}; const currentChannel = getCurrentChannel(state) || {};
const channelsInTeam = getChannelsNameMapInCurrentTeam(state); const channelsInTeam = getChannelsNameMapInCurrentTeam(state);
@@ -78,21 +79,21 @@ export function goToLastViewedChannel() {
}; };
} }
export function switchToChannelById(channelId: string) { export function switchToChannelById(channelId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState(); const state = getState();
const channel = getChannel(state, channelId); const channel = getChannel(state, channelId);
return dispatch(switchToChannel(channel)); return dispatch(switchToChannel(channel));
}; };
} }
export function loadIfNecessaryAndSwitchToChannelById(channelId: string) { export function loadIfNecessaryAndSwitchToChannelById(channelId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState(); const state = getState();
let channel = getChannel(state, channelId); let channel = getChannel(state, channelId);
if (!channel) { if (!channel) {
const res = await dispatch(loadChannel(channelId)); const res = await dispatch(loadChannel(channelId));
channel = res.data; channel = res.data!;
} }
return dispatch(switchToChannel(channel)); return dispatch(switchToChannel(channel));
}; };
@@ -129,8 +130,8 @@ export function switchToChannel(channel: Channel & {userId?: string}): NewAction
}; };
} }
export function joinChannelById(channelId: string) { export function joinChannelById(channelId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState(); const state = getState();
const currentUserId = getCurrentUserId(state); const currentUserId = getCurrentUserId(state);
const currentTeamId = getCurrentTeamId(state); const currentTeamId = getCurrentTeamId(state);
@@ -139,8 +140,8 @@ export function joinChannelById(channelId: string) {
}; };
} }
export function leaveChannel(channelId: string) { export function leaveChannel(channelId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let state = getState(); let state = getState();
const currentUserId = getCurrentUserId(state); const currentUserId = getCurrentUserId(state);
const currentTeam = getCurrentTeam(state); const currentTeam = getCurrentTeam(state);
@@ -190,8 +191,8 @@ export function leaveChannel(channelId: string) {
}; };
} }
export function leaveDirectChannel(channelName: string) { export function leaveDirectChannel(channelName: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState(); const state = getState();
const currentUserId = getCurrentUserId(state); const currentUserId = getCurrentUserId(state);
const teams = getTeamsList(state); // dms are shared across teams but on local storage are set linked to one, we need to look into all. const teams = getTeamsList(state); // dms are shared across teams but on local storage are set linked to one, we need to look into all.
@@ -210,9 +211,9 @@ export function leaveDirectChannel(channelName: string) {
}; };
} }
export function autocompleteUsersInChannel(prefix: string, channelId: string) { export function autocompleteUsersInChannel(prefix: string, channelId: string): NewActionFuncAsync<UserAutocomplete> {
const addLastViewAtToProfiles = makeAddLastViewAtToProfiles(); const addLastViewAtToProfiles = makeAddLastViewAtToProfiles();
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState(); const state = getState();
const currentTeamId = getCurrentTeamId(state); const currentTeamId = getCurrentTeamId(state);
@@ -292,8 +293,8 @@ export function loadUnreads(channelId: string, prefetch = false): NewActionFuncA
}; };
} }
export function loadPostsAround(channelId: string, focusedPostId: string) { export function loadPostsAround(channelId: string, focusedPostId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc) => { return async (dispatch) => {
const {data, error} = await dispatch(PostActions.getPostsAround(channelId, focusedPostId, Posts.POST_CHUNK_SIZE / 2)); const {data, error} = await dispatch(PostActions.getPostsAround(channelId, focusedPostId, Posts.POST_CHUNK_SIZE / 2));
if (error) { if (error) {
return { return {
@@ -306,17 +307,17 @@ export function loadPostsAround(channelId: string, focusedPostId: string) {
dispatch({ dispatch({
type: ActionTypes.INCREASE_POST_VISIBILITY, type: ActionTypes.INCREASE_POST_VISIBILITY,
data: channelId, data: channelId,
amount: data.order.length, amount: data!.order.length,
}); });
return { return {
atLatestMessage: data.next_post_id === '', atLatestMessage: data!.next_post_id === '',
atOldestmessage: data.prev_post_id === '', atOldestmessage: data!.prev_post_id === '',
}; };
}; };
} }
export function loadLatestPosts(channelId: string) { export function loadLatestPosts(channelId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc) => { return async (dispatch) => {
const time = Date.now(); const time = Date.now();
const {data, error} = await dispatch(PostActions.getPosts(channelId, 0, Posts.POST_CHUNK_SIZE / 2)); const {data, error} = await dispatch(PostActions.getPosts(channelId, 0, Posts.POST_CHUNK_SIZE / 2));
@@ -336,8 +337,8 @@ export function loadLatestPosts(channelId: string) {
return { return {
data, data,
atLatestMessage: data.next_post_id === '', atLatestMessage: data!.next_post_id === '',
atOldestmessage: data.prev_post_id === '', atOldestmessage: data!.prev_post_id === '',
}; };
}; };
} }
@@ -359,9 +360,9 @@ export function loadPosts({
channelId, channelId,
postId, postId,
type, type,
}: LoadPostsParameters) { }: LoadPostsParameters): ThunkActionFunc<Promise<LoadPostsReturnValue>> {
//type here can be BEFORE_ID or AFTER_ID //type here can be BEFORE_ID or AFTER_ID
return async (dispatch: DispatchFunc): Promise<LoadPostsReturnValue> => { return async (dispatch) => {
const POST_INCREASE_AMOUNT = Constants.POST_CHUNK_SIZE / 2; const POST_INCREASE_AMOUNT = Constants.POST_CHUNK_SIZE / 2;
dispatch({ dispatch({
@@ -393,23 +394,23 @@ export function loadPosts({
}; };
} }
dispatch(loadCustomStatusEmojisForPostList(data.posts)); dispatch(loadCustomStatusEmojisForPostList(data!.posts));
actions.push({ actions.push({
type: ActionTypes.INCREASE_POST_VISIBILITY, type: ActionTypes.INCREASE_POST_VISIBILITY,
data: channelId, data: channelId,
amount: data.order.length, amount: data!.order.length,
}); });
dispatch(batchActions(actions)); dispatch(batchActions(actions));
return { return {
moreToLoad: type === PostRequestTypes.BEFORE_ID ? data.prev_post_id !== '' : data.next_post_id !== '', moreToLoad: type === PostRequestTypes.BEFORE_ID ? data!.prev_post_id !== '' : data!.next_post_id !== '',
}; };
}; };
} }
export function syncPostsInChannel(channelId: string, since: number, prefetch = false) { export function syncPostsInChannel(channelId: string, since: number, prefetch = false): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const time = Date.now(); const time = Date.now();
const state = getState(); const state = getState();
const socketStatus = getSocketStatus(state as GlobalState); const socketStatus = getSocketStatus(state as GlobalState);
@@ -483,8 +484,8 @@ export function scrollPostListToBottom() {
}; };
} }
export function markChannelAsReadOnFocus(channelId: string) { export function markChannelAsReadOnFocus(channelId: string): ThunkActionFunc<void> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
if (isManuallyUnread(getState(), channelId)) { if (isManuallyUnread(getState(), channelId)) {
return; return;
} }
@@ -494,21 +495,19 @@ export function markChannelAsReadOnFocus(channelId: string) {
} }
export function updateToastStatus(status: boolean) { export function updateToastStatus(status: boolean) {
return (dispatch: DispatchFunc) => { return {
dispatch({ type: ActionTypes.UPDATE_TOAST_STATUS,
type: ActionTypes.UPDATE_TOAST_STATUS, data: status,
data: status,
});
}; };
} }
export function deleteChannel(channelId: string) { export function deleteChannel(channelId: string): NewActionFuncAsync<boolean, GlobalState> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const res = await dispatch(deleteChannelRedux(channelId)); const res = await dispatch(deleteChannelRedux(channelId));
if (res.error) { if (res.error) {
return {data: false}; return {data: false};
} }
const state = getState() as GlobalState; const state = getState();
const selectedPost = getSelectedPost(state); const selectedPost = getSelectedPost(state);
const selectedPostId = getSelectedPostId(state); const selectedPostId = getSelectedPostId(state);

Просмотреть файл

@@ -6,7 +6,7 @@ import {General} from 'mattermost-redux/constants';
import {CategoryTypes} from 'mattermost-redux/constants/channel_categories'; import {CategoryTypes} from 'mattermost-redux/constants/channel_categories';
import {getCategory, makeGetChannelIdsForCategory} from 'mattermost-redux/selectors/entities/channel_categories'; import {getCategory, makeGetChannelIdsForCategory} from 'mattermost-redux/selectors/entities/channel_categories';
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels'; import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
import type {DispatchFunc, GetStateFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions'; import type {NewActionFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions';
import {insertMultipleWithoutDuplicates} from 'mattermost-redux/utils/array_utils'; import {insertMultipleWithoutDuplicates} from 'mattermost-redux/utils/array_utils';
import {getCategoriesForCurrentTeam, getChannelsInCategoryOrder, getDisplayedChannels} from 'selectors/views/channel_sidebar'; import {getCategoriesForCurrentTeam, getChannelsInCategoryOrder, getDisplayedChannels} from 'selectors/views/channel_sidebar';
@@ -33,7 +33,7 @@ export function stopDragging() {
return {type: ActionTypes.SIDEBAR_DRAGGING_STOP}; return {type: ActionTypes.SIDEBAR_DRAGGING_STOP};
} }
export function createCategory(teamId: string, displayName: string, channelIds?: string[]): NewActionFuncAsync { export function createCategory(teamId: string, displayName: string, channelIds?: string[]): NewActionFuncAsync<unknown, GlobalState> {
return async (dispatch, getState) => { return async (dispatch, getState) => {
if (channelIds) { if (channelIds) {
const state = getState() as GlobalState; const state = getState() as GlobalState;
@@ -61,9 +61,9 @@ export function addChannelsInSidebar(categoryId: string, channelId: string) {
// moveChannelsInSidebar moves channels to a given category in the sidebar, but it accounts for when the target index // moveChannelsInSidebar moves channels to a given category in the sidebar, but it accounts for when the target index
// may have changed due to archived channels not being shown in the sidebar. // may have changed due to archived channels not being shown in the sidebar.
export function moveChannelsInSidebar(categoryId: string, targetIndex: number, draggableChannelId: string, setManualSorting = true) { export function moveChannelsInSidebar(categoryId: string, targetIndex: number, draggableChannelId: string, setManualSorting = true): NewActionFuncAsync<unknown, GlobalState> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState() as GlobalState; const state = getState();
const multiSelectedChannelIds = state.views.channelSidebar.multiSelectedChannelIds; const multiSelectedChannelIds = state.views.channelSidebar.multiSelectedChannelIds;
let channelIds = []; let channelIds = [];
@@ -137,24 +137,26 @@ export function adjustTargetIndexForMove(state: GlobalState, categoryId: string,
return Math.max(newIndex - removedChannelsAboveInsert.length, 0); return Math.max(newIndex - removedChannelsAboveInsert.length, 0);
} }
export function clearChannelSelection() { export function clearChannelSelection(): NewActionFunc<unknown, GlobalState> {
return (dispatch: DispatchFunc, getState: () => GlobalState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
if (state.views.channelSidebar.multiSelectedChannelIds.length === 0) { if (state.views.channelSidebar.multiSelectedChannelIds.length === 0) {
// No selection to clear // No selection to clear
return Promise.resolve({data: true}); return {data: false};
} }
return dispatch({ dispatch({
type: ActionTypes.MULTISELECT_CHANNEL_CLEAR, type: ActionTypes.MULTISELECT_CHANNEL_CLEAR,
}); });
return {data: true};
}; };
} }
export function multiSelectChannelAdd(channelId: string) { export function multiSelectChannelAdd(channelId: string): NewActionFunc<unknown, GlobalState> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState() as GlobalState; const state = getState();
const multiSelectedChannelIds = state.views.channelSidebar.multiSelectedChannelIds; const multiSelectedChannelIds = state.views.channelSidebar.multiSelectedChannelIds;
// Nothing already selected, so we include the active channel // Nothing already selected, so we include the active channel
@@ -173,20 +175,18 @@ export function multiSelectChannelAdd(channelId: string) {
}; };
} }
export function setFirstChannelName(channelName: string) { export function setFirstChannelName(channelName: string) { // HARRISONTODO unused
return (dispatch: DispatchFunc) => { return {
dispatch({ type: ActionTypes.FIRST_CHANNEL_NAME,
type: ActionTypes.FIRST_CHANNEL_NAME, data: channelName,
data: channelName,
});
}; };
} }
// Much of this logic was pulled from the react-beautiful-dnd sample multiselect implementation // Much of this logic was pulled from the react-beautiful-dnd sample multiselect implementation
// Found here: https://github.com/atlassian/react-beautiful-dnd/tree/master/stories/src/multi-drag // Found here: https://github.com/atlassian/react-beautiful-dnd/tree/master/stories/src/multi-drag
export function multiSelectChannelTo(channelId: string) { export function multiSelectChannelTo(channelId: string): NewActionFunc<unknown, GlobalState> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState() as GlobalState; const state = getState();
const multiSelectedChannelIds = state.views.channelSidebar.multiSelectedChannelIds; const multiSelectedChannelIds = state.views.channelSidebar.multiSelectedChannelIds;
let lastSelected = state.views.channelSidebar.lastSelectedChannel; let lastSelected = state.views.channelSidebar.lastSelectedChannel;
@@ -209,7 +209,7 @@ export function multiSelectChannelTo(channelId: string) {
// nothing to do here // nothing to do here
if (indexOfNew === indexOfLast) { if (indexOfNew === indexOfLast) {
return null; return {data: false};
} }
const start: number = Math.min(indexOfLast, indexOfNew); const start: number = Math.min(indexOfLast, indexOfNew);

Просмотреть файл

@@ -18,7 +18,7 @@ import {
} from 'mattermost-redux/selectors/entities/posts'; } from 'mattermost-redux/selectors/entities/posts';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc, GetStateFunc, NewActionFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions'; import type {NewActionFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions';
import {isPostPendingOrFailed} from 'mattermost-redux/utils/post_utils'; import {isPostPendingOrFailed} from 'mattermost-redux/utils/post_utils';
import {executeCommand} from 'actions/command'; import {executeCommand} from 'actions/command';
@@ -52,10 +52,10 @@ export function updateCommentDraft(rootId: string, draft?: PostDraft, save = fal
return updateDraft(key, draft ?? null, rootId, save); return updateDraft(key, draft ?? null, rootId, save);
} }
export function makeOnMoveHistoryIndex(rootId: string, direction: number) { export function makeOnMoveHistoryIndex(rootId: string, direction: number): () => NewActionFunc<boolean, GlobalState> { // HARRISONTODO unused
const getMessageInHistory = makeGetMessageInHistoryItem(Posts.MESSAGE_TYPES.COMMENT as 'comment'); const getMessageInHistory = makeGetMessageInHistoryItem(Posts.MESSAGE_TYPES.COMMENT as 'comment');
return () => (dispatch: DispatchFunc, getState: () => GlobalState) => { return () => (dispatch, getState) => {
const draft = getPostDraft(getState(), StoragePrefixes.COMMENT_DRAFT, rootId); const draft = getPostDraft(getState(), StoragePrefixes.COMMENT_DRAFT, rootId);
if (draft.message !== '' && draft.message !== getMessageInHistory(getState())) { if (draft.message !== '' && draft.message !== getMessageInHistory(getState())) {
return {data: true}; return {data: true};
@@ -74,8 +74,8 @@ export function makeOnMoveHistoryIndex(rootId: string, direction: number) {
}; };
} }
export function submitPost(channelId: string, rootId: string, draft: PostDraft) { export function submitPost(channelId: string, rootId: string, draft: PostDraft): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState(); const state = getState();
const userId = getCurrentUserId(state); const userId = getCurrentUserId(state);
@@ -105,8 +105,8 @@ export function submitPost(channelId: string, rootId: string, draft: PostDraft)
}; };
} }
export function submitCommand(channelId: string, rootId: string, draft: PostDraft) { export function submitCommand(channelId: string, rootId: string, draft: PostDraft): NewActionFuncAsync<unknown, GlobalState> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState(); const state = getState();
const teamId = getCurrentTeamId(state); const teamId = getCurrentTeamId(state);
@@ -122,13 +122,13 @@ export function submitCommand(channelId: string, rootId: string, draft: PostDraf
const hookResult = await dispatch(runSlashCommandWillBePostedHooks(message, args)); const hookResult = await dispatch(runSlashCommandWillBePostedHooks(message, args));
if (hookResult.error) { if (hookResult.error) {
return {error: hookResult.error}; return {error: hookResult.error};
} else if (!hookResult.data.message && !hookResult.data.args) { } else if (!hookResult.data!.message && !hookResult.data!.args) {
// do nothing with an empty return from a hook // do nothing with an empty return from a hook
return {}; return {};
} }
message = hookResult.data.message; message = hookResult.data!.message;
args = hookResult.data.args; args = hookResult.data!.args;
const {error} = await dispatch(executeCommand(message, args)); const {error} = await dispatch(executeCommand(message, args));

Просмотреть файл

@@ -3,8 +3,6 @@
import type {MockStoreEnhanced} from 'redux-mock-store'; import type {MockStoreEnhanced} from 'redux-mock-store';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {close, open, toggle} from 'actions/views/lhs'; import {close, open, toggle} from 'actions/views/lhs';
import configureStore from 'store'; import configureStore from 'store';
@@ -24,7 +22,7 @@ describe('lhs view actions', () => {
}, },
}; };
let store: MockStoreEnhanced<GlobalState, DispatchFunc>; let store: MockStoreEnhanced<GlobalState>;
beforeEach(() => { beforeEach(() => {
store = mockStore(initialState); store = mockStore(initialState);

Просмотреть файл

@@ -3,7 +3,7 @@
import {selectChannel} from 'mattermost-redux/actions/channels'; import {selectChannel} from 'mattermost-redux/actions/channels';
import {getCurrentRelativeTeamUrl} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentRelativeTeamUrl} from 'mattermost-redux/selectors/entities/teams';
import type {DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions'; import type {NewActionFunc, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {SidebarSize} from 'components/resizable_sidebar/constants'; import {SidebarSize} from 'components/resizable_sidebar/constants';
@@ -59,8 +59,8 @@ export const selectStaticPage = (itemId: string) => ({
data: itemId, data: itemId,
}); });
export const selectLhsItem = (type: LhsItemType, id?: string) => { export const selectLhsItem = (type: LhsItemType, id?: string): ThunkActionFunc<unknown> => {
return (dispatch: DispatchFunc) => { return (dispatch) => {
switch (type) { switch (type) {
case LhsItemType.Channel: case LhsItemType.Channel:
dispatch(selectChannel(id || '')); dispatch(selectChannel(id || ''));
@@ -80,9 +80,9 @@ export const selectLhsItem = (type: LhsItemType, id?: string) => {
}; };
}; };
export function switchToLhsStaticPage(id: string) { export function switchToLhsStaticPage(id: string): NewActionFunc<boolean, GlobalState> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState() as GlobalState; const state = getState();
const teamUrl = getCurrentRelativeTeamUrl(state); const teamUrl = getCurrentRelativeTeamUrl(state);
getHistory().push(`${teamUrl}/${id}`); getHistory().push(`${teamUrl}/${id}`);

Просмотреть файл

@@ -3,7 +3,7 @@
import {getCurrentUser, getCurrentUserId} from 'mattermost-redux/selectors/entities/common'; import {getCurrentUser, getCurrentUserId} from 'mattermost-redux/selectors/entities/common';
import {getCurrentTeamId, getTeam} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeamId, getTeam} from 'mattermost-redux/selectors/entities/teams';
import type {DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions'; import type {NewActionFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions';
import {getTeamRedirectChannelIfIsAccesible} from 'actions/global_actions'; import {getTeamRedirectChannelIfIsAccesible} from 'actions/global_actions';
import LocalStorageStore from 'stores/local_storage_store'; import LocalStorageStore from 'stores/local_storage_store';
@@ -13,13 +13,11 @@ import InvitationModal from 'components/invitation_modal';
import {getHistory} from 'utils/browser_history'; import {getHistory} from 'utils/browser_history';
import {ActionTypes, Constants, ModalIdentifiers} from 'utils/constants'; import {ActionTypes, Constants, ModalIdentifiers} from 'utils/constants';
import type {GlobalState} from 'types/store';
import {openModal} from './modals'; import {openModal} from './modals';
export function switchToChannels() { export function switchToChannels(): NewActionFuncAsync<boolean> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState() as GlobalState; const state = getState();
const currentUserId = getCurrentUserId(state); const currentUserId = getCurrentUserId(state);
const user = getCurrentUser(state); const user = getCurrentUser(state);
const teamId = getCurrentTeamId(state) || LocalStorageStore.getPreviousTeamId(currentUserId); const teamId = getCurrentTeamId(state) || LocalStorageStore.getPreviousTeamId(currentUserId);
@@ -33,8 +31,8 @@ export function switchToChannels() {
}; };
} }
export function openInvitationsModal(timeout = 1) { export function openInvitationsModal(timeout = 1): NewActionFunc {
return (dispatch: DispatchFunc) => { return (dispatch) => {
dispatch(switchToChannels()); dispatch(switchToChannels());
setTimeout(() => { setTimeout(() => {
dispatch(openModal({ dispatch(openModal({

Просмотреть файл

@@ -2,6 +2,7 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import {cloneDeep, set} from 'lodash'; import {cloneDeep, set} from 'lodash';
import type {Dispatch} from 'redux';
import {batchActions} from 'redux-batched-actions'; import {batchActions} from 'redux-batched-actions';
import type {MockStoreEnhanced} from 'redux-mock-store'; import type {MockStoreEnhanced} from 'redux-mock-store';
@@ -12,7 +13,6 @@ import type {IDMappedObjects} from '@mattermost/types/utilities';
import {SearchTypes} from 'mattermost-redux/action_types'; import {SearchTypes} from 'mattermost-redux/action_types';
import * as PostActions from 'mattermost-redux/actions/posts'; import * as PostActions from 'mattermost-redux/actions/posts';
import * as SearchActions from 'mattermost-redux/actions/search'; import * as SearchActions from 'mattermost-redux/actions/search';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions.jsx'; import {trackEvent} from 'actions/telemetry_actions.jsx';
import { import {
@@ -132,7 +132,7 @@ describe('rhs view actions', () => {
}, },
} as GlobalState; } as GlobalState;
let store: MockStoreEnhanced<GlobalState, DispatchFunc>; let store: MockStoreEnhanced<GlobalState>;
beforeEach(() => { beforeEach(() => {
store = mockStore(initialState); store = mockStore(initialState);
@@ -277,7 +277,7 @@ describe('rhs view actions', () => {
describe('showFlaggedPosts', () => { describe('showFlaggedPosts', () => {
test('it dispatches the right actions', async () => { test('it dispatches the right actions', async () => {
(SearchActions.getFlaggedPosts as jest.Mock).mockReturnValue((dispatch: DispatchFunc) => { (SearchActions.getFlaggedPosts as jest.Mock).mockReturnValue((dispatch: Dispatch) => {
dispatch({type: 'MOCK_GET_FLAGGED_POSTS'}); dispatch({type: 'MOCK_GET_FLAGGED_POSTS'});
return {data: 'data'}; return {data: 'data'};
@@ -321,7 +321,7 @@ describe('rhs view actions', () => {
describe('showPinnedPosts', () => { describe('showPinnedPosts', () => {
test('it dispatches the right actions for the current channel', async () => { test('it dispatches the right actions for the current channel', async () => {
(SearchActions.getPinnedPosts as jest.Mock).mockReturnValue((dispatch: DispatchFunc) => { (SearchActions.getPinnedPosts as jest.Mock).mockReturnValue((dispatch: Dispatch) => {
dispatch({type: 'MOCK_GET_PINNED_POSTS'}); dispatch({type: 'MOCK_GET_PINNED_POSTS'});
return {data: 'data'}; return {data: 'data'};
@@ -367,7 +367,7 @@ describe('rhs view actions', () => {
test('it dispatches the right actions for a specific channel', async () => { test('it dispatches the right actions for a specific channel', async () => {
const channelId = 'channel1'; const channelId = 'channel1';
(SearchActions.getPinnedPosts as jest.Mock).mockReturnValue((dispatch: DispatchFunc) => { (SearchActions.getPinnedPosts as jest.Mock).mockReturnValue((dispatch: Dispatch) => {
dispatch({type: 'MOCK_GET_PINNED_POSTS'}); dispatch({type: 'MOCK_GET_PINNED_POSTS'});
return {data: 'data'}; return {data: 'data'};
@@ -741,7 +741,7 @@ describe('rhs view actions', () => {
}); });
it('opens pinned posts', async () => { it('opens pinned posts', async () => {
(SearchActions.getPinnedPosts as jest.Mock).mockReturnValue((dispatch: DispatchFunc) => { (SearchActions.getPinnedPosts as jest.Mock).mockReturnValue((dispatch: Dispatch) => {
dispatch({type: 'MOCK_GET_PINNED_POSTS'}); dispatch({type: 'MOCK_GET_PINNED_POSTS'});
return {data: 'data'}; return {data: 'data'};
}); });
@@ -765,7 +765,7 @@ describe('rhs view actions', () => {
}); });
it('opens flagged posts', async () => { it('opens flagged posts', async () => {
(SearchActions.getFlaggedPosts as jest.Mock).mockReturnValue((dispatch: DispatchFunc) => { (SearchActions.getFlaggedPosts as jest.Mock).mockReturnValue((dispatch: Dispatch) => {
dispatch({type: 'MOCK_GET_FLAGGED_POSTS'}); dispatch({type: 'MOCK_GET_FLAGGED_POSTS'});
return {data: 'data'}; return {data: 'data'};

Просмотреть файл

@@ -24,7 +24,7 @@ import {getPost} from 'mattermost-redux/selectors/entities/posts';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentTimezone} from 'mattermost-redux/selectors/entities/timezone'; import {getCurrentTimezone} from 'mattermost-redux/selectors/entities/timezone';
import {getCurrentUser, getCurrentUserMentionKeys} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUser, getCurrentUserMentionKeys} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc, GetStateFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions'; import type {NewActionFunc, NewActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions.jsx'; import {trackEvent} from 'actions/telemetry_actions.jsx';
import {getSearchTerms, getRhsState, getPluggableId, getFilesSearchExtFilter, getPreviousRhsState} from 'selectors/rhs'; import {getSearchTerms, getRhsState, getPluggableId, getFilesSearchExtFilter, getPreviousRhsState} from 'selectors/rhs';
@@ -37,11 +37,11 @@ import {getBrowserUtcOffset, getUtcOffsetForTimeZone} from 'utils/timezone';
import type {GlobalState} from 'types/store'; import type {GlobalState} from 'types/store';
import type {RhsState} from 'types/store/rhs'; import type {RhsState} from 'types/store/rhs';
function selectPostFromRightHandSideSearchWithPreviousState(post: Post, previousRhsState?: RhsState) { function selectPostFromRightHandSideSearchWithPreviousState(post: Post, previousRhsState?: RhsState): NewActionFuncAsync<boolean, GlobalState> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const postRootId = post.root_id || post.id; const postRootId = post.root_id || post.id;
await dispatch(PostActions.getPostThread(postRootId)); await dispatch(PostActions.getPostThread(postRootId));
const state = getState() as GlobalState; const state = getState();
dispatch({ dispatch({
type: ActionTypes.SELECT_POST, type: ActionTypes.SELECT_POST,
@@ -55,9 +55,9 @@ function selectPostFromRightHandSideSearchWithPreviousState(post: Post, previous
}; };
} }
function selectPostCardFromRightHandSideSearchWithPreviousState(post: Post, previousRhsState?: RhsState) { function selectPostCardFromRightHandSideSearchWithPreviousState(post: Post, previousRhsState?: RhsState): NewActionFuncAsync<boolean, GlobalState> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState() as GlobalState; const state = getState();
dispatch({ dispatch({
type: ActionTypes.SELECT_POST_CARD, type: ActionTypes.SELECT_POST_CARD,
@@ -70,8 +70,8 @@ function selectPostCardFromRightHandSideSearchWithPreviousState(post: Post, prev
}; };
} }
export function updateRhsState(rhsState: string, channelId?: string, previousRhsState?: RhsState) { export function updateRhsState(rhsState: string, channelId?: string, previousRhsState?: RhsState): NewActionFunc<boolean> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const action: AnyAction = { const action: AnyAction = {
type: ActionTypes.UPDATE_RHS_STATE, type: ActionTypes.UPDATE_RHS_STATE,
state: rhsState, state: rhsState,
@@ -105,9 +105,9 @@ export function openShowEditHistory(post: Post) {
}; };
} }
export function goBack() { export function goBack(): NewActionFuncAsync<boolean, GlobalState> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const prevState = getPreviousRhsState(getState() as GlobalState); const prevState = getPreviousRhsState(getState());
const defaultTab = 'channel-info'; const defaultTab = 'channel-info';
dispatch({ dispatch({
@@ -123,12 +123,12 @@ export function selectPostFromRightHandSideSearch(post: Post) {
return selectPostFromRightHandSideSearchWithPreviousState(post); return selectPostFromRightHandSideSearchWithPreviousState(post);
} }
export function selectPostCardFromRightHandSideSearch(post: Post) { export function selectPostCardFromRightHandSideSearch(post: Post) { // HARRISONTODO unused
return selectPostCardFromRightHandSideSearchWithPreviousState(post); return selectPostCardFromRightHandSideSearchWithPreviousState(post);
} }
export function selectPostFromRightHandSideSearchByPostId(postId: string) { export function selectPostFromRightHandSideSearchByPostId(postId: string): NewActionFuncAsync<boolean, GlobalState> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const post = getPost(getState(), postId); const post = getPost(getState(), postId);
return dispatch(selectPostFromRightHandSideSearch(post)); return dispatch(selectPostFromRightHandSideSearch(post));
}; };
@@ -170,8 +170,8 @@ export function setRhsSize(rhsSize?: SidebarSize) {
}; };
} }
export function updateSearchTermsForShortcut() { export function updateSearchTermsForShortcut(): ThunkActionFunc<unknown> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const currentChannelName = getCurrentChannelNameForSearchShortcut(getState()); const currentChannelName = getCurrentChannelNameForSearchShortcut(getState());
return dispatch(updateSearchTerms(`in:${currentChannelName} `)); return dispatch(updateSearchTerms(`in:${currentChannelName} `));
}; };
@@ -191,13 +191,13 @@ function updateSearchResultsTerms(terms: string) {
}; };
} }
export function performSearch(terms: string, isMentionSearch?: boolean) { export function performSearch(terms: string, isMentionSearch?: boolean): ThunkActionFunc<unknown, GlobalState> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
let searchTerms = terms; let searchTerms = terms;
const teamId = getCurrentTeamId(getState()); const teamId = getCurrentTeamId(getState());
const config = getConfig(getState()); const config = getConfig(getState());
const viewArchivedChannels = config.ExperimentalViewArchivedChannels === 'true'; const viewArchivedChannels = config.ExperimentalViewArchivedChannels === 'true';
const extensionsFilters = getFilesSearchExtFilter(getState() as GlobalState); const extensionsFilters = getFilesSearchExtFilter(getState());
const extensions = extensionsFilters?.map((ext) => `ext:${ext}`).join(' '); const extensions = extensionsFilters?.map((ext) => `ext:${ext}`).join(' ');
let termsWithExtensionsFilters = searchTerms; let termsWithExtensionsFilters = searchTerms;
@@ -231,18 +231,15 @@ export function performSearch(terms: string, isMentionSearch?: boolean) {
} }
export function filterFilesSearchByExt(extensions: string[]) { export function filterFilesSearchByExt(extensions: string[]) {
return (dispatch: DispatchFunc) => { return {
dispatch({ type: ActionTypes.SET_FILES_FILTER_BY_EXT,
type: ActionTypes.SET_FILES_FILTER_BY_EXT, data: extensions,
data: extensions,
});
return {data: true};
}; };
} }
export function showSearchResults(isMentionSearch = false) { export function showSearchResults(isMentionSearch = false): ThunkActionFunc<unknown, GlobalState> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState() as GlobalState; const state = getState();
const searchTerms = getSearchTerms(state); const searchTerms = getSearchTerms(state);
@@ -265,9 +262,9 @@ export function showRHSPlugin(pluggableId: string) {
}; };
} }
export function showChannelMembers(channelId: string, inEditingMode = false) { export function showChannelMembers(channelId: string, inEditingMode = false): NewActionFuncAsync<boolean, GlobalState> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState() as GlobalState; const state = getState();
if (inEditingMode) { if (inEditingMode) {
await dispatch(setEditChannelMembers(true)); await dispatch(setEditChannelMembers(true));
@@ -288,8 +285,8 @@ export function showChannelMembers(channelId: string, inEditingMode = false) {
}; };
} }
export function hideRHSPlugin(pluggableId: string) { export function hideRHSPlugin(pluggableId: string): NewActionFunc<boolean, GlobalState> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState() as GlobalState; const state = getState() as GlobalState;
if (getPluggableId(state) === pluggableId) { if (getPluggableId(state) === pluggableId) {
@@ -300,9 +297,9 @@ export function hideRHSPlugin(pluggableId: string) {
}; };
} }
export function toggleRHSPlugin(pluggableId: string) { export function toggleRHSPlugin(pluggableId: string): NewActionFunc<boolean, GlobalState> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState() as GlobalState; const state = getState();
if (getPluggableId(state) === pluggableId) { if (getPluggableId(state) === pluggableId) {
dispatch(hideRHSPlugin(pluggableId)); dispatch(hideRHSPlugin(pluggableId));
@@ -392,9 +389,9 @@ export function showPinnedPosts(channelId?: string): NewActionFuncAsync<boolean,
}; };
} }
export function showChannelFiles(channelId: string) { export function showChannelFiles(channelId: string): NewActionFuncAsync<boolean, GlobalState> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState() as GlobalState; const state = getState();
const teamId = getCurrentTeamId(state); const teamId = getCurrentTeamId(state);
let previousRhsState = getRhsState(state); let previousRhsState = getRhsState(state);
@@ -450,8 +447,8 @@ export function showChannelFiles(channelId: string) {
}; };
} }
export function showMentions() { export function showMentions(): NewActionFunc<boolean, GlobalState> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const termKeys = getCurrentUserMentionKeys(getState()).filter(({key}) => { const termKeys = getCurrentUserMentionKeys(getState()).filter(({key}) => {
return key !== '@channel' && key !== '@all' && key !== '@here'; return key !== '@channel' && key !== '@all' && key !== '@here';
}); });
@@ -477,18 +474,15 @@ export function showMentions() {
} }
export function showChannelInfo(channelId: string) { export function showChannelInfo(channelId: string) {
return (dispatch: DispatchFunc) => { return {
dispatch({ type: ActionTypes.UPDATE_RHS_STATE,
type: ActionTypes.UPDATE_RHS_STATE, channelId,
channelId, state: RHSStates.CHANNEL_INFO,
state: RHSStates.CHANNEL_INFO,
});
return {data: true};
}; };
} }
export function closeRightHandSide() { export function closeRightHandSide(): NewActionFunc {
return (dispatch: DispatchFunc) => { return (dispatch) => {
const actionsBatch: AnyAction[] = [ const actionsBatch: AnyAction[] = [
{ {
type: ActionTypes.UPDATE_RHS_STATE, type: ActionTypes.UPDATE_RHS_STATE,
@@ -507,15 +501,15 @@ export function closeRightHandSide() {
}; };
} }
export const toggleMenu = () => (dispatch: DispatchFunc) => dispatch({ export const toggleMenu = (): ThunkActionFunc<unknown> => (dispatch) => dispatch({
type: ActionTypes.TOGGLE_RHS_MENU, type: ActionTypes.TOGGLE_RHS_MENU,
}); });
export const openMenu = () => (dispatch: DispatchFunc) => dispatch({ export const openMenu = (): ThunkActionFunc<unknown> => (dispatch) => dispatch({
type: ActionTypes.OPEN_RHS_MENU, type: ActionTypes.OPEN_RHS_MENU,
}); });
export const closeMenu = () => (dispatch: DispatchFunc) => dispatch({ export const closeMenu = (): ThunkActionFunc<unknown> => (dispatch) => dispatch({
type: ActionTypes.CLOSE_RHS_MENU, type: ActionTypes.CLOSE_RHS_MENU,
}); });
@@ -532,13 +526,14 @@ export function toggleRhsExpanded() {
}; };
} }
export function selectPostAndParentChannel(post: Post) { export function selectPostAndParentChannel(post: Post): NewActionFuncAsync { // HARRISONTODO unused
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const channel = getChannelSelector(getState(), post.channel_id); const channel = getChannelSelector(getState(), post.channel_id);
if (!channel) { if (!channel) {
await dispatch(getChannel(post.channel_id)); await dispatch(getChannel(post.channel_id));
} }
return dispatch(selectPost(post)); dispatch(selectPost(post));
return {data: true};
}; };
} }
@@ -551,8 +546,8 @@ export function selectPost(post: Post) {
}; };
} }
export function selectPostById(postId: string) { export function selectPostById(postId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState(); const state = getState();
const post = getPost(state, postId) ?? (await dispatch(fetchPost(postId))).data; const post = getPost(state, postId) ?? (await dispatch(fetchPost(postId))).data;
if (post) { if (post) {
@@ -582,8 +577,8 @@ export const debouncedClearHighlightReply = debounce((dispatch) => {
return dispatch(clearHighlightReply); return dispatch(clearHighlightReply);
}, Constants.PERMALINK_FADEOUT); }, Constants.PERMALINK_FADEOUT);
export function selectPostAndHighlight(post: Post) { export function selectPostAndHighlight(post: Post): NewActionFunc {
return (dispatch: DispatchFunc) => { return (dispatch) => {
dispatch(batchActions([ dispatch(batchActions([
selectPost(post), selectPost(post),
highlightReply(post), highlightReply(post),
@@ -599,8 +594,8 @@ export function selectPostCard(post: Post) {
return {type: ActionTypes.SELECT_POST_CARD, postId: post.id, channelId: post.channel_id}; return {type: ActionTypes.SELECT_POST_CARD, postId: post.id, channelId: post.channel_id};
} }
export function openRHSSearch() { export function openRHSSearch(): NewActionFunc {
return (dispatch: DispatchFunc) => { return (dispatch) => {
dispatch(clearSearch()); dispatch(clearSearch());
dispatch(updateSearchTerms('')); dispatch(updateSearchTerms(''));
dispatch(updateSearchResultsTerms('')); dispatch(updateSearchResultsTerms(''));
@@ -611,8 +606,8 @@ export function openRHSSearch() {
}; };
} }
export function openAtPrevious(previous: any) { // TODO Could not find the proper type. Seems to be in several props around export function openAtPrevious(previous: any): ThunkActionFunc<unknown, GlobalState> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
if (!previous) { if (!previous) {
return dispatch(openRHSSearch()); return dispatch(openRHSSearch());
} }
@@ -659,11 +654,8 @@ export const unsuppressRHS = {
}; };
export function setEditChannelMembers(active: boolean) { export function setEditChannelMembers(active: boolean) {
return (dispatch: DispatchFunc) => { return {
dispatch({ type: ActionTypes.SET_EDIT_CHANNEL_MEMBERS,
type: ActionTypes.SET_EDIT_CHANNEL_MEMBERS, active,
active,
});
return {data: true};
}; };
} }

Просмотреть файл

@@ -4,7 +4,7 @@
import {getClientConfig, getLicenseConfig} from 'mattermost-redux/actions/general'; import {getClientConfig, getLicenseConfig} from 'mattermost-redux/actions/general';
import {loadMe} from 'mattermost-redux/actions/users'; import {loadMe} from 'mattermost-redux/actions/users';
import {Client4} from 'mattermost-redux/client'; import {Client4} from 'mattermost-redux/client';
import type {DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions'; import type {NewActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {getCurrentLocale, getTranslations} from 'selectors/i18n'; import {getCurrentLocale, getTranslations} from 'selectors/i18n';
@@ -18,8 +18,8 @@ const pluginTranslationSources: Record<string, TranslationPluginFunction> = {};
export type TranslationPluginFunction = (locale: string) => Translations export type TranslationPluginFunction = (locale: string) => Translations
export function loadConfigAndMe() { export function loadConfigAndMe(): NewActionFuncAsync<boolean> {
return async (dispatch: DispatchFunc) => { return async (dispatch) => {
await Promise.all([ await Promise.all([
dispatch(getClientConfig()), dispatch(getClientConfig()),
dispatch(getLicenseConfig()), dispatch(getLicenseConfig()),
@@ -35,10 +35,10 @@ export function loadConfigAndMe() {
}; };
} }
export function registerPluginTranslationsSource(pluginId: string, sourceFunction: TranslationPluginFunction) { export function registerPluginTranslationsSource(pluginId: string, sourceFunction: TranslationPluginFunction): ThunkActionFunc<void, GlobalState> {
pluginTranslationSources[pluginId] = sourceFunction; pluginTranslationSources[pluginId] = sourceFunction;
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState() as GlobalState; const state = getState();
const locale = getCurrentLocale(state); const locale = getCurrentLocale(state);
const immutableTranslations = getTranslations(state, locale); const immutableTranslations = getTranslations(state, locale);
const translations = {}; const translations = {};
@@ -60,8 +60,8 @@ export function unregisterPluginTranslationsSource(pluginId: string) {
Reflect.deleteProperty(pluginTranslationSources, pluginId); Reflect.deleteProperty(pluginTranslationSources, pluginId);
} }
export function loadTranslations(locale: string, url: string) { export function loadTranslations(locale: string, url: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc) => { return async (dispatch) => {
const translations = {...en}; const translations = {...en};
Object.values(pluginTranslationSources).forEach((pluginFunc) => { Object.values(pluginTranslationSources).forEach((pluginFunc) => {
Object.assign(translations, pluginFunc(locale)); Object.assign(translations, pluginFunc(locale));
@@ -87,8 +87,8 @@ export function loadTranslations(locale: string, url: string) {
}; };
} }
export function registerCustomPostRenderer(type: string, component: any, id: string) { export function registerCustomPostRenderer(type: string, component: any, id: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc) => { return async (dispatch) => {
// piggyback on plugins state to register a custom post renderer // piggyback on plugins state to register a custom post renderer
dispatch({ dispatch({
type: ActionTypes.RECEIVED_PLUGIN_POST_COMPONENT, type: ActionTypes.RECEIVED_PLUGIN_POST_COMPONENT,

Просмотреть файл

@@ -14,7 +14,6 @@ import {
getCloudCustomer as selectCloudCustomer, getCloudCustomer as selectCloudCustomer,
getCloudErrors, getCloudErrors,
} from 'mattermost-redux/selectors/entities/cloud'; } from 'mattermost-redux/selectors/entities/cloud';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {pageVisited} from 'actions/telemetry_actions'; import {pageVisited} from 'actions/telemetry_actions';
@@ -58,7 +57,7 @@ export const searchableStrings = [
]; ];
const BillingSubscriptions = () => { const BillingSubscriptions = () => {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const subscription = useSelector(selectCloudSubscription); const subscription = useSelector(selectCloudSubscription);
const [cloudLimits] = useGetLimits(); const [cloudLimits] = useGetLimits();
const errorLoadingData = useSelector((state: GlobalState) => { const errorLoadingData = useSelector((state: GlobalState) => {

Просмотреть файл

@@ -7,7 +7,6 @@ import {useDispatch, useSelector} from 'react-redux';
import {getCloudCustomer} from 'mattermost-redux/actions/cloud'; import {getCloudCustomer} from 'mattermost-redux/actions/cloud';
import {getCloudErrors} from 'mattermost-redux/selectors/entities/cloud'; import {getCloudErrors} from 'mattermost-redux/selectors/entities/cloud';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {pageVisited} from 'actions/telemetry_actions'; import {pageVisited} from 'actions/telemetry_actions';
@@ -27,7 +26,7 @@ export const searchableStrings = [
]; ];
const CompanyInfo: React.FC<Props> = () => { const CompanyInfo: React.FC<Props> = () => {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const {customer: customerError} = useSelector(getCloudErrors); const {customer: customerError} = useSelector(getCloudErrors);
useEffect(() => { useEffect(() => {

Просмотреть файл

@@ -10,7 +10,6 @@ import type {Feedback} from '@mattermost/types/cloud';
import {getSubscriptionProduct} from 'mattermost-redux/selectors/entities/cloud'; import {getSubscriptionProduct} from 'mattermost-redux/selectors/entities/cloud';
import {getLicense} from 'mattermost-redux/selectors/entities/general'; import {getLicense} from 'mattermost-redux/selectors/entities/general';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {subscribeCloudSubscription, deleteWorkspace as deleteWorkspaceRequest} from 'actions/cloud'; import {subscribeCloudSubscription, deleteWorkspace as deleteWorkspaceRequest} from 'actions/cloud';
import {closeModal, openModal} from 'actions/views/modals'; import {closeModal, openModal} from 'actions/views/modals';
@@ -45,7 +44,7 @@ export const messages = defineMessages({
}); });
export default function DeleteWorkspaceModal(props: Props) { export default function DeleteWorkspaceModal(props: Props) {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const openDowngradeModal = useOpenDowngradeModal(); const openDowngradeModal = useOpenDowngradeModal();
// License/product checks. // License/product checks.

Просмотреть файл

@@ -9,7 +9,6 @@ import type {GlobalState} from '@mattermost/types/store';
import {getCloudCustomer} from 'mattermost-redux/actions/cloud'; import {getCloudCustomer} from 'mattermost-redux/actions/cloud';
import {getCloudErrors} from 'mattermost-redux/selectors/entities/cloud'; import {getCloudErrors} from 'mattermost-redux/selectors/entities/cloud';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {pageVisited} from 'actions/telemetry_actions'; import {pageVisited} from 'actions/telemetry_actions';
@@ -32,7 +31,7 @@ export const searchableStrings = [
]; ];
const PaymentInfo: React.FC<Props> = () => { const PaymentInfo: React.FC<Props> = () => {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const {customer: customerError} = useSelector(getCloudErrors); const {customer: customerError} = useSelector(getCloudErrors);
const isCardAboutToExpire = useSelector((state: GlobalState) => { const isCardAboutToExpire = useSelector((state: GlobalState) => {

Просмотреть файл

@@ -8,8 +8,6 @@ import {useDispatch} from 'react-redux';
import {AlertOutlineIcon} from '@mattermost/compass-icons/components'; import {AlertOutlineIcon} from '@mattermost/compass-icons/components';
import type {AllowedIPRange, FetchIPResponse} from '@mattermost/types/config'; import type {AllowedIPRange, FetchIPResponse} from '@mattermost/types/config';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {applyIPFilters, getCurrentIP, getIPFilters} from 'actions/admin_actions'; import {applyIPFilters, getCurrentIP, getIPFilters} from 'actions/admin_actions';
import {getInstallation} from 'actions/cloud'; import {getInstallation} from 'actions/cloud';
import {closeModal, openModal} from 'actions/views/modals'; import {closeModal, openModal} from 'actions/views/modals';
@@ -30,7 +28,7 @@ import SaveChangesPanel from '../team_channel_settings/save_changes_panel';
import './ip_filtering.scss'; import './ip_filtering.scss';
const IPFiltering = () => { const IPFiltering = () => {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const [ipFilters, setIpFilters] = useState<AllowedIPRange[] | null>(null); const [ipFilters, setIpFilters] = useState<AllowedIPRange[] | null>(null);
const [originalIpFilters, setOriginalIpFilters] = useState<AllowedIPRange[] | null>(null); const [originalIpFilters, setOriginalIpFilters] = useState<AllowedIPRange[] | null>(null);

Просмотреть файл

@@ -7,8 +7,6 @@ import {useSelector, useDispatch} from 'react-redux';
import {GenericModal} from '@mattermost/components'; import {GenericModal} from '@mattermost/components';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {closeModal} from 'actions/views/modals'; import {closeModal} from 'actions/views/modals';
import {isModalOpen} from 'selectors/views/modals'; import {isModalOpen} from 'selectors/views/modals';
@@ -27,7 +25,7 @@ type Props = {
} }
const ConfirmLicenseRemovalModal: React.FC<Props> = (props: Props): JSX.Element | null => { const ConfirmLicenseRemovalModal: React.FC<Props> = (props: Props): JSX.Element | null => {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const show = useSelector((state: GlobalState) => isModalOpen(state, ModalIdentifiers.CONFIRM_LICENSE_REMOVAL)); const show = useSelector((state: GlobalState) => isModalOpen(state, ModalIdentifiers.CONFIRM_LICENSE_REMOVAL));
if (!show) { if (!show) {

Просмотреть файл

@@ -6,8 +6,6 @@ import {useSelector, useDispatch} from 'react-redux';
import {GenericModal} from '@mattermost/components'; import {GenericModal} from '@mattermost/components';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {closeModal} from 'actions/views/modals'; import {closeModal} from 'actions/views/modals';
import {isModalOpen} from 'selectors/views/modals'; import {isModalOpen} from 'selectors/views/modals';
@@ -22,7 +20,7 @@ type Props = {
} }
const EELicenseModal: React.FC<Props> = (props: Props): JSX.Element | null => { const EELicenseModal: React.FC<Props> = (props: Props): JSX.Element | null => {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const show = useSelector((state: GlobalState) => isModalOpen(state, ModalIdentifiers.ENTERPRISE_EDITION_LICENSE)); const show = useSelector((state: GlobalState) => isModalOpen(state, ModalIdentifiers.ENTERPRISE_EDITION_LICENSE));
if (!show) { if (!show) {

Просмотреть файл

@@ -12,7 +12,6 @@ import type {ClientLicense} from '@mattermost/types/config';
import {uploadLicense} from 'mattermost-redux/actions/admin'; import {uploadLicense} from 'mattermost-redux/actions/admin';
import {getLicenseConfig} from 'mattermost-redux/actions/general'; import {getLicenseConfig} from 'mattermost-redux/actions/general';
import {getLicense} from 'mattermost-redux/selectors/entities/general'; import {getLicense} from 'mattermost-redux/selectors/entities/general';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {closeModal} from 'actions/views/modals'; import {closeModal} from 'actions/views/modals';
import {getCurrentLocale} from 'selectors/i18n'; import {getCurrentLocale} from 'selectors/i18n';
@@ -38,7 +37,7 @@ type Props = {
} }
const UploadLicenseModal = (props: Props): JSX.Element | null => { const UploadLicenseModal = (props: Props): JSX.Element | null => {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const [fileObj, setFileObj] = React.useState<File | null>(props.fileObjFromProps); const [fileObj, setFileObj] = React.useState<File | null>(props.fileObjFromProps);
const [isUploading, setIsUploading] = React.useState(false); const [isUploading, setIsUploading] = React.useState(false);

Просмотреть файл

@@ -42,12 +42,8 @@ export interface Props {
enableGuestAccounts: boolean; enableGuestAccounts: boolean;
filters: Filters; filters: Filters;
actions: { actions: {
loadTeamMembersForProfilesList: (profiles: UserProfile[], teamId: string) => Promise<{ loadTeamMembersForProfilesList: (profiles: UserProfile[], teamId: string) => Promise<ActionResult>;
data: boolean; loadChannelMembersForProfilesList: (profiles: UserProfile[], channelId: string) => Promise<ActionResult>;
}>;
loadChannelMembersForProfilesList: (profiles: UserProfile[], channelId: string) => Promise<{
data: boolean;
}>;
setModalSearchTerm: (term: string) => ActionResult; setModalSearchTerm: (term: string) => ActionResult;
setModalFilters: (filters: Filters) => ActionResult; setModalFilters: (filters: Filters) => ActionResult;
}; };

Просмотреть файл

@@ -14,7 +14,6 @@ import {
} from 'mattermost-redux/selectors/entities/cloud'; } from 'mattermost-redux/selectors/entities/cloud';
import {getLicense} from 'mattermost-redux/selectors/entities/general'; import {getLicense} from 'mattermost-redux/selectors/entities/general';
import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {getHistory} from 'utils/browser_history'; import {getHistory} from 'utils/browser_history';
import {isCustomerCardExpired} from 'utils/cloud_utils'; import {isCustomerCardExpired} from 'utils/cloud_utils';
@@ -25,7 +24,7 @@ import AnnouncementBar from '../default_announcement_bar';
export default function PaymentAnnouncementBar() { export default function PaymentAnnouncementBar() {
const [requestedCustomer, setRequestedCustomer] = useState(false); const [requestedCustomer, setRequestedCustomer] = useState(false);
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const subscription = useSelector(selectCloudSubscription); const subscription = useSelector(selectCloudSubscription);
const customer = useSelector(selectCloudCustomer); const customer = useSelector(selectCloudCustomer);
const isStarterFree = useSelector(getSubscriptionProduct)?.sku === CloudProducts.STARTER; const isStarterFree = useSelector(getSubscriptionProduct)?.sku === CloudProducts.STARTER;

Просмотреть файл

@@ -10,7 +10,6 @@ import {savePreferences} from 'mattermost-redux/actions/preferences';
import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general'; import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general';
import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences'; import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions'; import {trackEvent} from 'actions/telemetry_actions';
import {isModalOpen} from 'selectors/views/modals'; import {isModalOpen} from 'selectors/views/modals';
@@ -31,7 +30,7 @@ const ShowStartTrialModal = () => {
const isUserAdmin = useSelector((state: GlobalState) => isCurrentUserSystemAdmin(state)); const isUserAdmin = useSelector((state: GlobalState) => isCurrentUserSystemAdmin(state));
const openStartTrialFormModal = useOpenStartTrialFormModal(); const openStartTrialFormModal = useOpenStartTrialFormModal();
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const getCategory = makeGetCategory(); const getCategory = makeGetCategory();
const userThreshold = 10; const userThreshold = 10;

Просмотреть файл

@@ -11,7 +11,6 @@ import {getCurrentUserId} from 'mattermost-redux/selectors/entities/common';
import {getLicense} from 'mattermost-redux/selectors/entities/general'; import {getLicense} from 'mattermost-redux/selectors/entities/general';
import {get as getPreference} from 'mattermost-redux/selectors/entities/preferences'; import {get as getPreference} from 'mattermost-redux/selectors/entities/preferences';
import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions'; import {trackEvent} from 'actions/telemetry_actions';
import {openModal, closeModal} from 'actions/views/modals'; import {openModal, closeModal} from 'actions/views/modals';
@@ -37,7 +36,7 @@ const ShowThreeDaysLeftTrialModal = () => {
const subscription = useSelector(getCloudSubscription); const subscription = useSelector(getCloudSubscription);
const isFreeTrial = subscription?.is_free_trial === 'true'; const isFreeTrial = subscription?.is_free_trial === 'true';
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const hadAdminDismissedModal = useSelector((state: GlobalState) => getPreference(state, Preferences.CLOUD_TRIAL_BANNER, CloudBanners.THREE_DAYS_LEFT_TRIAL_MODAL_DISMISSED)) === 'true'; const hadAdminDismissedModal = useSelector((state: GlobalState) => getPreference(state, Preferences.CLOUD_TRIAL_BANNER, CloudBanners.THREE_DAYS_LEFT_TRIAL_MODAL_DISMISSED)) === 'true';
const trialEndDate = new Date(subscription?.trial_end_at || 0); const trialEndDate = new Date(subscription?.trial_end_at || 0);

Просмотреть файл

@@ -5,8 +5,6 @@ import classNames from 'classnames';
import React, {useEffect} from 'react'; import React, {useEffect} from 'react';
import {useDispatch} from 'react-redux'; import {useDispatch} from 'react-redux';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {loadStatusesForChannelAndSidebar} from 'actions/status_actions'; import {loadStatusesForChannelAndSidebar} from 'actions/status_actions';
import CenterChannel from 'components/channel_layout/center_channel'; import CenterChannel from 'components/channel_layout/center_channel';
@@ -27,7 +25,7 @@ type Props = {
} }
export default function ChannelController(props: Props) { export default function ChannelController(props: Props) {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
const isMsBrowser = isInternetExplorer() || isEdge(); const isMsBrowser = isInternetExplorer() || isEdge();

Просмотреть файл

@@ -20,7 +20,6 @@ import {CategoryTypes} from 'mattermost-redux/constants/channel_categories';
import {getCategoryInTeamWithChannel} from 'mattermost-redux/selectors/entities/channel_categories'; import {getCategoryInTeamWithChannel} from 'mattermost-redux/selectors/entities/channel_categories';
import {getAllChannels} from 'mattermost-redux/selectors/entities/channels'; import {getAllChannels} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions'; import {trackEvent} from 'actions/telemetry_actions';
import {addChannelsInSidebar} from 'actions/views/channel_sidebar'; import {addChannelsInSidebar} from 'actions/views/channel_sidebar';
@@ -42,7 +41,7 @@ type Props = {
const ChannelMoveToSubMenu = (props: Props) => { const ChannelMoveToSubMenu = (props: Props) => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const allChannels = useSelector(getAllChannels); const allChannels = useSelector(getAllChannels);
const multiSelectedChannelIds = useSelector((state: GlobalState) => state.views.channelSidebar.multiSelectedChannelIds); const multiSelectedChannelIds = useSelector((state: GlobalState) => state.views.channelSidebar.multiSelectedChannelIds);

Просмотреть файл

@@ -18,7 +18,6 @@ import {CategoryTypes} from 'mattermost-redux/constants/channel_categories';
import {getCategoryInTeamWithChannel} from 'mattermost-redux/selectors/entities/channel_categories'; import {getCategoryInTeamWithChannel} from 'mattermost-redux/selectors/entities/channel_categories';
import {getAllChannels} from 'mattermost-redux/selectors/entities/channels'; import {getAllChannels} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions'; import {trackEvent} from 'actions/telemetry_actions';
import {addChannelsInSidebar} from 'actions/views/channel_sidebar'; import {addChannelsInSidebar} from 'actions/views/channel_sidebar';
@@ -42,7 +41,7 @@ type Props = {
const ChannelMoveToSubMenuOld = (props: Props) => { const ChannelMoveToSubMenuOld = (props: Props) => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const allChannels = useSelector(getAllChannels); const allChannels = useSelector(getAllChannels);
const multiSelectedChannelIds = useSelector((state: GlobalState) => state.views.channelSidebar.multiSelectedChannelIds); const multiSelectedChannelIds = useSelector((state: GlobalState) => state.views.channelSidebar.multiSelectedChannelIds);

Просмотреть файл

@@ -8,7 +8,6 @@ import {FormattedMessage} from 'react-intl';
import {useDispatch, useSelector} from 'react-redux'; import {useDispatch, useSelector} from 'react-redux';
import {isCurrentLicenseCloud} from 'mattermost-redux/selectors/entities/cloud'; import {isCurrentLicenseCloud} from 'mattermost-redux/selectors/entities/cloud';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {retryFailedCloudFetches} from 'actions/cloud'; import {retryFailedCloudFetches} from 'actions/cloud';
import {retryFailedHostedCustomerFetches} from 'actions/hosted_customer'; import {retryFailedHostedCustomerFetches} from 'actions/hosted_customer';
@@ -16,7 +15,7 @@ import {retryFailedHostedCustomerFetches} from 'actions/hosted_customer';
import './cloud_fetch_error.scss'; import './cloud_fetch_error.scss';
export default function CloudFetchError() { export default function CloudFetchError() {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const isCloud = useSelector(isCurrentLicenseCloud); const isCloud = useSelector(isCurrentLicenseCloud);
return (<div className='CloudFetchError '> return (<div className='CloudFetchError '>
<div className='CloudFetchError__header '> <div className='CloudFetchError__header '>

Просмотреть файл

@@ -8,7 +8,6 @@ import {useDispatch} from 'react-redux';
import {GenericModal} from '@mattermost/components'; import {GenericModal} from '@mattermost/components';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {isEmail} from 'mattermost-redux/utils/helpers'; import {isEmail} from 'mattermost-redux/utils/helpers';
import {validateBusinessEmail} from 'actions/cloud'; import {validateBusinessEmail} from 'actions/cloud';
@@ -36,7 +35,7 @@ const RequestBusinessEmailModal = (
onExited, onExited,
}: Props): JSX.Element | null => { }: Props): JSX.Element | null => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const [email, setEmail] = useState<string>(''); const [email, setEmail] = useState<string>('');
const [customInputLabel, setCustomInputLabel] = useState<CustomMessageInputType>(null); const [customInputLabel, setCustomInputLabel] = useState<CustomMessageInputType>(null);
const [trialBtnDisabled, setTrialBtnDisabled] = useState<boolean>(true); const [trialBtnDisabled, setTrialBtnDisabled] = useState<boolean>(true);

Просмотреть файл

@@ -5,15 +5,14 @@ import {useEffect, useState} from 'react';
import {useDispatch} from 'react-redux'; import {useDispatch} from 'react-redux';
import {getFilteredUsersStats} from 'mattermost-redux/actions/users'; import {getFilteredUsersStats} from 'mattermost-redux/actions/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
const useGetTotalUsersNoBots = (includeInactive = false): number => { const useGetTotalUsersNoBots = (includeInactive = false): number => {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const [userCount, setUserCount] = useState<number>(0); const [userCount, setUserCount] = useState<number>(0);
const getTotalUsers = async () => { const getTotalUsers = async () => {
const {data} = await dispatch(getFilteredUsersStats({include_bots: false, include_deleted: includeInactive}, false)); const {data} = await dispatch(getFilteredUsersStats({include_bots: false, include_deleted: includeInactive}, false));
setUserCount(data?.total_users_count); setUserCount(data?.total_users_count ?? 0);
}; };
useEffect(() => { useEffect(() => {

Просмотреть файл

@@ -10,8 +10,6 @@ import {useHistory, useLocation} from 'react-router-dom';
import type {UserProfile} from '@mattermost/types/users'; import type {UserProfile} from '@mattermost/types/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {loginWithDesktopToken} from 'actions/views/login'; import {loginWithDesktopToken} from 'actions/views/login';
import DesktopApp from 'utils/desktop_api'; import DesktopApp from 'utils/desktop_api';
@@ -35,7 +33,7 @@ type Props = {
} }
const DesktopAuthToken: React.FC<Props> = ({href, onLogin}: Props) => { const DesktopAuthToken: React.FC<Props> = ({href, onLogin}: Props) => {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();
const {search} = useLocation(); const {search} = useLocation();
const query = new URLSearchParams(search); const query = new URLSearchParams(search);

Просмотреть файл

@@ -10,7 +10,6 @@ import {clearErrors, logError} from 'mattermost-redux/actions/errors';
import {verifyUserEmail, getMe} from 'mattermost-redux/actions/users'; import {verifyUserEmail, getMe} from 'mattermost-redux/actions/users';
import {getIsOnboardingFlowEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {getIsOnboardingFlowEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {redirectUserToDefaultTeam} from 'actions/global_actions'; import {redirectUserToDefaultTeam} from 'actions/global_actions';
import {trackEvent} from 'actions/telemetry_actions.jsx'; import {trackEvent} from 'actions/telemetry_actions.jsx';
@@ -32,7 +31,7 @@ const enum VerifyStatus {
const DoVerifyEmail = () => { const DoVerifyEmail = () => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();
const {search} = useLocation(); const {search} = useLocation();

Просмотреть файл

@@ -13,7 +13,6 @@ import {checkHadPriorTrial} from 'mattermost-redux/selectors/entities/cloud';
import {getLicense} from 'mattermost-redux/selectors/entities/general'; import {getLicense} from 'mattermost-redux/selectors/entities/general';
import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences'; import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences';
import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {closeModal} from 'actions/views/modals'; import {closeModal} from 'actions/views/modals';
import {isModalOpen} from 'selectors/views/modals'; import {isModalOpen} from 'selectors/views/modals';
@@ -56,7 +55,7 @@ const FeatureRestrictedModal = ({
minimumPlanRequiredForFeature, minimumPlanRequiredForFeature,
}: FeatureRestrictedModalProps) => { }: FeatureRestrictedModalProps) => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
dispatch(getPrevTrialLicense()); dispatch(getPrevTrialLicense());

Просмотреть файл

@@ -10,7 +10,6 @@ import {getSubscriptionProduct, checkHadPriorTrial} from 'mattermost-redux/selec
import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general'; import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general';
import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences'; import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences';
import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {closeModal, openModal} from 'actions/views/modals'; import {closeModal, openModal} from 'actions/views/modals';
@@ -42,7 +41,7 @@ export default function InviteAs(props: Props) {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const license = useSelector(getLicense); const license = useSelector(getLicense);
const cloudFreeDeprecated = useSelector(deprecateCloudFree); const cloudFreeDeprecated = useSelector(deprecateCloudFree);
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
dispatch(getPrevTrialLicense()); dispatch(getPrevTrialLicense());

Просмотреть файл

@@ -9,7 +9,6 @@ import {GenericModal} from '@mattermost/components';
import {getLicense} from 'mattermost-redux/selectors/entities/general'; import {getLicense} from 'mattermost-redux/selectors/entities/general';
import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences'; import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions'; import {trackEvent} from 'actions/telemetry_actions';
import {closeModal} from 'actions/views/modals'; import {closeModal} from 'actions/views/modals';
@@ -43,7 +42,7 @@ const LearnMoreTrialModal = (
}: Props): JSX.Element | null => { }: Props): JSX.Element | null => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const [embargoed, setEmbargoed] = useState(false); const [embargoed, setEmbargoed] = useState(false);
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const [, salesLink] = useOpenSalesLink(); const [, salesLink] = useOpenSalesLink();

Просмотреть файл

@@ -10,7 +10,7 @@ import {autoUpdateTimezone} from 'mattermost-redux/actions/timezone';
import {getChannel, getCurrentChannelId, isManuallyUnread} from 'mattermost-redux/selectors/entities/channels'; import {getChannel, getCurrentChannelId, isManuallyUnread} from 'mattermost-redux/selectors/entities/channels';
import {getLicense, getConfig} from 'mattermost-redux/selectors/entities/general'; import {getLicense, getConfig} from 'mattermost-redux/selectors/entities/general';
import {getCurrentUser, shouldShowTermsOfService} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUser, shouldShowTermsOfService} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc, GenericAction} from 'mattermost-redux/types/actions'; import type {GenericAction, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {getChannelURL} from 'selectors/urls'; import {getChannelURL} from 'selectors/urls';
@@ -44,7 +44,7 @@ function mapStateToProps(state: GlobalState, ownProps: Props) {
} }
// NOTE: suggestions where to keep this welcomed // NOTE: suggestions where to keep this welcomed
const getChannelURLAction = (channelId: string, teamId: string, url: string) => (dispatch: DispatchFunc, getState: () => GlobalState) => { const getChannelURLAction = (channelId: string, teamId: string, url: string): ThunkActionFunc<void, GlobalState> => (dispatch, getState) => {
const state = getState(); const state = getState();
if (url && isPermalinkURL(url)) { if (url && isPermalinkURL(url)) {

Просмотреть файл

@@ -10,23 +10,18 @@ import {useSelector, useDispatch} from 'react-redux';
import {Link, useLocation, useHistory, Route} from 'react-router-dom'; import {Link, useLocation, useHistory, Route} from 'react-router-dom';
import type {Team} from '@mattermost/types/teams'; import type {Team} from '@mattermost/types/teams';
import type {UserProfile} from '@mattermost/types/users';
import {loadMe} from 'mattermost-redux/actions/users'; import {loadMe} from 'mattermost-redux/actions/users';
import {Client4} from 'mattermost-redux/client'; import {Client4} from 'mattermost-redux/client';
import {RequestStatus} from 'mattermost-redux/constants'; import {RequestStatus} from 'mattermost-redux/constants';
import {isCurrentLicenseCloud} from 'mattermost-redux/selectors/entities/cloud';
import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general'; import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general';
import {getIsOnboardingFlowEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {getIsOnboardingFlowEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getTeamByName, getMyTeamMember} from 'mattermost-redux/selectors/entities/teams'; import {getTeamByName, getMyTeamMember} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {isSystemAdmin} from 'mattermost-redux/utils/user_utils';
import {redirectUserToDefaultTeam} from 'actions/global_actions'; import {redirectUserToDefaultTeam} from 'actions/global_actions';
import {addUserToTeamFromInvite} from 'actions/team_actions'; import {addUserToTeamFromInvite} from 'actions/team_actions';
import {trackEvent} from 'actions/telemetry_actions'; import {trackEvent} from 'actions/telemetry_actions';
import {setNeedsLoggedInLimitReachedCheck} from 'actions/views/admin';
import {login} from 'actions/views/login'; import {login} from 'actions/views/login';
import LocalStorageStore from 'stores/local_storage_store'; import LocalStorageStore from 'stores/local_storage_store';
@@ -73,7 +68,7 @@ type LoginProps = {
const Login = ({onCustomizeHeader}: LoginProps) => { const Login = ({onCustomizeHeader}: LoginProps) => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();
const {pathname, search, hash} = useLocation(); const {pathname, search, hash} = useLocation();
@@ -112,7 +107,6 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
const experimentalPrimaryTeam = useSelector((state: GlobalState) => (ExperimentalPrimaryTeam ? getTeamByName(state, ExperimentalPrimaryTeam) : undefined)); const experimentalPrimaryTeam = useSelector((state: GlobalState) => (ExperimentalPrimaryTeam ? getTeamByName(state, ExperimentalPrimaryTeam) : undefined));
const experimentalPrimaryTeamMember = useSelector((state: GlobalState) => getMyTeamMember(state, experimentalPrimaryTeam?.id ?? '')); const experimentalPrimaryTeamMember = useSelector((state: GlobalState) => getMyTeamMember(state, experimentalPrimaryTeam?.id ?? ''));
const onboardingFlowEnabled = useSelector(getIsOnboardingFlowEnabled); const onboardingFlowEnabled = useSelector(getIsOnboardingFlowEnabled);
const isCloud = useSelector(isCurrentLicenseCloud);
const loginIdInput = useRef<HTMLInputElement>(null); const loginIdInput = useRef<HTMLInputElement>(null);
const passwordInput = useRef<HTMLInputElement>(null); const passwordInput = useRef<HTMLInputElement>(null);
@@ -578,7 +572,7 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
const submit = async ({loginId, password, token}: SubmitOptions) => { const submit = async ({loginId, password, token}: SubmitOptions) => {
setIsWaiting(true); setIsWaiting(true);
const {data: userProfile, error: loginError} = await dispatch(login(loginId, password, token)); const {error: loginError} = await dispatch(login(loginId, password, token));
if (loginError && loginError.server_error_id && loginError.server_error_id.length !== 0) { if (loginError && loginError.server_error_id && loginError.server_error_id.length !== 0) {
if (loginError.server_error_id === 'api.user.login.not_verified.app_error') { if (loginError.server_error_id === 'api.user.login.not_verified.app_error') {
@@ -632,10 +626,10 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
return; return;
} }
await postSubmit(userProfile); await postSubmit();
}; };
const postSubmit = async (userProfile: UserProfile) => { const postSubmit = async () => {
await dispatch(loadMe()); await dispatch(loadMe());
// check for query params brought over from signup_user_complete // check for query params brought over from signup_user_complete
@@ -647,21 +641,17 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
const {data: team} = await dispatch(addUserToTeamFromInvite(inviteToken, inviteId)); const {data: team} = await dispatch(addUserToTeamFromInvite(inviteToken, inviteId));
if (team) { if (team) {
finishSignin(userProfile, team); finishSignin(team);
} else { } else {
// there's not really a good way to deal with this, so just let the user log in like normal // there's not really a good way to deal with this, so just let the user log in like normal
finishSignin(userProfile); finishSignin();
} }
} else { } else {
finishSignin(userProfile); finishSignin();
} }
}; };
const finishSignin = (userProfile: UserProfile, team?: Team) => { const finishSignin = (team?: Team) => {
if (isCloud && isSystemAdmin(userProfile.roles)) {
dispatch(setNeedsLoggedInLimitReachedCheck(true));
}
setCSRFFromCookie(); setCSRFFromCookie();
// Record a successful login to local storage. If an unintentional logout occurs, e.g. // Record a successful login to local storage. If an unintentional logout occurs, e.g.

Просмотреть файл

@@ -8,7 +8,7 @@ import {General, Preferences, WebsocketEvents} from 'mattermost-redux/constants'
import {getConfig, isPerformanceDebuggingEnabled} from 'mattermost-redux/selectors/entities/general'; import {getConfig, isPerformanceDebuggingEnabled} from 'mattermost-redux/selectors/entities/general';
import {getBool} from 'mattermost-redux/selectors/entities/preferences'; import {getBool} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId, getStatusForUserId} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUserId, getStatusForUserId} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions'; import type {NewActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
function getTimeBetweenTypingEvents(state: GlobalState) { function getTimeBetweenTypingEvents(state: GlobalState) {
const config = getConfig(state); const config = getConfig(state);
@@ -16,8 +16,8 @@ function getTimeBetweenTypingEvents(state: GlobalState) {
return config.TimeBetweenUserTypingUpdatesMilliseconds === undefined ? 0 : parseInt(config.TimeBetweenUserTypingUpdatesMilliseconds, 10); return config.TimeBetweenUserTypingUpdatesMilliseconds === undefined ? 0 : parseInt(config.TimeBetweenUserTypingUpdatesMilliseconds, 10);
} }
export function userStartedTyping(userId: string, channelId: string, rootId: string, now: number) { export function userStartedTyping(userId: string, channelId: string, rootId: string, now: number): ThunkActionFunc<void> {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
if ( if (
@@ -45,8 +45,8 @@ export function userStartedTyping(userId: string, channelId: string, rootId: str
}; };
} }
function fillInMissingInfo(userId: string) { function fillInMissingInfo(userId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState(); const state = getState();
const currentUserId = getCurrentUserId(state); const currentUserId = getCurrentUserId(state);

Просмотреть файл

@@ -34,7 +34,7 @@ interface FormDateStateWithoutOtherPayment {
} }
export const useGatherIntent = ({typeGatherIntent}: UseGatherIntentArgs) => { export const useGatherIntent = ({typeGatherIntent}: UseGatherIntentArgs) => {
const dispatch = useDispatch<any>(); const dispatch = useDispatch();
const [feedbackSaved, setFeedbackSave] = useState(false); const [feedbackSaved, setFeedbackSave] = useState(false);
const [showError, setShowError] = useState(false); const [showError, setShowError] = useState(false);
const [submittingFeedback, setSubmittingFeedback] = useState(false); const [submittingFeedback, setSubmittingFeedback] = useState(false);

Просмотреть файл

@@ -12,7 +12,7 @@ import {getCurrentChannel, getChannel as getChannelFromRedux} from 'mattermost-r
import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeam, getTeam} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeam, getTeam} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions'; import type {NewActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {getUserIdFromChannelName} from 'mattermost-redux/utils/channel_utils'; import {getUserIdFromChannelName} from 'mattermost-redux/utils/channel_utils';
import {isSystemAdmin} from 'mattermost-redux/utils/user_utils'; import {isSystemAdmin} from 'mattermost-redux/utils/user_utils';
@@ -33,8 +33,8 @@ type Option = {
skipRedirectReplyPermalink: boolean; skipRedirectReplyPermalink: boolean;
} }
function focusRootPost(post: Post, channel: Channel) { function focusRootPost(post: Post, channel: Channel): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const postURL = getPostURL(getState() as GlobalState, post); const postURL = getPostURL(getState() as GlobalState, post);
dispatch(selectChannel(channel.id)); dispatch(selectChannel(channel.id));
@@ -49,11 +49,11 @@ function focusRootPost(post: Post, channel: Channel) {
}; };
} }
function focusReplyPost(post: Post, channel: Channel, teamId: string, returnTo: string, option: Option) { function focusReplyPost(post: Post, channel: Channel, teamId: string, returnTo: string, option: Option): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const {data} = await dispatch(getPostThread(post.root_id)); const {data} = await dispatch(getPostThread(post.root_id));
if (data.first_inaccessible_post_time) { if (data!.first_inaccessible_post_time) {
getHistory().replace(`/error?type=${ErrorPageTypes.CLOUD_ARCHIVED}&returnTo=${returnTo}`); getHistory().replace(`/error?type=${ErrorPageTypes.CLOUD_ARCHIVED}&returnTo=${returnTo}`);
return {data: false}; return {data: false};
} }
@@ -83,8 +83,8 @@ function focusReplyPost(post: Post, channel: Channel, teamId: string, returnTo:
}; };
} }
export function focusPost(postId: string, returnTo = '', currentUserId: string, option: Option = {skipRedirectReplyPermalink: false}) { export function focusPost(postId: string, returnTo = '', currentUserId: string, option: Option = {skipRedirectReplyPermalink: false}): ThunkActionFunc<Promise<void>> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
// Ignore if prompt is still visible // Ignore if prompt is still visible
if (privateChannelJoinPromptVisible) { if (privateChannelJoinPromptVisible) {
return; return;
@@ -108,7 +108,7 @@ export function focusPost(postId: string, returnTo = '', currentUserId: string,
privateChannelJoinPromptVisible = true; privateChannelJoinPromptVisible = true;
const joinPromptResult = await dispatch(joinPrivateChannelPrompt(currentTeam, postInfo.channel_display_name)); const joinPromptResult = await dispatch(joinPrivateChannelPrompt(currentTeam, postInfo.channel_display_name));
privateChannelJoinPromptVisible = false; privateChannelJoinPromptVisible = false;
if ('data' in joinPromptResult && !joinPromptResult.data.join) { if ('data' in joinPromptResult && !joinPromptResult.data!.join) {
return; return;
} }
} }
@@ -155,7 +155,7 @@ export function focusPost(postId: string, returnTo = '', currentUserId: string,
const membership = await dispatch(getChannelMember(channel.id, currentUserId)); const membership = await dispatch(getChannelMember(channel.id, currentUserId));
if ('data' in membership) { if ('data' in membership) {
myMember = membership.data; myMember = membership.data!;
} }
if (!myMember) { if (!myMember) {

Просмотреть файл

@@ -9,7 +9,6 @@ import {useDispatch} from 'react-redux';
import type {Post} from '@mattermost/types/posts'; import type {Post} from '@mattermost/types/posts';
import {getPostEditHistory} from 'mattermost-redux/actions/posts'; import {getPostEditHistory} from 'mattermost-redux/actions/posts';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import AlertIcon from 'components/common/svg_images_components/alert_svg'; import AlertIcon from 'components/common/svg_images_components/alert_svg';
import LoadingScreen from 'components/loading_screen'; import LoadingScreen from 'components/loading_screen';
@@ -48,7 +47,7 @@ const PostEditHistory = ({
const [postEditHistory, setPostEditHistory] = useState<Post[]>([]); const [postEditHistory, setPostEditHistory] = useState<Post[]>([]);
const [hasError, setHasError] = useState<boolean>(false); const [hasError, setHasError] = useState<boolean>(false);
const [isLoading, setIsLoading] = useState<boolean>(false); const [isLoading, setIsLoading] = useState<boolean>(false);
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const scrollbars = useRef<Scrollbars | null>(null); const scrollbars = useRef<Scrollbars | null>(null);
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const retrieveErrorHeading = formatMessage({ const retrieveErrorHeading = formatMessage({

Просмотреть файл

@@ -15,7 +15,6 @@ import {
} from 'mattermost-redux/selectors/entities/cloud'; } from 'mattermost-redux/selectors/entities/cloud';
import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences'; import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences';
import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {subscribeCloudSubscription} from 'actions/cloud'; import {subscribeCloudSubscription} from 'actions/cloud';
import {trackEvent} from 'actions/telemetry_actions'; import {trackEvent} from 'actions/telemetry_actions';
@@ -58,7 +57,7 @@ type ContentProps = {
function Content(props: ContentProps) { function Content(props: ContentProps) {
const {formatMessage, formatNumber} = useIntl(); const {formatMessage, formatNumber} = useIntl();
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const [limits] = useGetLimits(); const [limits] = useGetLimits();
const openPricingModalBackAction = useOpenPricingModal(); const openPricingModalBackAction = useOpenPricingModal();

Просмотреть файл

@@ -10,7 +10,6 @@ import {getTeammateNameDisplaySetting} from 'mattermost-redux/selectors/entities
import {getCurrentRelativeTeamUrl, getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentRelativeTeamUrl, getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentTimezone} from 'mattermost-redux/selectors/entities/timezone'; import {getCurrentTimezone} from 'mattermost-redux/selectors/entities/timezone';
import {getStatusForUserId, getUser} from 'mattermost-redux/selectors/entities/users'; import {getStatusForUserId, getUser} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {displayUsername} from 'mattermost-redux/utils/user_utils'; import {displayUsername} from 'mattermost-redux/utils/user_utils';
import {openDirectChannelToUserId} from 'actions/channel_actions'; import {openDirectChannelToUserId} from 'actions/channel_actions';
@@ -112,7 +111,7 @@ const ProfilePopover = ({
}: ProfilePopoverProps) => { }: ProfilePopoverProps) => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const user = useSelector((state: GlobalState) => getUser(state, userId)); const user = useSelector((state: GlobalState) => getUser(state, userId));
const currentTeamId = useSelector((state: GlobalState) => getCurrentTeamId(state)); const currentTeamId = useSelector((state: GlobalState) => getCurrentTeamId(state));
const channelId = useSelector((state: GlobalState) => (channelIdProp || getDefaultChannelId(state))); const channelId = useSelector((state: GlobalState) => (channelIdProp || getDefaultChannelId(state)));

Просмотреть файл

@@ -9,6 +9,7 @@ import type {PreferenceType} from '@mattermost/types/preferences';
import type {UserStatus} from '@mattermost/types/users'; import type {UserStatus} from '@mattermost/types/users';
import {Preferences} from 'mattermost-redux/constants'; import {Preferences} from 'mattermost-redux/constants';
import type {ActionResult} from 'mattermost-redux/types/actions';
import ConfirmModal from 'components/confirm_modal'; import ConfirmModal from 'components/confirm_modal';
@@ -139,7 +140,7 @@ type Props = {
/* /*
* Function to get and then reset the user's status if needed * Function to get and then reset the user's status if needed
*/ */
autoResetStatus: () => Promise<{data: UserStatus}>; autoResetStatus: () => Promise<ActionResult<UserStatus>>;
/* /*
* Function to set the status for a user * Function to set the status for a user
@@ -172,8 +173,8 @@ export default class ResetStatusModal extends React.PureComponent<Props, State>
public componentDidMount(): void { public componentDidMount(): void {
this.props.actions.autoResetStatus().then( this.props.actions.autoResetStatus().then(
(result: {data: UserStatus}) => { (result) => {
const status = result.data; const status = result.data!;
const statusIsManual = status.manual; const statusIsManual = status.manual;
const autoResetPrefNotSet = this.props.autoResetPref === ''; const autoResetPrefNotSet = this.props.autoResetPref === '';

Просмотреть файл

@@ -139,7 +139,7 @@ export type Actions = {
migrateRecentEmojis: () => void; migrateRecentEmojis: () => void;
loadConfigAndMe: () => Promise<ActionResult>; loadConfigAndMe: () => Promise<ActionResult>;
registerCustomPostRenderer: (type: string, component: any, id: string) => Promise<ActionResult>; registerCustomPostRenderer: (type: string, component: any, id: string) => Promise<ActionResult>;
initializeProducts: () => Promise<ActionResult[]>; initializeProducts: () => Promise<unknown>;
} }
type Props = { type Props = {

Просмотреть файл

@@ -285,7 +285,7 @@ const Search: React.FC<Props> = (props: Props): JSX.Element => {
return; return;
} }
const {error} = await actions.showSearchResults(Boolean(props.isMentionSearch)); const {error} = await actions.showSearchResults(Boolean(props.isMentionSearch)) as any;
if (!error) { if (!error) {
handleSearchOnSuccess(); handleSearchOnSuccess();

Просмотреть файл

@@ -43,7 +43,7 @@ export type DispatchProps = {
updateSearchTerms: (term: string) => Action; updateSearchTerms: (term: string) => Action;
updateSearchTermsForShortcut: () => void; updateSearchTermsForShortcut: () => void;
updateSearchType: (searchType: string) => Action; updateSearchType: (searchType: string) => Action;
showSearchResults: (isMentionSearch: boolean) => Record<string, any>; showSearchResults: (isMentionSearch: boolean) => unknown;
showChannelFiles: (channelId: string) => void; showChannelFiles: (channelId: string) => void;
showMentions: () => void; showMentions: () => void;
showFlaggedPosts: () => void; showFlaggedPosts: () => void;

Просмотреть файл

@@ -18,7 +18,6 @@ import {getLicense} from 'mattermost-redux/selectors/entities/general';
import {getSelfHostedSignupProgress} from 'mattermost-redux/selectors/entities/hosted_customer'; import {getSelfHostedSignupProgress} from 'mattermost-redux/selectors/entities/hosted_customer';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences'; import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUser, getFilteredUsersStats} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUser, getFilteredUsersStats} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {confirmSelfHostedExpansion} from 'actions/hosted_customer'; import {confirmSelfHostedExpansion} from 'actions/hosted_customer';
import {pageVisited} from 'actions/telemetry_actions'; import {pageVisited} from 'actions/telemetry_actions';
@@ -166,7 +165,7 @@ export function canSubmit(formState: FormState, progress: ValueOf<typeof SelfHos
} }
export default function SelfHostedExpansionModal() { export default function SelfHostedExpansionModal() {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const intl = useIntl(); const intl = useIntl();
const cardRef = useRef<CardInputType | null>(null); const cardRef = useRef<CardInputType | null>(null);
const theme = useSelector(getTheme); const theme = useSelector(getTheme);

Просмотреть файл

@@ -8,7 +8,6 @@ import {useDispatch} from 'react-redux';
import {useLocation, useHistory} from 'react-router-dom'; import {useLocation, useHistory} from 'react-router-dom';
import {sendVerificationEmail} from 'mattermost-redux/actions/users'; import {sendVerificationEmail} from 'mattermost-redux/actions/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions'; import {trackEvent} from 'actions/telemetry_actions';
@@ -28,7 +27,7 @@ const enum ResendStatus {
const ShouldVerifyEmail = () => { const ShouldVerifyEmail = () => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const history = useHistory(); const history = useHistory();
const {search} = useLocation(); const {search} = useLocation();

Просмотреть файл

@@ -11,7 +11,6 @@ import {getCurrentUserId} from 'mattermost-redux/selectors/entities/common';
import {getBool} from 'mattermost-redux/selectors/entities/preferences'; import {getBool} from 'mattermost-redux/selectors/entities/preferences';
import {haveICurrentChannelPermission} from 'mattermost-redux/selectors/entities/roles'; import {haveICurrentChannelPermission} from 'mattermost-redux/selectors/entities/roles';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions'; import {trackEvent} from 'actions/telemetry_actions';
import {setAddChannelCtaDropdown} from 'actions/views/add_channel_dropdown'; import {setAddChannelCtaDropdown} from 'actions/views/add_channel_dropdown';
@@ -28,7 +27,7 @@ import {ModalIdentifiers, Preferences, Touched} from 'utils/constants';
import type {GlobalState} from 'types/store'; import type {GlobalState} from 'types/store';
const AddChannelsCtaButton = (): JSX.Element | null => { const AddChannelsCtaButton = (): JSX.Element | null => {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const currentTeamId = useSelector(getCurrentTeamId); const currentTeamId = useSelector(getCurrentTeamId);
const intl = useIntl(); const intl = useIntl();
const touchedAddChannelsCtaButton = useSelector((state: GlobalState) => getBool(state, Preferences.TOUCHED, Touched.ADD_CHANNELS_CTA)); const touchedAddChannelsCtaButton = useSelector((state: GlobalState) => getBool(state, Preferences.TOUCHED, Touched.ADD_CHANNELS_CTA));

Просмотреть файл

@@ -16,7 +16,7 @@ import {localizeMessage} from 'utils/utils';
import type {PropsFromRedux} from './index'; import type {PropsFromRedux} from './index';
interface Props extends PropsFromRedux { export interface Props extends PropsFromRedux {
channel: Channel; channel: Channel;
currentTeamName: string; currentTeamName: string;
} }

Просмотреть файл

@@ -31,7 +31,7 @@ type Props = {
active: boolean; active: boolean;
actions: { actions: {
savePreferences: (userId: string, preferences: PreferenceType[]) => Promise<ActionResult>; savePreferences: (userId: string, preferences: PreferenceType[]) => Promise<ActionResult>;
leaveDirectChannel: (channelId: string) => Promise<{data: boolean}>; leaveDirectChannel: (channelId: string) => Promise<ActionResult>;
}; };
}; };

Просмотреть файл

@@ -9,7 +9,6 @@ import {useSelector, useDispatch} from 'react-redux';
import {getLicenseConfig} from 'mattermost-redux/actions/general'; import {getLicenseConfig} from 'mattermost-redux/actions/general';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/common'; import {getCurrentUser} from 'mattermost-redux/selectors/entities/common';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {requestTrialLicense} from 'actions/admin_actions'; import {requestTrialLicense} from 'actions/admin_actions';
import {validateBusinessEmail} from 'actions/cloud'; import {validateBusinessEmail} from 'actions/cloud';
@@ -69,7 +68,7 @@ type Props = {
function StartTrialFormModal(props: Props): JSX.Element | null { function StartTrialFormModal(props: Props): JSX.Element | null {
const [status, setLoadStatus] = useState(TrialLoadStatus.NotStarted); const [status, setLoadStatus] = useState(TrialLoadStatus.NotStarted);
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const currentUser = useSelector(getCurrentUser); const currentUser = useSelector(getCurrentUser);
const [name, setName] = useState(''); const [name, setName] = useState('');
const [email, setEmail] = useState(currentUser.email); const [email, setEmail] = useState(currentUser.email);
@@ -149,7 +148,7 @@ function StartTrialFormModal(props: Props): JSX.Element | null {
let buttonText; let buttonText;
let onTryAgain = handleErrorModalTryAgain; let onTryAgain = handleErrorModalTryAgain;
if (data.status === 422) { if ((data as any).status === 422) {
title = (<></>); title = (<></>);
subtitle = ( subtitle = (
<FormattedMessage <FormattedMessage

Просмотреть файл

@@ -3,6 +3,8 @@
/* eslint-disable max-lines */ /* eslint-disable max-lines */
import type {Store} from 'redux';
import {Constants} from 'utils/constants'; import {Constants} from 'utils/constants';
import { import {
@@ -56,7 +58,6 @@ import type {
AutocompleteSuggestion, AutocompleteSuggestion,
AutocompleteStaticSelect, AutocompleteStaticSelect,
Channel, Channel,
Store,
ExtendedAutocompleteSuggestion} from './app_command_parser_dependencies'; ExtendedAutocompleteSuggestion} from './app_command_parser_dependencies';
export enum ParseState { export enum ParseState {
@@ -990,7 +991,7 @@ export class AppCommandParser {
// Silently fail on default value // Silently fail on default value
break; break;
} }
user = dispatchResult.data; user = dispatchResult.data!;
} }
parsed.values[f.name] = user.username; parsed.values[f.name] = user.username;
break; break;
@@ -1004,7 +1005,7 @@ export class AppCommandParser {
// Silently fail on default value // Silently fail on default value
break; break;
} }
channel = dispatchResult.data; channel = dispatchResult.data!;
} }
parsed.values[f.name] = channel.name; parsed.values[f.name] = channel.name;
break; break;

Просмотреть файл

@@ -5,17 +5,13 @@ import type {Channel} from '@mattermost/types/channels';
import type {AutocompleteSuggestion} from '@mattermost/types/integrations'; import type {AutocompleteSuggestion} from '@mattermost/types/integrations';
import type {UserProfile} from '@mattermost/types/users'; import type {UserProfile} from '@mattermost/types/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {sendEphemeralPost} from 'actions/global_actions'; import {sendEphemeralPost} from 'actions/global_actions';
import ReduxStore from 'stores/redux_store'; import reduxStore from 'stores/redux_store';
import {Constants} from 'utils/constants'; import {Constants} from 'utils/constants';
import {isMac} from 'utils/user_agent'; import {isMac} from 'utils/user_agent';
import {localizeAndFormatMessage} from 'utils/utils'; import {localizeAndFormatMessage} from 'utils/utils';
import type {GlobalState} from 'types/store';
import type {ParsedCommand} from './app_command_parser'; import type {ParsedCommand} from './app_command_parser';
export type { export type {
@@ -72,12 +68,7 @@ export {
filterEmptyOptions, filterEmptyOptions,
} from 'utils/apps'; } from 'utils/apps';
export type Store = { export const getStore = () => reduxStore;
dispatch: DispatchFunc;
getState: () => GlobalState;
}
export const getStore = () => ReduxStore;
export {getChannelSuggestions, getUserSuggestions, inTextMentionSuggestions} from '../mentions'; export {getChannelSuggestions, getUserSuggestions, inTextMentionSuggestions} from '../mentions';
@@ -119,7 +110,7 @@ export type ExtendedAutocompleteSuggestion = AutocompleteSuggestion & {
} }
export const displayError = (err: string, channelID: string, rootID?: string) => { export const displayError = (err: string, channelID: string, rootID?: string) => {
ReduxStore.dispatch(sendEphemeralPost(err, channelID, rootID)); reduxStore.dispatch(sendEphemeralPost(err, channelID, rootID));
}; };
// Shim of mobile-version intl // Shim of mobile-version intl

Просмотреть файл

@@ -1,28 +1,22 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import type {Store} from 'redux';
import type {UserAutocomplete} from '@mattermost/types/autocomplete'; import type {UserAutocomplete} from '@mattermost/types/autocomplete';
import type {Channel} from '@mattermost/types/channels'; import type {Channel} from '@mattermost/types/channels';
import type {AutocompleteSuggestion} from '@mattermost/types/integrations'; import type {AutocompleteSuggestion} from '@mattermost/types/integrations';
import type {UserProfile} from '@mattermost/types/users'; import type {UserProfile} from '@mattermost/types/users';
import {autocompleteChannels} from 'mattermost-redux/actions/channels'; import {autocompleteChannels} from 'mattermost-redux/actions/channels';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {autocompleteUsersInChannel} from 'actions/views/channel'; import {autocompleteUsersInChannel} from 'actions/views/channel';
import {Constants} from 'utils/constants'; import {Constants} from 'utils/constants';
import type {GlobalState} from 'types/store';
export const COMMAND_SUGGESTION_CHANNEL = Constants.Integrations.COMMAND_SUGGESTION_CHANNEL; export const COMMAND_SUGGESTION_CHANNEL = Constants.Integrations.COMMAND_SUGGESTION_CHANNEL;
export const COMMAND_SUGGESTION_USER = Constants.Integrations.COMMAND_SUGGESTION_USER; export const COMMAND_SUGGESTION_USER = Constants.Integrations.COMMAND_SUGGESTION_USER;
export type Store = {
dispatch: DispatchFunc;
getState: () => GlobalState;
}
export async function inTextMentionSuggestions(pretext: string, store: Store, channelID: string, teamID: string, delimiter = ''): Promise<AutocompleteSuggestion[] | null> { export async function inTextMentionSuggestions(pretext: string, store: Store, channelID: string, teamID: string, delimiter = ''): Promise<AutocompleteSuggestion[] | null> {
const separatedWords = pretext.split(' '); const separatedWords = pretext.split(' ');
const incompleteLessLastWord = separatedWords.slice(0, -1).join(' '); const incompleteLessLastWord = separatedWords.slice(0, -1).join(' ');

Просмотреть файл

@@ -7,8 +7,6 @@ import {useSelector, useDispatch} from 'react-redux';
import {GenericModal} from '@mattermost/components'; import {GenericModal} from '@mattermost/components';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions'; import {trackEvent} from 'actions/telemetry_actions';
import {closeModal} from 'actions/views/modals'; import {closeModal} from 'actions/views/modals';
import {isModalOpen} from 'selectors/views/modals'; import {isModalOpen} from 'selectors/views/modals';
@@ -27,7 +25,7 @@ type Props = {
} }
const SwitchToYearlyPlanConfirmModal: React.FC<Props> = (props: Props): JSX.Element | null => { const SwitchToYearlyPlanConfirmModal: React.FC<Props> = (props: Props): JSX.Element | null => {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const show = useSelector((state: GlobalState) => isModalOpen(state, ModalIdentifiers.CONFIRM_SWITCH_TO_YEARLY)); const show = useSelector((state: GlobalState) => isModalOpen(state, ModalIdentifiers.CONFIRM_SWITCH_TO_YEARLY));

Просмотреть файл

@@ -7,8 +7,6 @@ import {useSelector, useDispatch} from 'react-redux';
import {GenericModal} from '@mattermost/components'; import {GenericModal} from '@mattermost/components';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {closeModal} from 'actions/views/modals'; import {closeModal} from 'actions/views/modals';
import {isModalOpen} from 'selectors/views/modals'; import {isModalOpen} from 'selectors/views/modals';
@@ -35,7 +33,7 @@ type Props = {
} }
function ThreeDaysLeftTrialModal(props: Props): JSX.Element | null { function ThreeDaysLeftTrialModal(props: Props): JSX.Element | null {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const openPricingModal = useOpenPricingModal(); const openPricingModal = useOpenPricingModal();
const show = useSelector((state: GlobalState) => isModalOpen(state, ModalIdentifiers.THREE_DAYS_LEFT_TRIAL_MODAL)); const show = useSelector((state: GlobalState) => isModalOpen(state, ModalIdentifiers.THREE_DAYS_LEFT_TRIAL_MODAL));

Просмотреть файл

@@ -5,8 +5,6 @@ import React from 'react';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import {useDispatch} from 'react-redux'; import {useDispatch} from 'react-redux';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions'; import {trackEvent} from 'actions/telemetry_actions';
import {openModal} from 'actions/views/modals'; import {openModal} from 'actions/views/modals';
@@ -24,7 +22,7 @@ export interface UpgradeLinkProps {
} }
const UpgradeLink = (props: UpgradeLinkProps) => { const UpgradeLink = (props: UpgradeLinkProps) => {
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const styleButton = props.styleButton ? ' style-button' : ''; const styleButton = props.styleButton ? ' style-button' : '';
const styleLink = props.styleLink ? ' style-link' : ''; const styleLink = props.styleLink ? ' style-link' : '';

Просмотреть файл

@@ -10,7 +10,6 @@ import {getCloudSubscription, getSubscriptionProduct} from 'mattermost-redux/sel
import {getLicense} from 'mattermost-redux/selectors/entities/general'; import {getLicense} from 'mattermost-redux/selectors/entities/general';
import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences'; import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences';
import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc} from 'mattermost-redux/types/actions';
import {openModal} from 'actions/views/modals'; import {openModal} from 'actions/views/modals';
@@ -33,7 +32,7 @@ const MenuCloudTrial = ({id}: Props): JSX.Element | null => {
const subscriptionProduct = useSelector(getSubscriptionProduct); const subscriptionProduct = useSelector(getSubscriptionProduct);
const license = useSelector(getLicense); const license = useSelector(getLicense);
const cloudFreeDeprecated = useSelector(deprecateCloudFree); const cloudFreeDeprecated = useSelector(deprecateCloudFree);
const dispatch = useDispatch<DispatchFunc>(); const dispatch = useDispatch();
const isCloud = license?.Cloud === 'true'; const isCloud = license?.Cloud === 'true';
const isFreeTrial = subscription?.is_free_trial === 'true'; const isFreeTrial = subscription?.is_free_trial === 'true';

Просмотреть файл

@@ -6,6 +6,7 @@ import {batchActions} from 'redux-batched-actions';
import type {Channel, ChannelUnread} from '@mattermost/types/channels'; import type {Channel, ChannelUnread} from '@mattermost/types/channels';
import type {FetchPaginatedThreadOptions} from '@mattermost/types/client4'; import type {FetchPaginatedThreadOptions} from '@mattermost/types/client4';
import type {ServerError} from '@mattermost/types/errors';
import type {Group} from '@mattermost/types/groups'; import type {Group} from '@mattermost/types/groups';
import type {Post, PostList, PostAcknowledgement} from '@mattermost/types/posts'; import type {Post, PostList, PostAcknowledgement} from '@mattermost/types/posts';
import type {Reaction} from '@mattermost/types/reactions'; import type {Reaction} from '@mattermost/types/reactions';
@@ -31,7 +32,7 @@ import {getAllGroupsByName} from 'mattermost-redux/selectors/entities/groups';
import * as PostSelectors from 'mattermost-redux/selectors/entities/posts'; import * as PostSelectors from 'mattermost-redux/selectors/entities/posts';
import {getUnreadScrollPositionPreference, isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {getUnreadScrollPositionPreference, isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId, getUsersByUsername} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUserId, getUsersByUsername} from 'mattermost-redux/selectors/entities/users';
import type {ActionResult, DispatchFunc, GetStateFunc, NewActionFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions'; import type {ActionResult, DispatchFunc, GetStateFunc, NewActionFunc, NewActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {isCombinedUserActivityPost} from 'mattermost-redux/utils/post_list'; import {isCombinedUserActivityPost} from 'mattermost-redux/utils/post_list';
import {logError} from './errors'; import {logError} from './errors';
@@ -137,8 +138,8 @@ export function postRemoved(post: Post) {
}; };
} }
export function getPost(postId: string) { export function getPost(postId: string): NewActionFuncAsync<Post> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let post; let post;
const crtEnabled = isCollapsedThreadsEnabled(getState()); const crtEnabled = isCollapsedThreadsEnabled(getState());
@@ -163,8 +164,8 @@ export function getPost(postId: string) {
}; };
} }
export function createPost(post: Post, files: any[] = []) { export function createPost(post: Post, files: any[] = []): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState(); const state = getState();
const currentUserId = state.entities.users.currentUserId; const currentUserId = state.entities.users.currentUserId;
@@ -290,8 +291,8 @@ export function createPost(post: Post, files: any[] = []) {
}; };
} }
export function createPostImmediately(post: Post, files: any[] = []) { export function createPostImmediately(post: Post, files: any[] = []): NewActionFuncAsync<Post> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const state = getState(); const state = getState();
const currentUserId = state.entities.users.currentUserId; const currentUserId = state.entities.users.currentUserId;
const timestamp = Date.now(); const timestamp = Date.now();
@@ -462,8 +463,8 @@ function getUnreadPostData(unreadChan: ChannelUnread, state: GlobalState) {
return data; return data;
} }
export function setUnreadPost(userId: string, postId: string) { export function setUnreadPost(userId: string, postId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let state = getState(); let state = getState();
const post = PostSelectors.getPost(state, postId); const post = PostSelectors.getPost(state, postId);
let unreadChan; let unreadChan;
@@ -501,8 +502,8 @@ export function setUnreadPost(userId: string, postId: string) {
}; };
} }
export function pinPost(postId: string) { export function pinPost(postId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
dispatch({type: PostTypes.EDIT_POST_REQUEST}); dispatch({type: PostTypes.EDIT_POST_REQUEST});
let posts; let posts;
@@ -553,8 +554,8 @@ export function decrementPinnedPostCount(channelId: Channel['id']) {
}; };
} }
export function unpinPost(postId: string) { export function unpinPost(postId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
dispatch({type: PostTypes.EDIT_POST_REQUEST}); dispatch({type: PostTypes.EDIT_POST_REQUEST});
let posts; let posts;
@@ -592,8 +593,8 @@ export function unpinPost(postId: string) {
}; };
} }
export function addReaction(postId: string, emojiName: string) { export function addReaction(postId: string, emojiName: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const currentUserId = getState().entities.users.currentUserId; const currentUserId = getState().entities.users.currentUserId;
let reaction; let reaction;
@@ -635,8 +636,8 @@ export function removeReaction(postId: string, emojiName: string): NewActionFunc
}; };
} }
export function getCustomEmojiForReaction(name: string) { export function getCustomEmojiForReaction(name: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const nonExistentEmoji = getState().entities.emojis.nonExistentEmoji; const nonExistentEmoji = getState().entities.emojis.nonExistentEmoji;
const customEmojisByName = selectCustomEmojisByName(getState()); const customEmojisByName = selectCustomEmojisByName(getState());
@@ -656,8 +657,8 @@ export function getCustomEmojiForReaction(name: string) {
}; };
} }
export function getReactionsForPost(postId: string) { export function getReactionsForPost(postId: string): ThunkActionFunc<Promise<Reaction[] | {error: ServerError}>> { // HARRISONTODO unused
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let reactions; let reactions;
try { try {
reactions = await Client4.getReactionsForPost(postId); reactions = await Client4.getReactionsForPost(postId);
@@ -708,8 +709,8 @@ export function getReactionsForPost(postId: string) {
}; };
} }
export function flagPost(postId: string) { export function flagPost(postId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const {currentUserId} = getState().entities.users; const {currentUserId} = getState().entities.users;
const preference = { const preference = {
user_id: currentUserId, user_id: currentUserId,
@@ -758,8 +759,8 @@ async function getPaginatedPostThread(rootId: string, options: FetchPaginatedThr
return list; return list;
} }
export function getPostThread(rootId: string, fetchThreads = true) { export function getPostThread(rootId: string, fetchThreads = true): NewActionFuncAsync<PostList> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
dispatch({type: PostTypes.GET_POST_THREAD_REQUEST}); dispatch({type: PostTypes.GET_POST_THREAD_REQUEST});
const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState()); const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState());
@@ -786,10 +787,10 @@ export function getPostThread(rootId: string, fetchThreads = true) {
}; };
} }
export function getNewestPostThread(rootId: string) { export function getNewestPostThread(rootId: string): NewActionFuncAsync {
const getPostsForThread = PostSelectors.makeGetPostsForThread(); const getPostsForThread = PostSelectors.makeGetPostsForThread();
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
dispatch({type: PostTypes.GET_POST_THREAD_REQUEST}); dispatch({type: PostTypes.GET_POST_THREAD_REQUEST});
const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState()); const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState());
const savedPosts = getPostsForThread(getState(), rootId); const savedPosts = getPostsForThread(getState(), rootId);
@@ -827,8 +828,8 @@ export function getNewestPostThread(rootId: string) {
}; };
} }
export function getPosts(channelId: string, page = 0, perPage = Posts.POST_CHUNK_SIZE, fetchThreads = true, collapsedThreadsExtended = false) { export function getPosts(channelId: string, page = 0, perPage = Posts.POST_CHUNK_SIZE, fetchThreads = true, collapsedThreadsExtended = false): NewActionFuncAsync<PostList> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let posts; let posts;
const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState()); const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState());
try { try {
@@ -849,8 +850,8 @@ export function getPosts(channelId: string, page = 0, perPage = Posts.POST_CHUNK
}; };
} }
export function getPostsUnread(channelId: string, fetchThreads = true, collapsedThreadsExtended = false) { export function getPostsUnread(channelId: string, fetchThreads = true, collapsedThreadsExtended = false): NewActionFuncAsync<PostList> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const shouldLoadRecent = getUnreadScrollPositionPreference(getState()) === Preferences.UNREAD_SCROLL_POSITION_START_FROM_NEWEST; const shouldLoadRecent = getUnreadScrollPositionPreference(getState()) === Preferences.UNREAD_SCROLL_POSITION_START_FROM_NEWEST;
const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState()); const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState());
const userId = getCurrentUserId(getState()); const userId = getCurrentUserId(getState());
@@ -890,8 +891,8 @@ export function getPostsUnread(channelId: string, fetchThreads = true, collapsed
}; };
} }
export function getPostsSince(channelId: string, since: number, fetchThreads = true, collapsedThreadsExtended = false) { export function getPostsSince(channelId: string, since: number, fetchThreads = true, collapsedThreadsExtended = false): NewActionFuncAsync<PostList> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let posts; let posts;
try { try {
const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState()); const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState());
@@ -915,8 +916,8 @@ export function getPostsSince(channelId: string, since: number, fetchThreads = t
}; };
} }
export function getPostsBefore(channelId: string, postId: string, page = 0, perPage = Posts.POST_CHUNK_SIZE, fetchThreads = true, collapsedThreadsExtended = false) { export function getPostsBefore(channelId: string, postId: string, page = 0, perPage = Posts.POST_CHUNK_SIZE, fetchThreads = true, collapsedThreadsExtended = false): NewActionFuncAsync<PostList> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let posts; let posts;
try { try {
const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState()); const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState());
@@ -937,8 +938,8 @@ export function getPostsBefore(channelId: string, postId: string, page = 0, perP
}; };
} }
export function getPostsAfter(channelId: string, postId: string, page = 0, perPage = Posts.POST_CHUNK_SIZE, fetchThreads = true, collapsedThreadsExtended = false) { export function getPostsAfter(channelId: string, postId: string, page = 0, perPage = Posts.POST_CHUNK_SIZE, fetchThreads = true, collapsedThreadsExtended = false): NewActionFuncAsync<PostList> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let posts; let posts;
try { try {
const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState()); const collapsedThreadsEnabled = isCollapsedThreadsEnabled(getState());
@@ -959,8 +960,8 @@ export function getPostsAfter(channelId: string, postId: string, page = 0, perPa
}; };
} }
export function getPostsAround(channelId: string, postId: string, perPage = Posts.POST_CHUNK_SIZE / 2, fetchThreads = true, collapsedThreadsExtended = false) { export function getPostsAround(channelId: string, postId: string, perPage = Posts.POST_CHUNK_SIZE / 2, fetchThreads = true, collapsedThreadsExtended = false): NewActionFuncAsync<PostList> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let after; let after;
let thread; let thread;
let before; let before;
@@ -1008,9 +1009,9 @@ export function getPostsAround(channelId: string, postId: string, perPage = Post
// getThreadsForPosts is intended for an array of posts that have been batched // getThreadsForPosts is intended for an array of posts that have been batched
// (see the actions/websocket_actions/handleNewPostEvents function in the webapp) // (see the actions/websocket_actions/handleNewPostEvents function in the webapp)
export function getThreadsForPosts(posts: Post[], fetchThreads = true) { export function getThreadsForPosts(posts: Post[], fetchThreads = true): ThunkActionFunc<unknown> {
const rootsSet = new Set<string>(); const rootsSet = new Set<string>();
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
if (!Array.isArray(posts) || !posts.length) { if (!Array.isArray(posts) || !posts.length) {
return {data: true}; return {data: true};
} }
@@ -1138,8 +1139,8 @@ export async function getMentionsAndStatusesForPosts(postsArrayOrMap: Post[]|Pos
return Promise.all(promises); return Promise.all(promises);
} }
export function getPostsByIds(ids: string[]) { export function getPostsByIds(ids: string[]): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let posts; let posts;
try { try {
@@ -1250,19 +1251,15 @@ export function removePost(post: ExtendedPost): NewActionFunc<boolean> {
}; };
} }
export function selectPost(postId: string) { export function selectPost(postId: string) { // HARRISONTODO unused
return async (dispatch: DispatchFunc) => { return {
dispatch({ type: PostTypes.RECEIVED_POST_SELECTED,
type: PostTypes.RECEIVED_POST_SELECTED, data: postId,
data: postId,
});
return {data: true};
}; };
} }
export function moveThread(postId: string, channelId: string) { export function moveThread(postId: string, channelId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
try { try {
await Client4.moveThread(postId, channelId); await Client4.moveThread(postId, channelId);
} catch (error) { } catch (error) {
@@ -1285,8 +1282,8 @@ export function selectFocusedPostId(postId: string) {
}; };
} }
export function unflagPost(postId: string) { export function unflagPost(postId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const {currentUserId} = getState().entities.users; const {currentUserId} = getState().entities.users;
const preference = { const preference = {
user_id: currentUserId, user_id: currentUserId,
@@ -1300,8 +1297,8 @@ export function unflagPost(postId: string) {
}; };
} }
export function addPostReminder(userId: string, postId: string, timestamp: number) { export function addPostReminder(userId: string, postId: string, timestamp: number): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
try { try {
await Client4.addPostReminder(userId, postId, timestamp); await Client4.addPostReminder(userId, postId, timestamp);
} catch (error) { } catch (error) {
@@ -1317,8 +1314,8 @@ export function doPostAction(postId: string, actionId: string, selectedOption =
return doPostActionWithCookie(postId, actionId, '', selectedOption); return doPostActionWithCookie(postId, actionId, '', selectedOption);
} }
export function doPostActionWithCookie(postId: string, actionId: string, actionCookie: string, selectedOption = '') { export function doPostActionWithCookie(postId: string, actionId: string, actionCookie: string, selectedOption = ''): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let data; let data;
try { try {
data = await Client4.doPostActionWithCookie(postId, actionId, actionCookie, selectedOption); data = await Client4.doPostActionWithCookie(postId, actionId, actionCookie, selectedOption);
@@ -1340,29 +1337,21 @@ export function doPostActionWithCookie(postId: string, actionId: string, actionC
} }
export function addMessageIntoHistory(message: string) { export function addMessageIntoHistory(message: string) {
return async (dispatch: DispatchFunc) => { return {
dispatch({ type: PostTypes.ADD_MESSAGE_INTO_HISTORY,
type: PostTypes.ADD_MESSAGE_INTO_HISTORY, data: message,
data: message,
});
return {data: true};
}; };
} }
export function resetHistoryIndex(index: string) { export function resetHistoryIndex(index: string) {
return async (dispatch: DispatchFunc) => { return {
dispatch({ type: PostTypes.RESET_HISTORY_INDEX,
type: PostTypes.RESET_HISTORY_INDEX, data: index,
data: index,
});
return {data: true};
}; };
} }
export function moveHistoryIndexBack(index: string) { export function moveHistoryIndexBack(index: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc) => { return async (dispatch) => {
dispatch({ dispatch({
type: PostTypes.MOVE_HISTORY_INDEX_BACK, type: PostTypes.MOVE_HISTORY_INDEX_BACK,
data: index, data: index,
@@ -1372,8 +1361,8 @@ export function moveHistoryIndexBack(index: string) {
}; };
} }
export function moveHistoryIndexForward(index: string) { export function moveHistoryIndexForward(index: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc) => { return async (dispatch) => {
dispatch({ dispatch({
type: PostTypes.MOVE_HISTORY_INDEX_FORWARD, type: PostTypes.MOVE_HISTORY_INDEX_FORWARD,
data: index, data: index,
@@ -1386,8 +1375,8 @@ export function moveHistoryIndexForward(index: string) {
/** /**
* Ensures thread-replies in channels correctly follow CRT:ON/OFF * Ensures thread-replies in channels correctly follow CRT:ON/OFF
*/ */
export function resetReloadPostsInChannel() { export function resetReloadPostsInChannel(): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
dispatch({ dispatch({
type: PostTypes.RESET_POSTS_IN_CHANNEL, type: PostTypes.RESET_POSTS_IN_CHANNEL,
}); });
@@ -1403,8 +1392,8 @@ export function resetReloadPostsInChannel() {
}; };
} }
export function acknowledgePost(postId: string) { export function acknowledgePost(postId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const userId = getCurrentUserId(getState()); const userId = getCurrentUserId(getState());
let data; let data;
@@ -1425,8 +1414,8 @@ export function acknowledgePost(postId: string) {
}; };
} }
export function unacknowledgePost(postId: string) { export function unacknowledgePost(postId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const userId = getCurrentUserId(getState()); const userId = getCurrentUserId(getState());
try { try {

Просмотреть файл

@@ -6,7 +6,7 @@ import type {Role} from '@mattermost/types/roles';
import {RoleTypes} from 'mattermost-redux/action_types'; import {RoleTypes} from 'mattermost-redux/action_types';
import {Client4} from 'mattermost-redux/client'; import {Client4} from 'mattermost-redux/client';
import {getRoles} from 'mattermost-redux/selectors/entities/roles_helpers'; import {getRoles} from 'mattermost-redux/selectors/entities/roles_helpers';
import type {DispatchFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions'; import type {NewActionFuncAsync} from 'mattermost-redux/types/actions';
import {bindClientFunc} from './helpers'; import {bindClientFunc} from './helpers';
@@ -62,9 +62,9 @@ export function editRole(role: Partial<Role> & {id: string}) {
} }
export function setPendingRoles(roles: string[]) { export function setPendingRoles(roles: string[]) {
return async (dispatch: DispatchFunc) => { return {
dispatch({type: RoleTypes.SET_PENDING_ROLES, data: roles}); type: RoleTypes.SET_PENDING_ROLES,
return {data: roles}; data: roles,
}; };
} }

Просмотреть файл

@@ -18,7 +18,7 @@ import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/pre
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getThread as getThreadSelector, getThreadItemsInChannel} from 'mattermost-redux/selectors/entities/threads'; import {getThread as getThreadSelector, getThreadItemsInChannel} from 'mattermost-redux/selectors/entities/threads';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions'; import type {DispatchFunc, GetStateFunc, NewActionFunc, NewActionFuncAsync} from 'mattermost-redux/types/actions';
import {logError} from './errors'; import {logError} from './errors';
import {forceLogoutIfNecessary} from './helpers'; import {forceLogoutIfNecessary} from './helpers';
@@ -26,8 +26,8 @@ import {getPostThread} from './posts';
type ExtendedPost = Post & { system_post_ids?: string[] }; type ExtendedPost = Post & { system_post_ids?: string[] };
export function fetchThreads(userId: string, teamId: string, {before = '', after = '', perPage = ThreadConstants.THREADS_CHUNK_SIZE, unread = false, totalsOnly = false, threadsOnly = false, extended = false, since = 0} = {}) { export function fetchThreads(userId: string, teamId: string, {before = '', after = '', perPage = ThreadConstants.THREADS_CHUNK_SIZE, unread = false, totalsOnly = false, threadsOnly = false, extended = false, since = 0} = {}): NewActionFuncAsync<UserThreadList> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let data: undefined | UserThreadList; let data: undefined | UserThreadList;
try { try {
@@ -42,8 +42,8 @@ export function fetchThreads(userId: string, teamId: string, {before = '', after
}; };
} }
export function getThreads(userId: string, teamId: string, {before = '', after = '', perPage = ThreadConstants.THREADS_CHUNK_SIZE, unread = false, extended = true} = {}) { export function getThreads(userId: string, teamId: string, {before = '', after = '', perPage = ThreadConstants.THREADS_CHUNK_SIZE, unread = false, extended = true} = {}): NewActionFuncAsync<UserThreadList> {
return async (dispatch: DispatchFunc) => { return async (dispatch) => {
const response = await dispatch(fetchThreads(userId, teamId, {before, after, perPage, unread, totalsOnly: false, threadsOnly: true, extended})); const response = await dispatch(fetchThreads(userId, teamId, {before, after, perPage, unread, totalsOnly: false, threadsOnly: true, extended}));
if (response.error) { if (response.error) {
@@ -79,8 +79,8 @@ export function getThreads(userId: string, teamId: string, {before = '', after =
}; };
} }
export function getThreadCounts(userId: string, teamId: string) { export function getThreadCounts(userId: string, teamId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc) => { return async (dispatch) => {
const response = await dispatch(fetchThreads(userId, teamId, {totalsOnly: true, threadsOnly: false})); const response = await dispatch(fetchThreads(userId, teamId, {totalsOnly: true, threadsOnly: false}));
if (response.error) { if (response.error) {
@@ -111,8 +111,8 @@ export function getThreadCounts(userId: string, teamId: string) {
}; };
} }
export function getCountsAndThreadsSince(userId: string, teamId: string, since?: number) { export function getCountsAndThreadsSince(userId: string, teamId: string, since?: number): NewActionFuncAsync {
return async (dispatch: DispatchFunc) => { return async (dispatch) => {
const response = await dispatch(fetchThreads(userId, teamId, {since, totalsOnly: false, threadsOnly: false, extended: true})); const response = await dispatch(fetchThreads(userId, teamId, {since, totalsOnly: false, threadsOnly: false, extended: true}));
if (response.error) { if (response.error) {
@@ -218,8 +218,8 @@ export function handleThreadArrived(dispatch: DispatchFunc, getState: GetStateFu
return thread; return thread;
} }
export function getThread(userId: string, teamId: string, threadId: string, extended = true) { export function getThread(userId: string, teamId: string, threadId: string, extended = true): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
let thread; let thread;
try { try {
thread = await Client4.getUserThread(userId, teamId, threadId, extended); thread = await Client4.getUserThread(userId, teamId, threadId, extended);
@@ -246,8 +246,8 @@ export function handleAllMarkedRead(dispatch: DispatchFunc, teamId: string) {
}); });
} }
export function markAllThreadsInTeamRead(userId: string, teamId: string) { export function markAllThreadsInTeamRead(userId: string, teamId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
try { try {
await Client4.updateThreadsReadForUser(userId, teamId); await Client4.updateThreadsReadForUser(userId, teamId);
} catch (error) { } catch (error) {
@@ -262,8 +262,8 @@ export function markAllThreadsInTeamRead(userId: string, teamId: string) {
}; };
} }
export function markThreadAsUnread(userId: string, teamId: string, threadId: string, postId: string) { export function markThreadAsUnread(userId: string, teamId: string, threadId: string, postId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
try { try {
await Client4.markThreadAsUnreadForUser(userId, teamId, threadId, postId); await Client4.markThreadAsUnreadForUser(userId, teamId, threadId, postId);
} catch (error) { } catch (error) {
@@ -276,8 +276,8 @@ export function markThreadAsUnread(userId: string, teamId: string, threadId: str
}; };
} }
export function markLastPostInThreadAsUnread(userId: string, teamId: string, threadId: string) { export function markLastPostInThreadAsUnread(userId: string, teamId: string, threadId: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const getPostsForThread = makeGetPostsForThread(); const getPostsForThread = makeGetPostsForThread();
let posts = getPostsForThread(getState(), threadId); let posts = getPostsForThread(getState(), threadId);
@@ -303,8 +303,8 @@ export function markLastPostInThreadAsUnread(userId: string, teamId: string, thr
}; };
} }
export function updateThreadRead(userId: string, teamId: string, threadId: string, timestamp: number) { export function updateThreadRead(userId: string, teamId: string, threadId: string, timestamp: number): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
try { try {
await Client4.updateThreadReadForUser(userId, teamId, threadId, timestamp); await Client4.updateThreadReadForUser(userId, teamId, threadId, timestamp);
} catch (error) { } catch (error) {
@@ -334,8 +334,8 @@ export function handleReadChanged(
prevUnreadReplies: number; prevUnreadReplies: number;
newUnreadReplies: number; newUnreadReplies: number;
}, },
) { ): NewActionFunc {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const channel = getChannel(state, channelId); const channel = getChannel(state, channelId);
const thread = getThreadSelector(state, threadId); const thread = getThreadSelector(state, threadId);
@@ -369,8 +369,8 @@ export function handleFollowChanged(dispatch: DispatchFunc, threadId: string, te
}); });
} }
export function setThreadFollow(userId: string, teamId: string, threadId: string, newState: boolean) { export function setThreadFollow(userId: string, teamId: string, threadId: string, newState: boolean): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
handleFollowChanged(dispatch, threadId, teamId, newState); handleFollowChanged(dispatch, threadId, teamId, newState);
try { try {
@@ -412,8 +412,8 @@ export function handleAllThreadsInChannelMarkedRead(dispatch: DispatchFunc, getS
dispatch(batchActions(actions)); dispatch(batchActions(actions));
} }
export function decrementThreadCounts(post: ExtendedPost) { export function decrementThreadCounts(post: ExtendedPost): NewActionFunc {
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const thread = getThreadSelector(state, post.id); const thread = getThreadSelector(state, post.id);
@@ -424,12 +424,13 @@ export function decrementThreadCounts(post: ExtendedPost) {
const channel = getChannel(state, post.channel_id); const channel = getChannel(state, post.channel_id);
const teamId = channel?.team_id || getCurrentTeamId(state); const teamId = channel?.team_id || getCurrentTeamId(state);
return dispatch({ dispatch({
type: ThreadTypes.DECREMENT_THREAD_COUNTS, type: ThreadTypes.DECREMENT_THREAD_COUNTS,
teamId, teamId,
replies: thread.unread_replies, replies: thread.unread_replies,
mentions: thread.unread_mentions, mentions: thread.unread_mentions,
channelType: channel.type, channelType: channel.type,
}); });
return {data: true};
}; };
} }

Просмотреть файл

@@ -3,12 +3,12 @@
import {getCurrentTimezoneFull} from 'mattermost-redux/selectors/entities/timezone'; import {getCurrentTimezoneFull} from 'mattermost-redux/selectors/entities/timezone';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions'; import type {NewActionFuncAsync} from 'mattermost-redux/types/actions';
import {updateMe} from './users'; import {updateMe} from './users';
export function autoUpdateTimezone(deviceTimezone: string) { export function autoUpdateTimezone(deviceTimezone: string): NewActionFuncAsync {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => { return async (dispatch, getState) => {
const currentUser = getCurrentUser(getState()); const currentUser = getCurrentUser(getState());
const currentTimezone = getCurrentTimezoneFull(getState()); const currentTimezone = getCurrentTimezoneFull(getState());
const newTimezoneExists = currentTimezone.automaticTimezone !== deviceTimezone; const newTimezoneExists = currentTimezone.automaticTimezone !== deviceTimezone;

Просмотреть файл

@@ -292,7 +292,7 @@ export function getProfilesNotInTeam(teamId: string, groupConstrained: boolean,
}; };
} }
export function getProfilesWithoutTeam(page: number, perPage: number = General.PROFILE_CHUNK_SIZE, options: any = {}): NewActionFuncAsync { export function getProfilesWithoutTeam(page: number, perPage: number = General.PROFILE_CHUNK_SIZE, options: any = {}): NewActionFuncAsync<UserProfile[]> {
return async (dispatch, getState) => { return async (dispatch, getState) => {
let profiles = null; let profiles = null;
try { try {

Просмотреть файл

@@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import type {Action as ReduxAction, AnyAction} from 'redux'; import type {Action as ReduxAction, AnyAction, Dispatch} from 'redux';
import type {ThunkAction as BaseThunkAction} from 'redux-thunk'; import type {ThunkAction as BaseThunkAction} from 'redux-thunk';
import type {GlobalState} from '@mattermost/types/store'; import type {GlobalState} from '@mattermost/types/store';
@@ -14,6 +14,7 @@ import type {GlobalState} from '@mattermost/types/store';
*/ */
import 'redux-thunk/extend-redux'; import 'redux-thunk/extend-redux';
export type DispatchFunc = Dispatch;
export type GetStateFunc = () => GlobalState; export type GetStateFunc = () => GlobalState;
export type GenericAction = AnyAction; export type GenericAction = AnyAction;
@@ -25,8 +26,6 @@ export type ActionResult<Data = any, Error = any> = {
error?: Error; error?: Error;
}; };
export type DispatchFunc = (action: AnyAction | NewActionFunc<unknown, any> | NewActionFuncAsync<unknown, any> | ThunkActionFunc<any>, getState?: GetStateFunc | null) => Promise<ActionResult>;
/** /**
* NewActionFunc should be the return type of most non-async Thunk action creators. If that action requires web app * NewActionFunc should be the return type of most non-async Thunk action creators. If that action requires web app
* state, the second type parameter should be used to pass the version of GlobalState from 'types/store'. * state, the second type parameter should be used to pass the version of GlobalState from 'types/store'.

Просмотреть файл

@@ -3,7 +3,7 @@
import type {Store} from 'redux'; import type {Store} from 'redux';
import type {DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions'; import type {NewActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import store from 'stores/redux_store'; import store from 'stores/redux_store';
@@ -14,8 +14,8 @@ export abstract class ProductPlugin {
abstract uninitialize(): void; abstract uninitialize(): void;
} }
export function initializeProducts() { export function initializeProducts(): ThunkActionFunc<Promise<unknown>> {
return (dispatch: DispatchFunc) => { return (dispatch) => {
return Promise.all([ return Promise.all([
dispatch(loadRemoteModules()), dispatch(loadRemoteModules()),
dispatch(configureClient()), dispatch(configureClient()),
@@ -23,16 +23,16 @@ export function initializeProducts() {
}; };
} }
function configureClient() { function configureClient(): NewActionFuncAsync {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
return (dispatch: DispatchFunc, getState: GetStateFunc) => { return (dispatch, getState) => {
return Promise.resolve({data: true}); return Promise.resolve({data: true});
}; };
} }
function loadRemoteModules() { function loadRemoteModules(): NewActionFuncAsync {
/* eslint-disable no-console */ /* eslint-disable no-console */
return async (/*dispatch: DispatchFunc, getState: GetStateFunc*/) => { return async (/*dispatch, getState*/) => {
// const config = getConfig(getState()); // const config = getConfig(getState());
/** /**