updated gamebanner

This commit is contained in:
Linrador 2025-10-16 00:14:16 +02:00
parent fb200876d0
commit 844ac4fe33
4 changed files with 24 additions and 107 deletions

View File

@ -200,16 +200,22 @@ export default function GameBanner(props: GameBannerProps = {}) {
// optional: Connect-URI vom Server holen
useEffect(() => {
(async () => {
try {
const r = await fetch('/api/cs2/server', { cache: 'no-store' })
if (!r.ok) return
const j = await r.json()
if (j.connectHref) setConnectHref(j.connectHref)
} catch {}
})()
}, [])
(async () => {
try {
const r = await fetch('/api/cs2/server', { cache: 'no-store' })
if (!r.ok) return
const j = await r.json()
// akzeptiere mehrere mögliche Feldnamen aus deiner API/DB
const href: unknown =
j?.connectHref ?? j?.connectUri ?? j?.connectURL ?? j?.connect_url
if (typeof href === 'string' && href.trim()) {
setConnectHref(href.trim())
}
} catch {
// ignore network errors
}
})()
}, [])
// WS lifecycle
const aliveRef = useRef(true)
const retryRef = useRef<number | null>(null)
@ -320,9 +326,11 @@ export default function GameBanner(props: GameBannerProps = {}) {
const scoreStr = scoreProp ?? ((score.a == null || score.b == null) ? ' : ' : `${score.a} : ${score.b}`)
const envConnect =
process.env.NEXT_PUBLIC_CONNECT_HREF ||
process.env.NEXT_PUBLIC_STEAM_CONNECT_URI ||
process.env.NEXT_PUBLIC_CS2_CONNECT_URI ||
'steam://rungameid/730//+retry'
'steam://connect/94.130.66.149:27015/0000' // <- normaler connect-Link als letzter Fallback
const connectUri = connectUriProp ?? connectHref ?? envConnect
// --- Animation + Höhe an Spacer melden

View File

@ -1,81 +0,0 @@
// /src/app/[locale]/components/GameBannerHost.tsx
'use client'
import useSWR from 'swr'
import { useSession } from 'next-auth/react'
import GameBanner from './GameBanner'
import { useGameBannerStore } from '@/lib/useGameBannerStore'
type LiveCfg = {
activeMatchId: string | null
activeMapKey: string | null
activeMapLabel: string | null
activeMapBg: string | null
activeParticipants: string[] | null
activeSince: string | null
bannerExpiresAt?: string | null
updatedAt?: string
}
const fetcher = (url: string) => fetch(url, { cache: 'no-store' }).then(r => r.json())
export default function GameBannerHost() {
const banner = useGameBannerStore(s => s.gameBanner)
const setBanner = useGameBannerStore(s => s.setGameBanner)
const { data: session } = useSession()
const meId = session?.user?.steamId ? String(session.user.steamId) : null
const { data } = useSWR<{ ok: boolean; data: LiveCfg | null }>(
'/api/cs2/server/live',
fetcher,
{
revalidateOnMount: true,
revalidateIfStale: true,
dedupingInterval: 0,
refreshInterval: 30000,
fallbackData: { ok: true, data: null },
}
)
const cfg = data?.data ?? null
console.debug('[BannerHost] meId=', meId, 'participants=', cfg?.activeParticipants);
// --- robust notExpired (invalid date-strings => nicht blockieren)
const expiresMs = cfg?.bannerExpiresAt ? new Date(cfg.bannerExpiresAt).getTime() : null
const notExpired = expiresMs == null || Number.isFinite(expiresMs) && expiresMs > Date.now()
// --- Teilnehmer-Check (nur das!)
const meIsParticipant =
!!meId &&
Array.isArray(cfg?.activeParticipants) &&
cfg.activeParticipants.map(String).includes(meId)
// nur diese beiden Bedingungen:
const canShow = meIsParticipant && notExpired
if (!canShow) return null
const connectUriFallback =
process.env.NEXT_PUBLIC_STEAM_CONNECT_URI ||
process.env.NEXT_PUBLIC_CS2_CONNECT_URI ||
'steam://rungameid/730//+retry'
return (
<GameBanner
variant={banner?.variant ?? 'disconnected'}
visible={true}
zIndex={banner?.zIndex ?? 9999}
inline={banner?.inline ?? false}
serverLabel={banner?.serverLabel}
mapKey={banner?.mapKey ?? cfg?.activeMapKey ?? undefined}
mapLabel={banner?.mapLabel ?? cfg?.activeMapLabel ?? undefined}
bgUrl={banner?.bgUrl ?? cfg?.activeMapBg ?? undefined}
iconUrl={banner?.iconUrl}
connectUri={banner?.connectUri ?? connectUriFallback}
score={banner?.score ?? ' : '}
connectedCount={banner?.connectedCount ?? 0}
totalExpected={banner?.totalExpected ?? (cfg?.activeParticipants?.length ?? 0)}
onReconnect={() => {/* optional: auf connectUri navigieren */}}
onDisconnect={() => setBanner(null)}
/>
)
}

View File

@ -409,7 +409,6 @@ export default function MapVotePanel({ match }: Props) {
const holdMapRef = useRef<string | null>(null)
const submittedRef = useRef<boolean>(false)
const [progressByMap, setProgressByMap] = useState<Record<string, number>>({})
const lastEvtKeyRef = useRef<string>(''); // Dedupe gleicher Events
const resetHold = useCallback(() => {
if (rafRef.current) cancelAnimationFrame(rafRef.current)
@ -781,18 +780,7 @@ export default function MapVotePanel({ match }: Props) {
const shouldRefresh = isRefreshEvent(type);
if (shouldRefresh) {
// einfache Dedupe: gleicher Event-Key in kurzer Folge -> ignorieren
const evtKey = [
type,
evtMatchId ?? '',
evtTeamId ?? '',
actionType ?? '',
actionData ?? '',
].join('|');
if (evtKey === lastEvtKeyRef.current) return;
lastEvtKeyRef.current = evtKey;
scheduleReload(); // <— statt load()
scheduleReload();
}
}, [lastEvent, match.id, match.teamA?.id, match.teamB?.id, matchBaseTs, teamSteamIds, applyLeaderChange, scheduleReload]);
@ -1391,7 +1379,9 @@ export default function MapVotePanel({ match }: Props) {
src={mapLogo}
alt={label}
className="max-h-[70%] max-w-[88%] object-contain drop-shadow-lg"
fill
sizes={"max-h-[70%] max-w-[88%]"}
width={48}
height={48}
/>
<span className="px-2 py-0.5 rounded-md text-white/90 font-semibold text-xs md:text-sm">
{label}

View File

@ -66,7 +66,7 @@ export default async function RootLayout({children, params}: Props) {
<main className="flex-1 min-w-0 min-h-0 overflow-auto">
<div className="h-full min-h-0 box-border p-4 sm:p-6">{children}</div>
</main>
<GameBanner /> {/* ⬅️ nur noch diese */}
<GameBanner />
<GameBannerSpacer className="hidden sm:block" />
</div>
</div>