more work on mithril lobby

pull/185/head
Thibault Duplessis 2014-12-28 18:50:30 +01:00
parent 4c8b9bff5b
commit 85f87f19b6
25 changed files with 440 additions and 541 deletions

View File

@ -53,7 +53,7 @@ object Lobby extends LilaController {
negotiate(
html = if (HTTPRequest isSynchronousHttp ctx.req) fuccess(Redirect(routes.Lobby.home))
else fuccess(html.lobby.seeks(seeks)),
api = _ => fuccess(Ok(Json.obj("seeks" -> JsArray(seeks.map(_.render)))))
api = _ => fuccess(Ok(JsArray(seeks.map(_.render))))
)
}
}

View File

@ -9,5 +9,12 @@ trans.joinTheGame,
trans.cancel,
trans.casual,
trans.rated,
trans.variant
trans.variant,
trans.mode,
trans.list,
trans.graph,
trans.filterGames,
trans.youNeedAnAccountToDoThat,
trans.oneDay,
trans.nbDays
)))

View File

@ -1,8 +1,6 @@
@(form: Form[_], key: String, index: Int, value: String, checks: List[String], text: Html, hint: Option[String])
<label @hint.map { h =>
data-hint="@h" class="hover hint--bottom"
}.getOrElse {class="hover"}>
<label class="hover" @hint.map { h => title="@h" }>
<input
type="checkbox"
name="@{form(key).name}[@index]"

View File

@ -2,6 +2,6 @@
@options.zipWithIndex.map {
case ((value, text, hint), index) => {
@setup.filterCheckbox(form, key, index, value.toString, checks, Html(text), hint)
<div class="checkable">@setup.filterCheckbox(form, key, index, value.toString, checks, Html(text), hint)</div>
}
}

View File

