diff --git a/CREDITS.md b/CREDITS.md index 7c363c2..0b97806 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -1,6 +1,7 @@ ## [Chromesoul](https://github.com/TychoBrahe/chromesoul) -* Rodolphe Breard +* Rodolphe Breard (development) +* Romain Mardargent (design) ### Special thanks diff --git a/chromesoul.css b/chromesoul.css index 24b2a93..10930ef 100644 --- a/chromesoul.css +++ b/chromesoul.css @@ -1,18 +1,50 @@ -#l-lst { +/* + * Page itself + */ + +body { + margin: 0; + padding: 0; + background: #347db0 url(img/chromesoul-logo.png) no-repeat 10px 10px; +} + +/* + * Top menu + */ + +#user-status { + position: fixed; + right: 285px; + top: 10px; + margin: 0; + padding: 0; + width: 150px; +} + +#settings-btn { + position: fixed; + right: 222px; + top: 10px; + margin: 0; + padding: 0; +} + +/* + * Contact list + */ + +#contact-lst-wrapper { position: fixed; right: 0; top: 0; + margin: 0; padding: 0 5px 0 5px; width: 200px; height: 100%; border-left: 1px solid #aaa; -} - -#l-lst > h2 { - margin: 0; - padding: 0; - text-align: center; - font-size: 1em; + background-color: #e4e4e4; + box-shadow: 0px 0px 10px #666; + overflow-y: scroll; } #contact-lst { @@ -23,15 +55,53 @@ #contact-lst > li { margin: 5px 0 0 0; - padding: 5px; + padding: 5px 5px 5px 28px; border: 1px solid #aaa; + background-size: 23px 26px; + background-repeat: no-repeat; } -#r-lst { - padding-right: 210px; +#add-contact::-webkit-input-placeholder { + color: rgba(52, 125, 176, 0.42); +} + +#add-contact { + padding: 2px; + outline: 0px solid #aaa; + width: 184px; + height: 20px; + margin: 5px 0 0 0; +} + +#add-contact, #contact-lst > li { + box-shadow: inset 0px 0px 1px #666; + background-color: #f3f3f3; + border: 1px solid #347db0; + color: #347db0; + font-family: monospace; +} + +.remove { + float: right; + font-family: sans-serif; + font-size: 12px; + cursor: pointer; +} + +/* + * Main content + */ + +#main-ctn { + margin: 135px 0 0 0; + padding: 10px 220px 10px 10px; min-width: 400px; } +/* + * Tabs + */ + #tab-lst { margin: 0; padding: 0; @@ -75,6 +145,10 @@ margin: 5px; } +/* + * Chat + */ + .chat-log { margin: 0; padding: 2px 5px 2px 0; @@ -84,38 +158,23 @@ font-family: monospace; } -#add-contact, .chat-input { - padding: 0; - border-style: none; - outline: 1px solid #aaa; + +.chat-input-wrapper { + padding-right: 2px; +} + +.chat-input { + padding: 0px; + outline: 0px solid #aaa; width: 100%; height: 20px; margin: 5px 0 0 0; } -#add-contact:focus, .chat-input:focus { +.chat-input:focus { outline-offset: 0; } -.chat-input-wrapper { - background-image: url('img/user-offline.png'); - background-repeat: no-repeat; - background-position: left bottom; - padding-left: 24px; -} - -#tab-lst > #tab-config { - background-image: url('img/preferences.png'); - background-repeat: no-repeat; - background-position: center; - padding-left: 12px; - padding-right: 12px; -} - -#tab-config > span { - display: none; -} - .spk-oth { color: red; } @@ -124,9 +183,23 @@ color: blue; } -.remove { - float: right; - font-family: sans-serif; - font-size: 12px; - cursor: pointer; +/* + * Scrollbar + */ + +::-webkit-scrollbar { + width: 10px; + height: 10px; + background-color: green; +} + +::-webkit-scrollbar-track-piece { + background-color: #e4e4e4; +} + +::-webkit-scrollbar-thumb { + height: 40px; + background-color: #347db0; + border-left: 1px solid #e4e4e4; + border-right: 1px solid #e4e4e4; } diff --git a/chromesoul.html b/chromesoul.html index 786bdfe..01dfb44 100644 --- a/chromesoul.html +++ b/chromesoul.html @@ -6,30 +6,29 @@ -

