Skip to content

Commit a4028bb

Browse files
init
0 parents  commit a4028bb

12 files changed

+7530
-0
lines changed

Diff for: .babelrc

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"presets": [
3+
"es2015",
4+
"react"
5+
]
6+
}

Diff for: .eslintrc

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"extends": ["eslint:recommended", "airbnb"],
3+
"rules": {
4+
"linebreak-style": [
5+
"error",
6+
"windows"
7+
],
8+
"comma-dangle": ["error", {"functions": "never"}],
9+
"no-underscore-dangle": 0,
10+
"no-nested-ternary": 0,
11+
"radix": 0,
12+
"semi": 0,
13+
"react/prop-types": 0,
14+
"jsx-a11y/anchor-is-valid": 0
15+
},
16+
"env": {
17+
"es6": true,
18+
"node": true,
19+
"browser": true
20+
}
21+
}

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

Diff for: client/Root.jsx

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import React from 'react';
2+
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
3+
import injectTapEventPlugin from 'react-tap-event-plugin';
4+
import { BrowserRouter, Route, Switch, Redirect, Link } from 'react-router-dom';
5+
6+
import UserSelection from './UserSelection';
7+
import socket from './socket'
8+
9+
injectTapEventPlugin()
10+
11+
const Navbar = () => (
12+
<ul>
13+
<li> <Link to="/"> { 'Home' } </Link> </li>
14+
<li> <Link to="/1"> { 'Chatroom 1' } </Link> </li>
15+
<li> <Link to="/2"> { 'Chatroom 2' } </Link> </li>
16+
</ul>
17+
)
18+
19+
const Home = () => <h1> { 'Home' } </h1>
20+
const Chatroom = props => <h1> { `$Chatroom ${props.id} ${props.name}`} </h1>
21+
22+
export default class Root extends React.Component {
23+
constructor(props, context) {
24+
super(props, context)
25+
this.state = {
26+
name: '',
27+
isRegisterInProcess: false,
28+
client: socket()
29+
}
30+
31+
this.register = this.register.bind(this)
32+
this.renderChatroomOrRedirect = this.renderChatroomOrRedirect.bind(this)
33+
this.onRegisterResponse = this.onRegisterResponse.bind(this)
34+
this.onEnterUserSelection = this.onEnterUserSelection.bind(this)
35+
}
36+
37+
onRegisterResponse(name) {
38+
this.setState({ isRegisterInProcess: false, name })
39+
}
40+
41+
onEnterUserSelection(renderUserSelection) {
42+
if (this.state.name) {
43+
return <Redirect to="/" />
44+
}
45+
46+
return this.state.isRegisterInProcess
47+
? <h1> Loading </h1>
48+
: renderUserSelection()
49+
}
50+
51+
register(name) {
52+
this.setState({ isRegisterInProcess: true })
53+
this.state.client.register(name, (err) => {
54+
if (err) return this.onRegisterResponse('')
55+
return this.onRegisterResponse(name)
56+
})
57+
}
58+
59+
renderChatroomOrRedirect(renderChatroom) {
60+
return !this.state.name
61+
? <Redirect to="/register" />
62+
: renderChatroom()
63+
}
64+
65+
render() {
66+
return (
67+
<BrowserRouter>
68+
<MuiThemeProvider>
69+
<div>
70+
<Navbar />
71+
<Switch>
72+
<Route
73+
exact
74+
path="/"
75+
component={Home}
76+
/>
77+
<Route
78+
exact
79+
path="/register"
80+
render={
81+
(props) => {
82+
const toHome = () => props.history.push('/')
83+
return this.onEnterUserSelection(() => (
84+
<UserSelection
85+
close={toHome}
86+
register={name => this.register(name, toHome)}
87+
/>
88+
))
89+
}
90+
}
91+
/>
92+
<Route
93+
exact
94+
path="/1"
95+
render={() => this.renderChatroomOrRedirect(() => <Chatroom id="1" />)}
96+
/>
97+
<Route
98+
exact
99+
path="/2"
100+
render={() => this.renderChatroomOrRedirect(() => <Chatroom id="2" />)}
101+
/>
102+
</Switch>
103+
</div>
104+
</MuiThemeProvider>
105+
</BrowserRouter>
106+
)
107+
}
108+
}

Diff for: client/UserSelection.jsx

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React from 'react';
2+
import Dialog from 'material-ui/Dialog';
3+
import FlatButton from 'material-ui/FlatButton';
4+
import TextField from 'material-ui/TextField';
5+
6+
export default class UserSelection extends React.Component {
7+
constructor(props) {
8+
super(props)
9+
this.state = {
10+
input: ''
11+
}
12+
13+
this.handleInput = this.handleInput.bind(this)
14+
this.handleOk = this.handleOk.bind(this)
15+
}
16+
17+
handleInput(e) {
18+
this.setState({ input: e.target.value })
19+
}
20+
21+
22+
handleOk() {
23+
this.props.register(this.state.input)
24+
}
25+
26+
render() {
27+
const actions = [
28+
<FlatButton
29+
label="Cancel"
30+
primary
31+
onClick={this.props.close}
32+
/>,
33+
<FlatButton
34+
label="Submit"
35+
primary
36+
keyboardFocused
37+
onClick={this.handleOk}
38+
/>
39+
]
40+
41+
return (
42+
<Dialog
43+
title="What's your name?"
44+
actions={actions}
45+
modal={false}
46+
open
47+
onRequestClose={this.props.close}
48+
>
49+
<TextField
50+
hintText="Enter your name."
51+
floatingLabelText="Enter your name."
52+
value={this.state.input}
53+
onChange={this.handleInput}
54+
/>
55+
</Dialog>
56+
)
57+
}
58+
}

Diff for: client/index.jsx

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
4+
import Root from './Root';
5+
6+
ReactDOM.render(
7+
<Root />,
8+
document.getElementById('root')
9+
)
10+
11+
if (module.hot) {
12+
module.hot.accept('./Root', () => {
13+
// eslint-disable-next-line
14+
const NextRoot = require('./Root').default
15+
ReactDOM.render(
16+
<NextRoot />,
17+
document.getElementById('root')
18+
)
19+
})
20+
}

Diff for: client/socket.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
const io = require('socket.io-client')
2+
3+
export default function(args) {
4+
const socket = io.connect('http://localhost:3000')
5+
6+
let connected = function() {}
7+
let userJoined = function() {}
8+
let userLeft = function() {}
9+
10+
function setConnectedCb(cb) {
11+
connected = cb
12+
}
13+
14+
function setUserJoinedCb(cb) {
15+
userJoined = cb
16+
}
17+
18+
function setUserLeftCb(cb) {
19+
userLeft = cb
20+
}
21+
22+
socket.on('connected', connected)
23+
socket.on('userJoined', userJoined)
24+
socket.on('userLeft', userLeft)
25+
26+
socket.on('error', function(err) {
27+
console.log('received socket error:')
28+
console.log(err)
29+
})
30+
31+
function register(name, cb) {
32+
socket.emit('register', name, cb)
33+
}
34+
35+
function join(chatroomId, cb) {
36+
socket.emit('join', chatroomId, cb)
37+
}
38+
39+
function leave(chatroomId, cb) {
40+
socket.emit('leave', chatroomId, cb)
41+
}
42+
43+
function message(chatroomId, message, cb) {
44+
socket.emit('message', { chatroomId, message }, cb)
45+
}
46+
47+
return { register, join, leave, message, setConnectedCb, setUserJoinedCb, setUserLeftCb }
48+
}
49+

0 commit comments

Comments
 (0)