@ -26,6 +26,9 @@ final class LobbyApi(
(ctx.me ?? GameRepo.nowPlaying) zip
getFilter(ctx) map {
case (((hooks, seeks), povs), filter) => Json.obj(
"me" -> ctx.me.map { u =>
Json.obj("username" -> u.username)
},
"version" -> lobbyVersion(),
"hooks" -> JsArray(hooks map (_.render)),
"seeks" -> JsArray(seeks map (_.render)),

View File

@ -50,7 +50,7 @@ case class Seek(
"username" -> user.username,
"rating" -> rating,
"variant" -> realVariant.shortName,
"mode" -> realMode.toString,
"mode" -> realMode.id,
"days" -> daysPerTurn,
"color" -> chess.Color(color).??(_.name),
"perf" -> Json.obj(

View File

@ -18,7 +18,7 @@ case class FilterConfig(
def render = play.api.libs.json.Json.obj(
"variant" -> variant.map(_.shortName),
"mode" -> mode.map(_.toString),
"mode" -> mode.map(_.id),
"speed" -> speed.map(_.id),
"rating" -> ratingRange.notBroad.map(rr => List(rr.min, rr.max)))

View File

@ -1237,132 +1237,6 @@ var storage = {
var $newposts = $("div.new_posts");
var nbPlayersElement = document.getElementById('site_baseline span');
var lobby;
// var $canvas = $wrap.find('.canvas');
// var $hooksList = $wrap.find('#hooks_list');
// var $tableWrap = $hooksList.find('div.table_wrap');
// var $table = $tableWrap.find('table').sortable();
// var $tbody = $table.find('tbody');
// var animation = 500;
// var hookPool = [];
// var nextHooks = [];
// var flushHooksTimeout;
// var flushHooksSchedule = function() {
// flushHooksTimeout = setTimeout(flushHooks, 8000);
// };
// var flushHooks = function() {
// clearTimeout(flushHooksTimeout);
// $tbody.fadeIn(500);
// $tableWrap.clone().attr('id', 'tableclone').appendTo($hooksList).fadeOut(500, function() {
// $(this).remove();
// });
// $tbody.find('tr.disabled').remove();
// $tbody.append(nextHooks);
// nextHooks = [];
// $table.trigger('sortable.sort');
// flushHooksSchedule();
// };
// flushHooksSchedule();
// $('body').on('lichess.hook-flush', flushHooks);
// $wrap.on('click', '>div.tabs>a', function() {
// var tab = $(this).data('tab');
// $(this).siblings().removeClass('active').end().addClass('active');
// $wrap.find('>.tab').hide().filter('.' + tab).show();
// storage.set('lobbytab', tab);
// reloadSeeksIfVisible();
// });
// var active = storage.get('lobbytab');
// if (['real_time', 'seeks', 'now_playing'].indexOf(active) === -1) active = 'real_time';
// if (!$wrap.find('>div.tabs>.' + active).length) active = 'real_time';
// $wrap.find('>div.tabs>.' + active).addClass('active');
// $wrap.find('>.' + active).show();
// $realTime.on('click', '.toggle', function() {
// var mode = $(this).data('mode');
// $realTime.children().hide().filter('#hooks_' + mode).show();
// storage.set('lobbymode', mode);
// });
// var mode = storage.get('lobbymode') || 'list';
// $('#hooks_' + mode).show();
// $wrap.find('a.filter').click(function() {
// var $a = $(this);
// var $div = $wrap.find('#hook_filter');
// setTimeout(function() {
// $div.click(function(e) {
// e.stopPropagation();
// });
// $('html').one('click', function(e) {
// $div.off('click').removeClass('active');
// $a.removeClass('active');
// });
// }, 10);
// if ($(this).toggleClass('active').hasClass('active')) {
// $div.addClass('active');
// if ($div.is(':empty')) {
// $.ajax({
// url: $(this).attr('href'),
// success: function(html) {
// var save = $.fp.debounce(function() {
// var $form = $div.find('form');
// $.ajax({
// url: $form.attr('action'),
// data: $form.serialize(),
// type: 'post',
// success: function(filter) {
// lichess_preload.filter = filter;
// drawHooks();
// $('body').trigger('lichess.hook-flush');
// }
// });
// }, 500);
// $div.html(html).find('input').change(save);
// $div.find('button.reset').click(function() {
// $div.find('label input').prop('checked', true).trigger('change');
// $div.find('.rating_range').each(function() {
// var s = $(this);
// s.slider('values', [s.slider('option', 'min'), s.slider('option', 'max')]).trigger('change');
// });
// });
// $div.find('button').click(function() {
// $wrap.find('a.filter').click();
// return false;
// });
// $div.find('.rating_range').each(function() {
// var $this = $(this);
// var $input = $this.find("input");
// var $span = $this.siblings(".range");
// var min = $input.data("min");
// var max = $input.data("max");
// var values = $input.val() ? $input.val().split("-") : [min, max];
// $span.text(values.join(' - '));
// function change() {
// setTimeout(function() {
// var values = $this.slider('values');
// $input.val(values[0] + "-" + values[1]);
// $span.text(values[0] + " - " + values[1]);
// save();
// }, 50);
// }
// $this.slider({
// range: true,
// min: min,
// max: max,
// values: values,
// step: 50,
// slide: change
// }).change(change);
// });
// }
// });
// }
// } else {
// $div.removeClass('active');
// }
// return false;
// });
function resizeTimeline() {
if ($timeline.length) {
@ -1375,10 +1249,6 @@ var storage = {
}
resizeTimeline();
// lichess_preload.hookPool.forEach(addHook);
// drawHooks(true);
// $table.find('th:eq(2)').click().end();
lichess.socket = new lichess.StrongSocket(
'/lobby/socket/v1',
cfg.data.version, {
@ -1400,13 +1270,6 @@ var storage = {
streams: function(html) {
$('#streams_on_air').html(html);
},
// hook_add: function(hook) {
// addHook(hook);
// drawHooks();
// if (hook.action == 'cancel') $('body').trigger('lichess.hook-flush');
// },
// hook_remove: removeHook,
// hook_list: syncHookIds,
featured: changeFeatured,
redirect: function(e) {
$.lichessOpeningPreventClicks();
@ -1426,7 +1289,6 @@ var storage = {
});
}, Math.round(Math.random() * 5000));
},
// reload_seeks: reloadSeeksIfVisible,
nbr: function(e) {
if (nbPlayersElement && e) {
var prev = parseInt(nbPlayersElement.textContent, 10);
@ -1465,24 +1327,6 @@ var storage = {
cfg.socketSend = lichess.socket.send.bind(lichess.socket);
lobby = LichessLobby(document.getElementById('hooks_wrap'), cfg);
// var variantConfirms = {
// '960': "This is a Chess960 game!\n\nThe starting position of the pieces on the players' home ranks is randomized.\nRead more: http://wikipedia.org/wiki/Chess960\n\nDo you want to play Chess960?",
// 'KotH': "This is a King of the Hill game!\n\nThe game can be won by bringing the king to the center.\nRead more: http://lichess.org/king-of-the-hill",
// '3+': "This is a Three-check game!\n\nThe game can be won by checking the opponent 3 times.\nRead more: http://en.wikipedia.org/wiki/Three-check_chess",
// "Anti": "This is an antichess chess game!\n\n If you can take a piece, you must. The game can be won by losing all your pieces."
// };
// function confirmVariant(variant) {
// return Object.keys(variantConfirms).every(function(key) {
// var v = variantConfirms[key]
// if (variant == key && !storage.get(key)) {
// var c = confirm(v);
// if (c) storage.set(key, 1);
// return c;
// } else return true;
// })
// }
// $seeks.on('click', 'tr', function() {
// if ($(this).hasClass('must_login')) {
// if (confirm($.trans('You need an account to do that'))) {
@ -1510,189 +1354,6 @@ var storage = {
$('body').trigger('lichess.content_loaded');
}
// function removeHook(id) {
// hookPool = hookPool.filter(function(h) {
// return h.id != id;
// });
// drawHooks();
// }
// function syncHookIds(ids) {
// hookPool = hookPool.filter(function(h) {
// return $.fp.contains(ids, h.id);
// });
// drawHooks();
// }
// function addHook(hook) {
// hook.action = hook.uid == lichess.StrongSocket.sri ? "cancel" : "join";
// hookPool.push(hook);
// }
// function disableHook(id) {
// $tbody.children('.' + id).addClass('disabled').attr('title', '');
// destroyChartHook(id);
// }
// function destroyHook(id) {
// $tbody.children('.' + id).remove();
// destroyChartHook(id);
// }
// function destroyChartHook(id) {
// $('#' + id).not('.hiding').addClass('hiding').fadeOut(animation, function() {
// $.powerTip.destroy($(this));
// $(this).remove();
// });
// }
// function drawHooks(initial) {
// var filter = lichess_preload.filter;
// var seen = [];
// var hidden = 0;
// var visible = 0;
// hookPool.forEach(function(hook) {
// var hide = !$.fp.contains(filter.variant, hook.variant) || !$.fp.contains(filter.mode, hook.mode) || !$.fp.contains(filter.speed, hook.speed) ||
// (filter.rating && (!hook.rating || (hook.rating < filter.rating[0] || hook.rating > filter.rating[1])));
// var hash = hook.mode + hook.variant + hook.time + hook.rating;
// if (hide && hook.action != 'cancel') {
// destroyHook(hook.id);
// hidden++;
// } else if ($.fp.contains(seen, hash) && hook.action != 'cancel') {
// $('#' + hook.id).filter(':visible').hide();
// $tbody.children('.' + hook.id).hide();
// } else {
// visible++;
// if (!$('#' + hook.id).length) {
// $canvas.append($(renderPlot(hook)).fadeIn(animation));
// if (initial) $tbody.append(renderTr(hook));
// else nextHooks.push(renderTr(hook));
// } else {
// $('#' + hook.id).not(':visible').fadeIn(animation);
// $tbody.children('.' + hook.id).show();
// }
// }
// if (hook.action != 'cancel') seen.push(hash);
// });
// $.makeArray($canvas.find('>span.plot')).map(function(o) {
// return o.getAttribute('data-id');
// }).concat(
// $.makeArray($tbody.children()).map(function(o) {
// return o.getAttribute('data-id');
// })).forEach(function(id) {
// if (!$.fp.find(hookPool, function(x) {
// return x.id == id;
// })) disableHook(id);
// });
// $wrap
// .find('a.filter')
// .toggleClass('on', hidden > 0)
// .find('span.number').text('(' + hidden + ')');
// $('body').trigger('lichess.content_loaded');
// }
// function renderPlot(hook) {
// var bottom = Math.max(0, ratingY(hook.rating) - 7);
// var left = Math.max(0, clockX(hook.time) - 4);
// var klass = [
// 'plot',
// hook.mode == "Rated" ? 'rated' : 'casual',
// hook.action == 'cancel' ? 'cancel' : '',
// hook.variant != 'STD' ? 'variant' : ''
// ].join(' ');
// var $plot = $('<span id="' + hook.id + '" class="' + klass + '" style="bottom:' + bottom + 'px;left:' + left + 'px;"></span>');
// return $plot.data('hook', hook).powerTip({
// fadeInTime: 0,
// fadeOutTime: 0,
// placement: hook.rating > 2200 ? 'se' : 'ne',
// mouseOnToPopup: true,
// closeDelay: 200,
// intentPollInterval: 50,
// popupId: 'hook'
// }).data('powertipjq', $(renderHook(hook)));
// }
// function ratingY(e) {
// function ratingLog(a) {
// return Math.log(a / 150 + 1);
// }
// var rating = Math.max(800, Math.min(2800, e || 1500));
// var ratio;
// if (rating == 1500) {
// ratio = 0.25;
// } else if (rating > 1500) {
// ratio = 0.25 + (ratingLog(rating - 1500) / ratingLog(1300)) * 3 / 4;
// } else {
// ratio = 0.25 - (ratingLog(1500 - rating) / ratingLog(500)) / 4;
// }
// return Math.round(ratio * 489);
// }
// function clockX(dur) {
// function durLog(a) {
// return Math.log((a - 30) / 200 + 1);
// }
// var max = 2000;
// return Math.round(durLog(Math.min(max, dur || max)) / durLog(max) * 489);
// }
// function renderHook(hook) {
// var html = '';
// if (hook.rating) {
// html += '<a class="opponent" href="/@/' + hook.username + '">' + hook.username.substr(0, 14) + '</a>';
// html += '<span class="rating">' + hook.rating + '</span>';
// } else {
// html += '<span class="opponent anon">Anonymous</span>';
// }
// html += '<span class="clock">' + hook.clock + '</span>';
// html += '<span class="mode">' +
// '<span class="varicon" data-icon="' + hook.perf.icon + '"></span>' + $.trans(hook.mode) + '</span>';
// html += '<span class="is is2 color-icon ' + (hook.color || "random") + '"></span>';
// return html;
// }
// function renderTr(hook) {
// var title = (hook.action == "join") ? $.trans('Join the game') + ' - ' + hook.perf.name : $.trans('cancel');
// return '<tr title="' + title + '" data-id="' + hook.id + '" class="' + hook.id + ' ' + hook.action + '">' + [
// ['', '<span class="is is2 color-icon ' + (hook.color || "random") + '"></span>'],
// [hook.username, (hook.rating ? '<a href="/@/' + hook.username + '" class="ulink">' + hook.username + '</a>' : 'Anonymous')],
// [hook.rating || 0, hook.rating ? hook.rating : ''],
// [hook.time, hook.clock],
// [hook.mode,
// '<span class="varicon" data-icon="' + hook.perf.icon + '"></span>' +
// $.trans(hook.mode)
// ]
// ].map(function(x) {
// return '<td data-sort-value="' + x[0] + '">' + x[1] + '</td>';
// }).join('') + '</tr>';
// }
// $('#hooks_chart').append(
// [1000, 1200, 1400, 1500, 1600, 1800, 2000, 2200, 2400].map(function(v) {
// var b = ratingY(v);
// return '<span class="y label" style="bottom:' + (b + 5) + 'px">' + v + '</span>' +
// '<div class="grid horiz" style="height:' + (b + 4) + 'px"></div>';
// }).join('') + [1, 2, 3, 5, 7, 10, 15, 20, 30].map(function(v) {
// var l = clockX(v * 60);
// return '<span class="x label" style="left:' + l + 'px">' + v + '</span>' +
// '<div class="grid vert" style="width:' + (l + 7) + 'px"></div>';
// }).join(''));
// $tbody.on('click', 'a.ulink', function(e) {
// e.stopPropagation();
// });
// $tbody.on('click', 'td:not(.disabled)', function() {
// $('#' + $(this).parent().data('id')).click();
// });
// $canvas.on('click', '>span.plot:not(.hiding)', function() {
// var data = $(this).data('hook');
// if (data.action != 'join' || confirmVariant(data.variant)) {
// lichess.socket.send(data.action, data.id);
// }
// });
var $startButtons = $('#start_buttons');
if (!lichess.StrongSocket.available) {
@ -1803,10 +1464,7 @@ var storage = {
type: 'post'
});
$form.find('a.close').click();
if ($timeModeSelect.val() == '1')
$('#hooks_wrap .tabs .real_time').click();
else
$('#hooks_wrap .tabs .seeks').click();
lobby.setTab($timeModeSelect.val() === '1' ? 'real_time' : 'seeks');
return false;
};
$formTag.find('.color_submits button').click(function() {

View File

@ -180,7 +180,6 @@ body.dark div.undertable_top span.title {
color: #777;
}
body.dark .crosstable td a,
body.dark #hook_filter td > label.hover:hover,
body.dark #promotion_choice {
background: rgba(0, 0, 0, 0.7);
}
@ -210,15 +209,10 @@ body.dark #hooks_wrap .table_wrap tr.hook:hover td,
body.dark #now_playing > a:hover {
background: rgba(27, 51, 68, 0.7);
}
body.dark #hook_filter {
background: rgba(0, 0, 0, 0.8);
}
body.dark #hook_filter td > label {
body.dark #hook_filter .checkable {
color: #c0c0c0;
}
body.dark #hooks_wrap,
body.dark #hooks_wrap a.filter:hover,
body.dark #hooks_wrap a.filter.active,
body.dark #hooks_wrap > div.tabs > a:hover,
body.dark #hooks_wrap > div.tabs > a.active {
background-color: #303030;

View File

@ -32,14 +32,14 @@ div.lobby_and_ground {
background: #f0f0f0 url(../images/wN-bg.svg);
background-size: 100% 100%;
}
#hooks_wrap > div.tabs {
#hooks_wrap > .tabs {
position: absolute;
top: -22px;
left: 0px;
height: 20px;
line-height: 20px;
}
#hooks_wrap > div.tabs > a {
#hooks_wrap > .tabs > a {
display: inline-block;
text-decoration: none;
padding: 0px 8px;
@ -48,99 +48,76 @@ div.lobby_and_ground {
background: #dadada;
transition: 0.13s;
}
#hooks_wrap > div.tabs > a:hover,
#hooks_wrap > div.tabs > a.active {
#hooks_wrap > .tabs > a:hover,
#hooks_wrap > .tabs > a.active {
background: #f0f0f0;
}
#hooks_wrap > div.tabs > a:hover {
#hooks_wrap > .tabs > a:hover {
border-top: 2px solid #808080;
}
#hooks_wrap > div.tabs > a.active {
#hooks_wrap > .tabs > a.active {
font-weight: bold;
border-bottom-color: #f0f0f0;
border-top: 2px solid #d85000;
}
#hooks_wrap > div.tabs .unread {
#hooks_wrap > .tabs .unread {
margin-left: 3px;
}
#hooks_wrap .toggle {
cursor: pointer;
}
#hooks_wrap .hooks_chart .toggle {
#hooks_wrap .toggles {
position: absolute;
top: 15px;
left: 13px;
top: 13px;
left: 15px;
width: 483px;
z-index: 2;
}
#hooks_wrap > a.filter {
position: absolute;
top: -20px;
left: 487px;
height: 20px;
line-height: 20px;
font-size: 1.1em;
padding: 0 5px;
border-bottom: 0;
display: block;
text-decoration: none;
#hooks_wrap .mode_toggle {
float: left;
cursor: pointer;
}
#hooks_wrap .filter_toggle {
float: right;
cursor: pointer;
font-size: 1.2em;
opacity: 0.8;
transition: 0.13s;
}
#hooks_wrap > a.filter:hover,
#hooks_wrap > a.filter.active {
background: #f0f0f0;
#hooks_wrap .filter_toggle .number {
margin-left: 3px;
font-size: 0.8em;
}
#hooks_wrap > a.filter span.number {
display: none;
#hooks_wrap .filter_toggle:hover {
opacity: 1;
}
#hooks_wrap > a.filter.on {
padding: 0 10px 0 2px;
#hooks_wrap .hook_filter {
padding: 10px 20px;
}
#hooks_wrap > a.filter.on span.number {
display: inline;
}
#hook_filter {
position: absolute;
z-index: 99;
top: 1px;
left: 1px;
width: 472px;
height: calc(100% - 42px);
padding: 20px;
background: rgba(255, 255, 255, 0.8);
display: none;
}
#hook_filter.active {
display: block;
}
#hook_filter table {
#hooks_wrap .hook_filter table {
width: 100%;
}
#hook_filter td {
#hooks_wrap .hook_filter td {
padding: 20px 0;
}
#hook_filter td:first-child {
#hooks_wrap .hook_filter td:first-child {
font-size: 1.3em;
}
#hook_filter td > label {
display: block;
#hooks_wrap .hook_filter .checkable {
padding: 3px 0;
color: #444;
}
#hook_filter label.hover,
#hook_filter input {
#hooks_wrap .hook_filter label.hover,
#hooks_wrap .hook_filter input {
vertical-align: middle;
cursor: pointer;
}
#hook_filter td > label.hover:hover {
background: #fff;
}
#hook_filter .range {
#hooks_wrap .hook_filter .range {
display: block;
text-align: center;
}
#hook_filter .actions {
#hooks_wrap .hook_filter .actions {
margin-top: 20px;
text-align: right;
}
#hook_filter .actions button {
#hooks_wrap .hook_filter .actions button {
padding: 6px;
margin-left: 3px;
}
@ -155,9 +132,6 @@ div.lobby_and_ground {
font-weight: lighter;
border-bottom: transparent;
}
#hooks_list thead th {
cursor: pointer;
}
#hooks_wrap .table_wrap th.sorting-asc,
#hooks_wrap .table_wrap th.sorting-desc {
font-weight: normal;

