diff --git a/manifest.json b/manifest.json index 16fff83c..bb16c7dc 100644 --- a/manifest.json +++ b/manifest.json @@ -3,7 +3,7 @@ "description": "Shows Win/Lose/Draw and average accuracy for players on chess.com", "author": "thieleju", "manifest_version": 3, - "version": "2.4.0", + "version": "2.5.0", "permissions": ["activeTab", "scripting", "storage"], "action": { "default_locale": "en", diff --git a/package.json b/package.json index 61198081..acb962b3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "chess-com-insights", "private": true, - "version": "2.4.0", + "version": "2.5.0", "type": "module", "repository": { "type": "git", diff --git a/settings.json b/settings.json index f62b4aac..a25e432c 100644 --- a/settings.json +++ b/settings.json @@ -3,9 +3,16 @@ "FETCH_RETRY_DELAY": 600, "LOAD_DELAY": 1700, "query_selectors": { - "target_name": "user-tagline-username", - "target_top": "board-layout-top", - "target_bottom": "board-layout-bottom" + "top": "board-layout-top", + "bottom": "board-layout-bottom", + "normal": { + "username": "user-tagline-username", + "elementToAppend": "user-tagline-username" + }, + "compact": { + "username": "user-tagline-compact-username", + "elementToAppend": "user-tagline-compact-theatre" + } }, "colors": { "wins": "#6b9438", @@ -13,7 +20,11 @@ "draws": "#b38235" }, "defaultSettings": { - "game_modes": ["bullet", "blitz", "rapid"], + "game_modes": [ + "bullet", + "blitz", + "rapid" + ], "time_interval": "last 12 hours", "hide_own_stats": false, "show_accuracy": true, @@ -21,7 +32,12 @@ "popup_darkmode": true, "color_highlighting": false }, - "validGameModes": ["blitz", "rapid", "bullet", "daily"], + "validGameModes": [ + "blitz", + "rapid", + "bullet", + "daily" + ], "validTimeIntervals": [ "last hour", "last 6 hours", diff --git a/src/modules/SettingsManager.ts b/src/modules/SettingsManager.ts index e3375387..edf78f4d 100644 --- a/src/modules/SettingsManager.ts +++ b/src/modules/SettingsManager.ts @@ -67,7 +67,7 @@ export class SettingsManager { const validGameModes: GameMode[] = this.settingsJSON .validGameModes as GameMode[] - const isBoolean = (value: any) => typeof value === "boolean" + const isBoolean = (value: unknown) => typeof value === "boolean" const isValidGameMode = (mode: GameMode) => validGameModes.includes(mode) const isValidTimeInterval = (interval: TimeInterval) => validTimeIntervals.includes(interval) diff --git a/src/modules/StatsUpdater.ts b/src/modules/StatsUpdater.ts index 1addb9b6..ac34cb55 100644 --- a/src/modules/StatsUpdater.ts +++ b/src/modules/StatsUpdater.ts @@ -72,6 +72,8 @@ export class StatsUpdater { if (attachEventListeners) { this.attachFlipBoardClickEvent() this.attachSettingsUpdateListener() + this.attachTheatreModeClickEvent() + this.attachFocusModeClickEvent() } if (!startObserving) return @@ -207,6 +209,36 @@ export class StatsUpdater { } } + /** + * Attach click event listener to the theatre button. + */ + private attachTheatreModeClickEvent(): void { + const toggle_theatre_mode = this.uiWindow + .getDocument() + .getElementById("board-controls-theatre") + if (!toggle_theatre_mode) return + + toggle_theatre_mode.addEventListener("click", () => { + this.updateStatsForBothPlayers() + this.updateTitleForBothPlayers() + }) + } + + /** + * Attach click event listener to the focus button. + */ + private attachFocusModeClickEvent(): void { + const toggle_focus_mode = this.uiWindow + .getDocument() + .getElementById("board-controls-focus") + if (!toggle_focus_mode) return + + toggle_focus_mode.addEventListener("click", () => { + this.updateStatsForBothPlayers() + this.updateTitleForBothPlayers() + }) + } + /** * Attach click event listener to the flip board button. */ diff --git a/src/modules/UiUpdater.ts b/src/modules/UiUpdater.ts index fcfa7b74..74f347f5 100644 --- a/src/modules/UiUpdater.ts +++ b/src/modules/UiUpdater.ts @@ -11,9 +11,16 @@ export class UiUpdater { private color_draws: string private query_selectors: { - target_top: string - target_bottom: string - target_name: string + top: string + bottom: string + normal: { + username: string + elementToAppend: string + } + compact: { + username: string + elementToAppend: string + } } private uiWindow: UiWindow @@ -175,17 +182,16 @@ export class UiUpdater { * @returns {HTMLElement | null} The player element for the player, or null if not found. */ getPlayerElement(player: "top" | "bottom"): HTMLElement | null { - const target_top = this.query_selectors.target_top - const target_bottom = this.query_selectors.target_bottom - const target_name = this.query_selectors.target_name + const { top, bottom, normal, compact } = this.query_selectors + + const location = player === "top" ? top : bottom + const elementToAppend = this.isInCompactMode() + ? compact.elementToAppend + : normal.elementToAppend return this.uiWindow .getDocument() - .querySelector( - player === "top" - ? `.${target_top} .${target_name}` - : `.${target_bottom} .${target_name}` - ) as HTMLElement + .querySelector(`.${location} .${elementToAppend}`) as HTMLElement } /** @@ -229,17 +235,13 @@ export class UiUpdater { * @returns {string} The username of the player. */ getUsername(player: "top" | "bottom"): string { - const target_top = this.query_selectors.target_top - const target_bottom = this.query_selectors.target_bottom - const target_name = this.query_selectors.target_name + const { top, bottom, normal, compact } = this.query_selectors + const location = player === "top" ? top : bottom + const username = this.isInCompactMode() ? compact.username : normal.username const player_el = this.uiWindow .getDocument() - .querySelector( - player === "top" - ? `.${target_top} .${target_name}` - : `.${target_bottom} .${target_name}` - ) as HTMLElement + .querySelector(`.${location} .${username}`) as HTMLElement return player_el?.innerText || "" } @@ -255,4 +257,17 @@ export class UiUpdater { .getDocument() .querySelector(side === "top" ? ".flag-1" : ".flag-2") as HTMLElement } + + /** + * Checks whether the UI is in compact mode by looking for the normal user html element. + * + * @returns {boolean} A flag indicating whether the UI is in compact mode. + */ + isInCompactMode(): boolean { + const { top, normal } = this.query_selectors + const normalElementsVisible = this.uiWindow + .getDocument() + .querySelector(`.${top} .${normal.username}`) + return !normalElementsVisible + } } diff --git a/src/modules/UrlObserver.ts b/src/modules/UrlObserver.ts index 58568e72..b21e8e45 100644 --- a/src/modules/UrlObserver.ts +++ b/src/modules/UrlObserver.ts @@ -4,7 +4,9 @@ import { UiWindow } from "../types/wrapper" * MutationObserver for observing URL changes. */ export class UrlObserver { - private eventListeners: { [event: string]: ((...args: any[]) => void)[] } = {} + private eventListeners: { + [event: string]: ((...args: unknown[]) => void)[] + } = {} private mutationObserver: MutationObserver | null private prevPathname: string @@ -26,7 +28,7 @@ export class UrlObserver { * @param {Function} listener - The event listener function. * @returns {void} */ - on(event: string, listener: (...args: any[]) => void): void { + on(event: string, listener: (...args: unknown[]) => void): void { if (!this.eventListeners[event]) { this.eventListeners[event] = [] } @@ -41,7 +43,7 @@ export class UrlObserver { * @param {any[]} args - Arguments to pass to the listeners. * @returns {void} */ - private emit(event: string, ...args: any[]): void { + private emit(event: string, ...args: unknown[]): void { const listeners = this.eventListeners[event] if (listeners) { for (const listener of listeners) { diff --git a/src/types/settings.d.ts b/src/types/settings.d.ts index d5c3b8c9..d397f576 100644 --- a/src/types/settings.d.ts +++ b/src/types/settings.d.ts @@ -24,9 +24,16 @@ export interface SettingsJSON { FETCH_RETRY_DELAY: number LOAD_DELAY: number query_selectors: { - target_name: string - target_top: string - target_bottom: string + top: string + bottom: string + normal: { + username: string + elementToAppend: string + } + compact: { + username: string + elementToAppend: string + } } colors: { wins: string