Moving to multi-server support

This commit is contained in:
Neale Pickett 2015-02-09 16:53:43 -07:00
parent 30eaf147f1
commit c04d246d9e
23 changed files with 290 additions and 1938 deletions

20
LICENSE Normal file
View file

@ -0,0 +1,20 @@
Copyright (c) 2015 Neale Pickett
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
The software is provided "as is", without warranty of any kind, express or
implied, including but not limited to the warranties of merchantability,
fitness for a particular purpose and noninfringement. In no event shall
the authors or copyright holders be liable for any claim, damages or
other liability, whether in an action of contract, tort or otherwise,
arising from, out of or in connection with the Software or the use or
other dealings in the Software.

View file

@ -1,24 +0,0 @@
ICONS += app/icon-16.png
ICONS += app/icon-32.png
ICONS += app/icon-48.png
ICONS += app/icon-128.png
ICONS += app/icon-256.png
all: icons serverside
serverside: spongy spongy.cgi
spongy: src/spongy/spongy.go
GOPATH=$(CURDIR) go build -v $@
spongy.cgi: src/spongy.cgi/spongy.cgi.go
GOPATH=$(CURDIR) go build -v $@
chmod +s $@
icons: $(ICONS)
app/icon-%.png: chat.svg
inkscape --export-png=$@ --export-width=$* $<
package: icons
cd app && zip -ru ../package.zip .

View file

@ -1,75 +0,0 @@
{
"appName": {
"description": "Application name",
"message": "Spongy Chat Client"
},
"appShortName": {
"description": "Short application name",
"message": "Spongy Chat"
},
"appDesc": {
"description": "Application description for app store listing",
"message": "Chat client for the Spongy bouncer thingamajiggy"
},
"unknownCommand": {
"description": "Text for unrecognized command",
"message": "??? $COMMAND$ $ARGS$ $TEXT$",
"placeholders": {
"fullSender": {
"content": "$1",
"example": "fritz!~bob@example.net"
},
"command": {
"content": "$2",
"example": "PRIVMSG"
},
"sender": {
"content": "$3",
"example": "fritz"
},
"forum": {
"content": "$4",
"example": "#hottub"
},
"args": {
"content": "$5",
"example": "+o,fred"
},
"text": {
"content": "$6",
"example": "Hello everybody"
}
}
},
"privmsgCommand": {
"description": "Text for a privmsg (a regular chat message)",
"message": "$6"
},
"noticeCommand": {
"description": "Text for a notice",
"message": "$6"
},
"nickCommand": {
"description": "Text for nickname change",
"message": "$1 is now known as $3"
},
"modeCommand": {
"message": "sets channel mode $5"
},
"joinCommand": {
"description": "Channel join",
"message": "joins the channel."
},
"faultCommand": {
"description": "Spongy fault",
"message": "Spongy error: $6"
}
}

View file

@ -1,10 +0,0 @@
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('wirc.html', {
state: 'normal',
width: 775,
height: 400,
minWidth: 320,
minHeight: 160,
id: 'spongy'
})
})

View file

@ -1 +0,0 @@
merf.

View file