View File

@ -2,20 +2,28 @@ var m = require('mithril');
var socket = require('./socket');
var variant = require('./variant');
var hookRepo = require('./hookRepo');
var seekRepo = require('./seekRepo');
var store = require('./store');
var xhr = require('./xhr');
var util = require('chessground').util;
module.exports = function(env) {
this.data = env.data;
this.data.hooks.forEach(hookRepo.init);
hookRepo.sort(this);
this.data.seeks.forEach(seekRepo.init);
seekRepo.sort(this);
this.socket = new socket(env.socketSend, this);
this.vm = {
tab: store.tab.get(),
mode: store.mode.get(),
stepHooks: hookRepo.stepSlice(this),
filter: {
open: false
},
stepHooks: this.data.hooks.slice(0),
stepping: false
};
@ -27,7 +35,7 @@ module.exports = function(env) {
m.redraw();
setTimeout(function() {
this.vm.stepping = false;
this.vm.stepHooks = hookRepo.stepSlice(this);
this.vm.stepHooks = this.data.hooks.slice(0);
m.redraw();
}.bind(this), 500);
flushHooksSchedule();
@ -37,11 +45,21 @@ module.exports = function(env) {
flushHooksSchedule();
this.setTab = function(tab) {
if (tab === 'seeks' && tab !== this.vm.tab) xhr.seeks().then(this.setSeeks);
this.vm.tab = store.tab.set(tab);
}.bind(this);
this.setMode = function(mode) {
this.vm.mode = store.mode.set(mode);
this.vm.filter.open = false;
}.bind(this);
this.toggleFilter = function() {
this.vm.filter.open = !this.vm.filter.open;
}.bind(this);
this.setFilter = function(filter) {
this.data.filter = filter;
}.bind(this);
this.clickHook = function(id) {
@ -52,6 +70,19 @@ module.exports = function(env) {
// if (hook.action === 'cancel' || variant.confirm(hook.variant)) this.socket.send(hook.action, hook.id);
}.bind(this);
this.clickSeek = function(id) {
var seek = seekRepo.find(this, id);
if (!seek) return;
console.log(seek);
// if (hook.action === 'cancel' || variant.confirm(hook.variant)) this.socket.send(hook.action, hook.id);
}.bind(this);
this.setSeeks = function(seeks) {
this.data.seeks = seeks;
this.data.seeks.forEach(seekRepo.init);
seekRepo.sort(this);
}.bind(this);
this.router = env.routes;
this.trans = function(key) {
var str = env.i18n[key] || key;

View File

@ -0,0 +1,21 @@
module.exports = function(ctrl, hooks) {
var f = ctrl.data.filter;
var seen = [], hidden = 0, visible = [];
hooks.forEach(function(hook) {
if (hook.action === 'cancel') visible.push(hook);
else {
if (!$.fp.contains(f.variant, hook.variant) || !$.fp.contains(f.mode, hook.mode) || !$.fp.contains(f.speed, hook.speed) ||
(f.rating && (!hook.rating || (hook.rating < f.rating[0] || hook.rating > f.rating[1])))) {
hidden++;
} else {
var hash = hook.mode + hook.variant + hook.time + hook.rating;
if (!$.fp.contains(seen, hash)) visible.push(hook);
seen.push(hash);
}
}
});
return {
visible: visible,
hidden: hidden
};
}

View File

@ -6,10 +6,20 @@ function sort(ctrl) {
ctrl.data.hooks.sort(order);
}
function fixBC(hook) {
hook.mode = hook.mode === 'Casual' ? 0 : 1;
}
function init(hook) {
hook.action = hook.uid === lichess.socket.settings.params.sri ? 'cancel' : 'join';
fixBC(hook);
}
module.exports = {
init: init,
sort: sort,
add: function(ctrl, hook) {
hook.action = hook.uid === lichess.socket.settings.params.sri ? 'cancel' : 'join';
init(hook);
ctrl.data.hooks.push(hook);
sort(ctrl);
},
@ -26,9 +36,6 @@ module.exports = {
return ids.indexOf(h.id) !== -1;
});
},
stepSlice: function(ctrl) {
return ctrl.data.hooks.slice(0, 14);
},
find: function(ctrl, id) {
return ctrl.data.hooks.filter(function(h) {
return h.id === id;

View File

@ -13,7 +13,11 @@ module.exports = function(element, opts) {
});
return {
socketReceive: controller.socket.receive
socketReceive: controller.socket.receive,
setTab: function(tab) {
controller.setTab(tab);
m.redraw();
}
};
};

View File

@ -0,0 +1,26 @@
function order(a, b) {
return a.rating > b.rating ? -1 : 1;
}
function sort(ctrl) {
ctrl.data.seeks.sort(order);
}
function fixBC(seek) {
seek.mode = seek.mode === 'Casual' ? 0 : 1;
}
function init(seek) {
seek.action = seek.uid === lichess.socket.settings.params.sri ? 'cancelSeek' : 'joinSeek';
fixBC(seek);
}
module.exports = {
init: init,
sort: sort,
find: function(ctrl, id) {
return ctrl.data.seeks.filter(function(s) {
return s.id === id;
})[0];
}
};

View File

@ -19,11 +19,13 @@ module.exports = function(send, ctrl) {
hook_list: function(ids) {
hookRepo.syncIds(ctrl, ids);
m.redraw();
},
reload_seeks: function() {
if (ctrl.vm.tab === 'seeks') xhr.seeks().then(ctrl.setSeeks);
}
};
this.receive = function(type, data) {
// if (type != 'n') console.log(type, data);
if (handlers[type]) {
handlers[type](data);
return true;

View File

@ -0,0 +1,54 @@
var m = require('mithril');
var tds = require('./util').tds;
var util = require('chessground').util;
function renderSeek(ctrl, seek) {
return m('tr', {
key: seek.id,
title: (seek.action === 'joinSeek') ? ctrl.trans('joinTheGame') + ' - ' + seek.perf.name : ctrl.trans('cancel'),
'data-id': seek.id,
class: 'seek ' + seek.action
}, tds([
m('span', {
class: 'is is2 color-icon ' + (seek.color || 'random')
}), (seek.rating ? m('a.ulink', {
href: '/@/' + seek.username
}, seek.username) : 'Anonymous'),
seek.rating ? seek.rating : '',
seek.days ? ctrl.trans(seek.days === 1 ? 'oneDay' : 'nbDays', seek.days) : '∞', [m('span', {
class: 'varicon',
'data-icon': seek.perf.icon
}), ctrl.trans(seek.mode === 1 ? 'rated' : 'casual')]
]));
};
module.exports = function(ctrl) {
return m('table.table_wrap', [
m('thead',
m('tr', [
m('th'),
m('th', ctrl.trans('player')),
m('th', 'Rating'),
m('th', ctrl.trans('time')),
m('th', ctrl.trans('mode'))
])
),
m('tbody', {
onclick: function(e) {
var el = e.target;
if (el.classList.contains('ulink')) return;
do {
el = el.parentNode;
if (el.nodeName === 'TR') {
if (!this.data.me) {
if (confirm(this.trans('youNeedAnAccountToDoThat'))) location.href = '/signup';
return;
}
return ctrl.clickSeek(el.getAttribute('data-id'));
}
}
while (el.nodeName !== 'TABLE');
}
}, ctrl.data.seeks.map(util.partial(renderSeek, ctrl)))
]);
};

View File

@ -1,20 +1,18 @@
var m = require('mithril');
var renderTabs = require('./tabs');
var renderRealTimeList = require('./realTimeList');
var renderRealTimeChart = require('./realTimeChart');
var renderRealTime = require('./realTime/main');
var renderSeeks = require('./correspondence');
module.exports = function(ctrl) {
var body;
switch (ctrl.vm.tab) {
case 'real_time':
switch (ctrl.vm.mode) {
case 'chart':
body = renderRealTimeChart(ctrl);
break;
default:
body = renderRealTimeList(ctrl);
}
body = renderRealTime(ctrl);
break;
case 'seeks':
body = renderSeeks(ctrl);
break;
}
return [
m('div.tabs', renderTabs(ctrl)),

View File

@ -120,21 +120,25 @@ function renderYAxis() {
});
}
module.exports = function(ctrl) {
return m('div.hooks_chart', [
m('span', {
module.exports = {
toggle: function(ctrl) {
return m('span', {
'data-hint': ctrl.trans('list'),
class: 'toggle hint--bottom',
class: 'mode_toggle hint--bottom',
onclick: util.partial(ctrl.setMode, 'list')
}, m('span.chart[data-icon=?]')),
m('div.canvas', {
onclick: function(e) {
if (e.target.classList.contains('plot')) {
ctrl.clickHook(e.target.id);
}, m('span.chart[data-icon=?]'));
},
render: function(ctrl, hooks) {
return m('div.hooks_chart', [
m('div.canvas', {
onclick: function(e) {
if (e.target.classList.contains('plot')) {
ctrl.clickHook(e.target.id);
}
}
}
}, ctrl.data.hooks.map(util.partial(renderPlot, ctrl))),
renderYAxis(),
renderXAxis()
]);
}, hooks.map(util.partial(renderPlot, ctrl))),
renderYAxis(),
renderXAxis()
]);
}
};

View File

@ -0,0 +1,81 @@
var m = require('mithril');
var util = require('chessground').util;
function initialize(ctrl, el) {
var $div = $(el);
var save = $.fp.debounce(function() {
var $form = $div.find('form');
$.ajax({
url: $form.attr('action'),
data: $form.serialize(),
type: 'POST',
success: function(filter) {
ctrl.setFilter(filter);
}
});
}, 200);
$div.find('input').change(save);
$div.find('button.reset').click(function() {
$div.find('label input').prop('checked', true).trigger('change');
$div.find('.rating_range').each(function() {
var s = $(this);
s.slider('values', [s.slider('option', 'min'), s.slider('option', 'max')]).trigger('change');
});
});
$div.find('button').click(function() {
ctrl.toggleFilter();
m.redraw();
return false;
});
$div.find('.rating_range').each(function() {
var $this = $(this);
var $input = $this.find("input");
var $span = $this.siblings(".range");
var min = $input.data("min");
var max = $input.data("max");
var values = $input.val() ? $input.val().split("-") : [min, max];
$span.text(values.join(' - '));
function change() {
var values = $this.slider('values');
$input.val(values[0] + "-" + values[1]);
$span.text(values[0] + " - " + values[1]);
save();
}
$this.slider({
range: true,
min: min,
max: max,
values: values,
step: 50,
slide: change
}).change(change);
});
}
module.exports = {
toggle: function(ctrl, nbFiltered) {
return m('span', {
class: 'filter_toggle' + (ctrl.vm.filter.open ? ' active' : ''),
onclick: util.partial(ctrl.toggleFilter)
}, [
ctrl.vm.filter.open ? m('span[data-icon=L]') : m('span', {
class: 'hint--bottom-left',
'data-hint': ctrl.trans('filterGames'),
}, m('span[data-icon=%]')),
nbFiltered > 0 ? m('span.number', nbFiltered) : null
]);
},
render: function(ctrl) {
return m('div.hook_filter', {
config: function(el, isUpdate, ctx) {
if (ctx.loaded) return;
$.get('/setup/filter', function(html) {
el.innerHTML = html;
ctx.loaded = true;
initialize(ctrl, el);
});
}
});
}
};

View File

@ -0,0 +1,77 @@
var m = require('mithril');
var util = require('chessground').util;
var tds = require('../util').tds;
function renderHook(ctrl, hook) {
return m('tr', {
key: hook.id,
title: (hook.action === 'join') ? ctrl.trans('joinTheGame') + ' - ' + hook.perf.name : ctrl.trans('cancel'),
'data-id': hook.id,
class: 'hook ' + hook.action + (hook.disabled ? ' disabled' : '')
}, tds([
m('span', {
class: 'is is2 color-icon ' + (hook.color || 'random')
}), (hook.rating ? m('a.ulink', {
href: '/@/' + hook.username
}, hook.username) : 'Anonymous'),
hook.rating ? hook.rating : '',
hook.clock, [m('span', {
class: 'varicon',
'data-icon': hook.perf.icon
}), ctrl.trans(hook.mode === 1 ? 'rated' : 'casual')]
]));
};
function isStandard(value) {
return function(hook) {
return (hook.variant === 'STD') === value;
};
}
module.exports = {
toggle: function(ctrl) {
return m('span', {
'data-hint': ctrl.trans('graph'),
class: 'mode_toggle hint--bottom',
onclick: util.partial(ctrl.setMode, 'chart')
}, m('span.chart[data-icon=9]'));
},
render: function(ctrl, allHooks) {
var max = 14;
var hooks = allHooks.slice(0, max);
var standards = hooks.filter(isStandard(true))
.map(util.partial(renderHook, ctrl));
var variants = hooks.filter(isStandard(false))
.slice(0, Math.max(0, max - standards.length - 1))
.map(util.partial(renderHook, ctrl));
return m('table.table_wrap', [
m('thead',
m('tr', [
m('th'),
m('th', ctrl.trans('player')),
m('th', 'Rating'),
m('th', ctrl.trans('time')),
m('th', ctrl.trans('mode'))
])
),
m('tbody', {
class: ctrl.vm.stepping ? 'stepping' : '',
onclick: function(e) {
var el = e.target;
if (el.classList.contains('ulink')) return;
do {
el = el.parentNode;
if (el.nodeName === 'TR') return ctrl.clickHook(el.getAttribute('data-id'));
}
while (el.nodeName !== 'TABLE');
}
}, [
standards,
variants.length ? m('tr.variants',
m('td[colspan=5]', '- ' + ctrl.trans('variant') + ' -')
) : null,
variants
])
]);
}
};

View File

@ -0,0 +1,32 @@
var m = require('mithril');
var list = require('./list');
var chart = require('./chart');
var filter = require('../../filter');
var filterView = require('./filter');
module.exports = function(ctrl) {
var filterBody, body, nbFiltered, modeToggle;
if (ctrl.vm.filter.open) filterBody = filterView.render(ctrl);
switch (ctrl.vm.mode) {
case 'chart':
var res = filter(ctrl, ctrl.data.hooks), hooks = res.visible;
nbFiltered = res.hidden;
body = filterBody || chart.render(ctrl, hooks);
modeToggle = ctrl.vm.filter.open ? null : chart.toggle(ctrl);
break;
default:
var res = filter(ctrl, ctrl.vm.stepHooks), hooks = res.visible;
nbFiltered = res.hidden;
body = filterBody || list.render(ctrl, hooks);
modeToggle = ctrl.vm.filter.open ? null : list.toggle(ctrl);
}
var filterToggle = filterView.toggle(ctrl, nbFiltered);
return [
m('div.toggles', [
filterToggle,
modeToggle
]),
body
];
}

View File

@ -1,76 +0,0 @@
var m = require('mithril');
var util = require('chessground').util;
function tds(bits) {
return bits.map(function(bit) {
return {
tag: 'td',
children: [bit]
};
});
}
function renderHook(ctrl, hook) {
var title = (hook.action === 'join') ? ctrl.trans('joinTheGame') + ' - ' + hook.perf.name : ctrl.trans('cancel');
return m('tr', {
key: hook.id,
title: (hook.action === 'join') ? ctrl.trans('joinTheGame') + ' - ' + hook.perf.name : ctrl.trans('cancel'),
'data-id': hook.id,
class: 'hook ' + hook.action + (hook.disabled ? ' disabled' : '')
}, tds([
m('span', {
class: 'is is2 color-icon ' + (hook.color || 'random')
}), (hook.rating ? m('a.ulink', {
href: '/@/' + hook.username
}, hook.username) : 'Anonymous'),
hook.rating ? hook.rating : '',
hook.clock, [m('span', {
class: 'varicon',
'data-icon': hook.perf.icon
}), ctrl.trans(hook.mode === 1 ? 'rated' : 'casual')]
]));
};
function isStandard(value) {
return function(hook) {
return (hook.variant === 'STD') === value;
};
}
module.exports = function(ctrl) {
var standards = ctrl.vm.stepHooks.filter(isStandard(true)).map(util.partial(renderHook, ctrl));
var variants = ctrl.vm.stepHooks.filter(isStandard(false)).map(util.partial(renderHook, ctrl));
return m('table.table_wrap', [
m('thead',
m('tr', [
m('th', m('span', {
'data-hint': ctrl.trans('graph'),
class: 'toggle hint--bottom',
onclick: util.partial(ctrl.setMode, 'chart')
}, m('span.chart[data-icon=9]'))),
m('th', ctrl.trans('player')),
m('th', 'Rating'),
m('th', ctrl.trans('time')),
m('th', ctrl.trans('mode'))
])
),
m('tbody', {
class: ctrl.vm.stepping ? 'stepping' : '',
onclick: function(e) {
var el = e.target;
if (el.classList.contains('ulink')) return;
do {
el = el.parentNode;
if (el.nodeName === 'TR') return ctrl.clickHook(el.getAttribute('data-id'));
}
while (el.nodeName !== 'TABLE');
}
}, [
standards,
variants.length ? m('tr.variants',
m('td[colspan=5]', '- ' + ctrl.trans('variant') + ' -')
) : null,
variants
])
]);
};

View File

@ -0,0 +1,12 @@
var m = require('mithril');
module.exports = {
tds: function(bits) {
return bits.map(function(bit) {
return {
tag: 'td',
children: [bit]
};
});
}
};

View File

@ -5,22 +5,14 @@ var xhrConfig = function(xhr) {
xhr.setRequestHeader('Accept', 'application/vnd.lichess.v1+json');
}
function reload(ctrl) {
ctrl.vm.reloading = true;
m.redraw();
var req = m.request({
function seeks() {
return m.request({
method: 'GET',
url: ctrl.data.url.round,
url: '/lobby/seeks',
config: xhrConfig
});
req.then(function() {
ctrl.vm.reloading = false;
}, function(err) {
lichess.reload();
});
return req;
}
module.exports = {
reload: reload
seeks: seeks
};