wewechat++ init
仓库提交至星火社区作品集 Signed-off-by: Riceneeder <86492950+Riceneeder@users.noreply.github.com>
This commit is contained in:
226
src/js/components/MessageInput/index.js
Normal file
226
src/js/components/MessageInput/index.js
Normal file
@@ -0,0 +1,226 @@
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { ipcRenderer } from 'electron';
|
||||
import clazz from 'classname';
|
||||
|
||||
import classes from './style.css';
|
||||
import Emoji from './Emoji';
|
||||
|
||||
export default class MessageInput extends Component {
|
||||
static propTypes = {
|
||||
me: PropTypes.object,
|
||||
sendMessage: PropTypes.func.isRequired,
|
||||
showMessage: PropTypes.func.isRequired,
|
||||
user: PropTypes.array.isRequired,
|
||||
confirmSendImage: PropTypes.func.isRequired,
|
||||
process: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
me: {},
|
||||
};
|
||||
|
||||
canisend() {
|
||||
var user = this.props.user;
|
||||
|
||||
if (
|
||||
true
|
||||
&& user.length === 1
|
||||
&& user.slice(-1).pop().UserName === this.props.me.UserName
|
||||
) {
|
||||
this.props.showMessage('Can\'t send messages to yourself.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async handleEnter(e) {
|
||||
var message = this.refs.input.value.trim();
|
||||
var user = this.props.user;
|
||||
var batch = user.length > 1;
|
||||
|
||||
if (
|
||||
false
|
||||
|| !this.canisend()
|
||||
|| !message
|
||||
|| e.charCode !== 13
|
||||
) return;
|
||||
|
||||
// You can not send message to yourself
|
||||
Promise.all(
|
||||
user.filter(e => e.UserName !== this.props.me.UserName).map(
|
||||
async e => {
|
||||
let res = await this.props.sendMessage(
|
||||
e,
|
||||
{
|
||||
content: message,
|
||||
type: 1,
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
if (!res) {
|
||||
await this.props.showMessage(batch ? `Sending message to ${e.NickName} has failed!` : 'Failed to send message.');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
this.refs.input.value = '';
|
||||
}
|
||||
|
||||
state = {
|
||||
showEmoji: false
|
||||
};
|
||||
|
||||
toggleEmoji(show = !this.state.showEmoji) {
|
||||
this.setState({ showEmoji: show });
|
||||
}
|
||||
|
||||
writeEmoji(emoji) {
|
||||
var input = this.refs.input;
|
||||
|
||||
input.value += `[${emoji}]`;
|
||||
input.focus();
|
||||
}
|
||||
|
||||
async batchProcess(file) {
|
||||
var message;
|
||||
var batch = this.props.user.length > 1;
|
||||
var receiver = this.props.user.filter(e => e.UserName !== this.props.me.UserName);
|
||||
var showMessage = this.props.showMessage;
|
||||
|
||||
if (this.canisend() === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let user of receiver) {
|
||||
if (message) {
|
||||
await this.props.sendMessage(user, message, true)
|
||||
.catch(ex => showMessage(`Sending message to ${user.NickName} has failed!`));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Do not repeat upload file, forward the message to another user
|
||||
message = await this.props.process(file, user);
|
||||
|
||||
if (message === false) {
|
||||
if (batch) {
|
||||
showMessage(`Send message to ${user.NickName} is failed!`);
|
||||
continue;
|
||||
}
|
||||
// In batch mode just show the failed message
|
||||
showMessage('Failed to send image.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async handlePaste(e) {
|
||||
var args = ipcRenderer.sendSync('file-paste');
|
||||
|
||||
if (args.hasImage && this.canisend()) {
|
||||
e.preventDefault();
|
||||
|
||||
if ((await this.props.confirmSendImage(args.filename)) === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
let parts = [
|
||||
new window.Blob([new window.Uint8Array(args.raw.data)], { type: 'image/png' })
|
||||
];
|
||||
let file = new window.File(parts, args.filename, {
|
||||
lastModified: new Date(),
|
||||
type: 'image/png'
|
||||
});
|
||||
|
||||
this.batchProcess(file);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
var input = this.refs.input;
|
||||
|
||||
// When user has changed clear the input
|
||||
if (
|
||||
true
|
||||
&& input
|
||||
&& input.value
|
||||
&& this.props.user.map(e => e.UserName).join() !== nextProps.user.map(e => e.UserName).join()
|
||||
) {
|
||||
input.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
var canisend = !!this.props.user.length;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
clazz(
|
||||
classes.container,
|
||||
this.props.className,
|
||||
{
|
||||
[classes.shouldSelectUser]: !canisend,
|
||||
}
|
||||
)
|
||||
}
|
||||
>
|
||||
<div
|
||||
className={classes.tips}
|
||||
>
|
||||
You should choose a contact first.
|
||||
</div>
|
||||
|
||||
<input
|
||||
id="messageInput"
|
||||
ref="input"
|
||||
type="text"
|
||||
placeholder="Type something to send..."
|
||||
readOnly={!canisend}
|
||||
onPaste={e => this.handlePaste(e)}
|
||||
onKeyPress={e => this.handleEnter(e)}
|
||||
/>
|
||||
|
||||
<div className={classes.action}>
|
||||
<i
|
||||
className="icon-ion-android-attach"
|
||||
id="showUploader"
|
||||
onClick={e => canisend && this.refs.uploader.click()}
|
||||
/>
|
||||
|
||||
<i
|
||||
className="icon-ion-ios-heart"
|
||||
id="showEmoji"
|
||||
onClick={e => canisend && this.toggleEmoji(true)}
|
||||
style={{
|
||||
color: 'red',
|
||||
}}
|
||||
/>
|
||||
|
||||
<input
|
||||
onChange={e => {
|
||||
this.batchProcess(e.target.files[0]);
|
||||
e.target.value = '';
|
||||
}}
|
||||
ref="uploader"
|
||||
style={{
|
||||
display: 'none',
|
||||
}}
|
||||
type="file"
|
||||
/>
|
||||
|
||||
<Emoji
|
||||
close={e => setTimeout(() => this.toggleEmoji(false), 100)}
|
||||
output={emoji => this.writeEmoji(emoji)}
|
||||
show={this.state.showEmoji}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user