import { usePublicKey } from "@/app/providers/AccountProvider/usePublicKey"; import { useUserInformation } from "@/app/providers/InformationProvider/useUserInformation"; import { getInitialsColor, isMessageDeliveredByTime } from "@/app/utils/utils"; import { Avatar, Box, Flex, MantineColor, Text, useComputedColorScheme, useMantineTheme } from "@mantine/core"; import { IconCheck, IconChecks, IconCircleCheck, IconCircleCheckFilled, IconCircleX, IconClock, IconTextCaption } from "@tabler/icons-react"; import { MessageError } from "../MessageError/MessageError"; import { DeliveredMessageState } from "@/app/providers/DialogProvider/DialogProvider"; import { Attachment, AttachmentType } from "@/app/providers/ProtocolProvider/protocol/packets/packet.message"; import { MessageAttachments } from "../MessageAttachments/MessageAttachments"; import { useAvatars } from "@/app/providers/AvatarProvider/useAvatars"; import { useContextMenu } from "@/app/providers/ContextMenuProvider/useContextMenu"; import { useNavigate } from "react-router-dom"; import { MessageReply, useReplyMessages } from "@/app/providers/DialogProvider/useReplyMessages"; import { useSetting } from "@/app/providers/SettingsProvider/useSetting"; import { useRosettaBreakpoints } from "@/app/hooks/useRosettaBreakpoints"; import { TextParser } from "../TextParser/TextParser"; import { useRosettaColors } from "@/app/hooks/useRosettaColors"; import { ATTACHMENTS_NOT_ALLOWED_TO_REPLY, ENTITY_LIMITS_TO_PARSE_IN_MESSAGE } from "@/app/constants"; import { useDialog } from "@/app/providers/DialogProvider/useDialog"; import { VerifiedBadge } from "../VerifiedBadge/VerifiedBadge"; import { useGroupMembers } from "@/app/providers/InformationProvider/useGroupMembers"; export enum MessageStyle { BUBBLES = 'bubbles', ROWS = 'rows' } export interface MessageProps { message: string; from_me?: boolean; readed?: boolean; avatar_no_render?: boolean; delivered: DeliveredMessageState; from: string; timestamp: number; message_id: string; attachments: Attachment[]; replyed?: boolean; is_last_message_in_stack?: boolean; chacha_key_plain: string; parent?: MessageProps; } interface MessageSystemProps { message: string; c?: MantineColor; } export function MessageSystem(props: MessageSystemProps) { const [wallpaper] = useSetting ('wallpaper', ''); return (<> {props.message} ); } export function Message(props: MessageProps) { const computedTheme = useComputedColorScheme(); const theme = useMantineTheme(); const publicKey = usePublicKey(); const openContextMenu = useContextMenu(); const colors = useRosettaColors(); const navigate = useNavigate(); const { isSelectionStarted, selectMessage, deselectMessage, isMessageSelected, translateMessagesToDialogInput } = useReplyMessages(); const { dialog } = useDialog(); const { md } = useRosettaBreakpoints(); const { members } = useGroupMembers(dialog); const [showTimeInReplyMessages] = useSetting ('showTimeInReplyMessages', false); const [wallpaper] = useSetting ('wallpaper', ''); const [userInfo] = useUserInformation(publicKey); const [opponent] = useUserInformation(props.from); const user = props.from_me ? userInfo : { ...opponent, avatar: "" }; const messageReply: MessageReply = { timestamp: props.timestamp, publicKey: user.publicKey, message: props.message, attachments: props.attachments.filter(a => a.type != AttachmentType.MESSAGES), message_id: props.message_id }; const avatars = useAvatars(user.publicKey); const [messageStyle] = useSetting ('messageStyle', MessageStyle.ROWS); const computedMessageStyle = props.replyed ? MessageStyle.ROWS : messageStyle; const navigateToUserProfile = () => { if (isSelectionStarted()) { return; } navigate(`/main/profile/${user.publicKey}`); } const canReply = () => { if (props.replyed) { return false; } if (messageReply.attachments.find((v) => ATTACHMENTS_NOT_ALLOWED_TO_REPLY.includes(v.type))) { return false; } if (messageReply.message.trim().length == 0 && messageReply.attachments.length == 0) { return false; } if (props.delivered != DeliveredMessageState.DELIVERED) { return false; } return true; } const onMessageSelectClick = () => { if (props.replyed || !canReply()) { return; } if (isMessageSelected(messageReply)) { deselectMessage(messageReply); } else { selectMessage(messageReply); } } const onDobuleClick = () => { if (!canReply()) { return; } if (isSelectionStarted()) { return; } selectMessage(messageReply); translateMessagesToDialogInput(dialog); } return (<> !props.replyed && openContextMenu([ { label: 'Copy Message', action: () => { navigator.clipboard.writeText(props.message); }, icon: , cond: async () => { return props.message.trim().length > 0; } }, { label: !isMessageSelected(messageReply) ? 'Select' : 'Deselect', action: onMessageSelectClick, icon: !isMessageSelected(messageReply) ? : , cond: () => { return canReply(); }, } ])} p={'sm'} pt={props.avatar_no_render ? 0 : 'sm'} style={{ cursor: 'pointer', userSelect: 'auto' }}> {computedMessageStyle == MessageStyle.ROWS && ( {(!props.avatar_no_render && (md || !props.replyed)) && 0 ? avatars[0].avatar : undefined} name={user.title} variant={props.parent ? 'filled' : 'light'} color="initials">} {!props.avatar_no_render && ( /** Только если не установлен флаг который * запрещает рендеринг аватарки и имени*/ <> {user.title} {(members.length > 0 && members[0] == props.from) && ( )} )} {props.attachments.length > 0 && } {!isSelectionStarted() && <> {props.delivered == DeliveredMessageState.DELIVERED && <> {props.from_me && !props.readed && ( )} {props.from_me && props.readed && ( )} } {(props.delivered == DeliveredMessageState.WAITING && (isMessageDeliveredByTime(props.timestamp, props.attachments.length))) && <> } {(props.delivered == DeliveredMessageState.ERROR || ((!isMessageDeliveredByTime(props.timestamp, props.attachments.length)) && props.delivered != DeliveredMessageState.DELIVERED)) && ( )} } {(isSelectionStarted() && !props.replyed && canReply()) && <> {isMessageSelected(messageReply) ? : } } {(isSelectionStarted() && !canReply() && !props.replyed) && } {(showTimeInReplyMessages || !props.replyed) && { new Date(props.timestamp).toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' }) }} )} {computedMessageStyle == MessageStyle.BUBBLES && (() => { const hasOnlyAttachments = props.attachments.length > 0 && props.message.trim().length === 0; return ( {(md && props.is_last_message_in_stack) && ( 0 ? avatars[0].avatar : undefined} name={user.title} color="initials" variant={wallpaper != '' ? 'filled' : 'light'} style={{ flexShrink: 0 }}> )} {(md && !props.is_last_message_in_stack) && ( )} {(!props.avatar_no_render && dialog.includes("#group") && wallpaper == '') && ( {user.title} {(members.length > 0 && members[0] == props.from) && ( )} )} {props.attachments.length > 0 && 0 ? 4 : 0}> } {props.message.trim().length > 0 && ( )} a.type != AttachmentType.MESSAGES) ? { position: 'absolute', bottom: 8, right: 8, backgroundColor: 'rgba(0, 0, 0, 0.3)', padding: '3px 8px', borderRadius: '10px', backdropFilter: 'blur(4px)' } : {}) }}> {wallpaper != '' && dialog.includes("#group") && ( {user.title} )} {!isSelectionStarted() && <> {props.delivered == DeliveredMessageState.DELIVERED && <> {props.from_me && !props.readed && ( )} {props.from_me && props.readed && ( )} } {(props.delivered == DeliveredMessageState.WAITING && (isMessageDeliveredByTime(props.timestamp, props.attachments.length))) && <> } {(props.delivered == DeliveredMessageState.ERROR || ((!isMessageDeliveredByTime(props.timestamp, props.attachments.length)) && props.delivered != DeliveredMessageState.DELIVERED)) && ( )} } {(isSelectionStarted() && !props.replyed && canReply()) && <> {isMessageSelected(messageReply) ? : } } {(isSelectionStarted() && !canReply() && !props.replyed) && } {(showTimeInReplyMessages || !props.replyed) && {new Date(props.timestamp).toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })} } ); })()} ); }