148 lines
4.1 KiB
TypeScript
148 lines
4.1 KiB
TypeScript
import { h, VNode } from 'snabbdom';
|
|
import { Redraw, Close, bind, header } from './util';
|
|
import debounce from 'common/debounce';
|
|
import * as xhr from 'common/xhr';
|
|
import throttle from 'common/throttle';
|
|
|
|
export interface BackgroundCtrl {
|
|
list: Background[];
|
|
set(k: string): void;
|
|
get(): string;
|
|
getImage(): string;
|
|
setImage(i: string): void;
|
|
trans: Trans;
|
|
close: Close;
|
|
}
|
|
|
|
export interface BackgroundData {
|
|
current: string;
|
|
image: string;
|
|
}
|
|
|
|
interface Background {
|
|
key: string;
|
|
name: string;
|
|
title?: string;
|
|
}
|
|
|
|
export function ctrl(data: BackgroundData, trans: Trans, redraw: Redraw, close: Close): BackgroundCtrl {
|
|
const list: Background[] = [
|
|
{ key: 'light', name: trans.noarg('light') },
|
|
{ key: 'dark', name: trans.noarg('dark') },
|
|
{ key: 'darkBoard', name: 'Dark Board', title: 'Like Dark, but chess boards are also darker' },
|
|
{ key: 'transp', name: trans.noarg('transparent') },
|
|
];
|
|
|
|
const announceFail = () => lichess.announce({ msg: 'Failed to save background preference' });
|
|
|
|
const reloadAllTheThings = () => {
|
|
if (window.Highcharts) lichess.reload();
|
|
};
|
|
|
|
return {
|
|
list,
|
|
trans,
|
|
get: () => data.current,
|
|
set: throttle(700, (c: string) => {
|
|
data.current = c;
|
|
xhr
|
|
.text('/pref/bg', {
|
|
body: xhr.form({ bg: c }),
|
|
method: 'post',
|
|
})
|
|
.then(reloadAllTheThings, announceFail);
|
|
applyBackground(data, list);
|
|
redraw();
|
|
}),
|
|
getImage: () => data.image,
|
|
setImage(i: string) {
|
|
data.image = i;
|
|
xhr
|
|
.text('/pref/bgImg', {
|
|
body: xhr.form({ bgImg: i }),
|
|
method: 'post',
|
|
})
|
|
.then(reloadAllTheThings, announceFail);
|
|
applyBackground(data, list);
|
|
redraw();
|
|
},
|
|
close,
|
|
};
|
|
}
|
|
|
|
export function view(ctrl: BackgroundCtrl): VNode {
|
|
const cur = ctrl.get();
|
|
|
|
return h('div.sub.background', [
|
|
header(ctrl.trans.noarg('background'), ctrl.close),
|
|
h(
|
|
'div.selector.large',
|
|
ctrl.list.map(bg => {
|
|
return h(
|
|
'a.text',
|
|
{
|
|
class: { active: cur === bg.key },
|
|
attrs: { 'data-icon': 'E', title: bg.title || '' },
|
|
hook: bind('click', () => ctrl.set(bg.key)),
|
|
},
|
|
bg.name
|
|
);
|
|
})
|
|
),
|
|
cur === 'transp' ? imageInput(ctrl) : null,
|
|
]);
|
|
}
|
|
|
|
function imageInput(ctrl: BackgroundCtrl) {
|
|
return h('div.image', [
|
|
h('p', ctrl.trans.noarg('backgroundImageUrl')),
|
|
h('input', {
|
|
attrs: {
|
|
type: 'text',
|
|
placeholder: 'https://',
|
|
value: ctrl.getImage(),
|
|
},
|
|
hook: {
|
|
insert: vnode => {
|
|
$(vnode.elm as HTMLElement).on(
|
|
'change keyup paste',
|
|
debounce(function (this: HTMLInputElement) {
|
|
const url = (this.value as string).trim();
|
|
// modules/pref/src/main/PrefForm.scala
|
|
if ((url.startsWith('https://') || url.startsWith('//')) && url.length >= 10 && url.length <= 400)
|
|
ctrl.setImage(url);
|
|
}, 300)
|
|
);
|
|
},
|
|
},
|
|
}),
|
|
]);
|
|
}
|
|
|
|
function applyBackground(data: BackgroundData, list: Background[]) {
|
|
const key = data.current;
|
|
const cls = key == 'transp' ? 'dark transp' : key == 'darkBoard' ? 'dark dark-board' : key;
|
|
|
|
$('body')
|
|
.removeClass([...list.map(b => b.key), 'dark-board'].join(' '))
|
|
.addClass(cls);
|
|
|
|
const prev = $('body').data('theme'),
|
|
sheet = key == 'darkBoard' ? 'dark' : key;
|
|
$('body').data('theme', sheet);
|
|
$('link[href*=".' + prev + '."]').each(function (this: HTMLLinkElement) {
|
|
const link = document.createElement('link') as HTMLLinkElement;
|
|
link.rel = 'stylesheet';
|
|
link.href = this.href.replace('.' + prev + '.', '.' + sheet + '.');
|
|
link.onload = () => setTimeout(() => this.remove(), 100);
|
|
document.head.appendChild(link);
|
|
});
|
|
|
|
if (key === 'transp') {
|
|
const bgData = document.getElementById('bg-data');
|
|
bgData
|
|
? (bgData.innerHTML = 'body.transp::before{background-image:url(' + data.image + ');}')
|
|
: $('head').append('<style id="bg-data">body.transp::before{background-image:url(' + data.image + ');}</style>');
|
|
}
|
|
}
|