anonymous dasher + zoom improvements

dasher
Thibault Duplessis 2017-05-05 12:04:25 +02:00
parent 65631b165c
commit c2dd3db2d6
10 changed files with 152 additions and 128 deletions

View File

@ -1,79 +1,83 @@
package controllers
import play.api.libs.json._
import play.api.mvc._
import scala.collection.breakOut
import lila.api.Context
import lila.app._
import lila.common.LightUser.lightUserWrites
import lila.pref.JsonView._
import play.api.libs.json._
object Dasher extends LilaController {
private def translations(implicit ctx: Context) = Env.i18n.jsDump.keysToObject(List(
Env.i18n.keys.profile,
Env.i18n.keys.inbox,
Env.i18n.keys.preferences,
Env.i18n.keys.logOut,
Env.i18n.keys.networkLagBetweenYouAndLichess,
Env.i18n.keys.timeToProcessAMoveOnLichessServer,
Env.i18n.keys.sound
), Env.i18n.pool lang ctx.req)
private def translations(implicit ctx: Context) = Env.i18n.jsDump.keysToObject(
ctx.isAnon.fold(
List(
Env.i18n.keys.signIn,
Env.i18n.keys.signUp
),
List(
Env.i18n.keys.profile,
Env.i18n.keys.inbox,
Env.i18n.keys.preferences,
Env.i18n.keys.logOut
)
) ::: List(
Env.i18n.keys.networkLagBetweenYouAndLichess,
Env.i18n.keys.timeToProcessAMoveOnLichessServer,
Env.i18n.keys.sound
), Env.i18n.pool lang ctx.req
)
def get = Open { implicit ctx =>
negotiate(
html = notFound,
api = _ => ctx.me match {
case None => fuccess(unauthorizedApiResult)
case Some(me) => Env.pref.api.getPref(me) map { prefs =>
Ok {
Json.obj(
"user" -> lila.common.LightUser.lightUserWrites.writes(me.light),
"lang" -> Json.obj(
"current" -> Env.i18n.pool.lang(ctx.req).language.toString,
"accepted" -> (ctx.req.acceptLanguages.map(_.language.toString)(breakOut): List[String]).distinct
),
"sound" -> Json.obj(
"list" -> lila.pref.SoundSet.list.map { set =>
s"${set.key} ${set.name}"
}
),
"background" -> Json.obj(
"current" -> ctx.currentBg,
"image" -> ctx.bgImg
),
"board" -> Json.obj(
"is3d" -> ctx.is3d,
"zoom" -> ctx.zoom
),
"theme" -> Json.obj(
"d2" -> Json.obj(
"current" -> ctx.currentTheme.name,
"list" -> lila.pref.Theme.list.map(_.name)
),
"d3" -> Json.obj(
"current" -> ctx.currentTheme3d.name,
"list" -> lila.pref.Theme3d.list.map(_.name)
)
),
"piece" -> Json.obj(
"d2" -> Json.obj(
"current" -> ctx.currentPieceSet.name,
"list" -> lila.pref.PieceSet.list.map(_.name)
),
"d3" -> Json.obj(
"current" -> ctx.currentPieceSet3d.name,
"list" -> lila.pref.PieceSet3d.list.map(_.name)
)
),
"kid" -> me.kid,
"coach" -> isGranted(_.Coach),
"prefs" -> prefs,
"i18n" -> translations
api = _ => Ok {
Json.obj(
"user" -> ctx.me.map(_.light),
"lang" -> Json.obj(
"current" -> Env.i18n.pool.lang(ctx.req).language.toString,
"accepted" -> (ctx.req.acceptLanguages.map(_.language.toString)(breakOut): List[String]).distinct
),
"sound" -> Json.obj(
"list" -> lila.pref.SoundSet.list.map { set =>
s"${set.key} ${set.name}"
}
),
"background" -> Json.obj(
"current" -> ctx.currentBg,
"image" -> ctx.bgImg
),
"board" -> Json.obj(
"is3d" -> ctx.is3d,
"zoom" -> ctx.zoom
),
"theme" -> Json.obj(
"d2" -> Json.obj(
"current" -> ctx.currentTheme.name,
"list" -> lila.pref.Theme.list.map(_.name)
),
"d3" -> Json.obj(
"current" -> ctx.currentTheme3d.name,
"list" -> lila.pref.Theme3d.list.map(_.name)
)
}
}
}
),
"piece" -> Json.obj(
"d2" -> Json.obj(
"current" -> ctx.currentPieceSet.name,
"list" -> lila.pref.PieceSet.list.map(_.name)
),
"d3" -> Json.obj(
"current" -> ctx.currentPieceSet3d.name,
"list" -> lila.pref.PieceSet3d.list.map(_.name)
)
),
"kid" -> ctx.me ?? (_.kid),
"coach" -> isGranted(_.Coach),
"i18n" -> translations
)
} fuccess
)
}
}

View File

@ -86,9 +86,9 @@ asyncJs: Boolean = false)(body: Html)(implicit ctx: Context)
<div id="hamburger" data-icon="["></div>
</div>
@ctx.me.map { me =>
<div class="auth">
<a id="user_tag" class="toggle toggle_auth link">@me.username</a>
<div id="dasher_app" class="links dropdown" data-playing="@playing">
<div class="dasher">
<a id="user_tag" class="toggle link">@me.username</a>
<div id="dasher_app" class="dropdown" data-playing="@playing">
<div class="initiating">@base.spinner()</div>
</div>
</div>
@ -98,7 +98,7 @@ asyncJs: Boolean = false)(body: Html)(implicit ctx: Context)
<span data-icon="U"></span>
</span>
</a>
<div id="challenge_app" class="links dropdown">
<div id="challenge_app" class="dropdown">
<div class="initiating">@base.spinner()</div>
</div>
</div>
@ -108,11 +108,21 @@ asyncJs: Boolean = false)(body: Html)(implicit ctx: Context)
<span data-icon=""></span>
</span>
</a>
<div id="notify_app" class="links dropdown">
<div id="notify_app" class="dropdown">
<div class="initiating">@base.spinner()</div>
</div>
</div>
}.getOrElse {
<div class="dasher">
<a class="toggle anon">
<span class="hint--bottom-left" data-hint="@trans.preferences()">
<span data-icon="%"></span>
</span>
</a>
<div id="dasher_app" class="dropdown" data-playing="@playing">
<div class="initiating">@base.spinner()</div>
</div>
</div>
<a href="@routes.Auth.login" class="signin button text">@trans.signIn()</a>
}
@if(!zen) {

View File

@ -181,5 +181,5 @@ $(function() {
}, 1000);
});
});
lichess.pubsub.emit('set_zoom')();
lichess.pubsub.emit('reset_zoom')();
});