@ -1,361 +0,0 @@
<html><head>
<meta charset="utf-8">
<!-- generic -->
<script src="util.js"></script>
<script src="keycodes.js"></script>
<script src="message_handler.js"></script>
<script src="event_emitter.js"></script>
<script src="chat/notification.js"></script>
<script src="chat/notification_group.js"></script>
<script src="net/abstract_tcp_socket.js"></script>
<script src="event.js"></script>
<script src="timer.js"></script>
<script src="context.js"></script>
<!-- net -->
<script src="net/chrome_socket.js"></script>
<script src="net/ssl_socket.js"></script>
<script src="net/remote_socket.js"></script>
<!-- irc protocol -->
<script src="irc/irc.js"></script>
<script src="irc/irc_util.js"></script>
<script src="irc/ctcp_handler.js"></script>
<script src="irc/server_response_handler.js"></script>
<!-- scripting -->
<script src="script/script.js"></script>
<script src="script/prepackaged/source_array.js"></script>
<script src="script/script_handler.js"></script>
<script src="script/script_loader.js"></script>
<!-- one identity -->
<script src="remote_connection.js"></script>
<script src="chat/remote_connection_handler.js"></script>
<script src="remote_device.js"></script>
<!-- user input -->
<script src="chat/custom_command_parser.js"></script>
<script src="input_stack.js"></script>
<script src="completion_finder.js"></script>
<script src="auto_complete.js"></script>
<script src="keyboard_shortcut_map.js"></script>
<script src="user_input_handler.js"></script>
<script src="chat/user_command_handler.js"></script>
<script src="chat/user_command.js"></script>
<script src="chat/developer_commands.js"></script>
<!-- client and UI -->
<script src="chat/chat.js"></script>
<script src="chat/walkthrough.js"></script>
<script src="chat/storage.js"></script>
<script src="chat/chat_log.js"></script>
<script src="chat/notice.js"></script>
<script src="chat/message_formatter.js"></script>
<script src="chat/html_list.js"></script>
<script src="chat/nick_mentioned_notification.js"></script>
<script src="chat/irc_message_handler.js"></script>
<script src="chat/window.js"></script>
<script src="chat/window_message_renderer.js"></script>
<script src="chat/scrollable.js"></script>
<script src="chat/help_message_renderer.js"></script>
<script src="chat/nick_list.js"></script>
<script src="chat/channel_list.js"></script>
<script src="chat/window_list.js"></script>
<!-- third party -->
<script src="third_party/jquery.js"></script>
<script src="third_party/md5.js"></script>
<!-- forge SSL library -->
<script type="text/javascript" src="third_party/forge/debug.js"></script>
<script type="text/javascript" src="third_party/forge/util.js"></script>
<script type="text/javascript" src="third_party/forge/log.js"></script>
<script type="text/javascript" src="third_party/forge/socket.js"></script>
<script type="text/javascript" src="third_party/forge/md5.js"></script>
<script type="text/javascript" src="third_party/forge/sha1.js"></script>
<script type="text/javascript" src="third_party/forge/sha256.js"></script>
<script type="text/javascript" src="third_party/forge/hmac.js"></script>
<script type="text/javascript" src="third_party/forge/aes.js"></script>
<script type="text/javascript" src="third_party/forge/pem.js"></script>
<script type="text/javascript" src="third_party/forge/asn1.js"></script>
<script type="text/javascript" src="third_party/forge/jsbn.js"></script>
<script type="text/javascript" src="third_party/forge/prng.js"></script>
<script type="text/javascript" src="third_party/forge/random.js"></script>
<script type="text/javascript" src="third_party/forge/oids.js"></script>
<script type="text/javascript" src="third_party/forge/rsa.js"></script>
<script type="text/javascript" src="third_party/forge/pbe.js"></script>
<script type="text/javascript" src="third_party/forge/x509.js"></script>
<script type="text/javascript" src="third_party/forge/pki.js"></script>
<script type="text/javascript" src="third_party/forge/tls.js"></script>
<script type="text/javascript" src="third_party/forge/aesCipherSuites.js"></script>
<script type="text/javascript" src="third_party/forge/tlssocket.js"></script>
<script type="text/javascript" src="third_party/forge/http.js"></script>
<link id="main-style" rel="stylesheet" href="style.css">
<link rel="stylesheet" href="message_style.css">
<link rel="stylesheet" href="topbar.css">
<title>CIRC undefined</title></head>
<body>
<!-- templates -->
<div id="templates">
<div class="server-channels">
<div class="server room">
<div class="content-item"></div>
<div class="remove-button">-</div>
</div>
<ul class="channels"></ul>
</div>
<li class="channel room">
<div class="content-item"></div>
<div class="remove-button">-</div>
</li>
<ul class="nicks"></ul>
<li class="nick">
<div class="content-item"></div>
</li>
<ul class="messages"></ul>
<li class="message">
<div class="timestamp"></div>
<div class="source-content-container">
<div class="source"></div>
<div class="content"></div>
</div>
</li>
</div>
<!-- main -->
<div id="main">
<div id="main-top-border"></div>
<div id="rooms-and-nicks" class="">
<div id="rooms-container">
<h1>rooms</h1>
<div class="rooms"><div class="server-channels">
<div class="server room current-server">
<div class="content-item">us.slashnet.org</div>
<div class="remove-button">-</div>
</div>
<ul class="channels"><li class="channel room selected">
<div class="content-item">#tron</div>
<div class="remove-button">-</div>
</li><li class="channel room footer">
<div class="content-item">+ add channel</div>
<div class="remove-button">-</div>
</li></ul>
</div><div class="server-channels">
<div class="server room footer">
<div class="content-item">+ add server</div>
<div class="remove-button">-</div>
</div>
<ul class="channels"></ul>
</div></div>
</div>
<div id="nicks-container">
<h1>members</h1>
<ul class="nicks"><li class="nick">
<div class="content-item">also</div>
</li><li class="nick">
<div class="content-item">atob</div>
</li><li class="nick">
<div class="content-item">Bermuda</div>
</li><li class="nick">
<div class="content-item">bit</div>
</li><li class="nick">
<div class="content-item">bk</div>
</li><li class="nick">
<div class="content-item">bz2</div>
</li><li class="nick">
<div class="content-item">caycos</div>
</li><li class="nick">
<div class="content-item">ckape</div>
</li><li class="nick">
<div class="content-item">clavicle</div>
</li><li class="nick">
<div class="content-item">CrackMonkey</div>
</li><li class="nick">
<div class="content-item">Dumont</div>
</li><li class="nick">
<div class="content-item">dzho</div>
</li><li class="nick">
<div class="content-item">emad</div>
</li><li class="nick">
<div class="content-item">eythian</div>
</li><li class="nick">
<div class="content-item">felixc</div>
</li><li class="nick">
<div class="content-item">fo0bar</div>
</li><li class="nick">
<div class="content-item">fuzzie</div>
</li><li class="nick">
<div class="content-item">GodEater</div>
</li><li class="nick">
<div class="content-item">hollow</div>
</li><li class="nick">
<div class="content-item">hoylemd</div>
</li><li class="nick">
<div class="content-item">jhewl</div>
</li><li class="nick">
<div class="content-item">jv</div>
</li><li class="nick">
<div class="content-item">kees</div>
</li><li class="nick">
<div class="content-item">khmer</div>
</li><li class="nick">
<div class="content-item">lamont</div>
</li><li class="nick">
<div class="content-item">lexicondal</div>
</li><li class="nick">
<div class="content-item">neale</div>
</li><li class="nick">
<div class="content-item">nemo</div>
</li><li class="nick">
<div class="content-item">nerdtron3000</div>
</li><li class="nick">
<div class="content-item">nornagon</div>
</li><li class="nick">
<div class="content-item">Octal</div>
</li><li class="nick">
<div class="content-item">pdx6</div>
</li><li class="nick">
<div class="content-item">pedro</div>
</li><li class="nick">
<div class="content-item">Randall</div>
</li><li class="nick">
<div class="content-item">sarah</div>
</li><li class="nick">
<div class="content-item">Sciri</div>
</li><li class="nick">
<div class="content-item">scorche</div>
</li><li class="nick">
<div class="content-item">scorche|sh</div>
</li><li class="nick">
<div class="content-item">Screwtape</div>
</li><li class="nick">
<div class="content-item">sneakums</div>
</li><li class="nick">
<div class="content-item">squinky</div>
</li><li class="nick">
<div class="content-item">stat</div>
</li><li class="nick">
<div class="content-item">teferi</div>
</li><li class="nick">
<div class="content-item">tiaz</div>
</li><li class="nick">
<div class="content-item">watson</div>
</li><li class="nick">
<div class="content-item">wcarss</div>
</li><li class="nick">
<div class="content-item">wombat</div>
</li><li class="nick">
<div class="content-item">X11R5</div>
</li><li class="nick">
<div class="content-item">Zen</div>
</li><li class="nick footer">
<div class="content-item">footer</div>
</li></ul></div>
</div>
<div class="dragbar"></div>
<div id="messages-and-input">
<div id="topic-container">
<button id="hide-channels" class="topbar-button">=</button>
<div id="status" class="content-item"><span title="Spel werkt, vertel het door! | hype mismatch error | ERG DRUK | <ginnie> everything is awesome! | Save The Date: 20150212 is Dumont's 15th Birthday | sparrows form Voltron | Deksels! | sysadmin establishment &quot;hanged&quot; by lunatic devop | Levis dehydrates unisexual cleavage. | A fanfare for locked traffic --" class="topic">Spel werkt, vertel het door! | hype mismatch error | ERG DRUK | &lt;ginnie&gt; everything is awesome! | Save The Date: 20150212 is Dumont's 15th Birthday | sparrows form Voltron | Deksels! | sysadmin establishment "hanged" by lunatic devop | Levis dehydrates unisexual cleavage. | A fanfare for locked traffic --</span></div>
</div>
<div id="notice" class="hide">
<div class="content"></div>
<button class="close">X</button>
<button class="option2 hidden"></button>
<button class="option1 hidden"></button>
</div>
<div id="messages-container"><ul class="messages"><li class="message system">
<div class="timestamp">3:46:12 PM</div>
<div class="source-content-container">
<div class="source empty"></div>
<div class="content"><span>Awesome, you've connected to #tron.</span></div>
</div>
</li><li class="message system">
<div class="timestamp">3:46:12 PM</div>
<div class="source-content-container">
<div class="source empty"></div>
<div class="content"><span>If you're ever stuck, type /help to see a list of all commands.</span></div>
</div>
</li><li class="message system">
<div class="timestamp">3:46:12 PM</div>
<div class="source-content-container">
<div class="source empty"></div>
<div class="content"><span>You can switch windows with alt+[0-9] or click in the channel list on the left.</span></div>
</div>
</li><li class="message update join self">
<div class="timestamp">3:46:12 PM</div>
<div class="source-content-container">
<div class="source empty"></div>
<div class="content"><span>(You joined the channel)</span></div>
</div>
</li><li class="message notice topic">
<div class="timestamp">3:46:12 PM</div>
<div class="source-content-container">
<div class="source empty"></div>
<div class="content"><span>The topic is: Spel werkt, vertel het door! | hype mismatch error | ERG DRUK | &lt;ginnie&gt; everything is awesome! | Save The Date: 20150212 is Dumont's 15th Birthday | sparrows form Voltron | Deksels! | sysadmin establishment "hanged" by lunatic devop | Levis dehydrates unisexual cleavage. | A fanfare for locked traffic --</span></div>
</div>
</li><li class="message notice topic_info">
<div class="timestamp">3:46:12 PM</div>
<div class="source-content-container">
<div class="source empty"></div>
<div class="content"><span>Topic set by sneakums on Fri Oct 17 2014 16:05:00 GMT-0600 (MDT).</span></div>
</div>
</li><li class="message notice-group notice">
<div class="timestamp">3:46:12 PM</div>
<div class="source-content-container">
<div class="source empty"></div>
<div class="content"><span>Received a CTCP VERSION from squinky.</span></div>
</div>
</li><li class="message update privmsg self">
<div class="timestamp">3:47:13 PM</div>
<div class="source-content-container">
<div class="source" colornumber="22"><span>nerdtron3000</span></div>
<div class="content"><span>merf</span></div>
</div>
</li><li class="message update privmsg self">
<div class="timestamp">3:47:53 PM</div>
<div class="source-content-container">
<div class="source" colornumber="22"><span>nerdtron3000</span></div>
<div class="content"><span>X11R5: say something to me</span></div>
</div>
</li><li class="message update mention privmsg">
<div class="timestamp">3:47:55 PM</div>
<div class="source-content-container">
<div class="source" colornumber="22"><span>X11R5</span></div>
<div class="content"><span>nerdtron3000: Get me some of those things where 99 times out on to something.</span></div>
</div>
</li><li class="message update privmsg self">
<div class="timestamp">3:48:01 PM</div>
<div class="source-content-container">
<div class="source" colornumber="22"><span>nerdtron3000</span></div>
<div class="content"><span>...</span></div>
</div>
</li><li class="message update privmsg">
<div class="timestamp">3:48:02 PM</div>
<div class="source-content-container">
<div class="source" colornumber="12"><span>Dumont</span></div>
<div class="content"><span>[You have a sad feeling for a moment, then it passes.]</span></div>
</div>
</li></ul></div>
<div id="nick-and-input">
<div id="nick"><span class="name">nerdtron3000</span></div><input id="input" class="" style="-webkit-transition: 300ms; transition: 300ms;">
</div>
</div>
</div>
<script src="main.js"></script>
<iframe src="script_frame.html" style="display: none;"></iframe></body></html>

