Merge branch 'master' into clarkeyUI
* master: select mate or material puzzles randomly - includes DB migration fix puzzle replay check puzzle hotfixes fix en passant in fast replay pl "polski" translation #10174. Author: kris9191. bind esc to chessground.cancelMove in round, analysis, and puzzle Revert "Remove JS link on Challenge Notif" Revert "Restyle messages drop-down." Conflicts: public/stylesheets/common.css
This commit is contained in:
commit
19faf9e8d9
|
@ -203,32 +203,6 @@ trait UserHelper { self: I18nHelper with StringHelper =>
|
|||
Html(s"""<a$dataIcon $klass $href>$space$titleS$content</a>""")
|
||||
}
|
||||
|
||||
def userSpan(
|
||||
user: User,
|
||||
cssClass: Option[String] = None,
|
||||
withOnline: Boolean = true,
|
||||
withPowerTip: Boolean = true,
|
||||
withTitle: Boolean = true,
|
||||
withBestRating: Boolean = false,
|
||||
withPerfRating: Option[PerfType] = None,
|
||||
text: Option[String] = None) = Html {
|
||||
val klass = userClass(user.id, cssClass, withOnline, withPowerTip)
|
||||
val content = text | user.username
|
||||
val titleS = if (withTitle) titleTag(user.title) else ""
|
||||
val space = if (withOnline) " " else ""
|
||||
val dataIcon = if (withOnline) """ data-icon="r"""" else ""
|
||||
val rating = withPerfRating map (_.key) flatMap user.perfs.ratingOf map { rating =>
|
||||
s" ($rating)"
|
||||
} getOrElse {
|
||||
withBestRating ?? {
|
||||
user.perfs.bestPerf ?? {
|
||||
case (pt, perf) => s" ${showPerfRating(pt, perf, "hint--bottom")}"
|
||||
}
|
||||
}
|
||||
}
|
||||
s"""<span$dataIcon $klass>$space$titleS$content$rating</span>"""
|
||||
}
|
||||
|
||||
private def userHref(username: String, params: String = "") =
|
||||
s"""href="${routes.User.show(username)}$params""""
|
||||
|
||||
|
|
|
@ -180,16 +180,10 @@ openGraph: Map[Symbol, String] = Map.empty)(body: Html)(implicit ctx: Context)
|
|||
<div class="ping">PING <strong>?</strong> ms</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="message_notifications_parent" class="message_notifications">
|
||||
<a id="message_notifications_tag" class="toggle toggle_message_notifications" data-href="@routes.Message.preview">
|
||||
<span data-icon="e"></span>
|
||||
<span id="nb_messages" class="new_messages@if(ctx.nbMessages > 0) { unread}">@ctx.nbMessages</span>
|
||||
</a>
|
||||
<div id="message_notifications" class="links dropdown">
|
||||
<div class="title">New messages (<a href="@routes.Message.inbox(page=1)">view all</a>)</div>
|
||||
<div id="message_notifications_display" class="content"> </div>
|
||||
</div>
|
||||
</div>
|
||||
<a data-href="@routes.Message.preview" class="goto_nav message blank_if_play @{(active exists (_.code == "message")).??("current")}" href="@routes.Message.inbox(page=1)">
|
||||
<span class="is2" data-icon="e"></span>
|
||||
<span id="nb_messages" class="new_messages@if(ctx.nbMessages > 0) { unread}">@ctx.nbMessages</span>
|
||||
</a>
|
||||
<div class="challenge_notifications">
|
||||
<a id="challenge_notifications_tag" class="toggle toggle_challenge_notifications">
|
||||
<span data-icon="U"></span>
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
@(me: User, threads: List[lila.message.Thread])(implicit ctx: Context)
|
||||
|
||||
@if(threads.nonEmpty) {
|
||||
<table><tbody>
|
||||
@threads.distinct.map { thread =>
|
||||
<div class="notification message_reminder">
|
||||
<div class="actions">
|
||||
<a class="action decline mark_as_read" href="@routes.Message.markAsRead(thread.id)" data-icon="L"></a>
|
||||
</div>
|
||||
<a href="@routes.Message.thread(thread.id)">
|
||||
<span class="inner">
|
||||
<span class="message_infos" data-icon="c">
|
||||
<span class="header">
|
||||
<strong>@usernameOrId(thread otherUserId me)</strong> • @thread.name
|
||||
<span class="content">
|
||||
@thread.firstPostUnreadBy(me).map(p => shorten(p.text, 100))
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<tr>
|
||||
<td>
|
||||
<a data-icon="c" class="revert-underline" href="@routes.Message.thread(thread.id)">
|
||||
@thread.name
|
||||
<strong>@usernameOrId(thread otherUserId me)</strong>
|
||||
@thread.firstPostUnreadBy(me).map(p => shorten(p.text, 100))
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a class="button mark_as_read hint--bottom" data-hint="Mark as read" href="@routes.Message.markAsRead(thread.id)">
|
||||
<span data-icon="E"></span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody></table>
|
||||
} else {
|
||||
@trans.noNewMessages()
|
||||
}
|
||||
|
|
|
@ -1,28 +1,26 @@
|
|||
@(g: Game, user: User)
|
||||
|
||||
<div id="challenge_reminder_@g.id" data-href="@routes.Round.watcher(g.id, "white")" class="notification challenge_reminder">
|
||||
<div class="actions">
|
||||
<a class="action decline" href="@routes.Setup.decline(g.id)" data-icon="L"></a>
|
||||
<div class="inner">
|
||||
<div class="actions">
|
||||
<a class="action decline" href="@routes.Setup.decline(g.id)" data-icon="L"></a>
|
||||
</div>
|
||||
<div class="game_infos" data-icon="@g.perfType match {
|
||||
case _ if g.fromPosition => {*}
|
||||
case Some(p) => {@p.iconChar}
|
||||
case _ => {8}
|
||||
}">
|
||||
<div class="header">
|
||||
@userLink(user, withOnline = false, withPerfRating = g.perfType, cssClass = "disabled".some)<br />
|
||||
<span class="setup">
|
||||
@g.clock.map(_.show).getOrElse {∞} •
|
||||
@if(g.variant.exotic) {
|
||||
@(if (g.variant == chess.Variant.KingOfTheHill) g.variant.shortName else g.variant.name)
|
||||
} else {
|
||||
@g.perfType.map(_.name)
|
||||
} • @g.rated.fold(trans.rated.en(), trans.casual.en())
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="@routes.Round.watcher(g.id, "white")">
|
||||
<span class="inner">
|
||||
<span class="game_infos" data-icon="@g.perfType match {
|
||||
case _ if g.fromPosition => {*}
|
||||
case Some(p) => {@p.iconChar}
|
||||
case _ => {8}
|
||||
}">
|
||||
<span class="header">
|
||||
@userSpan(user, withOnline = false, withPerfRating = g.perfType, withPowerTip = false)
|
||||
<span class="setup">
|
||||
@g.clock.map(_.show).getOrElse {∞} •
|
||||
@if(g.variant.exotic) {
|
||||
@(if (g.variant == chess.Variant.KingOfTheHill) g.variant.shortName else g.variant.name)
|
||||
} else {
|
||||
@g.perfType.map(_.name)
|
||||
} • @g.rated.fold(trans.rated.en(), trans.casual.en())
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
|
12
bin/mongodb/puzzle-mate.js
Normal file
12
bin/mongodb/puzzle-mate.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
db.puzzle.find({tags: {$exists:true}}).forEach(function(o) {
|
||||
db.puzzle.update({
|
||||
_id: o._id
|
||||
}, {
|
||||
$set: {
|
||||
mate: o.tags.indexOf("forced mate") !== -1
|
||||
},
|
||||
$unset: {
|
||||
tags: true
|
||||
}
|
||||
});
|
||||
});
|
|
@ -42,20 +42,20 @@ whiteLeftTheGame=Białe opuszczają grę
|
|||
blackLeftTheGame=Czarne opuszczają grę
|
||||
shareThisUrlToLetSpectatorsSeeTheGame=Podziel się tym adresem, aby zaprosić widzów do obserwowania tej gry
|
||||
youAreViewingThisGameAsASpectator=Obserwujesz tę grę jako widz
|
||||
replayAndAnalyse=Oglądaj i analizuj
|
||||
replayAndAnalyse=Odtwórz i analizuj
|
||||
computerAnalysisInProgress=Analiza komputerowa w toku
|
||||
theComputerAnalysisHasFailed=Analiza komputerowa nie powiodła się
|
||||
viewTheComputerAnalysis=Zobacz analizę komputerową
|
||||
requestAComputerAnalysis=Poproś o analizę komputerową
|
||||
computerAnalysis=Analiza komputerowa
|
||||
blunders=Gafy
|
||||
mistakes=Błędy
|
||||
blunders=Bład
|
||||
mistakes=Pomyłka
|
||||
inaccuracies=Niedokładności
|
||||
moveTimes=Czas przeznaczony na ruch
|
||||
flipBoard=Obróć szachownicę
|
||||
threefoldRepetition=Trzykrotne powtórzenie ruchów
|
||||
claimADraw=Wymuś remis
|
||||
offerDraw=Zaproponuj remis
|
||||
claimADraw=Zażądaj remisu
|
||||
offerDraw=Proponuj remis
|
||||
draw=Remis
|
||||
nbConnectedPlayers=%s graczy online
|
||||
gamesBeingPlayedRightNow=Aktualnie rozgrywane partie
|
||||
|
@ -85,7 +85,7 @@ username=Nazwa użytkownika
|
|||
password=Hasło
|
||||
haveAnAccount=Masz już konto?
|
||||
allYouNeedIsAUsernameAndAPassword=Wszystko czego potrzebujesz to nazwa użytkownika i hasło.
|
||||
changePassword=Zmiana hasła
|
||||
changePassword=Zmień hasło
|
||||
learnMoreAboutLichess=Dowiedz się więcej o Lichess
|
||||
rank=Miejsce
|
||||
gamesPlayed=Rozegranych partii
|
||||
|
@ -93,10 +93,10 @@ nbGamesWithYou=%s gier z tobą
|
|||
declineInvitation=Odrzuć zaproszenie
|
||||
cancel=Anuluj
|
||||
timeOut=Czas upłynął
|
||||
drawOfferSent=Propozycja remisu wysłana
|
||||
drawOfferDeclined=Propozycja remisu odrzucona
|
||||
drawOfferAccepted=Propozycja remisu przyjęta
|
||||
drawOfferCanceled=Propozycja remisu anulowana
|
||||
drawOfferSent=Oferta remisu wysłana
|
||||
drawOfferDeclined=Oferta remisu odrzucona
|
||||
drawOfferAccepted=Oferta remisu przyjęta
|
||||
drawOfferCanceled=Oferta remisu anulowana
|
||||
yourOpponentOffersADraw=Twój przeciwnik proponuje remis
|
||||
accept=Zaakceptuj
|
||||
decline=Odrzuć
|
||||
|
@ -111,11 +111,11 @@ casual=Nierankingowa
|
|||
rated=Rankingowa
|
||||
thisGameIsRated=Ta gra jest rankingowa
|
||||
rematch=Rewanż
|
||||
rematchOfferSent=Wysłano propozycję rewanżu
|
||||
rematchOfferAccepted=Propozycja rewanżu przyjęta
|
||||
rematchOfferCanceled=Propozycja reważnu anulowana
|
||||
rematchOfferDeclined=Odrzucono propozycję rewanżu
|
||||
cancelRematchOffer=Odrzuć propozycję rewanżu
|
||||
rematchOfferSent=Wysłano ofertę rewanżu
|
||||
rematchOfferAccepted=Oferta rewanżu przyjęta
|
||||
rematchOfferCanceled=Oferta reważnu anulowana
|
||||
rematchOfferDeclined=Odrzucono ofertę rewanżu
|
||||
cancelRematchOffer=Odrzuć ofertę rewanżu
|
||||
viewRematch=Pokaż rewanż
|
||||
play=Zagraj
|
||||
inbox=Skrzynka odbiorcza
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e21b6d6c806673a99d300cf16122b9f5edfa56b4
|
||||
Subproject commit be800c14554d0cce621e496dd452751c83966a38
|
|
@ -8,7 +8,6 @@ import org.joda.time.DateTime
|
|||
import play.api.libs.json._
|
||||
|
||||
case class Generated(
|
||||
tags: List[String],
|
||||
position: String,
|
||||
solution: JsObject,
|
||||
id: String) {
|
||||
|
@ -20,7 +19,6 @@ case class Generated(
|
|||
fen ← Generated fenOf history
|
||||
} yield Puzzle.make(
|
||||
gameId = id.some,
|
||||
tags = tags,
|
||||
history = position.trim.split(' ').toList,
|
||||
fen = fen,
|
||||
lines = lines)
|
||||
|
|
|
@ -9,7 +9,6 @@ import lila.rating.Perf
|
|||
case class Puzzle(
|
||||
id: PuzzleId,
|
||||
gameId: Option[String],
|
||||
tags: List[String],
|
||||
history: List[String],
|
||||
fen: String,
|
||||
lines: List[Line],
|
||||
|
@ -39,13 +38,11 @@ object Puzzle {
|
|||
|
||||
def make(
|
||||
gameId: Option[String],
|
||||
tags: List[String],
|
||||
history: List[String],
|
||||
fen: String,
|
||||
lines: Lines)(id: PuzzleId) = new Puzzle(
|
||||
id = id,
|
||||
gameId = gameId,
|
||||
tags = tags,
|
||||
history = history,
|
||||
fen = fen,
|
||||
lines = lines,
|
||||
|
@ -86,7 +83,6 @@ object Puzzle {
|
|||
object BSONFields {
|
||||
val id = "_id"
|
||||
val gameId = "gameId"
|
||||
val tags = "tags"
|
||||
val history = "history"
|
||||
val fen = "fen"
|
||||
val lines = "lines"
|
||||
|
@ -111,7 +107,6 @@ object Puzzle {
|
|||
def reads(r: BSON.Reader): Puzzle = Puzzle(
|
||||
id = r int id,
|
||||
gameId = r strO gameId,
|
||||
tags = r.get[List[String]](tags),
|
||||
history = r str history split ' ' toList,
|
||||
fen = r str fen,
|
||||
lines = r.get[Lines](lines),
|
||||
|
@ -127,7 +122,6 @@ object Puzzle {
|
|||
def writes(w: BSON.Writer, o: Puzzle) = BSONDocument(
|
||||
id -> o.id,
|
||||
gameId -> o.gameId,
|
||||
tags -> o.tags,
|
||||
history -> o.history.mkString(" "),
|
||||
fen -> o.fen,
|
||||
lines -> o.lines,
|
||||
|
|
|
@ -19,12 +19,11 @@ private[puzzle] final class Selector(
|
|||
modulo: Int) {
|
||||
|
||||
private val popularSelector = BSONDocument(
|
||||
Puzzle.BSONFields.voteSum -> BSONDocument("$gt" -> BSONInteger(anonMinRating))
|
||||
)
|
||||
Puzzle.BSONFields.voteSum -> BSONDocument("$gt" -> BSONInteger(anonMinRating)))
|
||||
|
||||
private val popularCount = lila.memo.AsyncCache.single[Int](
|
||||
f = puzzleColl.db command Count(puzzleColl.name, popularSelector.some),
|
||||
timeToLive = 1 day)
|
||||
private def mateSelector(mate: Boolean) = BSONDocument("mate" -> mate)
|
||||
|
||||
private lazy val popularCount = puzzleColl.db command Count(puzzleColl.name, popularSelector.some)
|
||||
|
||||
private def difficultyDecay(difficulty: Int) = difficulty match {
|
||||
case 1 => -200
|
||||
|
@ -32,19 +31,22 @@ private[puzzle] final class Selector(
|
|||
case _ => 0
|
||||
}
|
||||
|
||||
def apply(me: Option[User], difficulty: Int): Fu[Puzzle] = me match {
|
||||
case None => popularCount(true) map (_ - 1) flatMap { skipMax =>
|
||||
puzzleColl.find(popularSelector)
|
||||
.options(QueryOpts(skipN = Random nextInt skipMax))
|
||||
.one[Puzzle] flatten "Can't find a puzzle for anon player!"
|
||||
}
|
||||
case Some(user) => api.attempt.playedIds(user, modulo) flatMap { ids =>
|
||||
tryRange(user, toleranceStep, difficultyDecay(difficulty), ids)
|
||||
def apply(me: Option[User], difficulty: Int): Fu[Puzzle] = {
|
||||
val isMate = scala.util.Random.nextBoolean
|
||||
me match {
|
||||
case None => popularCount map (_ - 1) flatMap { skipMax =>
|
||||
puzzleColl.find(popularSelector ++ mateSelector(isMate))
|
||||
.options(QueryOpts(skipN = Random nextInt skipMax))
|
||||
.one[Puzzle] flatten "Can't find a puzzle for anon player!"
|
||||
}
|
||||
case Some(user) => api.attempt.playedIds(user, modulo) flatMap { ids =>
|
||||
tryRange(user, toleranceStep, difficultyDecay(difficulty), ids, isMate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def tryRange(user: User, tolerance: Int, decay: Int, ids: BSONArray): Fu[Puzzle] =
|
||||
puzzleColl.find(BSONDocument(
|
||||
private def tryRange(user: User, tolerance: Int, decay: Int, ids: BSONArray, isMate: Boolean): Fu[Puzzle] =
|
||||
puzzleColl.find(mateSelector(isMate) ++ BSONDocument(
|
||||
Puzzle.BSONFields.id -> BSONDocument("$nin" -> ids),
|
||||
Puzzle.BSONFields.rating -> BSONDocument(
|
||||
"$gt" -> BSONInteger(user.perfs.puzzle.intRating - tolerance + decay),
|
||||
|
@ -54,7 +56,7 @@ private[puzzle] final class Selector(
|
|||
.one[Puzzle] flatMap {
|
||||
case Some(puzzle) => fuccess(puzzle)
|
||||
case None => if ((tolerance + toleranceStep) <= toleranceMax)
|
||||
tryRange(user, tolerance + toleranceStep, decay, ids)
|
||||
tryRange(user, tolerance + toleranceStep, decay, ids, isMate)
|
||||
else fufail(s"Can't find a puzzle for user $user!")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,6 +175,10 @@ var storage = {
|
|||
nbChallengesAdd();
|
||||
$('#challenge_notifications').append(data.html);
|
||||
$notif = $('#' + htmlId);
|
||||
$notif.add($notif.find("a.disabled")).on('click', function() {
|
||||
location.href = $notif.data('href');
|
||||
return false;
|
||||
});
|
||||
declineListener($notif.find('a.decline'));
|
||||
$('body').trigger('lichess.content_loaded');
|
||||
if (!storage.get('challenge-' + data.id)) {
|
||||
|
@ -319,22 +323,26 @@ var storage = {
|
|||
setTimeout(userPowertips, 600);
|
||||
$('body').on('lichess.content_loaded', userPowertips);
|
||||
|
||||
$('#message_notifications_tag').on('click', function() {
|
||||
$.ajax({
|
||||
url: $(this).data('href'),
|
||||
success: function(html) {
|
||||
console.log(html);
|
||||
$('#message_notifications_display').html(html).addClass('messages').find('a.mark_as_read').click(function() {
|
||||
$.ajax({
|
||||
url: $(this).attr('href'),
|
||||
method: 'post'
|
||||
$('#top a.message').powerTip({
|
||||
placement: 'sw',
|
||||
mouseOnToPopup: true,
|
||||
closeDelay: 200
|
||||
}).on({
|
||||
powerTipPreRender: function() {
|
||||
$.ajax({
|
||||
url: $(this).data('href'),
|
||||
success: function(html) {
|
||||
$('#powerTip').html(html).addClass('messages').find('a.mark_as_read').click(function() {
|
||||
$.ajax({
|
||||
url: $(this).attr('href'),
|
||||
method: 'post'
|
||||
});
|
||||
return false;
|
||||
});
|
||||
$('#message_notifications_parent').toggleClass("shown", false);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}).data('powertip', ' ');
|
||||
|
||||
function setMoment() {
|
||||
$("time.moment").removeClass('moment').each(function() {
|
||||
|
|
4
public/javascripts/vendor/chessground.min.js
vendored
4
public/javascripts/vendor/chessground.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -804,7 +804,6 @@ div.side_box .top {
|
|||
div.side_box .padded {
|
||||
padding: 7px;
|
||||
}
|
||||
.notification .message_infos,
|
||||
.notification .game_infos,
|
||||
div.side_box .game_infos {
|
||||
padding-left: 36px;
|
||||
|
@ -819,7 +818,6 @@ div.side_box .game_infos {
|
|||
padding-bottom: 8px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.notification .message_infos::before,
|
||||
.notification .game_infos::before,
|
||||
div.side_box .game_infos::before {
|
||||
position: absolute;
|
||||
|
@ -965,18 +963,15 @@ body.offline #nb_connected_players {
|
|||
#user_tag {
|
||||
font-weight: bold;
|
||||
}
|
||||
#top div.message_notifications,
|
||||
#top div.challenge_notifications,
|
||||
#top div.auth {
|
||||
float: right;
|
||||
position: relative;
|
||||
}
|
||||
#top div.message_notifications.shown .links,
|
||||
#top div.challenge_notifications.shown .links,
|
||||
#top div.auth.shown .links {
|
||||
display: block;
|
||||
}
|
||||
#top div.message_notificatiosn .links > a,
|
||||
#top div.challenge_notifications .links > a,
|
||||
#top div.auth .links > a {
|
||||
display: block;
|
||||
|
@ -1008,40 +1003,22 @@ body.offline #nb_connected_players {
|
|||
display: block;
|
||||
padding: 5px 10px 10px 10px;
|
||||
}
|
||||
#top #message_notifications_tag span:before,
|
||||
#top #challenge_notifications_tag span:before {
|
||||
font-size: 1.45em;
|
||||
padding-left: 3px;
|
||||
}
|
||||
#top div.message_notifications div.title {
|
||||
padding: 5px 3% 5px 3%;
|
||||
text-align: center;
|
||||
width: 200px;
|
||||
}
|
||||
#top div.message_notifications div.title a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
#top #challenge_notifications div.title {
|
||||
padding: 5px 3% 5px 3%;
|
||||
text-align: center;
|
||||
}
|
||||
#message_notifications div.notification,
|
||||
#challenge_notifications div.notification {
|
||||
cursor: pointer;
|
||||
border-top: 1px solid #c0c0c0;
|
||||
padding: 6px 8px 7px 8px;
|
||||
position: relative;
|
||||
}
|
||||
#message_notifications div.notification:hover,
|
||||
#challenge_notifications div.notification:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
#message_notifications span.inner,
|
||||
#challenge_notifications span.inner {
|
||||
display: block;
|
||||
width: calc(100% - 15px);
|
||||
height: 100%;
|
||||
padding: 6px 8px 7px 8px;
|
||||
}
|
||||
#message_notifications,
|
||||
#challenge_notifications,
|
||||
#notifications {
|
||||
position: absolute;
|
||||
|
@ -1067,51 +1044,37 @@ body.offline #nb_connected_players {
|
|||
line-height: inherit;
|
||||
height: auto;
|
||||
}
|
||||
#challenge_notifications > div a.close,
|
||||
#notifications > div a.close {
|
||||
text-decoration: none;
|
||||
float: right;
|
||||
}
|
||||
#challenge_notifications > div a.close:hover,
|
||||
#notifications > div a.close:hover {
|
||||
font-weight: bold;
|
||||
}
|
||||
#challenge_notifications .user_link {
|
||||
font-weight: bold;
|
||||
}
|
||||
#message_notifications_display .content,
|
||||
#challenge_notifications .setup {
|
||||
display: block;
|
||||
}
|
||||
#challenge_notifications .setup {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
#message_notifications .actions,
|
||||
#challenge_notifications .actions,
|
||||
#notifications .actions {
|
||||
position: relative;
|
||||
float: right;
|
||||
z-index: 4;
|
||||
text-decoration: none;
|
||||
}
|
||||
#message_notifications .actions,
|
||||
#challenge_notifications .actions {
|
||||
z-index: 1;
|
||||
}
|
||||
#message_notifications a,
|
||||
#challenge_notifications a {
|
||||
text-decoration: none;
|
||||
}
|
||||
#challenge_notifications a,
|
||||
#notifications a {
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
#message_notifications .actions a,
|
||||
#challenge_notifications .actions a {
|
||||
font-weight: bold;
|
||||
margin-right: 5px;
|
||||
}
|
||||
#challenge_notifications .actions a,
|
||||
#notifications .actions a {
|
||||
margin-left: 10px;
|
||||
}
|
||||
#message_notifications .actions a:hover,
|
||||
#challenge_notifications .actions a:hover,
|
||||
#notifications .actions a:hover {
|
||||
color: #d85000;
|
||||
|
|
|
@ -125,8 +125,7 @@ body.dark div.training div.box,
|
|||
body.dark div.force_resign_zone,
|
||||
body.dark div.negotiation,
|
||||
body.dark div.side_box div.game_infos,
|
||||
body.dark #challenge_notifications div.notification,
|
||||
body.dark #message_notifications div.notification {
|
||||
body.dark #challenge_notifications > div.notification {
|
||||
border-color: #3d3d3d;
|
||||
}
|
||||
body.dark .crosstable td.last {
|
||||
|
@ -145,8 +144,7 @@ body.dark #hooks_wrap > div.tabs > a,
|
|||
body.dark #top div.auth .links a:hover,
|
||||
body.dark #top ul.language_links a:hover,
|
||||
body.dark #top ul.language_links a.current,
|
||||
body.dark #challenge_notifications > div.notification:hover,
|
||||
body.dark #message_notifications div.notification:hover {
|
||||
body.dark #challenge_notifications > div.notification:hover {
|
||||
background-color: #3e3e3e;
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
opacity: 0.5;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
div.cg-board {
|
||||
#puzzle div.cg-board {
|
||||
width: 512px;
|
||||
height: 512px;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
"watchify": "^1.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"chessground": "1.7.20",
|
||||
"chessground": "1.7.24",
|
||||
"chessli.js": "file:../chessli",
|
||||
"game": "file:../game",
|
||||
"lodash-node": "^2.4.1",
|
||||
|
|
|
@ -113,6 +113,6 @@ module.exports = function(cfg, router, i18n, onChange) {
|
|||
return str;
|
||||
};
|
||||
|
||||
keyboard(this);
|
||||
showGround();
|
||||
keyboard(this);
|
||||
};
|
||||
|
|
|
@ -39,4 +39,5 @@ module.exports = function(ctrl) {
|
|||
}
|
||||
m.redraw();
|
||||
}));
|
||||
k.bind(['esc'], ctrl.chessground.cancelMove);
|
||||
};
|
||||
|
|
|
@ -30,10 +30,11 @@
|
|||
"watchify": "^1.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"chessground": "1.7.20",
|
||||
"chessground": "1.7.24",
|
||||
"chessli.js": "file:../chessli",
|
||||
"lodash-node": "^2.4.1",
|
||||
"merge": "^1.2.0",
|
||||
"mithril": "0.1.24"
|
||||
"mithril": "0.1.24",
|
||||
"mousetrap": "0.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
var m = require('mithril');
|
||||
var k = require('mousetrap');
|
||||
var partial = require('lodash-node/modern/functions/partial');
|
||||
var merge = require('merge');
|
||||
var last = require('lodash-node/modern/arrays/last');
|
||||
|
@ -88,6 +89,8 @@ module.exports = function(cfg, router, i18n) {
|
|||
}
|
||||
}, this.data.chessground));
|
||||
|
||||
k.bind(['esc'], this.chessground.cancelMove);
|
||||
|
||||
this.initiate = function() {
|
||||
if (this.data.mode != 'view')
|
||||
setTimeout(partial(this.playInitialMove, this.data.puzzle.id), 1000);
|
||||
|
|
|
@ -13,6 +13,8 @@ module.exports = function(cfg) {
|
|||
chess: chess.make(cfg.puzzle.fen)
|
||||
};
|
||||
|
||||
if (cfg.user) cfg.user.history = cfg.user.history || [];
|
||||
|
||||
merge(data, cfg);
|
||||
|
||||
data.puzzle.initialMove = puzzle.str2move(data.puzzle.initialMove);
|
||||
|
|
|
@ -79,7 +79,12 @@ function makeHistory(data) {
|
|||
var c = chess.make(data.puzzle.fen);
|
||||
return [data.puzzle.initialMove].concat(line.map(str2move)).map(function(m) {
|
||||
chess.move(c, m);
|
||||
return {move: m, fen: c.fen(), check: c.in_check()};
|
||||
return {
|
||||
move: m,
|
||||
fen: c.fen(),
|
||||
check: c.in_check(),
|
||||
turnColor: c.turn() == 'w' ? 'white' : 'black'
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -89,9 +94,9 @@ function jump(chessgroundData, data, to) {
|
|||
chessground.configure(chessgroundData, {
|
||||
fen: state.fen,
|
||||
lastMove: state.move,
|
||||
check: null
|
||||
check: state.check,
|
||||
turnColor: state.turnColor
|
||||
});
|
||||
if (state.check) chessground.board.setCheck(chessgroundData);
|
||||
}
|
||||
|
||||
function reload(chessgroundData, data, cfg) {
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
"watchify": "^1.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"chessground": "1.7.20",
|
||||
"chessground": "1.7.24",
|
||||
"chessli.js": "file:../chessli",
|
||||
"game": "file:../game",
|
||||
"lodash-node": "^2.4.1",
|
||||
|
|
|
@ -3,6 +3,7 @@ var blur = require('./blur');
|
|||
var game = require('game').game;
|
||||
var status = require('game').status;
|
||||
var keyboard = require('./replay/keyboard');
|
||||
var k = require('mousetrap');
|
||||
|
||||
module.exports = function(ctrl) {
|
||||
|
||||
|
@ -15,14 +16,17 @@ module.exports = function(ctrl) {
|
|||
|
||||
if (game.isPlayerPlaying(d) && game.nbMoves(d, d.player.color) === 0) $.sound.dong();
|
||||
|
||||
if (game.isPlayerPlaying(d)) window.addEventListener('beforeunload', function(e) {
|
||||
if (!lichess.hasToReload && !ctrl.data.blind && game.playable(ctrl.data) && ctrl.data.clock) {
|
||||
ctrl.socket.send('bye');
|
||||
var msg = 'There is a game in progress!';
|
||||
(e || window.event).returnValue = msg;
|
||||
return msg;
|
||||
}
|
||||
});
|
||||
if (game.isPlayerPlaying(d)) {
|
||||
window.addEventListener('beforeunload', function(e) {
|
||||
if (!lichess.hasToReload && !ctrl.data.blind && game.playable(ctrl.data) && ctrl.data.clock) {
|
||||
ctrl.socket.send('bye');
|
||||
var msg = 'There is a game in progress!';
|
||||
(e || window.event).returnValue = msg;
|
||||
return msg;
|
||||
}
|
||||
});
|
||||
k.bind(['esc'], ctrl.chessground.cancelMove);
|
||||
}
|
||||
|
||||
keyboard.init(ctrl);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue