diff --git a/index.html b/index.html index 782f25d4c..2280fe292 100644 --- a/index.html +++ b/index.html @@ -120,12 +120,12 @@
diff --git a/src/client/GameModeSelector.ts b/src/client/GameModeSelector.ts index 0c98d2635..121527460 100644 --- a/src/client/GameModeSelector.ts +++ b/src/client/GameModeSelector.ts @@ -18,7 +18,7 @@ import { SinglePlayerModal } from "./SinglePlayerModal"; import { terrainMapFileLoader } from "./TerrainMapFileLoader"; import { getMapName, renderDuration, translateText } from "./Utils"; -const CARD_BG = "bg-[color-mix(in_oklab,var(--frenchBlue)_70%,black)]"; +const CARD_BG = "bg-sky-950"; @customElement("game-mode-selector") export class GameModeSelector extends LitElement { @@ -79,62 +79,93 @@ export class GameModeSelector extends LitElement { this.requestUpdate(); } - render() { + private getSortedLobbies(): PublicGameInfo[] { const ffa = this.lobbies?.games?.["ffa"]?.[0]; const teams = this.lobbies?.games?.["team"]?.[0]; const special = this.lobbies?.games?.["special"]?.[0]; + return [ffa, teams, special] + .filter((g): g is PublicGameInfo => !!g) + .sort((a, b) => a.startsAt - b.startsAt); + } + + private getLobbyTitleContent(lobby: PublicGameInfo): string | TemplateResult { + if (lobby === this.lobbies?.games?.["special"]?.[0]) { + const subtitle = this.getLobbyTitle(lobby); + const mainTitle = translateText("mode_selector.special_title"); + return subtitle + ? html` + ${mainTitle} + + ${subtitle} + + ` + : mainTitle; + } + return this.getLobbyTitle(lobby); + } + + render() { + const sorted = this.getSortedLobbies(); + const featured = sorted[0]; + const upcoming = sorted.slice(1); return html` -
- ${ffa ? this.renderLobbyCard(ffa, this.getLobbyTitle(ffa)) : nothing} - ${teams - ? this.renderLobbyCard(teams, this.getLobbyTitle(teams)) +
+ + ${featured + ? html`
+ ${this.renderFeaturedLobbyCard( + featured, + this.getLobbyTitleContent(featured), + )} +
+ ${upcoming.map((lobby) => + this.renderUpcomingLobbyCard( + lobby, + this.getLobbyTitleContent(lobby), + ), + )} +
+
` : nothing} - ${special ? this.renderSpecialLobbyCard(special) : nothing} - ${this.renderQuickActionsSection()} + + +
${this.renderSingleplayerButton()}
+ + +
${this.renderSecondaryActions()}
`; } - private renderSpecialLobbyCard(lobby: PublicGameInfo) { - const subtitle = this.getLobbyTitle(lobby); - const mainTitle = translateText("mode_selector.special_title"); - const titleContent = subtitle - ? html` - ${mainTitle} - - ${subtitle} - - ` - : mainTitle; - return this.renderLobbyCard(lobby, titleContent); + private renderSingleplayerButton() { + return html` + + `; } - private renderQuickActionsSection() { + private renderSecondaryActions() { return html` -
-
- ${this.renderSmallActionCard( - translateText("main.solo"), - this.openSinglePlayerModal, - )} - ${this.renderSmallActionCard( - translateText("mode_selector.ranked_title"), - this.openRankedMenu, - )} -
-
- ${this.renderSmallActionCard( - translateText("main.create"), - this.openHostLobby, - )} - ${this.renderSmallActionCard( - translateText("main.join"), - this.openJoinLobby, - )} -
+
+ ${this.renderSmallActionCard( + translateText("mode_selector.ranked_title"), + this.openRankedMenu, + )} + ${this.renderSmallActionCard( + translateText("main.create"), + this.openHostLobby, + )} + ${this.renderSmallActionCard( + translateText("main.join"), + this.openJoinLobby, + )}
`; } @@ -161,18 +192,92 @@ export class GameModeSelector extends LitElement { (document.querySelector("join-lobby-modal") as JoinLobbyModal)?.open(); }; - private renderSmallActionCard(title: string, onClick: () => void) { + private renderFeaturedLobbyCard( + lobby: PublicGameInfo, + titleContent: string | TemplateResult, + ) { + const mapType = lobby.gameConfig!.gameMap as GameMapType; + const mapImageSrc = terrainMapFileLoader.getMapData(mapType).webpPath; + const timeRemaining = Math.max( + 0, + Math.floor((lobby.startsAt - this.serverTimeOffset - Date.now()) / 1000), + ); + const timeDisplay = renderDuration(timeRemaining); + const mapName = getMapName(lobby.gameConfig?.gameMap); + const modifierLabels = this.getModifierLabels( + lobby.gameConfig?.publicGameModifiers, + ); + if (modifierLabels.length > 1) { + modifierLabels.sort((a, b) => a.length - b.length); + } + return html` `; } - private renderLobbyCard( + private renderUpcomingLobbyCard( lobby: PublicGameInfo, titleContent: string | TemplateResult, ) { @@ -185,72 +290,40 @@ export class GameModeSelector extends LitElement { const timeDisplay = renderDuration(timeRemaining); const mapName = getMapName(lobby.gameConfig?.gameMap); - const modifierLabels = this.getModifierLabels( - lobby.gameConfig?.publicGameModifiers, - ); - // Sort by length for visual consistency (shorter labels first) - if (modifierLabels.length > 1) { - modifierLabels.sort((a, b) => a.length - b.length); - } - return html` + `; + } + private validateAndJoin(lobby: PublicGameInfo) { if (!this.validateUsername()) return; diff --git a/src/client/components/PlayPage.ts b/src/client/components/PlayPage.ts index aec22ccf2..6386b1662 100644 --- a/src/client/components/PlayPage.ts +++ b/src/client/components/PlayPage.ts @@ -17,7 +17,7 @@ export class PlayPage extends LitElement {
+ +
+ +
- -
- -
-
- - -
-
- -