|
@@ -0,0 +1,338 @@
|
|
|
+import React, {useState, useEffect, useRef} from 'react'
|
|
|
+import FileDownloadIcon from '@mui/icons-material/FileDownload';
|
|
|
+import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
|
|
|
+import Popper from '@mui/material/Popper';
|
|
|
+
|
|
|
+import { connect } from 'react-redux'
|
|
|
+import { dateFromStamp, stringColor, backURL } from '../helpers'
|
|
|
+
|
|
|
+import { UserAvatar, CMyAvatar } from '.'
|
|
|
+
|
|
|
+
|
|
|
+const msgBlock = {
|
|
|
+ alignSelf: "start",
|
|
|
+ display: "flex",
|
|
|
+ justifyContent: "flex-start",
|
|
|
+ alignItems: "start",
|
|
|
+ margin: "2px",
|
|
|
+ marginRight: "5%",
|
|
|
+ maxWidth: "calc(95% - 2px)",
|
|
|
+ minWidth: "40%",
|
|
|
+ wordWrap: "break-word",
|
|
|
+}
|
|
|
+
|
|
|
+const myMsgBlock = {
|
|
|
+ alignSelf: "end",
|
|
|
+ display: "flex",
|
|
|
+ justifyContent: "flex-start",
|
|
|
+ alignItems: "start",
|
|
|
+ margin: "2px",
|
|
|
+ marginLeft: "5%",
|
|
|
+ maxWidth: "calc(95% - 2px)",
|
|
|
+ minWidth: "40%",
|
|
|
+ wordWrap: "break-word",
|
|
|
+}
|
|
|
+
|
|
|
+const avBlock = {
|
|
|
+ alignSelf: "end",
|
|
|
+ width: "40px",
|
|
|
+ marginRight: "10px"
|
|
|
+}
|
|
|
+
|
|
|
+const bodyBlock = {
|
|
|
+ display: "flex",
|
|
|
+ flexDirection: "column",
|
|
|
+ justifyContent: "flex-start",
|
|
|
+ borderRadius: "5px",
|
|
|
+ backgroundColor: "#fff",
|
|
|
+ width: "calc(100% - 50px)",
|
|
|
+ padding: "10px"
|
|
|
+}
|
|
|
+
|
|
|
+const myBodyBlock = {
|
|
|
+ display: "flex",
|
|
|
+ flexDirection: "column",
|
|
|
+ justifyContent: "flex-start",
|
|
|
+ borderRadius: "5px",
|
|
|
+ backgroundColor: "#1976d255",
|
|
|
+ width: "calc(100% - 50px)",
|
|
|
+ padding: "10px"
|
|
|
+}
|
|
|
+
|
|
|
+const nameBlock = {
|
|
|
+ fontWeight: 600,
|
|
|
+ fontSize: "12px",
|
|
|
+ alignSelf: "start",
|
|
|
+ maxWidth: "100%",
|
|
|
+ marginBottom: "5px",
|
|
|
+}
|
|
|
+const contentBlock = {
|
|
|
+ alignSelf: "stretch",
|
|
|
+ maxWidth: "100%",
|
|
|
+}
|
|
|
+const dateBlock = {
|
|
|
+ alignSelf: "end",
|
|
|
+ maxWidth: "100%",
|
|
|
+ fontSize: "10px",
|
|
|
+ color: "#555"
|
|
|
+}
|
|
|
+
|
|
|
+const mediaBlock = {
|
|
|
+ marginBottom: "20px"
|
|
|
+}
|
|
|
+const textBlock = {
|
|
|
+}
|
|
|
+
|
|
|
+const imgStyle = {
|
|
|
+ maxWidth: "100%",
|
|
|
+ width: "auto",
|
|
|
+ maxHeight: "400px",
|
|
|
+ height: "auto",
|
|
|
+ margin: "0 5px"
|
|
|
+}
|
|
|
+const downloadStyle = {
|
|
|
+ display: "flex",
|
|
|
+ maxWidth: "300px",
|
|
|
+ minHeight: "54px",
|
|
|
+ borderRadius: "30px",
|
|
|
+ textDecoration: "none",
|
|
|
+ margin: "5px 0",
|
|
|
+ padding: "10px",
|
|
|
+ backgroundColor: "#eeee"
|
|
|
+}
|
|
|
+const imgDownload = {
|
|
|
+ alignSelf: "center",
|
|
|
+ borderRadius: "50%",
|
|
|
+ backgroundColor: "#1976d2",
|
|
|
+ height: "45px",
|
|
|
+ width: "45px",
|
|
|
+ display: "flex",
|
|
|
+ justifyContent: "center",
|
|
|
+ alignItems: "center",
|
|
|
+ marginRight: "10px",
|
|
|
+}
|
|
|
+const textDownload = {
|
|
|
+ alignSelf: "start",
|
|
|
+ // marginTop: "10px",
|
|
|
+ maxWidth: "calc(100% - 55px)",
|
|
|
+ fontSize: 14,
|
|
|
+ fontWeight: 500,
|
|
|
+ color: "#000",
|
|
|
+ wordWrap: "break-word",
|
|
|
+ overflow: "hidden"
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const Msg = ({ msg, prevOwner, prevTime, myProfile, onEvent }) => {
|
|
|
+
|
|
|
+ const myId = myProfile?._id || null
|
|
|
+ const myLogin = myProfile?.login || null
|
|
|
+ const myNick = myProfile?.nick || null
|
|
|
+
|
|
|
+ const { _id, text, owner, media, createdAt } = msg
|
|
|
+ const {nick, login, avatar} = owner
|
|
|
+
|
|
|
+ const allMedia = {}
|
|
|
+ if (media) for (const file of media) {
|
|
|
+ if (file.type) {
|
|
|
+
|
|
|
+ const objName = file.type.split('/')[0]
|
|
|
+ if (allMedia.hasOwnProperty(objName)) {
|
|
|
+
|
|
|
+ allMedia[objName].push(file)
|
|
|
+ } else {
|
|
|
+ allMedia[objName] = [file]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const prOwner = prevOwner.current
|
|
|
+ prevOwner.current = owner._id
|
|
|
+
|
|
|
+ const prTime = prevTime.current
|
|
|
+ prevTime.current = createdAt
|
|
|
+
|
|
|
+ // console.log( prTime - createdAt, text)
|
|
|
+ const nameBlockNew = {...nameBlock, color: stringColor.stringToColor(nick || login)}
|
|
|
+ return (
|
|
|
+ <div onClick={onEvent}
|
|
|
+ style={(myId === owner._id) ?
|
|
|
+ ( (prOwner === owner._id) ?
|
|
|
+ {...myMsgBlock, marginBottom: "2px"} : {...myMsgBlock, marginBottom: "15px"}) :
|
|
|
+ ( (prOwner === owner._id) ?
|
|
|
+ {...msgBlock, marginBottom: "2px"} : {...msgBlock, marginBottom: "15px"})
|
|
|
+ }
|
|
|
+ >
|
|
|
+
|
|
|
+ <div style={avBlock} >
|
|
|
+ { (prOwner === owner._id &&
|
|
|
+ prTime - createdAt < 600000) ||
|
|
|
+ ( (myId === owner._id) ?
|
|
|
+ <CMyAvatar /> :
|
|
|
+ <UserAvatar profile={owner} /> ) }
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div style={(myId === owner._id) ? myBodyBlock : bodyBlock} >
|
|
|
+
|
|
|
+ <div style={(myId === owner._id) ? nameBlock : nameBlockNew} >
|
|
|
+ { (myId === owner._id) ? (myNick || myLogin) : (nick || login) }
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div style={contentBlock} >
|
|
|
+ { (Object.keys(allMedia).length > 0) &&
|
|
|
+ <div style={mediaBlock}>
|
|
|
+ { Object.keys(allMedia).map((key) =>
|
|
|
+ <div key={key} >
|
|
|
+ {
|
|
|
+ (key === 'image') &&
|
|
|
+ allMedia[key].map((mediaObj) =>
|
|
|
+ <img
|
|
|
+ key={mediaObj.url}
|
|
|
+ style={imgStyle}
|
|
|
+ src={backURL + mediaObj.url}
|
|
|
+ />
|
|
|
+ ) ||
|
|
|
+ (key === 'video') &&
|
|
|
+ allMedia[key].map((mediaObj) =>
|
|
|
+ <video
|
|
|
+ key={mediaObj.url}
|
|
|
+ style={imgStyle}
|
|
|
+ src={backURL + mediaObj.url}
|
|
|
+ controls
|
|
|
+ preload={'metadata'}
|
|
|
+ >
|
|
|
+ </video>
|
|
|
+ ) ||
|
|
|
+ (key === 'audio') &&
|
|
|
+ allMedia[key].map((mediaObj) =>
|
|
|
+ <div
|
|
|
+ key={mediaObj.url}
|
|
|
+ >
|
|
|
+ <audio
|
|
|
+ src={backURL + mediaObj.url}
|
|
|
+ controls
|
|
|
+ >
|
|
|
+ </audio>
|
|
|
+ </div>
|
|
|
+ ) ||
|
|
|
+ allMedia[key].map((mediaObj) =>
|
|
|
+ <a
|
|
|
+ key={mediaObj.url}
|
|
|
+ href={backURL + mediaObj.url}
|
|
|
+ download
|
|
|
+ style={downloadStyle}
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ style={imgDownload}>
|
|
|
+ <FileDownloadIcon
|
|
|
+ style={{
|
|
|
+ fontSize: 35,
|
|
|
+ color: "#ddd",
|
|
|
+ }} />
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ style={textDownload} >
|
|
|
+ {mediaObj.originalFileName}
|
|
|
+ </div>
|
|
|
+ </a>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+
|
|
|
+ <pre style={textBlock}>
|
|
|
+ {text}
|
|
|
+ </pre>
|
|
|
+
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div style={dateBlock} >
|
|
|
+ {dateFromStamp(createdAt)}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+export const CMsg = connect( state => ({ myProfile: state.promise.myProfile?.payload || {}}))(Msg)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+export const MsgMenu = (props) => {
|
|
|
+
|
|
|
+ const [anchorEl, setAnchorEl] = useState(null);
|
|
|
+
|
|
|
+ const handleClick = (e) => {
|
|
|
+ e.preventDefault()
|
|
|
+ if (e.button === 2) {
|
|
|
+
|
|
|
+ }
|
|
|
+ setAnchorEl(anchorEl ? null : e.currentTarget);
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ const open = Boolean(anchorEl);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+
|
|
|
+ <CMsg {...props} onEvent={handleClick} />
|
|
|
+
|
|
|
+ <Popper open={open} anchorEl={anchorEl}>
|
|
|
+
|
|
|
+ <div style={{ backgroundColor: "#fff"}} >
|
|
|
+ РЕДАКТИРОВАНИЕ
|
|
|
+ </div>
|
|
|
+ </Popper>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+//tg
|
|
|
+
|
|
|
+{/* <div class="media-inner dark interactive" style="">
|
|
|
+ <canvas class="thumbnail" width="1304" height="720" style="width: 480px; height: 265px;">
|
|
|
+ </canvas>
|
|
|
+ <img class="thumbnail opacity-transition slow" alt=""
|
|
|
+ draggable="true" style="width: 480px; height: 265px;">
|
|
|
+ <video class="full-media" width="480" height="265" autoplay="" loop="" playsinline="" draggable="true">
|
|
|
+ <source src="blob:https://web.telegram.org/464cc156-4e7f-415e-bec5-5fdf5b6c2d98">
|
|
|
+ </video>
|
|
|
+ <div class="message-media-duration">5:27</div>
|
|
|
+</div> */}
|
|
|
+
|
|
|
+
|
|
|
+{/* <div class="File interactive">
|
|
|
+ <div class="file-icon-container">
|
|
|
+ <div class="file-icon orange">
|
|
|
+ <span class="file-ext" dir="auto">
|
|
|
+ zip
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <i class="action-icon icon-download"></i>
|
|
|
+ </div>
|
|
|
+ <div class="file-info">
|
|
|
+ <div class="file-title" dir="auto">2.1 01-02.zip</div>
|
|
|
+ <div class="file-subtitle" dir="auto">
|
|
|
+ <span>0.6 KB</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div> */}
|