commit
8a5bbff725
|
@ -28,7 +28,7 @@ function isSpotifyLink(text) {
|
|||
|
||||
// https://gist.github.com/takien/4077195#
|
||||
function getYoutubeId(url) {
|
||||
var ID = '';
|
||||
let ID = '';
|
||||
url = url.replace(/(>|<)/gi,'').split(/(vi\/|v=|\/v\/|youtu\.be\/|\/embed\/)/);
|
||||
if(url[2] !== undefined) {
|
||||
ID = url[2].split(/[^0-9a-z_\-]/i);
|
||||
|
@ -45,12 +45,12 @@ const MessageRender = ({ message }) => (
|
|||
message[2] === "`" && SyntaxLookup[message.slice(0,2)]
|
||||
? <SyntaxHighlighter language={SyntaxLookup[message.slice(0,2)]} style={atomDark}>{message.slice(3)}</SyntaxHighlighter>
|
||||
: <Linkify><span style={{ wordWrap: 'break-word', whiteSpace: 'pre-line' }}>{message}</span></Linkify>
|
||||
)
|
||||
);
|
||||
class ChatBox extends PureComponent {
|
||||
|
||||
state = {
|
||||
imgUrl: null
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { message } = this.props;
|
||||
|
@ -66,7 +66,7 @@ class ChatBox extends PureComponent {
|
|||
const imgUrl = URL.createObjectURL(blob);
|
||||
const image = `data:image/png;base64,${content.toString('base64')}`;
|
||||
this.setState({ imgUrl });
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { username, message, pubkey } = this.props;
|
||||
|
@ -101,7 +101,7 @@ class ChatBox extends PureComponent {
|
|||
/>
|
||||
</ListItem>
|
||||
}
|
||||
{!!imgUrl && <img src={imgUrl} alt='ipfs-image' style={{ width: '100%' }}/>}
|
||||
{!!imgUrl && <img src={imgUrl} alt='ipfs' style={{ width: '100%' }}/>}
|
||||
</Fragment>
|
||||
)
|
||||
};
|
||||
|
|
|
@ -3,10 +3,16 @@ import React, { Fragment, PureComponent, createRef } from 'react';
|
|||
import { Formik } from 'formik';
|
||||
import autoscroll from 'autoscroll-react';
|
||||
import List from '@material-ui/core/List';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import ListItemAvatar from '@material-ui/core/ListItemAvatar';
|
||||
import Avatar from '@material-ui/core/Avatar';
|
||||
import ListItemText from '@material-ui/core/ListItemText';
|
||||
import Divider from '@material-ui/core/Divider';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Dropzone from 'react-dropzone';
|
||||
import Jazzicon, { jsNumberForAddress } from 'react-jazzicon';
|
||||
|
||||
import ChatBox from './ChatBox';
|
||||
import ChatHeader from './ChatHeader';
|
||||
import { uploadFileAndSend } from '../utils/ipfs';
|
||||
|
@ -32,7 +38,7 @@ class WhoIsTyping extends PureComponent {
|
|||
const userList = this.whoIsTyping();
|
||||
return (
|
||||
<div>
|
||||
{!userList.length ? "" : userList.join(',' ) + " is typing"}
|
||||
{!userList.length ? "" : `${userList.join(',')} is typing`}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -45,8 +51,8 @@ function onDrop(acceptedFiles, rejectedFiles, ipfs, sendMessage) {
|
|||
|
||||
const keyDownHandler = (e, typingEvent, setValue, value) => {
|
||||
if(e.shiftKey && e.keyCode === 13) {
|
||||
e.preventDefault()
|
||||
const cursor = e.target.selectionStart
|
||||
e.preventDefault();
|
||||
const cursor = e.target.selectionStart;
|
||||
const newValue = `${value.slice(0, cursor)}\n${value.slice(cursor)}`;
|
||||
setValue('chatInput', newValue);
|
||||
}
|
||||
|
@ -56,85 +62,102 @@ const keyDownHandler = (e, typingEvent, setValue, value) => {
|
|||
form.dispatchEvent(new Event("submit"));
|
||||
}
|
||||
typingEvent(e)
|
||||
}
|
||||
};
|
||||
|
||||
const AutoScrollList = autoscroll(List);
|
||||
const formStyle = { display: 'flex', justifyContent: 'center', alignItems: 'center', flexBasis: '10%' };
|
||||
const listStyle = { overflow: 'scroll', flexBasis: '76%' };
|
||||
const listStyle = { overflowY: 'auto', flexBasis: '76%', position: 'absolute', top: '72px', left: 0, right: 0, bottom: '67px' };
|
||||
const ChatRoomForm = createRef();
|
||||
const ChatRoom = ({ messages, sendMessage, currentChannel, usersTyping, typingEvent, channelUsers, allUsers, ipfs }) => (
|
||||
<div style={{ height: '100vh' }}>
|
||||
<Dropzone
|
||||
onDrop={(a, r) => { onDrop(a,r,ipfs,sendMessage) } }
|
||||
disableClick
|
||||
style={{ position: 'relative', height: '100%' }}
|
||||
activeStyle={{ backgroundColor: 'grey', outline: '5px dashed lightgrey', alignSelf: 'center', outlineOffset: '-10px' }}>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
justify="flex-start"
|
||||
alignItems="stretch"
|
||||
style={{ height: '100%' }}
|
||||
>
|
||||
<ChatHeader currentChannel={currentChannel}/>
|
||||
<Divider />
|
||||
<AutoScrollList style={listStyle}>
|
||||
{messages[currentChannel] && messages[currentChannel].map((message) => (
|
||||
<Fragment key={message.data.payload}>
|
||||
<ChatBox {...message} ipfs={ipfs} />
|
||||
<li>
|
||||
<Divider />
|
||||
</li>
|
||||
</Fragment>
|
||||
))}
|
||||
</AutoScrollList>
|
||||
<Formik
|
||||
initialValues={{ chatInput: '' }}
|
||||
onSubmit={(values, { setSubmitting, resetForm }) => {
|
||||
const { chatInput } = values;
|
||||
sendMessage(chatInput);
|
||||
resetForm();
|
||||
setSubmitting(false);
|
||||
}}
|
||||
<Grid container style={{ height: '100vh'}}>
|
||||
<Grid xs={8} item >
|
||||
<Dropzone
|
||||
onDrop={(a, r) => { onDrop(a,r,ipfs,sendMessage) } }
|
||||
disableClick
|
||||
style={{ position: 'relative', height: '100%' }}
|
||||
activeStyle={{ backgroundColor: 'grey', outline: '5px dashed lightgrey', alignSelf: 'center', outlineOffset: '-10px' }}>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
justify="flex-start"
|
||||
alignItems="stretch"
|
||||
style={{ height: '100%' }}
|
||||
>
|
||||
{({
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
setFieldValue
|
||||
}) => (
|
||||
<div>
|
||||
<form onSubmit={handleSubmit} style={formStyle} ref={ChatRoomForm}>
|
||||
<TextField
|
||||
id="chatInput"
|
||||
multiline
|
||||
style={{ width: 'auto', flexGrow: '0.95', margin: '2px 0 0 0' }}
|
||||
label="Type a message..."
|
||||
type="text"
|
||||
name="chatInput"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
onChange={handleChange}
|
||||
onKeyDown={(e) => keyDownHandler(e, typingEvent, setFieldValue, values.chatInput)}
|
||||
onBlur={handleBlur}
|
||||
value={values.chatInput || ''}
|
||||
/>
|
||||
{errors.chatInput && touched.chatInput && errors.chatInput}
|
||||
</form>
|
||||
<WhoIsTyping
|
||||
currentChannel={currentChannel}
|
||||
usersTyping={usersTyping}
|
||||
users={allUsers} />
|
||||
</div>
|
||||
)}
|
||||
</Formik>
|
||||
</Grid>
|
||||
</Dropzone>
|
||||
</div>
|
||||
<ChatHeader currentChannel={currentChannel}/>
|
||||
<Divider />
|
||||
<AutoScrollList style={listStyle}>
|
||||
{messages[currentChannel] && messages[currentChannel].map((message) => (
|
||||
<Fragment key={message.data.payload}>
|
||||
<ChatBox {...message} ipfs={ipfs} />
|
||||
<li>
|
||||
<Divider />
|
||||
</li>
|
||||
</Fragment>
|
||||
))}
|
||||
</AutoScrollList>
|
||||
<Formik
|
||||
initialValues={{ chatInput: '' }}
|
||||
onSubmit={(values, { setSubmitting, resetForm }) => {
|
||||
const { chatInput } = values;
|
||||
sendMessage(chatInput);
|
||||
resetForm();
|
||||
setSubmitting(false);
|
||||
}}
|
||||
>
|
||||
{({
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
setFieldValue
|
||||
}) => (
|
||||
<div className="chat-input" style={{position: 'absolute', bottom: 0, left: 0, right: 0, paddingBottom: 10}}>
|
||||
<form onSubmit={handleSubmit} style={formStyle} ref={ChatRoomForm}>
|
||||
<TextField
|
||||
id="chatInput"
|
||||
multiline
|
||||
style={{ width: 'auto', flexGrow: '0.95', margin: '2px 0 0 0' }}
|
||||
label="Type a message..."
|
||||
type="text"
|
||||
name="chatInput"
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
onChange={handleChange}
|
||||
onKeyDown={(e) => keyDownHandler(e, typingEvent, setFieldValue, values.chatInput)}
|
||||
onBlur={handleBlur}
|
||||
value={values.chatInput || ''}
|
||||
/>
|
||||
{errors.chatInput && touched.chatInput && errors.chatInput}
|
||||
</form>
|
||||
<WhoIsTyping
|
||||
currentChannel={currentChannel}
|
||||
usersTyping={usersTyping}
|
||||
users={allUsers} />
|
||||
</div>
|
||||
)}
|
||||
</Formik>
|
||||
</Grid>
|
||||
</Dropzone>
|
||||
</Grid>
|
||||
<Grid xs={4} item style={{overflow: 'auto'}}>
|
||||
<List>
|
||||
{Object.keys(channelUsers).map(user => (
|
||||
<ListItem button key={user}>
|
||||
<span className="dot" style={{"height": "10px", "width": "11px", "background-color": (allUsers[user].online ? "lightgreen" : "lightgrey"), "border-radius": "50%", "margin-right": "10px"}}/>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
<Jazzicon diameter={40} seed={jsNumberForAddress(user)} />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={allUsers[user].username} />
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
export default ChatRoom;
|
||||
|
|
|
@ -4,7 +4,6 @@ import StatusJS from 'status-js-api';
|
|||
import IPFS from 'ipfs';
|
||||
import { isNil } from 'lodash';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import routes from '../constants/routes';
|
||||
import ChatRoom from './ChatRoom';
|
||||
import ContextPanel from './ContextPanel';
|
||||
import Login from './Login';
|
||||
|
@ -57,7 +56,7 @@ export default class Home extends PureComponent<Props> {
|
|||
this.keyringController.exportAccount(account)
|
||||
.then(key => { status.connect(URL, `0x${key}`) })
|
||||
.then(() => { this.onConnect() })
|
||||
}
|
||||
};
|
||||
|
||||
onConnect = () => {
|
||||
const { currentChannel } = this.state;
|
||||
|
|
Loading…
Reference in New Issue