Welcome to chromesoul

- -

+

Status:

-
-

Contacts

+
+ +
-
- -
-
- Login:
- Password (socks):
- Enable messages:
- -
+
+

You haven't configured chromesoul yet, you should go to the configuration pannel.

+
+ Login:
+ Password (socks):
+ Enable messages:
+ +
+
+
    +
    diff --git a/img/chromesoul-logo.png b/img/chromesoul-logo.png new file mode 100644 index 0000000..6be3449 Binary files /dev/null and b/img/chromesoul-logo.png differ diff --git a/img/default-avatar.jpg b/img/default-avatar.jpg new file mode 100644 index 0000000..0e7e73b Binary files /dev/null and b/img/default-avatar.jpg differ diff --git a/img/preferences.png b/img/preferences.png deleted file mode 100644 index eb28840..0000000 Binary files a/img/preferences.png and /dev/null differ diff --git a/img/settings.png b/img/settings.png new file mode 100644 index 0000000..322a987 Binary files /dev/null and b/img/settings.png differ diff --git a/img/user-available.png b/img/user-available.png deleted file mode 100644 index 12f43ff..0000000 Binary files a/img/user-available.png and /dev/null differ diff --git a/img/user-away.png b/img/user-away.png deleted file mode 100644 index 195aef6..0000000 Binary files a/img/user-away.png and /dev/null differ diff --git a/img/user-busy.png b/img/user-busy.png deleted file mode 100644 index 8a0a8eb..0000000 Binary files a/img/user-busy.png and /dev/null differ diff --git a/img/user-idle.png b/img/user-idle.png deleted file mode 100644 index a975379..0000000 Binary files a/img/user-idle.png and /dev/null differ diff --git a/img/user-invisible.png b/img/user-invisible.png deleted file mode 100644 index f73116a..0000000 Binary files a/img/user-invisible.png and /dev/null differ diff --git a/img/user-offline.png b/img/user-offline.png deleted file mode 100644 index c5fa77c..0000000 Binary files a/img/user-offline.png and /dev/null differ diff --git a/lib/contacts.nsui.js b/lib/contacts.nsui.js index edcfd9b..a67431a 100644 --- a/lib/contacts.nsui.js +++ b/lib/contacts.nsui.js @@ -16,27 +16,59 @@ var ContactList = function() { this.storage = chrome.storage.sync; - this.contacts = {}; + this.contacts = {}; // {: {name: , li: , avatar: }} this.lst = document.getElementById("contact-lst"); }; ContactList.prototype.insertContact = function(elem) { - var i, nb_el = this.lst.children.length; + var i, next = null; - for (i = 0; i < nb_el; i++) { - if (this.lst.children[i].children[0].innerHTML > elem.children[0].innerHTML) { - this.lst.insertBefore(elem, this.lst.children[i]); - return ; + for (i in this.contacts) { + if (this.contacts.hasOwnProperty(i)) { + if (elem.name < this.contacts[i].name && (next === null || this.contacts[i].name < next.name)) { + next = this.contacts[i]; + } } } - this.lst.appendChild(elem); + + if (next !== null) { + this.lst.insertBefore(elem.li, next.li); + } else { + this.lst.appendChild(elem.li); + } }; +ContactList.prototype.getContactPic = function(elem, infos) { + var xhr = new XMLHttpRequest(); + + xhr.open("GET", "http://www.epitech.eu/intra/photos/" + infos.name + ".jpg", true); + xhr.responseType = "blob"; + xhr.onload = (function(el) { + return function(e) { + if (e.target.status === 200) { + infos.avatar = window.webkitURL.createObjectURL(this.response); + } else { + infos.avatar= "img/default-avatar.jpg"; + } + + elem.style.backgroundImage = "url('" + infos.avatar + "')"; + }; + })(this); + xhr.send(); +} + ContactList.prototype.addContact = function(name) { - var li = null, login = null, close = null; + var infos = {}, li = null, login = null, close = null; if (typeof this.contacts[name] === "undefined") { + infos = { + "name": name, + "li": null, + "avatar": null + }; + li = document.createElement("li"); + this.getContactPic(li, infos); login = document.createElement("span"); close = document.createElement("span"); close.classList.add("remove"); @@ -55,20 +87,19 @@ ContactList.prototype.addContact = function(name) { elem.rmContact(name); }; })(this)); - this.contacts[name] = li; + + infos.li = li; + this.contacts[name] = infos; this.save(); - this.insertContact(li); + this.insertContact(infos); } }; ContactList.prototype.rmContact = function(name) { - for (var i = this.lst.children.length - 1; i >= 0; --i) { - if (this.lst.children[i].children[0].innerHTML === name) { - this.lst.removeChild(this.lst.children[i]); - delete this.contacts[name]; - this.save(); - break ; - } + if (typeof this.contacts[name] !== "undefined") { + this.lst.removeChild(this.contacts[name].li); + delete this.contacts[name]; + this.save(); } }; diff --git a/lib/ns_client.js b/lib/ns_client.js index 1ff216a..7f11d05 100644 --- a/lib/ns_client.js +++ b/lib/ns_client.js @@ -57,22 +57,31 @@ var NsClient = function() { })(this); }; +NsClient.prototype.replacePairs = function(str, pairs) { + for (var i in pairs) { + if (pairs.hasOwnProperty(i)) { + str = str.replace(pairs[i], i); + } + } + return str; +} + NsClient.prototype.msgDecode = function(msg) { - msg = unescape(msg) - msg = msg.replace('@', '@'); - msg = msg.replace('*', '*'); - msg = msg.replace('/', '/'); - msg = msg.replace('+', '+'); - return msg; + return this.replacePairs(unescape(msg), { + "@": /%40/g, + "*": /%2A/g, + "/": /%2F/g, + "+": /%2B/g + }); }; NsClient.prototype.msgEncode = function(msg) { - msg = escape(msg) - msg = msg.replace('@', '@'); - msg = msg.replace('*', '*'); - msg = msg.replace('/', '/'); - msg = msg.replace('+', '+'); - return msg; + return this.replacePairs(escape(msg), { + "%40": /@/g, + "%2A": /\*/g, + "%2F": /\//g, + "%2B": /\+/g, + }); }; NsClient.prototype.connect = function() { diff --git a/lib/nsui.js b/lib/nsui.js index 7512825..729c0e5 100644 --- a/lib/nsui.js +++ b/lib/nsui.js @@ -39,13 +39,10 @@ Nsui.prototype.deleteTab = function(tab) { if (new_tab !== null) { new_tab.show(); - } else { - document.getElementById("configuration").style.display = "block"; } }; Nsui.prototype.hideAllTabs = function() { - document.getElementById("configuration").style.display = "none"; for (i = this.tab_lst.length - 1; i >= 0; --i) { this.tab_lst[i].hide(); } @@ -86,7 +83,9 @@ Nsui.prototype.addNewTab = function(tab_name) { if (tab === null) { tab = this.createTab(tab_name); } - if (!tab.isCurrent()) { + if (this.tab_lst.length <= 1) { + tab.show(); + } else if (!tab.isCurrent()) { tab.setActive(); } @@ -98,7 +97,7 @@ Nsui.prototype.addContentToTab = function(tab_name, content) { if ($cs.opts.get("enable_msg")) { tab = this.addNewTab(tab_name); - tab.appendText(this.formatMessage(content)); + tab.appendMessage(content); } }; @@ -122,23 +121,40 @@ Nsui.prototype.formatMessage = function(msg) { fmt += '' + document.getElementById('login').value + ': '; } - msg.message = msg.message.replace("<", "<"); - msg.message = msg.message.replace(">", ">"); - fmt += msg.message; - - fmt += '
    '; + fmt += this.sanitizeText(msg.message); + fmt += "
    "; return fmt; }; +Nsui.prototype.sanitizeText = function(str) { + return str.replace(/&/g, '&').replace(//g, '>'); +}; + +Nsui.prototype.showContent = function(part_id) { + var i, ctn_lst = ["config-pannel", "chat-pannel", "pre-conf-pannel"]; + + for (i = ctn_lst.length - 1; i>= 0; --i) { + if (ctn_lst[i] === part_id) { + document.getElementById(ctn_lst[i]).style.display = "block"; + } else { + document.getElementById(ctn_lst[i]).style.display = "none"; + } + } +}; + +Nsui.prototype.switchContent = function(part_id, part_id_to) { + if (document.getElementById(part_id).style.display !== "block") { + this.showContent(part_id); + } else { + this.showContent(part_id_to); + } +} + Nsui.prototype.init = function() { - document.getElementById("tab-config").addEventListener("click", (function(elem) { + document.getElementById("settings-btn").addEventListener("click", (function(elem) { return function() { - for (var i = elem.tab_lst.length - 1; i >= 0; --i) { - elem.tab_lst[i].hide(); - } - this.classList.add("tab-current"); - document.getElementById("configuration").style.display = "block"; + elem.switchContent("config-pannel", "chat-pannel"); }; })(this), false); @@ -153,4 +169,11 @@ Nsui.prototype.init = function() { elem.hideAllTabs(); }; })(this); + + this.showContent("chat-pannel"); + setTimeout(function() { + if ($cs.opts.get("login") === null || $cs.opts.get("pwd_socks") === null) { + $cs.ui.showContent("pre-conf-pannel"); + } + }, 600); }; diff --git a/lib/tab.nsui.js b/lib/tab.nsui.js index 3f6b47d..9120742 100644 --- a/lib/tab.nsui.js +++ b/lib/tab.nsui.js @@ -19,27 +19,19 @@ var Tab = function(name) { this.chat_input = null; this.wr_lst = document.getElementById("tab-lst"); this.wr_body = document.getElementById("tab-body-wrapper"); + this.buff_len = 1000; + this.history_index = 0; + this.history = []; this.initListElement(); this.initBodyElement(); }; Tab.prototype.filterName = function(name) { - // TODO: enforce an id compliant name - return name; + return name.replace(/[^a-z0-9\-_]/g, "").replace(/^[0-9]/g, "_"); }; Tab.prototype.initListElement = function() { - var inner = document.createElement("span"), - evt_click = function(elem) { - return function() { - elem.show(); - }; - }, - evt_dblclick = function(elem) { - return function() { - elem.close(); - }; - }; + var inner = document.createElement("span"); inner.innerHTML = this.name; this.el_lst = document.createElement("li"); @@ -73,7 +65,9 @@ Tab.prototype.initBodyElement = function() { this.chat_input.setAttribute("type", "text"); this.chat_input.addEventListener("keyup", (function(elem) { return function(event) { - if (event.keyCode == 13 && this.value != "") { + var key_submit = 13, key_up = 38, key_down = 40; + + if (event.keyCode === key_submit && this.value != "") { var msg = this.value; this.value = ""; @@ -83,6 +77,20 @@ Tab.prototype.initBodyElement = function() { } else { console.error("chromesoul client not found"); } + } else if (event.keyCode === key_up) { + if (elem.history_index < elem.history.length) { + elem.history_index++; + this.value = elem.history[elem.history.length - elem.history_index]; + } + } else if (event.keyCode === key_down) { + if (elem.history_index > 0) { + elem.history_index--; + if (elem.history_index > 0) { + this.value = elem.history[elem.history.length - elem.history_index]; + } else { + this.value = ""; + } + } } }; })(this), false); @@ -128,13 +136,22 @@ Tab.prototype.setActive = function() { Tab.prototype.flushText = function() { var str = this.chat_log.innerHTML, sep = "
    ", t = str.split(sep); - if (t.length > 1000) { + if (t.length > this.buff_len + 1) { this.chat_log.innerHTML = str.substring(str.indexOf(sep) + sep.length); } + while (this.history.length > this.buff_len) { + this.history.shift(); + } }; -Tab.prototype.appendText = function(text) { +Tab.prototype.appendMessage = function(msg) { + this.history_index = 0; + this.chat_log.innerHTML += $cs.ui.formatMessage(msg); + + if (!(typeof msg.login !== "undefined" && msg.login !== null)) { + this.history.push(msg.message); + } + this.flushText(); - this.chat_log.innerHTML += text; - this.chat_log.scrollTop = 42000; + this.chat_log.scrollTop = 42 * this.buff_len; }; diff --git a/manifest.json b/manifest.json index 42c3107..52a275d 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "name": "chromesoul", - "version": "0.3.4", + "version": "0.4.2", "minimum_chrome_version": "24", "manifest_version": 2, "offline_enabled": false, @@ -11,6 +11,7 @@ } }, "permissions": [ + "http://www.epitech.eu/intra/photos/", "background", "storage", {"socket": ["tcp-connect:ns-server.epita.fr:4242"]}