View file

@ -1,27 +0,0 @@
{
"manifest_version": 2,
"version": "1.0",
"name": "__MSG_appName__",
"short_name": "__MSG_appShortName__",
"description": "__MSG_appDesc__",
"author": "Neale Pickett <neale@woozle.org>",
"icons": {
"16": "icon-16.png",
"32": "icon-32.png",
"48": "icon-48.png",
"128": "icon-128.png",
"256": "icon-256.png"
},
"app": {
"background": {
"scripts": ["background.js"]
}
},
"permissions": [
"storage",
"fileSystem",
"https://woozle.org/"
],
"default_locale": "en"
}

View file

@ -1,165 +0,0 @@
.message.mode, .message.nick, .message.join {
color: #606043;
}
.message.notice {
color: #97008B;
font-style: oblique;
}
.message.error {
color: #B33B2D;
}
.message.self {
color: #005816;
}
.message.privmsg {
color: #505053;
}
.message.privmsg.self {
color: gray;
}
.message.privmsg.mention {
color: darkred;
}
.message.privmsg.mention .source {
font-weight: bold;
}
.message.privmsg.direct .source {
color: #488AA8;
}
/* Nickname Colors. Taken from Textual */
.message.privmsg.self .source-content-container .source {
color: #ea0d68;
}
.message:not(.self) .source-content-container .source[colornumber='0'] {
color: #0080ff;
}
.message:not(.self) .source-content-container .source[colornumber='1'] {
color: #059005;
}
.message:not(.self) .source-content-container .source[colornumber='2'] {
color: #a80054;
}
.message:not(.self) .source-content-container .source[colornumber='3'] {
color: #9b0db1;
}
.message:not(.self) .source-content-container .source[colornumber='4'] {
color: #108860;
}
.message:not(.self) .source-content-container .source[colornumber='5'] {
color: #7F4FFF;
}
.message:not(.self) .source-content-container .source[colornumber='6'] {
color: #58701a;
}
.message:not(.self) .source-content-container .source[colornumber='7'] {
color: #620a8e;
}
.message:not(.self) .source-content-container .source[colornumber='8'] {
color: #BB0008;
}
.message:not(.self) .source-content-container .source[colornumber='9'] {
color: #44345f;
}
.message:not(.self) .source-content-container .source[colornumber='10'] {
color: #2f5353;
}
.message:not(.self) .source-content-container .source[colornumber='11'] {
color: #904000;
}
.message:not(.self) .source-content-container .source[colornumber='12'] {
color: #808000;
}
.message:not(.self) .source-content-container .source[colornumber='13'] {
color: #57797e;
}
.message:not(.self) .source-content-container .source[colornumber='14'] {
color: #3333dd;
}
.message:not(.self) .source-content-container .source[colornumber='15'] {
color: #5f4d22;
}
.message:not(.self) .source-content-container .source[colornumber='16'] {
color: #706616;
}
.message:not(.self) .source-content-container .source[colornumber='17'] {
color: #46799c;
}
.message:not(.self) .source-content-container .source[colornumber='18'] {
color: #80372e;
}
.message:not(.self) .source-content-container .source[colornumber='19'] {
color: #8F478E;
}
.message:not(.self) .source-content-container .source[colornumber='20'] {
color: #5b9e4c;
}
.message:not(.self) .source-content-container .source[colornumber='21'] {
color: #13826c;
}
.message:not(.self) .source-content-container .source[colornumber='22'] {
color: #b13637;
}
.message:not(.self) .source-content-container .source[colornumber='23'] {
color: #e45d59;
}
.message:not(.self) .source-content-container .source[colornumber='24'] {
color: #1b51ae;
}
.message:not(.self) .source-content-container .source[colornumber='25'] {
color: #4855ac;
}
.message:not(.self) .source-content-container .source[colornumber='26'] {
color: #7f1d86;
}
.message:not(.self) .source-content-container .source[colornumber='27'] {
color: #73643f;
}
.message:not(.self) .source-content-container .source[colornumber='28'] {
color: #0b9578;
}
.message:not(.self) .source-content-container .source[colornumber='29'] {
color: #569c96;
}
.message:not(.self) .source-content-container .source[colornumber='30'] {
color: #08465f;
}

