mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2026-01-03 05:54:22 +08:00
all ts errors
This commit is contained in:
parent
86dcef01e2
commit
9e3f601b58
18 changed files with 389 additions and 1417 deletions
|
|
@ -1,3 +1,5 @@
|
|||
import * as TribeTypes from "../tribe/types";
|
||||
|
||||
export class InputSuggestions {
|
||||
private inputElement: JQuery<HTMLElement>;
|
||||
private suggestionsElement: JQuery<HTMLElement> | undefined;
|
||||
|
|
@ -36,7 +38,7 @@ export class InputSuggestions {
|
|||
this.inputElement.on("input", () => {
|
||||
const inputVal = this.inputElement.val() as string;
|
||||
const split = inputVal.split(" ");
|
||||
const last = split[split.length - 1];
|
||||
const last = split[split.length - 1] as string;
|
||||
const search = last.slice(this.prefix.length);
|
||||
|
||||
if (
|
||||
|
|
@ -91,9 +93,9 @@ export class InputSuggestions {
|
|||
const suggestionsElement = document.createElement("div");
|
||||
suggestionsElement.classList.add("inputSuggestions");
|
||||
if (this.position === "top") {
|
||||
this.inputElement[0].before(suggestionsElement);
|
||||
this.inputElement[0]?.before(suggestionsElement);
|
||||
} else {
|
||||
this.inputElement[0].after(suggestionsElement);
|
||||
this.inputElement[0]?.after(suggestionsElement);
|
||||
}
|
||||
this.suggestionsElement = $(suggestionsElement);
|
||||
this.selectedIndex = 0;
|
||||
|
|
@ -139,17 +141,19 @@ export class InputSuggestions {
|
|||
}
|
||||
|
||||
for (const searchString of this.foundKeys) {
|
||||
const suggestion = this.data[searchString];
|
||||
const suggestion = this.data[
|
||||
searchString
|
||||
] as TribeTypes.InputSuggestionEntry;
|
||||
const el = `
|
||||
<div class="suggestion ${
|
||||
added === this.selectedIndex ? "selected" : ""
|
||||
}" data-search-string="${searchString}" data-id="${added}">
|
||||
${
|
||||
suggestion.imageIcon
|
||||
suggestion.imageIcon !== undefined
|
||||
? `<div class="icon"><img src="${suggestion.imageIcon}" /></div>`
|
||||
: suggestion.faIcon
|
||||
: suggestion.faIcon !== undefined
|
||||
? `<div class="icon"><i class="fas fa-fw ${suggestion.faIcon}"></i></div>`
|
||||
: suggestion.textIcon
|
||||
: suggestion.textIcon !== undefined
|
||||
? `<div class="icon"><span>${suggestion.textIcon}</span></div>`
|
||||
: ""
|
||||
}
|
||||
|
|
@ -172,20 +176,20 @@ export class InputSuggestions {
|
|||
if (!this.suggestionsElement) return;
|
||||
if (this.position === "top") {
|
||||
this.suggestionsElement.css({
|
||||
left: this.inputElement[0].offsetLeft + "px",
|
||||
width: this.inputElement[0].offsetWidth + "px",
|
||||
left: this.inputElement[0]?.offsetLeft + "px",
|
||||
width: this.inputElement[0]?.offsetWidth + "px",
|
||||
top:
|
||||
this.inputElement[0].offsetTop -
|
||||
this.suggestionsElement[0].offsetHeight +
|
||||
(this.inputElement[0]?.offsetTop ?? 0) -
|
||||
(this.suggestionsElement[0]?.offsetHeight ?? 0) +
|
||||
"px",
|
||||
});
|
||||
} else {
|
||||
this.suggestionsElement.css({
|
||||
left: this.inputElement[0].offsetLeft + "px",
|
||||
width: this.inputElement[0].offsetWidth + "px",
|
||||
left: this.inputElement[0]?.offsetLeft + "px",
|
||||
width: this.inputElement[0]?.offsetWidth + "px",
|
||||
top:
|
||||
this.inputElement[0].offsetTop +
|
||||
this.inputElement[0].offsetHeight +
|
||||
(this.inputElement[0]?.offsetTop ?? 0) +
|
||||
(this.inputElement[0]?.offsetHeight ?? 0) +
|
||||
"px",
|
||||
});
|
||||
}
|
||||
|
|
@ -215,9 +219,9 @@ export class InputSuggestions {
|
|||
applySelection(): void {
|
||||
if (!this.suggestionsElement) return;
|
||||
if (this.selectedIndex === undefined) return;
|
||||
if (!this.suggestionsElement) return;
|
||||
if (this.suggestionsElement === undefined) return;
|
||||
const toInsert = this.foundKeys[this.selectedIndex];
|
||||
if (!toInsert) return;
|
||||
if (toInsert === undefined) return;
|
||||
|
||||
const currentVal = this.inputElement.val() as string;
|
||||
const split = currentVal.split(" ");
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ import * as TribeDelta from "../tribe/tribe-delta";
|
|||
import * as Random from "../utils/random";
|
||||
import * as TribeState from "../tribe/tribe-state";
|
||||
import * as Tribe from "../tribe/tribe";
|
||||
import * as TribeTypes from "../tribe/types";
|
||||
|
||||
export const glarsesMode = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
import * as TestWords from "../test/test-words";
|
||||
import * as TestUI from "../test/test-ui";
|
||||
import Config from "../config";
|
||||
import { convertRemToPixels } from "../utils/misc";
|
||||
import * as SlowTimer from "../states/slow-timer";
|
||||
import { getRoom } from "./tribe-state";
|
||||
import tribeSocket from "./tribe-socket";
|
||||
import * as LineJumpEvent from "../observables/line-jump-event";
|
||||
import * as ThemeColors from "../elements/theme-colors";
|
||||
import * as ConfigEvent from "../observables/config-event";
|
||||
import * as TestState from "../test/test-state";
|
||||
import { convertRemToPixels } from "../utils/numbers";
|
||||
import * as TribeTypes from "./types";
|
||||
|
||||
const carets: { [key: string]: TribeCaret } = {};
|
||||
|
||||
|
|
@ -28,7 +30,8 @@ export class TribeCaret {
|
|||
|
||||
public spawn(): void {
|
||||
if (this.element) {
|
||||
return this.destroy();
|
||||
this.destroy();
|
||||
return;
|
||||
}
|
||||
//create element and store
|
||||
const element = document.createElement("div");
|
||||
|
|
@ -80,7 +83,8 @@ export class TribeCaret {
|
|||
public animate(animationDuration: number): void {
|
||||
if (!this.element) {
|
||||
this.spawn();
|
||||
return this.animate(125);
|
||||
this.animate(125);
|
||||
return;
|
||||
}
|
||||
// if ($("#paceCaret").hasClass("hidden")) {
|
||||
// $("#paceCaret").removeClass("hidden");
|
||||
|
|
@ -106,7 +110,7 @@ export class TribeCaret {
|
|||
try {
|
||||
const newIndex =
|
||||
animationWordIndex -
|
||||
(TestWords.words.currentIndex - TestUI.currentWordElementIndex);
|
||||
(TestState.activeWordIndex - TestUI.activeWordElementIndex);
|
||||
currentWord = <HTMLElement>(
|
||||
document.querySelectorAll("#words .word")[newIndex]
|
||||
);
|
||||
|
|
@ -129,6 +133,7 @@ export class TribeCaret {
|
|||
currentLetterWidth === undefined ||
|
||||
caretWidth === undefined
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/only-throw-error
|
||||
throw ``;
|
||||
}
|
||||
|
||||
|
|
@ -149,7 +154,7 @@ export class TribeCaret {
|
|||
this.element.addClass("hidden");
|
||||
}
|
||||
|
||||
const currentTop = this.element[0].offsetTop;
|
||||
const currentTop = this.element[0]?.offsetTop;
|
||||
|
||||
if (newTop !== undefined) {
|
||||
const smoothlinescroll = $("#words .smoothScroller").height() ?? 0;
|
||||
|
|
@ -230,7 +235,7 @@ export class TribeCaret {
|
|||
}
|
||||
}
|
||||
|
||||
async changeColor(color: keyof MonkeyTypes.ThemeColors): Promise<void> {
|
||||
async changeColor(color: ThemeColors.ColorName): Promise<void> {
|
||||
if (!this.element) return;
|
||||
const colorHex = await ThemeColors.get(color);
|
||||
this.element.css({
|
||||
|
|
@ -261,7 +266,7 @@ export function init(): void {
|
|||
if (!room) return;
|
||||
for (const socketId of Object.keys(room.users)) {
|
||||
if (socketId === tribeSocket.getId()) continue;
|
||||
if (room.users[socketId].isTyping !== true) continue;
|
||||
if (room.users[socketId]?.isTyping !== true) continue;
|
||||
|
||||
const name = room.users[socketId].name;
|
||||
|
||||
|
|
@ -273,11 +278,9 @@ export function updateAndAnimate(
|
|||
data: Record<string, TribeTypes.UserProgress>
|
||||
): void {
|
||||
for (const socketId of Object.keys(data)) {
|
||||
const d = data[socketId] as TribeTypes.UserProgress;
|
||||
if (!carets[socketId]) continue;
|
||||
carets[socketId].updatePosition(
|
||||
data[socketId].wordIndex,
|
||||
data[socketId].letterIndex
|
||||
);
|
||||
carets[socketId].updatePosition(d.wordIndex, d.letterIndex);
|
||||
carets[socketId].animate(getRoom()?.updateRate ?? 500);
|
||||
}
|
||||
}
|
||||
|
|
@ -285,29 +288,31 @@ export function updateAndAnimate(
|
|||
export function destroy(socketId: string): void {
|
||||
if (carets[socketId]) {
|
||||
carets[socketId].destroy();
|
||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||
delete carets[socketId];
|
||||
}
|
||||
}
|
||||
|
||||
export function changeColor(
|
||||
socketId: string,
|
||||
color: keyof MonkeyTypes.ThemeColors
|
||||
color: ThemeColors.ColorName
|
||||
): void {
|
||||
if (carets[socketId]) {
|
||||
carets[socketId].changeColor(color);
|
||||
void carets[socketId].changeColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
export function destroyAll(): void {
|
||||
for (const socketId of Object.keys(carets)) {
|
||||
carets[socketId].destroy();
|
||||
carets[socketId]?.destroy();
|
||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||
delete carets[socketId];
|
||||
}
|
||||
}
|
||||
|
||||
export function lineJump(offset: number, withAnimation: boolean): void {
|
||||
for (const socketId of Object.keys(carets)) {
|
||||
carets[socketId].lineJump(offset, withAnimation);
|
||||
carets[socketId]?.lineJump(offset, withAnimation);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -328,7 +333,7 @@ ConfigEvent.subscribe((key, value, _nosave, previousValue) => {
|
|||
(value === "on" && previousValue === "noNames")
|
||||
) {
|
||||
for (const socketId of Object.keys(carets)) {
|
||||
carets[socketId].setNameVisibility(Config.tribeCarets === "on");
|
||||
carets[socketId]?.setNameVisibility(Config.tribeCarets === "on");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@ import { Chart, ChartConfiguration } from "chart.js";
|
|||
import * as TribeState from "./tribe-state";
|
||||
import * as ThemeColors from "../elements/theme-colors";
|
||||
import * as Notifications from "../elements/notifications";
|
||||
import { createErrorMessage, smooth } from "../utils/misc";
|
||||
import { createErrorMessage } from "../utils/misc";
|
||||
import tribeSocket from "./tribe-socket";
|
||||
import { smooth } from "../utils/arrays";
|
||||
|
||||
const charts: Record<string, Chart> = {};
|
||||
|
||||
|
|
@ -42,12 +43,12 @@ const settings: ChartConfiguration = {
|
|||
pointStyle: "crossRot",
|
||||
pointRadius: function (context): 0 | 2 {
|
||||
const index = context.dataIndex;
|
||||
const value = context.dataset.data[index] ?? 0;
|
||||
const value = (context.dataset.data[index] ?? 0) as number;
|
||||
return value <= 0 ? 0 : 2;
|
||||
},
|
||||
pointHoverRadius: function (context): 0 | 3 {
|
||||
const index = context.dataIndex;
|
||||
const value = context.dataset.data[index] ?? 0;
|
||||
const value = (context.dataset.data[index] ?? 0) as number;
|
||||
return value <= 0 ? 0 : 3;
|
||||
},
|
||||
},
|
||||
|
|
@ -257,8 +258,9 @@ async function fillData(chart: Chart, userId: string): Promise<void> {
|
|||
const labels: number[] = [];
|
||||
const room = TribeState.getRoom();
|
||||
if (!room) return;
|
||||
const result = room.users[userId].result;
|
||||
const result = room.users[userId]?.result;
|
||||
if (!result) return;
|
||||
|
||||
for (let i = 1; i <= result.chartData.wpm.length; i++) {
|
||||
labels.push(i);
|
||||
}
|
||||
|
|
@ -271,20 +273,27 @@ async function fillData(chart: Chart, userId: string): Promise<void> {
|
|||
const smoothedRawData = smooth(result.chartData.raw, 1);
|
||||
|
||||
chart.data.labels = labels;
|
||||
//@ts-expect-error
|
||||
chart.data.datasets[0].data = result.chartData.wpm;
|
||||
//@ts-expect-error
|
||||
chart.data.datasets[1].data = smoothedRawData;
|
||||
//@ts-expect-error
|
||||
chart.data.datasets[2].data = result.chartData.err;
|
||||
|
||||
// chart.options.scales["wpm"].ticks.max = Math.round(chartmaxval);
|
||||
// chart.options.scales["raw"].ticks.max = Math.round(chartmaxval);
|
||||
|
||||
if (userId == tribeSocket.getId()) {
|
||||
//@ts-expect-error
|
||||
chart.data.datasets[0].borderColor = await ThemeColors.get("main");
|
||||
// chart.data.datasets[0].backgroundColor = await ThemeColors.get("main");
|
||||
} else {
|
||||
//@ts-expect-error
|
||||
|
||||
chart.data.datasets[0].borderColor = await ThemeColors.get("text");
|
||||
// chart.data.datasets[0].backgroundColor = await ThemeColors.get("text");
|
||||
}
|
||||
//@ts-expect-error
|
||||
chart.data.datasets[1].borderColor = await ThemeColors.get("sub");
|
||||
// chart.data.datasets[1].backgroundColor = await ThemeColors.get("sub");
|
||||
|
||||
|
|
@ -303,10 +312,7 @@ export async function drawChart(userId: string): Promise<void> {
|
|||
return;
|
||||
}
|
||||
|
||||
const chart = new Chart(
|
||||
element,
|
||||
$.extend(true, {}, settings) as ChartConfiguration
|
||||
);
|
||||
const chart = new Chart(element, $.extend(true, {}, settings));
|
||||
|
||||
await fillData(chart, userId);
|
||||
|
||||
|
|
@ -329,7 +335,7 @@ export async function drawAllCharts(): Promise<void> {
|
|||
if (!room) return;
|
||||
const list = Object.keys(room.users);
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const userId = list[i];
|
||||
const userId = list[i] as string;
|
||||
if (!charts[userId]) {
|
||||
await drawChart(userId);
|
||||
}
|
||||
|
|
@ -343,7 +349,7 @@ export async function updateChartMaxValues(): Promise<void> {
|
|||
let maxRaw = 0;
|
||||
|
||||
for (const userId of Object.keys(room.users)) {
|
||||
const result = room.users[userId].result;
|
||||
const result = room.users[userId]?.result;
|
||||
if (!result) continue;
|
||||
const maxUserWpm = Math.max(maxWpm, Math.max(...result.chartData.wpm));
|
||||
const maxUserRaw = Math.max(maxRaw, Math.max(...result.chartData.raw));
|
||||
|
|
@ -358,7 +364,7 @@ export async function updateChartMaxValues(): Promise<void> {
|
|||
|
||||
const list = Object.keys(room.users);
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const userId = list[i];
|
||||
const userId = list[i] as string;
|
||||
if (charts[userId]) {
|
||||
const scales = charts[userId].options.scales;
|
||||
if (scales?.["wpm"]) {
|
||||
|
|
@ -370,7 +376,7 @@ export async function updateChartMaxValues(): Promise<void> {
|
|||
scales["raw"].min = 0;
|
||||
}
|
||||
|
||||
const result = room.users[userId].result;
|
||||
const result = room.users[userId]?.result;
|
||||
if (result && scales?.["errors"]) {
|
||||
scales["errors"].max = Math.max(...result.chartData.err) + 1;
|
||||
scales["errors"].min = 0;
|
||||
|
|
@ -380,15 +386,16 @@ export async function updateChartMaxValues(): Promise<void> {
|
|||
// Math.round(chartmaxval);
|
||||
// charts[userId].options.scales.yAxes[1].ticks.max =
|
||||
// Math.round(chartmaxval);
|
||||
await charts[userId].update();
|
||||
charts[userId].update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function destroyAllCharts(): void {
|
||||
Object.keys(charts).forEach((userId) => {
|
||||
charts[userId].clear();
|
||||
charts[userId].destroy();
|
||||
charts[userId]?.clear();
|
||||
charts[userId]?.destroy();
|
||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||
delete charts[userId];
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import * as Misc from "../utils/misc";
|
|||
import * as TestUI from "../test/test-ui";
|
||||
import tribeSocket from "./tribe-socket";
|
||||
import { InputSuggestions } from "../elements/input-suggestions";
|
||||
import { getEmojiList } from "../utils/json-data";
|
||||
import * as TribeTypes from "./types";
|
||||
|
||||
let lastMessageTimestamp = 0;
|
||||
let shouldScrollChat = true;
|
||||
|
|
@ -63,7 +65,7 @@ export function isAnyChatSuggestionVisible(): boolean {
|
|||
);
|
||||
}
|
||||
|
||||
Misc.getEmojiList().then((emojis) => {
|
||||
void getEmojiList().then((emojis) => {
|
||||
const dataToSet: Record<string, TribeTypes.InputSuggestionEntry> = {};
|
||||
for (const emoji of emojis) {
|
||||
if (emoji.type === "emoji") {
|
||||
|
|
@ -112,7 +114,12 @@ export function reset(where: "both" | "lobby" | "result" = "both"): void {
|
|||
|
||||
export function fill(where: "both" | "lobby" | "result"): void {
|
||||
for (const message of chatHistory) {
|
||||
displayMessage(message.isSystem, message.socketId, message.message, where);
|
||||
void displayMessage(
|
||||
message.isSystem,
|
||||
message.socketId,
|
||||
message.message,
|
||||
where
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -140,8 +147,10 @@ function sendChattingUpdate(bool: boolean): void {
|
|||
// }
|
||||
|
||||
export function scrollChat(): void {
|
||||
const chatEl = $(".pageTribe .lobby .chat .messages")[0];
|
||||
const chatEl2 = $(".pageTest #result #tribeResultBottom .chat .messages")[0];
|
||||
const chatEl = $(".pageTribe .lobby .chat .messages")[0] as HTMLElement;
|
||||
const chatEl2 = $(
|
||||
".pageTest #result #tribeResultBottom .chat .messages"
|
||||
)[0] as HTMLElement;
|
||||
|
||||
if (shouldScrollChat) {
|
||||
chatEl.scrollTop = chatEl.scrollHeight;
|
||||
|
|
@ -162,18 +171,23 @@ export function updateIsTyping(): void {
|
|||
const names: string[] = [];
|
||||
|
||||
for (const userId of Object.keys(room.users)) {
|
||||
if (room.users[userId].isChatting && userId !== tribeSocket.getId()) {
|
||||
names.push(room.users[userId].name);
|
||||
const user = room.users[userId] as TribeTypes.User;
|
||||
if (user.isChatting && userId !== tribeSocket.getId()) {
|
||||
names.push(user.name);
|
||||
}
|
||||
}
|
||||
if (names.length > 0) {
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
if (i === 0) {
|
||||
string += `<span class="who">${Misc.escapeHTML(names[i])}</span>`;
|
||||
string += `<span class="who">${Misc.escapeHTML(names[i] ?? "")}</span>`;
|
||||
} else if (i === names.length - 1) {
|
||||
string += ` and <span class="who">${Misc.escapeHTML(names[i])}</span>`;
|
||||
string += ` and <span class="who">${Misc.escapeHTML(
|
||||
names[i] ?? ""
|
||||
)}</span>`;
|
||||
} else {
|
||||
string += `, <span class="who">${Misc.escapeHTML(names[i])}</span>`;
|
||||
string += `, <span class="who">${Misc.escapeHTML(
|
||||
names[i] ?? ""
|
||||
)}</span>`;
|
||||
}
|
||||
}
|
||||
if (names.length == 1) {
|
||||
|
|
@ -194,12 +208,12 @@ async function insertImageEmoji(text: string): Promise<string> {
|
|||
let big = "";
|
||||
if (textSplit.length === 1) big = "big";
|
||||
for (let i = 0; i < textSplit.length; i++) {
|
||||
if (/:.+:/g.test(textSplit[i])) {
|
||||
const emoji = await Misc.getEmojiList();
|
||||
if (/:.+:/g.test(textSplit[i] as string)) {
|
||||
const emoji = await getEmojiList();
|
||||
const result = emoji.filter(
|
||||
(e) =>
|
||||
Misc.escapeHTML(e.from).toLowerCase() ==
|
||||
textSplit[i].replace(/:/g, "").toLowerCase()
|
||||
textSplit[i]?.replace(/:/g, "").toLowerCase()
|
||||
);
|
||||
if (result[0] !== undefined) {
|
||||
if (result[0].type === "image") {
|
||||
|
|
@ -230,7 +244,7 @@ export function appendMessage(
|
|||
chatHistory.splice(0, chatHistory.length - 100);
|
||||
}
|
||||
|
||||
displayMessage(isSystem, socketId, message);
|
||||
void displayMessage(isSystem, socketId, message);
|
||||
}
|
||||
|
||||
export async function displayMessage(
|
||||
|
|
@ -241,9 +255,10 @@ export async function displayMessage(
|
|||
): Promise<void> {
|
||||
let cls = "message";
|
||||
let author = "";
|
||||
const fromName = socketId
|
||||
? TribeState.getRoom()?.users[socketId]?.name
|
||||
: undefined;
|
||||
const fromName =
|
||||
socketId !== undefined
|
||||
? TribeState.getRoom()?.users[socketId]?.name
|
||||
: undefined;
|
||||
if (isSystem) {
|
||||
cls = "systemMessage";
|
||||
} else {
|
||||
|
|
@ -367,9 +382,9 @@ $(".pageTest #result #tribeResultBottom .chat .input input").on(
|
|||
|
||||
$(".pageTribe .lobby .chat .messages").on("scroll", (_e) => {
|
||||
const el = $(".pageTribe .lobby .chat .messages")[0];
|
||||
const scrollHeight = el.scrollHeight as number;
|
||||
const scrollTop = el.scrollTop as number;
|
||||
const height = el.clientHeight as number;
|
||||
const scrollHeight = el?.scrollHeight as number;
|
||||
const scrollTop = el?.scrollTop as number;
|
||||
const height = el?.clientHeight as number;
|
||||
if (height + scrollTop < scrollHeight - 20) {
|
||||
shouldScrollChat = false;
|
||||
} else {
|
||||
|
|
@ -379,9 +394,9 @@ $(".pageTribe .lobby .chat .messages").on("scroll", (_e) => {
|
|||
|
||||
$(".pageTest #result #tribeResultBottom .chat .messages").on("scroll", (_e) => {
|
||||
const el = $(".pageTest #result #tribeResultBottom .chat .messages")[0];
|
||||
const scrollHeight = el.scrollHeight as number;
|
||||
const scrollTop = el.scrollTop as number;
|
||||
const height = el.clientHeight as number;
|
||||
const scrollHeight = el?.scrollHeight as number;
|
||||
const scrollTop = el?.scrollTop as number;
|
||||
const height = el?.clientHeight as number;
|
||||
if (height + scrollTop < scrollHeight - 20) {
|
||||
shouldScrollChat = false;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
import Config, * as UpdateConfig from "../config";
|
||||
import * as Funbox from "../test/funbox/funbox";
|
||||
// import * as Notifications from "./notifications";
|
||||
import * as CustomText from "../test/custom-text";
|
||||
// import * as CustomText from "../test/custom-text";
|
||||
import * as TribeConfigSyncEvent from "../observables/tribe-config-sync-event";
|
||||
import * as TribeButtons from "./tribe-buttons";
|
||||
import * as TribeState from "../tribe/tribe-state";
|
||||
import tribeSocket from "./tribe-socket";
|
||||
import * as TribeTypes from "./types";
|
||||
import { Difficulty, Mode } from "@monkeytype/contracts/schemas/shared";
|
||||
import {
|
||||
QuoteLength,
|
||||
StopOnError,
|
||||
} from "@monkeytype/contracts/schemas/configs";
|
||||
|
||||
export function getArray(config: TribeTypes.RoomConfig): string[] {
|
||||
const ret: string[] = [];
|
||||
|
|
@ -42,10 +48,10 @@ export function getArray(config: TribeTypes.RoomConfig): string[] {
|
|||
if (config["difficulty"] !== "normal") ret.push(config["difficulty"]);
|
||||
// if(config['language'] !== "english")
|
||||
ret.push(config["language"]);
|
||||
if (config["punctuation"] !== false) ret.push("punctuation");
|
||||
if (config["numbers"] !== false) ret.push("numbers");
|
||||
if (config["punctuation"]) ret.push("punctuation");
|
||||
if (config["numbers"]) ret.push("numbers");
|
||||
if (config["funbox"] !== "none") ret.push(config["funbox"]);
|
||||
if (config["lazyMode"] !== false) ret.push("lazy mode");
|
||||
if (config["lazyMode"]) ret.push("lazy mode");
|
||||
if (config["stopOnError"] !== "off") {
|
||||
ret.push("stop on " + config["stopOnError"] == "word" ? "word" : "letter");
|
||||
}
|
||||
|
|
@ -59,42 +65,30 @@ export function getArray(config: TribeTypes.RoomConfig): string[] {
|
|||
}
|
||||
|
||||
export function apply(config: TribeTypes.RoomConfig): void {
|
||||
UpdateConfig.setMode(config.mode as MonkeyTypes.Mode, true, true);
|
||||
UpdateConfig.setMode(config.mode as Mode, true, true);
|
||||
if (config.mode === "time") {
|
||||
UpdateConfig.setTimeConfig(config.mode2 as number, true, true);
|
||||
} else if (config.mode === "words") {
|
||||
UpdateConfig.setWordCount(config.mode2 as number, true, true);
|
||||
} else if (config.mode === "quote") {
|
||||
UpdateConfig.setQuoteLength(
|
||||
config.mode2 as MonkeyTypes.QuoteLength,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
);
|
||||
UpdateConfig.setQuoteLength(config.mode2 as QuoteLength, true, true, true);
|
||||
} else if (config.mode === "custom") {
|
||||
CustomText.setText(config.customText.text, true);
|
||||
CustomText.setIsWordRandom(config.customText.isWordRandom, true);
|
||||
CustomText.setIsTimeRandom(config.customText.isTimeRandom, true);
|
||||
CustomText.setTime(config.customText.time, true);
|
||||
CustomText.setWord(config.customText.word, true);
|
||||
//todo fix
|
||||
// CustomText.setText(config.customText.text, true);
|
||||
// CustomText.setIsWordRandom(config.customText.isWordRandom, true);
|
||||
// CustomText.setIsTimeRandom(config.customText.isTimeRandom, true);
|
||||
// CustomText.setTime(config.customText.time, true);
|
||||
// CustomText.setWord(config.customText.word, true);
|
||||
}
|
||||
UpdateConfig.setDifficulty(
|
||||
config.difficulty as MonkeyTypes.Difficulty,
|
||||
true,
|
||||
true
|
||||
);
|
||||
UpdateConfig.setDifficulty(config.difficulty as Difficulty, true, true);
|
||||
UpdateConfig.setLanguage(config.language, true, true);
|
||||
UpdateConfig.setPunctuation(config.punctuation, true, true);
|
||||
UpdateConfig.setNumbers(config.numbers, true, true);
|
||||
Funbox.setFunbox(config.funbox, true);
|
||||
UpdateConfig.setLazyMode(config.lazyMode, true, true);
|
||||
UpdateConfig.setStopOnError(
|
||||
config.stopOnError as MonkeyTypes.StopOnError,
|
||||
true,
|
||||
true
|
||||
);
|
||||
UpdateConfig.setStopOnError(config.stopOnError as StopOnError, true, true);
|
||||
if (config.minWpm !== "off") {
|
||||
UpdateConfig.setMinWpmCustomSpeed(config.minWpm as number, true, true);
|
||||
UpdateConfig.setMinWpmCustomSpeed(config.minWpm, true, true);
|
||||
UpdateConfig.setMinWpm("custom", true, true);
|
||||
} else {
|
||||
UpdateConfig.setMinWpm("off", true, true);
|
||||
|
|
@ -163,13 +157,14 @@ function sync(): void {
|
|||
minAcc: Config.minAcc === "custom" ? Config.minAccCustom : "off",
|
||||
minBurst:
|
||||
Config.minBurst === "fixed" ? Config.minBurstCustomSpeed : "off",
|
||||
customText: {
|
||||
text: CustomText.text,
|
||||
isWordRandom: CustomText.isWordRandom,
|
||||
isTimeRandom: CustomText.isTimeRandom,
|
||||
word: CustomText.word,
|
||||
time: CustomText.time,
|
||||
},
|
||||
//todo fix
|
||||
// customText: {
|
||||
// text: CustomText.text,
|
||||
// isWordRandom: CustomText.isWordRandom,
|
||||
// isTimeRandom: CustomText.isTimeRandom,
|
||||
// word: CustomText.word,
|
||||
// time: CustomText.time,
|
||||
// },
|
||||
isInfiniteTest:
|
||||
(Config.mode == "time" || Config.mode == "words") && mode2 == "0",
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import * as SlowTimer from "../states/slow-timer";
|
|||
import tribeSocket from "./tribe-socket";
|
||||
import { FinalPositions } from "./tribe-socket/routes/room";
|
||||
import { getOrdinalNumberString } from "@monkeytype/util/numbers";
|
||||
import * as TribeTypes from "./types";
|
||||
|
||||
const initialised: Record<string, boolean | object> = {};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
import { Mode } from "@monkeytype/contracts/schemas/shared";
|
||||
import Socket from "../socket";
|
||||
import { QuoteLength } from "@monkeytype/contracts/schemas/configs";
|
||||
import * as TribeTypes from "../../types";
|
||||
|
||||
type GetPublicRoomsResponse = {
|
||||
status?: string;
|
||||
rooms?: TribeTypes.Room[];
|
||||
};
|
||||
|
||||
async function getPublicRooms(
|
||||
_page: number,
|
||||
search: string
|
||||
): Promise<TribeSocket.GetPublicRoomsResponse> {
|
||||
): Promise<GetPublicRoomsResponse> {
|
||||
return new Promise((resolve) => {
|
||||
Socket.emit(
|
||||
"room_get_public_rooms",
|
||||
|
|
@ -13,22 +19,27 @@ async function getPublicRooms(
|
|||
page: 0,
|
||||
search: search,
|
||||
},
|
||||
(e: TribeSocket.GetPublicRoomsResponse) => {
|
||||
(e: GetPublicRoomsResponse) => {
|
||||
resolve(e);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
type JoinRoomResponse = {
|
||||
status?: string;
|
||||
room?: TribeTypes.Room;
|
||||
};
|
||||
|
||||
async function join(
|
||||
roomId: string,
|
||||
fromBrowser: boolean
|
||||
): Promise<TribeSocket.JoinRoomResponse> {
|
||||
): Promise<JoinRoomResponse> {
|
||||
return new Promise((resolve) => {
|
||||
Socket.emit(
|
||||
"room_join",
|
||||
{ roomId, fromBrowser },
|
||||
(res: TribeSocket.JoinRoomResponse) => {
|
||||
(res: JoinRoomResponse) => {
|
||||
resolve(res);
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,10 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
|
||||
import Socket from "../socket";
|
||||
import * as TribeTypes from "../../types";
|
||||
|
||||
async function versionCheck(
|
||||
expectedVersion: string
|
||||
|
|
@ -104,7 +110,9 @@ function connect(callback: () => void): void {
|
|||
});
|
||||
}
|
||||
|
||||
function disconnect(callback: (reason: string, details?: any) => void): void {
|
||||
function disconnect(
|
||||
callback: (reason: string, details?: unknown) => void
|
||||
): void {
|
||||
Socket.on("disconnect", callback);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,7 @@ declare namespace TribeSocket {
|
|||
status?: string;
|
||||
rooms?: TribeTypes.Room[];
|
||||
}
|
||||
interface JoinRoomResponse {
|
||||
status?: string;
|
||||
room?: TribeTypes.Room;
|
||||
}
|
||||
|
||||
interface VersionCheckResponse {
|
||||
status: string;
|
||||
version: string;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import TribeSocket from "./tribe-socket";
|
||||
import * as TribeTypes from "./types";
|
||||
|
||||
let state = -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import tribeSocket from "./tribe-socket";
|
||||
import * as TribeTypes from "./types";
|
||||
|
||||
export let inQueueNumbers = [0, 0, 0, 0];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import * as TribeState from "./tribe-state";
|
||||
import * as TribeUserSettingsPopup from "../popups/tribe-user-settings-popup";
|
||||
import tribeSocket from "./tribe-socket";
|
||||
import { User } from "./types";
|
||||
|
||||
export function reset(page?: string): void {
|
||||
if (page === undefined) {
|
||||
|
|
@ -16,7 +17,7 @@ export function reset(page?: string): void {
|
|||
export function update(page?: string): void {
|
||||
const room = TribeState.getRoom();
|
||||
if (!room) return;
|
||||
if (!page) {
|
||||
if (page === undefined) {
|
||||
update("lobby");
|
||||
update("result");
|
||||
return;
|
||||
|
|
@ -28,8 +29,8 @@ export function update(page?: string): void {
|
|||
usersArray.push(room.users[userId]);
|
||||
}
|
||||
const sortedUsers = usersArray.sort(
|
||||
(a, b) => (b.points ?? 0) - (a.points ?? 0)
|
||||
);
|
||||
(a, b) => (b?.points ?? 0) - (a?.points ?? 0)
|
||||
) as User[];
|
||||
sortedUsers.forEach((user) => {
|
||||
let icons = "";
|
||||
if (user.isTyping && !user.isFinished) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ import * as TestWords from "../test/test-words";
|
|||
import * as TestStats from "../test/test-stats";
|
||||
import * as TestInput from "../test/test-input";
|
||||
import * as TribeCarets from "./tribe-carets";
|
||||
import * as TribeTypes from "./types";
|
||||
import { navigate } from "../controllers/route-controller";
|
||||
import { ColorName } from "../elements/theme-colors";
|
||||
|
||||
const defaultName = "Guest";
|
||||
let name = "Guest";
|
||||
|
|
@ -111,7 +113,7 @@ function updateState(newState: number): void {
|
|||
} else if (state === 21) {
|
||||
TribeResults.hideTimer();
|
||||
TribeResults.updateTimerText("Time left for everyone to get ready");
|
||||
if (TribeState.getAutoReady() === true) {
|
||||
if (TribeState.getAutoReady()) {
|
||||
TribeSocket.out.room.readyUpdate();
|
||||
}
|
||||
} else if (state === 22) {
|
||||
|
|
@ -137,7 +139,7 @@ export async function init(): Promise<void> {
|
|||
|
||||
//todo remove, only for dev
|
||||
const lstribename = window.localStorage.getItem("tribeName");
|
||||
if (lstribename) {
|
||||
if (lstribename !== undefined && lstribename !== null) {
|
||||
name = lstribename;
|
||||
TribeSocket.updateName(lstribename);
|
||||
}
|
||||
|
|
@ -164,17 +166,17 @@ export function joinRoom(roomId: string, fromBrowser = false): void {
|
|||
return;
|
||||
}
|
||||
|
||||
TribeSocket.out.room.join(roomId, fromBrowser).then((response) => {
|
||||
void TribeSocket.out.room.join(roomId, fromBrowser).then((response) => {
|
||||
if (response.room) {
|
||||
TribeState.setRoom(response.room);
|
||||
updateState(response.room.state);
|
||||
TribePageLobby.init();
|
||||
TribePages.change("lobby");
|
||||
void TribePages.change("lobby");
|
||||
TribeSound.play("join");
|
||||
TribeChat.updateSuggestionData();
|
||||
// history.replaceState(null, "", `/tribe/${roomId}`);
|
||||
} else {
|
||||
TribePages.change("menu");
|
||||
void TribePages.change("menu");
|
||||
history.replaceState("/tribe", "", "/tribe");
|
||||
}
|
||||
});
|
||||
|
|
@ -218,14 +220,14 @@ async function connect(): Promise<void> {
|
|||
UpdateConfig.setTimerStyle("mini", true);
|
||||
TribePageMenu.enableButtons();
|
||||
updateState(1);
|
||||
if (autoJoin) {
|
||||
if (autoJoin !== undefined) {
|
||||
TribePagePreloader.updateText(`Joining room ${autoJoin}`);
|
||||
TribePagePreloader.updateSubtext("Please wait...");
|
||||
setTimeout(() => {
|
||||
joinRoom(autoJoin as string);
|
||||
}, 500);
|
||||
} else {
|
||||
TribePages.change("menu");
|
||||
void TribePages.change("menu");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -236,10 +238,13 @@ function checkIfEveryoneIsReady(): void {
|
|||
if (Object.keys(room.users).length <= 1) return;
|
||||
let everyoneReady = true;
|
||||
Object.keys(room.users).forEach((userId) => {
|
||||
if (room && (room.users[userId].isLeader || room.users[userId].isAfk)) {
|
||||
if (
|
||||
room !== undefined &&
|
||||
(room.users[userId]?.isLeader || room.users[userId]?.isAfk)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (room && !room.users[userId].isReady) {
|
||||
if (room !== undefined && !room.users[userId]?.isReady) {
|
||||
everyoneReady = false;
|
||||
}
|
||||
});
|
||||
|
|
@ -253,12 +258,12 @@ function checkIfEveryoneIsReady(): void {
|
|||
}
|
||||
|
||||
TribeSocket.in.system.connect(() => {
|
||||
connect();
|
||||
void connect();
|
||||
});
|
||||
|
||||
$(".tribechangename").on("click", () => {
|
||||
const name = prompt("Name");
|
||||
if (name) {
|
||||
if (name !== "" && name !== null) {
|
||||
window.localStorage.setItem("tribeName", name); //todo remove, only for dev
|
||||
TribeSocket.out.user.setName(name, true);
|
||||
}
|
||||
|
|
@ -273,6 +278,7 @@ TribeSocket.in.system.disconnect((reason, details) => {
|
|||
const roomId = TribeState.getRoom()?.id;
|
||||
if (!$(".pageTribe").hasClass("active")) {
|
||||
Notifications.add(
|
||||
//@ts-ignore
|
||||
`Disconnected: ${details?.["description"]} (${reason})`,
|
||||
-1,
|
||||
{
|
||||
|
|
@ -281,14 +287,15 @@ TribeSocket.in.system.disconnect((reason, details) => {
|
|||
);
|
||||
}
|
||||
TribeState.setRoom(undefined);
|
||||
TribePages.change("preloader");
|
||||
void TribePages.change("preloader");
|
||||
TribePagePreloader.updateIcon("times");
|
||||
TribePagePreloader.updateText(`Disconnected`);
|
||||
//@ts-ignore
|
||||
TribePagePreloader.updateSubtext(`${details?.["description"]} (${reason})`);
|
||||
TribePagePreloader.showReconnectButton();
|
||||
|
||||
reset();
|
||||
if (roomId) {
|
||||
void reset();
|
||||
if (roomId !== undefined) {
|
||||
autoJoin = roomId;
|
||||
}
|
||||
});
|
||||
|
|
@ -301,12 +308,12 @@ TribeSocket.in.system.connectFailed((err) => {
|
|||
customTitle: "Tribe",
|
||||
});
|
||||
}
|
||||
TribePages.change("preloader");
|
||||
void TribePages.change("preloader");
|
||||
TribePagePreloader.updateIcon("times");
|
||||
TribePagePreloader.updateText("Connection failed");
|
||||
TribePagePreloader.updateSubtext(err.message);
|
||||
TribePagePreloader.showReconnectButton();
|
||||
reset();
|
||||
void reset();
|
||||
});
|
||||
|
||||
TribeSocket.in.system.connectError((err) => {
|
||||
|
|
@ -317,12 +324,12 @@ TribeSocket.in.system.connectError((err) => {
|
|||
customTitle: "Tribe",
|
||||
});
|
||||
}
|
||||
TribePages.change("preloader");
|
||||
void TribePages.change("preloader");
|
||||
TribePagePreloader.updateIcon("times");
|
||||
TribePagePreloader.updateText(`Connection error`);
|
||||
TribePagePreloader.updateSubtext(err.message);
|
||||
TribePagePreloader.showReconnectButton();
|
||||
reset();
|
||||
void reset();
|
||||
});
|
||||
|
||||
TribeSocket.in.system.reconnect((attempt) => {
|
||||
|
|
@ -347,7 +354,7 @@ TribeSocket.in.room.joined((data) => {
|
|||
TribeState.setRoom(data.room);
|
||||
updateState(data.room.state);
|
||||
TribePageLobby.init();
|
||||
TribePages.change("lobby");
|
||||
void TribePages.change("lobby");
|
||||
TribeSound.play("join");
|
||||
TribeChat.updateSuggestionData();
|
||||
// history.replaceState(null, "", `/tribe/${e.room.id}`);
|
||||
|
|
@ -368,6 +375,7 @@ TribeSocket.in.room.playerJoined((data) => {
|
|||
TribeSocket.in.room.playerLeft((data) => {
|
||||
const room = TribeState.getRoom();
|
||||
if (room?.users) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||
delete room.users[data.userId];
|
||||
room.size = Object.keys(room.users).length;
|
||||
TribeUserList.update();
|
||||
|
|
@ -392,8 +400,8 @@ TribeSocket.in.room.left(() => {
|
|||
}
|
||||
TribeCarets.destroyAll();
|
||||
TribeSound.play("leave");
|
||||
TribePages.change("menu").then(() => {
|
||||
reset();
|
||||
void TribePages.change("menu").then(() => {
|
||||
void reset();
|
||||
});
|
||||
TribeChat.updateIsTyping();
|
||||
name = defaultName;
|
||||
|
|
@ -416,7 +424,7 @@ TribeSocket.in.room.nameChanged((data) => {
|
|||
TribeSocket.in.room.userIsReady((data) => {
|
||||
const room = TribeState.getRoom();
|
||||
if (!room) return;
|
||||
room.users[data.userId].isReady = true;
|
||||
(room.users[data.userId] as TribeTypes.User).isReady = true;
|
||||
TribeUserList.update();
|
||||
TribeButtons.update();
|
||||
checkIfEveryoneIsReady();
|
||||
|
|
@ -425,7 +433,9 @@ TribeSocket.in.room.userIsReady((data) => {
|
|||
TribeSocket.in.room.userAfkUpdate((data) => {
|
||||
const room = TribeState.getRoom();
|
||||
if (!room) return;
|
||||
room.users[data.userId].isAfk = data.isAfk;
|
||||
const user = room.users[data.userId];
|
||||
if (!user) return;
|
||||
user.isAfk = data.isAfk;
|
||||
TribeUserList.update();
|
||||
TribeButtons.update();
|
||||
});
|
||||
|
|
@ -433,12 +443,15 @@ TribeSocket.in.room.userAfkUpdate((data) => {
|
|||
TribeSocket.in.room.leaderChanged((data) => {
|
||||
const room = TribeState.getRoom();
|
||||
if (!room) return;
|
||||
const user = room.users[data.userId];
|
||||
if (!user) return;
|
||||
for (const userId of Object.keys(room.users)) {
|
||||
delete room.users[userId].isLeader;
|
||||
delete room.users[userId]?.isLeader;
|
||||
}
|
||||
room.users[data.userId].isLeader = true;
|
||||
room.users[data.userId].isAfk = false;
|
||||
room.users[data.userId].isReady = false;
|
||||
|
||||
user.isLeader = true;
|
||||
user.isAfk = false;
|
||||
user.isReady = false;
|
||||
TribeUserList.update();
|
||||
TribeButtons.update();
|
||||
TribePageLobby.updateVisibility();
|
||||
|
|
@ -448,7 +461,9 @@ TribeSocket.in.room.leaderChanged((data) => {
|
|||
TribeSocket.in.room.chattingChanged((data) => {
|
||||
const room = TribeState.getRoom();
|
||||
if (!room) return;
|
||||
room.users[data.userId].isChatting = data.isChatting;
|
||||
const user = room.users[data.userId];
|
||||
if (!user) return;
|
||||
user.isChatting = data.isChatting;
|
||||
TribeChat.updateIsTyping();
|
||||
});
|
||||
|
||||
|
|
@ -546,14 +561,15 @@ TribeSocket.in.room.usersUpdate((data) => {
|
|||
|
||||
let isChattingChanged = false;
|
||||
for (const [userId, user] of Object.entries(data)) {
|
||||
const roomUser = room.users[userId] as TribeTypes.User;
|
||||
if (user.isTyping !== undefined) {
|
||||
room.users[userId].isTyping = user.isTyping;
|
||||
roomUser.isTyping = user.isTyping;
|
||||
}
|
||||
if (user.isAfk !== undefined) room.users[userId].isAfk = user.isAfk;
|
||||
if (user.isReady !== undefined) room.users[userId].isReady = user.isReady;
|
||||
if (user.isAfk !== undefined) roomUser.isAfk = user.isAfk;
|
||||
if (user.isReady !== undefined) roomUser.isReady = user.isReady;
|
||||
if (user.isChatting !== undefined) {
|
||||
isChattingChanged = true;
|
||||
room.users[userId].isChatting = user.isChatting;
|
||||
roomUser.isChatting = user.isChatting;
|
||||
}
|
||||
}
|
||||
TribeUserList.update("lobby");
|
||||
|
|
@ -588,7 +604,7 @@ TribeSocket.in.room.progressUpdate((data) => {
|
|||
if (
|
||||
TribeState.getState() >= 10 &&
|
||||
TribeState.getState() <= 21 &&
|
||||
TestState.isActive === true
|
||||
TestState.isActive
|
||||
) {
|
||||
const wpmAndRaw = TestStats.calculateWpmAndRaw();
|
||||
const acc = Math.floor(TestStats.calculateAccuracy());
|
||||
|
|
@ -610,7 +626,7 @@ TribeSocket.in.room.progressUpdate((data) => {
|
|||
}
|
||||
|
||||
const wordsProgress = Math.floor(
|
||||
(TestWords.words.currentIndex / outof) * 100
|
||||
(TestState.activeWordIndex / outof) * 100
|
||||
);
|
||||
|
||||
progress = wordsProgress + globalWordProgress;
|
||||
|
|
@ -625,15 +641,16 @@ TribeSocket.in.room.progressUpdate((data) => {
|
|||
raw: wpmAndRaw.raw,
|
||||
acc,
|
||||
progress,
|
||||
wordIndex: TestWords.words.currentIndex,
|
||||
wordIndex: TestState.activeWordIndex,
|
||||
letterIndex: inputLen - 1,
|
||||
afk: TestInput.afkHistory[TestInput.afkHistory.length - 1],
|
||||
afk: TestInput.afkHistory[TestInput.afkHistory.length - 1] ?? false,
|
||||
});
|
||||
}
|
||||
|
||||
TribeCarets.updateAndAnimate(data.users);
|
||||
|
||||
for (const [userId, userProgress] of Object.entries(data.users)) {
|
||||
if (room.users[userId] === undefined) continue;
|
||||
room.users[userId].progress = userProgress;
|
||||
if (userId == TribeSocket.getId()) {
|
||||
TribeDelta.update();
|
||||
|
|
@ -657,9 +674,11 @@ TribeSocket.in.room.progressUpdate((data) => {
|
|||
TribeSocket.in.room.userResult((data) => {
|
||||
const room = TribeState.getRoom();
|
||||
if (!room) return;
|
||||
room.users[data.userId].result = data.result;
|
||||
room.users[data.userId].isFinished = true;
|
||||
room.users[data.userId].isTyping = false;
|
||||
const user = room.users[data.userId];
|
||||
if (!user) return;
|
||||
user.result = data.result;
|
||||
user.isFinished = true;
|
||||
user.isTyping = false;
|
||||
const resolve = data.result?.resolve;
|
||||
if (
|
||||
resolve === undefined ||
|
||||
|
|
@ -673,13 +692,13 @@ TribeSocket.in.room.userResult((data) => {
|
|||
|
||||
let color = undefined;
|
||||
if (resolve?.failed === true) {
|
||||
color = "colorfulError" as keyof MonkeyTypes.ThemeColors;
|
||||
color = "colorfulError" as ColorName;
|
||||
}
|
||||
|
||||
if (color) TribeCarets.changeColor(data.userId, color);
|
||||
TribeBars.fadeUser("test", data.userId, color);
|
||||
TribeBars.fadeUser("tribe", data.userId, color);
|
||||
if (room.config.isInfiniteTest === false) {
|
||||
if (!room.config.isInfiniteTest) {
|
||||
TribeResults.fadeUser("result", data.userId);
|
||||
}
|
||||
if (resolve?.afk) {
|
||||
|
|
@ -704,7 +723,7 @@ TribeSocket.in.room.userResult((data) => {
|
|||
await TribeChartController.drawChart(data.userId);
|
||||
}
|
||||
if (TribeState.getState() >= 21) {
|
||||
TribeChartController.updateChartMaxValues();
|
||||
void TribeChartController.updateChartMaxValues();
|
||||
}
|
||||
}, 250);
|
||||
}
|
||||
|
|
@ -761,14 +780,19 @@ TribeSocket.in.room.finalPositions((data) => {
|
|||
TribeResults.updateMiniCrowns("result", data.miniCrowns);
|
||||
for (const userArray of Object.values(data.positions)) {
|
||||
for (const user of userArray) {
|
||||
room.users[user.id].points = user.newPointsTotal;
|
||||
const u = room.users[user.id] as TribeTypes.User;
|
||||
u.points = user.newPointsTotal;
|
||||
}
|
||||
}
|
||||
TribeUserList.update();
|
||||
|
||||
let localGlow = false;
|
||||
|
||||
for (const winner of data.positions["1"]) {
|
||||
const positions = data.positions["1"];
|
||||
|
||||
if (!positions) return;
|
||||
|
||||
for (const winner of positions) {
|
||||
if (winner.id === TribeSocket.getId()) {
|
||||
localGlow = true;
|
||||
}
|
||||
|
|
@ -786,7 +810,7 @@ TribeSocket.in.room.finalPositions((data) => {
|
|||
TribeResults.showCrown("result", winner.id, isGlowing);
|
||||
}
|
||||
|
||||
if (data.positions[1].some((u) => u.id === TribeSocket.getId())) {
|
||||
if (positions.some((u) => u.id === TribeSocket.getId())) {
|
||||
TribeSound.play("finish_win");
|
||||
if (localGlow) {
|
||||
TribeSound.play("glow");
|
||||
|
|
@ -803,7 +827,7 @@ $(`.pageTribe .tribePage.lobby .lobbyButtons .startTestButton,
|
|||
|
||||
$(".pageTribe .tribePage.preloader .reconnectButton").on("click", () => {
|
||||
TribePagePreloader.hideReconnectButton();
|
||||
init();
|
||||
void init();
|
||||
});
|
||||
|
||||
window.addEventListener("beforeunload", () => {
|
||||
|
|
|
|||
134
frontend/src/ts/tribe/types.ts
Normal file
134
frontend/src/ts/tribe/types.ts
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
import { ChartData } from "@monkeytype/contracts/schemas/results";
|
||||
|
||||
export type SystemStats = {
|
||||
pingStart: number;
|
||||
stats: [
|
||||
number, // online users
|
||||
rooms: {
|
||||
mm: [number, number, number, number];
|
||||
custom: [number, number];
|
||||
},
|
||||
queueLengths: [number, number, number, number],
|
||||
version: string
|
||||
];
|
||||
};
|
||||
|
||||
export type InputSuggestionEntry = {
|
||||
display: string;
|
||||
imageIcon?: string;
|
||||
faIcon?: string;
|
||||
textIcon?: string;
|
||||
};
|
||||
|
||||
export type Result = {
|
||||
wpm: number;
|
||||
raw: number;
|
||||
acc: number;
|
||||
consistency: number;
|
||||
testDuration: number;
|
||||
charStats: number[];
|
||||
chartData: ChartData;
|
||||
resolve: ResultResolve;
|
||||
};
|
||||
|
||||
export type ResultResolve = {
|
||||
login?: boolean;
|
||||
saved?: boolean;
|
||||
failed?: boolean;
|
||||
afk?: boolean;
|
||||
repeated?: boolean;
|
||||
failedReason?: string;
|
||||
valid?: boolean;
|
||||
tooShort?: boolean;
|
||||
saveFailedMessage?: string;
|
||||
isPb?: boolean;
|
||||
bailedOut?: boolean;
|
||||
};
|
||||
|
||||
export type RoomJoin = {
|
||||
room: Room;
|
||||
};
|
||||
|
||||
export type Room = {
|
||||
id: string;
|
||||
state: number;
|
||||
users: {
|
||||
[socketId: string]: User;
|
||||
};
|
||||
size: number;
|
||||
updateRate: number;
|
||||
isPrivate: boolean;
|
||||
name: string;
|
||||
config: RoomConfig;
|
||||
maxRaw: number;
|
||||
maxWpm: number;
|
||||
minRaw: number;
|
||||
minWpm: number;
|
||||
seed: number;
|
||||
};
|
||||
|
||||
export type RoomConfig = {
|
||||
mode: string;
|
||||
mode2: string | number | number[];
|
||||
difficulty: string;
|
||||
language: string;
|
||||
punctuation: boolean;
|
||||
numbers: boolean;
|
||||
funbox: string;
|
||||
lazyMode: boolean;
|
||||
stopOnError: string;
|
||||
minWpm: number | "off";
|
||||
minAcc: number | "off";
|
||||
minBurst: number | "off";
|
||||
//todo fix
|
||||
// customText: {
|
||||
// text: string[];
|
||||
// isWordRandom: boolean;
|
||||
// isTimeRandom: boolean;
|
||||
// time: number;
|
||||
// word: number;
|
||||
// };
|
||||
isInfiniteTest: boolean;
|
||||
};
|
||||
|
||||
export type UserProgressOut = {
|
||||
wpm: number;
|
||||
raw: number;
|
||||
acc: number;
|
||||
progress: number;
|
||||
wordIndex: number;
|
||||
letterIndex: number;
|
||||
afk: boolean;
|
||||
};
|
||||
|
||||
export type UserProgress = {
|
||||
wpm: number;
|
||||
raw: number;
|
||||
acc: number;
|
||||
progress: number;
|
||||
wpmProgress: number;
|
||||
wordIndex: number;
|
||||
letterIndex: number;
|
||||
afk: boolean;
|
||||
};
|
||||
|
||||
export type User = {
|
||||
id: string;
|
||||
isLeader?: boolean;
|
||||
name: string;
|
||||
isReady?: boolean;
|
||||
result?: Result;
|
||||
progress?: UserProgress;
|
||||
isFinished?: boolean;
|
||||
isTyping?: boolean;
|
||||
isAfk?: boolean;
|
||||
isChatting?: boolean;
|
||||
points?: number;
|
||||
};
|
||||
|
||||
export type MiniCrowns = {
|
||||
raw: string[];
|
||||
wpm: string[];
|
||||
acc: string[];
|
||||
consistency: string[];
|
||||
};
|
||||
133
frontend/src/ts/types/tribe.d.ts
vendored
133
frontend/src/ts/types/tribe.d.ts
vendored
|
|
@ -1,133 +0,0 @@
|
|||
declare namespace TribeTypes {
|
||||
interface SystemStats {
|
||||
pingStart: number;
|
||||
stats: [
|
||||
number, // online users
|
||||
rooms: {
|
||||
mm: [number, number, number, number];
|
||||
custom: [number, number];
|
||||
},
|
||||
queueLengths: [number, number, number, number],
|
||||
version: string
|
||||
];
|
||||
}
|
||||
|
||||
interface InputSuggestionEntry {
|
||||
display: string;
|
||||
imageIcon?: string;
|
||||
faIcon?: string;
|
||||
textIcon?: string;
|
||||
}
|
||||
|
||||
interface Result {
|
||||
wpm: number;
|
||||
raw: number;
|
||||
acc: number;
|
||||
consistency: number;
|
||||
testDuration: number;
|
||||
charStats: number[];
|
||||
chartData: MonkeyTypes.ChartData;
|
||||
resolve: ResultResolve;
|
||||
}
|
||||
|
||||
interface ResultResolve {
|
||||
login?: boolean;
|
||||
saved?: boolean;
|
||||
failed?: boolean;
|
||||
afk?: boolean;
|
||||
repeated?: boolean;
|
||||
failedReason?: string;
|
||||
valid?: boolean;
|
||||
tooShort?: boolean;
|
||||
saveFailedMessage?: string;
|
||||
isPb?: boolean;
|
||||
bailedOut?: boolean;
|
||||
}
|
||||
|
||||
interface RoomJoin {
|
||||
room: Room;
|
||||
}
|
||||
|
||||
interface Room {
|
||||
id: string;
|
||||
state: number;
|
||||
users: {
|
||||
[socketId: string]: User;
|
||||
};
|
||||
size: number;
|
||||
updateRate: number;
|
||||
isPrivate: boolean;
|
||||
name: string;
|
||||
config: RoomConfig;
|
||||
maxRaw: number;
|
||||
maxWpm: number;
|
||||
minRaw: number;
|
||||
minWpm: number;
|
||||
seed: number;
|
||||
}
|
||||
|
||||
interface RoomConfig {
|
||||
mode: string;
|
||||
mode2: string | number | number[];
|
||||
difficulty: string;
|
||||
language: string;
|
||||
punctuation: boolean;
|
||||
numbers: boolean;
|
||||
funbox: string;
|
||||
lazyMode: boolean;
|
||||
stopOnError: string;
|
||||
minWpm: number | "off";
|
||||
minAcc: number | "off";
|
||||
minBurst: number | "off";
|
||||
customText: {
|
||||
text: string[];
|
||||
isWordRandom: boolean;
|
||||
isTimeRandom: boolean;
|
||||
time: number;
|
||||
word: number;
|
||||
};
|
||||
isInfiniteTest: boolean;
|
||||
}
|
||||
|
||||
interface UserProgressOut {
|
||||
wpm: number;
|
||||
raw: number;
|
||||
acc: number;
|
||||
progress: number;
|
||||
wordIndex: number;
|
||||
letterIndex: number;
|
||||
afk: boolean;
|
||||
}
|
||||
|
||||
interface UserProgress {
|
||||
wpm: number;
|
||||
raw: number;
|
||||
acc: number;
|
||||
progress: number;
|
||||
wpmProgress: number;
|
||||
wordIndex: number;
|
||||
letterIndex: number;
|
||||
afk: boolean;
|
||||
}
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
isLeader?: boolean;
|
||||
name: string;
|
||||
isReady?: boolean;
|
||||
result?: Result;
|
||||
progress?: UserProgress;
|
||||
isFinished?: boolean;
|
||||
isTyping?: boolean;
|
||||
isAfk?: boolean;
|
||||
isChatting?: boolean;
|
||||
points?: number;
|
||||
}
|
||||
|
||||
interface MiniCrowns {
|
||||
raw: string[];
|
||||
wpm: string[];
|
||||
acc: string[];
|
||||
consistency: string[];
|
||||
}
|
||||
}
|
||||
|
|
@ -434,3 +434,18 @@ export async function getReleasesFromGitHub(): Promise<GithubRelease[]> {
|
|||
"https://api.github.com/repos/monkeytypegame/monkeytype/releases?per_page=5"
|
||||
);
|
||||
}
|
||||
|
||||
export type Emoji = {
|
||||
type: "image" | "emoji";
|
||||
from: string;
|
||||
to: string;
|
||||
};
|
||||
|
||||
export async function getEmojiList(): Promise<Emoji[]> {
|
||||
try {
|
||||
const data = await cachedFetchJson<Emoji[]>("/./emoji/_list.json");
|
||||
return data;
|
||||
} catch (e) {
|
||||
throw new Error("Emoji list JSON fetch failed");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue