diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json new file mode 100644 index 0000000..c0c2c24 --- /dev/null +++ b/app/_locales/en/messages.json @@ -0,0 +1,15 @@ +{ + "appName": { + "message": "wIRC Chat Client", + "description": "Application name" + }, + "appShortName": { + "message": "wIRC", + "description": "Short application name" + }, + "appDesc": { + "message": "Chat client for the wIRC bouncer thingamajiggy", + "description": "Application description for app store listing" + } +} + diff --git a/app/background.js b/app/background.js new file mode 100644 index 0000000..31c2421 --- /dev/null +++ b/app/background.js @@ -0,0 +1,5 @@ +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('wirc.html', { + 'state': 'normal' + }) +}) diff --git a/app/example.html b/app/example.html new file mode 100644 index 0000000..0c07b8a --- /dev/null +++ b/app/example.html @@ -0,0 +1,361 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +CIRC undefined + + + +
+ +
+
+
+
-
+
+ +
+ +
  • +
    +
    -
    +
  • + + + +
  • +
    +
  • + + + +
  • +
    +
    +
    +
    +
    +
  • + +
    + + +
    +
    +
    +
    +

    rooms

    +
    +
    +
    us.slashnet.org
    +
    -
    +
    +
    • +
      #tron
      +
      -
      +
    +
    + +
      +
      +
      +
      +

      members

      +
      • +
        also
        +
      • +
        atob
        +
      • +
        Bermuda
        +
      • +
        bit
        +
      • +
        bk
        +
      • +
        bz2
        +
      • +
        caycos
        +
      • +
        ckape
        +
      • +
        clavicle
        +
      • +
        CrackMonkey
        +
      • +
        Dumont
        +
      • +
        dzho
        +
      • +
        emad
        +
      • +
        eythian
        +
      • +
        felixc
        +
      • +
        fo0bar
        +
      • +
        fuzzie
        +
      • +
        GodEater
        +
      • +
        hollow
        +
      • +
        hoylemd
        +
      • +
        jhewl
        +
      • +
        jv
        +
      • +
        kees
        +
      • +
        khmer
        +
      • +
        lamont
        +
      • +
        lexicondal
        +
      • +
        neale
        +
      • +
        nemo
        +
      • +
        nerdtron3000
        +
      • +
        nornagon
        +
      • +
        Octal
        +
      • +
        pdx6
        +
      • +
        pedro
        +
      • +
        Randall
        +
      • +
        sarah
        +
      • +
        Sciri
        +
      • +
        scorche
        +
      • +
        scorche|sh
        +
      • +
        Screwtape
        +
      • +
        sneakums
        +
      • +
        squinky
        +
      • +
        stat
        +
      • +
        teferi
        +
      • +
        tiaz
        +
      • +
        watson
        +
      • +
        wcarss
        +
      • +
        wombat
        +
      • +
        X11R5
        +
      • +
        Zen
        +
      +
      + +
      + +
      +
      + +
      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 "hanged" by lunatic devop | Levis dehydrates unisexual cleavage. | A fanfare for locked traffic --
      +
      +
      +
      + + + +
      +
      • +
        3:46:12 PM
        +
        +
        +
        Awesome, you've connected to #tron.
        +
        +
      • +
        3:46:12 PM
        +
        +
        +
        If you're ever stuck, type /help to see a list of all commands.
        +
        +
      • +
        3:46:12 PM
        +
        +
        +
        You can switch windows with alt+[0-9] or click in the channel list on the left.
        +
        +
      • +
        3:46:12 PM
        +
        +
        +
        (You joined the channel)
        +
        +
      • +
        3:46:12 PM
        +
        +
        +
        The topic is: 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 "hanged" by lunatic devop | Levis dehydrates unisexual cleavage. | A fanfare for locked traffic --
        +
        +
      • +
        3:46:12 PM
        +
        +
        +
        Topic set by sneakums on Fri Oct 17 2014 16:05:00 GMT-0600 (MDT).
        +
        +
      • +
        3:46:12 PM
        +
        +
        +
        Received a CTCP VERSION from squinky.
        +
        +
      • +
        3:47:13 PM
        +
        +
        nerdtron3000
        +
        merf
        +
        +
      • +
        3:47:53 PM
        +
        +
        nerdtron3000
        +
        X11R5: say something to me
        +
        +
      • +
        3:47:55 PM
        +
        +
        X11R5
        +
        nerdtron3000: Get me some of those things where 99 times out on to something.
        +
        +
      • +
        3:48:01 PM
        +
        +
        nerdtron3000
        +
        ...
        +
        +
      • +
        3:48:02 PM
        +
        +
        Dumont
        +
        [You have a sad feeling for a moment, then it passes.]
        +
        +
      +
      +
      nerdtron3000
      +
      +
      +
      + + + + \ No newline at end of file diff --git a/app/manifest.json b/app/manifest.json new file mode 100644 index 0000000..227be33 --- /dev/null +++ b/app/manifest.json @@ -0,0 +1,21 @@ +{ + "manifest_version": 2, + "version": "1.0", + + "name": "__MSG_appName__", + "short_name": "__MSG_appShortName__", + "description": "__MSG_appDesc__", + "author": "Neale Pickett ", + "icons": {"128": "wirc.png"}, + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "permissions": [ + "storage", + "fileSystem", + "https://woozle.org/" + ], + "default_locale": "en" +} diff --git a/app/message_style.css b/app/message_style.css new file mode 100644 index 0000000..5da3f16 --- /dev/null +++ b/app/message_style.css @@ -0,0 +1,172 @@ +.message.system { + color: #505053; +} + +.message.notice { + color: #97008B; +} + +.message.error { + color: #B33B2D; +} + +.message.update { + color: #00068F; +} + +.message.update.self { + color: #005816; +} + +.message.update.privmsg { + color: #505053; +} + +.message.update.privmsg.self { + color: gray; +} + +.message.update.privmsg.mention { + color: darkred; +} + +.message.update.privmsg.mention .source { + font-weight: bold; +} + +.message.update.privmsg.direct .source { + color: #488AA8; +} + +.message.update.privmsg.notice .source { + color: #97008B; +} + +/* Nickname Colors. Taken from Textual */ + +.message.update.privmsg.self .source-content-container .source { + color: #ea0d68; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='0'] { + color: #0080ff; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='1'] { + color: #059005; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='2'] { + color: #a80054; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='3'] { + color: #9b0db1; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='4'] { + color: #108860; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='5'] { + color: #7F4FFF; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='6'] { + color: #58701a; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='7'] { + color: #620a8e; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='8'] { + color: #BB0008; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='9'] { + color: #44345f; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='10'] { + color: #2f5353; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='11'] { + color: #904000; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='12'] { + color: #808000; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='13'] { + color: #57797e; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='14'] { + color: #3333dd; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='15'] { + color: #5f4d22; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='16'] { + color: #706616; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='17'] { + color: #46799c; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='18'] { + color: #80372e; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='19'] { + color: #8F478E; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='20'] { + color: #5b9e4c; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='21'] { + color: #13826c; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='22'] { + color: #b13637; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='23'] { + color: #e45d59; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='24'] { + color: #1b51ae; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='25'] { + color: #4855ac; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='26'] { + color: #7f1d86; +} +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='27'] { + color: #73643f; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='28'] { + color: #0b9578; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='29'] { + color: #569c96; +} + +.message.update.privmsg:not(.self) .source-content-container .source[colornumber='30'] { + color: #08465f; +} diff --git a/app/server.js b/app/server.js new file mode 100644 index 0000000..4749e41 --- /dev/null +++ b/app/server.js @@ -0,0 +1,38 @@ +// Functionality dealing with server-level things + +var maxScrollback = 500; + +function Server(baseURL, network, authtok, messageHandler) { + 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]; + var sender = parts[3]; + var forum = parts[4]; + var args = parts.slice(5); + var txt = line.substr(lhs.length + 2); + + messageHandler(timestamp, fullSender, command, sender, forum, args, txt); + } + + function handleEventSourceMessage(oEvent) { + msgs = oEvent.data.split("\n"); + + var first = Math.min(0, msgs.length - maxScrollback); + for (var i = first; i < msgs.length; i += 1) { + handleEeventSourceLine(msgs[i]); + } + } + + function handleEventSourceError(oEvent) { + timestamp = new Date(); + messageHandler(timestamp, null, "ERROR", null, null, [], null); + } + + var pullURL = baseURL + "?network=" + encodeURIComponent(network) + "&authtok=" + encodeURIComponent(authtok); + this.eventSource = new EventSource(baseURL); + this.eventSource.addEventListener("message", handleEventSourceMessage); + this.eventSource.addEventListener("error", handleEventSourceError); +} diff --git a/app/style.css b/app/style.css new file mode 100644 index 0000000..7ece3ca --- /dev/null +++ b/app/style.css @@ -0,0 +1,510 @@ +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: 14px; +} + +.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: 12px; + 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: 18px; + 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: 30px; + 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: 4px 10px 4px 15px; + width: 100%; +} + +.message .sender { + font-weight: bold; + padding-right: 5px; + margin-left: -5px; + white-space: nowrap; + display: inline; + text-align: right; + cursor: text; +} + +.message .sender.empty { + padding-right: 0; +} + +.message .text { + display: inline; + white-space: pre-wrap; + cursor: text; +} + +#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:not(.privmsg) + .message.privmsg .source-content-container { + padding-top: 4px; + padding-bottom: 1px; +} +.message.privmsg + .message.privmsg .source-content-container { + padding-top: 1px; + padding-bottom: 1px; +} + +.message:not(.group) + .message.group .source-content-container { + padding-top: 4px; + padding-bottom: 0px; +} +.message.group + .message.group .source-content-container { + padding-top: 0px; + padding-bottom: 0px; +} + +.message:not(.notice-group) + .message.notice-group .source-content-container { + padding-top: 4px; + padding-bottom: 0px; +} +.message.notice-group + .message.notice-group .source-content-container { + padding-top: 0px; + padding-bottom: 0px; +} + +.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: 14px; + 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, +::-webkit-scrollbar-button:end:increment { + display: block; + height: 0; +} +::-webkit-scrollbar-track-piece { + background-color: rgba(0,0,0,0.1); +} +::-webkit-scrollbar-thumb:vertical { + height: 50px; + background-color: #999; + border-radius: 8px; +} +::-webkit-scrollbar-thumb:vertical:hover { + background-color: #888; +} +::-webkit-scrollbar-thumb:horizontal { + width: 50px; + background-color: #999; + border-radius: 8px; +} diff --git a/app/topbar.css b/app/topbar.css new file mode 100644 index 0000000..8db1003 --- /dev/null +++ b/app/topbar.css @@ -0,0 +1,43 @@ +#hide-channels { + display: inline-block; + font-size: 12px; +} + +#topic-container { + border-bottom: 1px solid #CCC; + -webkit-box-flex: 0; + display: -webkit-box; + background-color: #ECECEC; + padding: 4px 6px; +} + +#status { + -webkit-box-flex: 1; + padding: 4px 5px; +} + +#status .topic { + font-style: italic; +} + +.topbar-button { + background: rgba(0, 0, 0, .08); + border: 0 transparent; + text-decoration: none; + cursor: pointer; + border-radius: 2px; + -webkit-transition: .1s linear -webkit-box-shadow; + margin-right: 4px; +} + +.topbar-button:active { + box-shadow: 0 0 0 1px rgba(0 ,0 ,0 ,.15) inset, 0 0 6px rgba(0, 0, 0, .2) inset; +} + +.topbar-button:hover { + background: rgba(0, 0, 0, .13); +} + +.topbar-button:focus { + outline: none; +} diff --git a/app/wirc.html b/app/wirc.html new file mode 100644 index 0000000..27dd1db --- /dev/null +++ b/app/wirc.html @@ -0,0 +1,79 @@ + + + + + + + + + + + + +
      + +
      +
      +
      +
      -
      +
      +
        +
        + +
      • +
        +
        -
        +
      • + + + +
      • +
        +
      • + + + +
      • +
        +
        +
        +
        +
        +
      • + +
        + + +
        +
        +
        +
        +

        rooms

        +
        +
        +
        +

        members

        +
        +
        + +
        + +
        +
        + +
        +
        +
        +
        + + + +
        +
        +
        +
        +
        +
        +
        + + diff --git a/app/wirc.js b/app/wirc.js new file mode 100644 index 0000000..349e824 --- /dev/null +++ b/app/wirc.js @@ -0,0 +1,237 @@ +var msgRe = /([^ ]+) (<[^>]+>) (.*)/; +var kibozeRe = /[Nn]eal/; +var urlRe = /[a-z]+:\/\/[^ ]*/; + +var nick = "Mme. M"; + +var scrollbackLength = 500; + +if (String.prototype.startsWith == null) { + String.prototype.startsWith = function(needle) { + return this.lastIndexOf(needle, 0) == 0; + } +} + +function getTemplate(className) { + return document.templates.getElementsByClassName(className)[0].cloneNode(true); +} + +function isinView(oObject) { + return (oObject.offsetParent.clientHeight <= oObject.offsetTop); +} + +function selectForum(room) { + var kids = document.rooms_list.childNodes; + + for (i = 0; i < kids.length; i += 1) { + e = kids[i]; + if (e == room) { + e.className = "room selected"; + e.messages.display = "block"; + } else { + e.className = "room"; + e.messages.display = "none"; + } + } + + if (room.lastChild) { + room.lastChild.scrollIntoView(false); + } +} + +fora = {} +function getForumElement(forum) { + var fe = fora[forum]; + + if (! fe) { + var room = getTemplate("channel room"); + room.textContent = forum; + document.rooms_list.appendChild(room); + + fe = getTemplate("messages"); + fe.room = room; + + room.messages = fe; + // XXX: split out into non-anon function + room.addEventListener("click", function() {selectForum(fe)}); + + fora[forum] = fe; + document.getElementById("messages-container").appendChild(fe); + } + + return fe; +} + +function addMessagePart(p, className, text) { + var e = document.createElement("span"); + e.className = className; + e.appendChild(document.createTextNode(text)); + p.appendChild(e); + p.appendChild(document.createTextNode(" ")); +} + +function addText(p, text, kiboze) { + // 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)); + p.appendChild(txtElement); + + 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; + } + } +} + +function focus(e) { + var pct = 1; + var timeout; + + selectForum(e.parentNode); + e.scrollIntoView(false); + e.style.backgroundColor = "yellow"; + + timeout = setInterval(function() { + pct = pct - 0.1; + e.style.backgroundColor = "rgba(255, 255, 0, " + pct + ")"; + if (pct <= 0) { + e.style.backgroundColor = "inherit"; + clearInterval(timeout); + } + }, 50) +} + +function addMessage(txt) { + var lhs = txt.split(" :", 1)[0] + var parts = lhs.split(' ') + var ts = new Date(parts[0] * 1000); + var fullSender = parts[1]; + var command = parts[2]; + var sender = parts[3]; + var forum = parts[4]; + var args = parts.slice(5); + var msg = txt.substr(lhs.length + 2) + + var forumElement = getForumElement(forum); + var p = getTemplate("message"); + + addMessagePart(p, "timestamp", ts.toLocaleTimeString()); + + switch (command) { + case "PING": + case "PONG": + return; + break; + case "PRIVMSG": + addMessagePart(p, "forum", forum); + addMessagePart(p, "sender", sender); + addText(p, msg, (sender == forum)); + break; + case "NOTICE": + addMessagePart(p, "forum", forum); + addMessagePart(p, "sender notice", sender); + addText(p, msg, (sender == forum)); + break; + default: + addMessagePart(p, "forum", forum); + addMessagePart(p, "sender", sender); + addMessagePart(p, "raw", command + " " + args + " " + msg); + break; + } + while (forumElement.childNodes.length > scrollbackLength) { + forumElement.removeChild(forumElement.firstChild) + } + forumElement.appendChild(p); + p.scrollIntoView(false); +} + +function newmsg(oEvent) { + msgs = oEvent.data.split("\n"); + + var first = Math.max(0, msgs.length - scrollbackLength); + for (var i = first; i < msgs.length; i += 1) { + addMessage(msgs[i]); + } +} + +function handleInput(oEvent) { + console.log(oEvent); + var oReq = new XMLHttpRequest(); + function reqListener() { + } + + var txt = oEvent.target.value; + if (txt.startsWith("/connect ")) { + // XXX: should allow tokens with spaces + var parts = txt.split(" "); + + connect(parts[1], parts[2], parts[3]); + } else { + oReq.onload = reqListener; + oReq.open("POST", window.postURL, true); + oReq.send(new FormData(event.target)); + } + + oEvent.target.value = ""; + + return false; +} + +function connect(url, server, authtok) { + document.postURL = url; + var pullURL = url + "?server=" + server + "&auth=" + authtok + + if (document.source != null) { + document.source.close(); + } + document.source = new EventSource(pullURL); + document.source.onmessage = newmsg; + + chrome.storage.sync.set({"connections": [[url, server, authtok]]}); +} + +function restore(items) { + var connections = items["connections"]; + + for (var k = 0; k < connections.length; k += 1) { + var conn = connections[k]; + + connect(conn[0], conn[1], conn[2]); + } +} + +function init() { + chrome.storage.sync.get("connections", restore); + document.getElementById("input").addEventListener("change", handleInput); + + document.templates = document.getElementById("templates"); + document.rooms_list = document.getElementById("rooms-container").getElementsByClassName("rooms")[0]; +} + +window.addEventListener("load", init); diff --git a/chat.png b/app/wirc.png similarity index 100% rename from chat.png rename to app/wirc.png diff --git a/index.html b/index.html deleted file mode 100644 index 5e4cef5..0000000 --- a/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - #tron - - - - - -
        -
        -
        - - - - - - -
        -
        - - diff --git a/wirc.css b/wirc.css deleted file mode 100644 index 6f730ab..0000000 --- a/wirc.css +++ /dev/null @@ -1,58 +0,0 @@ - -#foraText, #kiboze { - max-height: 20em; - overflow: scroll; -} -#foraText p, #kiboze p { - margin: 0em 0em 0em 4em; - text-indent: -4em; -} -#kiboze { - max-height: 7em; - background-color: #eee; -} -.timestamp { - color: silver; -} -.forum { - color: darkblue; - display: none; -} -.sender { - color: green; -} -.sender:before { - content: "<"; -} -.sender:after { - content: ">"; -} -.sender.notice { - color: olive; -} -.sender.notice:before { - content: "-"; -} -.sender.notice:after { - content: "-"; -} -.raw { - color: purple; -} - -.active { - background-color: yellow; -} -.current { - background-color: cornsilk; -} - -input[name~=target] { - width: 7em; -} -input[name~=text] { - width: 75%; -} -body { - height: 100%; -} \ No newline at end of file diff --git a/wirc.js b/wirc.js deleted file mode 100644 index ab82796..0000000 --- a/wirc.js +++ /dev/null @@ -1,202 +0,0 @@ -var msgRe = /([^ ]+) (<[^>]+>) (.*)/; -var kibozeRe = /[Nn]eal/; -var urlRe = /[a-z]+:\/\/[^ ]*/; - -var nick = "Mme. M"; - -function isinView(oObject) { - return (oObject.offsetParent.clientHeight <= oObject.offsetTop); -} - -function selectForum(fe) { - var kids = document.getElementById("foraText").childNodes; - - for (i = 0; i < kids.length; i += 1) { - e = kids[i]; - console.log(i, e); - if (e == fe) { - e.style.display = "block"; - } else { - e.style.display = "none"; - if (e.button.className == "current") { - e.button.className = ""; - } - } - } - - fe.button.className = "current"; - if (fe.lastChild) { - fe.lastChild.scrollIntoView(false); - } - document.getElementById("target").value = fe.forum; -} - -function getForumElement(forum) { - var id = "a:" + forum; - var fe = document.getElementById(id); - - if (! fe) { - var button = document.createElement("button"); - button.appendChild(document.createTextNode(forum)); - button.onclick = function() { selectForum(fe); } - document.getElementById("foraButtons").appendChild(button); - - fe = document.createElement("div"); - fe.id = id - fe.forum = forum - fe.button = button - document.getElementById("foraText").appendChild(fe); - } - - if (fe.button.className != "current") { - fe.button.className = "active"; - } - return fe; -} - -function addMessagePart(p, className, text) { - var e = document.createElement("span"); - e.className = className; - e.appendChild(document.createTextNode(text)); - p.appendChild(e); - p.appendChild(document.createTextNode(" ")); -} - -function addText(p, text, kiboze) { - // 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)); - p.appendChild(txtElement); - - if ((kiboze) || (-1 != text.search(kibozeRe))) { - var k = document.getElementById("kiboze"); - var p2 = p.cloneNode(true); - k.insertBefore(p2, k.firstChild); - p2.onclick = function() { focus(p); } - - // Setting title makes the tab flash sorta - document.title = document.title; - } -} - -function focus(e) { - var pct = 1; - var timeout; - - selectForum(e.parentNode); - e.scrollIntoView(false); - e.style.backgroundColor = "yellow"; - - timeout = setInterval(function() { - pct = pct - 0.1; - e.style.backgroundColor = "rgba(255, 255, 0, " + pct + ")"; - if (pct <= 0) { - e.style.backgroundColor = "inherit"; - clearInterval(timeout); - } - }, 50) -} - -function addMessage(txt) { - var lhs = txt.split(" :", 1)[0] - var parts = lhs.split(' ') - var ts = new Date(parts[0] * 1000); - var fullSender = parts[1]; - var command = parts[2]; - var sender = parts[3]; - var forum = parts[4]; - var args = parts.slice(5); - var msg = txt.substr(lhs.length + 2) - - var forumElement; - var p = document.createElement("p"); - - if (command == "NICK") { - forumElement = getForumElement("."); - } else { - forumElement = getForumElement(forum); - } - - addMessagePart(p, "timestamp", ts.toLocaleTimeString()); - - switch (command) { - case "PING": - case "PONG": - return; - break; - case "PRIVMSG": - addMessagePart(p, "forum", forum); - addMessagePart(p, "sender", sender); - addText(p, msg, (sender == forum)); - break; - case "NOTICE": - addMessagePart(p, "forum", forum); - addMessagePart(p, "sender notice", sender); - addText(p, msg, (sender == forum)); - break; - default: - addMessagePart(p, "forum", forum); - addMessagePart(p, "sender", sender); - addMessagePart(p, "raw", command + " " + args + " " + msg); - break; - } - forumElement.appendChild(p); - p.scrollIntoView(false); -} - -function newmsg(event) { - msgs = event.data.split("\n"); - - for (var i = 0; i < msgs.length; i += 1) { - addMessage(msgs[i]); - } -} - -function handleCommand(event) { - window.evt = event; - var oReq = new XMLHttpRequest(); - function reqListener() { - } - oReq.onload = reqListener; - oReq.open("POST", "wirc.cgi", true); - oReq.send(new FormData(event.target)); - - event.target.reset(); - - return false; -} - -function init() { - var server = document.getElementById("server").value; - var authtok = prompt("Auth token", ""); - document.getElementById("authtok").value = authtok; - - var source = new EventSource("wirc.cgi?server=" + server + "&auth=" + authtok); - source.onmessage = newmsg; - - document.getElementById("command").onsubmit = handleCommand; - - var txte = document.getElementById("text"); - txte.addEventListener("blur", txte.focus); -} - -window.onload = init;