@@ -1,896 +0,0 @@ -import React, { useMemo, useState } from 'react' -import { Box, Menu, MenuItem, Skeleton, Slide, Typography } from '@mui/material' -import Stack from '@mui/material/Stack' -import Image from 'next/image' - -import FullScreenModal from '#/features/image-modal/full-screen-modal' -import { TooltipCustom } from '#/shared' -import { formatDate } from '#/shared/lib/helpers' -import { Message } from '#/shared/lib/types/model' -import { BotMessage } from '#/widgets/messages' - -import { Markdown } from '../../markdown/markdown' - -interface IMessagesList { - // messageResponse: Message[] | null - // mode?: string - // sendMessage?: (title: string) => void - // getMessagesPagination?: () => Promise - - device: 'mobile' | 'desktop' - modelType: string - isNewMessage: boolean - message: Message - deleteMessage?: (message_uid: string) => void - modelTitle: string | undefined - setResendValue: (value: string) => void - onLoadImage?: (event: React.ChangeEvent | null, file?: File) => void -} - -export const UserMessage = React.memo(function UserMessage(props: IMessagesList) { - const [anchorEl, setAnchorEl] = React.useState(null) - const open = Boolean(anchorEl) - const desktop = props.device === 'desktop' - const [modal, setModal] = useState(false) - const [loaded, setLoaded] = useState(false) - - const copy = (text: string) => { - navigator.clipboard.writeText(text) - } - const handleClick = (event: React.MouseEvent) => { - setAnchorEl(event.currentTarget) - } - const handleClose = () => { - setAnchorEl(null) - } - - const fileName = useMemo(() => { - if (!props.message.file) return 'Подбираем имя файла...' - const matches = (props.message.file as string).match(/air-messages\/(.+?)\.(.+?)\?/) - if (!matches) return 'Подбираем имя файла...' - return `${matches[1]}.${matches[2]}` - }, []) - - const resend = async () => { - props.setResendValue(props.message.content) - if (props.message.file !== null) { - fetch(props.message.file as string, { - method: 'GET', - headers: {}, - }).then((response) => { - response.arrayBuffer().then(function (buffer) { - const url = new Blob([buffer]) - const binaryFile = new File([url], 'image.png') - if (props.onLoadImage) { - props.onLoadImage(null, binaryFile) - } - }) - }) - } - } - - const flexStyle = { - display: 'flex', - alignItems: 'center', - justifyContent: 'start', - gap: '12px', - color: '#7f7df3 !important', - fontWeight: '600 !important', - lineHeight: '140%', - letterSpacing: '0.2px', - cursor: 'pointer', - } - - return ( - <> - {props.message.file && ( - - )} - - {!props.message.from_model ? ( - // - - - - - {formatDate(props.message.created_at, { - hour: 'numeric', - minute: 'numeric', - })} - - - - - {props.message.file ? ( - /\.jpg|\.png|\.jpeg|\.gif|\.webp|\.svg\.wav/.test( - props.message.file as string - ) ? ( - - - { - if (!props.message.file) - return - setModal(true) - }} - onLoadingComplete={() => - setLoaded(true) - } - style={{ - objectFit: 'contain', - height: '100%', - width: '100%', - borderRadius: '13px', - cursor: 'pointer', - opacity: loaded - ? '100%' - : '0%', - minWidth: '100px', - minHeight: '100px', - }} - width={500} - height={500} - src={ - props.message.file - .toString() - .split('?type')[0] - } - alt={ - 'К сожалению, изображение не загрузилось' - } - /> - {!loaded && ( - - )} - - - - - - - - - - - - - - - { - copy( - props.message - .content - ) - }} - > - - - - - - - Копировать - - { - if ( - props.deleteMessage - ) - props.deleteMessage( - props - .message - .uid - ) - }} - > - - - - Удалить - - - - - {!props.message.is_sent && ( - 1 - )} - - 30 - ? 'pre-wrap' - : 'pre', - }} - > - {/**/} - {props.message.content} - - - - ) : ( - - - { - if (props.message.file) { - window.open( - props.message - .file as string, - '_blank' - ) - } - }} - className='smallScroll' - sx={{ - overflowY: 'auto', - position: 'relative', - padding: '15px 23px', - - border: `1px solid #303035`, - - boxShadow: 'none', - fontSize: '15px', - marginTop: 0.5, - textAlign: 'left', - fontFamily: - 'Raleway,sans-serif', - borderRadius: '13px', - '& p': { - color: 'inherit', - fontStyle: 'inherit', - }, - ...flexStyle, - }} - > - - - - - - - - - - - - - - - - - - - - - - - { - copy( - props.message - .content - ) - }} - > - - - - - - - Копировать - - { - if ( - props.deleteMessage - ) - props.deleteMessage( - props - .message - .uid - ) - }} - > - - - - Удалить - - - - - {!props.message.is_sent && ( - 1 - )} - - 30 - ? 'pre-wrap' - : 'pre', - }} - > - {/**/} - {props.message.content} - - - - ) - ) : ( - - - - - - - - - - - - - - { - copy(props.message.content) - }} - > - - - - - - - Копировать - - { - if (props.deleteMessage) - props.deleteMessage( - props.message.uid - ) - }} - > - - - - Удалить - - - - - {!props.message.is_sent && ( - 1 - )} - - 30 - ? 'pre-wrap' - : 'pre', - }} - > - {/**/} - {props.message.content} - - - )} - - - - ) : ( - - )} - - - ) -}) @@ -1,816 +0,0 @@ -import React, { useEffect, useMemo, useState } from 'react' -import { Box, Menu, MenuItem, Skeleton, Slide, Typography } from '@mui/material' -import Stack from '@mui/material/Stack' -import Image from 'next/image' - -import { TooltipCustom } from '#/shared' -import { Message } from '#/shared/lib/types/model' -import { BotMessage } from '#/widgets/messages' -import { Markdown } from '../../markdown/markdown' -import { formatDate } from '#/shared/lib/helpers' - -interface IMessagesList { - // messageResponse: Message[] | null - // mode?: string - // sendMessage?: (title: string) => void - // getMessagesPagination?: () => Promise - - device: 'mobile' | 'desktop' - modelType: string - isNewMessage: boolean - setCurrentSrc: (value: string) => void - message: Message - setModal: (value: boolean) => void - deleteMessage?: (message_uid: string) => void - modelTitle: string | undefined - setResendValue: (value: string) => void - onLoadImage?: (event: React.ChangeEvent | null, file?: File) => void -} - -export const UserMessage = React.memo(function UserMessage({ setCurrentSrc, setModal, ...props }: IMessagesList) { - const [anchorEl, setAnchorEl] = React.useState(null) - const open = Boolean(anchorEl) - const desktop = props.device === 'desktop' - const [loaded, setLoaded] = useState(false) - - const copy = (text: string) => { - navigator.clipboard.writeText(text) - } - const handleClick = (event: React.MouseEvent) => { - setAnchorEl(event.currentTarget) - } - const handleClose = () => { - setAnchorEl(null) - } - - const fileName = useMemo(() => { - if (!props.message.file) return 'Подбираем имя файла...' - const matches = (props.message.file as string).match(/air-messages\/(.+?)\.(.+?)\?/) - if (!matches) return 'Подбираем имя файла...' - return `${matches[1]}.${matches[2]}` - }, []) - - const resend = async () => { - props.setResendValue(props.message.content) - if (props.message.file !== null) { - fetch(props.message.file as string, { - method: 'GET', - headers: {}, - }).then((response) => { - response.arrayBuffer().then(function (buffer) { - const url = new Blob([buffer]) - const binaryFile = new File([url], 'image.png') - if (props.onLoadImage) { - props.onLoadImage(null, binaryFile) - } - }) - }) - } - } - - const flexStyle = { - display: 'flex', - alignItems: 'center', - justifyContent: 'start', - gap: '12px', - color: '#7f7df3 !important', - fontWeight: '600 !important', - lineHeight: '140%', - letterSpacing: '0.2px', - cursor: 'pointer', - } - - return ( - <> - - {!props.message.from_model ? ( - // - - - - - {formatDate(props.message.created_at, { - hour: 'numeric', - minute: 'numeric', - })} - - - - - {props.message.file ? ( - /\.jpg|\.png|\.jpeg|\.gif|\.webp|\.svg/.test( - props.message.file as string - ) ? ( - - - { - if (!props.message.file) return - setCurrentSrc(props.message.file.toString()) - setModal(true) - }} - onLoadingComplete={() => setLoaded(true)} - style={{ - objectFit: 'contain', - height: '100%', - width: '100%', - borderRadius: '13px', - cursor: 'pointer', - opacity: loaded ? '100%' : '0%', - minWidth: '100px', - minHeight: '100px', - }} - width={500} - height={500} - src={props.message.file.toString().split('?type')[0]} - alt={'К сожалению, изображение не загрузилось'} - /> - {!loaded && ( - - )} - - - - - - - - - - - - - - - { - copy(props.message.content) - }} - > - - - - - - - Копировать - - { - if (props.deleteMessage) - props.deleteMessage( - props.message.uid - ) - }} - > - - - - Удалить - - - - - {!props.message.is_sent && ( - 1 - )} - - 30 - ? 'pre-wrap' - : 'pre', - }} - > - {/**/} - {props.message.content} - - - - ) : ( - - - { - if (props.message.file) { - window.open( - props.message.file as string, - '_blank' - ) - } - }} - className='smallScroll' - sx={{ - overflowY: 'auto', - position: 'relative', - padding: '15px 23px', - - border: '1px solid #303035', - - boxShadow: 'none', - fontSize: '15px', - marginTop: 0.5, - textAlign: 'left', - fontFamily: 'Raleway,sans-serif', - borderRadius: '13px', - '& p': { - color: 'inherit', - fontStyle: 'inherit', - }, - ...flexStyle, - }} - > - - - - - - - - - - - - - - - - - - - - - - - { - copy(props.message.content) - }} - > - - - - - - - Копировать - - { - if (props.deleteMessage) - props.deleteMessage( - props.message.uid - ) - }} - > - - - - Удалить - - - - - {!props.message.is_sent && ( - 1 - )} - - 30 - ? 'pre-wrap' - : 'pre', - }} - > - {/**/} - {props.message.content} - - - - ) - ) : ( - - - - - - - - - - - - - - { - copy(props.message.content) - }} - > - - - - - - - Копировать - - { - if (props.deleteMessage) - props.deleteMessage(props.message.uid) - }} - > - - - - Удалить - - - - - {!props.message.is_sent && ( - 1 - )} - - 30 ? 'pre-wrap' : 'pre', - }} - > - {/**/} - {props.message.content} - - - )} - - - - ) : ( - - )} - - - ) -}) @@ -0,0 +1,48 @@ +import React from 'react' + +interface FullscreenIconProps { + width?: number | string + height?: number | string + className?: string +} + +export const FullscreenIcon: React.FC = ({ + width = 14, + height = 14, + className +}) => { + return ( + + + + + + + + + + + + + + ) +} \ No newline at end of file @@ -0,0 +1,21 @@ +import React from 'react' + +interface FullscreenIconProps { + width?: number | string + height?: number | string + className?: string +} + +export const ZoomOutIcon: React.FC = ({ width = 20, height = 20, className }) => { + return ( + + + + ) +} @@ -0,0 +1,21 @@ +import React from 'react' + +interface FullscreenIconProps { + width?: number | string + height?: number | string + className?: string +} + +export const ZoomOutIcon: React.FC = ({ width = 20, height = 20, className }) => { + return ( + + + + ) +} @@ -8,12 +8,15 @@ import { formatDate } from '#/shared/lib/helpers' import { Markdown } from '#/widgets/markdown/markdown' import styles from './bot-message.module.scss' +import { FullscreenIcon } from './icons/fullscreen-icon' +import { FullscreenMessageModal } from './fullscreen-message-modal' export function BotMessage(props: any) { // const LazyCode = dynamic(() => import('src/widgets/chat-gpt-field/ui/code')) const [anchorEl, setAnchorEl] = React.useState(null) const open = Boolean(anchorEl) const [markdownMessage, setMarkDownMessage] = React.useState('') + const [fullscreenModalOpen, setFullscreenModalOpen] = React.useState(false) const copy = (text: string) => { navigator.clipboard.writeText(text) @@ -33,9 +36,7 @@ export function BotMessage(props: any) { fileName = splitFileName.slice(0, 25) + '...' + - splitFileName - .slice(splitFileName.length - 8, splitFileName.length) - .split('.')[0] + + splitFileName.slice(splitFileName.length - 8, splitFileName.length).split('.')[0] + '.' + splitFileName.split('.')[1] } else { @@ -72,12 +73,7 @@ export function BotMessage(props: any) { > {props.desktop && ( - {''} + {''} )} {props.message.file ? ( - + + -