UNPKG

@selfcommunity/react-ui

Version:

React UI Components to integrate a Community created with SelfCommunity Platform.

167 lines (157 loc) • 9.43 kB
import { __awaiter, __rest } from "tslib"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useContext, useState } from 'react'; import { styled } from '@mui/material/styles'; import { ListItem, Typography, IconButton, Box, useTheme, Button } from '@mui/material'; import PrivateMessageThreadItemSkeleton from './Skeleton'; import { useIntl } from 'react-intl'; import { SCMessageFileType, SCPrivateMessageStatusType } from '@selfcommunity/types'; import Icon from '@mui/material/Icon'; import classNames from 'classnames'; import { useThemeProps } from '@mui/system'; import { SCUserContext } from '@selfcommunity/react-core'; import useMediaQuery from '@mui/material/useMediaQuery'; import PrivateMessageSettingsIconButton from '../PrivateMessageSettingsIconButton'; import { bytesToSize } from '../../utils/sizeCoverter'; import BaseDialog from '../../shared/BaseDialog'; import LightBox from '../../shared/Lightbox'; import AutoPlayer from '../../shared/AutoPlayer'; import { useSnackbar } from 'notistack'; import { PREFIX } from './constants'; import { isSupportedVideoFormat } from '../../utils/thumbnailCoverter'; const classes = { root: `${PREFIX}-root`, username: `${PREFIX}-username`, text: `${PREFIX}-text`, img: `${PREFIX}-img`, document: `${PREFIX}-document`, video: `${PREFIX}-video`, other: `${PREFIX}-other`, iconButton: `${PREFIX}-icon-button`, messageTime: `${PREFIX}-message-time`, menuItem: `${PREFIX}-menu-item`, downloadButton: `${PREFIX}-download-button`, dialogRoot: `${PREFIX}-dialog-root` }; const DialogRoot = styled(BaseDialog, { name: PREFIX, slot: 'DialogRoot' })(() => ({})); const Root = styled(ListItem, { name: PREFIX, slot: 'Root' })(() => ({})); /** * > API documentation for the Community-JS PrivateMessageItem component. Learn about the available props and the CSS API. #### Import ```jsx import {PrivateMessageThreadItem} from '@selfcommunity/react-ui'; ``` #### Component Name The name `SCPrivateMessageThreadItem` can be used when providing style overrides in the theme. #### CSS |Rule Name|Global class|Description| |---|---|---| |root|.SCPrivateMessageThreadItem-root|Styles applied to the root element.| |text|.SCPrivateMessageThreadItem-text|Styles applied to the message text element.| |img|.SCPrivateMessageThreadItem-img|Styles applied to the img element.| |document|.SCPrivateMessageThreadItem-document|Styles applied to the message file element.| |video|.SCPrivateMessageThreadItem-video|Styles applied to the message video element.| |other|.SCPrivateMessageThreadItem-other|Styles applied to other media type element.| |messageTime|.SCPrivateMessageThreadItem-message-time|Styles applied to the thread message time element.| |menuItem|.SCPrivateMessageThreadItem-menu-item|Styles applied to the thread message menu item element.| |dialogRoot|.SCPrivateMessageThreadItem-dialog-root|Styles applied to dialog root element.| * @param inProps */ export default function PrivateMessageThreadItem(inProps) { var _a; // PROPS const props = useThemeProps({ props: inProps, name: PREFIX }); const { message = null, className = null, mouseEvents = {}, isHovering = null, showMenuIcon = false, onMenuIconClick = null } = props, rest = __rest(props, ["message", "className", "mouseEvents", "isHovering", "showMenuIcon", "onMenuIconClick"]); // INTL const intl = useIntl(); // CONTEXT const scUserContext = useContext(SCUserContext); // STATE const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); const hasFile = message ? message.file : null; const [openDialog, setOpenDialog] = useState(false); const { enqueueSnackbar } = useSnackbar(); const getMouseEvents = (mouseEnter, mouseLeave) => ({ onMouseEnter: mouseEnter, onMouseLeave: mouseLeave, onTouchStart: mouseEnter, onTouchMove: mouseLeave }); const handleMenuItemClick = () => { onMenuIconClick(); }; const handleDownload = (file) => __awaiter(this, void 0, void 0, function* () { try { const response = yield fetch(file.url); const data = yield response.blob(); const blob = URL.createObjectURL(data); const link = document.createElement('a'); link.href = blob; link.download = file.filename; link.click(); URL.revokeObjectURL(blob); link.remove(); } catch (error) { console.log(error); enqueueSnackbar(error, { variant: 'error', autoHideDuration: 3000 }); } }); // RENDERING const renderMessageFile = (m) => { if (!m) { return null; } let section = null; const defaultSection = (_jsx(Box, Object.assign({ className: classes.other }, { children: _jsxs(Button, Object.assign({ onClick: () => handleDownload(m.file), startIcon: _jsx(Icon, { children: "download" }) }, { children: [_jsx(Typography, { children: m.file.filename }), _jsx(Typography, { children: bytesToSize(m.file.filesize) })] })) }))); if (m.file) { let type = m.file.mimetype; switch (true) { case type.startsWith(SCMessageFileType.IMAGE): section = (_jsx(Box, Object.assign({ className: classes.img }, { children: _jsx("img", { src: m.file.thumbnail, loading: "lazy", alt: 'img', onClick: () => setOpenDialog(true) }) }))); break; case type.startsWith(SCMessageFileType.VIDEO): if (!isSupportedVideoFormat(m.file.filename)) { section = defaultSection; } else { section = (_jsxs(Box, Object.assign({ className: classNames(classes.img, classes.video) }, { children: [_jsx("img", { src: m.file.thumbnail, loading: "lazy", alt: 'img' }), _jsx(IconButton, Object.assign({ onClick: () => setOpenDialog(true) }, { children: _jsx(Icon, { children: "play_circle_outline" }) }))] }))); } break; case type.startsWith(SCMessageFileType.DOCUMENT): section = (_jsxs(Box, Object.assign({ className: m.file.filename.endsWith('.pdf') ? classes.document : classes.other }, { children: [m.file.filename.endsWith('.pdf') && _jsx("img", { src: m.file.thumbnail, loading: "lazy", alt: 'img' }), _jsxs(Button, Object.assign({ onClick: () => handleDownload(m.file), startIcon: _jsx(Icon, { children: "download" }) }, { children: [_jsx(Typography, { children: m.file.filename }), _jsx(Typography, { children: bytesToSize(m.file.filesize) })] }))] }))); break; default: // section = <Icon>hide_image</Icon>; section = defaultSection; break; } } return _jsx(_Fragment, { children: section }); }; if (!message) { return _jsx(PrivateMessageThreadItemSkeleton, { elevation: 0 }); } /** * Renders root object */ return (_jsxs(Root, Object.assign({ className: classNames(classes.root, className) }, getMouseEvents(mouseEvents.onMouseEnter, mouseEvents.onMouseLeave), rest, { secondaryAction: (isHovering || isMobile) && showMenuIcon && message.status !== SCPrivateMessageStatusType.HIDDEN && _jsx(PrivateMessageSettingsIconButton, { onMenuItemDeleteClick: handleMenuItemClick }) }, { children: [message.group && ((_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.username) !== message.sender.username && (_jsx(Typography, Object.assign({ color: "secondary", variant: "h4", className: classes.username }, { children: message.sender.username }))), _jsxs(_Fragment, { children: [hasFile && message.status !== SCPrivateMessageStatusType.HIDDEN ? (renderMessageFile(message)) : (_jsx(Box, Object.assign({ className: classes.text }, { children: _jsx(Typography, { component: "span", dangerouslySetInnerHTML: { __html: message.message } }) }))), _jsx(Typography, Object.assign({ className: classes.messageTime, color: "text.secondary" }, { children: `${intl.formatDate(message.created_at, { hour: 'numeric', minute: 'numeric' })}` }))] }), openDialog && (_jsx(_Fragment, { children: (message === null || message === void 0 ? void 0 : message.file.mimetype.startsWith(SCMessageFileType.VIDEO)) ? (_jsx(DialogRoot, Object.assign({ open: openDialog, onClose: () => setOpenDialog(false), className: classes.dialogRoot }, { children: _jsx(AutoPlayer, { url: message === null || message === void 0 ? void 0 : message.file.url, width: '100%', enableAutoplay: false }) }))) : (_jsx(LightBox, { images: [{ src: message === null || message === void 0 ? void 0 : message.file.url, key: message.file.uuid }], onClose: () => setOpenDialog(false), toolbarButtons: _jsx(IconButton, Object.assign({ onClick: () => handleDownload(message === null || message === void 0 ? void 0 : message.file), className: classes.downloadButton }, { children: _jsx(Icon, { children: "download" }) }), 'download') })) }))] }))); }