Add web app versions of ActionFunc types (#29483)

* Re-export ActionFunc types from mattermost-redux from types/store

* Start using ActionFunc types from types/store instead of mattermost-redux

These are all the places where the type checker failed when I added the
web app version of ActionFunc. I'll move all the other files in a
separate commit.

* Use ActionFunc types from types/store everywhere outside mattermost-redux

* Make types/store versions of ActionFunc use web app GlobalState

* Stop passing GlobalState into ActionFunc explicitly

* Stop casting as GlobalState where it's no longer needed

* Prevent importing mattermost-redux version of ActionFunc in the rest of the app

* Fix no-restricted-imports applying incorrectly to mattermost-redux and types/store
Этот коммит содержится в:
Harrison Healey
2024-12-09 13:37:41 -05:00
коммит произвёл GitHub
родитель 7263ba4bc1
Коммит e873e5c1ef
48 изменённых файлов: 206 добавлений и 166 удалений

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

@@ -41,6 +41,22 @@
"rules": {
"no-only-tests/no-only-tests": ["error", {"focus": ["only", "skip"]}]
}
},
{
"files": ["*"],
"excludedFiles": ["src/packages/mattermost-redux/**"],
"rules": {
"@typescript-eslint/no-restricted-imports": [
"error",
{
"paths": [{
"name": "mattermost-redux/types/actions",
"importNames": ["DispatchFunc", "GetStateFunc", "ActionFunc", "ActionFuncAsync", "ThunkActionFunc"],
"message": "Use the web app version of it from types/store"
}]
}
]
}
}
]
}

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

