Merge branch 'master' into bugfix/board-editor-mobile

# Conflicts:
#	ui/editor/src/view.js
pull/2799/head
Brandon Evans 2017-03-17 08:02:06 -05:00
commit f6531a2de9
29 changed files with 529 additions and 472 deletions

View File

@ -69,7 +69,7 @@ trait AssetHelper { self: I18nHelper =>
"""<script src="//code.highcharts.com/4.1.4/highcharts-more.js"></script>"""
}
def momentLangTag(async: Boolean = false)(implicit ctx: lila.api.Context) = {
def momentLangUrl(implicit ctx: lila.api.Context): Option[String] = {
val l = lang(ctx)
((l.language, l.country.toLowerCase) match {
case ("en", "us") => none
@ -80,9 +80,7 @@ trait AssetHelper { self: I18nHelper =>
case ("ar", "ma" | "sa" | "tn") => l.code.some
case ("fr", "ca") => l.code.some
case _ => l.language.some
}).fold(Html("")) { locale =>
jsAt(s"vendor/moment/locale/${locale.toLowerCase}.js", static = true, async = async)
}
}).map { locale => s"/assets/vendor/moment/locale/${locale.toLowerCase}.js" }
}
val tagmanagerTag = cdnOrLocal(

View File

@ -76,7 +76,7 @@ asyncJs: Boolean = false)(body: Html)(implicit ctx: Context)
data-asset-url="@assetBaseUrl"
data-asset-version="@ctx.pageData.assetVersion"
data-accept-languages="@acceptLanguages.mkString(",")"
data-zoom="@ctx.zoomOrDefault">
@ctx.zoom.map { zoom => data-zoom="@zoom" }>
<form id="blind_mode" action="@routes.Main.toggleBlindMode" method="POST">
<input type="hidden" name="enable" value="@ctx.blindMode.fold(0,1)" />
<input type="hidden" name="redirect" value="@ctx.req.path" />
@ -85,22 +85,18 @@ asyncJs: Boolean = false)(body: Html)(implicit ctx: Context)
<div id="site_description">@trans.freeOnlineChessGamePlayChessNowInACleanInterfaceNoRegistrationNoAdsNoPluginRequiredPlayChessWithComputerFriendsOrRandomOpponents()</div>
<div id="top" class="@ctx.is3d.fold("is3d", "is2d")">
@topmenu()
<div id="ham-plate" class="fright link" data-hint="@trans.menu()" class="hint--bottom">
<div id="ham-plate" class="link" data-hint="@trans.menu()" class="hint--bottom">
<div id="hamburger" data-icon="["></div>
</div>
<div class="lichess_language fright">
<div class="lichess_language">
<a class="toggle link" href="#">@langName(lang)</a>
<form action="@routes.I18n.select" method="POST" class="language_links dropdown" data-url="@staticUrl("trans/refs.json")?v=@ctx.pageData.assetVersion">
<ul>
<li><a href="@routes.I18n.contribute">Help translate Lichess!</a></li>
</ul>
</form>
<form action="@routes.I18n.select" method="POST" class="language_links dropdown"></form>
</div>
@ctx.me.map { me =>
<div class="auth fright">
<div class="auth">
@auth.userDropdown(me, playing)
</div>
<div class="challenge_notifications fright">
<div class="challenge_notifications">
<a id="challenge_notifications_tag" class="toggle link data-count" data-count="@ctx.nbChallenges">
<span class="hint--bottom-left" data-hint="Challenges">
<span data-icon="U"></span>
@ -110,7 +106,7 @@ asyncJs: Boolean = false)(body: Html)(implicit ctx: Context)
<div class="initiating">@base.spinner()</div>
</div>
</div>
<div class="site_notifications fright">
<div class="site_notifications">
<a id="site_notifications_tag" class="toggle link data-count" data-count="@ctx.nbNotifications">
<span class="hint--bottom-left" data-hint="Notifications">
<span data-icon=""></span>
@ -121,10 +117,10 @@ asyncJs: Boolean = false)(body: Html)(implicit ctx: Context)
</div>
</div>
}.getOrElse {
<a href="@routes.Auth.login" class="signin button fright text">@trans.signIn()</a>
<a href="@routes.Auth.login" class="signin button text">@trans.signIn()</a>
}
@if(!zen) {
<div id="sound_control" class="fright">
<div id="sound_control">
<a id="sound_state" class="toggle link hint--bottom-left" data-hint="@trans.sound()">
<span class="is2 on" data-icon="#"></span>
<span class="is2 off" data-icon="$"></span>
@ -142,22 +138,22 @@ asyncJs: Boolean = false)(body: Html)(implicit ctx: Context)
</div>
</div>
@if(ctx.teamNbRequests > 0) {
<a class="fright link data-count" href="@routes.Team.requests()" data-count="@ctx.teamNbRequests">
<a class="link data-count" href="@routes.Team.requests()" data-count="@ctx.teamNbRequests">
<span class="hint--bottom-left" data-hint="@trans.teams()">
<span data-icon="f"></span>
</span>
</a>
}
<div id="themepicker" class="fright">
<div id="themepicker">
<a id="themepicker_toggle" class="toggle icon link hint--bottom-left" data-hint="@trans.theming()" data-url="@routes.Main.themepicker">
&nbsp;<span data-icon="@closingBrace"></span>&nbsp;
<span data-icon="@closingBrace"></span>
</a>
</div>
@if(isGranted(_.SeeReport)) {
<a class="fright link text data-count" href="@routes.Report.list" data-count="@reportNbUnprocessed" data-icon="@icon.mod"></a>
<a class="link text data-count" href="@routes.Report.list" data-count="@reportNbUnprocessed" data-icon="@icon.mod"></a>
}
}
<a id="reconnecting" class="fright link" onclick="window.location.reload()" data-icon="B">&nbsp;@trans.reconnecting()</a>
<a id="reconnecting" class="link" onclick="window.location.reload()" data-icon="B">&nbsp;@trans.reconnecting()</a>
</div>
<div class="content @ctx.is3d.fold("is3d", "is2d")">
<div id="site_header">
@ -201,12 +197,16 @@ asyncJs: Boolean = false)(body: Html)(implicit ctx: Context)
@if(chessground) {@jsTag("vendor/chessground.min.js")}
@if(ctx.requiresFingerprint) { @fingerprintTag }
@jsAt(s"compiled/lichess.site${isProd??".min"}.js", async = asyncJs)
@if(!asyncJs) {
@momentLangTag(false)
}
@if(withGtm) { @embedJs { dataLayer = []; } }
@moreJs
@if(lang.language != "en") { @embedJs { lichess_translations = @jsI18n() } }
@if(lang.language != "en") {
@embedJs {
lichess_translations = @jsI18n();
@momentLangUrl.map { url =>
moment_locale_url = "@url";
}
}
}
@if(withGtm) {@gtm()}
</body>
</html>

View File

