dasher theme selector

This commit is contained in:
Thibault Duplessis 2017-05-04 18:51:28 +02:00
parent bf06fd91cf
commit d7d625baee
12 changed files with 270 additions and 137 deletions

View file

@ -46,6 +46,20 @@ object Dasher extends LilaController {
"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" -> ctx.currentPieceSet.name,
"d3" -> ctx.currentPieceSet3d.name
),
"kid" -> me.kid,
"coach" -> isGranted(_.Coach),
"prefs" -> prefs,

View file

@ -168,6 +168,152 @@
margin-top: 10px;
}
#dasher_app .theme .list {
margin: 5px 0;
display: flex;
flex-flow: row wrap;
}
#dasher_app .theme .list a {
flex: 0 0 50%;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
#dasher_app .theme .list span {
display: block;
width: 64px;
height: 32px;
box-sizing: border-box;
}
#dasher_app .theme.d3 .list span {
width: 66px;
height: 30px;
transition: transform 0.3s;
}
#dasher_app .theme .list a:hover {
filter: brightness(1.1);
}
#dasher_app .theme .list a:hover span {
transform: scale(1.05);
}
#dasher_app .theme .list a.active {
background: #3893E8;
}
#dasher_app .theme.d2 .blue {
background-image: url(../images/board/svg/blue.svg);
background-size: 256px;
}
#dasher_app .theme.d2 .blue2 {
background-image: url(../images/board/blue2.thumbnail.jpg);
}
#dasher_app .theme.d2 .wood2 {
background-image: url(../images/board/wood2.thumbnail.jpg);
}
#dasher_app .theme.d2 .wood3 {
background-image: url(../images/board/wood3.thumbnail.jpg);
}
#dasher_app .theme.d2 .blue3 {
background-image: url(../images/board/blue3.thumbnail.jpg);
}
#dasher_app .theme.d2 .marble {
background-image: url(../images/board/marble.thumbnail.jpg);
}
#dasher_app .theme.d2 .brown {
background-image: url(../images/board/svg/brown.svg);
background-size: 256px;
}
#dasher_app .theme.d2 .green {
background-image: url(../images/board/svg/green.svg);
background-size: 256px;
}
#dasher_app .theme.d2 .olive {
background-image: url(../images/board/olive.thumbnail.jpg);
}
#dasher_app .theme.d2 .purple {
background-image: url(../images/board/svg/purple.svg);
background-size: 256px;
}
#dasher_app .theme.d2 .grey {
background-image: url(../images/board/grey.thumbnail.jpg);
}
#dasher_app .theme.d2 .wood {
background-image: url(../images/board/wood.thumbnail.jpg);
}
#dasher_app .theme.d2 .canvas {
background-image: url(../images/board/canvas2.thumbnail.jpg);
}
#dasher_app .theme.d2 .leather {
background-image: url(../images/board/leather.thumbnail.jpg);
}
#dasher_app .theme.d2 .metal {
background-image: url(../images/board/metal.thumbnail.jpg);
}
#dasher_app .theme.d2 .maple {
background-image: url(../images/board/maple.thumbnail.jpg);
}
#dasher_app .theme.d3 .Black-White-Aluminium {
background-image: url(../images/staunton/board/Black-White-Aluminium.thumbnail.png);
}
#dasher_app .theme.d3 .Brushed-Aluminium {
background-image: url(../images/staunton/board/Brushed-Aluminium.thumbnail.png);
}
#dasher_app .theme.d3 .China-Blue {
background-image: url(../images/staunton/board/China-Blue.thumbnail.png);
}
#dasher_app .theme.d3 .China-Green {
background-image: url(../images/staunton/board/China-Green.thumbnail.png);
}
#dasher_app .theme.d3 .China-Grey {
background-image: url(../images/staunton/board/China-Grey.thumbnail.png);
}
#dasher_app .theme.d3 .China-Scarlet {
background-image: url(../images/staunton/board/China-Scarlet.thumbnail.png);
}
#dasher_app .theme.d3 .China-Yellow {
background-image: url(../images/staunton/board/China-Yellow.thumbnail.png);
}
#dasher_app .theme.d3 .Classic-Blue {
background-image: url(../images/staunton/board/Classic-Blue.thumbnail.png);
}
#dasher_app .theme.d3 .Transparent-Glass {
background-image: url(../images/staunton/board/Glass.thumbnail.png);
}
#dasher_app .theme.d3 .Gold-Silver {
background-image: url(../images/staunton/board/Gold-Silver.thumbnail.png);
}
#dasher_app .theme.d3 .Green-Glass {
background-image: url(../images/staunton/board/Green-Glass.thumbnail.png);
}
#dasher_app .theme.d3 .Light-Wood {
background-image: url(../images/staunton/board/Light-Wood.thumbnail.png);
}
#dasher_app .theme.d3 .Power-Coated {
background-image: url(../images/staunton/board/Power-Coated.thumbnail.png);
}
#dasher_app .theme.d3 .Purple-Black {
background-image: url(../images/staunton/board/Purple-Black.thumbnail.png);
}
#dasher_app .theme.d3 .Rosewood {
background-image: url(../images/staunton/board/Rosewood.thumbnail.png);
}
#dasher_app .theme.d3 .Wood-Glass {
background-image: url(../images/staunton/board/Wood-Glass.thumbnail.png);
}
#dasher_app .theme.d3 .Wax {
background-image: url(../images/staunton/board/Wax.thumbnail.png);
}
#dasher_app .theme.d3 .Jade {
background-image: url(../images/staunton/board/Jade.thumbnail.png);
}
#dasher_app .theme.d3 .Marble {
background-image: url(../images/board/3d/marble.thumbnail.png);
}
#dasher_app .theme.d3 .Woodi {
background-image: url(../images/board/3d/woodi.thumbnail.png);
}
body.dark #dasher_app .subs,
body.dark #dasher_app .status {
border-color: #3d3d3d;