@@ -9,7 +9,6 @@ import type {Post} from '@mattermost/types/posts';
import {Client4} from 'mattermost-redux/client';
import {AppCallResponseTypes} from 'mattermost-redux/constants/apps';
import type {ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {cleanForm} from 'mattermost-redux/utils/apps';
import {openModal} from 'actions/views/modals';
@@ -22,6 +21,7 @@ import {ModalIdentifiers} from 'utils/constants';
import {getSiteURL, shouldOpenInNewTab} from 'utils/url';
import type {DoAppCallResult} from 'types/apps';
import type {ActionFuncAsync, ThunkActionFunc} from 'types/store';
import {sendEphemeralPost} from './global_actions';

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

@@ -13,7 +13,6 @@ import {savePreferences} from 'mattermost-redux/actions/preferences';
import {getChannelByName, getUnreadChannelIds, getChannel} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamUrl, getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions.jsx';
import {loadNewDMIfNeeded, loadNewGMIfNeeded, loadProfilesForSidebar} from 'actions/user_actions';
@@ -22,6 +21,8 @@ import {getHistory} from 'utils/browser_history';
import {Constants, Preferences, NotificationLevels} from 'utils/constants';
import {getDirectChannelName} from 'utils/utils';
import type {ActionFuncAsync} from 'types/store';
export function openDirectChannelToUserId(userId: UserProfile['id']): ActionFuncAsync<Channel> {
return async (dispatch, getState) => {
const state = getState();

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

@@ -4,13 +4,12 @@
import type {ChannelBookmark, ChannelBookmarkCreate, ChannelBookmarkPatch} from '@mattermost/types/channel_bookmarks';
import * as Actions from 'mattermost-redux/actions/channel_bookmarks';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import {getConnectionId} from 'selectors/general';
import type {GlobalState} from 'types/store';
import type {ActionFuncAsync} from 'types/store';
export function deleteBookmark(channelId: string, id: string): ActionFuncAsync<boolean, GlobalState> {
export function deleteBookmark(channelId: string, id: string): ActionFuncAsync<boolean> {
return (dispatch, getState) => {
const state = getState();
const connectionId = getConnectionId(state);
@@ -18,7 +17,7 @@ export function deleteBookmark(channelId: string, id: string): ActionFuncAsync<b
};
}
export function createBookmark(channelId: string, bookmark: ChannelBookmarkCreate): ActionFuncAsync<boolean, GlobalState> {
export function createBookmark(channelId: string, bookmark: ChannelBookmarkCreate): ActionFuncAsync<boolean> {
return (dispatch, getState) => {
const state = getState();
const connectionId = getConnectionId(state);
@@ -26,7 +25,7 @@ export function createBookmark(channelId: string, bookmark: ChannelBookmarkCreat
};
}
export function editBookmark(channelId: string, id: string, patch: ChannelBookmarkPatch): ActionFuncAsync<boolean, GlobalState> {
export function editBookmark(channelId: string, id: string, patch: ChannelBookmarkPatch): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const state = getState();
const connectionId = getConnectionId(state);
@@ -34,7 +33,7 @@ export function editBookmark(channelId: string, id: string, patch: ChannelBookma
};
}
export function reorderBookmark(channelId: string, id: string, newOrder: number): ActionFuncAsync<boolean, GlobalState> {
export function reorderBookmark(channelId: string, id: string, newOrder: number): ActionFuncAsync<boolean> {
return (dispatch, getState) => {
const state = getState();
const connectionId = getConnectionId(state);
@@ -42,6 +41,6 @@ export function reorderBookmark(channelId: string, id: string, newOrder: number)
};
}
export function fetchChannelBookmarks(channelId: string): ActionFuncAsync<ChannelBookmark[], GlobalState> {
export function fetchChannelBookmarks(channelId: string): ActionFuncAsync<ChannelBookmark[]> {
return Actions.fetchChannelBookmarks(channelId);
}

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

@@ -7,11 +7,10 @@ import {CloudTypes} from 'mattermost-redux/action_types';
import {getCloudCustomer, getCloudProducts, getCloudSubscription, getInvoices} from 'mattermost-redux/actions/cloud';
import {Client4} from 'mattermost-redux/client';
import {getCloudErrors} from 'mattermost-redux/selectors/entities/cloud';
import type {ActionFunc, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions.jsx';
import type {GlobalState} from 'types/store';
import type {ActionFunc, ThunkActionFunc} from 'types/store';
export function getInstallation() {
return async () => {
@@ -125,7 +124,7 @@ export function getTeamsUsage(): ThunkActionFunc<Promise<boolean | ServerError>>
};
}
export function retryFailedCloudFetches(): ActionFunc<boolean, GlobalState> {
export function retryFailedCloudFetches(): ActionFunc<boolean> {
return (dispatch, getState) => {
const errors = getCloudErrors(getState());
if (Object.keys(errors).length === 0) {

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

@@ -16,7 +16,6 @@ import {isMarketplaceEnabled} from 'mattermost-redux/selectors/entities/general'
import {haveICurrentTeamPermission} from 'mattermost-redux/selectors/entities/roles';
import {getCurrentRelativeTeamUrl, getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import * as GlobalActions from 'actions/global_actions';
import * as PostActions from 'actions/post_actions';
@@ -35,7 +34,7 @@ import {isUrlSafe, getSiteURL} from 'utils/url';
import * as UserAgent from 'utils/user_agent';
import {localizeMessage, getUserIdFromChannelName} from 'utils/utils';
import type {GlobalState} from 'types/store';
import type {ActionFuncAsync} from 'types/store';
import {doAppSubmit, openAppsModal, postEphemeralCallResponseForCommandArgs} from './apps';
import {trackEvent} from './telemetry_actions';
@@ -47,9 +46,9 @@ export type ExecuteCommandReturnType = {
appResponse?: AppCallResponse;
}
export function executeCommand(message: string, args: CommandArgs): ActionFuncAsync<ExecuteCommandReturnType, GlobalState> {
export function executeCommand(message: string, args: CommandArgs): ActionFuncAsync<ExecuteCommandReturnType> {
return async (dispatch, getState) => {
const state = getState() as GlobalState;
const state = getState();
let msg = message;
@@ -149,7 +148,7 @@ export function executeCommand(message: string, args: CommandArgs): ActionFuncAs
}
if (appsEnabled(state)) {
const getGlobalState = () => getState() as GlobalState;
const getGlobalState = () => getState();
const createErrorMessage = (errMessage: string) => {
return {error: {message: errMessage}};
};

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

@@ -10,12 +10,13 @@ import {FileTypes} from 'mattermost-redux/action_types';
import {getLogErrorAction} from 'mattermost-redux/actions/errors';
import {forceLogoutIfNecessary} from 'mattermost-redux/actions/helpers';
import {Client4} from 'mattermost-redux/client';
import type {ThunkActionFunc} from 'mattermost-redux/types/actions';
import type {FilePreviewInfo} from 'components/file_preview/file_preview';
import {localizeMessage} from 'utils/utils';
import type {ThunkActionFunc} from 'types/store';
export interface UploadFile {
file: File;
name: string;

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

@@ -25,7 +25,6 @@ import {getConfig, isPerformanceDebuggingEnabled} from 'mattermost-redux/selecto
import {getBool, getIsOnboardingFlowEnabled, isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamId, getMyTeams, getTeam, getMyTeamMember, getTeamMemberships, getActiveTeamsList} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUser, getCurrentUserId, isFirstAdmin} from 'mattermost-redux/selectors/entities/users';
import type {ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {calculateUnreadCount} from 'mattermost-redux/utils/channel_utils';
import {handleNewPost} from 'actions/post_actions';
@@ -49,7 +48,7 @@ import DesktopApp from 'utils/desktop_api';
import {filterAndSortTeamsByDisplayName} from 'utils/team_utils';
import * as Utils from 'utils/utils';
import type {GlobalState} from 'types/store';
import type {ActionFuncAsync, ThunkActionFunc, GlobalState} from 'types/store';
import {openModal} from './views/modals';
@@ -170,7 +169,7 @@ export function showMobileSubMenuModal(elements: any[]) { // TODO Use more speci
dispatch(openModal(submenuModalData));
}
export function sendEphemeralPost(message: string, channelId?: string, parentId?: string, userId?: string): ActionFuncAsync<boolean, GlobalState> {
export function sendEphemeralPost(message: string, channelId?: string, parentId?: string, userId?: string): ActionFuncAsync<boolean> {
return (doDispatch, doGetState) => {
const timestamp = Utils.getTimestamp();
const post = {

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

@@ -5,9 +5,7 @@ import type {Channel} from '@mattermost/types/channels';
import type {CommandArgs} from '@mattermost/types/integrations';
import type {Post} from '@mattermost/types/posts';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import type {GlobalState} from 'types/store';
import type {ActionFuncAsync} from 'types/store';
import type {DesktopNotificationArgs} from 'types/store/plugins';
import type {NewPostMessageProps} from './new_post';
@@ -16,7 +14,7 @@ import type {NewPostMessageProps} from './new_post';
* @param {Post} originalPost
* @returns {ActionFuncAsync<Post>}
*/
export function runMessageWillBePostedHooks(originalPost: Post): ActionFuncAsync<Post, GlobalState> {
export function runMessageWillBePostedHooks(originalPost: Post): ActionFuncAsync<Post> {
return async (dispatch, getState) => {
const hooks = getState().plugins.components.MessageWillBePosted;
if (!hooks || hooks.length === 0) {
@@ -43,7 +41,7 @@ export function runMessageWillBePostedHooks(originalPost: Post): ActionFuncAsync
};
}
export function runSlashCommandWillBePostedHooks(originalMessage: string, originalArgs: CommandArgs): ActionFuncAsync<{message: string; args: CommandArgs}, GlobalState> {
export function runSlashCommandWillBePostedHooks(originalMessage: string, originalArgs: CommandArgs): ActionFuncAsync<{message: string; args: CommandArgs}> {
return async (dispatch, getState) => {
const hooks = getState().plugins.components.SlashCommandWillBePosted;
if (!hooks || hooks.length === 0) {
@@ -78,7 +76,7 @@ export function runSlashCommandWillBePostedHooks(originalMessage: string, origin
};
}
export function runMessageWillBeUpdatedHooks(newPost: Partial<Post>, oldPost: Post): ActionFuncAsync<Partial<Post>, GlobalState> {
export function runMessageWillBeUpdatedHooks(newPost: Partial<Post>, oldPost: Post): ActionFuncAsync<Partial<Post>> {
return async (dispatch, getState) => {
const hooks = getState().plugins.components.MessageWillBeUpdated;
if (!hooks || hooks.length === 0) {
@@ -105,7 +103,7 @@ export function runMessageWillBeUpdatedHooks(newPost: Partial<Post>, oldPost: Po
};
}
export function runDesktopNotificationHooks(post: Post, msgProps: NewPostMessageProps, channel: Channel, teamId: string, args: DesktopNotificationArgs): ActionFuncAsync<DesktopNotificationArgs, GlobalState> {
export function runDesktopNotificationHooks(post: Post, msgProps: NewPostMessageProps, channel: Channel, teamId: string, args: DesktopNotificationArgs): ActionFuncAsync<DesktopNotificationArgs> {
return async (dispatch, getState) => {
const hooks = getState().plugins.components.DesktopNotificationHooks;
if (!hooks || hooks.length === 0) {

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

@@ -5,7 +5,8 @@ import type {ServerError} from '@mattermost/types/errors';
import {HostedCustomerTypes} from 'mattermost-redux/action_types';
import {Client4} from 'mattermost-redux/client';
import type {ThunkActionFunc} from 'mattermost-redux/types/actions';
import type {ThunkActionFunc} from 'types/store';
export function getSelfHostedProducts(): ThunkActionFunc<Promise<boolean | ServerError>> {
return async (dispatch) => {

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

@@ -7,7 +7,8 @@ import * as IntegrationActions from 'mattermost-redux/actions/integrations';
import {getProfilesByIds} from 'mattermost-redux/actions/users';
import {appsEnabled} from 'mattermost-redux/selectors/entities/apps';
import {getUser} from 'mattermost-redux/selectors/entities/users';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import type {ActionFuncAsync} from 'types/store';
const DEFAULT_PAGE_SIZE = 100;

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

@@ -13,7 +13,6 @@ import * as TeamActions from 'mattermost-redux/actions/teams';
import {getChannelMembersInChannels} from 'mattermost-redux/selectors/entities/channels';
import {getTeamMember} from 'mattermost-redux/selectors/entities/teams';
import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc, ActionFuncAsync} from 'mattermost-redux/types/actions';
import {isGuest} from 'mattermost-redux/utils/user_utils';
import {addUsersToTeam} from 'actions/team_actions';
@@ -23,6 +22,8 @@ import type {InviteResults} from 'components/invitation_modal/result_view';
import {ConsolePages} from 'utils/constants';
import type {DispatchFunc, ActionFuncAsync} from 'types/store';
export function sendMembersInvites(teamId: string, users: UserProfile[], emails: string[]): ActionFuncAsync<InviteResults> {
return async (dispatch, getState) => {
if (users.length > 0) {

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

@@ -9,7 +9,6 @@ import {AppBindingLocations, AppCallResponseTypes} from 'mattermost-redux/consta
import {appsEnabled} from 'mattermost-redux/selectors/entities/apps';
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import type {ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {getFilter, getPlugin} from 'selectors/views/marketplace';
@@ -19,12 +18,12 @@ import type {DoAppCallResult} from 'components/suggestion/command_provider/app_c
import {createCallContext, createCallRequest} from 'utils/apps';
import {ActionTypes} from 'utils/constants';
import type {GlobalState} from 'types/store';
import type {ActionFuncAsync, ThunkActionFunc} from 'types/store';
import {doAppSubmit, openAppsModal, postEphemeralCallResponseForContext} from './apps';
// fetchPlugins fetches the latest marketplace plugins and apps, subject to any existing search filter.
export function fetchListing(localOnly = false): ActionFuncAsync<Array<MarketplacePlugin | MarketplaceApp>, GlobalState> {
export function fetchListing(localOnly = false): ActionFuncAsync<Array<MarketplacePlugin | MarketplaceApp>> {
return async (dispatch, getState) => {
const state = getState();
const filter = getFilter(state);
@@ -83,7 +82,7 @@ export function filterListing(filter: string): ReturnType<typeof fetchListing> {
// installPlugin installs the latest version of the given plugin from the marketplace.
//
// On success, it also requests the current state of the plugins to reflect the newly installed plugin.
export function installPlugin(id: string): ThunkActionFunc<void, GlobalState> {
export function installPlugin(id: string): ThunkActionFunc<void> {
return async (dispatch, getState) => {
dispatch({
type: ActionTypes.INSTALLING_MARKETPLACE_ITEM,
@@ -124,7 +123,7 @@ export function installPlugin(id: string): ThunkActionFunc<void, GlobalState> {
// 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.
export function installApp(id: string): ThunkActionFunc<Promise<boolean>, GlobalState> {
export function installApp(id: string): ThunkActionFunc<Promise<boolean>> {
return async (dispatch, getState) => {
dispatch({
type: ActionTypes.INSTALLING_MARKETPLACE_ITEM,

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

@@ -7,7 +7,6 @@ import type {GlobalState} from '@mattermost/types/store';
import {ChannelTypes} from 'mattermost-redux/action_types';
import {receivedNewPost} from 'mattermost-redux/actions/posts';
import {Posts} from 'mattermost-redux/constants';
import type {GetStateFunc} from 'mattermost-redux/types/actions';
import * as NewPostActions from 'actions/new_post';
@@ -168,7 +167,7 @@ describe('actions/new_post', () => {
window.isActive = true;
const actions = NewPostActions.setChannelReadAndViewed(testStore.dispatch, testStore.getState as GetStateFunc, post2, newPostMessageProps, false);
const actions = NewPostActions.setChannelReadAndViewed(testStore.dispatch, testStore.getState, post2, newPostMessageProps, false);
expect(actions).toMatchObject([
{

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

@@ -18,7 +18,6 @@ import * as PostSelectors from 'mattermost-redux/selectors/entities/posts';
import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getThread} from 'mattermost-redux/selectors/entities/threads';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {DispatchFunc, GetStateFunc, ActionFunc, ActionFuncAsync} from 'mattermost-redux/types/actions';
import {
isFromWebhook,
isSystemMessage,
@@ -32,7 +31,7 @@ import {isThreadOpen, makeGetThreadLastViewedAt} from 'selectors/views/threads';
import WebSocketClient from 'client/web_websocket_client';
import {ActionTypes} from 'utils/constants';
import type {GlobalState} from 'types/store';
import type {DispatchFunc, GetStateFunc, ActionFunc, ActionFuncAsync} from 'types/store';
export type NewPostMessageProps = {
channel_type: ChannelType;
@@ -49,7 +48,7 @@ export type NewPostMessageProps = {
post: string;
}
export function completePostReceive(post: Post, websocketMessageProps: NewPostMessageProps, fetchedChannelMember?: boolean): ActionFuncAsync<boolean, GlobalState> {
export function completePostReceive(post: Post, websocketMessageProps: NewPostMessageProps, fetchedChannelMember?: boolean): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const state = getState();
const rootPost = PostSelectors.getPost(state, post.root_id);
@@ -150,7 +149,7 @@ export function setChannelReadAndViewed(dispatch: DispatchFunc, getState: GetSta
return actionsToMarkChannelAsUnread(getState, websocketMessageProps.team_id, post.channel_id, websocketMessageProps.mentions || '', fetchedChannelMember, post.root_id === '', post?.metadata?.priority?.priority);
}
export function setThreadRead(post: Post): ActionFunc<boolean, GlobalState> {
export function setThreadRead(post: Post): ActionFunc<boolean> {
const getThreadLastViewedAt = makeGetThreadLastViewedAt();
return (dispatch, getState) => {
const state = getState();

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

@@ -17,7 +17,6 @@ import {
} from 'mattermost-redux/selectors/entities/preferences';
import {getAllUserMentionKeys} from 'mattermost-redux/selectors/entities/search';
import {getCurrentUserId, getCurrentUser, getStatusForUserId, getUser} from 'mattermost-redux/selectors/entities/users';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import {isChannelMuted} from 'mattermost-redux/utils/channel_utils';
import {ensureString, isSystemMessage, isUserAddedInChannel} from 'mattermost-redux/utils/post_utils';
import {displayUsername} from 'mattermost-redux/utils/user_utils';
@@ -36,7 +35,7 @@ import {cjkrPattern, escapeRegex} from 'utils/text_formatting';
import {isDesktopApp, isMobileApp} from 'utils/user_agent';
import * as Utils from 'utils/utils';
import type {GlobalState} from 'types/store';
import type {ActionFuncAsync, GlobalState} from 'types/store';
import {runDesktopNotificationHooks} from './hooks';
import type {NewPostMessageProps} from './new_post';
@@ -103,7 +102,7 @@ export function getDesktopNotificationSound(channelMember: ChannelMembership | u
return DesktopNotificationSounds.BING;
}
export function sendDesktopNotification(post: Post, msgProps: NewPostMessageProps): ActionFuncAsync<NotificationResult, GlobalState> {
export function sendDesktopNotification(post: Post, msgProps: NewPostMessageProps): ActionFuncAsync<NotificationResult> {
return async (dispatch, getState) => {
const state = getState();
@@ -411,7 +410,7 @@ function shouldSkipNotification(
return undefined;
}
export function notifyMe(title: string, body: string, channelId: string, teamId: string, silent: boolean, soundName: string, url: string): ActionFuncAsync<NotificationResult, GlobalState> {
export function notifyMe(title: string, body: string, channelId: string, teamId: string, silent: boolean, soundName: string, url: string): ActionFuncAsync<NotificationResult> {
return async (dispatch) => {
// handle notifications in desktop app
if (isDesktopApp()) {

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

@@ -17,13 +17,6 @@ import * as PostSelectors from 'mattermost-redux/selectors/entities/posts';
import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUserId, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import type {
DispatchFunc,
ActionFunc,
ActionFuncAsync,
ThunkActionFunc,
GetStateFunc,
} from 'mattermost-redux/types/actions';
import {canEditPost, comparePosts} from 'mattermost-redux/utils/post_utils';
import {addRecentEmoji, addRecentEmojis} from 'actions/emoji_actions';
@@ -50,7 +43,13 @@ import {
import {matchEmoticons} from 'utils/emoticons';
import {makeGetIsReactionAlreadyAddedToPost, makeGetUniqueEmojiNameReactionsForPost} from 'utils/post_utils';
import type {GlobalState} from 'types/store';
import type {
DispatchFunc,
ActionFunc,
ActionFuncAsync,
ThunkActionFunc,
GlobalState,
} from 'types/store';
import type {NewPostMessageProps} from './new_post';
import {completePostReceive} from './new_post';
@@ -61,7 +60,7 @@ export type CreatePostOptions = {
ignorePostError?: boolean;
}
export function handleNewPost(post: Post, msg?: {data?: NewPostMessageProps & GroupChannel}): ActionFuncAsync<boolean, GlobalState> {
export function handleNewPost(post: Post, msg?: {data?: NewPostMessageProps & GroupChannel}): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
let websocketMessageProps = {};
const state = getState();
@@ -95,7 +94,7 @@ const getPostsForIds = PostSelectors.makeGetPostsForIds();
export function flagPost(postId: string): ActionFuncAsync {
return async (dispatch, getState) => {
await dispatch(PostActions.flagPost(postId));
const state = getState() as GlobalState;
const state = getState();
const rhsState = getRhsState(state);
if (rhsState === RHSStates.FLAG) {
@@ -109,7 +108,7 @@ export function flagPost(postId: string): ActionFuncAsync {
export function unflagPost(postId: string): ActionFuncAsync {
return async (dispatch, getState) => {
await dispatch(PostActions.unflagPost(postId));
const state = getState() as GlobalState;
const state = getState();
const rhsState = getRhsState(state);
if (rhsState === RHSStates.FLAG) {
@@ -137,7 +136,7 @@ export function createPost(
files: FileInfo[],
afterSubmit?: (response: SubmitPostReturnType) => void,
options?: OnSubmitOptions,
): ActionFuncAsync<PostActions.CreatePostReturnType, GlobalState> {
): ActionFuncAsync<PostActions.CreatePostReturnType> {
return async (dispatch) => {
dispatch(addRecentEmojisForMessage(post.message));
@@ -156,11 +155,11 @@ export function createPost(
};
}
export function createSchedulePostFromDraft(scheduledPost: ScheduledPost): ActionFuncAsync<PostActions.CreatePostReturnType, GlobalState> {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
export function createSchedulePostFromDraft(scheduledPost: ScheduledPost): ActionFuncAsync<PostActions.CreatePostReturnType> {
return async (dispatch, getState) => {
dispatch(addRecentEmojisForMessage(scheduledPost.message));
const state = getState() as GlobalState;
const state = getState();
const connectionId = getConnectionId(state);
const channel = state.entities.channels.channels[scheduledPost.channel_id];
const result = await dispatch(createSchedulePost(scheduledPost, channel.team_id, connectionId));
@@ -186,9 +185,9 @@ function storeCommentDraft(rootPostId: string, draft: null): ActionFunc {
};
}
export function submitReaction(postId: string, action: string, emojiName: string): ActionFuncAsync<PostActions.SubmitReactionReturnType, GlobalState> {
export function submitReaction(postId: string, action: string, emojiName: string): ActionFuncAsync<PostActions.SubmitReactionReturnType> {
return async (dispatch, getState) => {
const state = getState() as GlobalState;
const state = getState();
const getIsReactionAlreadyAddedToPost = makeGetIsReactionAlreadyAddedToPost();
const isReactionAlreadyAddedToPost = getIsReactionAlreadyAddedToPost(state, postId, emojiName);
@@ -202,7 +201,7 @@ export function submitReaction(postId: string, action: string, emojiName: string
};
}
export function toggleReaction(postId: string, emojiName: string): ActionFuncAsync<PostActions.SubmitReactionReturnType, GlobalState> {
export function toggleReaction(postId: string, emojiName: string): ActionFuncAsync<PostActions.SubmitReactionReturnType> {
return async (dispatch, getState) => {
const state = getState();
const getIsReactionAlreadyAddedToPost = makeGetIsReactionAlreadyAddedToPost();
@@ -216,10 +215,10 @@ export function toggleReaction(postId: string, emojiName: string): ActionFuncAsy
};
}
export function addReaction(postId: string, emojiName: string): ActionFuncAsync<PostActions.SubmitReactionReturnType, GlobalState> {
export function addReaction(postId: string, emojiName: string): ActionFuncAsync<PostActions.SubmitReactionReturnType> {
const getUniqueEmojiNameReactionsForPost = makeGetUniqueEmojiNameReactionsForPost();
return async (dispatch, getState) => {
const state = getState() as GlobalState;
const state = getState();
const config = getConfig(state);
const uniqueEmojiNames = getUniqueEmojiNameReactionsForPost(state, postId) ?? [];
@@ -242,7 +241,7 @@ export function addReaction(postId: string, emojiName: string): ActionFuncAsync<
};
}
export function searchForTerm(term: string): ActionFunc<boolean, GlobalState> {
export function searchForTerm(term: string): ActionFunc<boolean> {
return (dispatch) => {
dispatch(RhsActions.updateSearchTerms(term));
dispatch(RhsActions.showSearchResults());
@@ -291,7 +290,7 @@ function removePostFromSearchResults(postId: string, state: GlobalState, dispatc
}
}
export function pinPost(postId: string): ActionFuncAsync<boolean, GlobalState> {
export function pinPost(postId: string): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
await dispatch(PostActions.pinPost(postId));
const state = getState();
@@ -304,7 +303,7 @@ export function pinPost(postId: string): ActionFuncAsync<boolean, GlobalState> {
};
}
export function unpinPost(postId: string): ActionFuncAsync<boolean, GlobalState> {
export function unpinPost(postId: string): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
await dispatch(PostActions.unpinPost(postId));
const state = getState();
@@ -395,7 +394,7 @@ export function markMostRecentPostInChannelAsUnread(channelId: string): ActionFu
}
// Action called by DeletePostModal when the post is deleted
export function deleteAndRemovePost(post: Post): ActionFuncAsync<boolean, GlobalState> {
export function deleteAndRemovePost(post: Post): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const {error} = await dispatch(PostActions.deletePost(post));
if (error) {
@@ -432,7 +431,7 @@ export function deleteAndRemovePost(post: Post): ActionFuncAsync<boolean, Global
};
}
export function toggleEmbedVisibility(postId: string): ThunkActionFunc<void, GlobalState> {
export function toggleEmbedVisibility(postId: string): ThunkActionFunc<void> {
return (dispatch, getState) => {
const state = getState();
const currentUserId = getCurrentUserId(state);
@@ -446,7 +445,7 @@ export function resetEmbedVisibility() {
return StorageActions.actionOnGlobalItemsWithPrefix(StoragePrefixes.EMBED_VISIBLE, () => null);
}
export function toggleInlineImageVisibility(postId: string, imageKey: string): ThunkActionFunc<void, GlobalState> {
export function toggleInlineImageVisibility(postId: string, imageKey: string): ThunkActionFunc<void> {
return (dispatch, getState) => {
const state = getState();
const currentUserId = getCurrentUserId(state);

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

@@ -10,11 +10,10 @@ import {getIsUserStatusesConfigEnabled} from 'mattermost-redux/selectors/entitie
import {getPostsInCurrentChannel} from 'mattermost-redux/selectors/entities/posts';
import {getDirectShowPreferences} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {ActionFunc} from 'mattermost-redux/types/actions';
import {loadCustomEmojisForCustomStatusesByUserIds} from 'actions/emoji_actions';
import type {GlobalState} from 'types/store';
import type {ActionFunc} from 'types/store';
/**
* Adds the following users to the status pool for fetching their statuses:
@@ -22,7 +21,7 @@ import type {GlobalState} from 'types/store';
* - All users who have DMs open with the current user.
* - The current user.
*/
export function addVisibleUsersInCurrentChannelAndSelfToStatusPoll(): ActionFunc<boolean, GlobalState> {
export function addVisibleUsersInCurrentChannelAndSelfToStatusPoll(): ActionFunc<boolean> {
return (dispatch, getState) => {
const state = getState();
const currentUserId = getCurrentUserId(state);

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

@@ -15,11 +15,12 @@ import {getUser} from 'mattermost-redux/actions/users';
import {Client4} from 'mattermost-redux/client';
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {getHistory} from 'utils/browser_history';
import {Preferences} from 'utils/constants';
import type {ActionFuncAsync, ThunkActionFunc} from 'types/store';
export function removeUserFromTeamAndGetStats(teamId: Team['id'], userId: UserProfile['id']): ActionFuncAsync {
return async (dispatch, getState) => {
const response = await dispatch(TeamActions.removeUserFromTeam(teamId, userId));

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

@@ -22,7 +22,7 @@ import {getIsUserStatusesConfigEnabled} from 'mattermost-redux/selectors/entitie
import {getBool, isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamId, getTeamMember} from 'mattermost-redux/selectors/entities/teams';
import * as Selectors from 'mattermost-redux/selectors/entities/users';
import type {ActionResult, ActionFunc, ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import type {ActionResult} from 'mattermost-redux/types/actions';
import {calculateUnreadCount} from 'mattermost-redux/utils/channel_utils';
import {loadCustomEmojisForCustomStatusesByUserIds} from 'actions/emoji_actions';
@@ -33,7 +33,7 @@ import store from 'stores/redux_store';
import {Constants, Preferences, UserStatuses} from 'utils/constants';
import * as Utils from 'utils/utils';
import type {GlobalState} from 'types/store';
import type {ActionFunc, ActionFuncAsync, ThunkActionFunc, GlobalState} from 'types/store';
const dispatch = store.dispatch;
const getState = store.getState;

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

@@ -7,10 +7,10 @@ import type {UserReportOptions, UserReport, UserReportFilter} from '@mattermost/
import {logError} from 'mattermost-redux/actions/errors';
import {forceLogoutIfNecessary} from 'mattermost-redux/actions/helpers';
import {Client4} from 'mattermost-redux/client';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import {ActionTypes} from 'utils/constants';
import type {ActionFuncAsync} from 'types/store';
import type {AdminConsoleUserManagementTableProperties} from 'types/store/views';
export function setNeedsLoggedInLimitReachedCheck(data: boolean) {

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

@@ -42,7 +42,6 @@ import {
} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUserId, getUserByUsername} from 'mattermost-redux/selectors/entities/users';
import {makeAddLastViewAtToProfiles} from 'mattermost-redux/selectors/entities/utils';
import type {ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {getChannelByName} from 'mattermost-redux/utils/channel_utils';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
@@ -61,7 +60,7 @@ import {getHistory} from 'utils/browser_history';
import {isArchivedChannel} from 'utils/channel_utils';
import {Constants, ActionTypes, EventTypes, PostRequestTypes} from 'utils/constants';
import type {GlobalState} from 'types/store';
import type {ActionFuncAsync, ThunkActionFunc} from 'types/store';
export function goToLastViewedChannel(): ActionFuncAsync {
return async (dispatch, getState) => {
@@ -180,8 +179,8 @@ export function leaveChannel(channelId: string): ActionFuncAsync {
if (!prevChannel || !getMyChannelMemberships(state)[prevChannel.id]) {
LocalStorageStore.removePreviousChannel(currentUserId, currentTeam.id, state);
}
const selectedPost = getSelectedPost(state as GlobalState);
const selectedPostId = getSelectedPostId(state as GlobalState);
const selectedPost = getSelectedPost(state);
const selectedPostId = getSelectedPostId(state);
if (selectedPostId && selectedPost.exists === false) {
dispatch(closeRightHandSide());
}
@@ -424,9 +423,9 @@ export function syncPostsInChannel(channelId: string, since: number, prefetch =
return async (dispatch, getState) => {
const time = Date.now();
const state = getState();
const socketStatus = getSocketStatus(state as GlobalState);
const socketStatus = getSocketStatus(state);
let sinceTimeToGetPosts = since;
const lastPostsApiCallForChannel = getLastPostsApiTimeForChannel(state as GlobalState, channelId);
const lastPostsApiCallForChannel = getLastPostsApiTimeForChannel(state, channelId);
const actions = [];
if (lastPostsApiCallForChannel && lastPostsApiCallForChannel < socketStatus.lastDisconnectAt) {
@@ -495,7 +494,7 @@ export function scrollPostListToBottom() {
};
}
export function markAsReadOnFocus(): ThunkActionFunc<void, GlobalState> {
export function markAsReadOnFocus(): ThunkActionFunc<void> {
return (dispatch, getState) => {
const state = getState();
const currentChannelId = getCurrentChannelId(state);
@@ -523,7 +522,7 @@ export function updateToastStatus(status: boolean) {
};
}
export function deleteChannel(channelId: string): ActionFuncAsync<boolean, GlobalState> {
export function deleteChannel(channelId: string): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const res = await dispatch(deleteChannelRedux(channelId));
if (res.error) {

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

@@ -6,14 +6,13 @@ import {General} from 'mattermost-redux/constants';
import {CategoryTypes} from 'mattermost-redux/constants/channel_categories';
import {getCategory, makeGetChannelIdsForCategory} from 'mattermost-redux/selectors/entities/channel_categories';
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
import type {ActionFunc, ActionFuncAsync} from 'mattermost-redux/types/actions';
import {insertMultipleWithoutDuplicates} from 'mattermost-redux/utils/array_utils';
import {getCategoriesForCurrentTeam, getChannelsInCategoryOrder, getDisplayedChannels} from 'selectors/views/channel_sidebar';
import {ActionTypes} from 'utils/constants';
import type {DraggingState, GlobalState} from 'types/store';
import type {ActionFunc, ActionFuncAsync, DraggingState, GlobalState} from 'types/store';
export function setUnreadFilterEnabled(enabled: boolean) {
return {
@@ -33,10 +32,10 @@ export function stopDragging() {
return {type: ActionTypes.SIDEBAR_DRAGGING_STOP};
}
export function createCategory(teamId: string, displayName: string, channelIds?: string[]): ActionFuncAsync<unknown, GlobalState> {
export function createCategory(teamId: string, displayName: string, channelIds?: string[]): ActionFuncAsync<unknown> {
return async (dispatch, getState) => {
if (channelIds) {
const state = getState() as GlobalState;
const state = getState();
const multiSelectedChannelIds = state.views.channelSidebar.multiSelectedChannelIds;
channelIds.forEach((channelId) => {
if (multiSelectedChannelIds.indexOf(channelId) >= 0) {
@@ -61,7 +60,7 @@ 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
// may have changed due to archived channels not being shown in the sidebar.
export function moveChannelsInSidebar(categoryId: string, targetIndex: number, draggableChannelId: string, setManualSorting = true): ActionFuncAsync<unknown, GlobalState> {
export function moveChannelsInSidebar(categoryId: string, targetIndex: number, draggableChannelId: string, setManualSorting = true): ActionFuncAsync<unknown> {
return (dispatch, getState) => {
const state = getState();
const multiSelectedChannelIds = state.views.channelSidebar.multiSelectedChannelIds;
@@ -137,7 +136,7 @@ export function adjustTargetIndexForMove(state: GlobalState, categoryId: string,
return Math.max(newIndex - removedChannelsAboveInsert.length, 0);
}
export function clearChannelSelection(): ActionFunc<unknown, GlobalState> {
export function clearChannelSelection(): ActionFunc<unknown> {
return (dispatch, getState) => {
const state = getState();
@@ -154,7 +153,7 @@ export function clearChannelSelection(): ActionFunc<unknown, GlobalState> {
};
}
export function multiSelectChannelAdd(channelId: string): ActionFunc<unknown, GlobalState> {
export function multiSelectChannelAdd(channelId: string): ActionFunc<unknown> {
return (dispatch, getState) => {
const state = getState();
const multiSelectedChannelIds = state.views.channelSidebar.multiSelectedChannelIds;
@@ -177,7 +176,7 @@ export function multiSelectChannelAdd(channelId: string): ActionFunc<unknown, Gl
// 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
export function multiSelectChannelTo(channelId: string): ActionFunc<unknown, GlobalState> {
export function multiSelectChannelTo(channelId: string): ActionFunc<unknown> {
return (dispatch, getState) => {
const state = getState();
const multiSelectedChannelIds = state.views.channelSidebar.multiSelectedChannelIds;

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

@@ -21,7 +21,6 @@ import {isCustomGroupsEnabled} from 'mattermost-redux/selectors/entities/prefere
import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {ActionFunc, ActionFuncAsync} from 'mattermost-redux/types/actions';
import type {ExecuteCommandReturnType} from 'actions/command';
import {executeCommand} from 'actions/command';
@@ -33,7 +32,7 @@ import EmojiMap from 'utils/emoji_map';
import {containsAtChannel, groupsMentionedInText} from 'utils/post_utils';
import * as Utils from 'utils/utils';
import type {GlobalState} from 'types/store';
import type {ActionFunc, ActionFuncAsync} from 'types/store';
import type {PostDraft} from 'types/store/draft';
export function submitPost(
@@ -43,7 +42,7 @@ export function submitPost(
afterSubmit?: (response: SubmitPostReturnType) => void,
schedulingInfo?: SchedulingInfo,
options?: OnSubmitOptions,
): ActionFuncAsync<CreatePostReturnType, GlobalState> {
): ActionFuncAsync<CreatePostReturnType> {
return async (dispatch, getState) => {
const state = getState();
@@ -118,7 +117,7 @@ export function submitPost(
type SubmitCommandRerturnType = ExecuteCommandReturnType & CreatePostReturnType;
export function submitCommand(channelId: string, rootId: string, draft: PostDraft): ActionFuncAsync<SubmitCommandRerturnType, GlobalState> {
export function submitCommand(channelId: string, rootId: string, draft: PostDraft): ActionFuncAsync<SubmitCommandRerturnType> {
return async (dispatch, getState) => {
const state = getState();
@@ -171,7 +170,7 @@ export function onSubmit(
draft: PostDraft,
options: OnSubmitOptions,
schedulingInfo?: SchedulingInfo,
): ActionFuncAsync<SubmitPostReturnType, GlobalState> {
): ActionFuncAsync<SubmitPostReturnType> {
return async (dispatch, getState) => {
const {message, channelId, rootId} = draft;
const state = getState();

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

@@ -14,7 +14,6 @@ import {Client4} from 'mattermost-redux/client';
import Preferences from 'mattermost-redux/constants/preferences';
import {syncedDraftsAreAllowedAndEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {ActionFunc, ActionFuncAsync} from 'mattermost-redux/types/actions';
import {setGlobalItem} from 'actions/storage';
import {makeGetDrafts} from 'selectors/drafts';
@@ -23,7 +22,7 @@ import {getGlobalItem} from 'selectors/storage';
import {ActionTypes, StoragePrefixes} from 'utils/constants';
import type {GlobalState} from 'types/store';
import type {ActionFunc, ActionFuncAsync, GlobalState} from 'types/store';
import type {PostDraft} from 'types/store/draft';
type Draft = {
@@ -36,7 +35,7 @@ type Draft = {
* Gets drafts stored on the server and reconciles them with any locally stored drafts.
* @param teamId Only drafts for the given teamId will be fetched.
*/
export function getDrafts(teamId: string): ActionFuncAsync<boolean, GlobalState> {
export function getDrafts(teamId: string): ActionFuncAsync<boolean> {
const getLocalDrafts = makeGetDrafts(false);
return async (dispatch, getState) => {
@@ -70,7 +69,7 @@ export function getDrafts(teamId: string): ActionFuncAsync<boolean, GlobalState>
};
}
export function removeDraft(key: string, channelId: string, rootId = ''): ActionFuncAsync<boolean, GlobalState> {
export function removeDraft(key: string, channelId: string, rootId = ''): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const state = getState();
@@ -91,7 +90,7 @@ export function removeDraft(key: string, channelId: string, rootId = ''): Action
};
}
export function updateDraft(key: string, value: PostDraft|null, rootId = '', save = false): ActionFuncAsync<boolean, GlobalState> {
export function updateDraft(key: string, value: PostDraft|null, rootId = '', save = false): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const state = getState();
let updatedValue: PostDraft|null = null;

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

@@ -3,14 +3,13 @@
import {selectChannel} from 'mattermost-redux/actions/channels';
import {getCurrentRelativeTeamUrl} from 'mattermost-redux/selectors/entities/teams';
import type {ActionFunc, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {SidebarSize} from 'components/resizable_sidebar/constants';
import {getHistory} from 'utils/browser_history';
import Constants, {ActionTypes} from 'utils/constants';
import type {GlobalState} from 'types/store';
import type {ActionFunc, ThunkActionFunc} from 'types/store';
import {LhsItemType} from 'types/store/lhs';
export const setLhsSize = (sidebarSize?: SidebarSize) => {
@@ -80,7 +79,7 @@ export const selectLhsItem = (type: LhsItemType, id?: string): ThunkActionFunc<u
};
};
export function switchToLhsStaticPage(id: string): ActionFunc<boolean, GlobalState> {
export function switchToLhsStaticPage(id: string): ActionFunc<boolean> {
return (dispatch, getState) => {
const state = getState();
const teamUrl = getCurrentRelativeTeamUrl(state);

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

@@ -9,7 +9,8 @@ import {UserTypes} from 'mattermost-redux/action_types';
import {logError} from 'mattermost-redux/actions/errors';
import {loadRolesIfNeeded} from 'mattermost-redux/actions/roles';
import {Client4} from 'mattermost-redux/client';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import type {ActionFuncAsync} from 'types/store';
export function login(loginId: string, password: string, mfaToken = ''): ActionFuncAsync {
return async (dispatch) => {

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

@@ -3,7 +3,6 @@
import {getCurrentUser, getCurrentUserId} from 'mattermost-redux/selectors/entities/common';
import {getCurrentTeamId, getTeam} from 'mattermost-redux/selectors/entities/teams';
import type {ActionFunc, ActionFuncAsync} from 'mattermost-redux/types/actions';
import {getTeamRedirectChannelIfIsAccesible} from 'actions/global_actions';
import LocalStorageStore from 'stores/local_storage_store';
@@ -13,6 +12,8 @@ import InvitationModal from 'components/invitation_modal';
import {getHistory} from 'utils/browser_history';
import {ActionTypes, Constants, ModalIdentifiers} from 'utils/constants';
import type {ActionFunc, ActionFuncAsync} from 'types/store';
import {openModal} from './modals';
export function switchToChannels(): ActionFuncAsync<boolean> {

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

@@ -3,7 +3,8 @@
import {getChannelMember} from 'mattermost-redux/actions/channels';
import {getTeamMember} from 'mattermost-redux/actions/teams';
import type {ThunkActionFunc} from 'mattermost-redux/types/actions';
import type {ThunkActionFunc} from 'types/store';
export function getMembershipForEntities(teamId: string, userId: string, channelId?: string): ThunkActionFunc<unknown> {
return (dispatch) => {

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

@@ -23,7 +23,6 @@ import {getLatestInteractablePostId, getPost} from 'mattermost-redux/selectors/e
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentTimezone} from 'mattermost-redux/selectors/entities/timezone';
import {getCurrentUser, getCurrentUserMentionKeys} from 'mattermost-redux/selectors/entities/users';
import type {ActionFunc, ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {trackEvent} from 'actions/telemetry_actions.jsx';
import {
@@ -42,10 +41,10 @@ import {ActionTypes, RHSStates, Constants} from 'utils/constants';
import {Mark, Measure, measureAndReport} from 'utils/performance_telemetry';
import {getBrowserUtcOffset, getUtcOffsetForTimeZone} from 'utils/timezone';
import type {GlobalState} from 'types/store';
import type {ActionFunc, ActionFuncAsync, ThunkActionFunc} from 'types/store';
import type {RhsState} from 'types/store/rhs';
function selectPostWithPreviousState(post: Post, previousRhsState?: RhsState): ActionFunc<boolean, GlobalState> {
function selectPostWithPreviousState(post: Post, previousRhsState?: RhsState): ActionFunc<boolean> {
return (dispatch, getState) => {
const state = getState();
@@ -55,7 +54,7 @@ function selectPostWithPreviousState(post: Post, previousRhsState?: RhsState): A
};
}
function selectPostCardFromRightHandSideSearchWithPreviousState(post: Post, previousRhsState?: RhsState): ActionFuncAsync<boolean, GlobalState> {
function selectPostCardFromRightHandSideSearchWithPreviousState(post: Post, previousRhsState?: RhsState): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const state = getState();
@@ -105,7 +104,7 @@ export function openShowEditHistory(post: Post) {
};
}
export function goBack(): ActionFuncAsync<boolean, GlobalState> {
export function goBack(): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const prevState = getPreviousRhsState(getState());
const defaultTab = 'channel-info';
@@ -123,14 +122,14 @@ export function selectPostFromRightHandSideSearch(post: Post) {
return selectPostWithPreviousState(post);
}
export function selectPostFromRightHandSideSearchByPostId(postId: string): ActionFuncAsync<boolean, GlobalState> {
export function selectPostFromRightHandSideSearchByPostId(postId: string): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const post = getPost(getState(), postId);
return dispatch(selectPostFromRightHandSideSearch(post));
};
}
export function replyToLatestPostInChannel(channelId: string): ActionFuncAsync<boolean, GlobalState> {
export function replyToLatestPostInChannel(channelId: string): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const state = getState();
const postId = getLatestInteractablePostId(state, channelId);
@@ -209,7 +208,7 @@ function updateSearchResultsType(searchType: string) {
};
}
export function performSearch(terms: string, teamId: string, isMentionSearch?: boolean): ThunkActionFunc<unknown, GlobalState> {
export function performSearch(terms: string, teamId: string, isMentionSearch?: boolean): ThunkActionFunc<unknown> {
return (dispatch, getState) => {
let searchTerms = terms;
const config = getConfig(getState());
@@ -256,7 +255,7 @@ export function filterFilesSearchByExt(extensions: string[]) {
};
}
export function showSearchResults(isMentionSearch = false): ThunkActionFunc<unknown, GlobalState> {
export function showSearchResults(isMentionSearch = false): ThunkActionFunc<unknown> {
return (dispatch, getState) => {
const state = getState();
@@ -285,7 +284,7 @@ export function showRHSPlugin(pluggableId: string) {
};
}
export function showChannelMembers(channelId: string, inEditingMode = false): ActionFuncAsync<boolean, GlobalState> {
export function showChannelMembers(channelId: string, inEditingMode = false): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const state = getState();
@@ -308,9 +307,9 @@ export function showChannelMembers(channelId: string, inEditingMode = false): Ac
};
}
export function hideRHSPlugin(pluggableId: string): ActionFunc<boolean, GlobalState> {
export function hideRHSPlugin(pluggableId: string): ActionFunc<boolean> {
return (dispatch, getState) => {
const state = getState() as GlobalState;
const state = getState();
if (getPluggableId(state) === pluggableId) {
dispatch(closeRightHandSide());
@@ -320,7 +319,7 @@ export function hideRHSPlugin(pluggableId: string): ActionFunc<boolean, GlobalSt
};
}
export function toggleRHSPlugin(pluggableId: string): ActionFunc<boolean, GlobalState> {
export function toggleRHSPlugin(pluggableId: string): ActionFunc<boolean> {
return (dispatch, getState) => {
const state = getState();
@@ -369,7 +368,7 @@ export function showFlaggedPosts(): ActionFuncAsync {
};
}
export function showPinnedPosts(channelId?: string): ActionFuncAsync<boolean, GlobalState> {
export function showPinnedPosts(channelId?: string): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const state = getState();
const currentChannelId = getCurrentChannelId(state);
@@ -412,7 +411,7 @@ export function showPinnedPosts(channelId?: string): ActionFuncAsync<boolean, Gl
};
}
export function showChannelFiles(channelId: string): ActionFuncAsync<boolean, GlobalState> {
export function showChannelFiles(channelId: string): ActionFuncAsync<boolean> {
return async (dispatch, getState) => {
const state = getState();
const teamId = getSearchTeam(state);
@@ -470,7 +469,7 @@ export function showChannelFiles(channelId: string): ActionFuncAsync<boolean, Gl
};
}
export function showMentions(): ActionFunc<boolean, GlobalState> {
export function showMentions(): ActionFunc<boolean> {
return (dispatch, getState) => {
const termKeys = getCurrentUserMentionKeys(getState()).filter(({key}) => {
return key !== '@channel' && key !== '@all' && key !== '@here';
@@ -622,7 +621,7 @@ export function openRHSSearch(): ActionFunc {
};
}
export function openAtPrevious(previous: any): ThunkActionFunc<unknown, GlobalState> {
export function openAtPrevious(previous: any): ThunkActionFunc<unknown> {
return (dispatch, getState) => {
if (!previous) {
return dispatch(openRHSSearch());

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

@@ -2,21 +2,20 @@
// See LICENSE.txt for license information.
import {Client4} from 'mattermost-redux/client';
import type {ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {getCurrentLocale, getTranslations} from 'selectors/i18n';
import en from 'i18n/en.json';
import {ActionTypes} from 'utils/constants';
import type {GlobalState} from 'types/store';
import type {ActionFuncAsync, ThunkActionFunc} from 'types/store';
import type {Translations} from 'types/store/i18n';
const pluginTranslationSources: Record<string, TranslationPluginFunction> = {};
export type TranslationPluginFunction = (locale: string) => Translations
export function registerPluginTranslationsSource(pluginId: string, sourceFunction: TranslationPluginFunction): ThunkActionFunc<void, GlobalState> {
export function registerPluginTranslationsSource(pluginId: string, sourceFunction: TranslationPluginFunction): ThunkActionFunc<void> {
pluginTranslationSources[pluginId] = sourceFunction;
return (dispatch, getState) => {
const state = getState();

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

@@ -7,13 +7,12 @@ import {updateThreadRead} from 'mattermost-redux/actions/threads';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getThread} from 'mattermost-redux/selectors/entities/threads';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {ThunkActionFunc} from 'mattermost-redux/types/actions';
import {isThreadManuallyUnread, isThreadOpen} from 'selectors/views/threads';
import {ActionTypes, Threads} from 'utils/constants';
import type {GlobalState} from 'types/store';
import type {ThunkActionFunc} from 'types/store';
export function updateThreadLastOpened(threadId: string, lastViewedAt: number) {
return {
@@ -52,7 +51,7 @@ export function updateThreadToastStatus(status: boolean) {
};
}
export function markThreadAsRead(threadId: string): ThunkActionFunc<void, GlobalState> {
export function markThreadAsRead(threadId: string): ThunkActionFunc<void> {
return (dispatch, getState) => {
const state = getState();
const currentUserId = getCurrentUserId(state);

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

@@ -18,9 +18,8 @@ import {getChannel as fetchChannel} from 'mattermost-redux/actions/channels';
import {Client4} from 'mattermost-redux/client';
import {getChannel} from 'mattermost-redux/selectors/entities/channels';
import {getActiveTeamsList, getTeam} from 'mattermost-redux/selectors/entities/teams';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import type {GlobalState} from 'types/store';
import type {ActionFuncAsync} from 'types/store';
export const useRemoteClusters = () => {
const [remoteClusters, setRemoteClusters] = useState<RemoteCluster[]>();
@@ -154,7 +153,7 @@ export const useSharedChannelRemoteRows = (remoteId: string, opts: {filter: 'hom
}
setLoadingState(true);
dispatch<ActionFuncAsync<IDMappedObjects<SharedChannelRemoteRow>, GlobalState>>(async (dispatch, getState) => {
dispatch<ActionFuncAsync<IDMappedObjects<SharedChannelRemoteRow>>>(async (dispatch, getState) => {
const collected: IDMappedObjects<SharedChannelRemoteRow> = {};
const missing: SharedChannelRemote[] = [];

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

@@ -4,10 +4,11 @@
import type {UserProfile} from '@mattermost/types/users';
import {getMissingProfilesByUsernames} from 'mattermost-redux/actions/users';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import {getPotentialMentionsForName} from 'utils/post_utils';
import type {ActionFuncAsync} from 'types/store';
export function getMissingMentionedUsers(text: string): ActionFuncAsync<Array<UserProfile['username']>> {
return getMissingProfilesByUsernames(getPotentialMentionsForName(text));
}

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

@@ -12,7 +12,6 @@ import {Client4} from 'mattermost-redux/client';
import {getChannelByName, getOtherChannels, getChannel, getChannelsNameMapInTeam, getRedirectChannelNameForTeam} from 'mattermost-redux/selectors/entities/channels';
import {getTeamByName} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUser, getCurrentUserId, getUserByUsername as selectUserByUsername, getUser as selectUser, getUserByEmail as selectUserByEmail} from 'mattermost-redux/selectors/entities/users';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import * as UserUtils from 'mattermost-redux/utils/user_utils';
import {openDirectChannelToUserId} from 'actions/channel_actions';
@@ -22,6 +21,8 @@ import {joinPrivateChannelPrompt} from 'utils/channel_utils';
import {Constants} from 'utils/constants';
import * as Utils from 'utils/utils';
import type {ActionFuncAsync} from 'types/store';
import type {Match, MatchAndHistory} from './channel_identifier_router';
const LENGTH_OF_ID = 26;

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

@@ -31,7 +31,7 @@ type Props = {
const InstalledOutgoingOAuthConnections = (props: Props) => {
const [loading, setLoading] = useState(true);
const canManageOutgoingOAuthConnections = useSelector((state) => haveITeamPermission(state as GlobalState, props.team.id, Permissions.MANAGE_OUTGOING_OAUTH_CONNECTIONS));
const canManageOutgoingOAuthConnections = useSelector((state: GlobalState) => haveITeamPermission(state, props.team.id, Permissions.MANAGE_OUTGOING_OAUTH_CONNECTIONS));
const enableOutgoingOAuthConnections = (useSelector(getConfig).EnableOutgoingOAuthConnections === 'true');
const connections = useSelector(getOutgoingOAuthConnections);

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

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

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

@@ -9,7 +9,8 @@ import {getIsUserStatusesConfigEnabled} from 'mattermost-redux/selectors/entitie
import {getConfig, isPerformanceDebuggingEnabled} from 'mattermost-redux/selectors/entities/general';
import {getBool} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId, getStatusForUserId} from 'mattermost-redux/selectors/entities/users';
import type {ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import type {ActionFuncAsync, ThunkActionFunc} from 'types/store';
function getTimeBetweenTypingEvents(state: GlobalState) {
const config = getConfig(state);

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

@@ -12,7 +12,6 @@ import {getCurrentChannel, getChannel as getChannelFromRedux} from 'mattermost-r
import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeam, getTeam} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
import type {ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {getUserIdFromChannelName} from 'mattermost-redux/utils/channel_utils';
import {isSystemAdmin} from 'mattermost-redux/utils/user_utils';
@@ -25,7 +24,7 @@ import {joinPrivateChannelPrompt} from 'utils/channel_utils';
import {ActionTypes, Constants, ErrorPageTypes} from 'utils/constants';
import {isComment, getPostURL} from 'utils/post_utils';
import type {GlobalState} from 'types/store';
import type {ActionFuncAsync, ThunkActionFunc} from 'types/store';
let privateChannelJoinPromptVisible = false;
@@ -35,7 +34,7 @@ type Option = {
function focusRootPost(post: Post, channel: Channel): ActionFuncAsync {
return async (dispatch, getState) => {
const postURL = getPostURL(getState() as GlobalState, post);
const postURL = getPostURL(getState(), post);
dispatch(selectChannel(channel.id));
dispatch({
@@ -58,7 +57,7 @@ function focusReplyPost(post: Post, channel: Channel, teamId: string, returnTo:
return {data: false};
}
const state = getState() as GlobalState;
const state = getState();
const team = getTeam(state, channel.team_id || teamId);
const currentChannel = getCurrentChannel(state);

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

@@ -3,7 +3,6 @@
import {removePost} from 'mattermost-redux/actions/posts';
import type {ExtendedPost} from 'mattermost-redux/actions/posts';
import type {ActionFunc} from 'mattermost-redux/types/actions';
import {removeDraft} from 'actions/views/drafts';
import {closeRightHandSide} from 'actions/views/rhs';
@@ -12,13 +11,13 @@ import {isThreadOpen} from 'selectors/views/threads';
import {StoragePrefixes} from 'utils/constants';
import type {GlobalState} from 'types/store';
import type {ActionFunc} from 'types/store';
/**
* This action is called when the deleted post which is shown as 'deleted' in the RHS is then removed from the channel manually.
* @param post Deleted post
*/
export function removePostCloseRHSDeleteDraft(post: ExtendedPost): ActionFunc<boolean, GlobalState> {
export function removePostCloseRHSDeleteDraft(post: ExtendedPost): ActionFunc<boolean> {
return (dispatch, getState) => {
if (isThreadOpen(getState(), post.id)) {
dispatch(closeRightHandSide());

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

@@ -18,13 +18,13 @@ import {General} from 'mattermost-redux/constants';
import {isCollapsedThreadsEnabled, getIsOnboardingFlowEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getActiveTeamsList} from 'mattermost-redux/selectors/entities/teams';
import {checkIsFirstAdmin, getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import type {ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import {redirectUserToDefaultTeam, emitUserLoggedOutEvent} from 'actions/global_actions';
import {ActionTypes, StoragePrefixes} from 'utils/constants';
import {doesCookieContainsMMUserId} from 'utils/utils';
import type {ActionFuncAsync, ThunkActionFunc} from 'types/store';
import type {Translations} from 'types/store/i18n';
export type TranslationPluginFunction = (locale: string) => Translations

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

@@ -14,16 +14,15 @@ import {getIsUserStatusesConfigEnabled} from 'mattermost-redux/selectors/entitie
import {getLicense} from 'mattermost-redux/selectors/entities/general';
import {isCustomGroupsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import {addVisibleUsersInCurrentChannelAndSelfToStatusPoll} from 'actions/status_actions';
import {addUserToTeam} from 'actions/team_actions';
import LocalStorageStore from 'stores/local_storage_store';
import {isSuccess} from 'types/actions';
import type {GlobalState} from 'types/store';
import type {ActionFuncAsync} from 'types/store';
export function initializeTeam(team: Team): ActionFuncAsync<Team, GlobalState> {
export function initializeTeam(team: Team): ActionFuncAsync<Team> {
return async (dispatch, getState) => {
dispatch(selectTeam(team.id));
@@ -81,7 +80,7 @@ export function initializeTeam(team: Team): ActionFuncAsync<Team, GlobalState> {
};
}
export function joinTeam(teamname: string, joinedOnFirstLoad: boolean): ActionFuncAsync<Team, GlobalState> {
export function joinTeam(teamname: string, joinedOnFirstLoad: boolean): ActionFuncAsync<Team> {
return async (dispatch, getState) => {
const state = getState();
const currentUser = getCurrentUser(state);

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

@@ -2,6 +2,7 @@
// See LICENSE.txt for license information.
import type {ServerError} from '@mattermost/types/errors';
import type {GlobalState} from '@mattermost/types/store';
import {UserTypes} from 'mattermost-redux/action_types';
import {Client4} from 'mattermost-redux/client';
@@ -75,7 +76,7 @@ export function bindClientFunc<Func extends(...args: any[]) => Promise<any>>({
onSuccess?: ActionType | ActionType[];
onFailure?: ActionType;
params?: Parameters<Func>;
}): ActionFuncAsync<Awaited<ReturnType<Func>>> {
}): ActionFuncAsync<Awaited<ReturnType<Func>>, GlobalState> {
return async (dispatch, getState) => {
if (onRequest) {
dispatch(requestData(onRequest));

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

@@ -180,7 +180,7 @@ export function createPost(
post: Post,
files: any[] = [],
afterSubmit?: (response: any) => void,
): ActionFuncAsync<CreatePostReturnType, GlobalState> {
): ActionFuncAsync<CreatePostReturnType> {
return async (dispatch, getState) => {
const state = getState();
const currentUserId = state.entities.users.currentUserId;
@@ -512,7 +512,7 @@ export type SubmitReactionReturnType = {
removedReaction?: boolean;
}
export function addReaction(postId: string, emojiName: string): ActionFuncAsync<SubmitReactionReturnType, GlobalState> {
export function addReaction(postId: string, emojiName: string): ActionFuncAsync<SubmitReactionReturnType> {
return async (dispatch, getState) => {
const currentUserId = getState().entities.users.currentUserId;
@@ -534,7 +534,7 @@ export function addReaction(postId: string, emojiName: string): ActionFuncAsync<
};
}
export function removeReaction(postId: string, emojiName: string): ActionFuncAsync<SubmitReactionReturnType, GlobalState> {
export function removeReaction(postId: string, emojiName: string): ActionFuncAsync<SubmitReactionReturnType> {
return async (dispatch, getState) => {
const currentUserId = getState().entities.users.currentUserId;

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

@@ -3,10 +3,10 @@
import type {Store} from 'redux';
import type {ActionFuncAsync, ThunkActionFunc} from 'mattermost-redux/types/actions';
import store from 'stores/redux_store';
import type {ActionFuncAsync, ThunkActionFunc} from 'types/store';
import PluginRegistry from './registry';
export abstract class ProductPlugin {

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

@@ -3,6 +3,9 @@
import type {GlobalState as BaseGlobalState} from '@mattermost/types/store';
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import type * as MMReduxTypes from 'mattermost-redux/types/actions';
import type {PluginsState} from './plugins';
import type {ViewsState} from './views';
@@ -20,3 +23,37 @@ export type GlobalState = BaseGlobalState & {
};
views: ViewsState;
};
/**
* A version of {@link MMReduxTypes.DispatchFunc} which supports dispatching web app actions.
*/
export type DispatchFunc = MMReduxTypes.DispatchFunc;
/**
* A version of {@link MMReduxTypes.GetStateFunc} which supports web app state.
*/
export type GetStateFunc<State extends GlobalState = GlobalState> = MMReduxTypes.GetStateFunc<State>;
/**
* A version of {@link MMReduxTypes.ActionFunc} which supports web app state and allows dispatching its actions.
*/
export type ActionFunc<
Data = unknown,
State extends GlobalState = GlobalState,
> = MMReduxTypes.ActionFunc<Data, State>;
/**
* A version of {@link MMReduxTypes.ActionFuncAsync} which supports web app state and allows dispatching its actions.
*/
export type ActionFuncAsync<
Data = unknown,
State extends GlobalState = GlobalState,
> = MMReduxTypes.ActionFuncAsync<Data, State>;
/**
* A version of {@link MMReduxTypes.ThunkActionFunc} which supports web app state and allows dispatching its actions.
*/
export type ThunkActionFunc<
ReturnType,
State extends GlobalState = GlobalState
> = MMReduxTypes.ThunkActionFunc<ReturnType, State>;

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

@@ -10,7 +10,6 @@ import Permissions from 'mattermost-redux/constants/permissions';
import {getRedirectChannelNameForTeam} from 'mattermost-redux/selectors/entities/channels';
import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import type {ActionFuncAsync} from 'mattermost-redux/types/actions';
import {openModal} from 'actions/views/modals';
import LocalStorageStore from 'stores/local_storage_store';
@@ -20,7 +19,7 @@ import JoinPrivateChannelModal from 'components/join_private_channel_modal';
import Constants, {ModalIdentifiers} from 'utils/constants';
import * as Utils from 'utils/utils';
import type {GlobalState} from 'types/store';
import type {ActionFuncAsync, GlobalState} from 'types/store';
import {getHistory} from './browser_history';
import {cleanUpUrlable} from './url';

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

@@ -1,12 +1,12 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import type {ThunkActionFunc} from 'mattermost-redux/types/actions';
import icon50 from 'images/icon50x50.png';
import iconWS from 'images/icon_WS.png';
import * as UserAgent from 'utils/user_agent';
import type {ThunkActionFunc} from 'types/store';
export type NotificationResult = {
status: 'error' | 'not_sent' | 'success' | 'unsupported';
reason?: string;