View file

@ -1,102 +0,0 @@
// Functionality dealing with server-level things
var maxScrollback = 500;
var networks = {};
function networkConnect(network, baseURL, authtok) {
var eventSource;
var element = getTemplate("server-channels");
var channels = element.getElementsByClassName("channels")[0];
var roomElement = element.getElementsByClassName("server")[0];
var rooms = {".": roomElement};
newRoom(roomElement, element, network, maxScrollback);
function makeRoom(name) {
var rElement = getTemplate("channel");
newRoom(rElement, element, name, maxScrollback);
channels.appendChild(rElement);
rooms[name] = rElement;
return rElement;
}
function handleEventSourceLine(line) {
var lhs = line.split(" :", 1)[0];
var parts = lhs.split(' ');
var timestamp = new Date(parts[0] * 1000);
var fullSender = parts[1];
var command = parts[2].toLowerCase();
var sender = parts[3];
var forum = parts[4];
var args = parts.slice(5);
var txt = line.substr(lhs.length + 2);
switch (command) {
case "prevlog":
// Just ignore this
return;
}
var room = rooms[forum];
if (! room) {
room = makeRoom(forum);
}
// XXX: Handle differently based on command
room.addMessage(timestamp, fullSender, command, sender, args, txt);
}
function handleEventSourceMessage(oEvent) {
msgs = oEvent.data.split("\n");
var first = Math.max(0, msgs.length - maxScrollback);
for (var i = first; i < msgs.length; i += 1) {
handleEventSourceLine(msgs[i]);
}
}
function handleEventSourceError(oEvent) {
timestamp = new Date();
roomElement.addMessage(timestamp, ".", "fault", ".", [], "Unable to open events feed (permissions problem on server?)");
console.log(oEvent);
}
element.send = function(target, text) {
function handleError(oEvent) {
console.log("XXX: That didn't work out.", target, text)
}
var form = new FormData();
form.append("type", "command");
form.append("auth", authtok);
form.append("network", network);
form.append("target", target);
form.append("text", text);
var oReq = new XMLHttpRequest();
oReq.addEventListener("error", handleError);
oReq.open("POST", baseURL, true);
oReq.send(form);
}
element.close = function() {
console.log("Closing");
eventSource.close();
element.parentNode.removeChild(element);
roomElement.close();
// XXX: Close all associated rooms, too!
}
if (networks[network]) {
networks[network].close();
}
networks[network] = element;
var pullURL = baseURL + "?network=" + encodeURIComponent(network) + "&auth=" + encodeURIComponent(authtok);
eventSource = new EventSource(pullURL);
eventSource.addEventListener("message", handleEventSourceMessage);
eventSource.addEventListener("error", handleEventSourceError);
document.getElementsByClassName("rooms")[0].appendChild(element);
}

