diff --git a/client/src/js/actions/route.js b/client/src/js/actions/route.js new file mode 100644 index 00000000..858a8f69 --- /dev/null +++ b/client/src/js/actions/route.js @@ -0,0 +1,7 @@ +var Reflux = require('reflux'); + +var routeActions = Reflux.createActions([ + 'navigate' +]); + +module.exports = routeActions; \ No newline at end of file diff --git a/client/src/js/actions/tab.js b/client/src/js/actions/tab.js index f14eb391..738eb08c 100644 --- a/client/src/js/actions/tab.js +++ b/client/src/js/actions/tab.js @@ -1,7 +1,13 @@ var Reflux = require('reflux'); +var routeActions = require('./route'); + var tabActions = Reflux.createActions([ 'select' ]); +tabActions.select.preEmit = function() { + routeActions.navigate('app'); +}; + module.exports = tabActions; \ No newline at end of file diff --git a/client/src/js/app.js b/client/src/js/app.js index 28d1d1e8..c41ecd0f 100644 --- a/client/src/js/app.js +++ b/client/src/js/app.js @@ -7,6 +7,7 @@ require('./irc'); var socket = require('./socket'); var util = require('./util'); var App = require('./components/App.jsx'); +var Connect = require('./components/Connect.jsx'); var Chat = require('./components/Chat.jsx'); var Settings = require('./components/Settings.jsx'); var tabActions = require('./actions/tab'); @@ -19,11 +20,11 @@ var nick = 'test' + Math.floor(Math.random() * 99999); socket.on('connect', function() { socket.send('uuid', uuid); - serverActions.connect('irc.freenode.net', nick, 'username', true, 'Freenode'); + /*serverActions.connect('irc.freenode.net', nick, 'username', true, 'Freenode'); serverActions.connect('irc.quakenet.org', nick, 'username', false, 'QuakeNet'); channelActions.join(['#stuff'], 'irc.freenode.net'); - channelActions.join(['#herp'], 'irc.quakenet.org'); + channelActions.join(['#herp'], 'irc.quakenet.org');*/ }); socket.on('error', function(error) { @@ -32,6 +33,7 @@ socket.on('error', function(error) { var routes = ( + diff --git a/client/src/js/components/App.jsx b/client/src/js/components/App.jsx index de5803c8..0f438d97 100644 --- a/client/src/js/components/App.jsx +++ b/client/src/js/components/App.jsx @@ -1,9 +1,22 @@ var React = require('react'); -var RouteHandler = require('react-router').RouteHandler; +var Reflux = require('reflux'); +var Router = require('react-router'); +var RouteHandler = Router.RouteHandler; +var Navigation = Router.Navigation; var TabList = require('./TabList.jsx'); +var routeActions = require('../actions/route'); var App = React.createClass({ + mixins: [ + Navigation, + Reflux.listenTo(routeActions.navigate, 'navigate') + ], + + navigate: function(path) { + this.transitionTo(path); + }, + render: function() { return (
diff --git a/client/src/js/components/Connect.jsx b/client/src/js/components/Connect.jsx new file mode 100644 index 00000000..d34ea21f --- /dev/null +++ b/client/src/js/components/Connect.jsx @@ -0,0 +1,45 @@ +var React = require('react'); +var _ = require('lodash'); + +var serverActions = require('../actions/server'); +var channelActions = require('../actions/channel'); + +var Connect = React.createClass({ + handleSubmit: function(e) { + e.preventDefault(); + + var name = e.target.name.value.trim(); + var address = e.target.address.value.trim(); + var ssl = e.target.ssl.checked; + var nick = e.target.nick.value.trim(); + var username = e.target.username.value.trim(); + var channels = _.filter(_.map(e.target.channels.value.split(','), _.trim)); + + if (address.indexOf('.') > 0 && nick && username) { + serverActions.connect(address, nick, username, ssl, name); + + if (channels.length > 0) { + channelActions.join(channels, address); + } + } + }, + + render: function() { + return ( +
+
+

Connect

+ + + + + + + +
+
+ ); + } +}); + +module.exports = Connect; \ No newline at end of file diff --git a/client/src/js/components/MessageInput.jsx b/client/src/js/components/MessageInput.jsx index ea28d007..3e75f2f9 100644 --- a/client/src/js/components/MessageInput.jsx +++ b/client/src/js/components/MessageInput.jsx @@ -4,6 +4,7 @@ var Reflux = require('reflux'); var selectedTabStore = require('../stores/selectedTab'); var messageActions = require('../actions/message'); var channelActions = require('../actions/channel'); +var tabActions = require('../actions/tab'); function dispatchCommand(cmd, channel, server) { var params = cmd.slice(1).split(' '); @@ -12,6 +13,7 @@ function dispatchCommand(cmd, channel, server) { case 'join': if (params[1]) { channelActions.join([params[1]], server); + tabActions.select(server, params[1]); } break; diff --git a/client/src/js/components/TabList.jsx b/client/src/js/components/TabList.jsx index 38ba0835..a7436f57 100644 --- a/client/src/js/components/TabList.jsx +++ b/client/src/js/components/TabList.jsx @@ -7,6 +7,7 @@ var privateChatStore = require('../stores/privateChat'); var serverStore = require('../stores/server'); var selectedTabStore = require('../stores/selectedTab'); var tabActions = require('../actions/tab'); +var routeActions = require('../actions/route'); var TabList = React.createClass({ mixins: [ @@ -25,6 +26,14 @@ var TabList = React.createClass({ }; }, + handleConnectClick: function() { + routeActions.navigate('connect'); + }, + + handleSettingsClick: function() { + routeActions.navigate('settings'); + }, + render: function() { var self = this; var tabClass; @@ -85,10 +94,10 @@ var TabList = React.createClass({ return (
- + {tabs}
- +
); diff --git a/client/src/js/stores/channel.js b/client/src/js/stores/channel.js index c18517d2..1d70e0dc 100644 --- a/client/src/js/stores/channel.js +++ b/client/src/js/stores/channel.js @@ -82,6 +82,7 @@ var channelStore = Reflux.createStore({ init: function() { this.listenToMany(actions); this.listenTo(serverActions.connect, 'addServer'); + this.listenTo(serverActions.load, 'loadServers'); }, part: function(partChannels, server) { @@ -99,8 +100,10 @@ var channelStore = Reflux.createStore({ }, removeUser: function(user, server, channel) { - _.remove(channels[server][channel].users, { nick: user }); - this.trigger(channels); + if (channels[server][channel]) { + _.remove(channels[server][channel].users, { nick: user }); + this.trigger(channels); + } }, removeUserAll: function(user, server) { @@ -182,6 +185,15 @@ var channelStore = Reflux.createStore({ } }, + loadServers: function(storedServers) { + _.each(storedServers, function(server) { + if (!(server.address in channels)) { + channels[server.address] = {}; + } + }); + this.trigger(channels); + }, + getChannels: function(server) { return channels[server]; }, diff --git a/client/src/js/stores/server.js b/client/src/js/stores/server.js index c5c4c732..59b72aa4 100644 --- a/client/src/js/stores/server.js +++ b/client/src/js/stores/server.js @@ -2,6 +2,7 @@ var Reflux = require('reflux'); var _ = require('lodash'); var actions = require('../actions/server'); +var tabActions = require('../actions/tab'); var servers = {}; @@ -11,13 +12,20 @@ var serverStore = Reflux.createStore({ }, connect: function(server, nick, username, tls, name) { + var i = server.indexOf(':'); + if (i > 0) { + server = server.slice(0, i); + } + servers[server] = { address: server, nick: nick, username: username, name: name || server }; + this.trigger(servers); + tabActions.select(server); }, load: function(storedServers) { diff --git a/client/src/style.css b/client/src/style.css index 2c4e6cbe..5c945cc6 100644 --- a/client/src/style.css +++ b/client/src/style.css @@ -89,6 +89,62 @@ p { width: 100px; } +.connect { + display: flex; + justify-content: center; + align-items: center; + position: fixed; + top: 0; + left: 200px; + right: 0; + bottom: 0; +} + +.connect-form h1 { + font: 32px Montserrat, sans-serif; + margin-bottom: 15px; + text-align: center; +} + +.connect-form input { + display: block; + margin: 5px 0px; + padding: 10px; + border: none; +} + +.connect-form input[type="submit"], +.connect-form input[type="text"] { + width: 200px; +} + +.connect-form input[type="submit"] { + height: 50px; + font-family: Montserrat, sans-serif; + background: #6BB758; + color: #FFF; + cursor: pointer; +} + +.connect-form input[type="submit"]:hover { + background: #7BBF6A; +} + +.connect-form input[type="submit"]:active { + background: #6BB758; +} + +.connect-form input[type="checkbox"] { + display: inline-block; + margin: 15px 10px; + margin-left: 0; + vertical-align: center; +} + +.connect-form label { + color: #333; +} + .chat-title-bar { font-family: Montserrat, sans-serif; position: fixed; diff --git a/message_handler.go b/message_handler.go index fb77edf4..9ac23673 100644 --- a/message_handler.go +++ b/message_handler.go @@ -24,19 +24,26 @@ func handleMessages(irc *IRC, session *Session) { case JOIN: user := msg.Prefix + var channel string + + if len(msg.Params) > 0 { + channel = msg.Params[0] + } else { + channel = msg.Trailing + } session.sendJSON("join", Join{ Server: irc.Host, User: user, - Channels: msg.Params, + Channels: []string{channel}, }) - channelStore.AddUser(user, irc.Host, msg.Params[0]) + channelStore.AddUser(user, irc.Host, channel) if user == irc.nick { session.user.AddChannel(storage.Channel{ Server: irc.Host, - Name: msg.Params[0], + Name: channel, }) }