Migrate components/post_view/post_flag_icon/post_flag_icon.tsx from class to function component (#24187)

* Class to functional example 3

* Address feedback

* Address feedback

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Daniel Espino García
2023-08-11 16:57:25 +02:00
коммит произвёл GitHub
родитель 544ceeba3e
Коммит c1c07ba1bb

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

@@ -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 React from 'react'; import React, {useCallback, useEffect, useRef, useState} from 'react';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
@@ -19,115 +19,97 @@ export type Actions = {
unflagPost: typeof unflagPost; unflagPost: typeof unflagPost;
} }
interface Props { type Props = {
location?: keyof typeof Locations; location?: keyof typeof Locations;
postId: string; postId: string;
isFlagged: boolean; isFlagged: boolean;
actions: Actions; actions: Actions;
} }
interface State { const PostFlagIcon = ({
a11yActive: boolean; actions: {
} flagPost,
unflagPost,
},
isFlagged,
postId,
location = Locations.CENTER,
}: Props) => {
const buttonRef = useRef<HTMLButtonElement>(null);
const [a11yActive, setA11yActive] = useState(false);
export default class PostFlagIcon extends React.PureComponent<Props, State> { const handlePress = useCallback((e: React.MouseEvent) => {
static defaultProps = {
location: Locations.CENTER,
};
private buttonRef: React.RefObject<HTMLButtonElement>;
constructor(props: Props) {
super(props);
this.buttonRef = React.createRef();
this.state = {
a11yActive: false,
};
}
componentDidMount() {
if (this.buttonRef.current) {
this.buttonRef.current.addEventListener(A11yCustomEventTypes.ACTIVATE, this.handleA11yActivateEvent);
this.buttonRef.current.addEventListener(A11yCustomEventTypes.DEACTIVATE, this.handleA11yDeactivateEvent);
}
}
componentWillUnmount() {
if (this.buttonRef.current) {
this.buttonRef.current.removeEventListener(A11yCustomEventTypes.ACTIVATE, this.handleA11yActivateEvent);
this.buttonRef.current.removeEventListener(A11yCustomEventTypes.DEACTIVATE, this.handleA11yDeactivateEvent);
}
}
componentDidUpdate() {
if (this.state.a11yActive && this.buttonRef.current) {
this.buttonRef.current.dispatchEvent(new Event(A11yCustomEventTypes.UPDATE));
}
}
handlePress = (e: React.MouseEvent) => {
e.preventDefault(); e.preventDefault();
const {
actions,
isFlagged,
postId,
} = this.props;
if (isFlagged) { if (isFlagged) {
actions.unflagPost(postId); unflagPost(postId);
} else { } else {
actions.flagPost(postId); flagPost(postId);
} }
}; }, [flagPost, unflagPost, postId, isFlagged]);
handleA11yActivateEvent = () => { useEffect(() => {
this.setState({a11yActive: true}); function handleA11yActivateEvent() {
}; setA11yActive(true);
}
handleA11yDeactivateEvent = () => { function handleA11yDeactivateEvent() {
this.setState({a11yActive: false}); setA11yActive(false);
};
render() {
const isFlagged = this.props.isFlagged;
let flagIcon;
if (isFlagged) {
flagIcon = <FlagIconFilled className={classNames('icon', 'icon--small', 'icon--small-filled', {'post-menu__item--selected': isFlagged})}/>;
} else {
flagIcon = <FlagIcon className={classNames('icon', 'icon--small')}/>;
} }
return ( if (buttonRef.current) {
<OverlayTrigger buttonRef.current.addEventListener(A11yCustomEventTypes.ACTIVATE, handleA11yActivateEvent);
className='hidden-xs' buttonRef.current.addEventListener(A11yCustomEventTypes.DEACTIVATE, handleA11yDeactivateEvent);
key={`flagtooltipkey${isFlagged ? 'flagged' : ''}`} }
delayShow={Constants.OVERLAY_TIME_DELAY} return () => {
placement='top' if (buttonRef.current) {
overlay={ buttonRef.current.removeEventListener(A11yCustomEventTypes.ACTIVATE, handleA11yActivateEvent);
<Tooltip buttonRef.current.removeEventListener(A11yCustomEventTypes.DEACTIVATE, handleA11yDeactivateEvent);
id='flagTooltip' }
className='hidden-xs' };
> }, []);
<FormattedMessage
id={isFlagged ? t('flag_post.unflag') : t('flag_post.flag')} useEffect(() => {
defaultMessage={isFlagged ? 'Remove from Saved' : 'Save'} if (a11yActive && buttonRef.current) {
/> buttonRef.current.dispatchEvent(new Event(A11yCustomEventTypes.UPDATE));
</Tooltip> }
} }, [a11yActive]);
>
<button let flagIcon;
ref={this.buttonRef} if (isFlagged) {
id={`${this.props.location}_flagIcon_${this.props.postId}`} flagIcon = <FlagIconFilled className={classNames('icon', 'icon--small', 'icon--small-filled', {'post-menu__item--selected': isFlagged})}/>;
aria-label={isFlagged ? localizeMessage('flag_post.unflag', 'Remove from Saved').toLowerCase() : localizeMessage('flag_post.flag', 'Save').toLowerCase()} } else {
className='post-menu__item' flagIcon = <FlagIcon className={classNames('icon', 'icon--small')}/>;
onClick={this.handlePress}
>
{flagIcon}
</button>
</OverlayTrigger>
);
} }
}
return (
<OverlayTrigger
className='hidden-xs'
key={`flagtooltipkey${isFlagged ? 'flagged' : ''}`}
delayShow={Constants.OVERLAY_TIME_DELAY}
placement='top'
overlay={
<Tooltip
id='flagTooltip'
className='hidden-xs'
>
<FormattedMessage
id={isFlagged ? t('flag_post.unflag') : t('flag_post.flag')}
defaultMessage={isFlagged ? 'Remove from Saved' : 'Save'}
/>
</Tooltip>
}
>
<button
ref={buttonRef}
id={`${location}_flagIcon_${postId}`}
aria-label={isFlagged ? localizeMessage('flag_post.unflag', 'Remove from Saved').toLowerCase() : localizeMessage('flag_post.flag', 'Save').toLowerCase()}
className='post-menu__item'
onClick={handlePress}
>
{flagIcon}
</button>
</OverlayTrigger>
);
};
export default React.memo(PostFlagIcon);