View file

@ -167,116 +167,4 @@ body.transp #themepicker input.background_image {
background-image: url(../piece/companion/wN.svg);
}
#top div.color_demo.blue {
background-image: url(../images/board/svg/blue.svg);
background-size: 256px;
}
#top div.color_demo.blue2 {
background-image: url(../images/board/blue2.thumbnail.jpg);
}
#top div.color_demo.wood2 {
background-image: url(../images/board/wood2.thumbnail.jpg);
}
#top div.color_demo.wood3 {
background-image: url(../images/board/wood3.thumbnail.jpg);
}
#top div.color_demo.blue3 {
background-image: url(../images/board/blue3.thumbnail.jpg);
}
#top div.color_demo.marble {
background-image: url(../images/board/marble.thumbnail.jpg);
}
#top div.color_demo.brown {
background-image: url(../images/board/svg/brown.svg);
background-size: 256px;
}
#top div.color_demo.green {
background-image: url(../images/board/svg/green.svg);
background-size: 256px;
}
#top div.color_demo.olive {
background-image: url(../images/board/olive.thumbnail.jpg);
}
#top div.color_demo.purple {
background-image: url(../images/board/svg/purple.svg);
background-size: 256px;
}
#top div.color_demo.grey {
background-image: url(../images/board/grey.thumbnail.jpg);
}
#top div.color_demo.wood {
background-image: url(../images/board/wood.thumbnail.jpg);
}
#top div.color_demo.canvas {
background-image: url(../images/board/canvas2.thumbnail.jpg);
}
#top div.color_demo.leather {
background-image: url(../images/board/leather.thumbnail.jpg);
}
#top div.color_demo.metal {
background-image: url(../images/board/metal.thumbnail.jpg);
}
#top div.color_demo.maple {
background-image: url(../images/board/maple.thumbnail.jpg);
}
#top .is3d .Black-White-Aluminium {
background-image: url(../images/staunton/board/Black-White-Aluminium.thumbnail.png);
}
#top .is3d .Brushed-Aluminium {
background-image: url(../images/staunton/board/Brushed-Aluminium.thumbnail.png);
}
#top .is3d .China-Blue {
background-image: url(../images/staunton/board/China-Blue.thumbnail.png);
}
#top .is3d .China-Green {
background-image: url(../images/staunton/board/China-Green.thumbnail.png);
}
#top .is3d .China-Grey {
background-image: url(../images/staunton/board/China-Grey.thumbnail.png);
}
#top .is3d .China-Scarlet {
background-image: url(../images/staunton/board/China-Scarlet.thumbnail.png);
}
#top .is3d .China-Yellow {
background-image: url(../images/staunton/board/China-Yellow.thumbnail.png);
}
#top .is3d .Classic-Blue {
background-image: url(../images/staunton/board/Classic-Blue.thumbnail.png);
}
#top .is3d .Transparent-Glass {
background-image: url(../images/staunton/board/Glass.thumbnail.png);
}
#top .is3d .Gold-Silver {
background-image: url(../images/staunton/board/Gold-Silver.thumbnail.png);
}
#top .is3d .Green-Glass {
background-image: url(../images/staunton/board/Green-Glass.thumbnail.png);
}
#top .is3d .Light-Wood {
background-image: url(../images/staunton/board/Light-Wood.thumbnail.png);
}
#top .is3d .Power-Coated {
background-image: url(../images/staunton/board/Power-Coated.thumbnail.png);
}
#top .is3d .Purple-Black {
background-image: url(../images/staunton/board/Purple-Black.thumbnail.png);
}
#top .is3d .Rosewood {
background-image: url(../images/staunton/board/Rosewood.thumbnail.png);
}
#top .is3d .Wood-Glass {
background-image: url(../images/staunton/board/Wood-Glass.thumbnail.png);
}
#top .is3d .Wax {
background-image: url(../images/staunton/board/Wax.thumbnail.png);
}
#top .is3d .Jade {
background-image: url(../images/staunton/board/Jade.thumbnail.png);
}
#top .is3d .Marble {
background-image: url(../images/board/3d/marble.thumbnail.png);
}
#top .is3d .Woodi {
background-image: url(../images/board/3d/woodi.thumbnail.png);
}

