update embedded TV frame mini-game
parent
4d534dd954
commit
10e44190c5
|
@ -1,18 +1,19 @@
|
|||
package views.html.game
|
||||
|
||||
import chess.format.Forsyth
|
||||
import controllers.routes
|
||||
|
||||
import lila.api.Context
|
||||
import lila.app.templating.Environment._
|
||||
import lila.app.ui.ScalatagsTemplate._
|
||||
import lila.game.Pov
|
||||
|
||||
import controllers.routes
|
||||
import chess.format.Forsyth
|
||||
|
||||
object mini {
|
||||
|
||||
private val dataLive = attr("data-live")
|
||||
private val dataState = attr("data-state")
|
||||
private val dataTime = attr("data-time")
|
||||
private val cgWrap = span(cls := "cg-wrap")(cgWrapContent)
|
||||
|
||||
def apply(
|
||||
pov: Pov,
|
||||
|
@ -30,7 +31,7 @@ object mini {
|
|||
renderState(pov)
|
||||
)(
|
||||
renderPlayer(!pov),
|
||||
span(cls := "cg-wrap")(cgWrapContent),
|
||||
cgWrap,
|
||||
renderPlayer(pov)
|
||||
)
|
||||
}
|
||||
|
@ -40,13 +41,12 @@ object mini {
|
|||
val isLive = game.isBeingPlayed
|
||||
a(
|
||||
href := (if (tv) routes.Tv.index() else routes.Round.watcher(pov.gameId, pov.color.name)),
|
||||
title := gameTitle(pov.game, pov.color),
|
||||
cls := s"mini-game mini-game-${game.id} mini-game--init is2d ${isLive ?? "mini-game--live"} ${game.variant.key}",
|
||||
dataLive := isLive.option(game.id),
|
||||
renderState(pov)
|
||||
)(
|
||||
renderPlayer(!pov),
|
||||
span(cls := "cg-wrap")(cgWrapContent),
|
||||
cgWrap,
|
||||
renderPlayer(pov)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ object embed {
|
|||
),
|
||||
jQueryTag,
|
||||
jsAt("javascripts/vendor/chessground.min.js", defer = false),
|
||||
jsAt("compiled/util.js", defer = false),
|
||||
jsAt("compiled/tv.js", defer = false)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -47,13 +47,16 @@ final private class TvBroadcast extends Actor {
|
|||
featuredId = id.some
|
||||
queues.foreach(_ offer msg)
|
||||
|
||||
case MoveGameEvent(_, fen, move) if queues.nonEmpty =>
|
||||
case MoveGameEvent(game, fen, move) if queues.nonEmpty =>
|
||||
val msg = makeMessage(
|
||||
"fen",
|
||||
Json.obj(
|
||||
"fen" -> fen,
|
||||
"lm" -> move
|
||||
)
|
||||
Json
|
||||
.obj(
|
||||
"fen" -> s"$fen ${game.turnColor.letter}",
|
||||
"lm" -> move
|
||||
)
|
||||
.add("cw" -> game.clock.map(_.remainingTime(chess.White).roundSeconds))
|
||||
.add("bw" -> game.clock.map(_.remainingTime(chess.Black).roundSeconds))
|
||||
)
|
||||
queues.foreach(_ offer msg)
|
||||
}
|
||||
|
|
|
@ -81,7 +81,8 @@ object Tv {
|
|||
name = "Top Rated",
|
||||
icon = "C",
|
||||
secondsSinceLastMove = freshBlitz,
|
||||
filters = Seq(rated(2150), standard, noBot)
|
||||
filters = Seq(rated(150), standard, noBot)
|
||||
// filters = Seq(rated(2150), standard, noBot)
|
||||
)
|
||||
case object Bullet
|
||||
extends Channel(
|
||||
|
|
|
@ -10,6 +10,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.mini-board, .mini-game .cg-wrap {
|
||||
.cg-wrap {
|
||||
@extend %square;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
&__user {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
|
@ -10,12 +10,6 @@
|
|||
z-index: z("powertip");
|
||||
}
|
||||
|
||||
#powerTip {
|
||||
.mini-board {
|
||||
border-width: 0 0 1px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.upt {
|
||||
&__info {
|
||||
@extend %flex-column;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@import "../../../common/css/embed";
|
||||
@import "../../../common/css/component/board";
|
||||
@import "../../../common/css/component/vs";
|
||||
@import "../../../common/css/component/mini-game";
|
||||
@import "../tv/embed";
|
||||
|
|
|
@ -4,19 +4,14 @@ body {
|
|||
}
|
||||
|
||||
.embedded {
|
||||
.vstext, cg-board {
|
||||
background: $c-bg-page;
|
||||
padding: .3em;
|
||||
|
||||
cg-board {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
cg-board {
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
|
||||
.vstext {
|
||||
@extend %metal;
|
||||
|
||||
border-radius: 0 0 3px 3px;
|
||||
border: $border;
|
||||
border-top: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -191,96 +191,6 @@
|
|||
});
|
||||
};
|
||||
|
||||
lichess.miniBoard = {
|
||||
initAll() {
|
||||
Array.from(document.getElementsByClassName('mini-board--init')).forEach(lichess.miniBoard.init);
|
||||
},
|
||||
init(node) {
|
||||
if (!window.Chessground) return setTimeout(() => lichess.miniBoard.init(node), 500);
|
||||
const $el = $(node).removeClass('mini-board--init'),
|
||||
[fen, orientation, lm] = $el.data('state').split(',');
|
||||
$el.data('chessground', Chessground(node, {
|
||||
orientation,
|
||||
coordinates: false,
|
||||
viewOnly: !node.getAttribute('data-playable'),
|
||||
resizable: false,
|
||||
fen,
|
||||
lastMove: lm && (lm[1] === '@' ? [lm.slice(2)] : [lm[0] + lm[1], lm[2] + lm[3]]),
|
||||
drawable: {
|
||||
enabled: false,
|
||||
visible: false
|
||||
}
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
lichess.miniGame = (() => {
|
||||
const fenColor = fen => fen.indexOf(' b') > 0 ? 'black' : 'white';
|
||||
return {
|
||||
init(node, data) {
|
||||
const [fen, orientation, lm] = ((typeof data == 'string' && data) || node.getAttribute('data-state')).split(','),
|
||||
config = {
|
||||
coordinates: false,
|
||||
viewOnly: true,
|
||||
resizable: false,
|
||||
fen,
|
||||
orientation,
|
||||
lastMove: lm && (lm[1] === '@' ? [lm.slice(2)] : [lm[0] + lm[1], lm[2] + lm[3]]),
|
||||
drawable: {
|
||||
enabled: false,
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
$el = $(node).removeClass('mini-game--init'),
|
||||
$cg = $el.find('.cg-wrap'),
|
||||
turnColor = fenColor(fen);
|
||||
$cg.data('chessground', Chessground($cg[0], config));
|
||||
['white', 'black'].forEach(color =>
|
||||
$el.find('.mini-game__clock--' + color).each(function() {
|
||||
$(this).clock({
|
||||
time: parseInt(this.getAttribute('data-time')),
|
||||
pause: color != turnColor
|
||||
});
|
||||
})
|
||||
);
|
||||
return node.getAttribute('data-live');
|
||||
},
|
||||
initAll() {
|
||||
const nodes = Array.from(document.getElementsByClassName('mini-game--init')),
|
||||
ids = nodes.map(lichess.miniGame.init).filter(id => id);
|
||||
if (ids.length) window.lichess.StrongSocket.firstConnect.then(send =>
|
||||
send('startWatching', ids.join(' '))
|
||||
);
|
||||
},
|
||||
update(node, data) {
|
||||
const $el = $(node),
|
||||
lm = data.lm,
|
||||
lastMove = lm && (lm[1] === '@' ? [lm.slice(2)] : [lm[0] + lm[1], lm[2] + lm[3]]),
|
||||
cg = $el.find('.cg-wrap').data('chessground');
|
||||
cg.set({
|
||||
fen: data.fen,
|
||||
lastMove
|
||||
});
|
||||
const turnColor = fenColor(data.fen);
|
||||
const renderClock = (time, color) => {
|
||||
if (!isNaN(time)) $el.find('.mini-game__clock--' + color).clock('set', {
|
||||
time,
|
||||
pause: color != turnColor
|
||||
});
|
||||
};
|
||||
renderClock(data.wc, 'white');
|
||||
renderClock(data.bc, 'black');
|
||||
},
|
||||
finish(node, win) {
|
||||
['white', 'black'].forEach(color =>
|
||||
$(node).find('.mini-game__clock--' + color).each(function() {
|
||||
$(this).clock('destroy');
|
||||
}).replaceWith(`<span class="mini-game__result">${win ? (win == color[0] ? 1 : 0) : '½'}</span>`)
|
||||
);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
$(function() {
|
||||
if (lichess.analyse) LichessAnalyse.boot(lichess.analyse);
|
||||
else if (lichess.user_analysis) startUserAnalysis(lichess.user_analysis);
|
||||
|
@ -862,43 +772,6 @@
|
|||
};
|
||||
})());
|
||||
|
||||
lichess.widget("clock", {
|
||||
_create: function() {
|
||||
this.target = this.options.time * 1000 + Date.now();
|
||||
if (!this.options.pause) this.interval = setInterval(this.render.bind(this), 1000);
|
||||
this.render();
|
||||
},
|
||||
|
||||
set: function(opts) {
|
||||
this.options = opts;
|
||||
this.target = this.options.time * 1000 + Date.now();
|
||||
this.render();
|
||||
clearInterval(this.interval);
|
||||
if (!opts.pause) this.interval = setInterval(this.render.bind(this), 1000);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (document.body.contains(this.element[0])) {
|
||||
this.element.text(this.formatMs(this.target - Date.now()));
|
||||
this.element.toggleClass('clock--run', !this.options.pause);
|
||||
} else clearInterval(this.interval);
|
||||
},
|
||||
|
||||
pad: function(x) {
|
||||
return (x < 10 ? '0' : '') + x;
|
||||
},
|
||||
|
||||
formatMs: function(msTime) {
|
||||
const date = new Date(Math.max(0, msTime + 500)),
|
||||
hours = date.getUTCHours(),
|
||||
minutes = date.getUTCMinutes(),
|
||||
seconds = date.getUTCSeconds();
|
||||
return hours > 0 ?
|
||||
hours + ':' + this.pad(minutes) + ':' + this.pad(seconds) :
|
||||
minutes + ':' + this.pad(seconds);
|
||||
}
|
||||
});
|
||||
|
||||
$(function() {
|
||||
lichess.pubsub.on('content_loaded', lichess.miniBoard.initAll);
|
||||
lichess.pubsub.on('content_loaded', lichess.miniGame.initAll);
|
||||
|
|
|
@ -1,26 +1,3 @@
|
|||
function parseFen($elem) {
|
||||
$elem.each(function() {
|
||||
var $this = $(this).removeClass('parse-fen');
|
||||
var lm = $this.data('lastmove');
|
||||
var color = $this.data('color');
|
||||
var ground = $this.data('chessground');
|
||||
var config = {
|
||||
coordinates: false,
|
||||
resizable: false,
|
||||
drawable: { enabled: false, visible: false },
|
||||
viewOnly: true,
|
||||
fen: $this.data('fen'),
|
||||
lastMove: lm && [lm[0] + lm[1], lm[2] + lm[3]]
|
||||
};
|
||||
if (color) config.orientation = color;
|
||||
if (ground) ground.set(config);
|
||||
else {
|
||||
this.innerHTML = '<div class="cg-wrap"></div>';
|
||||
$this.data('chessground', Chessground(this.firstChild, config));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function resize() {
|
||||
var el = document.querySelector('#featured-game');
|
||||
if (el.offsetHeight > window.innerHeight)
|
||||
|
@ -29,19 +6,18 @@ function resize() {
|
|||
|
||||
$(function() {
|
||||
var $featured = $('#featured-game');
|
||||
var board = function() {
|
||||
return $featured.find('.mini-board');
|
||||
};
|
||||
parseFen(board());
|
||||
if (!window.EventSource) return;
|
||||
const findGame = () => document.getElementsByClassName('mini-game').item(0);
|
||||
const setup = () => lichess.miniGame.init(findGame());
|
||||
setup();
|
||||
var source = new EventSource($('body').data('stream-url'));
|
||||
source.addEventListener('message', function(e) {
|
||||
var data = JSON.parse(e.data);
|
||||
if (data.t == "featured") {
|
||||
$featured.html(data.d.html).find('a').attr('target', '_blank');
|
||||
parseFen(board());
|
||||
} else if (data.t == "fen") {
|
||||
parseFen(board().data("fen", data.d.fen).data("lastmove", data.d.lm));
|
||||
const msg = JSON.parse(e.data);
|
||||
if (msg.t == "featured") {
|
||||
$featured.html(msg.d.html).find('a').attr('target', '_blank');
|
||||
setup();
|
||||
} else if (msg.t == "fen") {
|
||||
lichess.miniGame.update(findGame(), msg.d);
|
||||
}
|
||||
}, false);
|
||||
resize();
|
||||
|
|
|
@ -235,7 +235,7 @@ lichess.loadCss = url => {
|
|||
lichess.loadCssPath = key =>
|
||||
lichess.loadCss(`css/${key}.${$('body').data('theme')}.${$('body').data('dev') ? 'dev' : 'min'}.css`);
|
||||
|
||||
lichess.jsModule = name =>
|
||||
lichess.jsModule = name =>
|
||||
`compiled/lichess.${name}${$('body').data('dev') ? '' : '.min'}.js`;
|
||||
|
||||
lichess.loadScript = (url, opts) =>
|
||||
|
@ -404,3 +404,130 @@ $.modal.close = function() {
|
|||
$(this).remove();
|
||||
});
|
||||
};
|
||||
|
||||
lichess.miniBoard = {
|
||||
initAll() {
|
||||
Array.from(document.getElementsByClassName('mini-board--init')).forEach(lichess.miniBoard.init);
|
||||
},
|
||||
init(node) {
|
||||
if (!window.Chessground) return setTimeout(() => lichess.miniBoard.init(node), 500);
|
||||
const $el = $(node).removeClass('mini-board--init'),
|
||||
[fen, orientation, lm] = $el.data('state').split(',');
|
||||
$el.data('chessground', Chessground(node, {
|
||||
orientation,
|
||||
coordinates: false,
|
||||
viewOnly: !node.getAttribute('data-playable'),
|
||||
resizable: false,
|
||||
fen,
|
||||
lastMove: lm && (lm[1] === '@' ? [lm.slice(2)] : [lm[0] + lm[1], lm[2] + lm[3]]),
|
||||
drawable: {
|
||||
enabled: false,
|
||||
visible: false
|
||||
}
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
lichess.miniGame = (() => {
|
||||
const fenColor = fen => fen.indexOf(' b') > 0 ? 'black' : 'white';
|
||||
return {
|
||||
init(node, data) {
|
||||
const [fen, orientation, lm] = ((typeof data == 'string' && data) || node.getAttribute('data-state')).split(','),
|
||||
config = {
|
||||
coordinates: false,
|
||||
viewOnly: true,
|
||||
resizable: false,
|
||||
fen,
|
||||
orientation,
|
||||
lastMove: lm && (lm[1] === '@' ? [lm.slice(2)] : [lm[0] + lm[1], lm[2] + lm[3]]),
|
||||
drawable: {
|
||||
enabled: false,
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
$el = $(node).removeClass('mini-game--init'),
|
||||
$cg = $el.find('.cg-wrap'),
|
||||
turnColor = fenColor(fen);
|
||||
$cg.data('chessground', Chessground($cg[0], config));
|
||||
['white', 'black'].forEach(color =>
|
||||
$el.find('.mini-game__clock--' + color).each(function() {
|
||||
$(this).clock({
|
||||
time: parseInt(this.getAttribute('data-time')),
|
||||
pause: color != turnColor
|
||||
});
|
||||
})
|
||||
);
|
||||
return node.getAttribute('data-live');
|
||||
},
|
||||
initAll() {
|
||||
const nodes = Array.from(document.getElementsByClassName('mini-game--init')),
|
||||
ids = nodes.map(lichess.miniGame.init).filter(id => id);
|
||||
if (ids.length) window.lichess.StrongSocket.firstConnect.then(send =>
|
||||
send('startWatching', ids.join(' '))
|
||||
);
|
||||
},
|
||||
update(node, data) {
|
||||
const $el = $(node),
|
||||
lm = data.lm,
|
||||
lastMove = lm && (lm[1] === '@' ? [lm.slice(2)] : [lm[0] + lm[1], lm[2] + lm[3]]),
|
||||
cg = $el.find('.cg-wrap').data('chessground');
|
||||
cg.set({
|
||||
fen: data.fen,
|
||||
lastMove
|
||||
});
|
||||
const turnColor = fenColor(data.fen);
|
||||
const renderClock = (time, color) => {
|
||||
if (!isNaN(time)) $el.find('.mini-game__clock--' + color).clock('set', {
|
||||
time,
|
||||
pause: color != turnColor
|
||||
});
|
||||
};
|
||||
renderClock(data.wc, 'white');
|
||||
renderClock(data.bc, 'black');
|
||||
},
|
||||
finish(node, win) {
|
||||
['white', 'black'].forEach(color =>
|
||||
$(node).find('.mini-game__clock--' + color).each(function() {
|
||||
$(this).clock('destroy');
|
||||
}).replaceWith(`<span class="mini-game__result">${win ? (win == color[0] ? 1 : 0) : '½'}</span>`)
|
||||
);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
lichess.widget("clock", {
|
||||
_create: function() {
|
||||
this.target = this.options.time * 1000 + Date.now();
|
||||
if (!this.options.pause) this.interval = setInterval(this.render.bind(this), 1000);
|
||||
this.render();
|
||||
},
|
||||
|
||||
set: function(opts) {
|
||||
this.options = opts;
|
||||
this.target = this.options.time * 1000 + Date.now();
|
||||
this.render();
|
||||
clearInterval(this.interval);
|
||||
if (!opts.pause) this.interval = setInterval(this.render.bind(this), 1000);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (document.body.contains(this.element[0])) {
|
||||
this.element.text(this.formatMs(this.target - Date.now()));
|
||||
this.element.toggleClass('clock--run', !this.options.pause);
|
||||
} else clearInterval(this.interval);
|
||||
},
|
||||
|
||||
pad: function(x) {
|
||||
return (x < 10 ? '0' : '') + x;
|
||||
},
|
||||
|
||||
formatMs: function(msTime) {
|
||||
const date = new Date(Math.max(0, msTime + 500)),
|
||||
hours = date.getUTCHours(),
|
||||
minutes = date.getUTCMinutes(),
|
||||
seconds = date.getUTCSeconds();
|
||||
return hours > 0 ?
|
||||
hours + ':' + this.pad(minutes) + ':' + this.pad(seconds) :
|
||||
minutes + ':' + this.pad(seconds);
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue