MM-50577 Replaced makeCreateAriaLabelForPost with better memoized usePostAriaLabel (#22833)

Этот коммит содержится в:
Harrison Healey
2023-04-13 16:24:20 -04:00
коммит произвёл GitHub
родитель 024a5472ff
Коммит 21b72c7607
5 изменённых файлов: 62 добавлений и 50 удалений

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

@@ -1,36 +1,24 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useRef} from 'react';
import {useSelector} from 'react-redux';
import {useIntl} from 'react-intl';
import React from 'react';
import {Post} from '@mattermost/types/posts';
import {GlobalState} from 'types/store';
import {makeCreateAriaLabelForPost} from 'utils/post_utils';
import {usePostAriaLabel} from 'utils/post_utils';
export type Props = React.HTMLProps<HTMLDivElement> & {
labelPrefix?: string;
post: Post;
}
const PostAriaLabelDiv = React.forwardRef((props: Props, ref: React.Ref<HTMLDivElement>) => {
const {
children,
labelPrefix,
post,
...otherProps
} = props;
const intl = useIntl();
const createAriaLabelForPost = useRef(makeCreateAriaLabelForPost());
let ariaLabel = useSelector<GlobalState, string>((state) => createAriaLabelForPost.current(state, post)(intl));
if (labelPrefix) {
ariaLabel = labelPrefix + ariaLabel;
}
const ariaLabel = usePostAriaLabel(post);
return (
<div

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

@@ -77,4 +77,18 @@ describe('LatestPostReader', () => {
expect(span.prop('children')).toContain(author.username);
expect(span.prop('children')).toContain('enero');
});
test('should be able to handle an empty post array', () => {
const {mountOptions} = mockStore(baseState);
const props = {
...baseProps,
postIds: [],
};
const wrapper = mount(<LatestPostReader {...props}/>, mountOptions);
const span = wrapper.childAt(0);
expect(span.prop('children')).toEqual('');
});
});

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

@@ -1,8 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useMemo, useRef} from 'react';
import {useIntl} from 'react-intl';
import React, {useMemo} from 'react';
import {useSelector} from 'react-redux';
import {getPost} from 'mattermost-redux/selectors/entities/posts';
@@ -11,27 +10,18 @@ import {Post} from '@mattermost/types/posts';
import {GlobalState} from 'types/store';
import {getLatestPostId, makeCreateAriaLabelForPost} from 'utils/post_utils';
import {getLatestPostId, usePostAriaLabel} from 'utils/post_utils';
interface Props {
postIds?: string[];
}
const LatestPostReader = (props: Props): JSX.Element => {
const intl = useIntl();
const {postIds} = props;
const latestPostId = useMemo(() => getLatestPostId(postIds || []), [postIds]);
const latestPost = useSelector<GlobalState, Post>((state) => getPost(state, latestPostId));
const createAriaLabelForPost = useRef(makeCreateAriaLabelForPost());
const ariaLabel = useSelector<GlobalState, string>((state) => {
if (!latestPost) {
return '';
}
return createAriaLabelForPost.current(state, latestPost)(intl);
});
const ariaLabel = usePostAriaLabel(latestPost);
return (
<span

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

@@ -71,13 +71,13 @@ export function getReactionsForPosts(state: GlobalState): RelationOneToOne<Post,
export function makeGetReactionsForPost(): (state: GlobalState, postId: Post['id']) => {
[x: string]: Reaction;
} | undefined | null {
} | undefined {
return createSelector('makeGetReactionsForPost', getReactionsForPosts, (state: GlobalState, postId: string) => postId, (reactions, postId) => {
if (reactions[postId]) {
return reactions[postId];
}
return null;
return undefined;
});
}

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

@@ -1,7 +1,11 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {IntlShape} from 'react-intl';
import {IntlShape, useIntl} from 'react-intl';
import {useMemo} from 'react';
import {useSelector} from 'react-redux';
import {createSelector} from 'reselect';
@@ -17,6 +21,8 @@ import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles'
import {getCurrentTeamId, getTeam} from 'mattermost-redux/selectors/entities/teams';
import {makeGetDisplayName, getCurrentUserId, getUser, UserMentionKey, getUsersByUsername} from 'mattermost-redux/selectors/entities/users';
import {memoizeResult} from 'mattermost-redux/utils/helpers';
import {Channel} from '@mattermost/types/channels';
import {ClientConfig, ClientLicense} from '@mattermost/types/config';
import {ServerError} from '@mattermost/types/errors';
@@ -42,8 +48,8 @@ import {allAtMentions} from 'utils/text_formatting';
import {isMobile} from 'utils/user_agent';
import * as Utils from 'utils/utils';
import * as Emoticons from './emoticons';
import EmojiMap from './emoji_map';
import * as Emoticons from './emoticons';
const CHANNEL_SWITCH_IGNORE_ENTER_THRESHOLD_MS = 500;
@@ -443,27 +449,41 @@ export function makeGetMentionsFromMessage(): (state: GlobalState, post: Post) =
);
}
export function makeCreateAriaLabelForPost(): (state: GlobalState, post: Post) => (intl: IntlShape) => string {
const getReactionsForPost = makeGetUniqueReactionsToPost();
const getDisplayName = makeGetDisplayName();
const getMentionsFromMessage = makeGetMentionsFromMessage();
export function usePostAriaLabel(post: Post | undefined) {
const intl = useIntl();
return createSelector(
'makeCreateAriaLabelForPost',
(state: GlobalState, post: Post) => post,
(state: GlobalState, post: Post) => getDisplayName(state, post.user_id),
(state: GlobalState, post: Post) => getReactionsForPost(state, post.id),
(state: GlobalState, post: Post) => get(state, Preferences.CATEGORY_FLAGGED_POST, post.id, null) != null,
getEmojiMap,
(state: GlobalState, post: Post) => getMentionsFromMessage(state, post),
(state: GlobalState) => getTeammateNameDisplaySetting(state),
(post, author, reactions, isFlagged, emojiMap, mentions, teammateNameDisplaySetting) => {
return (intl: IntlShape) => createAriaLabelForPost(post, author, isFlagged, reactions ?? {}, intl, emojiMap, mentions, teammateNameDisplaySetting);
},
);
const getDisplayName = useMemo(makeGetDisplayName, []);
const getReactionsForPost = useMemo(makeGetReactionsForPost, []);
const getMentionsFromMessage = useMemo(makeGetMentionsFromMessage, []);
const createAriaLabelMemoized = memoizeResult(createAriaLabelForPost);
return useSelector((state: GlobalState) => {
if (!post) {
return '';
}
const authorDisplayName = getDisplayName(state, post.user_id);
const reactions = getReactionsForPost(state, post?.id);
const isFlagged = get(state, Preferences.CATEGORY_FLAGGED_POST, post.id, null) != null;
const emojiMap = getEmojiMap(state);
const mentions = getMentionsFromMessage(state, post);
const teammateNameDisplaySetting = getTeammateNameDisplaySetting(state);
return createAriaLabelMemoized(
post,
authorDisplayName,
isFlagged,
reactions,
intl,
emojiMap,
mentions,
teammateNameDisplaySetting,
);
});
}
export function createAriaLabelForPost(post: Post, author: string, isFlagged: boolean, reactions: Record<string, Reaction>, intl: IntlShape, emojiMap: EmojiMap, mentions: Record<string, UserProfile>, teammateNameDisplaySetting: string): string {
export function createAriaLabelForPost(post: Post, author: string, isFlagged: boolean, reactions: Record<string, Reaction> | undefined, intl: IntlShape, emojiMap: EmojiMap, mentions: Record<string, UserProfile>, teammateNameDisplaySetting: string): string {
const {formatMessage, formatTime, formatDate} = intl;
let message = post.state === Posts.POST_DELETED ? formatMessage({