2021-06-18 15:11:54 +10:00
|
|
|
import {
|
|
|
|
|
FormControl,
|
|
|
|
|
InputLabel,
|
|
|
|
|
makeStyles,
|
|
|
|
|
MenuItem,
|
|
|
|
|
Select,
|
|
|
|
|
TextField,
|
|
|
|
|
} from '@material-ui/core';
|
|
|
|
|
import React, { ChangeEvent, useState, KeyboardEvent } from 'react';
|
|
|
|
|
import { Waku, WakuMessage } from 'js-waku';
|
|
|
|
|
import { DirectMessage, encode } from './messages';
|
|
|
|
|
import { DirectMessageContentTopic } from './App';
|
2021-06-24 16:05:22 +10:00
|
|
|
import { encryptMessage } from './crypto';
|
2021-06-18 15:11:54 +10:00
|
|
|
|
|
|
|
|
const useStyles = makeStyles((theme) => ({
|
|
|
|
|
formControl: {
|
|
|
|
|
margin: theme.spacing(1),
|
|
|
|
|
minWidth: 120,
|
|
|
|
|
},
|
|
|
|
|
selectEmpty: {
|
|
|
|
|
marginTop: theme.spacing(2),
|
|
|
|
|
},
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
export interface Props {
|
|
|
|
|
waku: Waku | undefined;
|
|
|
|
|
// address, public key
|
|
|
|
|
recipients: Map<string, string>;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-29 12:10:24 +10:00
|
|
|
export function SendMessage({ waku, recipients }: Props) {
|
2021-06-18 15:11:54 +10:00
|
|
|
const classes = useStyles();
|
|
|
|
|
const [recipient, setRecipient] = useState<string>('');
|
|
|
|
|
const [message, setMessage] = useState<string>();
|
|
|
|
|
|
|
|
|
|
const handleRecipientChange = (
|
|
|
|
|
event: ChangeEvent<{ name?: string; value: unknown }>
|
|
|
|
|
) => {
|
|
|
|
|
setRecipient(event.target.value as string);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleMessageChange = (event: ChangeEvent<HTMLInputElement>) => {
|
|
|
|
|
setMessage(event.target.value);
|
|
|
|
|
};
|
|
|
|
|
|
2021-06-29 12:10:24 +10:00
|
|
|
const items = Array.from(recipients.keys()).map((recipient) => {
|
2021-06-18 15:18:05 +10:00
|
|
|
return (
|
|
|
|
|
<MenuItem key={recipient} value={recipient}>
|
|
|
|
|
{recipient}
|
|
|
|
|
</MenuItem>
|
|
|
|
|
);
|
2021-06-18 15:11:54 +10:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const keyDownHandler = async (event: KeyboardEvent<HTMLInputElement>) => {
|
|
|
|
|
if (
|
|
|
|
|
event.key === 'Enter' &&
|
|
|
|
|
!event.altKey &&
|
|
|
|
|
!event.ctrlKey &&
|
|
|
|
|
!event.shiftKey
|
|
|
|
|
) {
|
|
|
|
|
if (!waku) return;
|
|
|
|
|
if (!recipient) return;
|
|
|
|
|
if (!message) return;
|
2021-06-29 12:10:24 +10:00
|
|
|
const publicKey = recipients.get(recipient);
|
2021-06-18 15:11:54 +10:00
|
|
|
if (!publicKey) return;
|
|
|
|
|
|
|
|
|
|
sendMessage(waku, recipient, publicKey, message, (res) => {
|
|
|
|
|
if (res) {
|
|
|
|
|
console.log('callback called with', res);
|
|
|
|
|
setMessage('');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
style={{
|
|
|
|
|
display: 'flex',
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
flexWrap: 'wrap',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<FormControl className={classes.formControl}>
|
|
|
|
|
<InputLabel id="select-recipient-label">Recipient</InputLabel>
|
|
|
|
|
<Select
|
|
|
|
|
labelId="select-recipient"
|
|
|
|
|
id="select-recipient"
|
|
|
|
|
value={recipient}
|
|
|
|
|
onChange={handleRecipientChange}
|
|
|
|
|
>
|
|
|
|
|
{items}
|
|
|
|
|
</Select>
|
|
|
|
|
</FormControl>
|
|
|
|
|
<TextField
|
|
|
|
|
id="message-input"
|
|
|
|
|
label="Message"
|
|
|
|
|
variant="filled"
|
|
|
|
|
onChange={handleMessageChange}
|
|
|
|
|
onKeyDown={keyDownHandler}
|
|
|
|
|
value={message}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function encodeEncryptedWakuMessage(
|
|
|
|
|
message: string,
|
|
|
|
|
publicKey: string,
|
|
|
|
|
address: string
|
|
|
|
|
): Promise<WakuMessage> {
|
2021-06-24 16:05:22 +10:00
|
|
|
const encryptedMsg = await encryptMessage(publicKey, message);
|
2021-06-18 15:11:54 +10:00
|
|
|
|
|
|
|
|
const directMsg: DirectMessage = {
|
|
|
|
|
toAddress: address,
|
|
|
|
|
encMessage: encryptedMsg,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const payload = encode(directMsg);
|
|
|
|
|
return WakuMessage.fromBytes(payload, DirectMessageContentTopic);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function sendMessage(
|
|
|
|
|
waku: Waku,
|
|
|
|
|
recipientAddress: string,
|
|
|
|
|
recipientPublicKey: string,
|
|
|
|
|
message: string,
|
|
|
|
|
callback: (res: boolean) => void
|
|
|
|
|
) {
|
|
|
|
|
encodeEncryptedWakuMessage(message, recipientPublicKey, recipientAddress)
|
|
|
|
|
.then((msg) => {
|
|
|
|
|
console.log('pushing');
|
|
|
|
|
waku.lightPush
|
|
|
|
|
.push(msg)
|
|
|
|
|
.then((res) => {
|
|
|
|
|
console.log('Message sent', res);
|
|
|
|
|
callback(res ? res.isSuccess : false);
|
|
|
|
|
})
|
|
|
|
|
.catch((e) => {
|
|
|
|
|
console.error('Failed to send message', e);
|
|
|
|
|
callback(false);
|
|
|
|
|
});
|
|
|
|
|
})
|
|
|
|
|
.catch((e) => {
|
|
|
|
|
console.error('Cannot encode & encrypt message', e);
|
|
|
|
|
callback(false);
|
|
|
|
|
});
|
|
|
|
|
}
|