diff --git a/crates/lanspread-tauri-deno-ts/src/components/calltoplay/CallToPlayOverlay.tsx b/crates/lanspread-tauri-deno-ts/src/components/calltoplay/CallToPlayOverlay.tsx index 4af3c06..14b0693 100644 --- a/crates/lanspread-tauri-deno-ts/src/components/calltoplay/CallToPlayOverlay.tsx +++ b/crates/lanspread-tauri-deno-ts/src/components/calltoplay/CallToPlayOverlay.tsx @@ -81,8 +81,7 @@ export const CallToPlayOverlay = ({ )} {sorted.map(nomination => { - const game = gameById.get(nomination.gameId); - if (!game) return null; + const game = gameById.get(nomination.gameId) ?? null; return ( diff --git a/crates/lanspread-tauri-deno-ts/src/components/calltoplay/CallToPlayTicker.tsx b/crates/lanspread-tauri-deno-ts/src/components/calltoplay/CallToPlayTicker.tsx index 288817d..65a4df5 100644 --- a/crates/lanspread-tauri-deno-ts/src/components/calltoplay/CallToPlayTicker.tsx +++ b/crates/lanspread-tauri-deno-ts/src/components/calltoplay/CallToPlayTicker.tsx @@ -75,7 +75,6 @@ export const CallToPlayTicker = ({ nominations, games, accent, onOpen }: Props)
{active.map(nomination => { const game = gameById.get(nomination.gameId); - if (!game) return null; const status = statusOf(nomination, now); if (status === 'started') return null; const ready = readyCountOf(nomination, now); @@ -102,7 +101,10 @@ export const CallToPlayTicker = ({ nominations, games, accent, onOpen }: Props) > {LABEL[status]} - {game.name} + {game?.name ?? 'Game unavailable here'} by {nomination.creator} {count} {time} diff --git a/crates/lanspread-tauri-deno-ts/src/components/calltoplay/NominationCard.tsx b/crates/lanspread-tauri-deno-ts/src/components/calltoplay/NominationCard.tsx index ec890b9..20da08f 100644 --- a/crates/lanspread-tauri-deno-ts/src/components/calltoplay/NominationCard.tsx +++ b/crates/lanspread-tauri-deno-ts/src/components/calltoplay/NominationCard.tsx @@ -20,7 +20,7 @@ import { CallToPlayParticipant, Game, Nomination } from '../../lib/types'; interface Props { nomination: Nomination; - game: Game; + game: Game | null; actorId: string | null; actions: CallToPlayActions; focused: boolean; @@ -94,7 +94,9 @@ export const NominationCard = ({ Math.min(100, (remaining / Math.max(1, nomination.deadline - windowStart)) * 100), ); const urgency = percentage < 20 ? 'high' : percentage < 50 ? 'mid' : 'low'; - const installedCount = (game.installed_peer_count ?? game.peer_count) + (game.installed ? 1 : 0); + const installedCount = game === null + ? 0 + : (game.installed_peer_count ?? game.peer_count) + (game.installed ? 1 : 0); const lanCount = Math.max(totalPeerCount + 1, installedCount); const timer = isStarted @@ -130,15 +132,19 @@ export const NominationCard = ({ >
- + {game + ? + :
}
-
{game.name}
+
{game?.name ?? 'Game unavailable here'}
{nomination.scheduledFor === null ? 'Called' : 'Scheduled'} by{' '} {nomination.creator} {nomination.scheduledFor !== null && ` · starts at ${formatClock(nomination.scheduledFor)}`} - {` · ${installedCount}/${lanCount} peers have it installed`} + {game + ? ` · ${installedCount}/${lanCount} peers have it installed` + : ` · this game is not in your current library (ID: ${nomination.gameId})`}
{timer} @@ -229,7 +235,7 @@ export const NominationCard = ({ interface CardActionsProps { nomination: Nomination; - game: Game; + game: Game | null; actorId: string | null; actions: CallToPlayActions; onLaunch: (game: Game) => void; @@ -274,7 +280,11 @@ const CardActions = ({ const readyCount = readyCountOf(nomination, now); if (isStarted) { - return
Launching {game.name}…
; + return ( +
+ {game ? `Launching ${game.name}…` : 'The match is starting.'} +
+ ); } if (scheduled) { if (isCreator) { @@ -310,9 +320,9 @@ const CardActions = ({ + >{game ? 'Start now' : 'Mark as started'} diff --git a/crates/lanspread-tauri-deno-ts/src/styles/launcher.css b/crates/lanspread-tauri-deno-ts/src/styles/launcher.css index 6093935..45f84ab 100644 --- a/crates/lanspread-tauri-deno-ts/src/styles/launcher.css +++ b/crates/lanspread-tauri-deno-ts/src/styles/launcher.css @@ -1933,6 +1933,14 @@ border-radius: 8px; overflow: hidden; } +.ctp-card-cover-missing { + width: 100%; height: 100%; + display: grid; place-items: center; + color: var(--t-3); + background: color-mix(in srgb, var(--bd-2) 55%, transparent); + border: 1px dashed var(--bd-2); +} +.ctp-card-cover-missing svg { width: 22px; height: 22px; } .ctp-card-info { flex: 1; min-width: 0; } .ctp-card-title { font-size: 14.5px; font-weight: 700; color: var(--t-1); } .ctp-card-sub { margin-top: 3px; font-size: 11.5px; color: var(--t-3); }