fix: resolve build and lint issues for game page display

This commit is contained in:
2026-04-26 15:59:31 +08:00
parent e7e16d4772
commit b2ce6f966b
4 changed files with 22 additions and 14 deletions
+7 -4
View File
@@ -1,6 +1,6 @@
"use client" "use client"
import { useCallback, useState, useEffect, useMemo } from "react" import { useCallback, useState, useEffect, useMemo, useRef } from "react"
import Image from "next/image" import Image from "next/image"
import { import {
Gamepad2Icon, Gamepad2Icon,
@@ -215,11 +215,14 @@ export function GamePageClient({
}, [gameId]) }, [gameId])
// Initialize selected devices when stats load // Initialize selected devices when stats load
const didInitDevices = useRef(false)
useEffect(() => { useEffect(() => {
if (stats && selectedDevices.length === 0) { if (stats && !didInitDevices.current) {
setSelectedDevices(stats.deviceBreakdown.map((d) => d.hardwareSlug)) didInitDevices.current = true
const slugs = stats.deviceBreakdown.map((d) => d.hardwareSlug)
queueMicrotask(() => setSelectedDevices(slugs))
} }
}, [stats, selectedDevices.length]) }, [stats])
// Filtered stats // Filtered stats
const filteredStats = useMemo(() => { const filteredStats = useMemo(() => {
+1 -1
View File
@@ -1,7 +1,7 @@
"use client" "use client"
import { useMemo } from "react" import { useMemo } from "react"
import { EChartWrapper, CHART_THEME, getDeviceColor } from "./EChartWrapper" import { EChartWrapper, CHART_THEME } from "./EChartWrapper"
import type { EChartsOption } from "echarts" import type { EChartsOption } from "echarts"
interface BoxplotEntry { interface BoxplotEntry {
+10 -5
View File
@@ -4,7 +4,7 @@ import { AnimatePresence, motion } from "motion/react"
import logo from "@/app/icon.png" import logo from "@/app/icon.png"
import Image from "next/image" import Image from "next/image"
import Link from "next/link" import Link from "next/link"
import { useEffect, useLayoutEffect, useRef, useState } from "react" import { useEffect, useRef, useState } from "react"
import { CircleXIcon, Gamepad2Icon, MenuIcon, XIcon } from "lucide-react" import { CircleXIcon, Gamepad2Icon, MenuIcon, XIcon } from "lucide-react"
import { routes } from "@/lib/routes" import { routes } from "@/lib/routes"
import { usePathname, useRouter, useSearchParams } from "next/navigation" import { usePathname, useRouter, useSearchParams } from "next/navigation"
@@ -37,14 +37,19 @@ export default function Navbar() {
const [userMenuOpen, setUserMenuOpen] = useState(false) const [userMenuOpen, setUserMenuOpen] = useState(false)
// Sync search query with URL ?q= param // Sync search query with URL ?q= param
useLayoutEffect(() => { const searchQueryRef = useRef(searchQuery)
useEffect(() => {
searchQueryRef.current = searchQuery
}, [searchQuery])
useEffect(() => {
const q = searchParams.get("q") || "" const q = searchParams.get("q") || ""
if (q === searchQueryRef.current) return
// If the URL has a different value than our state, we're syncing after // If the URL has a different value than our state, we're syncing after
// a navigation — skip the next URL-write to avoid clearing the param // a navigation — skip the next URL-write to avoid clearing the param
if (q !== searchQuery) {
skipNextUrlWrite.current = true skipNextUrlWrite.current = true
} const id = setTimeout(() => setSearchQuery(q), 0)
setSearchQuery(q) return () => clearTimeout(id)
}, [searchParams]) }, [searchParams])
// Update URL when debounced query changes (skip if already matches) // Update URL when debounced query changes (skip if already matches)
+3 -3
View File
@@ -147,8 +147,8 @@ export const searchUnifiedRoutes = new Elysia({ prefix: "/search" }).get(
} }
// ── 2b. Raw Performer + best FPS ──────────────────────────────── // ── 2b. Raw Performer + best FPS ────────────────────────────────
let rawPerformerMap = new Map<string, boolean>() const rawPerformerMap = new Map<string, boolean>()
let bestFpsMap = new Map<string, number>() const bestFpsMap = new Map<string, number>()
if (localGameIds.length > 0) { if (localGameIds.length > 0) {
const perfStats = await db const perfStats = await db
@@ -181,7 +181,7 @@ export const searchUnifiedRoutes = new Elysia({ prefix: "/search" }).get(
} }
// ── 2c. Latest version ────────────────────────────────────────── // ── 2c. Latest version ──────────────────────────────────────────
let latestVersionMap = new Map<string, string>() const latestVersionMap = new Map<string, string>()
if (localGameIds.length > 0) { if (localGameIds.length > 0) {
const versionRows = await db const versionRows = await db