diff --git a/frontend/src/ts/commandline/lists.ts b/frontend/src/ts/commandline/lists.ts index 742233fb9..d0c6f1893 100644 --- a/frontend/src/ts/commandline/lists.ts +++ b/frontend/src/ts/commandline/lists.ts @@ -259,7 +259,6 @@ export const commands: CommandsSubgroup = { ...TribeDeltaCommands, ...TribeCaretsCommands, - //sound ...SoundVolumeCommands, ...SoundOnClickCommands, @@ -500,12 +499,12 @@ const lists = { tags: TagsCommands[0]?.subgroup, resultSaving: ResultSavingCommands[0]?.subgroup, blindMode: BlindModeCommands[0]?.subgroup, - mode: ModeCommands[0].subgroup, - time: TimeCommands[0].subgroup, - words: WordsCommands[0].subgroup, - quoteLength: QuoteLengthCommands[0].subgroup, - punctuation: PunctuationCommands[0].subgroup, - numbers: NumbersCommands[0].subgroup, + mode: ModeCommands[0]?.subgroup, + time: TimeCommands[0]?.subgroup, + words: WordsCommands[0]?.subgroup, + quoteLength: QuoteLengthCommands[0]?.subgroup, + punctuation: PunctuationCommands[0]?.subgroup, + numbers: NumbersCommands[0]?.subgroup, }; export function doesListExist(listName: string): boolean { diff --git a/frontend/src/ts/commandline/lists/tribe-carets.ts b/frontend/src/ts/commandline/lists/tribe-carets.ts index e11bed1f0..ed9592e68 100644 --- a/frontend/src/ts/commandline/lists/tribe-carets.ts +++ b/frontend/src/ts/commandline/lists/tribe-carets.ts @@ -1,6 +1,7 @@ import * as UpdateConfig from "../../config"; +import { Command, CommandsSubgroup } from "../types"; -const subgroup: MonkeyTypes.CommandsSubgroup = { +const subgroup: CommandsSubgroup = { title: "Tribe carets...", configKey: "tribeCarets", list: [ @@ -31,7 +32,7 @@ const subgroup: MonkeyTypes.CommandsSubgroup = { ], }; -const commands: MonkeyTypes.Command[] = [ +const commands: Command[] = [ { id: "changeTribeCarets", display: "Tribe carets...", diff --git a/frontend/src/ts/commandline/lists/tribe-delta.ts b/frontend/src/ts/commandline/lists/tribe-delta.ts index 3545b5602..3efdc66e8 100644 --- a/frontend/src/ts/commandline/lists/tribe-delta.ts +++ b/frontend/src/ts/commandline/lists/tribe-delta.ts @@ -1,6 +1,7 @@ import * as UpdateConfig from "../../config"; +import { Command, CommandsSubgroup } from "../types"; -const subgroup: MonkeyTypes.CommandsSubgroup = { +const subgroup: CommandsSubgroup = { title: "Tribe delta...", configKey: "tribeDelta", list: [ @@ -31,7 +32,7 @@ const subgroup: MonkeyTypes.CommandsSubgroup = { ], }; -const commands: MonkeyTypes.Command[] = [ +const commands: Command[] = [ { id: "changeTribeDelta", display: "Tribe delta...", diff --git a/frontend/src/ts/controllers/input-controller.ts b/frontend/src/ts/controllers/input-controller.ts index 54ffb53d6..93f5beb04 100644 --- a/frontend/src/ts/controllers/input-controller.ts +++ b/frontend/src/ts/controllers/input-controller.ts @@ -1522,22 +1522,23 @@ $("#wordsInput").on("input", (event) => { if (popupVisible) { event.preventDefault(); return; + } - if ( - [10, 11].includes(TribeState.getState()) && - TribeState.getSelf()?.isTyping - ) { - event.preventDefault(); - return; - } + //this could be wrong + if ( + [10, 11].includes(TribeState.getState()) && + TribeState.getSelf()?.isTyping + ) { + event.preventDefault(); + return; + } - if ( - [10, 11].includes(TribeState.getState()) && - TribeState.getSelf()?.isTyping - ) { - event.preventDefault(); - return; - } + if ( + [10, 11].includes(TribeState.getState()) && + TribeState.getSelf()?.isTyping + ) { + event.preventDefault(); + return; } TestInput.setCurrentNotAfk(); diff --git a/frontend/src/ts/controllers/quotes-controller.ts b/frontend/src/ts/controllers/quotes-controller.ts index 6bd3bea0e..ce54f3346 100644 --- a/frontend/src/ts/controllers/quotes-controller.ts +++ b/frontend/src/ts/controllers/quotes-controller.ts @@ -153,9 +153,9 @@ class QuotesController { if (trulyRandom) { if (Config.quoteLength.length === 1) { - return randomElementFromArray( - this.quoteCollection.groups[Config.quoteLength[0]] - ); + const ql = Config.quoteLength[0] as number; + const group = this.quoteCollection.groups[ql] as Quote[]; + return randomElementFromArray(group); } else { return randomElementFromArray(this.quoteCollection.quotes); } diff --git a/frontend/src/ts/controllers/route-controller.ts b/frontend/src/ts/controllers/route-controller.ts index dca19b7d4..7dde4c346 100644 --- a/frontend/src/ts/controllers/route-controller.ts +++ b/frontend/src/ts/controllers/route-controller.ts @@ -68,7 +68,7 @@ const routes: Route[] = [ navigate("/tribe", navigateOptions); } } else { - PageController.change("test", { + void PageController.change("test", { tribeOverride: navigateOptions?.tribeOverride ?? false, force: navigateOptions?.force ?? false, }); @@ -163,7 +163,7 @@ const routes: Route[] = [ path: "/tribe", load: (params, navigateOptions): void => { if (navigateOptions?.tribeOverride === true) { - PageController.change("tribe", { + void PageController.change("tribe", { tribeOverride: navigateOptions?.tribeOverride ?? false, force: navigateOptions?.force ?? false, params, @@ -174,7 +174,7 @@ const routes: Route[] = [ if (TribeState.getState() == 22 && TribeState.getSelf()?.isLeader) { tribeSocket.out.room.backToLobby(); } else { - PageController.change("tribe", { + void PageController.change("tribe", { tribeOverride: navigateOptions?.tribeOverride ?? false, force: navigateOptions?.force ?? false, params, @@ -185,8 +185,8 @@ const routes: Route[] = [ { path: "/tribe/:roomId", load: (params): void => { - setAutoJoin(params["roomId"]); - PageController.change("tribe", { + setAutoJoin(params["roomId"] as string); + void PageController.change("tribe", { force: true, params, }); diff --git a/frontend/src/ts/elements/theme-colors.ts b/frontend/src/ts/elements/theme-colors.ts index 07bb850a0..6ca806921 100644 --- a/frontend/src/ts/elements/theme-colors.ts +++ b/frontend/src/ts/elements/theme-colors.ts @@ -11,9 +11,9 @@ let colors = { colorfulErrorExtra: "#7e2a33", }; -export async function get( - color: keyof MonkeyTypes.ThemeColors -): Promise { +export type ColorName = keyof typeof colors; + +export async function get(color: ColorName): Promise { if (!colors[color]) update(); return colors[color]; } diff --git a/frontend/src/ts/pages/page.ts b/frontend/src/ts/pages/page.ts index 23d8d031e..1dff10e5d 100644 --- a/frontend/src/ts/pages/page.ts +++ b/frontend/src/ts/pages/page.ts @@ -27,7 +27,7 @@ type PageProperties = { name: PageName; element: JQuery; path: string; - beforeHide?: () => Promise; + beforeHide?: (options: PageFunctionOptions) => Promise; afterHide?: () => Promise; beforeShow?: (options: Options) => Promise; afterShow?: () => Promise; diff --git a/frontend/src/ts/pages/settings.ts b/frontend/src/ts/pages/settings.ts index 2c68e955a..4c3927f82 100644 --- a/frontend/src/ts/pages/settings.ts +++ b/frontend/src/ts/pages/settings.ts @@ -434,12 +434,12 @@ async function initGroups(): Promise { "tribeDelta", UpdateConfig.setTribeDelta, "button" - ) as SettingsGroup; + ) as SettingsGroup; groups["tribeCarets"] = new SettingsGroup( "tribeCarets", UpdateConfig.setTribeCarets, "button" - ) as SettingsGroup; + ) as SettingsGroup; // groups.customLayoutfluid = new SettingsGroup( // "customLayoutfluid", // UpdateConfig.setCustomLayoutfluid diff --git a/frontend/src/ts/pages/test.ts b/frontend/src/ts/pages/test.ts index df8a6f1ba..9e9c7b5bf 100644 --- a/frontend/src/ts/pages/test.ts +++ b/frontend/src/ts/pages/test.ts @@ -8,7 +8,6 @@ import { updateFooterAndVerticalAds } from "../controllers/ad-controller"; import * as ModesNotice from "../elements/modes-notice"; import * as Keymap from "../elements/keymap"; import * as TribeState from "../tribe/tribe-state"; -import * as TestConfig from "../test/test-config"; export const page = new Page({ name: "test", diff --git a/frontend/src/ts/pages/tribe.ts b/frontend/src/ts/pages/tribe.ts index e297a5da1..245247ff2 100644 --- a/frontend/src/ts/pages/tribe.ts +++ b/frontend/src/ts/pages/tribe.ts @@ -3,18 +3,18 @@ import * as Tribe from "../tribe/tribe"; import * as TribeState from "../tribe/tribe-state"; import * as TribeChat from "../tribe/tribe-chat"; -export const page = new Page( - "tribe", - $(".page.pageTribe"), - "/tribe", - async () => { +export const page = new Page({ + name: "tribe", + element: $(".page.pageTribe"), + path: "/tribe", + beforeHide: async () => { // TODO: Fill it up later }, - async () => { + afterHide: async () => { // TODO: Fill it up later TribeChat.reset("lobby"); }, - async () => { + beforeShow: async () => { if (TribeState.getState() == 5) { TribeChat.fill("lobby"); setTimeout(() => { @@ -22,9 +22,9 @@ export const page = new Page( }, 50); } }, - async () => { + afterShow: async () => { if (TribeState.getState() < 1) { - Tribe.init(); + void Tribe.init(); } - } -); + }, +}); diff --git a/frontend/src/ts/popups/tribe-user-settings-popup.ts b/frontend/src/ts/popups/tribe-user-settings-popup.ts index bf0929f89..38ffe4bec 100644 --- a/frontend/src/ts/popups/tribe-user-settings-popup.ts +++ b/frontend/src/ts/popups/tribe-user-settings-popup.ts @@ -4,14 +4,15 @@ import tribeSocket from "../tribe/tribe-socket"; export function show(userId: string): void { if (!userId) { - return Notifications.add( + Notifications.add( "Cannot show user settings without passing in user id", -1 ); + return; } if ($("#tribeUserSettingsPopupWrapper").hasClass("hidden")) { $("#tribeUserSettingsPopup .title").text( - `User settings (${TribeState.getRoom()?.users[userId].name})` + `User settings (${TribeState.getRoom()?.users[userId]?.name})` ); $("#tribeUserSettingsPopup").attr("userid", userId); $("#tribeUserSettingsPopupWrapper") @@ -49,14 +50,14 @@ $("#tribeUserSettingsPopupWrapper").on("click", (e) => { $("#tribeUserSettingsPopup .button.banButton").on("click", () => { const userId = $("#tribeUserSettingsPopup").attr("userid"); - if (!userId) return; + if (userId === undefined) return; tribeSocket.out.room.banUser(userId); hide(); }); $("#tribeUserSettingsPopup .button.giveLeaderButton").on("click", () => { const userId = $("#tribeUserSettingsPopup").attr("userid"); - if (!userId) return; + if (userId === undefined) return; tribeSocket.out.room.giveLeader(userId); hide(); }); diff --git a/frontend/src/ts/test/result.ts b/frontend/src/ts/test/result.ts index c84d56c35..8303dd4a4 100644 --- a/frontend/src/ts/test/result.ts +++ b/frontend/src/ts/test/result.ts @@ -969,8 +969,8 @@ export async function update( if (room?.users) { for (const userId of Object.keys(room.users)) { if (userId === TribeState.getSelf()?.id) continue; - if (room.users[userId].isFinished) { - TribeChartController.drawChart(userId); + if (room.users[userId]?.isFinished) { + void TribeChartController.drawChart(userId); } } } diff --git a/frontend/src/ts/test/test-logic.ts b/frontend/src/ts/test/test-logic.ts index f06964c6c..ffad8bb49 100644 --- a/frontend/src/ts/test/test-logic.ts +++ b/frontend/src/ts/test/test-logic.ts @@ -70,6 +70,7 @@ import Format from "../utils/format"; import { QuoteLength } from "@monkeytype/contracts/schemas/configs"; import { Mode } from "@monkeytype/contracts/schemas/shared"; import { + ChartData, CompletedEvent, CustomTextDataWithTextLen, } from "@monkeytype/contracts/schemas/results"; @@ -687,9 +688,9 @@ export async function retrySavingResult(): Promise { Notifications.add("Retrying to save..."); const tribeChartData = { - wpm: [...(completedEvent.chartData as MonkeyTypes.ChartData).wpm], - raw: [...(completedEvent.chartData as MonkeyTypes.ChartData).raw], - err: [...(completedEvent.chartData as MonkeyTypes.ChartData).err], + wpm: [...(completedEvent.chartData as ChartData).wpm], + raw: [...(completedEvent.chartData as ChartData).raw], + err: [...(completedEvent.chartData as ChartData).err], }; await saveResult(completedEvent, tribeChartData, true); @@ -1127,11 +1128,11 @@ export async function finish(difficultyFailed = false): Promise { ); Result.updateTodayTracker(); - if (completedEvent.bailedOut === true) { + if (completedEvent.bailedOut) { resolve.bailedOut = true; } - if (completedEvent.bailedOut === true) { + if (completedEvent.bailedOut) { resolve.bailedOut = true; } @@ -1174,9 +1175,9 @@ export async function finish(difficultyFailed = false): Promise { } const tribeChartData = { - wpm: [...(completedEvent.chartData as MonkeyTypes.ChartData).wpm], - raw: [...(completedEvent.chartData as MonkeyTypes.ChartData).raw], - err: [...(completedEvent.chartData as MonkeyTypes.ChartData).err], + wpm: [...(completedEvent.chartData as ChartData).wpm], + raw: [...(completedEvent.chartData as ChartData).raw], + err: [...(completedEvent.chartData as ChartData).err], }; if (completedEvent.testDuration > 122) { @@ -1188,7 +1189,7 @@ export async function finish(difficultyFailed = false): Promise { if (dontSave) { void AnalyticsController.log("testCompletedInvalid"); resolveTestSavePromise(resolve); - TribeResults.send({ + void TribeResults.send({ wpm: completedEvent.wpm, raw: completedEvent.rawWpm, acc: completedEvent.acc, @@ -1221,7 +1222,7 @@ export async function finish(difficultyFailed = false): Promise { async function saveResult( completedEvent: CompletedEvent, - tribeChartData: SharedTypes.ChartData, + tribeChartData: ChartData, isRetrying: boolean ): Promise { if (!TestState.savingEnabled) { @@ -1234,7 +1235,7 @@ async function saveResult( resolve.saved = false; resolve.saveFailedMessage = "Disabled by user"; resolveTestSavePromise(resolve); - TribeResults.send({ + void TribeResults.send({ wpm: completedEvent.wpm, raw: completedEvent.rawWpm, acc: completedEvent.acc, @@ -1257,7 +1258,7 @@ async function saveResult( resolve.saved = false; resolve.saveFailedMessage = "Offline"; resolveTestSavePromise(resolve); - TribeResults.send({ + void TribeResults.send({ wpm: completedEvent.wpm, raw: completedEvent.rawWpm, acc: completedEvent.acc, @@ -1293,9 +1294,9 @@ async function saveResult( } resolve.login = true; resolve.saved = false; - resolve.saveFailedMessage = response.message; + resolve.saveFailedMessage = response.body.message; resolveTestSavePromise(resolve); - TribeResults.send({ + void TribeResults.send({ wpm: completedEvent.wpm, raw: completedEvent.rawWpm, acc: completedEvent.acc, @@ -1433,7 +1434,7 @@ async function saveResult( resolve.login = true; resolve.saved = true; - resolve.isPb = response?.data?.isPb ?? false; + resolve.isPb = response.body.data?.isPb ?? false; resolveTestSavePromise(resolve); @@ -1442,7 +1443,7 @@ async function saveResult( Notifications.add("Result saved", 1, { important: true }); } - TribeResults.send({ + void TribeResults.send({ wpm: completedEvent.wpm, raw: completedEvent.rawWpm, acc: completedEvent.acc, diff --git a/frontend/src/ts/test/test-ui.ts b/frontend/src/ts/test/test-ui.ts index 20d4253e0..7d29b61a5 100644 --- a/frontend/src/ts/test/test-ui.ts +++ b/frontend/src/ts/test/test-ui.ts @@ -589,27 +589,19 @@ function updateWordsHeight(force = false): void { $("#wordsWrapper").css({ overflow: "visible clip" }); } - $("#wordsWrapper") - .css("height", finalWrapperHeight + "px") - .css("overflow", "hidden"); - $(".outOfFocusWarning").css( - "margin-top", - finalWrapperHeight / 2 - Numbers.convertRemToPixels(1) / 2 + "px" - ); + setTimeout(() => { + $("#words").css("height", finalWordsHeight + "px"); + $("#wordsWrapper").css("height", finalWrapperHeight + "px"); + $(".outOfFocusWarning").css( + "margin-top", + finalWrapperHeight / 2 - convertRemToPixels(1) / 2 + "px" + ); + $("#typingTest .tribeCountdown").css( + "line-height", + finalWrapperHeight + "px" + ); + }, 0); } - - setTimeout(() => { - $("#words").css("height", finalWordsHeight + "px"); - $("#wordsWrapper").css("height", finalWrapperHeight + "px"); - $(".outOfFocusWarning").css( - "margin-top", - finalWrapperHeight / 2 - convertRemToPixels(1) / 2 + "px" - ); - $("#typingTest .tribeCountdown").css( - "line-height", - finalWrapperHeight + "px" - ); - }, 0); } export function addWord(word: string): void { @@ -673,7 +665,7 @@ export async function screenshot(): Promise { for (const fb of getActiveFunboxes()) { fb.functions?.applyGlobalCSS?.(); } - + if (TribeState.getState() > 5) { $(".pageTest #result .inviteLink").removeClass("hidden"); } @@ -1660,17 +1652,6 @@ $("#wordsInput").on("focusout", () => { Caret.hide(); }); -$(document).on("keypress", "#practiseWordsButton", (event) => { - if (event.keyCode == 13) { - PractiseWords.showPopup(true); - } -}); - -$(document.body).on("click", "#practiseWordsButton", () => { - // PractiseWords.init(); - PractiseWords.showPopup(); -}); - $(".pageTest").on("click", "#showWordHistoryButton", () => { toggleResultWords(); }); diff --git a/frontend/src/ts/test/words-generator.ts b/frontend/src/ts/test/words-generator.ts index 17f1b7e6d..d2e00f8f4 100644 --- a/frontend/src/ts/test/words-generator.ts +++ b/frontend/src/ts/test/words-generator.ts @@ -14,10 +14,6 @@ import * as Misc from "../utils/misc"; import * as Strings from "../utils/strings"; import * as Arrays from "../utils/arrays"; import * as TestState from "../test/test-state"; -import * as GetText from "../utils/generate"; -import * as Random from "../utils/random"; -import * as TribeState from "../tribe/tribe-state"; -import * as GetText from "../utils/generate"; import * as Random from "../utils/random"; import * as TribeState from "../tribe/tribe-state"; import * as GetText from "../utils/generate"; diff --git a/frontend/src/ts/tribe/pages/tribe-page-lobby.ts b/frontend/src/ts/tribe/pages/tribe-page-lobby.ts index 848df7a28..964c46210 100644 --- a/frontend/src/ts/tribe/pages/tribe-page-lobby.ts +++ b/frontend/src/ts/tribe/pages/tribe-page-lobby.ts @@ -132,19 +132,20 @@ export function updateRoomConfig(): void { } else if (room.config.mode === "custom") { let t = "Custom settings:"; - t += `\ntext length: ${CustomText.text.length}`; - if (CustomText.isTimeRandom || CustomText.isWordRandom) { - let r = ""; - let n = ""; - if (CustomText.isTimeRandom) { - r = "time"; - n = CustomText.time.toString(); - } else if (CustomText.isWordRandom) { - r = "words"; - n = CustomText.word.toString(); - } - t += `\nrandom: ${r} ${n}`; - } + t += `\ntext length: ${CustomText.getText().length}`; + //todo + // if (CustomText.isTimeRandom || CustomText.isWordRandom) { + // let r = ""; + // let n = ""; + // if (CustomText.isTimeRandom) { + // r = "time"; + // n = CustomText.time.toString(); + // } else if (CustomText.isWordRandom) { + // r = "words"; + // n = CustomText.word.toString(); + // } + // t += `\nrandom: ${r} ${n}`; + // } $(".pageTribe .tribePage.lobby .currentConfig .groups").append(`
diff --git a/frontend/src/ts/tribe/pages/tribe-page-menu.ts b/frontend/src/ts/tribe/pages/tribe-page-menu.ts index 8b3cab02f..32312ba02 100644 --- a/frontend/src/ts/tribe/pages/tribe-page-menu.ts +++ b/frontend/src/ts/tribe/pages/tribe-page-menu.ts @@ -49,7 +49,7 @@ function refreshQueueButtons(): void { queues.forEach((queue, id) => { if (queue) { atleastone = true; - $(buttons[id]).addClass("active"); + $(buttons[id] as HTMLElement).addClass("active"); } }); if (!atleastone) { diff --git a/frontend/src/ts/tribe/tribe-bars.ts b/frontend/src/ts/tribe/tribe-bars.ts index 9e25e63ee..076a87dc0 100644 --- a/frontend/src/ts/tribe/tribe-bars.ts +++ b/frontend/src/ts/tribe/tribe-bars.ts @@ -108,7 +108,7 @@ export function update(page: string, userId: string): void { } const user = room.users[userId]; - if (!el) { + if (!el || !user) { return; } @@ -162,7 +162,7 @@ export function completeBar(page: string, userId: string): void { export function fadeUser( page: string | undefined, userId: string, - changeColor?: keyof MonkeyTypes.ThemeColors + changeColor?: ThemeColors.ColorName ): void { if (page === undefined) { fadeUser("test", userId, changeColor); @@ -181,9 +181,9 @@ export function fadeUser( el.find(`.player[id=${userId}]`).addClass("faded"); - if (changeColor) { - ThemeColors.get(changeColor).then((color) => { - if (!el) return; + if (changeColor !== undefined) { + void ThemeColors.get(changeColor).then((color) => { + if (el === undefined) return; el.find(`.player[id=${userId}] .bar`).css("background-color", color); }); } diff --git a/frontend/src/ts/tribe/tribe-delta.ts b/frontend/src/ts/tribe/tribe-delta.ts index 313bcd7d6..2cda16e44 100644 --- a/frontend/src/ts/tribe/tribe-delta.ts +++ b/frontend/src/ts/tribe/tribe-delta.ts @@ -3,7 +3,7 @@ import Config from "../config"; import * as TestState from "../test/test-state"; import tribeSocket from "./tribe-socket"; import * as ConfigEvent from "../observables/config-event"; -import { mapRange } from "../utils/misc"; +import { mapRange } from "@monkeytype/util/numbers"; const el = $(".pageTest #miniTimerAndLiveWpm .tribeDelta"); const elBar = $(".pageTest #tribeDeltaBar"); diff --git a/frontend/src/ts/tribe/tribe-results.ts b/frontend/src/ts/tribe/tribe-results.ts index e4d4a82ce..c8704f48c 100644 --- a/frontend/src/ts/tribe/tribe-results.ts +++ b/frontend/src/ts/tribe/tribe-results.ts @@ -1,9 +1,9 @@ import * as TribeState from "./tribe-state"; -import * as Misc from "../utils/misc"; import Config from "../config"; 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"; const initialised: Record = {}; @@ -149,7 +149,7 @@ export function updatePositions( const userEl = $( `.pageTest #result #tribeResults table tbody tr.user[id="${user.id}"]` ); - const string = Misc.getPositionString(parseInt(position)); + const string = getOrdinalNumberString(parseInt(position)); userEl.find(".pos").text(string); userEl .find(".points") @@ -164,7 +164,7 @@ export function updatePositions( const el = $(".pageTest #result #tribeResults table tbody"); el.find("tr.user").each((_, userEl) => { const id = $(userEl).attr("id"); - if (id) { + if (id !== undefined) { elements[id] = $(userEl); } }); @@ -174,12 +174,13 @@ export function updatePositions( for (const [_pos, users] of Object.entries(positions)) { for (const user of users) { - el.append(elements[user.id]); + el.append(elements[user.id] as JQuery); + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete delete elements[user.id]; } } for (const id of Object.keys(elements)) { - el.append(elements[id]); + el.append(elements[id] as JQuery); } } } @@ -261,13 +262,13 @@ function updateUser(page: string, userId: string): void { otherText = "afk"; } else if (resolve.repeated) { otherText = "repeated"; - } else if (resolve.failed && room.config.isInfiniteTest === false) { + } else if (resolve.failed && !room.config.isInfiniteTest) { otherText = `failed(${resolve.failedReason})`; } else if (resolve.saved === false) { otherText = `save failed(${resolve.saveFailedMessage})`; } else if (resolve.valid === false) { otherText = `invalid`; - } else if (room.config.isInfiniteTest === true) { + } else if (room.config.isInfiniteTest) { otherText = `${Math.round(userResult.testDuration)}s`; } else if (resolve.saved && resolve.isPb) { otherText = "new pb"; @@ -280,8 +281,8 @@ function updateUser(page: string, userId: string): void { export function update(page: string, userId?: string): void { const room = TribeState.getRoom(); if (!room) return; - if (!initialised[page]) init(page); - if (userId) { + if (initialised[page] === undefined) init(page); + if (userId !== undefined) { updateUser(page, userId); } else { for (const [userId, user] of Object.entries(room.users)) { diff --git a/frontend/src/ts/tribe/tribe-socket/routes/room.ts b/frontend/src/ts/tribe/tribe-socket/routes/room.ts index d9e37e8af..13b7855a9 100644 --- a/frontend/src/ts/tribe/tribe-socket/routes/room.ts +++ b/frontend/src/ts/tribe/tribe-socket/routes/room.ts @@ -1,4 +1,6 @@ +import { Mode } from "@monkeytype/contracts/schemas/shared"; import Socket from "../socket"; +import { QuoteLength } from "@monkeytype/contracts/schemas/configs"; async function getPublicRooms( _page: number, @@ -86,8 +88,8 @@ function result(result: TribeTypes.Result): void { } function create( - mode: MonkeyTypes.Mode, - mode2: string | number | MonkeyTypes.QuoteLength[], + mode: Mode, + mode2: string | number | QuoteLength[], type?: string ): void { Socket.emit("room_create", { mode, mode2, type }); diff --git a/frontend/src/ts/tribe/tribe-sound.ts b/frontend/src/ts/tribe/tribe-sound.ts index 0fe87e967..7b692e838 100644 --- a/frontend/src/ts/tribe/tribe-sound.ts +++ b/frontend/src/ts/tribe/tribe-sound.ts @@ -24,6 +24,6 @@ export function play(name: string): void { if (!TribeState.getSelf()?.isTyping && ["cd", "cd_go"].includes(name)) { return; } - sounds[name].seek(0); - sounds[name].play(); + sounds[name]?.seek(0); + sounds[name]?.play(); } diff --git a/frontend/src/ts/tribe/tribe-stats.ts b/frontend/src/ts/tribe/tribe-stats.ts index c6af0ee14..1589dec49 100644 --- a/frontend/src/ts/tribe/tribe-stats.ts +++ b/frontend/src/ts/tribe/tribe-stats.ts @@ -13,7 +13,9 @@ export function hideLoading(): void { export function updateQueueButtons(): void { const buttons = $(".pageTribe .menu .matchmaking .buttons .button"); inQueueNumbers.forEach((num, index) => { - $(buttons[index]).find(".subtext .waiting").text(`Waiting: ${num}`); + $(buttons[index] as HTMLElement) + .find(".subtext .waiting") + .text(`Waiting: ${num}`); }); } @@ -41,12 +43,16 @@ export function updateMenuButtons( ): void { let buttons = $(".pageTribe .menu .matchmaking .buttons .button"); races.mm.forEach((num: number, index: number) => { - $(buttons[index]).find(".subtext .races").text(`Races: ${num}`); + $(buttons[index] as HTMLElement) + .find(".subtext .races") + .text(`Races: ${num}`); }); buttons = $(".pageTribe .menu .customRooms .buttons .button"); races.custom.forEach((num: number, index: number) => { - $(buttons[index]).find(".subtext .rooms").text(`Rooms: ${num}`); + $(buttons[index] as HTMLElement) + .find(".subtext .rooms") + .text(`Rooms: ${num}`); }); } @@ -55,7 +61,7 @@ let to: NodeJS.Timeout | null = null; export async function refresh(): Promise { showLoading(); - tribeSocket.out.system.stats(performance.now()).then((data) => { + void tribeSocket.out.system.stats(performance.now()).then((data) => { const ping = Math.round(performance.now() - data.pingStart); hideLoading(); setInQueue(data.stats[2]); @@ -78,7 +84,7 @@ export async function refresh(): Promise { ) { to = setTimeout(() => { to = null; - refresh(); + void refresh(); }, 15000); } } diff --git a/frontend/src/ts/utils/numbers.ts b/frontend/src/ts/utils/numbers.ts index cdd571fe9..e8c99bd7c 100644 --- a/frontend/src/ts/utils/numbers.ts +++ b/frontend/src/ts/utils/numbers.ts @@ -1,4 +1,5 @@ import { roundTo2 } from "@monkeytype/util/numbers"; +import * as Random from "./random"; /** * Converts a value in rem units to pixels based on the root element's font size. diff --git a/packages/contracts/src/schemas/configs.ts b/packages/contracts/src/schemas/configs.ts index 32a0dd763..43e2b472a 100644 --- a/packages/contracts/src/schemas/configs.ts +++ b/packages/contracts/src/schemas/configs.ts @@ -408,6 +408,7 @@ export const ConfigGroupNameSchema = z.enum([ "hideElements", "ads", "hidden", + "tribe", ]); export type ConfigGroupName = z.infer; @@ -500,6 +501,8 @@ export const ConfigGroupsLiteral = { lazyMode: "input", showAverage: "hideElements", maxLineWidth: "appearance", + tribeDelta: "tribe", + tribeCarets: "tribe", } as const satisfies Record; export type ConfigGroups = typeof ConfigGroupsLiteral; diff --git a/packages/util/src/numbers.ts b/packages/util/src/numbers.ts index aa090ca6b..2e18dc85c 100644 --- a/packages/util/src/numbers.ts +++ b/packages/util/src/numbers.ts @@ -125,3 +125,19 @@ export function mapRange( return result; } + +const suffixes = ["th", "st", "nd", "rd"]; +/** + * Gets the ordinal number string for a number. + * @param number The number to get the ordinal number string for. + * @returns The ordinal number string. + * @example getOrdinalNumberString(1) // "1st" + * @example getOrdinalNumberString(2) // "2nd" + * @returns The ordinal number string. + **/ +export function getOrdinalNumberString(number: number): string { + const lastTwo = number % 100; + const suffix = + suffixes[(lastTwo - 20) % 10] ?? suffixes[lastTwo] ?? suffixes[0]; + return `${number}${suffix}`; +}