From ff2b6ee23e9d57409c50533b80edb51c4082a7bb Mon Sep 17 00:00:00 2001 From: 苏向夜 Date: Sun, 29 Mar 2026 21:41:13 +0800 Subject: fix(build): fix pnpm build --- packages/ui/src/components/game-console.tsx.bk | 290 +++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 packages/ui/src/components/game-console.tsx.bk (limited to 'packages/ui/src/components/game-console.tsx.bk') diff --git a/packages/ui/src/components/game-console.tsx.bk b/packages/ui/src/components/game-console.tsx.bk new file mode 100644 index 0000000..6980c8c --- /dev/null +++ b/packages/ui/src/components/game-console.tsx.bk @@ -0,0 +1,290 @@ +import { Copy, Download, Filter, Search, Trash2, X } from "lucide-react"; +import { useEffect, useRef, useState } from "react"; +import { useLogsStore } from "@/stores/logs-store"; +import { useUIStore } from "@/stores/ui-store"; + +export function GameConsole() { + const uiStore = useUIStore(); + const logsStore = useLogsStore(); + + const [searchTerm, setSearchTerm] = useState(""); + const [selectedLevels, setSelectedLevels] = useState>( + new Set(["info", "warn", "error", "debug", "fatal"]), + ); + const [autoScroll, setAutoScroll] = useState(true); + const consoleEndRef = useRef(null); + const logsContainerRef = useRef(null); + + const levelColors: Record = { + info: "text-blue-400", + warn: "text-amber-400", + error: "text-red-400", + debug: "text-purple-400", + fatal: "text-rose-400", + }; + + const levelBgColors: Record = { + info: "bg-blue-400/10", + warn: "bg-amber-400/10", + error: "bg-red-400/10", + debug: "bg-purple-400/10", + fatal: "bg-rose-400/10", + }; + + // Filter logs based on search term and selected levels + const filteredLogs = logsStore.logs.filter((log) => { + const matchesSearch = + searchTerm === "" || + log.message.toLowerCase().includes(searchTerm.toLowerCase()) || + log.source.toLowerCase().includes(searchTerm.toLowerCase()); + + const matchesLevel = selectedLevels.has(log.level); + + return matchesSearch && matchesLevel; + }); + + // Auto-scroll to bottom when new logs arrive or autoScroll is enabled + useEffect(() => { + if (autoScroll && consoleEndRef.current && filteredLogs.length > 0) { + consoleEndRef.current.scrollIntoView({ behavior: "smooth" }); + } + }, [filteredLogs, autoScroll]); + + // Handle keyboard shortcuts + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + // Ctrl/Cmd + K to focus search + if ((e.ctrlKey || e.metaKey) && e.key === "k") { + e.preventDefault(); + // Focus search input + const searchInput = document.querySelector( + 'input[type="text"]', + ) as HTMLInputElement; + if (searchInput) searchInput.focus(); + } + // Escape to close console + if (e.key === "Escape") { + uiStore.toggleConsole(); + } + }; + + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [uiStore.toggleConsole]); + + const toggleLevel = (level: string) => { + const newLevels = new Set(selectedLevels); + if (newLevels.has(level)) { + newLevels.delete(level); + } else { + newLevels.add(level); + } + setSelectedLevels(newLevels); + }; + + const handleCopyAll = () => { + const logsText = logsStore.exportLogs(filteredLogs); + navigator.clipboard.writeText(logsText); + }; + + const handleExport = () => { + const logsText = logsStore.exportLogs(filteredLogs); + const blob = new Blob([logsText], { type: "text/plain" }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = `dropout_logs_${new Date().toISOString().replace(/[:.]/g, "-")}.txt`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + }; + + const handleClear = () => { + logsStore.clear(); + }; + + return ( + <> + {/* Header */} +
+
+

Game Console

+
+ Logs: + + {filteredLogs.length} + + / + + {logsStore.logs.length} + +
+
+ +
+ + {/* Toolbar */} +
+ {/* Search */} +
+ + setSearchTerm(e.target.value)} + placeholder="Search logs..." + className="w-full pl-10 pr-4 py-2 bg-[#3E3E42] border border-zinc-600 rounded text-sm text-white placeholder:text-zinc-500 focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500" + /> + {searchTerm && ( + + )} +
+ + {/* Level Filters */} +
+ {Object.entries(levelColors).map(([level, colorClass]) => ( + + ))} +
+ + {/* Actions */} +
+ + + +
+ + {/* Auto-scroll Toggle */} +
+ +
+
+ + {/* Logs Container */} +
+ {filteredLogs.length === 0 ? ( +
+
+ +

No logs match the current filters

+
+
+ ) : ( +
+ {filteredLogs.map((log) => ( +
+
+
+ {log.level.toUpperCase()} +
+
+ {log.timestamp} +
+
+ [{log.source}] +
+
{log.message}
+
+
+ ))} +
+
+ )} +
+ + {/* Footer */} +
+
+
+ Total: + {logsStore.logs.length} + | Filtered: + {filteredLogs.length} +
+
+ + Ctrl+K + + to search +
+
+
+ Updated: + + {new Date().toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + })} + +
+
+ + ); +} -- cgit v1.2.3-70-g09d2