lila/ui/tournament/src/ctrl.ts

186 lines
5.4 KiB
TypeScript

import makeSocket from './socket';
import * as xhr from './xhr';
import { myPage, players } from './pagination';
import * as sound from './sound';
import * as tour from './tournament';
import { TournamentData, TournamentOpts, Pages, PlayerInfo, TeamInfo, Standing } from './interfaces';
// eslint-disable-next-line no-duplicate-imports
import { TournamentSocket } from './socket';
interface CtrlTeamInfo {
requested?: string;
loaded?: TeamInfo;
}
export default class TournamentController {
opts: TournamentOpts;
data: TournamentData;
trans: Trans;
socket: TournamentSocket;
page: number;
pages: Pages = {};
lastPageDisplayed: number | undefined;
focusOnMe: boolean;
joinSpinner = false;
playerInfo: PlayerInfo = {};
teamInfo: CtrlTeamInfo = {};
disableClicks = true;
searching = false;
joinWithTeamSelector = false;
redraw: () => void;
private lastStorage = lichess.storage.make('last-redirect');
constructor(opts: TournamentOpts, redraw: () => void) {
this.opts = opts;
this.data = opts.data;
this.redraw = redraw;
this.trans = lichess.trans(opts.i18n);
this.socket = makeSocket(opts.socketSend, this);
this.page = this.data.standing.page;
this.focusOnMe = tour.isIn(this);
setTimeout(() => (this.disableClicks = false), 1500);
this.loadPage(this.data.standing);
this.scrollToMe();
sound.end(this.data);
sound.countDown(this.data);
this.recountTeams();
this.redirectToMyGame();
}
askReload = (): void => {
if (this.joinSpinner) xhr.reloadNow(this);
else xhr.reloadSoon(this);
};
reload = (data: TournamentData): void => {
// we joined a private tournament! Reload the page to load the chat
if (!this.data.me && data.me && this.data['private']) lichess.reload();
this.data = { ...this.data, ...data };
this.data.me = data.me; // to account for removal on withdraw
if (data.playerInfo && data.playerInfo.player.id === this.playerInfo.id) this.playerInfo.data = data.playerInfo;
this.loadPage(data.standing);
if (this.focusOnMe) this.scrollToMe();
sound.end(data);
sound.countDown(data);
this.joinSpinner = false;
this.recountTeams();
this.redirectToMyGame();
};
myGameId = () => this.data.me?.gameId;
private recountTeams() {
if (this.data.teamBattle)
this.data.teamBattle.hasMoreThanTenTeams = Object.keys(this.data.teamBattle.teams).length > 10;
}
private redirectToMyGame() {
const gameId = this.myGameId();
if (gameId) this.redirectFirst(gameId);
}
redirectFirst = (gameId: string, rightNow?: boolean) => {
const delay = rightNow || document.hasFocus() ? 10 : 1000 + Math.random() * 500;
setTimeout(() => {
if (this.lastStorage.get() !== gameId) {
this.lastStorage.set(gameId);
lichess.redirect('/' + gameId);
}
}, delay);
};
loadPage = (data: Standing) => {
if (!data.failed || !this.pages[data.page]) this.pages[data.page] = data.players;
};
setPage = (page: number) => {
this.page = page;
xhr.loadPage(this, page);
};
jumpToPageOf = (name: string) => {
const userId = name.toLowerCase();
xhr.loadPageOf(this, userId).then(data => {
this.loadPage(data);
this.page = data.page;
this.searching = false;
this.focusOnMe = false;
this.pages[this.page].filter(p => p.name.toLowerCase() == userId).forEach(this.showPlayerInfo);
this.redraw();
});
};
userSetPage = (page: number) => {
this.focusOnMe = false;
this.setPage(page);
};
userNextPage = () => this.userSetPage(this.page + 1);
userPrevPage = () => this.userSetPage(this.page - 1);
userLastPage = () => this.userSetPage(players(this).nbPages);
withdraw = () => {
xhr.withdraw(this);
this.joinSpinner = true;
this.focusOnMe = false;
};
join = (password?: string, team?: string) => {
this.joinWithTeamSelector = false;
if (!this.data.verdicts.accepted)
return this.data.verdicts.list.forEach(v => {
if (v.verdict !== 'ok') alert(v.verdict);
});
if (this.data.teamBattle && !team && !this.data.me) {
this.joinWithTeamSelector = true;
} else {
xhr.join(this, password, team);
this.joinSpinner = true;
this.focusOnMe = true;
}
};
scrollToMe = () => {
const page = myPage(this);
if (page && page !== this.page) this.setPage(page);
};
toggleFocusOnMe = () => {
if (!this.data.me) return;
this.focusOnMe = !this.focusOnMe;
if (this.focusOnMe) this.scrollToMe();
};
showPlayerInfo = player => {
if (this.data.secondsToStart) return;
const userId = player.name.toLowerCase();
this.teamInfo.requested = undefined;
this.playerInfo = {
id: this.playerInfo.id === userId ? null : userId,
player: player,
data: null,
};
if (this.playerInfo.id) xhr.playerInfo(this, this.playerInfo.id);
};
setPlayerInfoData = data => {
if (data.player.id === this.playerInfo.id) this.playerInfo.data = data;
};
showTeamInfo = (teamId: string) => {
this.playerInfo.id = undefined;
this.teamInfo = {
requested: this.teamInfo.requested === teamId ? undefined : teamId,
loaded: undefined,
};
if (this.teamInfo.requested) xhr.teamInfo(this, this.teamInfo.requested);
};
setTeamInfo = (teamInfo: TeamInfo) => {
if (teamInfo.id === this.teamInfo.requested) this.teamInfo.loaded = teamInfo;
};
toggleSearch = () => (this.searching = !this.searching);
}