123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- var Cycle = require('cyclejs');
- var Rx = Cycle.Rx;
- var RxDOM = require('rx-dom').DOM;
- var h = Cycle.h;
- var hashDriver = require('./drivers/hashDriver');
- var util = require('./util');
- var chat = require('./services/chat');
- var nav = [
- {partial: 'about', name: 'About'},
- {partial: 'chatRoom', name: 'Chat'},
- {partial: 'contribute', name: 'Contribute'}
- ];
- function intent(drivers) {
- var DOM = drivers.DOM;
- return {
- contribute: require('./intents/contribute')(drivers),
- route$: drivers.hash.map(function(route) {
- return route || 'about';
- }),
- chat$: DOM.get('#talk', 'input').map(function(ev) {
- return ev.target.value;
- }).startWith('').shareReplay(1),
- send$: DOM.get('#talk', 'keyup').filter(function(ev) {
- return ev.keyCode == 13 && ev.target.value.trim();
- }).shareReplay(1),
- disconnect$: DOM.get('#disconnect', 'click'),
- username$: DOM.get('#username', 'input').map(function(ev) {
- return ev.target.value;
- }),
- login$: DOM.get('#login-form', 'submit').map(function(ev) {
- ev.preventDefault();
- return true;
- })
- };
- }
- function model(actions) {
- var route$ = actions.route$.shareReplay(1);
- var username$ = actions.login$
- .withLatestFrom(actions.username$, function(submit, username) {
- return username;
- })
- .merge(actions.disconnect$.map(function() { return null; }))
- .startWith(null)
- .shareReplay(1)
- var room$ = route$
- .map(function(url) {
- if(url.startsWith('chatRoom/')) {
- return url.replace('chatRoom/', '');
- }
- else {
- return null;
- }
- })
- .startWith(null)
- .distinctUntilChanged();
- var outgoing$ = util.sync(actions.send$, actions.chat$)
- .map(function(msg) {
- return JSON.stringify({text: msg});
- })
- var results = chat.connect(username$, room$, outgoing$);
- var newRoute$ = results.details$
- .filter(function(params) {
- return params.username != null;
- })
- .map(function(params) {
- return 'chatRoom/'+params.room;
- })
- .distinctUntilChanged()
- var input$ = actions.chat$.merge(actions.send$.map(function() { return '' }));
- var messages$ = results.ws$
- .map(function(message) {
- if(message.kind === 'talk') {
- return message;
- }
- else if(message.kind == "join") {
- return {
- kind: 'join',
- user: message.user,
- message: ' has joined.'
- };
- }
- else if(message.kind == "quit") {
- return {
- kind: 'quit',
- user: message.user,
- message: ' has left.'
- };
- }
- else return null;
- })
- .filter(function(item) {
- return item != null;
- })
- .scan([], function(a, b) {
- a.push(b);
- return a;
- })
- .startWith([])
- return {
- hash: newRoute$,
- DOM: {
- username$: username$,
- room$: room$,
- details$: results.details$,
- route$: route$,
- status$: results.status$,
- error$: results.error$,
- chat$: input$,
- contribute$: actions.contribute.fields$
- }
- };
- }
- function renderLogin(props) {
- var isConnected = props.status === 'connected';
- var content;
- if(!isConnected) {
- content = [ h('a.navbar-link', {href: '#chatRoom'}, ['Play!']) ];
- }
- else {
- content = [
- "Logged in as "+props.username+" — ",
- h('a.navbar-link#disconnect', ['Disconnect'])
- ];
- }
- return h('div', {className: 'navbar-right collapse navbar-collapse'}, [
- h('p.navbar-text', content)
- ]);
- }
- function renderNav(props) {
- return (
- h('nav', {className: 'navbar navbar-inverse navbar-static-top', role: 'navigation'}, [
- h('div.container', [
- h('div.navbar-header', [
- h('span.brand.navbar-brand', ["Game 'n Chat"])
- ]),
- h('ul', {className: 'nav navbar-nav collapse navbar-collapse'}, nav.map(function(item) {
- var link = '#'+item.partial;
- if(item.partial === 'chatRoom' && props.status === 'connected' && props.details.room) {
- link += '/' + props.details.room;
- }
- var className = '';
- if(item.partial == props.route) {
- className = 'active';
- }
- return h('li', {className: className}, [
- h('a', {href: link}, [ item.name ])
- ]);
- })),
- renderLogin(props)
- ]),
- ])
- )
- }
- function renderFooter() {
- return h('footer', [
- h('p', [
- h('a', {href: 'http://twitter.com/pleasantprog', target: '_blank'}, ['@pleasantprog'])
- ])
- ]);
- }
- function renderContainer(props) {
- var route = props.route.replace(/\/.*/, '');
- var content = require('./templates/'+route)(props);
- return h('div.container', [
- h('div.content', [content]),
- renderFooter()
- ]);
- }
- function view(model) {
- return {
- hash: model.hash,
- DOM:
- util.asObject(model.DOM).map(function(model) {
- return h('div', [
- renderNav(model),
- renderContainer(model)
- ]);
- })
- }
- }
- function main(drivers) {
- return view(model(intent(drivers)));
- }
- Cycle.run(main, {
- DOM: Cycle.makeDOMDriver('body'),
- hash: hashDriver
- });
|