soapbox/app/soapbox/components/status-hover-card.tsx

103 wiersze
2.7 KiB
TypeScript
Czysty Zwykły widok Historia

2023-02-06 18:01:03 +00:00
import clsx from 'clsx';
import React, { useEffect, useState, useCallback } from 'react';
2022-06-17 04:19:53 +00:00
import { usePopper } from 'react-popper';
import { useHistory } from 'react-router-dom';
import {
closeStatusHoverCard,
updateStatusHoverCard,
2022-06-17 19:39:17 +00:00
} from 'soapbox/actions/status-hover-card';
import { fetchStatus } from 'soapbox/actions/statuses';
2022-11-15 16:13:54 +00:00
import StatusContainer from 'soapbox/containers/status-container';
2022-06-17 04:19:53 +00:00
import { useAppSelector, useAppDispatch } from 'soapbox/hooks';
2022-06-17 19:39:17 +00:00
import { showStatusHoverCard } from './hover-status-wrapper';
import { Card, CardBody } from './ui';
2022-06-17 04:19:53 +00:00
interface IStatusHoverCard {
visible: boolean
2022-06-17 04:19:53 +00:00
}
/** Popup status preview that appears when hovering reply to */
export const StatusHoverCard: React.FC<IStatusHoverCard> = ({ visible = true }) => {
const dispatch = useAppDispatch();
const history = useHistory();
const [popperElement, setPopperElement] = useState<HTMLElement | null>(null);
const statusId: string | undefined = useAppSelector(state => state.status_hover_card.statusId || undefined);
const status = useAppSelector(state => state.statuses.get(statusId!));
2022-06-17 04:19:53 +00:00
const targetRef = useAppSelector(state => state.status_hover_card.ref?.current);
2022-06-17 19:39:17 +00:00
useEffect(() => {
if (statusId && !status) {
dispatch(fetchStatus(statusId));
}
}, [statusId, status]);
2022-06-17 19:39:17 +00:00
2022-06-17 04:19:53 +00:00
useEffect(() => {
const unlisten = history.listen(() => {
showStatusHoverCard.cancel();
dispatch(closeStatusHoverCard());
});
return () => {
unlisten();
};
}, []);
const { styles, attributes } = usePopper(targetRef, popperElement, {
placement: 'top',
2022-06-17 04:19:53 +00:00
});
const handleMouseEnter = useCallback((): React.MouseEventHandler => {
return () => {
dispatch(updateStatusHoverCard());
};
}, []);
const handleMouseLeave = useCallback((): React.MouseEventHandler => {
return () => {
dispatch(closeStatusHoverCard(true));
};
}, []);
2022-06-17 04:19:53 +00:00
if (!statusId) return null;
const renderStatus = (statusId: string) => {
return (
// @ts-ignore
<StatusContainer
key={statusId}
id={statusId}
2022-06-20 22:37:20 +00:00
hoverable={false}
2022-06-17 04:19:53 +00:00
hideActionBar
muted
2022-06-17 04:19:53 +00:00
/>
);
};
return (
<div
2023-02-06 18:01:03 +00:00
className={clsx({
'absolute transition-opacity w-[500px] z-50 top-0 left-0': true,
2022-06-17 04:19:53 +00:00
'opacity-100': visible,
'opacity-0 pointer-events-none': !visible,
})}
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
onMouseEnter={handleMouseEnter()}
onMouseLeave={handleMouseLeave()}
2022-06-17 04:19:53 +00:00
>
<Card className='relative'>
<CardBody>
{renderStatus(statusId)}
</CardBody>
</Card>
</div>
);
};
export default StatusHoverCard;