View file

@ -1,162 +0,0 @@
function djbhash(a) {
var r = 5381;
for (var i = 0; i < a.length; i += 1) {
r = (((r << 5) + r) + a.charCodeAt(i)) & 0xffff;
}
return r;
}
function purtify(text) {
// Look for a URL
var txtElement = document.createElement("span");
txtElement.className = "text";
var rhs = text;
var match;
while ((match = urlRe.exec(rhs)) != null) {
var before = rhs.substr(0, match.index);
var a = document.createElement("a");
var href = match[0];
if (href.indexOf("hxx") == 0) {
href = "htt" + href.substr(3);
}
a.href = href
a.target = "_blank";
a.appendChild(document.createTextNode(match[0]));
txtElement.appendChild(document.createTextNode(before));
txtElement.appendChild(a);
rhs = rhs.substr(match.index + match[0].length);
}
txtElement.appendChild(document.createTextNode(rhs));
return txtElement;
}
function kiboze(this_is_currently_busted) {
if ((kiboze) || (-1 != text.search(kibozeRe))) {
var k = document.getElementById("kiboze");
var p2 = p.cloneNode(true);
if (k) {
k.insertBefore(p2, k.firstChild);
p2.onclick = function() { focus(p); }
// Setting title makes the tab flash sorta
document.title = document.title;
}
}
}
var visibleRoom;
function newRoom(element, network, name, maxSize) {
var messages = getTemplate("messages");
var lastmsg;
if (! maxSize) {
maxSize = 500;
}
function purtify(fullSender, command, sender, args, txt) {
var txtElement = document.createElement("span");
var msg = chrome.i18n.getMessage(command + "Command", [fullSender, command, sender, name, args, txt]);
if (! msg) {
msg = chrome.i18n.getMessage("unknownCommand", [fullSender, command, sender, name, String(args), txt]);
}
var rhs = msg;
var match;
while ((match = urlRe.exec(rhs)) != null) {
var before = rhs.substr(0, match.index);
var a = document.createElement("a");
var href = match[0];
if (href.indexOf("hxx") == 0) {
href = "htt" + href.substr(3);
}
a.href = href
a.target = "_blank";
a.appendChild(document.createTextNode(match[0]));
txtElement.appendChild(document.createTextNode(before));
txtElement.appendChild(a);
rhs = rhs.substr(match.index + match[0].length);
}
txtElement.appendChild(document.createTextNode(rhs));
return txtElement;
}
element.addMessage = function(timestamp, fullSender, command, sender, args, txt) {
var message = getTemplate("message");
var eTimestamp = message.getElementsByClassName("timestamp")[0];
var eSource = message.getElementsByClassName("source")[0];
var eContent = message.getElementsByClassName("content")[0];
message.classList.add(command);
if (sender == ".") {
message.classList.add("self");
}
eTimestamp.textContent = timestamp.toLocaleTimeString();
eSource.textContent = sender;
eSource.setAttribute("colornumber", djbhash(sender) % 31);
eContent.appendChild(purtify(fullSender, command, sender, args, txt));
messages.appendChild(message);
while (messages.childNodes.length > maxSize) {
messages.removeChild(messages.firstChild);
}
lastmsg = message;
if (visibleRoom == element) {
lastmsg.scrollIntoView(false);
}
}
element.hide = function() {
element.classList.remove("selected");
messages.style.display = "none";
}
element.show = function() {
if (visibleRoom) {
visibleRoom.hide()
}
element.classList.add("selected");
messages.style.display = null;
lastmsg.scrollIntoView(false);
visibleRoom = element;
}
element.send = function(text) {
network.send(name, text);
}
element.close = function() {
console.log(messages);
console.log(messages.parent);
messages.parent.removeChild(messages);
element.parent.removeChild(element);
}
function clicked() {
element.show();
}
// start hidden
element.hide();
element.addEventListener("click", clicked);
element.getElementsByClassName("content-item")[0].textContent = name;
document.getElementById("messages-container").appendChild(messages);
return element;
}

