updated gamebanner
This commit is contained in:
parent
fb200876d0
commit
844ac4fe33
@ -205,11 +205,17 @@ export default function GameBanner(props: GameBannerProps = {}) {
|
|||||||
const r = await fetch('/api/cs2/server', { cache: 'no-store' })
|
const r = await fetch('/api/cs2/server', { cache: 'no-store' })
|
||||||
if (!r.ok) return
|
if (!r.ok) return
|
||||||
const j = await r.json()
|
const j = await r.json()
|
||||||
if (j.connectHref) setConnectHref(j.connectHref)
|
// akzeptiere mehrere mögliche Feldnamen aus deiner API/DB
|
||||||
} catch {}
|
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
|
// WS lifecycle
|
||||||
const aliveRef = useRef(true)
|
const aliveRef = useRef(true)
|
||||||
const retryRef = useRef<number | null>(null)
|
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 scoreStr = scoreProp ?? ((score.a == null || score.b == null) ? '– : –' : `${score.a} : ${score.b}`)
|
||||||
|
|
||||||
const envConnect =
|
const envConnect =
|
||||||
|
process.env.NEXT_PUBLIC_CONNECT_HREF ||
|
||||||
process.env.NEXT_PUBLIC_STEAM_CONNECT_URI ||
|
process.env.NEXT_PUBLIC_STEAM_CONNECT_URI ||
|
||||||
process.env.NEXT_PUBLIC_CS2_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
|
const connectUri = connectUriProp ?? connectHref ?? envConnect
|
||||||
|
|
||||||
// --- Animation + Höhe an Spacer melden
|
// --- Animation + Höhe an Spacer melden
|
||||||
|
|||||||
@ -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)}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -409,7 +409,6 @@ export default function MapVotePanel({ match }: Props) {
|
|||||||
const holdMapRef = useRef<string | null>(null)
|
const holdMapRef = useRef<string | null>(null)
|
||||||
const submittedRef = useRef<boolean>(false)
|
const submittedRef = useRef<boolean>(false)
|
||||||
const [progressByMap, setProgressByMap] = useState<Record<string, number>>({})
|
const [progressByMap, setProgressByMap] = useState<Record<string, number>>({})
|
||||||
const lastEvtKeyRef = useRef<string>(''); // Dedupe gleicher Events
|
|
||||||
|
|
||||||
const resetHold = useCallback(() => {
|
const resetHold = useCallback(() => {
|
||||||
if (rafRef.current) cancelAnimationFrame(rafRef.current)
|
if (rafRef.current) cancelAnimationFrame(rafRef.current)
|
||||||
@ -781,18 +780,7 @@ export default function MapVotePanel({ match }: Props) {
|
|||||||
|
|
||||||
const shouldRefresh = isRefreshEvent(type);
|
const shouldRefresh = isRefreshEvent(type);
|
||||||
if (shouldRefresh) {
|
if (shouldRefresh) {
|
||||||
// einfache Dedupe: gleicher Event-Key in kurzer Folge -> ignorieren
|
scheduleReload();
|
||||||
const evtKey = [
|
|
||||||
type,
|
|
||||||
evtMatchId ?? '',
|
|
||||||
evtTeamId ?? '',
|
|
||||||
actionType ?? '',
|
|
||||||
actionData ?? '',
|
|
||||||
].join('|');
|
|
||||||
if (evtKey === lastEvtKeyRef.current) return;
|
|
||||||
lastEvtKeyRef.current = evtKey;
|
|
||||||
|
|
||||||
scheduleReload(); // <— statt load()
|
|
||||||
}
|
}
|
||||||
}, [lastEvent, match.id, match.teamA?.id, match.teamB?.id, matchBaseTs, teamSteamIds, applyLeaderChange, 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}
|
src={mapLogo}
|
||||||
alt={label}
|
alt={label}
|
||||||
className="max-h-[70%] max-w-[88%] object-contain drop-shadow-lg"
|
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">
|
<span className="px-2 py-0.5 rounded-md text-white/90 font-semibold text-xs md:text-sm">
|
||||||
{label}
|
{label}
|
||||||
|
|||||||
@ -66,7 +66,7 @@ export default async function RootLayout({children, params}: Props) {
|
|||||||
<main className="flex-1 min-w-0 min-h-0 overflow-auto">
|
<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>
|
<div className="h-full min-h-0 box-border p-4 sm:p-6">{children}</div>
|
||||||
</main>
|
</main>
|
||||||
<GameBanner /> {/* ⬅️ nur noch diese */}
|
<GameBanner />
|
||||||
<GameBannerSpacer className="hidden sm:block" />
|
<GameBannerSpacer className="hidden sm:block" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user