show realtime user game in powertip
parent
a6235e8a39
commit
7f6314e3ac
|
@ -5,6 +5,7 @@ import play.api.mvc._, Results._
|
|||
import lila.app._
|
||||
import lila.common.LilaCookie
|
||||
import lila.db.api.$find
|
||||
import lila.game.GameRepo
|
||||
import lila.security.Permission
|
||||
import lila.user.tube.userTube
|
||||
import lila.user.{ Context, User ⇒ UserModel, UserRepo }
|
||||
|
@ -21,7 +22,9 @@ object User extends LilaController {
|
|||
}
|
||||
|
||||
def showMini(username: String) = Open { implicit ctx ⇒
|
||||
mini(username)
|
||||
OptionFuOk(UserRepo named username) { user ⇒
|
||||
GameRepo nowPlaying user.id map { html.user.mini(user, _) }
|
||||
}
|
||||
}
|
||||
|
||||
def showFilter(username: String, filterName: String, page: Int) = Open { implicit ctx ⇒
|
||||
|
@ -53,12 +56,6 @@ object User extends LilaController {
|
|||
})
|
||||
} yield html.user.show(u, info, pag, filters)
|
||||
|
||||
private def mini(username: String)(implicit ctx: Context) =
|
||||
OptionOk(UserRepo named username) { user ⇒
|
||||
Thread sleep 200
|
||||
html.user.mini(user)
|
||||
}
|
||||
|
||||
def list(page: Int) = Open { implicit ctx ⇒
|
||||
Reasonable(page) {
|
||||
val nb = 10
|
||||
|
|
|
@ -1,25 +1,27 @@
|
|||
@(userId: String, signup: Boolean = false)(implicit ctx: Context)
|
||||
@(userId: String, signup: Boolean = false, playing: Boolean = false)(implicit ctx: Context)
|
||||
|
||||
@ctx.userId.map { myId =>
|
||||
@if(myId != userId) {
|
||||
@if(!blocks(userId, myId)) {
|
||||
@if(!playing) {
|
||||
<a title="@trans.challengeToPlay()" href="@routes.Lobby.home()?username=@userIdToUsername(userId)#friend" class="icon button" href="#">
|
||||
<span class="s16 challenge"></span>
|
||||
</a>
|
||||
}
|
||||
<a title="@trans.composeMessage()" href="@routes.Message.form()?username=@userId" class="icon button" href="#">
|
||||
<span class="s16 message"></span>
|
||||
</a>
|
||||
}
|
||||
@relationWith(userId) match {
|
||||
case None => {
|
||||
<a
|
||||
class="icon button relation"
|
||||
href="@routes.Relation.block(userId)"
|
||||
<a
|
||||
class="icon button relation"
|
||||
href="@routes.Relation.block(userId)"
|
||||
title="@trans.block()">
|
||||
<span class="s16 tdown"></span>
|
||||
</a>
|
||||
<a
|
||||
class="icon button relation"
|
||||
<a
|
||||
class="icon button relation"
|
||||
href="@routes.Relation.follow(userId)"
|
||||
title="@trans.follow()">
|
||||
<span class="s16 tup"></span>
|
||||
|
|
|
@ -1,23 +1,26 @@
|
|||
@(u: User)(implicit ctx: Context)
|
||||
@(u: User, playing: Option[Game])(implicit ctx: Context)
|
||||
<div class="title">
|
||||
<span class="user_link @isOnline(u.id).fold("online", "offline")">
|
||||
<strong title="Glicko rating">@u.rating</strong>
|
||||
<small title="Glicko rating deviation">±@u.perfs.global.glicko.intDeviation</small>
|
||||
<small title="Glicko rating deviation">±@u.perfs.global.glicko.intDeviation</small>
|
||||
@showProgress(u.progress)
|
||||
@u.count.game.localize @trans.games()
|
||||
</span>
|
||||
<p class="localization">
|
||||
@u.profileOrDefault.countryInfo.map {
|
||||
case (code, name) => {
|
||||
<span class="country"><img src="@staticUrl(s"images/flag/shiny/16/$code.png")" /> @name</span>
|
||||
}
|
||||
}
|
||||
@u.lang.flatMap(langName).map { name =>
|
||||
<span class="lang s16">@name</span>
|
||||
}
|
||||
@u.profileOrDefault.countryInfo.map {
|
||||
case (code, name) => {
|
||||
<span class="country"><img src="@staticUrl(s"images/flag/shiny/16/$code.png")" /> @name</span>
|
||||
}
|
||||
}
|
||||
@u.lang.flatMap(langName).map { name =>
|
||||
<span class="lang s16">@name</span>
|
||||
}
|
||||
</p>
|
||||
@if(followsMe(u.id)) {
|
||||
@trans.followsYou()
|
||||
}
|
||||
@playing.map { g =>
|
||||
@gameFen(g, g.player(u).getOrElse(g.firstPlayer).color)
|
||||
}
|
||||
</div>
|
||||
<div class="content relation_actions">@relation.actions(u.id)</div>
|
||||
<div class="content relation_actions">@relation.actions(u.id, playing = playing.isDefined)</div>
|
||||
|
|
|
@ -164,6 +164,11 @@ trait GameRepo {
|
|||
$count(Json.obj(BSONFields.createdAt -> ($gte($date(from)) ++ $lt($date(to)))))
|
||||
}).sequenceFu
|
||||
|
||||
def nowPlaying(userId: String): Fu[Option[Game]] =
|
||||
$find.one(Query.status(Status.Started) ++ Query.user(userId) ++ Json.obj(
|
||||
BSONFields.createdAt -> $gt($date(DateTime.now - 30.minutes))
|
||||
))
|
||||
|
||||
def bestOpponents(userId: String, limit: Int): Fu[List[(String, Int)]] = {
|
||||
import reactivemongo.bson._
|
||||
import reactivemongo.core.commands._
|
||||
|
|
|
@ -5,7 +5,6 @@ import scala.concurrent.duration._
|
|||
import akka.actor._
|
||||
import akka.pattern.{ ask, pipe }
|
||||
import chess.Color
|
||||
import makeTimeout.short
|
||||
import play.api.libs.json.{ JsObject, Json }
|
||||
|
||||
import actorApi._, round._
|
||||
|
@ -16,6 +15,7 @@ import lila.security.Flood
|
|||
import lila.socket.actorApi.{ Connected ⇒ _, _ }
|
||||
import lila.socket.Handler
|
||||
import lila.user.{ User, Context }
|
||||
import makeTimeout.short
|
||||
|
||||
private[round] final class SocketHandler(
|
||||
roundMap: ActorRef,
|
||||
|
@ -78,6 +78,9 @@ private[round] final class SocketHandler(
|
|||
case ("challenge", o) ⇒ ((o str "d") |@| member.userId).tupled foreach {
|
||||
case (to, from) ⇒ hub.actor.challenger ! lila.hub.actorApi.setup.RemindChallenge(gameId, from, to)
|
||||
}
|
||||
case ("liveGames", o) ⇒ o str "d" foreach { ids ⇒
|
||||
socket ! LiveGames(uid, ids.split(' ').toList)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ final class SocketHub extends Actor {
|
|||
|
||||
private val sockets = collection.mutable.Set[ActorRef]()
|
||||
|
||||
context.system.lilaBus.subscribe(self,
|
||||
'moveEvent, 'users, 'deploy, 'nbMembers, 'socket,
|
||||
context.system.lilaBus.subscribe(self,
|
||||
'moveEvent, 'users, 'deploy, 'nbMembers, 'socket,
|
||||
// FIXME this event only concern the current TV room
|
||||
'changeFeaturedGame)
|
||||
|
||||
|
|
|
@ -42,7 +42,13 @@ var storage = {
|
|||
//////////////////
|
||||
|
||||
var strongSocketDefaults = {
|
||||
events: {},
|
||||
events: {
|
||||
fen: function(e) {
|
||||
$('a.live_' + e.id).each(function() {
|
||||
parseFen($(this).data("fen", e.fen).data("lastmove", e.lm));
|
||||
});
|
||||
}
|
||||
},
|
||||
params: {
|
||||
sri: lichess_sri
|
||||
},
|
||||
|
@ -498,6 +504,7 @@ var storage = {
|
|||
url: $(this).attr('href') + '/mini',
|
||||
success: function(html) {
|
||||
$('#powerTip').html(html);
|
||||
$('body').trigger('lichess.content_loaded');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1739,93 +1746,93 @@ var storage = {
|
|||
// gamelist.js //
|
||||
/////////////////
|
||||
|
||||
$(function() {
|
||||
|
||||
function parseFen($elem) {
|
||||
if (!$elem || !$elem.jquery) {
|
||||
$elem = $('.parse_fen');
|
||||
}
|
||||
$elem.each(function() {
|
||||
var $this = $(this);
|
||||
var color = $this.data('color') || "white";
|
||||
var withKeys = $this.hasClass('with_keys');
|
||||
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
|
||||
var fen = $this.data('fen').split(' ')[0].replace(/\//g, '');
|
||||
var lm = $this.data('lastmove');
|
||||
var lastMove = lm ? [lm[0] + lm[1], lm[2] + lm[3]] : [];
|
||||
var x, y, html = '',
|
||||
scolor, pcolor, pclass, c, d, increment;
|
||||
var pclasses = {
|
||||
'p': 'pawn',
|
||||
'r': 'rook',
|
||||
'n': 'knight',
|
||||
'b': 'bishop',
|
||||
'q': 'queen',
|
||||
'k': 'king'
|
||||
};
|
||||
var pregex = /(p|r|n|b|q|k)/;
|
||||
|
||||
if ('white' == color) {
|
||||
x = 8;
|
||||
y = 1;
|
||||
increment = function() {
|
||||
y++;
|
||||
if (y > 8) {
|
||||
y = 1;
|
||||
x--;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
x = 1;
|
||||
y = 8;
|
||||
increment = function() {
|
||||
y--;
|
||||
if (y < 1) {
|
||||
y = 8;
|
||||
x++;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function openSquare(x, y) {
|
||||
var key = 'white' == color ? letters[y - 1] + x : letters[8 - y] + (9 - x);
|
||||
var scolor = (x + y) % 2 ? 'white' : 'black';
|
||||
if ($.inArray(key, lastMove) != -1) scolor += " moved";
|
||||
var html = '<div class="lmcs ' + scolor + '" style="top:' + (28 * (8 - x)) + 'px;left:' + (28 * (y - 1)) + 'px;"';
|
||||
if (withKeys) {
|
||||
html += ' data-key="' + key + '"';
|
||||
}
|
||||
return html + '>';
|
||||
}
|
||||
|
||||
function closeSquare() {
|
||||
return '</div>';
|
||||
}
|
||||
|
||||
for (var fenIndex in fen) {
|
||||
c = fen[fenIndex];
|
||||
html += openSquare(x, y);
|
||||
if (!isNaN(c)) { // it is numeric
|
||||
html += closeSquare();
|
||||
increment();
|
||||
for (d = 1; d < c; d++) {
|
||||
html += openSquare(x, y) + closeSquare();
|
||||
increment();
|
||||
}
|
||||
} else {
|
||||
pcolor = pregex.test(c) ? 'black' : 'white';
|
||||
pclass = pclasses[c.toLowerCase()];
|
||||
html += '<div class="lcmp ' + pclass + ' ' + pcolor + '"></div>';
|
||||
html += closeSquare();
|
||||
increment();
|
||||
}
|
||||
}
|
||||
|
||||
$this.html(html).removeClass('parse_fen');
|
||||
// attempt to free memory
|
||||
html = pclasses = increment = pregex = fen = $this = 0;
|
||||
});
|
||||
function parseFen($elem) {
|
||||
if (!$elem || !$elem.jquery) {
|
||||
$elem = $('.parse_fen');
|
||||
}
|
||||
$elem.each(function() {
|
||||
var $this = $(this);
|
||||
var color = $this.data('color') || "white";
|
||||
var withKeys = $this.hasClass('with_keys');
|
||||
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
|
||||
var fen = $this.data('fen').split(' ')[0].replace(/\//g, '');
|
||||
var lm = $this.data('lastmove');
|
||||
var lastMove = lm ? [lm[0] + lm[1], lm[2] + lm[3]] : [];
|
||||
var x, y, html = '',
|
||||
scolor, pcolor, pclass, c, d, increment;
|
||||
var pclasses = {
|
||||
'p': 'pawn',
|
||||
'r': 'rook',
|
||||
'n': 'knight',
|
||||
'b': 'bishop',
|
||||
'q': 'queen',
|
||||
'k': 'king'
|
||||
};
|
||||
var pregex = /(p|r|n|b|q|k)/;
|
||||
|
||||
if ('white' == color) {
|
||||
x = 8;
|
||||
y = 1;
|
||||
increment = function() {
|
||||
y++;
|
||||
if (y > 8) {
|
||||
y = 1;
|
||||
x--;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
x = 1;
|
||||
y = 8;
|
||||
increment = function() {
|
||||
y--;
|
||||
if (y < 1) {
|
||||
y = 8;
|
||||
x++;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function openSquare(x, y) {
|
||||
var key = 'white' == color ? letters[y - 1] + x : letters[8 - y] + (9 - x);
|
||||
var scolor = (x + y) % 2 ? 'white' : 'black';
|
||||
if ($.inArray(key, lastMove) != -1) scolor += " moved";
|
||||
var html = '<div class="lmcs ' + scolor + '" style="top:' + (28 * (8 - x)) + 'px;left:' + (28 * (y - 1)) + 'px;"';
|
||||
if (withKeys) {
|
||||
html += ' data-key="' + key + '"';
|
||||
}
|
||||
return html + '>';
|
||||
}
|
||||
|
||||
function closeSquare() {
|
||||
return '</div>';
|
||||
}
|
||||
|
||||
for (var fenIndex in fen) {
|
||||
c = fen[fenIndex];
|
||||
html += openSquare(x, y);
|
||||
if (!isNaN(c)) { // it is numeric
|
||||
html += closeSquare();
|
||||
increment();
|
||||
for (d = 1; d < c; d++) {
|
||||
html += openSquare(x, y) + closeSquare();
|
||||
increment();
|
||||
}
|
||||
} else {
|
||||
pcolor = pregex.test(c) ? 'black' : 'white';
|
||||
pclass = pclasses[c.toLowerCase()];
|
||||
html += '<div class="lcmp ' + pclass + ' ' + pcolor + '"></div>';
|
||||
html += closeSquare();
|
||||
increment();
|
||||
}
|
||||
}
|
||||
|
||||
$this.html(html).removeClass('parse_fen');
|
||||
// attempt to free memory
|
||||
html = pclasses = increment = pregex = fen = $this = 0;
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
parseFen();
|
||||
$('body').on('lichess.content_loaded', parseFen);
|
||||
|
||||
|
@ -1847,13 +1854,6 @@ var storage = {
|
|||
registerLiveGames();
|
||||
});
|
||||
|
||||
lichess.socketDefaults.events.fen = function(e) {
|
||||
$('a.live_' + e.id).each(function() {
|
||||
var $this = $(this);
|
||||
parseFen($this.data("fen", e.fen).data("lastmove", e.lm));
|
||||
});
|
||||
};
|
||||
|
||||
$('div.checkmateCaptcha').each(function() {
|
||||
var $captcha = $(this);
|
||||
var color = $captcha.find('.mini_board').data('color');
|
||||
|
|
Loading…
Reference in New Issue