From 1c7d4f2396b37b499aa9318cd9dcf2e189da4e23 Mon Sep 17 00:00:00 2001 From: Mattias Erming Date: Tue, 8 Jul 2014 22:50:41 +0200 Subject: [PATCH] Added 'Connect' window --- client/css/bootstrap.css | 316 ------------------------------- client/css/fonts/octicons.svg | 198 +++++++++++++++++++ client/css/fonts/octicons.woff | Bin 17492 -> 17492 bytes client/css/style.css | 152 +++++++++++++-- client/index.html | 73 +++++-- client/js/chat.js | 57 ++++-- lib/client.js | 40 ++-- lib/models/chan.js | 4 +- lib/models/msg.js | 6 +- lib/models/network.js | 14 +- lib/plugins/irc-events/errors.js | 2 +- lib/plugins/irc-events/quit.js | 3 +- lib/server.js | 31 +-- 13 files changed, 496 insertions(+), 400 deletions(-) create mode 100644 client/css/fonts/octicons.svg diff --git a/client/css/bootstrap.css b/client/css/bootstrap.css index 27faec8..253f179 100644 --- a/client/css/bootstrap.css +++ b/client/css/bootstrap.css @@ -960,322 +960,6 @@ address { margin-left: 0%; } } -@media (min-width: 992px) { - .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { - float: left; - } - .col-md-12 { - width: 100%; - } - .col-md-11 { - width: 91.66666667%; - } - .col-md-10 { - width: 83.33333333%; - } - .col-md-9 { - width: 75%; - } - .col-md-8 { - width: 66.66666667%; - } - .col-md-7 { - width: 58.33333333%; - } - .col-md-6 { - width: 50%; - } - .col-md-5 { - width: 41.66666667%; - } - .col-md-4 { - width: 33.33333333%; - } - .col-md-3 { - width: 25%; - } - .col-md-2 { - width: 16.66666667%; - } - .col-md-1 { - width: 8.33333333%; - } - .col-md-pull-12 { - right: 100%; - } - .col-md-pull-11 { - right: 91.66666667%; - } - .col-md-pull-10 { - right: 83.33333333%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-8 { - right: 66.66666667%; - } - .col-md-pull-7 { - right: 58.33333333%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-5 { - right: 41.66666667%; - } - .col-md-pull-4 { - right: 33.33333333%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-2 { - right: 16.66666667%; - } - .col-md-pull-1 { - right: 8.33333333%; - } - .col-md-pull-0 { - right: 0%; - } - .col-md-push-12 { - left: 100%; - } - .col-md-push-11 { - left: 91.66666667%; - } - .col-md-push-10 { - left: 83.33333333%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-8 { - left: 66.66666667%; - } - .col-md-push-7 { - left: 58.33333333%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-5 { - left: 41.66666667%; - } - .col-md-push-4 { - left: 33.33333333%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-2 { - left: 16.66666667%; - } - .col-md-push-1 { - left: 8.33333333%; - } - .col-md-push-0 { - left: 0%; - } - .col-md-offset-12 { - margin-left: 100%; - } - .col-md-offset-11 { - margin-left: 91.66666667%; - } - .col-md-offset-10 { - margin-left: 83.33333333%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-8 { - margin-left: 66.66666667%; - } - .col-md-offset-7 { - margin-left: 58.33333333%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-5 { - margin-left: 41.66666667%; - } - .col-md-offset-4 { - margin-left: 33.33333333%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-2 { - margin-left: 16.66666667%; - } - .col-md-offset-1 { - margin-left: 8.33333333%; - } - .col-md-offset-0 { - margin-left: 0%; - } -} -@media (min-width: 1200px) { - .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { - float: left; - } - .col-lg-12 { - width: 100%; - } - .col-lg-11 { - width: 91.66666667%; - } - .col-lg-10 { - width: 83.33333333%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-8 { - width: 66.66666667%; - } - .col-lg-7 { - width: 58.33333333%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-5 { - width: 41.66666667%; - } - .col-lg-4 { - width: 33.33333333%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-2 { - width: 16.66666667%; - } - .col-lg-1 { - width: 8.33333333%; - } - .col-lg-pull-12 { - right: 100%; - } - .col-lg-pull-11 { - right: 91.66666667%; - } - .col-lg-pull-10 { - right: 83.33333333%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-8 { - right: 66.66666667%; - } - .col-lg-pull-7 { - right: 58.33333333%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-5 { - right: 41.66666667%; - } - .col-lg-pull-4 { - right: 33.33333333%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-2 { - right: 16.66666667%; - } - .col-lg-pull-1 { - right: 8.33333333%; - } - .col-lg-pull-0 { - right: 0%; - } - .col-lg-push-12 { - left: 100%; - } - .col-lg-push-11 { - left: 91.66666667%; - } - .col-lg-push-10 { - left: 83.33333333%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-8 { - left: 66.66666667%; - } - .col-lg-push-7 { - left: 58.33333333%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-5 { - left: 41.66666667%; - } - .col-lg-push-4 { - left: 33.33333333%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-2 { - left: 16.66666667%; - } - .col-lg-push-1 { - left: 8.33333333%; - } - .col-lg-push-0 { - left: 0%; - } - .col-lg-offset-12 { - margin-left: 100%; - } - .col-lg-offset-11 { - margin-left: 91.66666667%; - } - .col-lg-offset-10 { - margin-left: 83.33333333%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-8 { - margin-left: 66.66666667%; - } - .col-lg-offset-7 { - margin-left: 58.33333333%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-5 { - margin-left: 41.66666667%; - } - .col-lg-offset-4 { - margin-left: 33.33333333%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-2 { - margin-left: 16.66666667%; - } - .col-lg-offset-1 { - margin-left: 8.33333333%; - } - .col-lg-offset-0 { - margin-left: 0%; - } -} .clearfix:before, .clearfix:after, .container:before, diff --git a/client/css/fonts/octicons.svg b/client/css/fonts/octicons.svg new file mode 100644 index 0000000..ea3e0f1 --- /dev/null +++ b/client/css/fonts/octicons.svg @@ -0,0 +1,198 @@ + + + + +(c) 2012-2014 GitHub + +When using the GitHub logos, be sure to follow the GitHub logo guidelines (https://github.com/logos) + +Font License: SIL OFL 1.1 (http://scripts.sil.org/OFL) +Applies to all font files + +Code License: MIT (http://choosealicense.com/licenses/mit/) +Applies to all other files + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/css/fonts/octicons.woff b/client/css/fonts/octicons.woff index c1e76ab4a31ce674350afc9cd971adb03b9dffc8..3c0e36ad6f5093911c4d1bff00132073cc173052 100644 GIT binary patch delta 59 zcmV-B0L1^)hym1y0g!qErd_dodpRa?N8 div, -#windows .chan { +#windows .chan, +#windows .window { background: #fff; bottom: 0; + display: none; left: 0; position: absolute; right: 0; top: 0; } -#windows .chan, -#settings, -#connect { - display: none; +#windows .window { + overflow-y: auto; +} +#windows .window h1 { + font: 36px Lato; +} +#windows .window input { + border: 2px solid #e9ecef; + border-radius: 4px; + color: #222; + font-size: 14px; + margin: 2px 0; + outline: 0; + padding: 8px 10px; + transition: border-color .2s; + -webkit-appearance: none; + width: 100%; +} +#windows .window input:hover, +#windows .window input:focus { + border-color: #bdc3c7; } #windows .active { display: block; } #chat { + bottom: 0; font: 13px Consolas, monospace; - position: relative; + left: 0; + position: absolute; + right: 0; + top: 0; } #chat button:hover { opacity: .6; @@ -236,6 +318,9 @@ button { top: 0; width: 180px; } +#chat .sidebar button { + color: #33b0f7; +} #chat .messages { display: table; height: 100%; @@ -359,12 +444,31 @@ button { display: block; line-height: 1.6em; } +#connect input { + width: 100%; +} +#connect label { + display: block; + margin-top: 10px; +} +#connect .title { + margin-bottom: 10px; +} +#connect .port:before { + content: ":"; + margin: 28px 0 0 -17px; + position: absolute; +} +#connect .btn { + margin-top: 30px; +} #form { bottom: 0; height: 40px; left: 0; position: absolute; right: 0px; + z-index: 1; } #form input { border: 0; @@ -418,6 +522,9 @@ button { #sidebar { left: -220px; } + #sidebar .empty:before { + margin-top: 0; + } #main { left: 0; } @@ -442,4 +549,7 @@ button { #chat .time { display: none; } + #windows .title { + display: none; + } } \ No newline at end of file diff --git a/client/index.html b/client/index.html index bcd4ee0..d963803 100644 --- a/client/index.html +++ b/client/index.html @@ -20,42 +20,81 @@
-
-
-
-
-

Connect

+
+
+
+
+

Connect

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
-
-
+
-
+
-
-
-

Settings

+
+
+

Settings

+
-
- +
diff --git a/client/js/chat.js b/client/js/chat.js index d88ff6b..0128247 100644 --- a/client/js/chat.js +++ b/client/js/chat.js @@ -55,27 +55,34 @@ $(function() { }); socket.on("init", function(data) { - var channels = $.map(data.networks, function(n) { - return n.channels; - }); - sidebar.find(".networks").html( + if (data.networks.length === 0) { + $("#footer").find(".connect").trigger("click"); + return; + } + + sidebar.find(".networks").append( render("networks", { networks: data.networks }) ); + var channels = $.map(data.networks, function(n) { + return n.channels; + }); chat.html( render("chat", { channels: channels }) ); + var id = $.cookie("target"); - var target = sidebar.find("[data-target=" + id + "]"); - if (target.length !== 0) { - target.trigger("click"); - } else { - sidebar.find(".chan") + var target = sidebar.find("[data-target=" + id + "]").trigger("click"); + if (target.length === 0) { + var first = sidebar.find(".chan") .eq(0) .trigger("click"); + if (first.length === 0) { + $("#footer").find(".connect").trigger("click"); + } } }); @@ -109,11 +116,18 @@ $(function() { }); socket.on("network", function(data) { + $("#connect").find(".btn").prop("disabled", false); + sidebar.find(".empty").hide(); sidebar.find(".networks").append( render("networks", { networks: [data.network] }) ); + chat.append( + render("chat", { + channels: data.network.channels + }) + ); sidebar.find(".chan") .last() .trigger("click"); @@ -216,7 +230,8 @@ $(function() { var names = $(this).closest(".users").find(".names"); names.find("button").each(function() { var btn = $(this); - if (btn.text().toLowerCase().indexOf(value) === 0) { + var name = btn.text().toLowerCase().replace(/[+%@~]/, ""); + if (name.indexOf(value) === 0) { btn.show(); } else { btn.hide(); @@ -271,9 +286,25 @@ $(function() { } }); - function isActive(chan) { - return active !== null && chan == active; - } + var connect = $("#connect"); + connect.on("submit", "form", function(e) { + e.preventDefault(); + var form = $(this) + .find(".btn") + .attr("disabled", true) + .end(); + + var post = {}; + var values = form.serializeArray(); + + $.each(values, function(i, obj) { + if (obj.value !== "") { + post[obj.name] = obj.value; + } + }); + + socket.emit("conn", post); + }); function complete(word) { return $.grep( diff --git a/lib/client.js b/lib/client.js index 3b7ab2f..5886ae0 100644 --- a/lib/client.js +++ b/lib/client.js @@ -24,13 +24,12 @@ var events = [ "whois" ]; -function Client(attr) { - _.merge(this, _.extend({ - id: id++, +function Client(sockets) { + _.merge(this, { networks: [], - keepAlive: false, - sockets: null - }, attr)); + id: id++, + sockets: sockets + }); } Client.prototype.emit = function(event, data) { @@ -63,7 +62,7 @@ Client.prototype.find = function(id) { Client.prototype.connect = function(args) { var client = this; var options = { - host: args.host, + host: args.host || "irc.freenode.org", port: args.port || 6667 }; @@ -72,9 +71,13 @@ Client.prototype.connect = function(args) { console.log(e); }); + var nick = args.nick || "shout"; + var realname = args.realname || "Shout User"; + var irc = slate(stream); - irc.nick("shout"); - irc.user("shout", "Shout User"); + irc.me = nick; + irc.nick(nick); + irc.user(nick, realname); var network = new Network({ host: options.host, @@ -87,10 +90,25 @@ Client.prototype.connect = function(args) { }); events.forEach(function(plugin) { - require("./plugins/irc-events/" + plugin).apply(client, [irc, network]); + require("./plugins/irc-events/" + plugin).apply(client, [ + irc, + network + ]); }); + var join = (args.join || "#shout-irc").replace(/\,/g, " ").split(/\s+/g); irc.on("welcome", function() { - irc.join("#shout-test"); + irc.join(join); + }); +}; + +Client.prototype.quit = function() { + this.networks.forEach(function(network) { + var irc = network.irc; + if (network.connected) { + irc.quit(""); + } else { + irc.stream.end(); + } }); }; diff --git a/lib/models/chan.js b/lib/models/chan.js index 432bbbe..2c932f3 100644 --- a/lib/models/chan.js +++ b/lib/models/chan.js @@ -13,9 +13,9 @@ var id = 0; function Chan(attr) { _.merge(this, _.extend({ id: id++, - type: Chan.Type.CHANNEL, - name: "", messages: [], + name: "", + type: Chan.Type.CHANNEL, users: [] }, attr)); } diff --git a/lib/models/msg.js b/lib/models/msg.js index 6e6c6cd..309297a 100644 --- a/lib/models/msg.js +++ b/lib/models/msg.js @@ -21,9 +21,9 @@ module.exports = Msg; function Msg(attr) { _.merge(this, _.extend({ - type: Msg.Type.MESSAGE, - time: moment().format("HH:mm"), from: "", - text: "" + text: "", + time: moment().format("HH:mm"), + type: Msg.Type.MESSAGE }, attr)); } diff --git a/lib/models/network.js b/lib/models/network.js index 3d13f72..db2eb60 100644 --- a/lib/models/network.js +++ b/lib/models/network.js @@ -7,12 +7,12 @@ var id = 0; function Network(attr) { _.merge(this, _.extend({ - id: id++, + channels: [], connected: false, host: "", + id: id++, irc: null, - name: capitalize(attr.host.split(".")[1]) || attr.host, - channels: [] + name: prettify(attr.host) }, attr)); this.channels.unshift( new Chan({name: this.name, type: Chan.Type.LOBBY}) @@ -23,6 +23,14 @@ Network.prototype.toJSON = function() { return _.omit(this, "irc"); }; +function prettify(host) { + var name = capitalize(host.split(".")[1]); + if (!name) { + name = host; + } + return name; +} + function capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1); } diff --git a/lib/plugins/irc-events/errors.js b/lib/plugins/irc-events/errors.js index 3fcae24..8597178 100644 --- a/lib/plugins/irc-events/errors.js +++ b/lib/plugins/irc-events/errors.js @@ -14,7 +14,7 @@ module.exports = function(irc, network) { }); if (!network.connected) { if (data.cmd == "ERR_NICKNAMEINUSE") { - var random = client.nick + Math.floor(10 + (Math.random() * 89)); + var random = irc.me + Math.floor(10 + (Math.random() * 89)); irc.nick(random); } } diff --git a/lib/plugins/irc-events/quit.js b/lib/plugins/irc-events/quit.js index 0f9f3f8..73965d5 100644 --- a/lib/plugins/irc-events/quit.js +++ b/lib/plugins/irc-events/quit.js @@ -16,7 +16,8 @@ module.exports = function(irc, network) { }); var msg = new Msg({ type: Msg.Type.QUIT, - from: data.nick + from: data.nick, + text: data.message }); chan.messages.push(msg); client.emit("msg", { diff --git a/lib/server.js b/lib/server.js index 65d9e80..35135d0 100644 --- a/lib/server.js +++ b/lib/server.js @@ -26,7 +26,7 @@ var inputs = [ module.exports = function() { sockets = io(http().use(http.static("client")).listen(config.port || 9000)); - sockets.on("connection", function(socket) { + sockets.on("connect", function(socket) { if (config.public) { auth.call(socket); } else { @@ -40,7 +40,18 @@ function init(socket, client) { socket.emit("auth"); socket.on("auth", auth); } else { - socket.on("input", function(data) { input(client, data); }); + socket.on( + "input", + function(data) { + input(client, data); + } + ); + socket.on( + "conn", + function(data) { + client.connect(data); + } + ); socket.join(client.id); socket.emit("init", { networks: client.networks @@ -51,15 +62,12 @@ function init(socket, client) { function auth(data) { var socket = this; if (config.public) { - // Temporary: - var client = clients[0]; - if (clients.length === 0) { - client = new Client({sockets: sockets}); - clients.push(client); - client.connect({ - host: "irc.freenode.org" - }); - } + var client = new Client(sockets); + clients.push(client); + socket.on("disconnect", function() { + clients = _.without(clients, client); + client.quit(); + }); init(socket, client); } else { if (false) { @@ -89,7 +97,6 @@ function input(client, data) { args ]); } catch (err) { - console.log(err.stack); // .. } });