progress on chessground based rounds
This commit is contained in:
parent
b3232bc84f
commit
18e428c1e8
|
@ -56,11 +56,10 @@ object Round extends LilaController with TheftPrevention {
|
|||
html = pov.game.started.fold(
|
||||
PreventTheft(pov) {
|
||||
(pov.game.tournamentId ?? TournamentRepo.byId) zip
|
||||
Env.game.crosstableApi(pov.game) zip
|
||||
(pov.game.playable ?? env.takebacker.isAllowedByPrefs(pov.game)) flatMap {
|
||||
case ((tour, crosstable), takebackable) =>
|
||||
Env.game.crosstableApi(pov.game) flatMap {
|
||||
case (tour, crosstable) =>
|
||||
env.jsonView.playerJson(pov, ctx.pref, Env.api.version, ctx.me) map { data =>
|
||||
Ok(html.round.player(pov, data, tour = tour, cross = crosstable, takebackable = takebackable))
|
||||
Ok(html.round.player(pov, data, tour = tour, cross = crosstable))
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@(pov: Pov, data: play.api.libs.json.JsObject, tour: Option[lila.tournament.Tournament], cross: Option[lila.game.Crosstable], takebackable: Boolean)(implicit ctx: Context)
|
||||
@(pov: Pov, data: play.api.libs.json.JsObject, tour: Option[lila.tournament.Tournament], cross: Option[lila.game.Crosstable])(implicit ctx: Context)
|
||||
|
||||
@import pov._
|
||||
|
||||
|
@ -10,7 +10,8 @@
|
|||
*@
|
||||
@jsAt(s"compiled/lichess.round.js")
|
||||
@helper.javascriptRouter("roundRoutes")(
|
||||
routes.javascript.Auth.signup
|
||||
routes.javascript.Auth.signup,
|
||||
routes.javascript.User.show
|
||||
)(ctx.req)
|
||||
@embedJs {
|
||||
lichess = lichess || {};
|
||||
|
@ -18,7 +19,29 @@ lichess.round = {
|
|||
data: @Html(play.api.libs.json.Json.stringify(data)),
|
||||
routes: roundRoutes.controllers,
|
||||
i18n: @Html(J.stringify(i18nJsObject(
|
||||
trans.premoveEnabledClickAnywhereToCancel)))
|
||||
trans.premoveEnabledClickAnywhereToCancel,
|
||||
trans.aiNameLevelAiLevel,
|
||||
trans.waiting,
|
||||
trans.yourTurn,
|
||||
trans.abortGame,
|
||||
trans.proposeATakeback,
|
||||
trans.offerDraw,
|
||||
trans.resign,
|
||||
trans.theOtherPlayerHasLeftTheGameYouCanForceResignationOrWaitForHim,
|
||||
trans.forceResignation,
|
||||
trans.forceDraw,
|
||||
trans.threefoldRepetition,
|
||||
trans.claimADraw,
|
||||
trans.drawOfferSent,
|
||||
trans.cancel,
|
||||
trans.yourOpponentOffersADraw,
|
||||
trans.accept,
|
||||
trans.decline,
|
||||
trans.takebackPropositionSent,
|
||||
trans.yourOpponentProposesATakeback,
|
||||
trans.youHaveNbSecondsToMakeYourFirstMove,
|
||||
trans.thisPlayerUsesChessComputerAssistance
|
||||
)))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,10 +93,6 @@ object Event {
|
|||
override def owner = true
|
||||
}
|
||||
|
||||
object Reload extends Empty {
|
||||
def typ = "resync"
|
||||
}
|
||||
|
||||
case class Promotion(role: PromotableRole, pos: Pos) extends Event {
|
||||
def typ = "promotion"
|
||||
def data = Json.obj(
|
||||
|
@ -141,8 +137,12 @@ object Event {
|
|||
case object ReloadTables extends Empty {
|
||||
def typ = "reloadTable"
|
||||
}
|
||||
case object ReloadTablesOwner extends Empty {
|
||||
def typ = "reloadTable"
|
||||
|
||||
case object Reload extends Empty {
|
||||
def typ = "reload"
|
||||
}
|
||||
case object ReloadOwner extends Empty {
|
||||
def typ = "reload"
|
||||
override def owner = true
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ private[round] final class Drawer(messenger: Messenger, finisher: Finisher) {
|
|||
case Pov(g, color) if (g playerCanOfferDraw color) => GameRepo save {
|
||||
messenger.system(g, _.drawOfferSent)
|
||||
Progress(g) map { g => g.updatePlayer(color, _ offerDraw g.turns) }
|
||||
} inject List(Event.ReloadTablesOwner)
|
||||
} inject List(Event.ReloadOwner)
|
||||
case _ => fufail("[drawer] invalid yes " + pov)
|
||||
}
|
||||
|
||||
|
@ -26,11 +26,11 @@ private[round] final class Drawer(messenger: Messenger, finisher: Finisher) {
|
|||
case Pov(g, color) if pov.player.isOfferingDraw => GameRepo save {
|
||||
messenger.system(g, _.drawOfferCanceled)
|
||||
Progress(g) map { g => g.updatePlayer(color, _.removeDrawOffer) }
|
||||
} inject List(Event.ReloadTablesOwner)
|
||||
} inject List(Event.ReloadOwner)
|
||||
case Pov(g, color) if pov.opponent.isOfferingDraw => GameRepo save {
|
||||
messenger.system(g, _.drawOfferDeclined)
|
||||
Progress(g) map { g => g.updatePlayer(!color, _.removeDrawOffer) }
|
||||
} inject List(Event.ReloadTablesOwner)
|
||||
} inject List(Event.ReloadOwner)
|
||||
case _ => fufail("[drawer] invalid no " + pov)
|
||||
}
|
||||
|
||||
|
|
|
@ -159,6 +159,7 @@ final class Env(
|
|||
chatApi = chatApi,
|
||||
userJsonView = userJsonView,
|
||||
getVersion = version,
|
||||
canTakeback = takebacker.isAllowedByPrefs,
|
||||
baseAnimationDuration = AnimationDuration)
|
||||
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@ final class JsonView(
|
|||
chatApi: lila.chat.ChatApi,
|
||||
userJsonView: lila.user.JsonView,
|
||||
getVersion: String => Fu[Int],
|
||||
canTakeback: Game => Fu[Boolean],
|
||||
baseAnimationDuration: Duration) {
|
||||
|
||||
def playerJson(
|
||||
|
@ -26,8 +27,9 @@ final class JsonView(
|
|||
playerUser: Option[User]): Fu[JsObject] =
|
||||
getVersion(pov.game.id) zip
|
||||
(pov.opponent.userId ?? UserRepo.byId) zip
|
||||
canTakeback(pov.game) zip
|
||||
getChat(pov.game, playerUser) map {
|
||||
case ((version, opponentUser), chat) =>
|
||||
case (((version, opponentUser), takebackable), chat) =>
|
||||
import pov._
|
||||
Json.obj(
|
||||
"game" -> Json.obj(
|
||||
|
@ -66,7 +68,8 @@ final class JsonView(
|
|||
"isProposingTakeback" -> opponent.isProposingTakeback.option(true)
|
||||
).noNull,
|
||||
"url" -> Json.obj(
|
||||
"socket" -> s"/$fullId/socket/v$apiVersion"
|
||||
"socket" -> s"/$fullId/socket/v$apiVersion",
|
||||
"round" -> s"/$fullId"
|
||||
),
|
||||
"pref" -> Json.obj(
|
||||
"animationDuration" -> animationDuration(pov, pref),
|
||||
|
@ -90,7 +93,8 @@ final class JsonView(
|
|||
},
|
||||
"possibleMoves" -> possibleMoves(pov),
|
||||
"tournamentId" -> game.tournamentId,
|
||||
"poolId" -> game.poolId)
|
||||
"poolId" -> game.poolId,
|
||||
"takebackable" -> takebackable)
|
||||
}
|
||||
|
||||
def watcherJson(pov: Pov, version: Int, tv: Boolean, pref: Pref) = {
|
||||
|
|
|
@ -31,11 +31,11 @@ private[round] final class Rematcher(
|
|||
case Pov(game, color) if pov.player.isOfferingRematch => GameRepo save {
|
||||
messenger.system(game, _.rematchOfferCanceled)
|
||||
Progress(game) map { g => g.updatePlayer(color, _.removeRematchOffer) }
|
||||
} inject List(Event.ReloadTablesOwner)
|
||||
} inject List(Event.ReloadOwner)
|
||||
case Pov(game, color) if pov.opponent.isOfferingRematch => GameRepo save {
|
||||
messenger.system(game, _.rematchOfferDeclined)
|
||||
Progress(game) map { g => g.updatePlayer(!color, _.removeRematchOffer) }
|
||||
} inject List(Event.ReloadTablesOwner)
|
||||
} inject List(Event.ReloadOwner)
|
||||
case _ => ClientErrorException.future("[rematcher] invalid no " + pov)
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ private[round] final class Rematcher(
|
|||
private def rematchCreate(pov: Pov): Fu[Events] = GameRepo save {
|
||||
messenger.system(pov.game, _.rematchOfferSent)
|
||||
Progress(pov.game) map { g => g.updatePlayer(pov.color, _ offerRematch) }
|
||||
} inject List(Event.ReloadTablesOwner)
|
||||
} inject List(Event.ReloadOwner)
|
||||
|
||||
private def returnGame(pov: Pov): Fu[Game] = for {
|
||||
pieces ← pov.game.variant.standard.fold(
|
||||
|
|
|
@ -15,7 +15,7 @@ private[round] final class Takebacker(
|
|||
case Pov(game, color) if (game playerCanProposeTakeback color) => GameRepo save {
|
||||
messenger.system(game, _.takebackPropositionSent)
|
||||
Progress(game) map { g => g.updatePlayer(color, _.proposeTakeback) }
|
||||
} inject List(Event.ReloadTablesOwner)
|
||||
} inject List(Event.ReloadOwner)
|
||||
case _ => ClientErrorException.future("[takebacker] invalid yes " + pov)
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +25,11 @@ private[round] final class Takebacker(
|
|||
case Pov(game, color) if pov.player.isProposingTakeback => GameRepo save {
|
||||
messenger.system(game, _.takebackPropositionCanceled)
|
||||
Progress(game) map { g => g.updatePlayer(color, _.removeTakebackProposition) }
|
||||
} inject List(Event.ReloadTablesOwner)
|
||||
} inject List(Event.ReloadOwner)
|
||||
case Pov(game, color) if pov.opponent.isProposingTakeback => GameRepo save {
|
||||
messenger.system(game, _.takebackPropositionDeclined)
|
||||
Progress(game) map { g => g.updatePlayer(!color, _.removeTakebackProposition) }
|
||||
} inject List(Event.ReloadTablesOwner)
|
||||
} inject List(Event.ReloadOwner)
|
||||
case _ => ClientErrorException.future("[takebacker] invalid no " + pov)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -709,14 +709,13 @@ div.lichess_control .lichess_rematch.disabled {
|
|||
}
|
||||
#claim_draw_zone,
|
||||
div.force_resign_zone,
|
||||
div.proposed_takeback,
|
||||
div.offered_draw {
|
||||
div.negociation {
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
#claim_draw_zone .button,
|
||||
div.offered_draw .button,
|
||||
div.negociation .button,
|
||||
div.force_resign_zone .button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
@ -742,7 +741,9 @@ div.lichess_current_player div.lichess_player {
|
|||
position: absolute;
|
||||
margin-left: -5px;
|
||||
}
|
||||
div.lichess_current_player div.lichess_player div.piece {
|
||||
div.lichess_current_player div.lichess_player div.cg-piece {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
|
|
@ -126,8 +126,7 @@ body.dark #hooks_list .pool_buttons > a,
|
|||
body.dark #hooks_list .pool_title,
|
||||
body.dark div.training div.box,
|
||||
body.dark div.force_resign_zone,
|
||||
body.dark div.proposed_takeback,
|
||||
body.dark div.offered_draw {
|
||||
body.dark div.negotiation {
|
||||
border-color: #3d3d3d;
|
||||
}
|
||||
body.dark #crosstable td.last {
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
"watchify": "^1.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"chessground": "git://github.com/ornicar/chessground.git",
|
||||
"chessground": "^1.4.0",
|
||||
"lodash-node": "^2.4.1",
|
||||
"mithril": "^0.1.22"
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module.exports = function(data) {
|
||||
module.exports = function(data, onFlag) {
|
||||
|
||||
var lastUpdate;
|
||||
|
||||
|
@ -22,7 +22,8 @@ module.exports = function(data) {
|
|||
|
||||
this.tick = function(color) {
|
||||
m.startComputation();
|
||||
this.data[color] = lastUpdate[color] - (new Date() - lastUpdate.at) / 1000;
|
||||
this.data[color] = Math.max(0, lastUpdate[color] - (new Date() - lastUpdate.at) / 1000);
|
||||
if (this.data[color] === 0) onFlag();
|
||||
m.endComputation();
|
||||
}.bind(this);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
var m = require('mithril');
|
||||
var partial = require('lodash-node/modern/functions/partial');
|
||||
var throttle = require('lodash-node/modern/functions/throttle');
|
||||
var chessground = require('chessground');
|
||||
var data = require('./data');
|
||||
var round = require('./round');
|
||||
var ground = require('./ground');
|
||||
var socket = require('./socket');
|
||||
var clockCtrl = require('./clock/ctrl');
|
||||
var util = require('./util');
|
||||
|
||||
module.exports = function(cfg, router, i18n, socketSend) {
|
||||
|
||||
|
@ -24,36 +25,17 @@ module.exports = function(cfg, router, i18n, socketSend) {
|
|||
});
|
||||
}.bind(this);
|
||||
|
||||
this.chessground = new chessground.controller({
|
||||
fen: cfg.game.fen,
|
||||
orientation: this.data.player.color,
|
||||
turnColor: this.data.game.player,
|
||||
lastMove: util.str2move(this.data.game.lastMove),
|
||||
highlight: {
|
||||
lastMove: this.data.pref.highlight,
|
||||
check: this.data.pref.highlight,
|
||||
dragOver: true
|
||||
},
|
||||
movable: {
|
||||
free: false,
|
||||
color: round.isPlayerPlaying(this.data) ? this.data.player.color : null,
|
||||
dests: round.parsePossibleMoves(this.data.possibleMoves),
|
||||
showDests: this.data.pref.destination,
|
||||
events: {
|
||||
after: this.userMove
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
enabled: true,
|
||||
duration: this.data.pref.animationDuration
|
||||
},
|
||||
premovable: {
|
||||
enabled: this.data.pref.enablePremove,
|
||||
showDests: this.data.pref.destination
|
||||
}
|
||||
});
|
||||
this.chessground = ground.make(this.data, cfg.game.fen, this.userMove);
|
||||
|
||||
this.clock = this.data.clock ? new clockCtrl(this.data.clock) : false;
|
||||
this.reload = function(cfg) {
|
||||
this.data = data(cfg);
|
||||
ground.reload(this.chessground, this.data, cfg.game.fen);
|
||||
}.bind(this);
|
||||
|
||||
this.clock = this.data.clock ? new clockCtrl(
|
||||
this.data.clock,
|
||||
throttle(partial(this.socket.send, 'outoftime'), 500)
|
||||
) : false;
|
||||
|
||||
this.isClockRunning = function() {
|
||||
return !this.data.game.finished && ((this.data.game.turns - this.data.game.startedAtTurn) > 1 || this.data.game.clockRunning);
|
||||
|
|
53
ui/round/src/ground.js
Normal file
53
ui/round/src/ground.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
var chessground = require('chessground');
|
||||
var round = require('./round');
|
||||
var util = require('./util');
|
||||
|
||||
function makeConfig(data, fen) {
|
||||
return {
|
||||
fen: fen,
|
||||
orientation: data.player.color,
|
||||
turnColor: data.game.player,
|
||||
lastMove: util.str2move(data.game.lastMove),
|
||||
highlight: {
|
||||
lastMove: data.pref.highlight,
|
||||
check: data.pref.highlight,
|
||||
dragOver: true
|
||||
},
|
||||
movable: {
|
||||
free: false,
|
||||
color: round.isPlayerPlaying(data) ? data.player.color : null,
|
||||
dests: round.parsePossibleMoves(data.possibleMoves),
|
||||
showDests: data.pref.destination
|
||||
},
|
||||
animation: {
|
||||
enabled: true,
|
||||
duration: data.pref.animationDuration
|
||||
},
|
||||
premovable: {
|
||||
enabled: data.pref.enablePremove,
|
||||
showDests: data.pref.destination
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function make(data, fen, userMove) {
|
||||
var config = makeConfig(data, fen);
|
||||
config.movable.events = {
|
||||
after: userMove
|
||||
};
|
||||
return new chessground.controller(config);
|
||||
}
|
||||
|
||||
function reload(ground, data, fen) {
|
||||
ground.set(makeConfig(data, fen));
|
||||
}
|
||||
|
||||
function end(ground) {
|
||||
ground.stop();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
make: make,
|
||||
reload: reload,
|
||||
end: end
|
||||
};
|
|
@ -14,8 +14,42 @@ function parsePossibleMoves(possibleMoves) {
|
|||
});
|
||||
}
|
||||
|
||||
function playable(data) {
|
||||
return data.game.started && !data.game.finished;
|
||||
}
|
||||
|
||||
function mandatory(data) {
|
||||
return data.tournamentId || data.poolId;
|
||||
}
|
||||
|
||||
function abortable(data) {
|
||||
return playable(data) && data.game.turns < 2 && !mandatory(data);
|
||||
}
|
||||
|
||||
function takebackable(data) {
|
||||
return playable(data) && data.takebackable && !data.tournamentId && data.game.turns > 1 && !data.player.isProposingTakeback && !data.opponent.isProposingTakeback;
|
||||
}
|
||||
|
||||
function drawable(data) {
|
||||
return playable(data) && data.game.turns >= 2 && !data.player.isOfferingDraw && !data.opponent.ai;
|
||||
}
|
||||
|
||||
function resignable(data) {
|
||||
return playable(data) && !abortable(data);
|
||||
}
|
||||
|
||||
function getPlayer(data, color) {
|
||||
return data.player.color == color ? data.player : data.opponent;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isGamePlaying: isGamePlaying,
|
||||
isPlayerPlaying: isPlayerPlaying,
|
||||
playable: playable,
|
||||
abortable: abortable,
|
||||
takebackable: takebackable,
|
||||
drawable: drawable,
|
||||
resignable: resignable,
|
||||
getPlayer: getPlayer,
|
||||
parsePossibleMoves: parsePossibleMoves
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
var m = require('mithril');
|
||||
var round = require('./round');
|
||||
var ground = require('chessground');
|
||||
var ground = require('./ground');
|
||||
var xhr = require('./xhr');
|
||||
|
||||
module.exports = function(send, ctrl) {
|
||||
|
||||
|
@ -8,14 +9,14 @@ module.exports = function(send, ctrl) {
|
|||
|
||||
var handlers = {
|
||||
possibleMoves: function(o) {
|
||||
ctrl.chessground.reconfigure({
|
||||
ctrl.chessground.set({
|
||||
movable: {
|
||||
dests: round.parsePossibleMoves(o)
|
||||
}
|
||||
});
|
||||
},
|
||||
state: function(o) {
|
||||
ctrl.chessground.reconfigure({
|
||||
ctrl.chessground.set({
|
||||
turnColor: o.color
|
||||
});
|
||||
ctrl.data.game.player = o.color;
|
||||
|
@ -42,7 +43,7 @@ module.exports = function(send, ctrl) {
|
|||
ctrl.chessground.setPieces(pieces);
|
||||
},
|
||||
check: function(o) {
|
||||
ctrl.chessground.reconfigure({
|
||||
ctrl.chessground.set({
|
||||
check: o
|
||||
});
|
||||
},
|
||||
|
@ -58,11 +59,30 @@ module.exports = function(send, ctrl) {
|
|||
$.redirect(o);
|
||||
}, 400);
|
||||
},
|
||||
reload: function(o) {
|
||||
xhr.reload(ctrl.data).then(ctrl.reload);
|
||||
},
|
||||
threefoldRepetition: function() {
|
||||
// ???
|
||||
},
|
||||
clock: function(o) {
|
||||
if (ctrl.clock) ctrl.clock.update(o.white, o.black);
|
||||
},
|
||||
crowd: function(o) {
|
||||
m.startComputation();
|
||||
['white', 'black'].forEach(function(c) {
|
||||
round.getPlayer(ctrl.data, c).statused = true;
|
||||
round.getPlayer(ctrl.data, c).connected = o[c];
|
||||
});
|
||||
ctrl.data.watchers = o.watchers;
|
||||
m.endComputation();
|
||||
},
|
||||
end: function() {
|
||||
m.startComputation();
|
||||
ctrl.data.game.finished = true;
|
||||
m.endComputation();
|
||||
ground.end(ctrl.chessground);
|
||||
xhr.reload(ctrl.data).then(ctrl.reload);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,14 +1,112 @@
|
|||
var map = require('lodash-node/modern/collections/map');
|
||||
var chessground = require('chessground');
|
||||
var round = require('./round');
|
||||
var opposite = chessground.util.opposite;
|
||||
var classSet = chessground.util.classSet;
|
||||
var partial = chessground.util.partial;
|
||||
var clockView = require('./clock/view');
|
||||
var m = require('mithril');
|
||||
|
||||
function renderOpponent(ctrl) {
|
||||
var op = ctrl.data.opponent;
|
||||
return op.ai ? m('div.username.connected.statused',
|
||||
ctrl.trans('aiNameLevelAiLevel', 'Stockfish', op.ai)
|
||||
) : m('div', {
|
||||
class: 'username ' + op.color + ' ' + classSet({
|
||||
'statused': op.statused,
|
||||
'connected': op.connected,
|
||||
'offline': !op.connected
|
||||
})
|
||||
},
|
||||
op.user ? [
|
||||
m('a', {
|
||||
class: 'user_link ulpt',
|
||||
href: ctrl.router.User.show(op.user.username).url,
|
||||
target: round.playable(ctrl.data) ? '_blank' : null,
|
||||
'data-icon': 'r',
|
||||
}, [
|
||||
(op.user.title ? op.user.title + ' ' : '') + op.user.username,
|
||||
op.engine ? m('span[data-icon=j]', {
|
||||
title: ctrl.trans('thisPlayerUsesChessComputerAssistance')
|
||||
}) : null
|
||||
]),
|
||||
m('span.status')
|
||||
] : m('span.user_link', [
|
||||
'Anonymous',
|
||||
m('span.status')
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
function renderTableEnd(ctrl) {}
|
||||
|
||||
function renderButton(ctrl, condition, icon, hint, socketMsg) {
|
||||
return condition(ctrl.data) ? m('button', {
|
||||
class: 'button hint--bottom',
|
||||
'data-hint': ctrl.trans(hint),
|
||||
onclick: partial(ctrl.socket.send, socketMsg, null)
|
||||
}, m('span[data-icon=' + icon + ']')) : null;
|
||||
}
|
||||
|
||||
function renderTablePlay(ctrl) {
|
||||
var d = ctrl.data;
|
||||
return [
|
||||
m('div.lichess_current_player',
|
||||
m('div.lichess_player', [
|
||||
m('div.cg-piece.king.' + d.game.player),
|
||||
m('p', ctrl.trans(d.game.player == d.player.color ? 'yourTurn' : 'waiting'))
|
||||
])
|
||||
),
|
||||
m('div.lichess_control.icons', [
|
||||
renderButton(ctrl, round.abortable, 'L', 'abortGame', 'abort'),
|
||||
renderButton(ctrl, round.takebackable, 'i', 'proposeATakeback', 'takeback-yes'),
|
||||
renderButton(ctrl, round.drawable, '2', 'offerDraw', 'draw-yes'),
|
||||
renderButton(ctrl, round.resignable, 'b', 'resign', 'resign')
|
||||
]),
|
||||
d.player.isOfferingDraw ? m('div.negociation', [
|
||||
ctrl.trans('drawOfferSent') + ' ',
|
||||
m('a', {
|
||||
onclick: partial(ctrl.socket.send, 'draw-no', null)
|
||||
}, ctrl.trans('cancel'))
|
||||
]) : null,
|
||||
d.opponent.isOfferingDraw ? m('div.negociation', [
|
||||
ctrl.trans('yourOpponentOffersADraw'),
|
||||
m('br'),
|
||||
m('a.button[data-icon=E]', {
|
||||
onclick: partial(ctrl.socket.send, 'draw-yes', null)
|
||||
}, ctrl.trans('accept')),
|
||||
m.trust(' '),
|
||||
m('a.button[data-icon=L]', {
|
||||
onclick: partial(ctrl.socket.send, 'draw-no', null)
|
||||
}, ctrl.trans('decline')),
|
||||
]) : null,
|
||||
d.player.isProposingTakeback ? m('div.negociation', [
|
||||
ctrl.trans('takebackPropositionSent') + ' ',
|
||||
m('a', {
|
||||
onclick: partial(ctrl.socket.send, 'takeback-no', null)
|
||||
}, ctrl.trans('cancel'))
|
||||
]) : null,
|
||||
d.opponent.isProposingTakeback ? m('div.negociation', [
|
||||
ctrl.trans('yourOpponentProposesATakeback'),
|
||||
m('br'),
|
||||
m('a.button[data-icon=E]', {
|
||||
onclick: partial(ctrl.socket.send, 'takeback-yes', null)
|
||||
}, ctrl.trans('accept')),
|
||||
m.trust(' '),
|
||||
m('a.button[data-icon=L]', {
|
||||
onclick: partial(ctrl.socket.send, 'takeback-no', null)
|
||||
}, ctrl.trans('decline')),
|
||||
]) : null,
|
||||
];
|
||||
}
|
||||
|
||||
module.exports = function(ctrl) {
|
||||
var clockRunningColor = ctrl.isClockRunning() ? ctrl.data.game.player : null;
|
||||
return m('div', {
|
||||
config: function(el, isUpdate, context) {
|
||||
if (isUpdate) return;
|
||||
$('body').trigger('lichess.content_loaded');
|
||||
},
|
||||
class: 'lichess_game clearfix not_spectator pov_' + ctrl.data.player.color
|
||||
}, [
|
||||
ctrl.data.blindMode ? m('div#lichess_board_blind') : null,
|
||||
|
@ -24,7 +122,13 @@ module.exports = function(ctrl) {
|
|||
'table_with_clock': ctrl.clock,
|
||||
'finished': ctrl.data.game.finished
|
||||
})
|
||||
}), (ctrl.clock && !ctrl.data.blindMode) ? clockView(ctrl.clock, ctrl.data.player.color, "bottom", clockRunningColor) : null,
|
||||
}, [
|
||||
m('div.lichess_opponent', renderOpponent(ctrl)),
|
||||
m('div.lichess_separator'),
|
||||
m('div.table_inner',
|
||||
round.playable(ctrl.data) ? renderTablePlay(ctrl) : renderTableEnd(ctrl)
|
||||
)
|
||||
]), (ctrl.clock && !ctrl.data.blindMode) ? clockView(ctrl.clock, ctrl.data.player.color, "bottom", clockRunningColor) : null,
|
||||
])
|
||||
)
|
||||
]);
|
||||
|
|
18
ui/round/src/xhr.js
Normal file
18
ui/round/src/xhr.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
var m = require('mithril');
|
||||
|
||||
var xhrConfig = function(xhr) {
|
||||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||
xhr.setRequestHeader('Accept', 'application/vnd.lichess.v1+json');
|
||||
}
|
||||
|
||||
function reload(data) {
|
||||
return m.request({
|
||||
method: 'GET',
|
||||
url: data.url.round,
|
||||
config: xhrConfig
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
reload: reload
|
||||
};
|
Loading…
Reference in a new issue