Skip to content

Commit

Permalink
batch send message
Browse files Browse the repository at this point in the history
  • Loading branch information
trazyn committed Sep 1, 2017
1 parent 3e4e31b commit dc18280
Show file tree
Hide file tree
Showing 24 changed files with 718 additions and 193 deletions.
2 changes: 2 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ API from [https://web.wechat.com/](https://web.wechat.com/)
![preview](https://raw.githubusercontent.com/trazyn/weweChat/master/screenshots/pasteconfirmation.png)
- Drag to send file
![preview](https://raw.githubusercontent.com/trazyn/weweChat/master/screenshots/dragdrop.png)
- Batch send message
![preview](https://raw.githubusercontent.com/trazyn/weweChat/master/screenshots/batchsend.png)
- Send GIF emoji
![preview](https://raw.githubusercontent.com/trazyn/weweChat/master/screenshots/sendgif.gif)

Expand Down
8 changes: 8 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ let mainMenu = [
mainWindow.webContents.send('show-search');
}
},
{
label: 'Batch Send Message',
accelerator: 'Cmd+B',
click() {
mainWindow.show();
mainWindow.webContents.send('show-batchsend');
}
},
{
type: 'separator',
},
Expand Down
Binary file added screenshots/batchsend.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ class App extends Component {
stores.chat.toggleConversation(true);
});

// Batch send message
ipcRenderer.on('show-batchsend', () => {
stores.batchsend.toggle(true);
});

// Insert the qq emoji
ipcRenderer.on('show-emoji', () => {
if (this.canisend()) {
Expand Down
2 changes: 1 addition & 1 deletion src/js/components/Loader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import clazz from 'classname';
import './style.global.css';

export default class Button extends Component {
static PropTypes = {
static propTypes = {
show: PropTypes.bool,
fullscreen: PropTypes.bool,
};
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
146 changes: 146 additions & 0 deletions src/js/components/MessageInput/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@

import React, { Component, PropTypes } from 'react';
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: {},
};

isme = (user) => user.UserName === this.props.me.UserName;

async handleEnter(e) {
var message = this.refs.input.value.trim();
var user = this.props.user;
var batch = user.length > 1;

if (!message || e.charCode !== 13) return;

user.map(async e => {
if (this.isme(e)) {
this.props.showMessage('Can\'t send message to yourself.');
return;
}

let res = await this.props.sendMessage(e, {
content: message,
type: 1,
});

this.refs.input.value = '';

if (batch) {
this.props.showMessage(`Send message to ${e.NickName} is ${res ? 'success' : 'failed'}!`);
return;
}

if (!res) {
this.props.showMessage('Failed to send message.');
}
});
}

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 handlePaste(e) {
var args = ipcRenderer.sendSync('file-paste');

if (args.hasImage) {
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.props.process(file);
}
}

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 choice a contact at first.
</div>
<input
id="messageInput"
type="text"
ref="input"
placeholder="Type someting to send..."
readOnly={!canisend}
onPaste={e => this.handlePaste(e)}
onKeyPress={e => this.handleEnter(e)} />

<div className={classes.action}>
<i
id="showUploader"
className="icon-ion-android-attach"
onClick={e => canisend && this.refs.uploader.click()} />
<i
id="showEmoji"
className="icon-ion-ios-heart"
style={{
color: 'red',
}}
onClick={e => canisend && this.toggleEmoji(true)} />

<input
type="file"
ref="uploader"
onChange={e => {
this.props.process(e.target.files[0]);
e.target.value = '';
}}
style={{
display: 'none',
}} />
<Emoji
output={emoji => this.writeEmoji(emoji)}
close={e => setTimeout(() => this.toggleEmoji(false), 100)}
show={this.state.showEmoji} />
</div>
</div>
);
}
}
94 changes: 94 additions & 0 deletions src/js/components/MessageInput/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@

.container {
position: relative;
display: flex;
height: 60px;
align-items: center;
justify-content: space-between;

& input {
height: 60px;
width: 100%;
margin-left: 32px;
line-height: 60px;
border: 0;
padding-right: 17px;
background: 0;
color: #333;
font-size: 14px;
outline: 0;
}

& i {
font-size: 24px;
color: #000;
cursor: pointer;
}

& i:hover {
color: #34b7f1;
}
}

.action {
width: 65px;
margin-right: 17px;
display: flex;
justify-content: space-between;
}

.tips {
position: absolute;
height: 32px;
left: 14px;
top: -32px;
padding: 0 16px;
line-height: 32px;
font-size: 14px;
color: #fff;
background: color(#616161 -alpha(10%));
border-radius: 1px;
opacity: 0;
transform-origin: center bottom;
transition: .15s cubic-bezier(0, 0, .2, 1);
pointer-events: none;
}

.shouldSelectUser:hover .tips {
opacity: 1;
top: calc(-32px - 24px);
}


@media (width <= 800px) {
.container {
height: 46px;

& input {
height: 46px;
margin-left: 20px;
line-height: 46px;
}

& i {
font-size: 16px;
}
}

& .action {
width: 50px;
}

.tips {
height: 24px;
top: -24px;
padding: 0 12px;
line-height: 24px;
font-size: 12px;
}

.shouldSelectUser:hover .tips {
opacity: 1;
top: calc(-24px - 12px);
}
}
2 changes: 1 addition & 1 deletion src/js/components/Snackbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default class Snackbar extends Component {

return (
<div className="Snackbar">
<div className="Snackbar-text">{this.props.text}</div>
<div className="Snackbar-text" dangerouslySetInnerHTML={{__html: this.props.text}} />
<div className="Snackbar-action" onClick={() => this.props.close()}>DONE</div>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions src/js/components/Snackbar/style.global.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
padding-left: 24px;
font-family: 'Roboto';
background-color: #323232;
z-index: 999;
}

.Snackbar-action {
Expand Down
Loading

0 comments on commit dc18280

Please sign in to comment.