2018-10-23 23:15:40 +08:00
/ *
*
* NOTE : The client side of hack . chat is currently in development ,
* a new , more modern but still minimal version will be released
* soon . As a result of this , the current code has been deprecated
* and will not actively be updated .
*
* /
2019-01-14 06:08:16 +08:00
var verifyNickname = function ( nick ) {
return /^[a-zA-Z0-9_]{1,24}$/ . test ( nick ) ;
}
2018-10-23 23:15:40 +08:00
2018-03-10 15:47:00 +08:00
var frontpage = [
" _ _ _ _ " ,
" | |_ ___ ___| |_ ___| |_ ___| |_ " ,
" | |_ || _| '_| | _| |_ || _|" ,
" |_|_|__/|___|_,_|.|___|_|_|__/|_| " ,
"" ,
"" ,
"Welcome to hack.chat, a minimal, distraction-free chat application." ,
2018-10-23 23:15:40 +08:00
"Channels are created, joined and shared with the url, create your own channel by changing the text after the question mark." ,
"If you wanted your channel name to be 'your-channel': https://hack.chat/?your-channel" ,
"There are no channel lists, so a secret channel name can be used for private discussions." ,
2018-03-10 15:47:00 +08:00
"" ,
"Here are some pre-made channels you can join:" ,
"?lounge ?meta" ,
"?math ?physics ?chemistry" ,
"?technology ?programming" ,
"?games ?banana" ,
"And here's a random one generated just for you: ?" + Math . random ( ) . toString ( 36 ) . substr ( 2 , 8 ) ,
"" ,
"Formatting:" ,
"Whitespace is preserved, so source code can be pasted verbatim." ,
"Surround LaTeX with a dollar sign for inline style $\\zeta(2) = \\pi^2/6$, and two dollars for display. $$\\int_0^1 \\int_0^1 \\frac{1}{1-xy} dx dy = \\frac{\\pi^2}{6}$$" ,
2018-10-23 23:15:40 +08:00
"For syntax highlight, the first line of the code block must begin with #<format> where <format> can be html, js or any known format." ,
2018-03-10 15:47:00 +08:00
"" ,
2018-10-23 23:15:40 +08:00
"Current Github: https://github.com/hack-chat" ,
2018-03-26 05:16:02 +08:00
"Legacy GitHub: https://github.com/AndrewBelt/hack.chat" ,
2018-10-23 23:15:40 +08:00
"" ,
"Bots, Android clients, desktop clients, browser extensions, docker images, programming libraries, server modules and more:" ,
"https://github.com/hack-chat/3rd-party-software-list" ,
2018-03-10 15:47:00 +08:00
"" ,
2018-03-26 05:16:02 +08:00
"Server and web client released under the WTFPL and MIT open source license." ,
"No message history is retained on the hack.chat server."
2018-03-29 12:34:27 +08:00
] . join ( "\n" ) ;
2018-03-10 15:47:00 +08:00
2018-03-29 12:34:27 +08:00
function $ ( query ) {
return document . querySelector ( query ) ;
}
2018-03-10 15:47:00 +08:00
function localStorageGet ( key ) {
try {
return window . localStorage [ key ]
2018-05-17 23:42:16 +08:00
} catch ( e ) { }
2018-03-10 15:47:00 +08:00
}
function localStorageSet ( key , val ) {
try {
window . localStorage [ key ] = val
2018-05-17 23:42:16 +08:00
} catch ( e ) { }
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
var ws ;
2018-11-03 22:51:05 +08:00
var myNick = localStorageGet ( 'my-nick' ) || '' ;
2018-03-29 12:34:27 +08:00
var myChannel = window . location . search . replace ( /^\?/ , '' ) ;
var lastSent = [ "" ] ;
var lastSentPos = 0 ;
2018-03-10 15:47:00 +08:00
function join ( channel ) {
2018-03-26 05:16:02 +08:00
if ( document . domain == 'hack.chat' ) {
// For https://hack.chat/
2018-03-29 12:34:27 +08:00
ws = new WebSocket ( 'wss://hack.chat/chat-ws' ) ;
2018-03-26 05:16:02 +08:00
} else {
// for local installs
2018-03-29 12:34:27 +08:00
ws = new WebSocket ( 'ws://' + document . domain + ':6060' ) ;
2018-03-26 05:16:02 +08:00
}
2018-03-10 15:47:00 +08:00
2018-03-29 12:34:27 +08:00
var wasConnected = false ;
2018-03-10 15:47:00 +08:00
2018-03-29 12:34:27 +08:00
ws . onopen = function ( ) {
2018-03-10 15:47:00 +08:00
if ( ! wasConnected ) {
if ( location . hash ) {
2018-03-29 12:34:27 +08:00
myNick = location . hash . substr ( 1 ) ;
} else {
myNick = prompt ( 'Nickname:' , myNick ) ;
2018-03-10 15:47:00 +08:00
}
}
2018-03-29 12:34:27 +08:00
2018-03-10 15:47:00 +08:00
if ( myNick ) {
2018-03-29 12:34:27 +08:00
localStorageSet ( 'my-nick' , myNick ) ;
send ( { cmd : 'join' , channel : channel , nick : myNick } ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
wasConnected = true ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
ws . onclose = function ( ) {
2018-03-10 15:47:00 +08:00
if ( wasConnected ) {
2018-03-29 12:34:27 +08:00
pushMessage ( { nick : '!' , text : "Server disconnected. Attempting to reconnect. . ." } ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
window . setTimeout ( function ( ) {
join ( channel ) ;
} , 2000 ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
ws . onmessage = function ( message ) {
var args = JSON . parse ( message . data ) ;
var cmd = args . cmd ;
var command = COMMANDS [ cmd ] ;
command . call ( null , args ) ;
2018-03-10 15:47:00 +08:00
}
}
var COMMANDS = {
2018-03-29 12:34:27 +08:00
chat : function ( args ) {
2018-03-10 15:47:00 +08:00
if ( ignoredUsers . indexOf ( args . nick ) >= 0 ) {
2018-03-29 12:34:27 +08:00
return ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
pushMessage ( args ) ;
2018-03-10 15:47:00 +08:00
} ,
2018-03-29 12:34:27 +08:00
info : function ( args ) {
args . nick = '*' ;
pushMessage ( args ) ;
2018-03-10 15:47:00 +08:00
} ,
2018-03-29 12:34:27 +08:00
warn : function ( args ) {
args . nick = '!' ;
pushMessage ( args ) ;
2018-03-10 15:47:00 +08:00
} ,
2018-03-29 12:34:27 +08:00
onlineSet : function ( args ) {
var nicks = args . nicks ;
usersClear ( ) ;
nicks . forEach ( function ( nick ) {
userAdd ( nick ) ;
} ) ;
pushMessage ( { nick : '*' , text : "Users online: " + nicks . join ( ", " ) } )
2018-03-10 15:47:00 +08:00
} ,
2018-03-29 12:34:27 +08:00
onlineAdd : function ( args ) {
var nick = args . nick ;
userAdd ( nick ) ;
2018-03-10 15:47:00 +08:00
if ( $ ( '#joined-left' ) . checked ) {
2018-03-29 12:34:27 +08:00
pushMessage ( { nick : '*' , text : nick + " joined" } ) ;
2018-03-10 15:47:00 +08:00
}
} ,
2018-03-29 12:34:27 +08:00
onlineRemove : function ( args ) {
var nick = args . nick ;
userRemove ( nick ) ;
2018-03-10 15:47:00 +08:00
if ( $ ( '#joined-left' ) . checked ) {
2018-03-29 12:34:27 +08:00
pushMessage ( { nick : '*' , text : nick + " left" } ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
}
2018-03-10 15:47:00 +08:00
}
function pushMessage ( args ) {
// Message container
2018-03-29 12:34:27 +08:00
var messageEl = document . createElement ( 'div' ) ;
2018-10-08 02:45:20 +08:00
if ( args . text . includes ( '@' + myNick . split ( '#' ) [ 0 ] + ' ' ) ) {
messageEl . classList . add ( 'refmessage' ) ;
} else {
messageEl . classList . add ( 'message' ) ;
}
2018-03-10 15:47:00 +08:00
2018-07-30 05:57:57 +08:00
if ( verifyNickname ( myNick ) && args . nick == myNick ) {
2018-03-29 12:34:27 +08:00
messageEl . classList . add ( 'me' ) ;
2018-05-17 23:42:16 +08:00
} else if ( args . nick == '!' ) {
2018-03-29 12:34:27 +08:00
messageEl . classList . add ( 'warn' ) ;
2018-05-17 23:42:16 +08:00
} else if ( args . nick == '*' ) {
2018-03-29 12:34:27 +08:00
messageEl . classList . add ( 'info' ) ;
2018-05-17 23:42:16 +08:00
} else if ( args . admin ) {
2018-03-29 12:34:27 +08:00
messageEl . classList . add ( 'admin' ) ;
2018-05-17 23:42:16 +08:00
} else if ( args . mod ) {
2018-03-29 12:34:27 +08:00
messageEl . classList . add ( 'mod' ) ;
2018-03-10 15:47:00 +08:00
}
// Nickname
2018-03-29 12:34:27 +08:00
var nickSpanEl = document . createElement ( 'span' ) ;
nickSpanEl . classList . add ( 'nick' ) ;
messageEl . appendChild ( nickSpanEl ) ;
2018-03-10 15:47:00 +08:00
if ( args . trip ) {
2018-03-29 12:34:27 +08:00
var tripEl = document . createElement ( 'span' ) ;
tripEl . textContent = args . trip + " " ;
tripEl . classList . add ( 'trip' ) ;
nickSpanEl . appendChild ( tripEl ) ;
2018-03-10 15:47:00 +08:00
}
if ( args . nick ) {
2018-03-29 12:34:27 +08:00
var nickLinkEl = document . createElement ( 'a' ) ;
nickLinkEl . textContent = args . nick ;
nickLinkEl . onclick = function ( ) {
insertAtCursor ( "@" + args . nick + " " ) ;
$ ( '#chatinput' ) . focus ( ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
var date = new Date ( args . time || Date . now ( ) ) ;
nickLinkEl . title = date . toLocaleString ( ) ;
nickSpanEl . appendChild ( nickLinkEl ) ;
2018-03-10 15:47:00 +08:00
}
// Text
2018-03-29 12:34:27 +08:00
var textEl = document . createElement ( 'pre' ) ;
textEl . classList . add ( 'text' ) ;
2018-03-10 15:47:00 +08:00
2018-03-29 12:34:27 +08:00
textEl . textContent = args . text || '' ;
textEl . innerHTML = textEl . innerHTML . replace ( /(\?|https?:\/\/)\S+?(?=[,.!?:)]?\s|$)/g , parseLinks ) ;
2018-03-10 15:47:00 +08:00
2018-05-18 00:34:14 +08:00
if ( $ ( '#syntax-highlight' ) . checked && textEl . textContent . indexOf ( '#' ) == 0 ) {
var lang = textEl . textContent . split ( /\s+/g ) [ 0 ] . replace ( '#' , '' ) ;
var codeEl = document . createElement ( 'code' ) ;
codeEl . classList . add ( lang ) ;
var content = textEl . textContent . replace ( '#' + lang , '' ) ;
codeEl . textContent = content . trim ( ) ;
hljs . highlightBlock ( codeEl ) ;
textEl . innerHTML = '' ;
textEl . appendChild ( codeEl ) ;
2018-05-17 23:42:16 +08:00
} else if ( $ ( '#parse-latex' ) . checked ) {
2018-03-10 15:47:00 +08:00
// Temporary hotfix for \rule spamming, see https://github.com/Khan/KaTeX/issues/109
2018-03-29 12:34:27 +08:00
textEl . innerHTML = textEl . innerHTML . replace ( /\\rule|\\\\\s*\[.*?\]/g , '' ) ;
2018-03-10 15:47:00 +08:00
try {
2018-05-17 23:42:16 +08:00
renderMathInElement ( textEl , {
delimiters : [
{ left : "$$" , right : "$$" , display : true } ,
{ left : "$" , right : "$" , display : false } ,
]
} )
} catch ( e ) {
2018-03-29 12:34:27 +08:00
console . warn ( e ) ;
2018-03-10 15:47:00 +08:00
}
}
2018-03-29 12:34:27 +08:00
messageEl . appendChild ( textEl ) ;
2018-03-10 15:47:00 +08:00
// Scroll to bottom
2018-03-29 12:34:27 +08:00
var atBottom = isAtBottom ( ) ;
$ ( '#messages' ) . appendChild ( messageEl ) ;
2018-03-10 15:47:00 +08:00
if ( atBottom ) {
2018-03-29 12:34:27 +08:00
window . scrollTo ( 0 , document . body . scrollHeight ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
unread += 1 ;
updateTitle ( ) ;
2018-03-10 15:47:00 +08:00
}
function insertAtCursor ( text ) {
2018-03-29 12:34:27 +08:00
var input = $ ( '#chatinput' ) ;
var start = input . selectionStart || 0 ;
var before = input . value . substr ( 0 , start ) ;
var after = input . value . substr ( start ) ;
2018-03-10 15:47:00 +08:00
2018-03-29 12:34:27 +08:00
before += text ;
input . value = before + after ;
input . selectionStart = input . selectionEnd = before . length ;
updateInputSize ( ) ;
}
2018-03-10 15:47:00 +08:00
function send ( data ) {
if ( ws && ws . readyState == ws . OPEN ) {
2018-03-29 12:34:27 +08:00
ws . send ( JSON . stringify ( data ) ) ;
2018-03-10 15:47:00 +08:00
}
}
function parseLinks ( g0 ) {
2018-03-29 12:34:27 +08:00
var a = document . createElement ( 'a' ) ;
a . innerHTML = g0 ;
var url = a . textContent ;
a . href = url ;
a . target = '_blank' ;
return a . outerHTML ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
var windowActive = true ;
var unread = 0 ;
2018-03-10 15:47:00 +08:00
2018-03-29 12:34:27 +08:00
window . onfocus = function ( ) {
windowActive = true ;
2018-03-10 15:47:00 +08:00
2018-03-29 12:34:27 +08:00
updateTitle ( ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
window . onblur = function ( ) {
windowActive = false ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
window . onscroll = function ( ) {
2018-03-10 15:47:00 +08:00
if ( isAtBottom ( ) ) {
2018-03-29 12:34:27 +08:00
updateTitle ( ) ;
2018-03-10 15:47:00 +08:00
}
}
function isAtBottom ( ) {
2018-03-29 12:34:27 +08:00
return ( window . innerHeight + window . scrollY ) >= ( document . body . scrollHeight - 1 ) ;
2018-03-10 15:47:00 +08:00
}
function updateTitle ( ) {
if ( windowActive && isAtBottom ( ) ) {
2018-03-29 12:34:27 +08:00
unread = 0 ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
var title ;
2018-03-10 15:47:00 +08:00
if ( myChannel ) {
2018-03-29 12:34:27 +08:00
title = "?" + myChannel ;
2018-05-17 23:42:16 +08:00
} else {
2018-03-29 12:34:27 +08:00
title = "hack.chat" ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
2018-03-10 15:47:00 +08:00
if ( unread > 0 ) {
2018-03-29 12:34:27 +08:00
title = '(' + unread + ') ' + title ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
document . title = title ;
}
2018-03-10 15:47:00 +08:00
2018-03-29 12:34:27 +08:00
$ ( '#footer' ) . onclick = function ( ) {
$ ( '#chatinput' ) . focus ( ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
$ ( '#chatinput' ) . onkeydown = function ( e ) {
2018-03-10 15:47:00 +08:00
if ( e . keyCode == 13 /* ENTER */ && ! e . shiftKey ) {
2018-03-29 12:34:27 +08:00
e . preventDefault ( ) ;
2018-03-10 15:47:00 +08:00
// Submit message
if ( e . target . value != '' ) {
2018-03-29 12:34:27 +08:00
var text = e . target . value ;
e . target . value = '' ;
send ( { cmd : 'chat' , text : text } ) ;
lastSent [ 0 ] = text ;
lastSent . unshift ( "" ) ;
lastSentPos = 0 ;
updateInputSize ( ) ;
2018-03-10 15:47:00 +08:00
}
2018-05-17 23:42:16 +08:00
} else if ( e . keyCode == 38 /* UP */ ) {
2018-03-10 15:47:00 +08:00
// Restore previous sent messages
if ( e . target . selectionStart === 0 && lastSentPos < lastSent . length - 1 ) {
2018-03-29 12:34:27 +08:00
e . preventDefault ( ) ;
2018-03-10 15:47:00 +08:00
if ( lastSentPos == 0 ) {
2018-03-29 12:34:27 +08:00
lastSent [ 0 ] = e . target . value ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
lastSentPos += 1 ;
e . target . value = lastSent [ lastSentPos ] ;
e . target . selectionStart = e . target . selectionEnd = e . target . value . length ;
updateInputSize ( ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
} else if ( e . keyCode == 40 /* DOWN */ ) {
2018-03-10 15:47:00 +08:00
if ( e . target . selectionStart === e . target . value . length && lastSentPos > 0 ) {
2018-03-29 12:34:27 +08:00
e . preventDefault ( ) ;
lastSentPos -= 1 ;
e . target . value = lastSent [ lastSentPos ] ;
e . target . selectionStart = e . target . selectionEnd = 0 ;
updateInputSize ( ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
} else if ( e . keyCode == 27 /* ESC */ ) {
e . preventDefault ( ) ;
2018-03-10 15:47:00 +08:00
// Clear input field
2018-03-29 12:34:27 +08:00
e . target . value = "" ;
lastSentPos = 0 ;
lastSent [ lastSentPos ] = "" ;
updateInputSize ( ) ;
2018-05-17 23:42:16 +08:00
} else if ( e . keyCode == 9 /* TAB */ ) {
2018-03-10 15:47:00 +08:00
// Tab complete nicknames starting with @
2018-03-29 12:34:27 +08:00
e . preventDefault ( ) ;
var pos = e . target . selectionStart || 0 ;
var text = e . target . value ;
var index = text . lastIndexOf ( '@' , pos ) ;
2018-03-10 15:47:00 +08:00
if ( index >= 0 ) {
2018-03-29 12:34:27 +08:00
var stub = text . substring ( index + 1 , pos ) . toLowerCase ( ) ;
2018-03-10 15:47:00 +08:00
// Search for nick beginning with stub
2018-03-29 12:34:27 +08:00
var nicks = onlineUsers . filter ( function ( nick ) {
2018-03-10 15:47:00 +08:00
return nick . toLowerCase ( ) . indexOf ( stub ) == 0
2018-03-29 12:34:27 +08:00
} ) ;
2018-03-10 15:47:00 +08:00
if ( nicks . length == 1 ) {
2018-03-29 12:34:27 +08:00
insertAtCursor ( nicks [ 0 ] . substr ( stub . length ) + " " ) ;
2018-03-10 15:47:00 +08:00
}
}
}
}
function updateInputSize ( ) {
2018-03-29 12:34:27 +08:00
var atBottom = isAtBottom ( ) ;
2018-03-10 15:47:00 +08:00
2018-03-29 12:34:27 +08:00
var input = $ ( '#chatinput' ) ;
input . style . height = 0 ;
input . style . height = input . scrollHeight + 'px' ;
document . body . style . marginBottom = $ ( '#footer' ) . offsetHeight + 'px' ;
2018-03-10 15:47:00 +08:00
if ( atBottom ) {
2018-03-29 12:34:27 +08:00
window . scrollTo ( 0 , document . body . scrollHeight ) ;
2018-03-10 15:47:00 +08:00
}
}
2018-03-29 12:34:27 +08:00
$ ( '#chatinput' ) . oninput = function ( ) {
updateInputSize ( ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
updateInputSize ( ) ;
2018-03-10 15:47:00 +08:00
/* sidebar */
2018-03-29 12:34:27 +08:00
$ ( '#sidebar' ) . onmouseenter = $ ( '#sidebar' ) . ontouchstart = function ( e ) {
$ ( '#sidebar-content' ) . classList . remove ( 'hidden' ) ;
2018-06-18 02:32:03 +08:00
$ ( '#sidebar' ) . classList . add ( 'expand' ) ;
2018-03-29 12:34:27 +08:00
e . stopPropagation ( ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
$ ( '#sidebar' ) . onmouseleave = document . ontouchstart = function ( ) {
2018-03-10 15:47:00 +08:00
if ( ! $ ( '#pin-sidebar' ) . checked ) {
2018-03-29 12:34:27 +08:00
$ ( '#sidebar-content' ) . classList . add ( 'hidden' ) ;
2018-06-18 02:32:03 +08:00
$ ( '#sidebar' ) . classList . remove ( 'expand' ) ;
2018-03-10 15:47:00 +08:00
}
}
2018-03-29 12:34:27 +08:00
$ ( '#clear-messages' ) . onclick = function ( ) {
2018-03-10 15:47:00 +08:00
// Delete children elements
2018-03-29 12:34:27 +08:00
var messages = $ ( '#messages' ) ;
2018-03-10 15:47:00 +08:00
while ( messages . firstChild ) {
2018-03-29 12:34:27 +08:00
messages . removeChild ( messages . firstChild ) ;
2018-03-10 15:47:00 +08:00
}
}
// Restore settings from localStorage
if ( localStorageGet ( 'pin-sidebar' ) == 'true' ) {
2018-03-29 12:34:27 +08:00
$ ( '#pin-sidebar' ) . checked = true ;
$ ( '#sidebar-content' ) . classList . remove ( 'hidden' ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
2018-03-10 15:47:00 +08:00
if ( localStorageGet ( 'joined-left' ) == 'false' ) {
2018-03-29 12:34:27 +08:00
$ ( '#joined-left' ) . checked = false ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
2018-03-10 15:47:00 +08:00
if ( localStorageGet ( 'parse-latex' ) == 'false' ) {
2018-03-29 12:34:27 +08:00
$ ( '#parse-latex' ) . checked = false ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
$ ( '#pin-sidebar' ) . onchange = function ( e ) {
localStorageSet ( 'pin-sidebar' , ! ! e . target . checked ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
$ ( '#joined-left' ) . onchange = function ( e ) {
localStorageSet ( 'joined-left' , ! ! e . target . checked ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
$ ( '#parse-latex' ) . onchange = function ( e ) {
localStorageSet ( 'parse-latex' , ! ! e . target . checked ) ;
2018-03-10 15:47:00 +08:00
}
// User list
2018-03-29 12:34:27 +08:00
var onlineUsers = [ ] ;
var ignoredUsers = [ ] ;
2018-03-10 15:47:00 +08:00
function userAdd ( nick ) {
2018-03-29 12:34:27 +08:00
var user = document . createElement ( 'a' ) ;
user . textContent = nick ;
user . onclick = function ( e ) {
2018-03-10 15:47:00 +08:00
userInvite ( nick )
}
2018-03-29 12:34:27 +08:00
var userLi = document . createElement ( 'li' ) ;
userLi . appendChild ( user ) ;
$ ( '#users' ) . appendChild ( userLi ) ;
onlineUsers . push ( nick ) ;
2018-03-10 15:47:00 +08:00
}
function userRemove ( nick ) {
2018-03-29 12:34:27 +08:00
var users = $ ( '#users' ) ;
var children = users . children ;
2018-03-10 15:47:00 +08:00
for ( var i = 0 ; i < children . length ; i ++ ) {
2018-03-29 12:34:27 +08:00
var user = children [ i ] ;
2018-03-10 15:47:00 +08:00
if ( user . textContent == nick ) {
2018-03-29 12:34:27 +08:00
users . removeChild ( user ) ;
2018-03-10 15:47:00 +08:00
}
}
2018-03-29 12:34:27 +08:00
var index = onlineUsers . indexOf ( nick ) ;
2018-03-10 15:47:00 +08:00
if ( index >= 0 ) {
2018-03-29 12:34:27 +08:00
onlineUsers . splice ( index , 1 ) ;
2018-03-10 15:47:00 +08:00
}
}
function usersClear ( ) {
2018-03-29 12:34:27 +08:00
var users = $ ( '#users' ) ;
2018-03-10 15:47:00 +08:00
while ( users . firstChild ) {
2018-03-29 12:34:27 +08:00
users . removeChild ( users . firstChild ) ;
2018-03-10 15:47:00 +08:00
}
2018-03-29 12:34:27 +08:00
onlineUsers . length = 0 ;
2018-03-10 15:47:00 +08:00
}
function userInvite ( nick ) {
2018-03-29 12:34:27 +08:00
send ( { cmd : 'invite' , nick : nick } ) ;
2018-03-10 15:47:00 +08:00
}
function userIgnore ( nick ) {
2018-03-29 12:34:27 +08:00
ignoredUsers . push ( nick ) ;
2018-03-10 15:47:00 +08:00
}
/* color scheme switcher */
var schemes = [
'android' ,
'atelier-dune' ,
'atelier-forest' ,
'atelier-heath' ,
'atelier-lakeside' ,
'atelier-seaside' ,
'bright' ,
'chalk' ,
'default' ,
'eighties' ,
2019-01-12 00:02:22 +08:00
'greenscreen' ,
2019-01-11 22:24:10 +08:00
'mariana' ,
2018-03-10 15:47:00 +08:00
'mocha' ,
'monokai' ,
'nese' ,
'ocean' ,
'pop' ,
'railscasts' ,
'solarized' ,
2018-03-29 12:34:27 +08:00
'tomorrow'
] ;
2018-03-10 15:47:00 +08:00
2018-05-17 23:42:16 +08:00
var highlights = [
'agate' ,
'androidstudio' ,
2019-01-12 00:11:34 +08:00
'atom-one-dark' ,
2018-05-17 23:42:16 +08:00
'darcula' ,
'github' ,
'rainbow' ,
'tomorrow' ,
'xcode' ,
'zenburn'
]
2018-03-29 12:34:27 +08:00
var currentScheme = 'atelier-dune' ;
2018-05-17 23:42:16 +08:00
var currentHighlight = 'darcula' ;
2018-03-10 15:47:00 +08:00
function setScheme ( scheme ) {
2018-03-29 12:34:27 +08:00
currentScheme = scheme ;
$ ( '#scheme-link' ) . href = "schemes/" + scheme + ".css" ;
localStorageSet ( 'scheme' , scheme ) ;
2018-03-10 15:47:00 +08:00
}
2018-05-17 23:42:16 +08:00
function setHighlight ( scheme ) {
currentHighlight = scheme ;
$ ( '#highlight-link' ) . href = "//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/" + scheme + ".min.css" ;
localStorageSet ( 'highlight' , scheme ) ;
}
2018-03-10 15:47:00 +08:00
// Add scheme options to dropdown selector
2018-03-29 12:34:27 +08:00
schemes . forEach ( function ( scheme ) {
var option = document . createElement ( 'option' ) ;
option . textContent = scheme ;
option . value = scheme ;
$ ( '#scheme-selector' ) . appendChild ( option ) ;
} ) ;
2018-03-10 15:47:00 +08:00
2018-05-17 23:42:16 +08:00
highlights . forEach ( function ( scheme ) {
var option = document . createElement ( 'option' ) ;
option . textContent = scheme ;
option . value = scheme ;
$ ( '#highlight-selector' ) . appendChild ( option ) ;
} ) ;
2018-03-29 12:34:27 +08:00
$ ( '#scheme-selector' ) . onchange = function ( e ) {
setScheme ( e . target . value ) ;
2018-03-10 15:47:00 +08:00
}
2018-05-17 23:42:16 +08:00
$ ( '#highlight-selector' ) . onchange = function ( e ) {
setHighlight ( e . target . value ) ;
}
2018-03-10 15:47:00 +08:00
// Load sidebar configaration values from local storage if available
if ( localStorageGet ( 'scheme' ) ) {
2018-03-29 12:34:27 +08:00
setScheme ( localStorageGet ( 'scheme' ) ) ;
2018-03-10 15:47:00 +08:00
}
2018-05-17 23:42:16 +08:00
if ( localStorageGet ( 'highlight' ) ) {
setHighlight ( localStorageGet ( 'highlight' ) ) ;
}
2018-03-29 12:34:27 +08:00
$ ( '#scheme-selector' ) . value = currentScheme ;
2018-05-17 23:42:16 +08:00
$ ( '#highlight-selector' ) . value = currentHighlight ;
2018-03-10 15:47:00 +08:00
/* main */
if ( myChannel == '' ) {
2018-03-29 12:34:27 +08:00
pushMessage ( { text : frontpage } ) ;
$ ( '#footer' ) . classList . add ( 'hidden' ) ;
$ ( '#sidebar' ) . classList . add ( 'hidden' ) ;
} else {
join ( myChannel ) ;
2018-06-07 19:24:08 +08:00
}