View file

@ -1,7 +1,7 @@
import { h } from 'snabbdom'
import { VNode } from 'snabbdom/vnode'
import { Redraw, Close, bind } from './util'
import { Redraw, Close, bind, header } from './util'
export interface BackgroundCtrl {
list: Background[]
@ -56,10 +56,7 @@ export function view(ctrl: BackgroundCtrl): VNode {
const cur = ctrl.get();
return h('div.sub.background', [
h('a.head.text', {
attrs: { 'data-icon': 'I' },
hook: bind('click', ctrl.close)
}, 'Background'),
header('Background', ctrl.close),
h('div.selector', ctrl.list.map(bg => {
return h('a.text', {
class: { active: cur === bg.key },

View file

@ -21,17 +21,22 @@ export function ctrl(data: BoardData, redraw: Redraw, close: Close): BoardCtrl {
$.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();
redraw();
},
setZoom(v: number) {
data.zoom = v;
window.lichess.pubsub.emit('set_zoom')(v / 100);
publishZoom();
saveZoom();
},
close
@ -89,6 +94,4 @@ function applyDimension(is3d: boolean) {
$(this).attr('href', $(this).attr('href').replace(/board\.css/, 'board-3d.css')).appendTo('head');
});
}
window.lichess.pubsub.emit('set_zoom')();
}

View file

@ -3,6 +3,7 @@ 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 { ThemeCtrl, ThemeData, ctrl as themeCtrl } from './theme'
import { Redraw, Prop, prop } from './util'
import { get } from './xhr'
@ -17,13 +18,14 @@ export interface DasherData {
}
background: BackgroundData
board: BoardData
theme: ThemeData
kid: boolean
coach: boolean
prefs: any
i18n: any
}
export type Mode = 'links' | 'langs' | 'sound' | 'background' | 'board'
export type Mode = 'links' | 'langs' | 'sound' | 'background' | 'board' | 'theme'
export interface DasherCtrl {
mode: Prop<Mode>
@ -35,7 +37,8 @@ export type Mode = 'links' | 'langs' | 'sound' | 'background' | 'board'
langs: LangsCtrl
sound: SoundCtrl
background: BackgroundCtrl,
board: BoardCtrl
board: BoardCtrl,
theme: ThemeCtrl
}
opts: DasherOpts
}
@ -48,7 +51,7 @@ export type Mode = 'links' | 'langs' | 'sound' | 'background' | 'board'
const trans = window.lichess.trans(data.i18n);
let mode: Prop<Mode> = prop('board' as Mode);
let mode: Prop<Mode> = prop('theme' as Mode);
function setMode(m: Mode) {
mode(m);
@ -62,7 +65,8 @@ export type Mode = 'links' | 'langs' | 'sound' | 'background' | 'board'
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, redraw, close),
theme: themeCtrl(data.theme, () => data.board.is3d ? 'd3' : 'd2', redraw, close)
};
return {

View file

@ -1,7 +1,7 @@
import { h } from 'snabbdom'
import { VNode } from 'snabbdom/vnode'
import { Redraw, Close, spinner, bind } from './util'
import { Redraw, Close, spinner, bind, header } from './util'
import { get } from './xhr'
export interface Lang {
@ -52,10 +52,7 @@ export function view(ctrl: LangsCtrl): VNode {
if (!list) ctrl.load();
return h('div.sub.langs', [
h('a.head.text', {
attrs: { 'data-icon': 'I' },
hook: bind('click', ctrl.close)
}, 'Language'),
header('Language', ctrl.close),
list ? h('form', {
attrs: { method: 'post', action: '/translation/select' }
}, langLinks(ctrl, list)) : spinner()

View file

@ -54,6 +54,11 @@ export default function(ctrl: DasherCtrl): VNode {
modeCfg(ctrl, 'board'),
'Chess board')
const theme = h(
'a.sub',
modeCfg(ctrl, 'theme'),
'Theme')
return h('div', [
h('div.links', [
profile,
@ -66,7 +71,8 @@ export default function(ctrl: DasherCtrl): VNode {
langs,
sound,
background,
board
board,
theme
]),
pingView(ctrl.ping)
]);

View file

@ -1,7 +1,7 @@
import { h } from 'snabbdom'
import { VNode } from 'snabbdom/vnode'
import { Redraw, Close, bind } from './util'
import { Redraw, Close, bind, header } from './util'
type Key = string;
type Name = string;
@ -51,10 +51,7 @@ export function view(ctrl: SoundCtrl): VNode {
return h('div.sub.sound', {
class: { [ctrl.api.set()]: true }
}, [
h('a.head.text', {
attrs: { 'data-icon': 'I' },
hook: bind('click', ctrl.close)
}, ctrl.trans('sound')),
header(ctrl.trans('sound'), ctrl.close),
h('div.content', [
h('div.slider', { hook: { insert: vn => makeSlider(ctrl, vn) } }),
h('div.selector', {

70
ui/dasher/src/theme.ts Normal file
View file

@ -0,0 +1,70 @@
import { h } from 'snabbdom'
import { VNode } from 'snabbdom/vnode'
import { Redraw, Close, bind, header } from './util'
type Theme = string;
interface ThemeDimData {
current: Theme
list: Theme[]
}
export interface ThemeData {
d2: ThemeDimData
d3: ThemeDimData
}
export interface ThemeCtrl {
dimension: () => keyof ThemeData
data: () => ThemeDimData
set(t: Theme): void
close: Close
}
export function ctrl(data: ThemeData, dimension: () => keyof ThemeData, redraw: Redraw, close: Close): ThemeCtrl {
function dimensionData() {
return data[dimension()];
}
return {
dimension,
data: dimensionData,
set(t: Theme) {
const d = dimensionData();
d.current = t;
applyTheme(t, d.list);
$.post('/pref/theme' + (dimension() === 'd3' ? '3d' : ''), {
theme: t
}, window.lichess.reloadOtherTabs);
redraw();
},
close
};
}
export function view(ctrl: ThemeCtrl): VNode {
const d = ctrl.data();
return h('div.sub.theme.' + ctrl.dimension(), [
header('Theme', ctrl.close),
h('div.list', {
attrs: { method: 'post', action: '/pref/soundSet' }
}, d.list.map(themeView(d.current, ctrl.set)))
]);
}
function themeView(current: Theme, set: (t: Theme) => void) {
return (t: Theme) => h('a', {
hook: bind('click', () => set(t)),
class: { active: current === t }
}, [
h('span.' + t)
]);
}
function applyTheme(t: Theme, list: Theme[]) {
$('body').removeClass(list.join(' ')).addClass(t);
}

View file

@ -1,8 +1,8 @@
import { h } from 'snabbdom'
import { VNode } from 'snabbdom/vnode'
export type Redraw = () => void
export type Close = () => void
export type Redraw = () => void;
export type Close = () => void;
export interface Prop<T> {
(): T
@ -36,6 +36,13 @@ export function bind(eventName: string, f: (e: Event) => void, redraw: Redraw |
};
}
export function header(name: string, close: Close) {
return h('a.head.text', {
attrs: { 'data-icon': 'I' },
hook: bind('click', close)
}, name);
}
export function spinner() {
return h('div.spinner', [
h('svg', { attrs: { viewBox: '0 0 40 40' } }, [

View file

@ -7,6 +7,7 @@ import { view as langsView } from './langs'
import { view as soundView } from './sound'
import { view as backgroundView } from './background'
import { view as boardView } from './board'
import { view as themeView } from './theme'
import { spinner } from './util'
export function loading(): VNode {
@ -28,6 +29,9 @@ export function loaded(ctrl: DasherCtrl): VNode {
case 'board':
content = boardView(ctrl.subs.board);
break;
case 'theme':
content = themeView(ctrl.subs.theme);
break;
default:
content = links(ctrl);
}