Skip to content

Commit 5f4a83b

Browse files
author
James Halliday
committed
browser websocket chat
1 parent 904741a commit 5f4a83b

File tree

5 files changed

+108
-4
lines changed

5 files changed

+108
-4
lines changed

webapp/browser/main.js

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
var wsock = require('websocket-stream')
2+
var router = require('../router.js')
3+
var main = require('main-loop')
4+
var h = require('virtual-dom/h')
5+
var EventEmitter = require('events').EventEmitter
6+
var split = require('split2')
7+
var through = require('through2')
8+
9+
var state = {
10+
path: location.pathname,
11+
messages: []
12+
}
13+
var bus = new EventEmitter
14+
15+
var parts = location.pathname.split('/')
16+
if (parts[1] === 'house' && parts[3] === 'chat') {
17+
var house = parts[2]
18+
var ws = wsock('ws://' + location.host)
19+
bus.on('message', function (msg) {
20+
ws.write(JSON.stringify(msg) + '\n')
21+
})
22+
ws.pipe(split(JSON.parse)).pipe(through.obj(function (row, enc, next) {
23+
state.messages.push(row)
24+
loop.update(state)
25+
next()
26+
}))
27+
}
28+
29+
var loop = main(state, render, require('virtual-dom'))
30+
var content = document.querySelector('#content')
31+
content.replaceChild(loop.target, content.childNodes[0])
32+
33+
var singlePage = require('single-page')
34+
var show = singlePage(function (href) {
35+
state.path = href
36+
loop.update(state)
37+
})
38+
require('catch-links')(window, show)
39+
40+
function render (state) {
41+
var m = router.match(state.path)
42+
if (m) {
43+
m.state = state
44+
m.bus = bus
45+
return m.fn(m)
46+
}
47+
else return h('div', 'not found')
48+
}

webapp/package.json

+7-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,16 @@
77
"body": "^5.1.0",
88
"collect-stream": "^1.0.0",
99
"ecstatic": "^0.8.0",
10-
"routes": "^2.1.0"
10+
"routes": "^2.1.0",
11+
"split2": "^1.0.0",
12+
"through2": "^2.0.0",
13+
"websocket-stream": "^1.5.1"
1114
},
1215
"devDependencies": {},
1316
"scripts": {
14-
"test": "echo \"Error: no test specified\" && exit 1"
17+
"bundle": "browserify browser/main.js > public/bundle.js",
18+
"watch": "watchify browser/main.js -o public/bundle.js -dv",
19+
"start": "node server.js"
1520
},
1621
"author": "",
1722
"license": "ISC"

webapp/public/index.html

+2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ <h1>cyberwizard school</h1>
88
<ul>
99
<a href="/">home</a>
1010
<a href="/apply">apply to be sorted</a>
11+
<a href="/houses">houses</a>
1112
</ul>
1213
<div id="content"></div>
14+
<script src="/bundle.js"></script>
1315
</body>
1416
</html>

webapp/router.js

+31-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ var sorthash = require('./lib/sorthash.js')
44
var houses = require('./lib/houses.json')
55
module.exports = router
66

7+
router.addRoute('/', function (m) {
8+
return h('h1', 'WELCOME')
9+
})
10+
711
router.addRoute('/apply', function (m) {
812
return h('form', { method: 'POST', action: '/apply' }, [
913
h('div', [
@@ -39,11 +43,36 @@ router.addRoute('/houses', function (m) {
3943
}))
4044
})
4145

46+
router.addRoute('/house/:name/chat', function (m) {
47+
return h('div', [
48+
h('h1', m.params.name + ' house chat'),
49+
h('form', { onsubmit: onsubmit }, [
50+
h('input', { type: 'text', name: 'msg' }),
51+
h('input', { type: 'submit', value: 'chat' })
52+
]),
53+
h('div', (m.state.messages || []).map(function (msg) {
54+
return h('div', msg.txt)
55+
}))
56+
])
57+
58+
function onsubmit (ev) {
59+
ev.preventDefault()
60+
var house = m.params.name
61+
var txt = this.elements.msg.value
62+
m.bus.emit('message', {
63+
house: house,
64+
txt: txt
65+
})
66+
}
67+
})
68+
4269
router.addRoute('/house/:name', function (m) {
4370
return h('div', [
4471
h('h1', 'house ' + m.params.name),
45-
h('img', { src: '/' + m.params.name + '.svg' }),
46-
h('div', m.state.students.map(function (s) {
72+
h('a', { href: '/house/' + m.params.name + '/chat' },
73+
h('img', { src: '/' + m.params.name + '.svg' })
74+
),
75+
h('div', (m.state.students || []).map(function (s) {
4776
var name = s.key.split('!')[2]
4877
return h('div', name)
4978
}))

webapp/server.js

+20
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ var level = require('level')
1010
var db = level('students.db', { valueEncoding: 'json' })
1111
var collect = require('collect-stream')
1212
var sorthash = require('./lib/sorthash.js')
13+
var wsock = require('websocket-stream')
1314

1415
var server = http.createServer(function (req, res) {
1516
var m = router.match(req.url)
@@ -67,3 +68,22 @@ var server = http.createServer(function (req, res) {
6768
}
6869
})
6970
server.listen(5000)
71+
72+
var split = require('split2')
73+
var through = require('through2')
74+
var streams = []
75+
76+
wsock.createServer({ server: server }, function (stream) {
77+
streams.push(stream)
78+
stream.on('end', function () {
79+
var ix = streams.indexOf(stream)
80+
streams.splice(ix, 1)
81+
})
82+
stream.pipe(split(JSON.parse)).pipe(through.obj(write))
83+
function write (row, enc, next) {
84+
streams.forEach(function (stream) {
85+
stream.write(JSON.stringify(row) + '\n')
86+
})
87+
next()
88+
}
89+
})

0 commit comments

Comments
 (0)