View file

</
@ -1,484 +0,0 @@
html, body {
margin: 0;
padding: 0
}
*, *:before, *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
color: #505053;
/* font-family: sans-serif; */
font-size: 100%;
}
.hidden {
display: none;
}
#templates {
display: none;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
.footer {
display: none;
font-style: italic;
color: #9493A2;
}
.help-command {
display: inline-block;
width: 7em;
}
.content-item {
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
}
#main {
display: -webkit-box;
-webkit-box-orient: horizontal;
width: 100%;
height: 100%;
position: absolute;
border-top: 1px solid rgba(0,0,0,0.15);
}
#main-top-border {
position: absolute;
top: 0;
z-index: 100;
width: 100%;
height: 1px;
background-color: rgba(0,0,0,0.05);
pointer-events: none;
}
#rooms-and-nicks {
background-color: #F7F5E4;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-flex: 0;
width: 150px;
height: inherit;
padding: 4px 0px;
border-right: 1px solid rgba(0, 0, 0, .15);
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
#rooms-and-nicks h1 {
color: #406698;
text-transform: uppercase;
font-size: smaller;
padding: 8px 0px 2px 8px;
margin: 0px;
}
#rooms-and-nicks .nick,
#rooms-and-nicks .room {
padding: 0 8px;
line-height: 26px;
}
#rooms-and-nicks .room {
cursor: pointer;
}
#rooms-and-nicks .server.footer {
display: block;
}
.dragbar:hover {
width: 6px;
transition: width .1s;
}
.dragbar {
height: 100%;
width: 1px;
cursor: col-resize;
}
#ghostbar{
width:3px;
background-color:#000;
opacity:0.8;
position:absolute;
cursor: col-resize;
z-index:999
}
#rooms-container {
-webkit-box-flex: 0;
border-bottom: 1px solid #CCC;
padding-bottom: 10px;
}
.no-nicks #rooms-container {
border-bottom-style: none;
padding-bottom: 0px;
}
#rooms-and-nicks.hidden {
display: none;
}
#rooms-and-nicks .room.server {
background-color: #F2EFD3;
position: relative;
}
#rooms-and-nicks:hover .room.server .content-item {
width: 130px;
}
#rooms-and-nicks .add-channel {
position: absolute;
right: 2px;
top: -1px;
cursor: pointer;
font-size: larger;
display: none;
}
#rooms-and-nicks:hover .add-channel {
display: block;
}
#rooms-and-nicks .add-channel:hover {
color: #888;
}
#rooms-and-nicks .room.channel:first-child {
padding-top: 3px;
}
#rooms-and-nicks .room.channel:first-child .content-item {
padding-bottom: 3px;
line-height: 20px;
}
#rooms-and-nicks not(.current-server) + .channels .room.channel:nth-last-child(2) {
padding-bottom: 3px;
}
#rooms-and-nicks .room.channel:last-child {
padding-bottom: 3px;
}
#rooms-and-nicks not(.current-server) + .channels .room.channel:nth-last-child(2) .content-item {
padding-top: 3px;
line-height: 20px;
}
#rooms-and-nicks .room.channel:last-child .content-item {
padding-top: 3px;
line-height: 20px;
}
#rooms-and-nicks not(.current-server) + .channels .room.channel:nth-last-child(2):first-child .content-item {
line-height: 14px;
}
#rooms-and-nicks .room.channel:last-child:first-child .content-item {
line-height: 14px;
}
#rooms-and-nicks .current-server:not(.always-empty) + .channels .footer {
display: block;
}
#rooms-and-nicks .room.channel .content-item {
border-left: 1px solid rgba(0, 0, 0, .5);
padding-left: 7px;
}
#rooms-and-nicks .room.activity {
font-weight: bold;
}
#rooms-and-nicks .room.mention {
color: darkred;
}
#rooms-and-nicks .room.disconnected .content-item {
color: #9493A2;
font-style: italic;
}
#rooms-and-nicks .room.channel.disconnected .content-item {
border-left: 1px solid #9493A2;
}
#rooms-and-nicks .room.selected {
background-color: #F0E798;
}
#rooms-and-nicks .room {
position: relative;
}
#rooms-and-nicks .room .remove-button {
position: absolute;
right: 6px;
top: -1px;
cursor: pointer;
font-size: x-large;
color: rgba(0, 0, 0, .25);
display: none;
}
#rooms-and-nicks .room .remove-button:hover {
color: rgba(0, 0, 0, .5);
}
#rooms-and-nicks .room.selected:not(.footer):not(.always-empty) .content-item {
width: 123px;
}
#rooms-and-nicks .room:hover:not(.footer):not(.always-empty) .content-item {
width: 123px;
}
#rooms-and-nicks .room.selected:not(.footer):not(.always-empty) .remove-button {
display: inline-block;
}
#rooms-and-nicks .room:hover:not(.footer):not(.always-empty) .remove-button {
display: inline-block;
}
#nicks-container {
border-top: 1px solid #FFF;
-webkit-box-flex: 1;
}
.no-nicks #nicks-container {
display: none;
}
.rooms,
.nicks {
padding-top: 5px;
}
.nicks li:nth-child(odd) {
background-color: #F2EFD3;
}
#notice {
background-color: #406698;
box-shadow: 0px 1px 4px #888;
color: #FFF;
position: absolute;
width: 100%;
-webkit-transition: 150ms;
top: 0;
padding: 2px 0;
}
#notice.hide {
top: -38px;
}
#notice .content {
display: inline;
padding-left: 14px;
text-overflow: ellipsis;
white-space: nowrap;
overflow-x: hidden;
position: absolute;
top: 50%;
margin-top: -.5em;
}
#notice button {
float: right;
height: 22px;
font-size: 14px;
padding: 0px 4px;
margin: 4px;
border: none;
background-color: #ECECEC;
color: #505053;
cursor: pointer;
outline: none;
}
#notice button.close {
margin-right: 8px;
font-size: 12px;
border-radius: 42px;
width: 21px;
height: 21px;
}
#messages-and-input {
-webkit-box-flex: 1;
display: -webkit-box;
-webkit-box-orient: vertical;
box-shadow: 0px 0px 8px #CCC;
position: relative;
}
#messages-container {
overflow-y: auto;
-webkit-overflow-scrolling: touch;
-webkit-box-flex: 1;
border-bottom: 1px solid #CCC;
}
.messages {
display: table;
}
.message {
display: table-row;
-webkit-user-select: initial;
}
.message.activity-marker .source-content-container {
border-top: 1px solid rgb(224, 179, 179);
}
.message .timestamp {
color: #6060C0;
font-style: italic;
/* font-size: smaller; */
white-space: nowrap;
display: table-cell;
text-align: right;
padding: 0px 10px 0px 10px;
border-right: 1px solid rgba(0,0,0,0.15);
cursor: text;
}
.source-content-container {
display: table-cell;
padding: 1px 10px 1px 15px;
width: 100%;
}
.message .source {
font-weight: bold;
padding-right: 5px;
margin-left: -5px;
white-space: nowrap;
display: inline;
text-align: right;
cursor: text;
}
.message .source.empty {
padding-right: 0;
}
.message .content {
display: inline;
white-space: pre-wrap;
cursor: text;
word-break: break-word;
}
#messages-container .messages .message:first-child .source-content-container {
padding-top: 10px;
}
#messages-container .messages .message:last-child .source-content-container {
padding-bottom: 8px;
}
.message.list {
/* empty style for now */
}
.longword { word-break: break-all; }
#nick-and-input {
border-top: 1px solid #F9F9F9;
-webkit-box-flex: 0;
display: -webkit-box;
background-color: #ECECEC;
padding: 5px 10px 5px 10px;
}
#nick {
padding-top: 5px;
}
#nick > span {
padding-right: 10px;
}
#nick > .name:before {
font-weight: bold;
content: "[ "
}
#nick > .name:after {
font-weight: bold;
content: " ]"
}
#nick .away:before {
content: "("
}
#nick .away:after {
content: ")"
}
#input-bar {
-webkit-box-flex: 1;
display: -webkit-box;
}
#input {
background-color: #F9F9F9;
display: block;
-webkit-box-flex: 1;
width: 100%;
height: 30px;
border: 1px;
border-radius: 5px;
-webkit-box-shadow: 0px 0px 3px #888;
color: #505053;
font-size: 100%;
padding: 0px 8px;
outline: 0;
}
#input.blink {
-webkit-box-shadow: 0px 0px 6px #406698;
}
::-webkit-scrollbar {
width: 9px;
height: 9px;
}
::-webkit-scrollbar-button:start:decrement,