Skip to content

Commit 1c0b4c6

Browse files
committed
init
0 parents  commit 1c0b4c6

22 files changed

Lines changed: 803 additions & 0 deletions

.editorconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# http://editorconfig.org
2+
3+
root = true
4+
5+
[*]
6+
charset = utf-8
7+
end_of_line = lf
8+
insert_final_newline = true
9+
trim_trailing_whitespace = true
10+
indent_style = space
11+
indent_size = 2

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
*.log
3+
.DS_Store
4+
5+
dist

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
```shell
2+
$ npm install
3+
$ npm start
4+
```

package.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "irc",
3+
"version": "0.0.0",
4+
"description": "",
5+
"private": true,
6+
"scripts": {
7+
"start": "nw"
8+
},
9+
"main": "src/index.html",
10+
"author": "",
11+
"license": "MIT",
12+
"dependencies": {
13+
"classnames": "^1.1.4",
14+
"flux": "^2.0.1",
15+
"immutable": "^3.6.4",
16+
"keymirror": "^0.1.1",
17+
"nw": "^0.12.0",
18+
"object-assign": "^2.0.0",
19+
"react": "^0.13.0",
20+
"slate-irc": "^0.8.1"
21+
},
22+
"devDependencies": {
23+
"babel": "^4.7.12"
24+
}
25+
}

src/index.html

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
6+
<title>IRC</title>
7+
<meta name="description" content="">
8+
<meta name="viewport" content="width=device-width, initial-scale=1">
9+
10+
<link rel="shortcut icon" href="./favicon.ico">
11+
<link rel="stylesheet" href="static/reset.css">
12+
<link rel="stylesheet" href="static/style.css">
13+
</head>
14+
<body>
15+
<div id="main"></div>
16+
<script>
17+
// Prevents "document is not defined" error in React
18+
// http://stackoverflow.com/questions/25402492/nw-reactjs-requring-in-multiple-files-does-not-work
19+
global.document = window.document;
20+
global.navigator = window.navigator;
21+
22+
require('babel/register');
23+
require('./js/main');
24+
</script>
25+
</body>
26+
</html>