View File

@ -459,6 +459,10 @@ body > div.content {
line-height: 24px;
padding: 0 8px;
}
#top .dasher .anon {
font-size: 16px;
padding: 0 7px;
}
#top > * {
position: relative;
}

View File

@ -267,7 +267,7 @@ module.exports = function(ctrl) {
m('div', {
config: function(el, isUpdate) {
if (firstRender) firstRender = false;
else if (!isUpdate) lichess.pubsub.emit('set_zoom')();
else if (!isUpdate) lichess.pubsub.emit('reset_zoom')();
},
class: classSet({
'gauge_displayed': ctrl.showEvalGauge(),

View File

@ -15,28 +15,26 @@ export interface BoardData {
zoom: number
}
export function ctrl(data: BoardData, redraw: Redraw, close: Close): BoardCtrl {
export type PublishZoom = (v: number) => void;
export function ctrl(data: BoardData, publishZoom: PublishZoom, redraw: Redraw, close: Close): BoardCtrl {
const saveZoom = window.lichess.fp.debounce(() => {
$.ajax({ method: 'post', url: '/pref/zoom?v=' + data.zoom });
}, 500);
function publishZoom() {
window.lichess.pubsub.emit('set_zoom')(data.zoom / 100);
}
return {
data,
setIs3d(v: boolean) {
data.is3d = v;
$.post('/pref/is3d', { is3d: v }, window.lichess.reloadOtherTabs);
applyDimension(v);
publishZoom();
publishZoom(data.zoom / 100);
redraw();
},
setZoom(v: number) {
data.zoom = v;
publishZoom();
publishZoom(v / 100);
saveZoom();
},
close

View File

@ -2,14 +2,14 @@ import { PingCtrl, ctrl as pingCtrl } from './ping'
import { LangsCtrl, ctrl as langsCtrl } from './langs'
import { SoundCtrl, ctrl as soundCtrl } from './sound'
import { BackgroundCtrl, BackgroundData, ctrl as backgroundCtrl } from './background'
import { BoardCtrl, BoardData, ctrl as boardCtrl } from './board'
import { BoardCtrl, BoardData, PublishZoom, ctrl as boardCtrl } from './board'
import { ThemeCtrl, ThemeData, ctrl as themeCtrl } from './theme'
import { PieceCtrl, PieceData, ctrl as pieceCtrl } from './piece'
import { Redraw, Prop, prop } from './util'
import { get } from './xhr'
export interface DasherData {
user: LightUser
user?: LightUser
lang: {
current: string
accepted: string[]
@ -47,7 +47,8 @@ export type Mode = 'links' | 'langs' | 'sound' | 'background' | 'board' | 'theme
}
export interface DasherOpts {
playing: boolean
playing: boolean,
setZoom: PublishZoom
}
export function makeCtrl(opts: DasherOpts, data: DasherData, redraw: Redraw): DasherCtrl {
@ -68,7 +69,7 @@ export type Mode = 'links' | 'langs' | 'sound' | 'background' | 'board' | 'theme
langs: langsCtrl(data.lang, redraw, close),
sound: soundCtrl(data.sound.list, trans, redraw, close),
background: backgroundCtrl(data.background, redraw, close),
board: boardCtrl(data.board, redraw, close),
board: boardCtrl(data.board, opts.setZoom, redraw, close),
theme: themeCtrl(data.theme, () => data.board.is3d ? 'd3' : 'd2', redraw, setMode),
piece: pieceCtrl(data.piece, () => data.board.is3d ? 'd3' : 'd2', redraw, setMode)
};

View File

@ -9,30 +9,45 @@ export default function(ctrl: DasherCtrl): VNode {
const d = ctrl.data, trans = ctrl.trans;
const profile = h(
'a.user_link.online.text.is-green',
linkCfg(`/@/${d.user.name}`, d.user.patron ? '' : ''),
trans.noarg('profile'));
function userLinks(): Array<VNode | null> | null {
return d.user ? [
h(
'a.user_link.online.text.is-green',
linkCfg(`/@/${d.user.name}`, d.user.patron ? '' : ''),
trans.noarg('profile')),
const inbox = d.kid ? null : h(
'a.text',
linkCfg('/inbox', 'e'),
trans.noarg('inbox'));
d.kid ? null : h(
'a.text',
linkCfg('/inbox', 'e'),
trans.noarg('inbox')),
const prefs = h(
'a.text',
linkCfg('/account/preferences/game-display', '%', ctrl.opts.playing ? {target: '_blank'} : undefined),
trans.noarg('preferences'));
h(
'a.text',
linkCfg('/account/preferences/game-display', '%', ctrl.opts.playing ? {target: '_blank'} : undefined),
trans.noarg('preferences')),
const coach = !d.coach ? null : h(
'a.text',
linkCfg('/coach/edit', ':'),
'Coach manager');
!d.coach ? null : h(
'a.text',
linkCfg('/coach/edit', ':'),
'Coach manager'),
const logout = h(
'a.text',
linkCfg('/logout', 'w'),
trans.noarg('logOut'));
h(
'a.text',
linkCfg('/logout', 'w'),
trans.noarg('logOut'))
] : null;
}
function anonLinks() {
return [
h('a.text',
linkCfg('/login', 'E'),
trans('signIn')),
h('a.text',
linkCfg('/signup', 'F'),
trans('signUp'))
];
}
const langs = h(
'a.sub',
@ -65,13 +80,7 @@ export default function(ctrl: DasherCtrl): VNode {
'Piece set')
return h('div', [
h('div.links', [
profile,
inbox,
prefs,
coach,
logout
]),
h('div.links', userLinks() || anonLinks()),
h('div.subs', [
langs,
sound,

View File

@ -100,7 +100,7 @@ module.exports = function(ctrl) {
m('div', {
config: function(el, isUpdate) {
if (firstRender) firstRender = false;
else if (!isUpdate) lichess.pubsub.emit('set_zoom')();
else if (!isUpdate) lichess.pubsub.emit('reset_zoom')();
},
class: ctrl.showEvalGauge() ? 'gauge_displayed' : ''
}, [

View File

@ -371,25 +371,6 @@ lichess.topMenuIntent = function() {
if (lichess.socket === null) lichess.socket = lichess.StrongSocket("/socket", false);
}, 300);
lichess.dasherApp = (function() {
var instance, booted;
var $toggle = $('#user_tag');
$toggle.one('mouseover click', function() { load(); });
var load = function() {
if (booted) return;
booted = true;
var isDev = $('body').data('dev');
var $el = $('#dasher_app');
lichess.loadCss('/assets/stylesheets/dasherApp.css');
lichess.loadScript("/assets/compiled/lichess.dasher" + (isDev ? '' : '.min') + '.js').done(function() {
instance = LichessDasher.default($el.empty()[0], {
playing: $el.data('playing')
});
});
};
if ($('body').data('dev')) setTimeout(function() { $toggle.click(); }, 100);
})();
lichess.challengeApp = (function() {
var instance, booted;
var $toggle = $('#challenge_notifications_tag');
@ -527,11 +508,28 @@ lichess.topMenuIntent = function() {
document.body.dispatchEvent(new Event('chessground.resize'));
};
lichess.pubsub.on('set_zoom', function(v) {
if (!v) setZoom(currentZoom);
else if (v > 1 || $('body').data('zoom') > 100) setZoom(v);
lichess.pubsub.on('reset_zoom', function() {
if (currentZoom > 1 || $('body').data('zoom') > 100) setZoom(currentZoom);
});
// dasher
(function() {
var booted;
$('#top .dasher .toggle').one('mouseover click', function() {
if (booted) return;
booted = true;
var isDev = $('body').data('dev');
var $el = $('#dasher_app');
lichess.loadCss('/assets/stylesheets/dasherApp.css');
lichess.loadScript("/assets/compiled/lichess.dasher" + (isDev ? '' : '.min') + '.js').done(function() {
instance = LichessDasher.default($el.empty()[0], {
setZoom: setZoom,
playing: $el.data('playing')
});
});
});
})();
function translateTexts() {
$('.trans_me').each(function() {
var t = $(this).removeClass('trans_me');