Add an autocomplete with known server names to the connect dialog;
Added support for server messages (identification, shutdown, user
warning and promotion)
Connection dialog’s inputs are now wider
Only declare implemented client features
Added check for protocol version on connect before login
Avoid listbox being rendered as dropdown on mobiles
This commit is contained in:
Fabio Bas 2016-07-29 10:33:22 +02:00
parent 8644016d3c
commit a68df3611b
3 changed files with 151 additions and 17 deletions

View file

@ -2,6 +2,7 @@
<html>
<head>
<title>Cockatrice web client</title>
<link rel="shortcut icon" href="imgs/cockatrice.png" />
<link rel="stylesheet" href="js/jquery-ui-1.11.4.css">
<link rel="stylesheet" href="style.css">
</head>
@ -15,6 +16,7 @@ Loading cockatrice web client...
</div>
<div id="error-dialog" title="Error" style="display:none"></div>
<div id="info-dialog" title="Information" style="display:none"></div>
<div id="tabs" style="display:none">
<ul>
@ -26,7 +28,7 @@ Loading cockatrice web client...
<div id="tab-login">
<h3>Login to server</h3>
<label for="host">Host</label>
<input type="text" id="host" value="127.0.0.1" />
<input type="text" id="host" value="" />
<br/>
<label for="port">Port</label>
<input type="text" id="port" value ="4748" />
@ -54,11 +56,11 @@ Loading cockatrice web client...
<div id="tab-account">
<div class="buddies-container">
<h3>Buddies</h3>
<select id="buddies" size="10"></select>
<ul id="buddies" size="10"></ul>
</div>
<div class="ignores-container">
<h3>Ignores</h3>
<select id="ignores" size="10"></select>
<ul id="ignores" size="10"></ul>
</div>
<div class="userinfo-container">
<h3>User info</h3>
@ -86,6 +88,16 @@ Loading cockatrice web client...
$("#loading").hide();
$("#tabs").show();
$( "#host" ).autocomplete({
source: [
// add custom servers here
"cockatrice.woogerworks.com",
"vps.poixen.com",
"chickatrice.net",
"127.0.0.1"
]
});
$( document ).ready(function() {
function ts2time(ts) {
@ -102,6 +114,43 @@ Loading cockatrice web client...
return $("<div>").text(msg).html();
}
function htmlSanitize(msg) {
var div = $("<div>").html(msg);
// remove all tags except some
var tagsWhitelist = "br,a,img,center,b,font";
$(div).find("*").not(tagsWhitelist).each(function() {
$(this).replaceWith(this.innerHTML);
});
// remove all attributes except some
var attributesWhitelist = ["href","color"];
$(div).find("*").each(function() {
var attributes = this.attributes;
var i = attributes.length;
while( i-- ) {
var attr = attributes[i];
if( $.inArray(attr.name,attributesWhitelist) == -1 )
this.removeAttributeNode(attr);
}
});
// permit only some protocols in href
var hrefWhitelist = ["http://","https://","ftp://","//"];
$(div).find("[href]").each(function() {
var attributeValue = $(this).attr('href');
for(var protocol in hrefWhitelist)
if(attributeValue.indexOf(hrefWhitelist[protocol]) == 0)
return;
$(this).removeAttr('href');
});
return $(div).html();
}
function timeAgoToInterval(secs)
{
var days = Math.floor(secs / 86400);
@ -205,8 +254,29 @@ Loading cockatrice web client...
$(".room-header, .room-container").remove();
},
"serverMessageCallback" : function(message) {
$("#servermessages").append(htmlEscape(message) + '<br/>');
$("#servermessages").append(htmlSanitize(message) + '<br/>');
},
"serverIdentificationCallback" : function(data) {
console.log('Connected to: ' + data.serverName + ' version ' + data.serverVersion + ' protocol ' + data.protocolVersion);
},
"serverShutdownCallback" : function(data) {
$("#info-dialog").text('The server is going to be restarted in ' + data.minutes + ' minute(s).\nAll running games will be lost.\nReason for shutdown: ' + data.reason);
$("#info-dialog").dialog();
},
"notifyUserCallback" : function(data) {
switch(data.type)
{
case WebClient.pb.Event_NotifyUser.NotificationType.PROMOTED:
$("#info-dialog").text('You have been promoted to moderator. Please log out and back in for changes to take effect.');
$("#info-dialog").dialog();
break;
case WebClient.pb.Event_NotifyUser.NotificationType.WARNING:
$("#info-dialog").text('You have received a warning due to ' + data.warningReason + '.\nPlease refrain from engaging in this activity or further actions may be taken against you. If you have any questions, please private message a moderator.');
$("#info-dialog").dialog();
break;
}
},
"userInfoCallback" : function(data) {
$("#userinfo").empty();
$.each(data.userInfo, function(key, value) {
@ -240,13 +310,16 @@ Loading cockatrice web client...
$('#buddies').empty();
$.each(data.buddyList, function(key, value) {
$('#buddies').append('<option>' + value.name + '</option>');
debugger;
$('#buddies').append('<li>' + value.name + '</li>');
});
$("#buddies").selectable();
$('#ignores').empty();
$.each(data.ignoreList, function(key, value) {
$('#ignores').append('<option>' + value.name + '</option>');
$('#ignores').append('<li>' + value.name + '</li>');
});
$("#ignores").selectable();
$("#features").empty();
$.each(data.missingFeatures, function(key, value) {
@ -262,14 +335,14 @@ Loading cockatrice web client...
$("#error-dialog").dialog();
},
"joinRoomCallback" : function(room) {
$("div#tabs ul").append(
$("div#tabs > ul").append(
"<li class='room-header'><a href='#tab-room-" + room["roomId"] + "'>" + room["name"] + "</a></li>"
);
$("div#tabs").append(
"<div class='room-container' id='tab-room-" + room["roomId"] + "'>" +
"<div class='userlist-container'>" +
"<h3>Userlist</h3>" +
"<select class=\"userlist\" size=\"10\"></select>" +
"<ul class=\"userlist\" size=\"10\"></ul>" +
"</div><div class='chat-container'>" +
"<h3>Chat</h3>" +
"<div class=\"output\"></div>" +
@ -281,8 +354,9 @@ Loading cockatrice web client...
$("#tab-room-" + room["roomId"] + " .userlist").empty();
$.each(room["userList"], function(key, value) {
$("#tab-room-" + room["roomId"] + " .userlist").append('<option>' + value.name + '</option>');
$("#tab-room-" + room["roomId"] + " .userlist").append('<li>' + value.name + '</li>');
});
$("#tab-room-" + room["roomId"] + " .userlist").selectable();
$("#tab-room-" + room["roomId"] + " .say").click(function() {
var msg = $("#tab-room-" + room["roomId"] + " .input").val();

View file

@ -24,6 +24,7 @@ h3 {
#tab-login input {
margin-bottom: 10px;
width: 20em;
}
#loading {
@ -33,7 +34,7 @@ h3 {
}
.output, #servermessages {
min-height: 400px;
height: 400px;
overflow-x: hidden;
overflow-y: scroll;
word-wrap: break-word;
@ -44,7 +45,7 @@ h3 {
}
.input {
width:93%;
width:92%;
}
.say {
@ -75,7 +76,27 @@ h3 {
#buddies, #ignores, .userlist {
width: 100%;
min-height: 470px;
height: 500px;
list-style-type: none;
overflow-x: hidden;
overflow-y: scroll;
background: #fff;
padding: 0;
margin: 0;
cursor: pointer;
border: 1px solid #999;
}
#buddies li, #ignores li, .userlist li {
padding: 0 3px;
}
#buddies .ui-selecting, #ignores .ui-selecting, .userlist .ui-selecting {
background: #FECA40;
}
#buddies .ui-selected, #ignores .ui-selected, .userlist .ui-selected {
background: #F39814; color: white;
}
.buddies-container, .ignores-container, .userinfo-container, .missingfeatures-container {

View file

@ -9,6 +9,7 @@ var StatusEnum = {
var WebClient = {
status : StatusEnum.DISCONNECTED,
protocolVersion : 14,
socket : 0,
keepalivecb: null,
lastPingPending: false,
@ -39,6 +40,9 @@ var WebClient = {
"pb/response_login.proto",
"pb/session_event.proto",
"pb/event_server_message.proto",
"pb/event_server_identification.proto",
"pb/event_server_shutdown.proto",
"pb/event_notify_user.proto",
"pb/event_connection_closed.proto",
"pb/event_list_rooms.proto",
"pb/response_join_room.proto",
@ -157,8 +161,14 @@ var WebClient = {
"userName" : this.options.user,
"password" : this.options.pass,
"clientid" : this.guid(),
"clientver" : "webclient-0.1 (2015-12-23)",
"clientfeatures" : [ "client_id", "client_ver"],
"clientver" : "webclient-0.2 (2016-08-03)",
"clientfeatures" : [
"client_id",
"client_ver",
"feature_set",
"room_chat_history",
"client_warnings"
]
});
var sc = new WebClient.pb.SessionCommand({
@ -293,6 +303,37 @@ var WebClient = {
}
return;
}
if(raw[".Event_ServerIdentification.ext"]) {
if(this.options.serverIdentificationCallback)
this.options.serverIdentificationCallback(
raw[".Event_ServerIdentification.ext"]
);
if(raw[".Event_ServerIdentification.ext"].protocolVersion != WebClient.protocolVersion)
{
WebClient.socket.close();
WebClient.setStatus(StatusEnum.DISCONNECTED, 'Protocol version mismatch: ' + raw[".Event_ServerIdentification.ext"].protocolVersion);
return;
}
WebClient.setStatus(StatusEnum.CONNECTED, 'Logging in...');
WebClient.resetConnectionvars();
WebClient.doLogin();
return;
}
if(raw[".Event_ServerShutdown.ext"]) {
if(this.options.serverShutdownCallback)
this.options.serverShutdownCallback(raw[".Event_ServerShutdown.ext"]);
return;
}
if(raw[".Event_NotifyUser.ext"]) {
if(this.options.notifyUserCallback)
this.options.notifyUserCallback(raw[".Event_NotifyUser.ext"]);
return;
}
},
processRoomEvent : function (raw)
@ -348,9 +389,7 @@ var WebClient = {
}
this.socket.onopen = function(){
WebClient.setStatus(StatusEnum.CONNECTED, 'Connected, logging in...');
WebClient.resetConnectionvars();
WebClient.doLogin();
WebClient.setStatus(StatusEnum.CONNECTED, 'Connected');
}
this.socket.onmessage = function(event) {