src/js/actions/channel-actions.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import ircDispatcher from '../dispatchers/irc-dispatcher';
2+
import ActionTypes from '../constants/action-types';
3+
4+
module.exports = {
5+
requestJoinChannel({channelName}) {
6+
ircDispatcher.dispatch({
7+
type: ActionTypes.REQUEST_JOIN_CHANNEL,
8+
channelName
9+
})
10+
},
11+
12+
selectChannel({channelName}) {
13+
ircDispatcher.dispatch({
14+
type: ActionTypes.SELECT_CHANNEL,
15+
channelName
16+
});
17+
},
18+
19+
receiveMessage({channel, from, message, when}) {
20+
ircDispatcher.dispatch({
21+
type: ActionTypes.RECEIVE_MESSAGE,
22+
channel, from, message, when
23+
});
24+
}
25+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import ircDispatcher from '../dispatchers/irc-dispatcher';
2+
import ActionTypes from '../constants/action-types';
3+
4+
module.exports = {
5+
requestConnection({realName, nickname, password, server, port}) {
6+
ircDispatcher.dispatch({
7+
type: ActionTypes.REQUEST_CONNECTION,
8+
realName, nickname, password, server, port
9+
})
10+
}
11+
};

src/js/components/channel-list.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React from 'react';
2+
import { addons } from 'react/addons';
3+
import Immutable from 'immutable';
4+
import classNames from 'classnames';
5+
import ChannelStore from '../stores/channel-store';
6+
import ChannelActions from '../actions/channel-actions';
7+
8+
const component = React.createClass({
9+
mixins: [addons.PureRenderMixin],
10+
11+
componentWillMount() {
12+
ChannelStore.addChangeListener(this._onChange);
13+
},
14+
15+
getInitialState() {
16+
return {
17+
channels: Immutable.List(),
18+
selectedChannel: {}
19+
};
20+
},
21+
22+
_onChange() {
23+
this.setState({
24+
channels: ChannelStore.getChannels(),
25+
selectedChannel: ChannelStore.getSelectedChannel()
26+
});
27+
},
28+
29+
selectChannel(channelName) {
30+
ChannelActions.selectChannel({ channelName });
31+
},
32+
33+
render() {
34+
const channelElements = this.state.channels.sort().map((channel, i) => {
35+
const classes = classNames({
36+
'channel-list-item': true,
37+
'is-selected': channel.name === this.state.selectedChannel.name
38+
});
39+
40+
return (
41+
<li className={classes}
42+
key={i}
43+
onClick={this.selectChannel.bind(this, channel.name)}>{channel.name}</li>
44+
);
45+
});
46+
47+
return (
48+
<ul className="scrolling-panel channel-list">
49+
{channelElements.toArray()}
50+
</ul>
51+
);
52+
}
53+
});
54+
55+
module.exports = component;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from 'react';
2+
import { addons } from 'react/addons';
3+
4+
const component = React.createClass({
5+
mixins: [addons.PureRenderMixin],
6+
7+
getInitialState() {
8+
return {};
9+
},
10+
11+
handleFormSubmission(event) {
12+
event.preventDefault();
13+
// TODO: fire action
14+
},
15+
16+
render() {
17+
return (
18+
<form className="form-panel" onSubmit={this.handleFormSubmission}>
19+
<input type="text"
20+
placeholder="new message"
21+
required />
22+
</form>
23+
);
24+
}
25+
});
26+
27+
module.exports = component;
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import React from 'react';
2+
import { addons } from 'react/addons';
3+
import ConnectionActions from '../actions/connection-actions';
4+
5+
const component = React.createClass({
6+
mixins: [addons.PureRenderMixin],
7+
8+
getInitialState() {
9+
return {isConnecting: false};
10+
},
11+
12+
handleChange(key, event) {
13+
this.setState({
14+
[key]: event.target.value
15+
});
16+
},
17+
18+
handleFormSubmission(event) {
19+
event.preventDefault();
20+
this.setState({isConnecting: true});
21+
22+
const { realName, nickname, password, server, port } = this.state;
23+
ConnectionActions.requestConnection({
24+
realName, nickname, password, server, port: parseInt(port, 10)
25+
});
26+
},
27+
28+
render() {
29+
const inputGroupClass = 'input-group';
30+
const serverOptions = ['chat.freenode.net'];
31+
32+
return (
33+
<form className="connection-creator" onSubmit={this.handleFormSubmission}>
34+
<div className={inputGroupClass}>
35+
<label>Real Name</label>
36+
<input type="text"
37+
autoFocus
38+
required
39+
onChange={this.handleChange.bind(this, 'realName')} />
40+
</div>
41+
42+
<div className={inputGroupClass}>
43+
<label>Nickname</label>
44+
<input type="text"
45+
required
46+
onChange={this.handleChange.bind(this, 'nickname')} />
47+
</div>
48+
49+
<div className={inputGroupClass}>
50+
<label>Password</label>
51+
<input type="password"
52+
onChange={this.handleChange.bind(this, 'password')} />
53+
</div>
54+
55+
<div className={inputGroupClass}>
56+
<label>Server</label>
57+
<select required
58+
onChange={this.handleChange.bind(this, 'server')}>
59+
<option value=""></option>
60+
{serverOptions.map((n, i) => {
61+
return <option value={n} key={i}>{n}</option>
62+
})}
63+
</select>
64+
</div>
65+
66+
<div className={inputGroupClass}>
67+
<label>Port</label>
68+
<input type="number"
69+
required
70+
onChange={this.handleChange.bind(this, 'port')} />
71+
</div>
72+
73+
<input type="submit" disabled={this.state.isConnecting} />
74+
</form>
75+
);
76+
}
77+
});
78+
79+
module.exports = component;

0 commit comments

Comments
 (0)