diff --git a/public/css/layout.css b/public/css/layout.css
index c1b035a..ccd4c85 100644
--- a/public/css/layout.css
+++ b/public/css/layout.css
@@ -222,7 +222,7 @@ body {
width: 25px;
display: inline-block;
}
-.ircclient #chat .ircwrapper .chatarea .settings {
+.ircclient #chat .ircwrapper .chatarea .applet_default {
position: absolute;
top: 0;
bottom: 0;
@@ -234,6 +234,11 @@ body {
margin: auto;
overflow: auto;
}
+.ircclient #chat .ircwrapper .chatarea .applet_default .grade1,
+.ircclient #chat .ircwrapper .chatarea .applet_default .grade2,
+.ircclient #chat .ircwrapper .chatarea .applet_default .grade3 {
+ text-align: left;
+}
.ircclient #chat .ircwrapper .chatarea .settings .theme_button {
width: 120px;
height: 140px;
@@ -257,11 +262,6 @@ body {
text-align: center;
display: block;
}
-.ircclient #chat .ircwrapper .chatarea .settings .grade1,
-.ircclient #chat .ircwrapper .chatarea .settings .grade2,
-.ircclient #chat .ircwrapper .chatarea .settings .grade3 {
- text-align: left;
-}
.ircclient #chat .ircwrapper .chatarea.vnicks .nicklist {
display: block;
}
diff --git a/public/css/theme_default.css b/public/css/theme_default.css
index afaa9dc..fbec803 100644
--- a/public/css/theme_default.css
+++ b/public/css/theme_default.css
@@ -460,3 +460,23 @@
.topicbar .irc-underline {
text-decoration: underline;
}
+@-moz-keyframes hotTab {
+ 50% {
+ background-color: #6eebff;
+ }
+}
+@-webkit-keyframes hotTab {
+ 50% {
+ background-color: #6eebff;
+ }
+}
+@-o-keyframes hotTab {
+ 50% {
+ background-color: #6eebff;
+ }
+}
+@keyframes hotTab {
+ 50% {
+ background-color: #6eebff;
+ }
+}
diff --git a/public/css/theme_night.css b/public/css/theme_night.css
index 645cfe2..3a5974e 100644
--- a/public/css/theme_night.css
+++ b/public/css/theme_night.css
@@ -82,6 +82,9 @@ a:hover {
box-shadow: inset 4px 4px 8px #00d1ea;
color: #fff;
}
+.ircclient #chat .ircwrapper .toolbar .tabby .tab.hot {
+ animation: hotTab 1s linear infinite;
+}
.ircclient #chat .ircwrapper .toolbar .tabby .tab #unread {
background-color: #bf0000;
border: 1px solid #b00;
@@ -475,3 +478,23 @@ a:hover {
.topicbar .irc-underline {
text-decoration: underline;
}
+@-moz-keyframes hotTab {
+ 50% {
+ background-color: #3ee4ff;
+ }
+}
+@-webkit-keyframes hotTab {
+ 50% {
+ background-color: #3ee4ff;
+ }
+}
+@-o-keyframes hotTab {
+ 50% {
+ background-color: #3ee4ff;
+ }
+}
+@keyframes hotTab {
+ 50% {
+ background-color: #3ee4ff;
+ }
+}
diff --git a/public/index.html b/public/index.html
index 3c64b15..bbccfb8 100644
--- a/public/index.html
+++ b/public/index.html
@@ -58,7 +58,7 @@
Test
diff --git a/public/js/main.js b/public/js/main.js
index d5bf89d..0a6293e 100644
--- a/public/js/main.js
+++ b/public/js/main.js
@@ -147,7 +147,7 @@ Date.prototype.format = function (format, utc){
return format;
};
-irc.whoisMessage = function(whoisData, buffer) {
+function whoisMessage(whoisData, buffer) {
let messages = [];
for(let key in whoisData) {
switch(key) {
@@ -250,6 +250,15 @@ function linkify(text) {
return parsed;
}
+function serialize(obj) {
+ let str = [];
+ for(let p in obj)
+ if (obj.hasOwnProperty(p)) {
+ str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
+ }
+ return str.join("&");
+}
+
function removeClass(element, cl) {
let classList = element.className.split(" ");
@@ -373,6 +382,54 @@ let composer = {
btn.setAttribute('id', 'theme-'+name);
return btn;
+ },
+ embedURL: function(server, port, defaultNick, useSSL, hideServerData, channels) {
+ let builder = window.location.origin + "/";
+ let params = {};
+ let final_channels = [];
+
+ if(server)
+ builder += server + "/";
+
+ if(channels)
+ channels = channels.trim();
+
+ if(defaultNick)
+ params.nickname = defaultNick;
+
+ if(port && port != 6667)
+ params.port = port;
+
+ if(useSSL)
+ params.secure = 1;
+
+ if(hideServerData)
+ params.server_data = 0;
+
+ if(Object.keys(params).length > 0)
+ builder += "?" + serialize(params);
+
+ if(channels) {
+ if(channels.indexOf(",")) {
+ let tmp = channels.split(',');
+ for(let i in tmp) {
+ tmp[i] = tmp[i].trim();
+
+ if(tmp[i].indexOf('#') != 0)
+ tmp[i] = "#"+tmp[i];
+
+ final_channels.push(tmp[i]);
+ }
+ } else {
+ if(channels.indexOf('#') != 0)
+ channels = '#'+channels;
+ final_channels.push(channels);
+ }
+
+ builder += final_channels.join(',');
+ }
+
+ return builder;
}
}
@@ -384,6 +441,16 @@ let composer = {
// commandName: {execute: function(buffer, handler, command, message, listargs) {}, description: ""}
let commands = {
+ embed: {execute: function(buffer, handler, command, message, listargs) {
+ let data = irc.auther.getDataFromForm();
+ let url = "Couldn't compose URL!";
+
+ if(data)
+ url = composer.embedURL(data.server, data.port, data.nickname, data.secure, true, data.autojoin.join(','));
+
+ buffer.addMessage(url, null, "help");
+ }, description: "- Embed URL for the current connection"},
+
join: {execute: function(buffer, handler, command, message, listargs) {
if (!listargs[1]) {
if(!buffer.alive) {
@@ -794,6 +861,15 @@ class Tab {
}
}
+ setHot(hot) {
+ if(this.element) {
+ if(hot)
+ addClass(this.element, "hot");
+ else
+ removeClass(this.element, "hot");
+ }
+ }
+
setUnreadCount(count) {
if(this.element) {
let counter = this.element.querySelector('#unread');
@@ -834,6 +910,7 @@ class Buffer {
this.type = type;
this.active = false;
this.alive = true;
+ this.hot = false;
if(type != "applet") {
this.tab = new Tab(this);
@@ -862,6 +939,9 @@ class Buffer {
this.nicklist.render();
}
+ if(this.hot)
+ this.setHotStatus(false);
+
if(this.topic != null && this.topic != "") {
addClass(clientdom.chat, 'vtopic');
if(irc.config.colors)
@@ -899,6 +979,12 @@ class Buffer {
clientdom.letterbox.innerHTML = "";
}
+ setHotStatus(hot) {
+ this.hot = hot;
+ if(this.tab)
+ this.tab.setHot(hot);
+ }
+
appendMessage(meta) {
let mesgConstr = composer.message[irc.chatType](meta.time, meta.sender, meta.message, meta.type);
@@ -940,8 +1026,12 @@ class Buffer {
if(irc.serverData[this.server]) {
let mynick = irc.serverData[this.server].my_nick;
if((type == "privmsg" || type == "notice" || type == "action") &&
- message.toLowerCase().indexOf(mynick.toLowerCase()) != -1 && sender != mynick)
- console.log("TODO: notify user of mentioned");
+ message.toLowerCase().indexOf(mynick.toLowerCase()) != -1 && sender != mynick) {
+ // TODO: notify user of mentioned
+
+ if(!this.active)
+ this.setHotStatus(true);
+ }
}
}
@@ -1021,12 +1111,55 @@ class ThemeSelector {
}
}
-class Settings extends Buffer {
- constructor() {
- super("", "settings", "Settings", "applet");
+class AppletBuffer extends Buffer {
+ constructor(appletName, title, frame) {
+ super("", appletName, title, "applet");
this.tab = null;
this.isOpen = false;
this.timeout = null;
+ this.frame = frame;
+ }
+
+ closeBuffer() {
+ irc.chat.closeBuffer(this);
+ this.tab = null;
+ this.isOpen = false;
+ }
+
+ open() {
+ if(this.isOpen) {
+ irc.chat.render(this);
+ return;
+ }
+
+ this.tab = new Tab(this);
+ this.tab.renderTab();
+ irc.chat.buffers.push(this);
+ irc.chat.render(this);
+ this.isOpen = true;
+ }
+
+ addMessage(message, sender, type, time) {
+ // Don't send messages to any applet buffer
+ return;
+ }
+
+ switchOff() {
+ this.active = false;
+ this.tab.setActive(false);
+ this.frame.style.display = "none";
+ }
+
+ render() {
+ this.active = true;
+ this.tab.setActive(true);
+ this.frame.style.display = "block";
+ }
+}
+
+class Settings extends AppletBuffer {
+ constructor() {
+ super("settings", "Settings", clientdom.settings.frame);
this.themeSelection = "";
@@ -1050,25 +1183,6 @@ class Settings extends Buffer {
}
}
- open() {
- if(this.isOpen) {
- irc.chat.render(this);
- return;
- }
-
- this.tab = new Tab(this);
- this.tab.renderTab();
- irc.chat.buffers.push(this);
- irc.chat.render(this);
- this.isOpen = true;
- }
-
- closeBuffer() {
- irc.chat.closeBuffer(this);
- this.tab = null;
- this.isOpen = false;
- }
-
saveSpecified() {
if(this.timeout)
clearTimeout(this.timeout);
@@ -1137,25 +1251,12 @@ class Settings extends Buffer {
}
}
- addMessage(message, sender, type, time) {
- // Don't send messages to the settings buffer
- return;
- }
-
- switchOff() {
- this.active = false;
- this.tab.setActive(false);
- clientdom.settings.frame.style.display = "none";
- }
-
render() {
- this.active = true;
- this.tab.setActive(true);
+ super.render();
clientdom.chat.className = "chatarea";
clientdom.nicklist.innerHTML = "";
clientdom.topicbar.innerHTML = "";
clientdom.letterbox.innerHTML = "";
- clientdom.settings.frame.style.display = "block";
irc.chat.changeTitle("TeemantIRC - Settings");
}
}
@@ -1213,6 +1314,13 @@ class IRCConnector {
if(window.validators.iporhost(value))
clientdom.connector.server.value = value;
break;
+ case "server_data":
+ case "extra":
+ case "extras":
+ case "connection":
+ if(value == "false" || value == "0")
+ clientdom.connector.server_data.style.display = "none";
+ break;
case "port":
try {
let ppp = parseInt(value);
@@ -1240,9 +1348,7 @@ class IRCConnector {
}
}
- validateForm(event) {
- event.preventDefault();
-
+ getDataFromForm() {
let nickname = clientdom.connector.nickname.value;
let password = clientdom.connector.password.value;
let channel = clientdom.connector.channel.value;
@@ -1296,12 +1402,21 @@ class IRCConnector {
if(!clientdom.connector.pwtrigger.checked)
password = "";
- irc.socket.emit('irc_create', {nickname: nickname,
- autojoin: channel,
- server: server,
- port: port,
- password: password,
- secure: clientdom.connector.secure.checked });
+ return {nickname: nickname,
+ autojoin: channel,
+ server: server,
+ port: port,
+ password: password,
+ secure: clientdom.connector.secure.checked }
+ }
+
+ validateForm(event) {
+ event.preventDefault();
+
+ let data = this.getDataFromForm();
+ if(!data) return;
+
+ irc.socket.emit('irc_create', data);
return true;
}
@@ -1498,10 +1613,12 @@ class InputHandler {
class IRCChatWindow {
constructor() {
this.buffers = [];
- clientdom.frame.style.display = "none";
this.firstServer = true;
this.currentBuffer = null;
this.input_handler = new InputHandler();
+
+ clientdom.frame.style.display = "none";
+
clientdom.smsctrig.onclick = (e) => {
toggleClass(clientdom.chat, "vopentrig");
}
@@ -1520,6 +1637,7 @@ class IRCChatWindow {
irc.auther.authMessage("Disconnected", true);
clientdom.frame.style.display = "none";
this.firstServer = true;
+ window.onbeforeunload = null;
}
getBufferByName(buffername) {
@@ -1885,6 +2003,11 @@ function parseURL() {
irc.auther.fillFormFromURI();
}
+function stopWarnings() {
+ if(Object.keys(irc.serverData).length == 0)
+ window.onbeforeunload = null;
+}
+
window.onpopstate = parseURL;
window.onresize = function() {
@@ -1905,6 +2028,7 @@ window.onload = function() {
clientdom.settings['save'] = clientdom.settings.frame.querySelector('#save_settings');
clientdom.settings['saveStatus'] = clientdom.settings.frame.querySelector('#settings_status');
clientdom.connector['frame'] = irc.primaryFrame.querySelector('#authdialog');
+ clientdom.connector['server_data'] = clientdom.connector.frame.querySelector('.server_data');
clientdom.connector['messenger'] = clientdom.connector.frame.querySelector('#connmsg');
clientdom.connector['form'] = clientdom.connector.frame.querySelector('#IRCConnector');
clientdom.connector['nickname'] = clientdom.connector.form.querySelector('#nickname');
@@ -1979,6 +2103,10 @@ window.onload = function() {
serv.addMessage("You are no longer talking on this server.", null, "error");
serv.setAliveStatus(false);
}
+
+ if(irc.serverData[data.server])
+ delete irc.serverData[data.server];
+ stopWarnings();
break;
case "message":
if(data.to == irc.serverData[data.server].my_nick) {
@@ -2029,7 +2157,7 @@ window.onload = function() {
irc.auther.authMessage(data.message, data.error);
break;
case "whoisResponse":
- irc.whoisMessage(data.whois, irc.chat.getActiveBuffer());
+ whoisMessage(data.whois, irc.chat.getActiveBuffer());
break;
case "listedchan":
irc.chat.messageBuffer(data.server, data.server, {message: "
"+data.channel+""+
diff --git a/public/stylus/layout.styl b/public/stylus/layout.styl
index b58271c..116749a 100644
--- a/public/stylus/layout.styl
+++ b/public/stylus/layout.styl
@@ -196,7 +196,7 @@ body
.no-prefix
width: 25px;
display: inline-block;
- .settings
+ .applet_default
position: absolute;
top: 0;
bottom: 0;
@@ -207,6 +207,9 @@ body
min-width: 360px;
margin: auto;
overflow: auto;
+ .grade1, .grade2, .grade3
+ text-align: left;
+ .settings
.theme_button
width: 120px
height: 140px
@@ -226,8 +229,6 @@ body
width: 100%
text-align: center
display: block
- .grade1, .grade2, .grade3
- text-align: left;
&.vnicks
.nicklist
display: block;
diff --git a/public/stylus/theme_default.styl b/public/stylus/theme_default.styl
index 94b036c..0bb4d9f 100644
--- a/public/stylus/theme_default.styl
+++ b/public/stylus/theme_default.styl
@@ -285,3 +285,7 @@ box-shadow()
font-style: italic
.irc-underline
text-decoration: underline
+
+@keyframes hotTab
+ 50%
+ background-color: #6eebff
diff --git a/public/stylus/theme_night.styl b/public/stylus/theme_night.styl
index 7879625..42506b8 100644
--- a/public/stylus/theme_night.styl
+++ b/public/stylus/theme_night.styl
@@ -68,6 +68,8 @@ a:hover
background-size: contain
.tabby
.tab
+ &.hot
+ animation: hotTab 1s linear infinite;
background-color: #00bfde
border: 1px solid #0092a5
box-shadow inset 4px 4px 8px #00d1ea
@@ -295,3 +297,7 @@ a:hover
font-style: italic
.irc-underline
text-decoration: underline
+
+@keyframes hotTab
+ 50%
+ background-color: #3ee4ff
diff --git a/server/teemant_irc/irc.js b/server/teemant_irc/irc.js
index a01ecab..a5f848b 100644
--- a/server/teemant_irc/irc.js
+++ b/server/teemant_irc/irc.js
@@ -257,12 +257,16 @@ class IRCConnectionHandler {
case "376":
this.conn.emit('pass_to_client', {type: "server_message", messageType: "motd", message: line.trailing, server: serverName, from: realServerName});
break;
- case "351":
+ case "006":
+ case "007":
case "251":
+ case "255":
+ case "270":
case "290":
case "292":
+ case "323":
+ case "351":
case "381":
- case "255":
this.conn.emit('pass_to_client', {type: "server_message", messageType: "regular", message: line.trailing, server: serverName, from: realServerName});
break;
case "252":