You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
636 lines
19 KiB
636 lines
19 KiB
import React, { Component } from "react"; |
|
import Message from "./Message"; |
|
import ChatInputs from "./Input"; |
|
import Keyboard from "./Keyboard"; |
|
import { RecordState } from "audio-react-recorder"; |
|
import ReactPlayer from "react-player"; |
|
import ReactAudioPlayer from "react-audio-player"; |
|
// import { list, send, sendKeys } from "../../../Redux/actions/message"; |
|
import { chat } from "../../../Redux/actions"; |
|
import { connect } from "react-redux"; |
|
import Emoji from "./Emoji/index"; |
|
|
|
import "./index.scss"; |
|
class List extends Component { |
|
constructor(props) { |
|
super(props); |
|
this.state = { |
|
emoji: false, |
|
counter: 1, |
|
id: |
|
window.innerWidth < 1000 |
|
? window.location.href.split("/").pop() * 1 |
|
: this.props.id, |
|
data: {}, |
|
message: "", |
|
voice: null, |
|
file: null, |
|
image: null, |
|
video: null, |
|
music: null, |
|
document: null, |
|
}; |
|
} |
|
addcounter(type) { |
|
if (type === "parent") { |
|
if (localStorage.getItem("tapType") === "nothing") { |
|
localStorage.removeItem("tapType"); |
|
return; |
|
} else { |
|
this.setState({ counter: this.state.counter + 1 }); |
|
} |
|
} else { |
|
localStorage.setItem("tapType", "nothing"); |
|
return; |
|
} |
|
} |
|
|
|
start = () => { |
|
this.setState({ |
|
voice: RecordState.START, |
|
}); |
|
}; |
|
|
|
stop = () => { |
|
this.setState({ |
|
voice: RecordState.STOP, |
|
}); |
|
}; |
|
|
|
//audioData contains blob and blobUrl |
|
onStop = (audioData) => { |
|
this.setState({ |
|
voice: audioData, |
|
}); |
|
this.sendVoice(audioData); |
|
}; |
|
|
|
cancel = () => { |
|
this.setState({ |
|
voice: null, |
|
}); |
|
}; |
|
|
|
typeText = (type, val) => { |
|
if (type === "text") { |
|
this.setState({ |
|
message: val, |
|
}); |
|
} else { |
|
this.setState((prevState) => ({ |
|
message: prevState.message + val, |
|
})); |
|
} |
|
}; |
|
|
|
addFile = async (e) => { |
|
if ( |
|
e.target.files[0].type === "image/apng" || |
|
e.target.files[0].type === "image/avif" || |
|
e.target.files[0].type === "image/gif" || |
|
e.target.files[0].type === "image/jpeg" || |
|
e.target.files[0].type === "image/png" || |
|
e.target.files[0].type === "image/svg+xml" || |
|
e.target.files[0].type === "image/webp" |
|
) { |
|
this.setState({ |
|
image: URL.createObjectURL(e.target.files[0]), |
|
file: "fill", |
|
video: null, |
|
document: null, |
|
music: null, |
|
}); |
|
} else if ( |
|
e.target.files[0].type === "video/3gpp" || |
|
e.target.files[0].type === "video/mpeg" || |
|
e.target.files[0].type === "video/mp4" || |
|
e.target.files[0].type === "video/ogg" || |
|
e.target.files[0].type === "video/quicktime" || |
|
e.target.files[0].type === "video/webm" |
|
) { |
|
this.setState({ |
|
image: null, |
|
file: "fill", |
|
video: URL.createObjectURL(e.target.files[0]), |
|
document: null, |
|
music: null, |
|
}); |
|
} else if ( |
|
e.target.files[0].type === "audio/3gpp" || |
|
e.target.files[0].type === "audio/aac" || |
|
e.target.files[0].type === "audio/flac" || |
|
e.target.files[0].type === "audio/mpeg" || |
|
e.target.files[0].type === "audio/mp3" || |
|
e.target.files[0].type === "audio/mp4" || |
|
e.target.files[0].type === "audio/ogg" || |
|
e.target.files[0].type === "audio/wav" || |
|
e.target.files[0].type === "audio/webm" |
|
) { |
|
this.setState({ |
|
image: null, |
|
file: "fill", |
|
video: null, |
|
document: null, |
|
music: URL.createObjectURL(e.target.files[0]), |
|
}); |
|
} else { |
|
this.setState({ |
|
image: null, |
|
file: "fill", |
|
video: null, |
|
music: null, |
|
document: { |
|
data: URL.createObjectURL(e.target.files[0]), |
|
name: e.target.files[0].name, |
|
}, |
|
}); |
|
} |
|
}; |
|
|
|
sendMessage = () => { |
|
if (this.state.file !== null) { |
|
this.sendFile(); |
|
return; |
|
} else { |
|
let now = new Date(); |
|
this.setState((prevState) => ({ |
|
data: { |
|
...prevState.data, |
|
messages: [ |
|
...prevState.data.messages, |
|
{ |
|
id: "m12", |
|
type: "normal", |
|
text: prevState.message, |
|
voice: null, |
|
image: null, |
|
file: null, |
|
video: null, |
|
music: null, |
|
document: null, |
|
createdAt: now.toString(), |
|
user: { |
|
id: "u1", |
|
name: "علی", |
|
}, |
|
}, |
|
], |
|
}, |
|
})); |
|
this.setState({ |
|
message: "", |
|
}); |
|
} |
|
}; |
|
|
|
sendVoice = (audioData) => { |
|
let now = new Date(); |
|
this.setState((prevState) => ({ |
|
data: { |
|
...prevState.data, |
|
messages: [ |
|
...prevState.data.messages, |
|
{ |
|
id: "m9", |
|
text: null, |
|
type: "normal", |
|
voice: audioData, |
|
createdAt: now.toString(), |
|
image: null, |
|
video: null, |
|
document: null, |
|
music: null, |
|
user: { |
|
id: "u1", |
|
name: "علی", |
|
}, |
|
}, |
|
], |
|
}, |
|
})); |
|
this.setState({ |
|
voice: null, |
|
}); |
|
}; |
|
|
|
sendFile = () => { |
|
const { image, video, music, document } = this.state; |
|
let now = new Date(); |
|
if (image !== null) { |
|
this.setState((prevState) => ({ |
|
data: { |
|
...prevState.data, |
|
messages: [ |
|
...prevState.data.messages, |
|
{ |
|
id: "m8", |
|
type: "normal", |
|
text: prevState.message, |
|
voice: null, |
|
createdAt: now.toString(), |
|
image: image, |
|
video: null, |
|
document: null, |
|
music: null, |
|
user: { |
|
id: "u1", |
|
name: "علی", |
|
}, |
|
}, |
|
], |
|
}, |
|
})); |
|
this.setState({ |
|
file: null, |
|
image: null, |
|
message: "", |
|
}); |
|
} else if (video !== null) { |
|
this.setState((prevState) => ({ |
|
data: { |
|
...prevState.data, |
|
messages: [ |
|
...prevState.data.messages, |
|
{ |
|
id: "m8", |
|
type: "normal", |
|
text: prevState.message, |
|
voice: null, |
|
createdAt: now.toString(), |
|
image: null, |
|
video: video, |
|
document: null, |
|
music: null, |
|
user: { |
|
id: "u1", |
|
name: "علی", |
|
}, |
|
}, |
|
], |
|
}, |
|
})); |
|
this.setState({ |
|
file: null, |
|
video: null, |
|
message: "", |
|
}); |
|
} else if (music !== null) { |
|
this.setState((prevState) => ({ |
|
data: { |
|
...prevState.data, |
|
messages: [ |
|
...prevState.data.messages, |
|
{ |
|
id: "m8", |
|
text: prevState.message, |
|
type: "normal", |
|
voice: null, |
|
createdAt: now.toString(), |
|
image: null, |
|
video: null, |
|
document: null, |
|
music: music, |
|
user: { |
|
id: "u1", |
|
name: "علی", |
|
}, |
|
}, |
|
], |
|
}, |
|
})); |
|
this.setState({ |
|
file: null, |
|
music: null, |
|
message: "", |
|
}); |
|
} else if (document !== null) { |
|
this.setState((prevState) => ({ |
|
data: { |
|
...prevState.data, |
|
messages: [ |
|
...prevState.data.messages, |
|
{ |
|
id: "m8", |
|
text: prevState.message, |
|
type: "normal", |
|
voice: null, |
|
|
|
createdAt: now.toString(), |
|
image: null, |
|
video: null, |
|
document: document, |
|
music: null, |
|
user: { |
|
id: "u1", |
|
name: "علی", |
|
}, |
|
}, |
|
], |
|
}, |
|
})); |
|
this.setState({ |
|
file: null, |
|
document: null, |
|
message: "", |
|
}); |
|
} |
|
}; |
|
|
|
cancelSendFile = () => { |
|
this.setState({ |
|
file: null, |
|
document: null, |
|
message: "", |
|
image: null, |
|
video: null, |
|
voice: null, |
|
music: null, |
|
}); |
|
}; |
|
|
|
componentDidMount() { |
|
this.props.list({ chatId: this.state.id }); |
|
this.props.info({ id: this.state.id }); |
|
// this.componentDidUpdate(); |
|
} |
|
|
|
componentDidUpdate(prevProps) { |
|
let chatroom = document.getElementById("chatroom"); |
|
chatroom.scrollTop = chatroom.scrollHeight + 40; |
|
|
|
if (prevProps.id !== this.props.id) { |
|
this.props.info({ |
|
id: |
|
window.innerWidth < 1000 |
|
? window.location.href.split("/").pop() * 1 |
|
: this.props.id, |
|
}); |
|
|
|
this.props.list({ |
|
chatId: |
|
window.innerWidth < 1000 |
|
? window.location.href.split("/").pop() * 1 |
|
: this.props.id, |
|
}); |
|
} |
|
} |
|
|
|
randomColor() { |
|
let hex = Math.floor(Math.random() * 0x999999); |
|
let color = "#" + hex.toString(16); |
|
|
|
return color; |
|
} |
|
render() { |
|
const { setPage, chatInfo, messageList: msaster, userId } = this.props; //last |
|
const messageList = msaster.slice(0, this.state.counter); |
|
const last = messageList.slice(-1)[0] || {}; |
|
const userIdx = this.userIdx || {}; |
|
if (Object.keys(userIdx).length == 0) { |
|
chatInfo.users.map( |
|
(e) => (userIdx[e.id] = { ...e, color: this.randomColor() }) |
|
); |
|
this.userIdx = userIdx; |
|
} |
|
|
|
return ( |
|
<> |
|
{window.innerWidth < 1000 ? ( |
|
<div |
|
className="chat-body d-flex flex-column nobar " |
|
onClick={() => this.addcounter("parent")} |
|
> |
|
<div |
|
className="chat-body__content d-flex flex-column nobar" |
|
id="chatroom" |
|
style={{ |
|
paddingTop: 10, |
|
overflowX: "hidden", |
|
overflowY: this.state.file !== null ? "hidden" : "scroll", |
|
paddingBottom: last.action === "keyboard" ? 150 : 10, |
|
}} |
|
> |
|
{chatInfo.users && |
|
messageList.map((message, i) => |
|
this.state.image === null && |
|
this.state.music === null && |
|
this.state.video === null ? ( |
|
<Message |
|
addcounter={() => this.addcounter()} |
|
isActive={message.id == last.id} |
|
prevUserId={i > 0 ? messageList[i - 1].userId : 0} |
|
isSelf={new Set([101, 103, 106, 108, 110]).has( |
|
message.userId * 1 |
|
)} |
|
key={message.id} |
|
file={this.state.image} |
|
document={this.state.document} |
|
message={message} |
|
user={ |
|
userIdx[message.userId] || { |
|
id: 0, |
|
fileId: 0, |
|
name: "null", |
|
} |
|
} |
|
/> |
|
) : null |
|
)} |
|
{this.state.image !== null ? ( |
|
<div className="chat-body__content--preview d-flex"> |
|
<img src={this.state.image} alt="" /> |
|
</div> |
|
) : null} |
|
{this.state.video !== null ? ( |
|
<div className="chat-body__content--preview d-flex"> |
|
<ReactPlayer url={this.state.video} controls /> |
|
</div> |
|
) : null} |
|
{this.state.music !== null ? ( |
|
<div className="chat-body__content--preview d-flex"> |
|
<ReactAudioPlayer src={this.state.music} controls /> |
|
</div> |
|
) : null} |
|
{this.state.document !== null ? ( |
|
<div className="chat-body__content--confirm d-flex"> |
|
<div className="chat-body__content--confirm___box d-flex flex-column"> |
|
<p>{`ارسال (${this.state.document.name}) به ${this.props.info.title}؟`}</p> |
|
<div className="chat-body__content--confirm___box---options d-flex"> |
|
<button |
|
style={{ color: "#00ff00" }} |
|
onClick={() => this.sendFile()} |
|
> |
|
ارسال |
|
</button> |
|
<button |
|
style={{ color: "#ffffff" }} |
|
onClick={() => this.cancelSendFile()} |
|
> |
|
کنسل |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
) : null} |
|
</div> |
|
<div |
|
className="chat-body__footer d-flex nobar d-flex flex-column" |
|
onClick={() => this.addcounter("nothing")} |
|
> |
|
{last.action == "text" ? ( |
|
<ChatInputs |
|
addcounter={() => this.addcounter()} |
|
onStop={this.onStop} |
|
stop={this.stop} |
|
start={this.start} |
|
cancel={this.cancel} |
|
message={this.state.message} |
|
recordState={this.state.voice} |
|
typeText={this.typeText} |
|
sendMessage={this.sendMessage} |
|
addFile={this.addFile} |
|
file={this.state.file} |
|
parent={this} |
|
/> |
|
) : null} |
|
{last.action === "keyboard" ? ( |
|
<Keyboard |
|
options={last.options} |
|
addcounter={() => this.addcounter()} |
|
/> |
|
) : null} |
|
{this.state.emoji ? ( |
|
<div className="chat-body__footer--emoji d-flex flex-column"> |
|
<Emoji typeText={this.typeText} /> |
|
</div> |
|
) : null} |
|
</div> |
|
</div> |
|
) : null} |
|
{window.innerWidth > 1000 ? ( |
|
<div |
|
className="desktop-chat-body d-flex flex-column nobar " |
|
onClick={() => this.addcounter("parent")} |
|
> |
|
<div |
|
className="desktop-chat-body__content d-flex flex-column nobar" |
|
id="chatroom" |
|
style={{ |
|
paddingTop: 10, |
|
overflowX: "hidden", |
|
overflowY: this.state.file !== null ? "hidden" : "scroll", |
|
paddingBottom: last.action === "keyboard" ? 150 : 10, |
|
}} |
|
> |
|
{chatInfo.users && |
|
messageList.map((message, i) => |
|
this.state.image === null && |
|
this.state.music === null && |
|
this.state.video === null ? ( |
|
<Message |
|
addcounter={() => this.addcounter()} |
|
isActive={message.id == last.id} |
|
prevUserId={i > 0 ? messageList[i - 1].userId : 0} |
|
isSelf={new Set([101, 103, 106, 108, 110]).has( |
|
message.userId * 1 |
|
)} |
|
key={message.id} |
|
file={this.state.image} |
|
document={this.state.document} |
|
message={message} |
|
user={ |
|
userIdx[message.userId] || { |
|
id: 0, |
|
fileId: 0, |
|
name: "null", |
|
} |
|
} |
|
/> |
|
) : null |
|
)} |
|
{this.state.image !== null ? ( |
|
<div className="desktop-chat-body__content--preview d-flex"> |
|
<img src={this.state.image} alt="" /> |
|
</div> |
|
) : null} |
|
{this.state.video !== null ? ( |
|
<div className="desktop-chat-body__content--preview d-flex"> |
|
<ReactPlayer url={this.state.video} controls /> |
|
</div> |
|
) : null} |
|
{this.state.music !== null ? ( |
|
<div className="desktop-chat-body__content--preview d-flex"> |
|
<ReactAudioPlayer src={this.state.music} controls /> |
|
</div> |
|
) : null} |
|
{this.state.document !== null ? ( |
|
<div className="desktop-chat-body__content--confirm d-flex"> |
|
<div className="desktop-chat-body__content--confirm___box d-flex flex-column"> |
|
<p>{`ارسال (${this.state.document.name}) به ${this.props.info.title}؟`}</p> |
|
<div className="desktop-chat-body__content--confirm___box---options d-flex"> |
|
<button |
|
style={{ color: "#00ff00" }} |
|
onClick={() => this.sendFile()} |
|
> |
|
ارسال |
|
</button> |
|
<button |
|
style={{ color: "#ffffff" }} |
|
onClick={() => this.cancelSendFile()} |
|
> |
|
کنسل |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
) : null} |
|
</div> |
|
<div |
|
className="desktop-chat-body__footer d-flex nobar d-flex flex-column" |
|
onClick={() => this.addcounter("nothing")} |
|
> |
|
{last.action == "text" ? ( |
|
<ChatInputs |
|
addcounter={() => this.addcounter()} |
|
onStop={this.onStop} |
|
stop={this.stop} |
|
start={this.start} |
|
cancel={this.cancel} |
|
message={this.state.message} |
|
recordState={this.state.voice} |
|
typeText={this.typeText} |
|
sendMessage={this.sendMessage} |
|
addFile={this.addFile} |
|
file={this.state.file} |
|
parent={this} |
|
/> |
|
) : null} |
|
{last.action === "keyboard" ? ( |
|
<Keyboard |
|
options={last.options} |
|
addcounter={() => this.addcounter()} |
|
/> |
|
) : null} |
|
{this.state.emoji ? ( |
|
<div className="desktop-chat-body__footer--emoji d-flex flex-column"> |
|
<Emoji typeText={this.typeText} /> |
|
</div> |
|
) : null} |
|
</div> |
|
</div> |
|
) : null} |
|
</> |
|
); |
|
} |
|
} |
|
export default connect( |
|
(state) => { |
|
return { |
|
chatInfo: state.chat.info, |
|
userId: state.user.isLogin.id, |
|
messageList: state.message.list || [], |
|
last: state.message.list.slice(-1)[0] || {}, |
|
}; |
|
}, |
|
{ info: chat.info, bio: chat.bio } |
|
)(List);
|
|
|