diff --git a/src/games/plugins/update-clients.ts b/src/games/plugins/update-clients.ts index d69d3b4c..e2dc0a8d 100644 --- a/src/games/plugins/update-clients.ts +++ b/src/games/plugins/update-clients.ts @@ -11,6 +11,8 @@ import { LogsLink } from '../views/html/logs-link' import { PlayerConnectionStatusIndicator } from '../views/html/player-connection-status-indicator' import { GameEventList } from '../views/html/game-event-list' import { GameSlot } from '../views/html/game-slot' +import { whenGameEnds } from '../when-game-ends' +import { GamesLink } from '../../html/components/games-link' // eslint-disable-next-line @typescript-eslint/require-await export default fp(async app => { @@ -44,6 +46,18 @@ export default fp(async app => { } }) + events.on('game:created', async () => { + const cmp = await GamesLink() + app.gateway.broadcast(() => cmp) + }) + + events.on('game:updated', d => + whenGameEnds(d, async () => { + const cmp = await GamesLink() + app.gateway.broadcast(() => cmp) + }), + ) + events.on('match/player:connected', async ({ steamId }) => { const player = await collections.players.findOne({ steamId }) if (!player) { diff --git a/src/games/when-game-ends.ts b/src/games/when-game-ends.ts new file mode 100644 index 00000000..e2003e5c --- /dev/null +++ b/src/games/when-game-ends.ts @@ -0,0 +1,19 @@ +import { GameState } from '../database/models/game.model' +import type { Events } from '../events' + +type EventProps = Events['game:updated'] + +export async function whenGameEnds( + { before, after }: EventProps, + fn: (props: EventProps) => Promise | void, +) { + if ( + before.state !== after.state && + [GameState.created, GameState.configuring, GameState.launching, GameState.started].includes( + before.state, + ) && + [GameState.ended, GameState.interrupted].includes(after.state) + ) { + await fn({ before, after }) + } +} diff --git a/src/html/components/games-link.tsx b/src/html/components/games-link.tsx new file mode 100644 index 00000000..9e4cd4b0 --- /dev/null +++ b/src/html/components/games-link.tsx @@ -0,0 +1,17 @@ +import { collections } from '../../database/collections' +import { GameState } from '../../database/models/game.model' +import { GameLiveIndicator } from './game-live-indicator' + +export async function GamesLink() { + const gamesLiveCount = await collections.games.countDocuments({ + state: { + $in: [GameState.created, GameState.configuring, GameState.launching, GameState.started], + }, + }) + return ( + 0 && 'accent']} id="navbar-games-link"> + {gamesLiveCount > 0 ? : <>} + Games + + ) +} diff --git a/src/html/components/navigation-bar.tsx b/src/html/components/navigation-bar.tsx index f06461a2..720c3f6d 100644 --- a/src/html/components/navigation-bar.tsx +++ b/src/html/components/navigation-bar.tsx @@ -1,4 +1,5 @@ import type { User } from '../../auth/types/user' +import { GamesLink } from './games-link' import { IconBrandDiscord, IconChartPie, IconCrown, IconHeart } from './icons' import { IconBrandSteam } from './icons/icon-brand-steam' import { Profile } from './profile' @@ -29,7 +30,7 @@ function Menu(props: Html.PropsWithChildren<{ user?: User | undefined }>) { return (
- Games + Players Rules diff --git a/src/main.css b/src/main.css index 057832b7..d42d6d0a 100644 --- a/src/main.css +++ b/src/main.css @@ -152,6 +152,10 @@ dialog::backdrop { &.active { background-color: theme(colors.abru.dark.20); } + + &.accent { + color: theme(colors.accent.DEFAULT); + } } .profile-menu-item {