Merge branch 'master' into atomic_chess
* master: (29 commits) simul: move on on game end - fixes #179 fix spectator link to player improve lobby playing games timer - resolves #187 fallback language links for anon Revert "remove lang fallback links" fix dark language links hr "hrvatski" translation #11604. Author: gus_fring. th "ไทย" translation #11603. Author: Jer_King. Add Yoruba language yo "Yorùbá" translation #11588. Author: Mikhail04. sk "slovenčina" translation #11579. Author: xslyepov. hr "hrvatski" translation #11578. Author: DrOz. sr "Српски језик" translation #11568. Author: NoSurrenderNoRetreat. el "Ελληνικά" translation #11562. Author: kosf. pt "Português" translation #11561. Author: BearJr. ca "Català, valencià" translation #11560. Author: stanislaski. sk "slovenčina" translation #11557. Author: Inconnu_SVK. vi "Tiếng Việt" translation #11551. Author: mahabatnha. ar "العربية" translation #11549. Author: Abd0. pl "polski" translation #11535. Author: luk82. ...
This commit is contained in:
commit
7bfc208f04
|
@ -2,16 +2,32 @@ package controllers
|
|||
|
||||
import play.api.data.Form
|
||||
|
||||
import lila.app._
|
||||
import lila.common.{ Captcha, LilaCookie }
|
||||
import lila.i18n.{ Translation, TransInfo }
|
||||
import lila.api.Context
|
||||
import lila.app._
|
||||
import lila.common.{ Captcha, LilaCookie, HTTPRequest }
|
||||
import lila.i18n.{ Translation, TransInfo }
|
||||
import views._
|
||||
|
||||
object I18n extends LilaController {
|
||||
|
||||
private def env = Env.i18n
|
||||
|
||||
def select = OpenBody { implicit ctx =>
|
||||
import play.api.data.Forms._
|
||||
import play.api.data._
|
||||
implicit val req = ctx.body
|
||||
Form(single("lang" -> text.verifying(env.pool contains _))).bindFromRequest.fold(
|
||||
_ => notFound,
|
||||
lang => (ctx.me ?? { me => lila.user.UserRepo.setLang(me.id, lang) }) inject Redirect {
|
||||
s"${Env.api.Net.Protocol}${lang}.${Env.api.Net.Domain}" + {
|
||||
HTTPRequest.referer(ctx.req).fold(routes.Lobby.home.url) { str =>
|
||||
new java.net.URL(str).getPath
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
def contribute = Open { implicit ctx =>
|
||||
val mines = (ctx.req.acceptLanguages map env.transInfos.get).toList.flatten.distinct
|
||||
Ok(html.i18n.contribute(env.transInfos.all, mines)).fuccess
|
||||
|
|
|
@ -45,7 +45,11 @@ private[controllers] trait LilaController
|
|||
Open(BodyParsers.parse.anyContent)(f)
|
||||
|
||||
protected def Open[A](p: BodyParser[A])(f: Context => Fu[Result]): Action[A] =
|
||||
Action.async(p)(req => reqToCtx(req) flatMap f)
|
||||
Action.async(p) { req =>
|
||||
reqToCtx(req) flatMap { ctx =>
|
||||
Env.i18n.requestHandler.forUser(req, ctx.me).fold(f(ctx))(fuccess)
|
||||
}
|
||||
}
|
||||
|
||||
protected def OpenBody(f: BodyContext => Fu[Result]): Action[AnyContent] =
|
||||
OpenBody(BodyParsers.parse.anyContent)(f)
|
||||
|
@ -62,7 +66,9 @@ private[controllers] trait LilaController
|
|||
protected def Auth[A](p: BodyParser[A])(f: Context => UserModel => Fu[Result]): Action[A] =
|
||||
Action.async(p) { req =>
|
||||
reqToCtx(req) flatMap { implicit ctx =>
|
||||
ctx.me.fold(authenticationFailed)(me => f(ctx)(me))
|
||||
ctx.me.fold(authenticationFailed) { me =>
|
||||
Env.i18n.requestHandler.forUser(req, ctx.me).fold(f(ctx)(me))(fuccess)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,9 +110,9 @@ chessground: Boolean = true)(body: Html)(implicit ctx: Context)
|
|||
<a class="toggle" href="#">
|
||||
<span data-icon="u"> @langName(lang)</span>
|
||||
</a>
|
||||
<ul class="language_links dropdown" data-url="@staticUrl("trans/refs.json")">
|
||||
<form action="@routes.I18n.select" method="POST" class="language_links dropdown" data-url="@staticUrl("trans/refs.json")?v=@assetVersion">
|
||||
<li><a href="@routes.I18n.contribute">Help translate Lichess!</a></li>
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
@ctx.me.map { me =>
|
||||
<div class="auth">
|
||||
|
@ -172,7 +172,7 @@ chessground: Boolean = true)(body: Html)(implicit ctx: Context)
|
|||
<a id="site_title" href="@routes.Lobby.home">
|
||||
lichess<span class="extension">.org</span>
|
||||
</a>
|
||||
@if(acceptsLanguage(lang)) {
|
||||
@if(ctx.isAuth || acceptsLanguage(lang)) {
|
||||
@baseline
|
||||
} else {
|
||||
@langFallbackLinks
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=يوم واحد
|
|||
nbDays=%s يوم
|
||||
nbHours=%s ساعة
|
||||
time=الوقت
|
||||
rating=التصنيف
|
||||
username=إسم المستخدم
|
||||
password=كلمة السر
|
||||
haveAnAccount=هل لديك حساب؟
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=Un dia
|
|||
nbDays=%s dies
|
||||
nbHours=%s hores
|
||||
time=Temps
|
||||
rating=Puntuació
|
||||
username=Nom d'usuari
|
||||
password=Contrasenya
|
||||
haveAnAccount=Ja tens un compte?
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=Μία μέρα
|
|||
nbDays=%s μέρες
|
||||
nbHours=%s ώρες
|
||||
time=Χρόνος
|
||||
rating=Κατάταξη
|
||||
username=Όνομα χρήστη
|
||||
password=Κωδικός
|
||||
haveAnAccount=Έχετε λογαριασμό;
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=یک روز
|
|||
nbDays=روز %s
|
||||
nbHours=%s ساعت
|
||||
time=زمان
|
||||
rating=ریتینگ
|
||||
username=نام کاربری
|
||||
password=رمزعبور
|
||||
haveAnAccount=شما صاحب حساب کاربری می باشید؟
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
playWithAFriend=שחק עם חבר
|
||||
playWithTheMachine=שחק עם המחשב
|
||||
toInviteSomeoneToPlayGiveThisUrl=כדי להזמין מישהוא לשחק, תן את הכתובת הזאת
|
||||
toInviteSomeoneToPlayGiveThisUrl=כדי להזמין מישהו לשחק, תן את הכתובת הזאת
|
||||
gameOver=המשחק נגמר
|
||||
waitingForOpponent=ממתין ליריב
|
||||
waiting=ממתין
|
||||
|
@ -88,6 +88,7 @@ oneDay=יום אחד
|
|||
nbDays=ימים %s
|
||||
nbHours=%s שעות
|
||||
time=זמן
|
||||
rating=דירוג
|
||||
username=שם משתמש
|
||||
password=סיסמה
|
||||
haveAnAccount=יש לך חשבון?
|
||||
|
@ -169,6 +170,7 @@ tournaments=טורנירים
|
|||
tournamentPoints=נקודות טורניר
|
||||
viewTournament=צפה בטורניר
|
||||
backToTournament=בחזרה לטורניר
|
||||
backToGame=חזרה למשחק
|
||||
freeOnlineChessGamePlayChessNowInACleanInterfaceNoRegistrationNoAdsNoPluginRequiredPlayChessWithComputerFriendsOrRandomOpponents=משחק שחמט חינם ברשת. שחק שחמט כעת בממשק נקי. ללא הרשמה, ללא פרסומות, ללא תוכנת הרחבה. שחק שחמט עם המחשב, חברים או יריבים אקראיים.
|
||||
teams=קבוצות
|
||||
nbMembers=%s חברים
|
||||
|
@ -305,3 +307,5 @@ thisPuzzleIsCorrect=הפאזל נכון ומעניין.
|
|||
thisPuzzleIsWrong=הפאזל לא נכון או משעמם
|
||||
youHaveNbSecondsToMakeYourFirstMove=יש לך %s שניות לבצע את המהלך הראשון!
|
||||
nbGamesInPlay=%s משחקים בתהליך
|
||||
automaticallyProceedToNextGameAfterMoving=המשך אוטומטית למשחק הבא אחרי מהלך
|
||||
autoSwitch=החלפה אוטומטית
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=Jedan dan
|
|||
nbDays=%s dana
|
||||
nbHours=%s sati
|
||||
time=Vrijeme
|
||||
rating=Rejting
|
||||
username=Korisničko ime
|
||||
password=Zaporka
|
||||
haveAnAccount=Imate li otvoren račun?
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=Un giorno
|
|||
nbDays=%s giorni
|
||||
nbHours=%s ore
|
||||
time=Tempo
|
||||
rating=Punteggio
|
||||
username=Username
|
||||
password=Password
|
||||
haveAnAccount=Hai un account?
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=1 dzień na ruch
|
|||
nbDays=%s Dni
|
||||
nbHours=%s godzin
|
||||
time=Czas
|
||||
rating=Ranking
|
||||
username=Nazwa użytkownika
|
||||
password=Hasło
|
||||
haveAnAccount=Masz już konto?
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=Um dia
|
|||
nbDays=%s dias
|
||||
nbHours=%s horas
|
||||
time=Tempo
|
||||
rating=Rating
|
||||
username=Nome
|
||||
password=Palavra-chave
|
||||
haveAnAccount=Tem uma conta?
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=Jeden deň
|
|||
nbDays=%s dní
|
||||
nbHours=%s hodín
|
||||
time=Čas
|
||||
rating=Rating
|
||||
username=Meno užívateľa
|
||||
password=Heslo
|
||||
haveAnAccount=Máte účet?
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=një ditë
|
|||
nbDays=%s ditë
|
||||
nbHours=%s orë
|
||||
time=Koha
|
||||
rating=Vlerësuar
|
||||
username=Emri i përdoruesit
|
||||
password=Fjalëkalimi
|
||||
haveAnAccount=Keni një llogari?
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=Један дан
|
|||
nbDays=%s дана
|
||||
nbHours=%s сати
|
||||
time=Време
|
||||
rating=Рејтинг
|
||||
username=Корисничко име
|
||||
password=Лозинка
|
||||
haveAnAccount=Имате налог?
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=หนึ่งวัน
|
|||
nbDays=%s วัน
|
||||
nbHours=%s ชั่วโมง
|
||||
time=เวลา
|
||||
rating=ระดับคะแนน
|
||||
username=ชื่อผู้ใช้
|
||||
password=รหัสผ่าน
|
||||
haveAnAccount=มีบัญชีแล้วหรือยัง?
|
||||
|
@ -97,7 +98,7 @@ changeEmail=เปลี่ยนอีเมล
|
|||
email=อีเมล
|
||||
emailIsOptional=อีเมลเป็นตัวเลือกซึ่ง Lichess จะใช้เพื่อการตั้งรหัสผ่านของคุณใหม่ในกรณีที่คุณลืมมัน
|
||||
passwordReset=ตั้งรหัสผ่านใหม่
|
||||
forgotPassword=ลืมรหัสผ่านหรือเปล่า?
|
||||
forgotPassword=ลืมรหัสผ่าน?
|
||||
learnMoreAboutLichess=เรียนรู้เพิ่มเติมเกี่ยวกับ Lichess
|
||||
rank=อันดับ
|
||||
gamesPlayed=เกมที่ได้เล่น
|
||||
|
|
|
@ -88,6 +88,7 @@ oneDay=Một ngày
|
|||
nbDays=%s ngày
|
||||
nbHours=%s giờ
|
||||
time=Thời gian
|
||||
rating=Hệ số Elo
|
||||
username=Tên đăng nhập
|
||||
password=Mật khẩu
|
||||
haveAnAccount=Bạn có tài khoản chưa?
|
||||
|
|
38
conf/messages.yo
Normal file
38
conf/messages.yo
Normal file
|
@ -0,0 +1,38 @@
|
|||
gameOver=Game Ose
|
||||
white=Funfun
|
||||
black=Dudu
|
||||
whiteIsVictorious=Funfun ni ṣẹgun
|
||||
blackIsVictorious=Dudu ni ṣẹgun
|
||||
analysis=Onínọmbà
|
||||
signUp=Forukọsilẹ
|
||||
games=Ere
|
||||
forum=Forum
|
||||
correspondence=Lẹta
|
||||
time=akoko
|
||||
rating=Rating
|
||||
password=ọrọigbaniwọle
|
||||
changePassword=Ayipada ọrọigbaniwọle
|
||||
changeEmail=Ayipada imeeli
|
||||
email=Imeeli
|
||||
accept=Gba awọn
|
||||
decline=Sile
|
||||
casual=Unrated
|
||||
rated=Won won
|
||||
send=Firanṣẹ
|
||||
spectators=Ayé ti:
|
||||
search=àwárí
|
||||
tournament=Figagbaga
|
||||
tournaments=Awọn ere-idije
|
||||
teams=Egbe
|
||||
allTeams=Gbogbo egbe
|
||||
newTeam=Titun egbe
|
||||
myTeams=Mi egbe
|
||||
settings=Eto
|
||||
apply=Waye
|
||||
leaderboard=Leaderboard
|
||||
more=Diẹ
|
||||
winner=Olubori ọkunrin
|
||||
country=Orilẹ-ede
|
||||
training=Ikẹkọ
|
||||
victory=Isegun!
|
||||
thankYou=E dupe!
|
|
@ -182,6 +182,7 @@ GET /translation/form/:lang controllers.I18n.translationForm(lang: St
|
|||
POST /translation/post/:lang controllers.I18n.translationPost(lang: String)
|
||||
GET /translation/fetch/:from controllers.I18n.fetch(from: Int)
|
||||
POST /translation/hideCalls controllers.I18n.hideCalls
|
||||
POST /translation/select controllers.I18n.select
|
||||
|
||||
# Authentication
|
||||
GET /login controllers.Auth.login
|
||||
|
|
35
issues
Normal file
35
issues
Normal file
|
@ -0,0 +1,35 @@
|
|||
# ornicar/lila open issues
|
||||
184 Desktop notifications [feature] 1
|
||||
183 antichess doesn't play well with takebacks [bug] 1
|
||||
181 miniboard empty [bug] [planned] 1
|
||||
180 autoswitch after no other game in simul [improvement] [planned]
|
||||
179 simul autoswitch on game end [improvement] [planned]
|
||||
178 make sure ragequit is disabled in simul [bug] [planned]
|
||||
176 Spectator chat split by move number for the benefit of kibitzing context [feature]
|
||||
175 Implement realtime private messaging a la online-go/facebook [feature] 1
|
||||
174 clicking on other language subdomain should retain preferred language [feature] [planned]
|
||||
169 Predefined positions for game creation [feature] [planned]
|
||||
168 Add advanced options in analysis board [feature]
|
||||
167 Atomic chess [feature] [in progress]
|
||||
166 make puzzle of the day embeddable for site owners [feature]
|
||||
165 [Translation] To French. 'only accepts challenges from friends.' 1
|
||||
164 Unsubscribe from something [feature]
|
||||
163 The "%s games" link under favourite opponents no longer works
|
||||
161 TV channels [feature]
|
||||
155 Link Win/Draw/Loss indicator in Tournament Standings to Games [improvement]
|
||||
153 Add support for anti-chess in PDF exporter [improvement]
|
||||
149 Simul tournament [feature] [planned] @
|
||||
143 Stream title on TV doesn't wrap [improvement] 2
|
||||
142 Predefine move sequences in correspondence chess [feature] [planned] 3
|
||||
130 Several colours for clock bar [feature]
|
||||
128 when importing PGN, accept clock information [feature] 2
|
||||
127 export clock information in PGN [feature] 6
|
||||
126 Feature: Possibility to edit/delete forum posts [feature]
|
||||
114 Wrong encoding in names of wiki-pages [bug]
|
||||
97 Feature: Ability to rematch with different game settings [feature] 2
|
||||
77 Feature wish: Training mode long time chart [feature]
|
||||
73 Intermitent problem creating tournaments [bug] [can't reproduce]
|
||||
69 timing in "Spectator room" chat [feature]
|
||||
59 Feature: Clock pause [feature] 1
|
||||
58 separate TVs for bullet-time, blitz and slow games. [feature] [planned] 1
|
||||
53 Advanced comments [feature] 3
|
|
@ -21,6 +21,8 @@ object HTTPRequest {
|
|||
|
||||
def userAgent(req: RequestHeader): Option[String] = req.headers get HeaderNames.USER_AGENT
|
||||
|
||||
def referer(req: RequestHeader): Option[String] = req.headers get HeaderNames.REFERER
|
||||
|
||||
def sid(req: RequestHeader): Option[String] = req.session get "sid"
|
||||
|
||||
private val isBotPattern = {
|
||||
|
|
|
@ -4,13 +4,17 @@ import chess.format.{ pgn => chessPgn }
|
|||
|
||||
object Rewind {
|
||||
|
||||
private def createTags(fen: Option[String], game: Game) = {
|
||||
val variantTag = Some(chessPgn.Tag(_.Variant, game.variant.name))
|
||||
val fenTag = fen map (fenString => chessPgn.Tag(_.FEN, fenString))
|
||||
|
||||
List(variantTag, fenTag).flatten
|
||||
}
|
||||
|
||||
def apply(game: Game, initialFen: Option[String]): Valid[Progress] = chessPgn.Reader.movesWithSans(
|
||||
moveStrs = game.pgnMoves,
|
||||
op = sans => sans.isEmpty.fold(sans, sans.init),
|
||||
tags = initialFen.??(fen => List(
|
||||
chessPgn.Tag(_.FEN, fen),
|
||||
chessPgn.Tag(_.Variant, game.variant.name)
|
||||
))) map { replay =>
|
||||
tags = createTags(initialFen, game)) map { replay =>
|
||||
val rewindedGame = replay.state
|
||||
val rewindedHistory = rewindedGame.board.history
|
||||
val rewindedSituation = rewindedGame.situation
|
||||
|
|
|
@ -81,7 +81,8 @@ private[i18n] object Contributors {
|
|||
"mg" -> List("RAZAFIMAHEFA Aina"),
|
||||
"kb" -> List("skafis"),
|
||||
"zu" -> List("Dragon135"),
|
||||
"ur" -> List("alleey"))
|
||||
"ur" -> List("alleey"),
|
||||
"yo" -> List("Mikhail04"))
|
||||
|
||||
def apply(code: String): List[String] = ~(all get code)
|
||||
}
|
||||
|
|
|
@ -13,5 +13,7 @@ case class I18nDomain(domain: String) {
|
|||
|
||||
lazy val commonDomain = hasLang.fold(parts drop 1 mkString ".", domain)
|
||||
|
||||
def withLang(lang: Lang) = I18nDomain(lang.language + "." + commonDomain)
|
||||
def withLang(lang: Lang): I18nDomain = withLang(lang.language)
|
||||
|
||||
def withLang(lang: String): I18nDomain = I18nDomain(lang + "." + commonDomain)
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ private[i18n] case class I18nPool(val langs: Set[Lang], val default: Lang) {
|
|||
|
||||
val names: Map[String, String] = (langs map langNames).toMap
|
||||
|
||||
val contains: Set[String] = langs.map(_.language)
|
||||
|
||||
private def langNames(lang: Lang): (String, String) =
|
||||
lang.language -> LangList.nameOrCode(lang.language)
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package lila.i18n
|
||||
|
||||
import play.api.i18n.Lang
|
||||
import play.api.mvc.Results.Redirect
|
||||
import play.api.mvc.{ Action, RequestHeader, Handler }
|
||||
import play.api.mvc.{ Action, RequestHeader, Handler, Result }
|
||||
|
||||
import lila.common.HTTPRequest
|
||||
|
||||
|
@ -12,15 +11,20 @@ final class I18nRequestHandler(
|
|||
cdnDomain: String) {
|
||||
|
||||
def apply(req: RequestHeader): Option[Handler] =
|
||||
(HTTPRequest.isRedirectable(req) &&
|
||||
!pool.domainLang(req).isDefined &&
|
||||
req.host != cdnDomain
|
||||
) option Action {
|
||||
Redirect(redirectUrl(req))
|
||||
}
|
||||
if (HTTPRequest.isRedirectable(req) &&
|
||||
req.host != cdnDomain &&
|
||||
pool.domainLang(req).isEmpty) Some(Action(Redirect(redirectUrl(req))))
|
||||
else None
|
||||
|
||||
def forUser(req: RequestHeader, userOption: Option[lila.user.User]): Option[Result] = for {
|
||||
userLang <- userOption.flatMap(_.lang)
|
||||
reqLang <- pool domainLang req
|
||||
if userLang != reqLang.language
|
||||
} yield Redirect(redirectUrlLang(req, userLang))
|
||||
|
||||
private def redirectUrl(req: RequestHeader) =
|
||||
protocol +
|
||||
I18nDomain(req.domain).withLang(pool preferred req).domain +
|
||||
req.uri
|
||||
redirectUrlLang(req, pool.preferred(req).language)
|
||||
|
||||
private def redirectUrlLang(req: RequestHeader, lang: String) =
|
||||
s"$protocol${I18nDomain(req.domain).withLang(lang).domain}${req.uri}"
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ final class Env(
|
|||
def receive = {
|
||||
case User.Active(user, lang) =>
|
||||
if (!user.seenRecently) UserRepo setSeenAt user.id
|
||||
if (user.lang != lang.some) UserRepo.setLang(user.id, lang)
|
||||
onlineUserIdMemo put user.id
|
||||
}
|
||||
})), 'userActive)
|
||||
|
|
|
@ -257,9 +257,7 @@ trait UserRepo {
|
|||
"count.game" -> $gt(4)
|
||||
), "_id")(_.asOpt[String])
|
||||
|
||||
def setLang(id: ID, lang: String) {
|
||||
$update.fieldUnchecked(id, "lang", lang)
|
||||
}
|
||||
def setLang(id: ID, lang: String) = $update.field(id, "lang", lang)
|
||||
|
||||
def idsSumToints(ids: Iterable[String]): Fu[Int] = ids.isEmpty ? fuccess(0) | {
|
||||
import reactivemongo.core.commands._
|
||||
|
|
|
@ -904,9 +904,8 @@ lichess.storage = {
|
|||
url: $links.data('url'),
|
||||
success: function(list) {
|
||||
$links.prepend(list.map(function(lang) {
|
||||
var href = location.href.replace(/\/\/\w+\./, '//' + lang[0] + '.');
|
||||
var klass = $.fp.contains(langs, lang[0]) ? 'class="accepted"' : '';
|
||||
return '<li><a ' + klass + ' lang="' + lang[0] + '" href="' + href + '">' + lang[1] + '</a></li>';
|
||||
return '<li><button type="submit" ' + klass + '" name="lang" value="' + lang[0] + '">' + lang[1] + '</button></li>';
|
||||
}).join(''));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1217,42 +1217,48 @@ div.lichess_language {
|
|||
float: right;
|
||||
position: relative;
|
||||
}
|
||||
ul.language_links {
|
||||
.language_links {
|
||||
width: 620px;
|
||||
padding: 10px;
|
||||
max-height: 700px;
|
||||
overflow: auto;
|
||||
}
|
||||
#top div.lichess_language.shown ul.language_links {
|
||||
#top div.lichess_language.shown .language_links {
|
||||
display: block;
|
||||
}
|
||||
ul.language_links a {
|
||||
.language_links button {
|
||||
display: block;
|
||||
padding: 0.4em 0.5em;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
background: none;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
transition: 0.13s;
|
||||
}
|
||||
ul.language_links a.current,
|
||||
ul.language_links a.accepted {
|
||||
.language_links button.current,
|
||||
.language_links button.accepted {
|
||||
font-weight: bold;
|
||||
color: #444;
|
||||
}
|
||||
ul.language_links a.accepted {
|
||||
.language_links button.accepted {
|
||||
text-decoration: underline;
|
||||
}
|
||||
ul.language_links a:hover,
|
||||
ul.language_links a.current {
|
||||
.language_links button:hover,
|
||||
.language_links button.current {
|
||||
background: #F0F0F0;
|
||||
}
|
||||
ul.language_links li {
|
||||
.language_links li {
|
||||
width: 25%;
|
||||
height: 24px;
|
||||
float: left;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
ul.language_links li:last-child {
|
||||
.language_links li:last-child {
|
||||
width: 50%;
|
||||
font-weight: bold;
|
||||
padding-top: 10px;
|
||||
}
|
||||
#themepicker {
|
||||
float: right;
|
||||
|
@ -1265,7 +1271,7 @@ ul.language_links li:last-child {
|
|||
text-decoration: none;
|
||||
line-height: normal;
|
||||
}
|
||||
#themepicker.shown div.dropdown {
|
||||
#themepicker.shown .dropdown {
|
||||
display: block;
|
||||
width: 241px;
|
||||
text-align: center;
|
||||
|
@ -1824,25 +1830,6 @@ div.lichess_language {
|
|||
float: right;
|
||||
position: relative;
|
||||
}
|
||||
ul.language_links {
|
||||
width: 620px;
|
||||
padding: 10px;
|
||||
max-height: 700px;
|
||||
overflow: auto;
|
||||
}
|
||||
#top div.lichess_language.shown ul.language_links {
|
||||
display: block;
|
||||
}
|
||||
ul.language_links a {
|
||||
display: block;
|
||||
padding: 0.4em 0.5em;
|
||||
text-decoration: none;
|
||||
transition: 0.13s;
|
||||
}
|
||||
ul.language_links a.current,
|
||||
ul.language_links a.accepted {
|
||||
font-weight: bold;
|
||||
}
|
||||
div.undertable {
|
||||
width: 512px;
|
||||
font-size: 11.5px;
|
||||
|
|
|
@ -151,8 +151,7 @@ body.dark #themepicker div.theme:hover {
|
|||
}
|
||||
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 #top .language_links button:hover,
|
||||
body.dark #challenge_notifications > div.notification:hover,
|
||||
body.dark #message_notifications div.notification:hover {
|
||||
background-color: #3e3e3e;
|
||||
|
@ -276,7 +275,7 @@ body.dark #friend_box,
|
|||
body.dark #powerTip {
|
||||
background: #343434;
|
||||
}
|
||||
body.dark #top ul.language_links a.accepted,
|
||||
body.dark #top .language_links button.accepted,
|
||||
body.dark #lichess_forum div.post .message,
|
||||
body.dark #lichess_blog,
|
||||
body.dark #lichess_message div.thread_message div.thread_message_body,
|
||||
|
|
|
@ -19,7 +19,7 @@ module.exports = function(ctrl, player, klass) {
|
|||
},
|
||||
class: 'text user_link ' + (player.user.online ? 'online is-green' : 'offline') + (klass ? ' ' + klass : ''),
|
||||
href: '/@/' + player.user.username,
|
||||
target: game.isPlayerPlaying(ctrl.data) ? '_blank' : null,
|
||||
target: game.isPlayerPlaying(ctrl.data) ? '_blank' : '_self',
|
||||
'data-icon': 'r',
|
||||
}, [
|
||||
(player.user.title ? player.user.title + ' ' : '') + player.user.username,
|
||||
|
|
|
@ -2,6 +2,13 @@ var m = require('mithril');
|
|||
|
||||
var boardContent = m('div.cg-board-wrap', m('div.cg-board'));
|
||||
|
||||
function timer(pov) {
|
||||
var time = moment().add(pov.secondsLeft, 'seconds');
|
||||
return m('time.moment-from-now', {
|
||||
datetime: time
|
||||
}, time.fromNow());
|
||||
}
|
||||
|
||||
module.exports = function(ctrl) {
|
||||
return m('div#now_playing',
|
||||
ctrl.data.nowPlaying.map(function(pov) {
|
||||
|
@ -15,18 +22,13 @@ module.exports = function(ctrl) {
|
|||
'data-fen': pov.fen,
|
||||
'data-lastmove': pov.lastMove,
|
||||
config: function(el, isUpdate) {
|
||||
if (isUpdate) return;
|
||||
lichess.parseFen($(el));
|
||||
if (!isUpdate) lichess.parseFen($(el));
|
||||
}
|
||||
}, boardContent),
|
||||
m('span.meta', [
|
||||
pov.opponent.aiLevel ? ctrl.trans('aiNameLevelAiLevel', 'Stockfish', pov.opponent.aiLevel) : pov.opponent.username,
|
||||
m('span.indicator',
|
||||
pov.isMyTurn ? (pov.secondsLeft ? m('time.moment-from-now', {
|
||||
config: function(el, isUpdate) {
|
||||
if (!isUpdate) el.setAttribute('datetime', moment().add(pov.secondsLeft, 'seconds'));
|
||||
}
|
||||
}) : ctrl.trans('yourTurn')) : m.trust(' '))
|
||||
pov.isMyTurn ? (pov.secondsLeft ? timer(pov) : ctrl.trans('yourTurn')) : m.trust(' '))
|
||||
])
|
||||
])
|
||||
})
|
||||
|
|
|
@ -34,7 +34,7 @@ module.exports = function(ctrl, key) {
|
|||
}.bind(this);
|
||||
|
||||
this.next = function(id) {
|
||||
if (!this.value || !game.isPlayerPlaying(ctrl.data) || game.isPlayerTurn(ctrl.data)) return;
|
||||
if (!this.value || ctrl.data.player.spectator || game.isPlayerTurn(ctrl.data)) return;
|
||||
if (id) goToId(id);
|
||||
else xhr.next(ctrl).then(function(data) {
|
||||
if (data.next) goToId(data.next);
|
||||
|
|
Loading…
Reference in a new issue