@ -0,0 +1,28 @@
@(u: User, info: lila.app.mashup.UserInfo)(implicit ctx: Context)
@defining(info.allTrophies.filter(_.kind.klass.has("fire_trophy"))) { fireTrophies =>
@if(fireTrophies.nonEmpty) {
<div class="stacked">
@fireTrophies.sorted.map { trophy =>
@trophy.kind.icon.map { iconChar =>
<a @trophy.kind.url.map { url => href="@url" }
class="trophy award @trophy.kind.key @trophy.kind.klass hint--left"
data-hint="@trophy.kind.name">@Html(iconChar)</a>
}
}
</div>
}
}
@defining(info.allTrophies.filter(_.kind.klass.has("icon3d"))) { iconTrophies =>
@iconTrophies.sorted.map { trophy =>
@trophy.kind.icon.map { iconChar =>
<a @trophy.kind.url.map { url => href="@url" }
class="trophy award @trophy.kind.key @trophy.kind.klass hint--left"
data-hint="@trophy.kind.name">@Html(iconChar)</a>
}
}
}
@if(info.isCoach) {
<a href="@routes.Coach.show(u.username)"
class="trophy award icon3d coach hint--left" data-hint="Lichess coach">:</a>
}

View File

@ -3,7 +3,7 @@
@import lila.rating.PerfType
@if(!u.lame) {
@rankMap.map {
@rankMap.toList.sortBy(_._2).map {
case (perf, rank) if rank == 1 => {
<span class="trophy perf hint--left" data-hint="@PerfType.name(perf) Champion!">
<img src="@staticUrl("images/trophy/Big-Gold-Cup.png")" height=80 />
@ -27,4 +27,3 @@ case (perf, rank) if rank <= 100 => {
case _ => {}
}
}

View File

@ -25,31 +25,6 @@ url = s"$netBaseUrl${routes.User.show(u.username).url}",
description = describeUser(u)).some) {
<div data-username="@u.username" class="content_box no_padding user_show @filters.current.name@if(ctx.is(u)){ myself}">
<div class="content_box_top">
@if(u.plan.active) {
<a href="@routes.Plan.index" class="trophy award patron icon3d hint--left" data-hint="Patron since @showDate(u.plan.sinceDate)">
<span data-icon="@patronIconChar"></span>
</a>
}
@if(info.isCoach) {
<a href="@routes.Coach.show(u.username)" class="trophy award icon3d coach hint--left" data-hint="Lichess coach">
<span data-icon=":"></span>
</a>
}
@info.allTrophies.map { trophy =>
<a @trophy.kind.url.map { url =>
href="@url"
} class="trophy award @trophy.kind.key @trophy.kind.klass hint--left" data-hint="@trophy.kind.name">
@trophy.kind match {
case lila.user.Trophy.Kind.ZugMiracle => {
<img src="@staticUrl("images/trophy/zug-trophy.png")" height=80 />
}
case _ => {
<span data-icon="@trophy.kind.icon.map(Html.apply)"></span>
}
}
</a>
}
@perfTrophies(u, info.ranks)
<h1 class="lichess_title user_link @if(isOnline(u.id)){online}else{offline}">
@if(u.isPatron) {
<a href="@routes.Plan.index">@Html(patronIcon)</a>@u.titleUsername
@ -57,6 +32,13 @@ description = describeUser(u)).some) {
@Html(lineIcon)@u.titleUsername
}
</h1>
<div class="trophies@if(info.allTrophies.size > 6){ packed}">
@perfTrophies(u, info.ranks)
@otherTrophies(u, info)
</div>
@if(u.plan.active) {
<a href="@routes.Plan.index" class="trophy award patron icon3d hint--left" data-hint="Patron since @showDate(u.plan.sinceDate)">@patronIconChar</a>
}
@if(u.disabled) {
<span class="staff">CLOSED</span>
}

View File

@ -5,6 +5,13 @@ dir=$(mktemp -d)
echo "Building in $dir"
cd "$dir"
git clone https://github.com/ReactiveMongo/ReactiveMongo
cd ReactiveMongo
git checkout 0.12.1
export ITERATEES_VERSION=2.4.6
sbt publish-local
cd ..
git clone https://github.com/ornicar/Kamon --branch lila
cd Kamon
sbt publish-local

View File

@ -1,6 +1,6 @@
var user = 'thibault';
// var kind = 'moderator';
var kind = 'wayOfBerserk';
var kind = 'marathonSurvivor';
db.trophy.insert({
_id: kind + '/' + user,

View File

@ -72,8 +72,6 @@ sealed trait Context extends lila.user.UserContextWrapper {
def zoom: Option[Int] = req.session get "zoom" flatMap parseIntOption filter (100<)
def zoomOrDefault = zoom | 100
private def ctxPref(name: String): Option[String] =
req.session get name orElse { pref get name }

View File

@ -215,7 +215,7 @@ blocked=Blockiert
unblock=Nicht mehr blockieren
followsYou=Folgt dir
xStartedFollowingY=%s folgt nun %s
nbFollowers=%s Anhänger
nbFollowers=%s Follower
nbFollowing=%s folgend
more=Mehr
memberSince=Mitglied seit

View File

@ -3,11 +3,18 @@ package lila.user
import org.joda.time.DateTime
case class Trophy(
_id: String, // random
user: String,
kind: Trophy.Kind,
date: DateTime
)
_id: String, // random
user: String,
kind: Trophy.Kind,
date: DateTime
) extends Ordered[Trophy] {
def timestamp = date.getMillis
def compare(other: Trophy) =
if (kind.order == other.kind.order) timestamp compare other.timestamp
else kind.order compare other.kind.order
}
object Trophy {
@ -16,7 +23,8 @@ object Trophy {
val name: String,
val icon: Option[String],
val url: Option[String],
val klass: Option[String]
val klass: Option[String],
val order: Int
)
object Kind {
@ -26,7 +34,8 @@ object Trophy {
name = "Zug miracle",
icon = none,
url = "//lichess.org/qa/259/how-do-you-get-a-zug-miracle-trophy".some,
none
klass = none,
order = 1
)
object WayOfBerserk extends Kind(
@ -34,7 +43,8 @@ object Trophy {
name = "The way of Berserk",
icon = "`".some,
url = "//lichess.org/qa/340/way-of-berserk-trophy".some,
"fire_trophy".some
klass = "fire_trophy".some,
order = 2
)
object MarathonWinner extends Kind(
@ -42,7 +52,8 @@ object Trophy {
name = "Marathon Winner",
icon = "\\".some,
url = none,
"fire_trophy".some
klass = "fire_trophy".some,
order = 3
)
object MarathonTopTen extends Kind(
@ -50,7 +61,8 @@ object Trophy {
name = "Marathon Top 10",
icon = "\\".some,
url = none,
"fire_trophy".some
klass = "fire_trophy".some,
order = 4
)
object MarathonTopFifty extends Kind(
@ -58,7 +70,8 @@ object Trophy {
name = "Marathon Top 50",
icon = "\\".some,
url = none,
"fire_trophy".some
klass = "fire_trophy".some,
order = 5
)
object MarathonTopHundred extends Kind(
@ -66,7 +79,8 @@ object Trophy {
name = "Marathon Top 100",
icon = "\\".some,
url = none,
"fire_trophy".some
klass = "fire_trophy".some,
order = 6
)
object MarathonSurvivor extends Kind(
@ -74,7 +88,8 @@ object Trophy {
name = "Marathon #1 survivor",
icon = ",".some,
url = "//lichess.org/blog/VXF45yYAAPQgLH4d/chess-marathon-1".some,
"fire_trophy".some
klass = "fire_trophy".some,
order = 7
)
object BongcloudWarrior extends Kind(
@ -82,7 +97,8 @@ object Trophy {
name = "Bongcloud Warrior",
icon = "~".some,
url = "//lichess.org/forum/lichess-feedback/bongcloud-trophy".some,
"fire_trophy".some
klass = "fire_trophy".some,
order = 8
)
object Developer extends Kind(
@ -90,7 +106,8 @@ object Trophy {
name = "Lichess developer",
icon = "&#xe000;".some,
url = "https://github.com/ornicar/lila/graphs/contributors".some,
"icon3d".some
klass = "icon3d".some,
order = 100
)
object Moderator extends Kind(
@ -98,7 +115,8 @@ object Trophy {
name = "Lichess moderator",
icon = "&#xe002;".some,
url = "//lichess.org/report".some,
"icon3d".some
"icon3d".some,
order = 101
)
object Streamer extends Kind(
@ -106,7 +124,8 @@ object Trophy {
name = "Lichess streamer",
icon = "&#xe003;".some,
url = "//lichess.org/help/stream-on-lichess".some,
"icon3d".some
"icon3d".some,
order = 102
)
val all = List(

View File

@ -41,7 +41,7 @@ object Dependencies {
val scaffeine = "com.github.blemale" %% "scaffeine" % "2.0.0" % "compile"
object reactivemongo {
val version = "0.12.0"
val version = "0.12.1"
val driver = "org.reactivemongo" %% "reactivemongo" % version
val iteratees = "org.reactivemongo" %% "reactivemongo-iteratees" % version
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -113,6 +113,7 @@ piece.ghost {
}
piece.fading {
z-index: 2!important;
opacity: 0.5;
}
.cg-board-wrap .over {
will-change: transform;

View File

@ -8,7 +8,7 @@
}
#challenge_app .challenge {
padding: 10px 10px;
margin-top: 5px;
margin-bottom: 5px;
position: relative;
height: 36px;
transition: 0.13s;

View File

@ -421,6 +421,25 @@ body > div.content {
width: 1005px;
margin: 35px auto 30px auto;
}
.data-count::after,
.unread {
padding: 1px 5px 1px 4px;
font-weight: bold;
border-radius: 2px;
font-size: 0.9em;
}
.data-count::after {
content: attr(data-count);
top: 0;
right: 0;
position: absolute;
height: 11px;
padding: 1px 4px 1px 3px;
line-height: 10px;
}
.data-count[data-count='0']::after {
display: none;
}
#top {
position: relative;
height: 24px;
@ -428,10 +447,112 @@ body > div.content {
margin: 0 auto;
padding-top: 5px;
box-sizing: border-box;
display: flex;
flex-flow: row-reverse;
}
#top:hover {
z-index: 5001;
}
#top .link {
font-size: 13px;
height: 24px;
line-height: 24px;
padding: 0 8px;
}
#top > * {
position: relative;
}
#top .dropdown {
display: none;
position: absolute;
right: 0;
top: 28px;
background: #fff;
z-index: 3;
box-shadow: 2px 5px 6px rgba(0, 0, 0, 0.3);
}
#top .shown .dropdown {
display: block;
}
#top .shown a.toggle {
background: #fff;
height: 28px;
}
#top .links > a {
display: block;
padding: 5px 10px;
transition: 0.13s;
white-space: nowrap;
}
#top .auth .links a:hover {
background: #F0F0F0;
color: #444;
}
#top .signin {
margin: 3px 0.5em 0 0;
border-color: #d85000;
padding: 1px 5px;
}
#top .auth .sep {
display: block;
padding-top: 5px;
margin-top: 5px;
border-top: 1px solid #d4d4d4;
}
#top .status {
position: relative;
padding: 0 0 5px !important;
min-width: 133px;
}
#top .status .led {
position: absolute;
right: 10px;
top: 6px;
font-size: 20px;
opacity: 0.8;
width: 20px;
height: 20px;
border-radius: 50%;
box-shadow: inset 0 2px 2px 0 rgba(0, 0, 0, 0.4);
}
#top .status .ping,
#top .status .server {
display: block;
font-family: 'Roboto Mono', 'Roboto';
padding-left: 10px;
}
#top .status strong {
padding: 0 5px;
}
#top a.toggle {
display: block;
transition: color 0.13s;
}
#top .toggle:hover {
color: #303030;
}
@keyframes pulse-once {
0% { background: #d85000; }
100% { background: none; }
}
#top a.toggle.pulse {
animation: pulse-once 1.5s linear;
}
#top #themepicker_toggle span {
font-size: 17px;
}
#top #themepicker_toggle span:before {
vertical-align: -5px;
}
#reconnecting {
display: none;
}
body.offline #reconnecting,
#network_error {
display: inline-block;
color: #dc322f;
}
#site_description {
position: absolute;
top: -100px;
@ -719,50 +840,6 @@ div.side form.search input {
#site_header div.side_menu .sep {
margin: 10px;
}
#top .link {
font-size: 13px;
height: 24px;
line-height: 24px;
padding: 0 8px;
}
#reconnecting {
display: none;
}
body.offline #reconnecting,
#network_error {
display: inline-block;
color: #dc322f;
}
#top .fright {
float: right;
position: relative;
}
.data-count::after,
.unread {
padding: 1px 5px 1px 4px;
font-weight: bold;
border-radius: 2px;
font-size: 0.9em;
}
.data-count::after {
content: attr(data-count);
top: 0;
right: 0;
position: absolute;
height: 11px;
padding: 1px 4px 1px 3px;
line-height: 10px;
}
.data-count[data-count='0']::after {
display: none;
}
#top .shown a.toggle {
background: #fff;
}
#top .shown #challenge_notifications_tag.toggle,
#top .shown #site_notifications_tag.toggle {
height: 29px;
}
#ham-plate {
cursor: pointer;
@ -817,65 +894,6 @@ body.offline #reconnecting,
#user_tag {
font-weight: bold;
}
#top div.challenge_notifications,
#top div.auth,
#top #themepicker,
#top div.lichess_language {
position: relative;
}
#top div.challenge_notifications.shown .links,
#top div.site_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;
padding: 5px 10px;
transition: 0.13s;
white-space: nowrap;
}
#top div.auth .links a:hover {
background: #F0F0F0;
color: #444;
}
#top a.signin {
margin: 3px 0.5em 0 0;
border-color: #d85000;
padding: 1px 5px;
}
#top div.auth .sep {
display: block;
padding-top: 5px;
margin-top: 5px;
border-top: 1px solid #d4d4d4;
}
#top .status {
position: relative;
padding: 0 0 5px !important;
min-width: 133px;
}
#top .status .led {
position: absolute;
right: 10px;
top: 6px;
font-size: 20px;
opacity: 0.8;
width: 20px;
height: 20px;
border-radius: 50%;
box-shadow: inset 0 2px 2px 0 rgba(0, 0, 0, 0.4);
}
#top .status .ping,
#top .status .server {
display: block;
font-family: 'Roboto Mono', 'Roboto';
padding-left: 10px;
}
#top .status strong {
padding: 0 5px;
}
#challenge_notifications_tag.none {
display: none!important;
}
@ -917,44 +935,6 @@ form.wide textarea {
padding: 0.5em;
border: 1px solid #D4D4D4;
}
#top a.toggle {
display: block;
float: left;
}
#top a.toggle,
#top #sound_state {
transition: color 0.13s;
}
#top a.toggle:hover,
#sound_state:hover {
color: #303030;
}
@keyframes pulse-once {
0% { background: #d85000; }
100% { background: none; }
}
#top a.toggle.pulse {
animation: pulse-once 1.5s linear;
}
#top #themepicker_toggle,
#top #sound_state {
padding-right: 4px;
}
#top #themepicker_toggle span {
font-size: 17px;
}
#top #themepicker_toggle span:before {
vertical-align: -5px;
}
#top .dropdown {
display: none;
position: absolute;
right: 0;
top: 24px;
background: #fff;
z-index: 3;
box-shadow: 2px 5px 6px rgba(0, 0, 0, 0.3);
}
span.progress > .positive {
color: #759900;
}
@ -967,9 +947,6 @@ span.progress > .negative {
max-height: 700px;
overflow: auto;
}
#top div.lichess_language.shown .language_links {
display: block;
}
.language_links button {
display: block;
padding: 0.4em 0.5em;
@ -1001,16 +978,12 @@ span.progress > .negative {
padding-top: 10px;
}
#sound_control {
margin-right: 5px;
position: relative;
}
#sound_control .dropdown {
width: 120px;
padding: 10px;
}
#sound_control.shown .dropdown {
display: block;
}
#sound_control .slider {
float: right;
width: 10px;
@ -1919,27 +1892,37 @@ div.lichess_overboard .close:hover {
@keyframes fire {
0% {
text-shadow: 0 0 20px #fefcc9, 10px -10px 30px #feec85, -20px -20px 40px #ffae34, 20px -40px 50px #ec760c, -20px -60px 60px #cd4606, 0 -80px 70px #973716, 10px -90px 80px #451b0e;
text-shadow: 0 0 6.66px #fefcc9,
3.33px -3.33px 10px #feec85,
-6.66px -6.66px 13.33px #ffae34,
6.66px -13.33px 16.66px #ec760c,
-6.66px -20px 20px #cd4606,
0 -26.66px 11.66px #973716,
3.33px -30px 26.66px #451b0e;
}
100% {
text-shadow: 0 0 20px #fefcc9, 10px -10px 30px #fefcc9, -20px -20px 40px #feec85, 22px -42px 60px #ffae34, -22px -58px 50px #ec760c, 0 -82px 80px #cd4606, 10px -90px 80px #973716;
text-shadow: 0 0 6.66px #fefcc9,
3.33px -3.33px 10px #fefcc9,
-6.66px -6.66px 13.33px #feec85,
7.33px -14px 20px #ffae34,
-7.33px -19.33px 16.66px #ec760c,
0 -27.33px 26.66px #cd4606,
3.33px -30px 26.66px #973716;
}
}
.fire_trophy span {
transform: scale(0.35);
.fire_trophy {
color: rgba(0, 0, 0, 0.6);
font-size: 150px;
font-size: 60px;
display: block;
text-shadow: 0 0 20px #fefcc9, 10px -10px 30px #feec85, -20px -20px 40px #ffae34, 20px -40px 50px #ec760c, -20px -60px 60px #cd4606, 0 -80px 70px #973716, 10px -90px 80px #451b0e;
text-shadow: 0 0 6.66px #fefcc9,
3.33px -3.33px 10px #feec85,
-6.66px -6.66px 13.33px #ffae34,
6.66px -13.33px 16.66px #ec760c,
-6.66px -20px 20px #cd4606,
0 -26.66px 11.66px #973716,
3.33px -30px 26.66px #451b0e;
}
.fire_trophy.marathonWinner span,
.fire_trophy.marathonTopTen span,
.fire_trophy.marathonTopFifty span,
.fire_trophy.marathonTopHundred span {
filter: hue-rotate(190deg);
-webkit-filter: hue-rotate(190deg);
}
.fire_trophy span:hover {
.fire_trophy:hover {
animation: fire 1.25s ease-in-out infinite alternate;
}
/* switch toggle button */

View File

@ -99,13 +99,17 @@ ol.scheduled_tournaments a {
height: 80px;
opacity: 0.7;
transition: 1s;
font-family: "lichess" !important;
speak: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
#tournament.marathon .fire_trophy:hover {
opacity: 1;
}
#tournament.marathon .fire_trophy span {
margin-top: -78px;
margin-right: 32px;
#tournament.marathon .fire_trophy {
filter: hue-rotate(190deg);
-webkit-filter: hue-rotate(190deg);
}
#tournament .description {
padding: 20px;

View File

@ -1,141 +1,155 @@
div.user_show div.content_box_top .connected {
.user_show .content_box_top {
display: flex;
padding-left: 5px;
}
.user_show .content_box_top h1 {
margin: 0;
}
.user_show .content_box_top .connected {
color: #759900;
}
#lichess div.user_show .staff {
#lichess .user_show .staff {
color: #aa3333;
font-weight: bold;
margin-bottom: 1em;
}
div.user_show div.content_box_top > span,
div.user_show div.content_box_top > .trophy {
.user_show .content_box_top > span {
margin-left: 10px;
}
div.user_show div.content_box_top > span strong {
font-weight: normal;
color: #666;
}
div.user_show div.content_box_top > .trophy {
float: right;
.user_show .trophies {
margin-top: -47px;
flex: 1 1 100%;
display: flex;
flex-flow: row nowrap;
align-items: flex-end;
justify-content: flex-end;
}
div.user_show div.content_box_top > .trophy:first-child {
margin-right: 50px;
}
div.user_show .fire_trophy {
width: 70px;
.user_show .trophy {
height: 80px;
}
div.user_show .fire_trophy.marathonTopFifty,
div.user_show .fire_trophy.marathonTopHundred {
width: 40px;
.user_show .packed .trophy {
margin-right: -5px;
}
div.user_show .fire_trophy span {
transform: scale(0.35) translate(-103px, -3px);
margin-top: -63px!important;
margin-right: -50px;
.user_show .packed .stacked {
display: flex;
margin-right: 30px;
}
.user_show .packed .stacked .trophy {
width: 25px;
}
.user_show .trophy.award {
font-family: "lichess" !important;
speak: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
line-height: 100%;
height: 60px;
margin-top: 20px;
}
.user_show .fire_trophy {
opacity: 0.9;
transition: 0.8s;
height: 80px;
position: relative;
}
div.user_show .fire_trophy span:hover {
.user_show .fire_trophy:hover {
opacity: 1;
transform: scale(0.35) translate(-103px, -10px);
}
div.user_show .fire_trophy.marathonTopTen span {
transform: scale(0.3) translate(-112px, 14px);
.user_show .fire_trophy.marathonWinner,
.user_show .fire_trophy.marathonTopTen,
.user_show .fire_trophy.marathonTopFifty,
.user_show .fire_trophy.marathonTopHundred {
filter: hue-rotate(190deg);
-webkit-filter: hue-rotate(190deg);
}
div.user_show .fire_trophy.marathonTopTen span:hover {
transform: scale(0.3) translate(-112px, 6px);
.user_show .fire_trophy.marathonWinner {
height: 60px;
margin-top: 20px;
}
div.user_show .fire_trophy.marathonTopFifty span,
div.user_show .fire_trophy.marathonTopHundred span {
.user_show .fire_trophy.marathonTopTen {
font-size: 50px;
height: 50px;
margin-top: 30px;
width: 21px;
}
.user_show .fire_trophy.marathonTopFifty,
.user_show .fire_trophy.marathonTopHundred {
font-size: 40px;
height: 40px;
margin-top: 40px;
width: 17px;
animation: none;
}
div.user_show .trophy.icon3d {
margin-top: -10px!important;
font-size: 30px;
.user_show .fire_trophy.marathonTopFifty {
text-shadow: 0 0 5px #ffae34, 0 0 6.25px #ec760c, 0 0 7.5px #cd4606;
}
.user_show .fire_trophy.marathonTopHundred {
text-shadow: none;
color: #cd4606;
}
.user_show .trophy.icon3d {
width: 40px;
height: 40px;
margin-top: 20px;
vertical-align: middle;
font-size: 39px;
color: #ccc;
text-shadow: 0 1px 0 rgba(0,0,0,0.5);
transition: 0.3s;
}
div.user_show .trophy.icon3d:hover {
.user_show .trophy.icon3d:hover {
margin-top: -12px!important;
}
div.user_show .fire_trophy.marathonTopFifty span {
transform: scale(0.25) translate(-112px, 36px);
text-shadow: 0 0 20px #ffae34, 0 0 25px #ec760c, 0 0 30px #cd4606;
}
div.user_show .fire_trophy.marathonTopFifty span:hover {
transform: scale(0.25) translate(-112px, 28px);
}
div.user_show .fire_trophy.marathonTopHundred span {
transform: scale(0.2) translate(-112px, 90px);
text-shadow: none;
color: #cd4606;
}
div.user_show .fire_trophy.marathonTopHundred span:hover {
transform: scale(0.2) translate(-112px, 60px);
}
div.user_show .fire_trophy.marathonSurvivor span {
transform: scale(0.3) translate(-112px, 14px);
}
div.user_show .fire_trophy.marathonSurvivor span:hover {
transform: scale(0.3) translate(-112px, 6px);
}
div.user_show .fire_trophy.bongcloudWarrior span {
.user_show .fire_trophy.bongcloudWarrior {
filter: hue-rotate(70deg);
-webkit-filter: hue-rotate(70deg);
}
div.user_show .trophy.patron {
font-size: 50px;
margin-top: -40px!important;
margin-right: 10px!important;
.user_show .trophy.patron {
font-size: 60px;
margin: -30px 10px 0 30px!important;
transform: scale(-1, 1);
}
div.user_show .trophy.patron span {
color: #d59120;
transition: 0.5s;
}
div.user_show .trophy.patron:hover {
margin-top: -44px!important;
}
div.user_show .trophy.patron span:hover {
.user_show .trophy.patron:hover {
margin-top: -34px!important;
animation: fire 1.25s ease-in-out infinite alternate;
}
div.user_show .trophy.patron.hint--left:after {
.user_show .trophy.patron.hint--left:after {
transform: scale(-1, 1);
margin: 0;
}
div.user_show .trophy.patron.hint--left:after {
.user_show .trophy.patron.hint--left:after {
right: -330%;
}
div.user_show .trophy.patron.hint--left:hover:after {
.user_show .trophy.patron.hint--left:hover:after {
transform: scale(-1, 1), translateX(8px);
}
div.user_show .honorific {
.user_show .honorific {
display: inline-block;
margin-top: 1em;
font-weight: bold;
font-size: 1.4em;
}
div.user_show .social {
.user_show .social {
position: relative;
border-top: 0;
padding: 0 0 5px 10px;
height: 52px;
}
div.user_show .user_actions {
.user_show .user_actions {
position: absolute;
top: 12px;
right: 12px;
font-size: 1.2em;
}
div.user_show .user_actions form {
.user_show .user_actions form {
display: inline;
}
div.user_show .relation_actions {
.user_show .relation_actions {
display: inline;
}
div.user_show div.meat {
.user_show div.meat {
height: 325px;
position: relative;
}
@ -205,19 +219,19 @@ div.sub_ratings h3 {
font-weight: bold;
font-size: 1.2em;
}
div.user_show .rating_history {
.user_show .rating_history {
position: absolute;
left: -10px;
display: block;
width: 477px;
height: 339px;
}
div.user_show .rating_history .spinner {
.user_show .rating_history .spinner {
width: 90px;
height: 90px;
margin: 120px auto 0 auto;
}
div.user_show .user-infos {
.user_show .user-infos {
position: absolute;
top: 0;
left: 458px;
@ -227,13 +241,13 @@ div.user_show .user-infos {
width: 305px;
height: 325px;
}
div.user_show .with_insights .user-infos {
.user_show .with_insights .user-infos {
height: 265px;
}
div.user_show .user-infos:hover {
.user_show .user-infos:hover {
overflow-y: auto;
}
div.user_show .insight {
.user_show .insight {
position: absolute;
bottom: 0;
right: 0;
@ -243,273 +257,273 @@ div.user_show .insight {
border-top: 1px solid #c0c0c0;
border-left: 1px solid #c0c0c0;
}
div.user_show .insight .icon {
.user_show .insight .icon {
position: absolute;
top: 0;
right: 10px;
}
div.user_show .insight .icon::before {
.user_show .insight .icon::before {
color: #3893E8;
font-size: 40px;
line-height: 60px;
opacity: 0.8;
}
div.user_show .insight strong {
.user_show .insight strong {
color: #3893E8;
display: block;
font-weight: normal;
font-size: 1.5em;
margin: 10px 0 1px 0;
}
div.user_show .insight em {
.user_show .insight em {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
width: 275px;
}
div.user_show .insight:hover {
.user_show .insight:hover {
background: #3893E8;
}
div.user_show .insight:hover,
div.user_show .insight:hover *,
div.user_show .insight:hover .icon::before {
.user_show .insight:hover,
.user_show .insight:hover *,
.user_show .insight:hover .icon::before {
transition: 0.13s;
color: #fff;
}
div.user_show .name,
div.user_show .bio,
div.user_show .stats,
div.user_show .tournament_points,
div.user_show .teams {
.user_show .name,
.user_show .bio,
.user_show .stats,
.user_show .tournament_points,
.user_show .teams {
display: block;
margin-top: 16px;
}
div.user_show .bio {
.user_show .bio {
font-style: italic;
}
div.user_show .teams a {
.user_show .teams a {
display: block;
margin: 5px 0;
}
div.user_show .teams a.mine {
.user_show .teams a.mine {
color: #d59120;
}
div.user_show div.games {
.user_show div.games {
margin-top: 10px;
}
div.user_show div.games.center {
.user_show div.games.center {
text-align: center;
}
div.user_show .profile {
.user_show .profile {
margin-bottom: 1em;
}
div.user_show .claim_title_zone {
.user_show .claim_title_zone {
padding: 30px;
font-size: 1.2em;
line-height: 1.5em;
}
div.user_show .claim_title_zone h2 {
.user_show .claim_title_zone h2 {
font-size: 1.5em;
}
div.user_show .claim_title_zone p {
.user_show .claim_title_zone p {
margin: 2em 0;
}
div.user_show .claim_title_zone .actions {
.user_show .claim_title_zone .actions {
margin: 3em 0;
text-align: center;
}
div.user_show .note_zone {
.user_show .note_zone {
display: none;
margin: 1em 20px;
padding-bottom: 1em;
border-bottom: 1px solid #ccc;
}
div.user_show .note_zone textarea {
.user_show .note_zone textarea {
width: 98%;
margin-bottom: 5px;
height: 2em;
resize: vertical;
}
div.user_show .note_zone div {
.user_show .note_zone div {
padding-top: 1em;
border-top: 1px dotted #ccc;
margin-top: 1em;
}
div.user_show .note_zone p.meta {
.user_show .note_zone p.meta {
float: right;
text-align: right;
margin-left: 1em;
white-space: nowrap;
}
div.user_show .note_zone p.text {
.user_show .note_zone p.text {
min-height: 2.7em;
word-break: break-all;
}
div.user_show .mod_zone {
.user_show .mod_zone {
display: none;
margin: 1em 20px;
}
div.user_show .mod_zone .actions {
.user_show .mod_zone .actions {
width: 100%;
text-align: center;
}
div.user_show .mod_zone .neural,
div.user_show .mod_zone .mod_roles {
.user_show .mod_zone .neural,
.user_show .mod_zone .mod_roles {
padding: 10px 0;
}
div.user_show .mod_zone .neural strong {
.user_show .mod_zone .neural strong {
display: inline;
}
div.user_show .mod_zone .slist {
.user_show .mod_zone .slist {
border: 1px solid #ccc;
border-top: none;
font-size: 0.9em;
margin-bottom: 1em;
}
body.dark div.user_show .mod_zone .slist {
body.dark .user_show .mod_zone .slist {
border-color: #3d3d3d;
}
div.user_show .mod_zone .same {
.user_show .mod_zone .same {
font-style: italic;
font-weight: bold;
}
div.user_show .mod_zone form {
.user_show .mod_zone form {
display: inline;
}
div.user_show .mod_zone .listings {
.user_show .mod_zone .listings {
border: 1px solid #ccc;
}
div.user_show .mod_zone .listings > div {
.user_show .mod_zone .listings > div {
max-height: 20em;
overflow: auto;
}
div.user_show .mod_zone .spy_ips {
.user_show .mod_zone .spy_ips {
float: left;
margin-left: 1%;
width: 31%;
}
div.user_show .mod_zone .spy_ips > ul > li {
.user_show .mod_zone .spy_ips > ul > li {
list-style: inside disc;
}
div.user_show .mod_zone .spy_ips ul p {
.user_show .mod_zone .spy_ips ul p {
font-weight: bold;
display: inline;
}
div.user_show .mod_zone .spy_ips li li {
.user_show .mod_zone .spy_ips li li {
margin-left: 1em;
font-family: 'Roboto Mono';
}
div.user_show .mod_zone .spy_uas {
.user_show .mod_zone .spy_uas {
margin-left: 34%;
}
div.user_show .mod_zone .listings .blocked {
.user_show .mod_zone .listings .blocked {
color: red;
font-weight: bold;
}
div.user_show .mod_zone .ip .intel {
.user_show .mod_zone .ip .intel {
margin-left: 10px;
}
div.user_show .mod_zone strong {
.user_show .mod_zone strong {
display: block;
margin-top: 0.5em;
}
div.user_show .mod_zone strong.inline {
.user_show .mod_zone strong.inline {
display: inline;
}
div.user_show .mod_zone .plan_charges ul {
.user_show .mod_zone .plan_charges ul {
max-height: 100px;
overflow: auto;
}
div.user_show .mod_zone table.others.slist td:first-child {
.user_show .mod_zone table.others.slist td:first-child {
padding-left: 10px;
}
div.user_show .mod_zone .others .i {
.user_show .mod_zone .others .i {
padding: 0 2px;
}
div.user_show .mod_zone .others .i i {
.user_show .mod_zone .others .i i {
font-size: 1.5em;
}
div.user_show .mod_zone .reports {
.user_show .mod_zone .reports {
display: flex;
}
div.user_show .mod_zone .reports .half {
.user_show .mod_zone .reports .half {
flex: 1 1 50%;
overflow: hidden;
white-space: nowrap;
transition: 0.5s;
transition-delay: 0.3s;
}
div.user_show .mod_zone .reports .half:first-child {
.user_show .mod_zone .reports .half:first-child {
margin-right: 20px;
border-right: 1px solid #ccc;
}
body.dark div.user_show .mod_zone .reports .half:first-child {
body.dark .user_show .mod_zone .reports .half:first-child {
border-color: #3d3d3d;
}
div.user_show .mod_zone .reports .half:hover {
.user_show .mod_zone .reports .half:hover {
flex: 0 0 90%;
}
div.user_show .evaluation time {
.user_show .evaluation time {
display: inline;
}
div.user_show .evaluation strong {
.user_show .evaluation strong {
display: inline;
text-transform: uppercase;
}
div.user_show .evaluation .percentage {
.user_show .evaluation .percentage {
font-size: 0.9em;
}
div.user_show .evaluation .legend {
.user_show .evaluation .legend {
text-align: center;
font-weight: bold;
margin-bottom: 10px;
}
div.user_show .evaluation .legend span {
.user_show .evaluation .legend span {
padding: 10px;
}
div.user_show .evaluation .sig_1 {
.user_show .evaluation .sig_1 {
color: #2077C0;
/* dark blue */
}
div.user_show .evaluation .sig_2 {
.user_show .evaluation .sig_2 {
color: #23A1AB;
/* light blue */
}
div.user_show .evaluation .sig_3 {
.user_show .evaluation .sig_3 {
color: #DDCF3F;
/* yellow */
}
div.user_show .evaluation .sig_4 {
.user_show .evaluation .sig_4 {
color: #E79B64;
/* orange */
}
div.user_show .evaluation .sig_5 {
.user_show .evaluation .sig_5 {
color: #E73B38;
/* red */
}
div.user_show .evaluation .result_4 {
.user_show .evaluation .result_4 {
color: #E73B38;
/* red */
}
div.user_show .evaluation .result_3 {
.user_show .evaluation .result_3 {
color: #E73B38;
/* red */
}
div.user_show .evaluation .result_2 {
.user_show .evaluation .result_2 {
color: #E79B64;
/* orange */
}
div.user_show .evaluation .result_1 {
.user_show .evaluation .result_1 {
color: #2077C0;
/* dark blue */
}
div.user_show .evaluation .match {
.user_show .evaluation .match {
font-weight: bold;
color: #759900;
}
div.user_show div.content_box_inter.tabs {
.user_show div.content_box_inter.tabs {
margin-left: -8px;
padding-left: 30px;
width: 775px;
@ -518,39 +532,39 @@ div.user_show div.content_box_inter.tabs {
div.crosstable {
margin: 25px 10px 15px 10px;
}
div.user_show .reportCard {
.user_show .reportCard {
margin: 0 auto 10px auto;
}
div.user_show .reportCard th {
.user_show .reportCard th {
font-weight: bold;
font-size: 1.6em;
text-align: center;
padding: 0 5px 0 5px;
}
div.user_show .reportCard td {
.user_show .reportCard td {
text-align: center;
padding: 5px;
}
div.user_show .extra_stats {
.user_show .extra_stats {
margin: 0 auto 10px auto;
}
div.user_show .extra_stats caption {
.user_show .extra_stats caption {
text-align: center;
font-weight: bold;
font-size: 1.2em;
padding-bottom: 5px;
}
div.user_show .extra_stats th {
.user_show .extra_stats th {
text-align: right;
font-weight: bold;
font-size: 1.2em;
padding: 0 5px 0 5px;
}
div.user_show .extra_stats td {
.user_show .extra_stats td {
text-align: center;
padding: 5px;
}
div.user_show .results .aggregate {
.user_show .results .aggregate {
font-weight: bold;
font-size: 1.4em;
text-align: center;
@ -558,65 +572,65 @@ div.user_show .results .aggregate {
width: 50px;
transform: rotate(90deg);
}
div.user_show .reportCard .mark {
.user_show .reportCard .mark {
color: #dc322f;
}
div.user_show .reportCard .report {
.user_show .reportCard .report {
color: #B8AA1A;
}
div.user_show .search {
.user_show .search {
white-space: nowrap;
margin: 10px 0;
}
div.user_show .search table {
.user_show .search table {
display: inline-block;
box-sizing: border-box;
margin-left: 20px;
width: 360px;
}
div.user_show .search table tbody {
.user_show .search table tbody {
display: block;
}
div.user_show .search table:first-child {
.user_show .search table:first-child {
width: 400px;
}
div.user_show .search .header {
.user_show .search .header {
font-size: 1.3em;
}
div.user_show .search td {
.user_show .search td {
padding: 5px 0;
}
div.user_show .search label {
.user_show .search label {
margin-right: 10px;
}
div.user_show .search .single select {
.user_show .search .single select {
width: 100%;
}
div.user_show .search table .half {
.user_show .search table .half {
float: left;
width: 49%;
padding-right: 1%;
text-align: right;
}
div.user_show .search_status {
.user_show .search_status {
text-align: right;
padding: 10px 25px;
border-bottom: 1px solid #e4e4e4;
}
div.user_show .new_player {
.user_show .new_player {
padding: 20px;
}
div.user_show .new_player h2 {
.user_show .new_player h2 {
font-size: 1.4em;
}
div.user_show .new_player p {
.user_show .new_player p {
margin: 1em 0;
}
div.user_show .new_player li {
.user_show .new_player li {
list-style: disc inside;
line-height: 1.5em;
}
div.user_show .new_player a {
.user_show .new_player a {
color: #3893E8;
}

View File

@ -10,7 +10,12 @@ module.exports = {
if (!ctrl.vm.node.crazy) return;
var pocket = ctrl.vm.node.crazy.pockets[color === 'white' ? 0 : 1];
var dropped = ctrl.vm.justDropped;
var usable = !ctrl.embed && color === ctrl.turnColor();
var captured = ctrl.vm.justCaptured;
if (captured) {
captured = captured.promoted ? 'pawn' : captured.role;
}
var activeColor = color === ctrl.turnColor();
var usable = !ctrl.embed && activeColor;
return m('div', {
class: 'pocket is2d ' + position + (usable ? ' usable' : ''),
config: function(el, isUpdate, ctx) {
@ -30,8 +35,11 @@ module.exports = {
}
},
oKeys.map(function(role) {
var nb = defined(pocket[role]) ? pocket[role] : 0;
if (dropped && dropped.role === role && (dropped.ply % 2 === 1) ^ (color === 'white')) nb--;
var nb = pocket[role] || 0;
if (activeColor) {
if (dropped === role) nb--;
if (captured === role) nb++;
}
return m('piece', {
'data-role': role,
'data-color': color,

View File

@ -81,6 +81,7 @@ module.exports = function(opts) {
contextMenuPath: null,
justPlayed: null,
justDropped: null,
justCaptured: null,
keyboardHelp: location.hash === '#keyboard',
threatMode: false
};
@ -234,6 +235,7 @@ module.exports = function(opts) {
}
this.vm.justPlayed = null;
this.vm.justDropped = null;
this.vm.justCaptured = null;
this.explorer.setNode();
updateHref();
this.autoScroll();
@ -326,10 +328,8 @@ module.exports = function(opts) {
this.userNewPiece = function(piece, pos) {
if (crazyValid.drop(this.chessground, this.vm.node.drops, piece, pos)) {
this.vm.justPlayed = chessUtil.roleToSan[piece.role] + '@' + pos;
this.vm.justDropped = {
ply: this.vm.node.ply,
role: piece.role
};
this.vm.justDropped = piece.role;
this.vm.justCaptured = null;
sound.move();
var drop = {
role: piece.role,
@ -348,10 +348,10 @@ module.exports = function(opts) {
this.vm.justPlayed = orig;
this.vm.justDropped = null;
sound[capture ? 'capture' : 'move']();
if (!promotion.start(this, orig, dest, sendMove)) sendMove(orig, dest);
if (!promotion.start(this, orig, dest, capture, sendMove)) sendMove(orig, dest, capture);
}.bind(this);
var sendMove = function(orig, dest, prom) {
var sendMove = function(orig, dest, capture, prom) {
var move = {
orig: orig,
dest: dest,
@ -359,10 +359,12 @@ module.exports = function(opts) {
fen: this.vm.node.fen,
path: this.vm.path
};
if (capture) this.vm.justCaptured = capture;
if (prom) move.promotion = prom;
if (this.practice) this.practice.onUserMove();
this.socket.sendAnaMove(move);
preparePremoving();
m.redraw();
}.bind(this);
var preparePremoving = function() {

View File

@ -4,7 +4,7 @@ var util = require('chessground/util');
var promoting = false;
function start(ctrl, orig, dest, callback) {
function start(ctrl, orig, dest, capture, callback) {
var s = ctrl.chessground.state;
var piece = s.pieces[dest];
if (piece && piece.role == 'pawn' && (
@ -13,6 +13,7 @@ function start(ctrl, orig, dest, callback) {
promoting = {
orig: orig,
dest: dest,
capture, capture,
callback: callback
};
m.redraw();
@ -23,7 +24,8 @@ function start(ctrl, orig, dest, callback) {
function finish(ctrl, role) {
if (promoting) ground.promote(ctrl.chessground, promoting.dest, role);
if (promoting.callback) promoting.callback(promoting.orig, promoting.dest, role);
if (promoting.callback) promoting.callback(promoting.orig, promoting.dest,
promoting.capture, role);
promoting = false;
}

View File

@ -64,7 +64,9 @@ module.exports = function(root, studyData, data) {
}
sound.success();
var next = nextChapter();
if (next) root.study.setChapter(next.id);
if (next) setTimeout(function() {
root.study.setChapter(next.id);
}, 1000);
};
var onFailure = function() {
@ -101,6 +103,7 @@ module.exports = function(root, studyData, data) {
isWhite: function() {
return root.bottomColor() === 'white';
},
analysisUrl: analysisUrl
analysisUrl: analysisUrl,
nextChapter: nextChapter
};
};

View File

@ -56,7 +56,7 @@ module.exports = {
case true:
return m('a.feedback.win[href=/practice]', [
m('span', 'Success!'),
'Back to practice menu'
p.nextChapter() ? null : 'Back to practice menu'
]);
case false:
return m('a.feedback.fail', {

View File

@ -112,7 +112,8 @@ function makeConfig(ctrl) {
draggable: {
showGhost: true,
distance: 0,
autoDistance: false
autoDistance: false,
deleteOnDropOff: true
},
selectable: {
enabled: false

View File

@ -1,5 +1,6 @@
var chessground = require('./chessground');
var dragNewPiece = require('chessground/drag').dragNewPiece;
var eventPosition = require('chessground/util').eventPosition;
var editor = require('./editor');
var m = require('mithril');
@ -200,8 +201,12 @@ function onSelectSparePiece(ctrl, s, upEvent) {
role: s[1]
}, e, true);
document.addEventListener(upEvent, function() {
ctrl.vm.selected(s);
document.addEventListener(upEvent, function(e) {
if (ctrl.chessground.getKeyAtDomPos(eventPosition(e))) {
ctrl.vm.selected('pointer');
} else {
ctrl.vm.selected(s);
}
m.redraw();
}, {once: true});
}

View File

@ -2,27 +2,26 @@ var game = require('game').game;
// Register blur events to be sent as move metadata
var blur = false;
var lastFocus;
var lastMove;
var init = function(ctrl) {
if (game.isPlayerPlaying(ctrl.data) && !ctrl.data.simul)
window.addEventListener('blur', function() {
blur = true;
window.addEventListener('focus', function() {
lastFocus = Date.now();
});
}
var get = function() {
var value = blur;
blur = false;
return value;
return lastFocus - lastMove > 1000;
};
var reset = function() {
blur = false;
var onMove = function() {
lastMove = Date.now();
};
module.exports = {
init: init,
get: get,
reset: reset
onMove: onMove
};

View File

@ -195,6 +195,7 @@ module.exports = function(opts) {
role: role,
pos: key
};
if (blur.get()) drop.b = 1;
this.resign(false);
if (this.userId && this.data.pref.submitMove && !isPredrop) {
this.vm.dropToSubmit = drop;
@ -288,6 +289,7 @@ module.exports = function(opts) {
check: !!o.check
});
if (o.check) lichess.sound.check();
blur.onMove();
}
if (o.clock)(this.clock || this.correspondenceClock).update(o.clock.white, o.clock.black);
d.game.threefold = !!o.threefold;

View File

@ -432,27 +432,29 @@ lichess.notifyApp = (function() {
document.body.addEventListener('mouseover', lichess.powertip.mouseover);
function setMoment() {
$("time.moment").removeClass('moment').each(function() {
var parsed = moment(this.getAttribute('datetime'));
var format = this.getAttribute('data-format');
this.textContent = format === 'calendar' ? parsed.calendar(null, {
sameElse: 'DD/MM/YYYY HH:mm'
}) : parsed.format(format);
});
}
setMoment();
lichess.pubsub.on('content_loaded', setMoment);
function setMomentFromNow() {
lichess.requestIdleCallback(function() {
// check that locale was loaded
if (!window.moment_locale_url) lichess.requestIdleCallback(function() {
$(".moment-from-now").each(function() {
this.textContent = moment(this.getAttribute('datetime')).fromNow();
});
$("time.moment").removeClass('moment').each(function() {
var parsed = moment(this.getAttribute('datetime'));
var format = this.getAttribute('data-format');
this.textContent = format === 'calendar' ? parsed.calendar(null, {
sameElse: 'DD/MM/YYYY HH:mm'
}) : parsed.format(format);
});
});
}
setMomentFromNow();
lichess.pubsub.on('content_loaded', setMomentFromNow);
setInterval(setMomentFromNow, 2000);
if (window.moment_locale_url) lichess.loadScript(moment_locale_url, true).then(function() {
delete window.moment_locale_url;
setMoment();
});
else setMoment();
lichess.pubsub.on('content_loaded', setMoment);
setInterval(setMoment, 2000);
if ($('body').hasClass('blind_mode')) {
var setBlindMode = function() {
@ -469,7 +471,7 @@ lichess.notifyApp = (function() {
}, 300);
// Zoom
var currentZoom = lichess.isTrident ? 1 : $('body').data('zoom') / 100;
var currentZoom = (!lichess.isTrident && $('body').data('zoom') / 100) || 1;
var setZoom = function(zoom) {
@ -519,7 +521,6 @@ lichess.notifyApp = (function() {
};
var saveZoom = lichess.fp.debounce(function() {
console.log(currentZoom);
$.ajax({
method: 'post',
url: '/pref/zoom?v=' + Math.round(currentZoom * 100)
@ -612,15 +613,16 @@ lichess.notifyApp = (function() {
$('#top .lichess_language').one('mouseover', function() {
var $links = $(this).find('.language_links'),
langs = $('body').data('accept-languages').split(',');
langs = $('body').data('accept-languages').split(',');
$.ajax({
url: $links.data('url'),
url: lichess.assetUrl('/assets/trans/refs.json'),
cache: true,
success: function(list) {
$links.find('ul').prepend(list.map(function(lang) {
var klass = lichess.fp.contains(langs, lang[0]) ? 'class="accepted"' : '';
return '<li><button type="submit" ' + klass + ' name="lang" value="' + lang[0] + '">' + lang[1] + '</button></li>';
}).join(''));
$links.html('<ul><li><a href="/translation/contribute">Help translate Lichess!</a></li></ul>')
.find('ul').prepend(list.map(function(lang) {
var klass = lichess.fp.contains(langs, lang[0]) ? 'class="accepted"' : '';
return '<li><button type="submit" ' + klass + ' name="lang" value="' + lang[0] + '">' + lang[1] + '</button></li>';
}).join(''));
}
});
});

View File

@ -199,7 +199,7 @@ lichess.StrongSocket = function(url, version, settings) {
tryOtherUrl = true;
setTimeout(function() {
if (!$('#network_error').length) {
$('#top').append('<span class="fright link text" id="network_error" data-icon="j">Network error</span>');
$('#top').append('<span class="link text" id="network_error" data-icon="j">Network error</span>');
}
}, 1000);
clearTimeout(pingSchedule);

View File

@ -50,7 +50,7 @@ function image(d) {
function title(ctrl) {
var d = ctrl.data;
if (isMarathon(d)) return m('h1', [
m('span.fire_trophy.marathonWinner', m('span[data-icon=\\]')),
m('span.fire_trophy', '\\'),
d.fullName
]);
return m('h1', [