import { useEffect, useState } from 'react' import { Gamepad2, Plus, Trash2, Search, FolderOpen, Cpu, RefreshCw, Loader2 } from 'lucide-react' import { useTrackingStore } from '../store/tracking' import { GlassCard } from '../components/ui/GlassCard' import { NeonButton } from '../components/ui/NeonButton' import { Input } from '../components/ui/Input' import type { TrackedProcess } from '@shared/types' function formatTime(ms: number): string { const seconds = Math.floor(ms / 1000) const minutes = Math.floor(seconds / 60) const hours = Math.floor(minutes / 60) if (hours > 0) { const remainingMinutes = minutes % 60 return `${hours}ч ${remainingMinutes}м` } else if (minutes > 0) { return `${minutes}м` } else { return `${seconds}с` } } // System processes to filter out const SYSTEM_PROCESSES = new Set([ 'svchost', 'csrss', 'wininit', 'services', 'lsass', 'smss', 'winlogon', 'dwm', 'explorer', 'taskhost', 'conhost', 'spoolsv', 'searchhost', 'runtimebroker', 'sihost', 'fontdrvhost', 'ctfmon', 'dllhost', 'securityhealthservice', 'searchindexer', 'audiodg', 'wudfhost', 'system', 'registry', 'idle', 'memory compression', 'ntoskrnl', 'shellexperiencehost', 'startmenuexperiencehost', 'applicationframehost', 'systemsettings', 'textinputhost', 'searchui', 'cortana', 'lockapp', 'windowsinternal', 'taskhostw', 'wmiprvse', 'msiexec', 'trustedinstaller', 'tiworker', 'smartscreen', 'securityhealthsystray', 'sgrmbroker', 'gamebarpresencewriter', 'gamebar', 'gamebarftserver', 'microsoftedge', 'msedge', 'chrome', 'firefox', 'opera', 'brave', 'discord', 'slack', 'teams', 'zoom', 'skype', 'powershell', 'cmd', 'windowsterminal', 'code', 'devenv', 'node', 'npm', 'electron', 'vite' ]) export function GamesPage() { const { trackedGames, currentGame, loadTrackedGames, addGame, removeGame } = useTrackingStore() const [showAddModal, setShowAddModal] = useState(false) const [searchQuery, setSearchQuery] = useState('') const [addMode, setAddMode] = useState<'process' | 'manual'>('process') const [manualGame, setManualGame] = useState({ name: '', executableName: '' }) const [processes, setProcesses] = useState([]) const [isLoadingProcesses, setIsLoadingProcesses] = useState(false) useEffect(() => { loadTrackedGames() }, [loadTrackedGames]) const loadProcesses = async () => { setIsLoadingProcesses(true) try { const procs = await window.electronAPI.getRunningProcesses() // Filter out system processes and already tracked games const filtered = procs.filter(p => { const name = p.name.toLowerCase().replace('.exe', '') return !SYSTEM_PROCESSES.has(name) && !trackedGames.some(tg => tg.executableName.toLowerCase().replace('.exe', '') === name ) }) setProcesses(filtered) } catch (error) { console.error('Failed to load processes:', error) } finally { setIsLoadingProcesses(false) } } useEffect(() => { if (showAddModal && addMode === 'process') { loadProcesses() } }, [showAddModal, addMode]) const filteredProcesses = processes.filter( (proc) => proc.name.toLowerCase().includes(searchQuery.toLowerCase()) || (proc.windowTitle && proc.windowTitle.toLowerCase().includes(searchQuery.toLowerCase())) ) const handleAddProcess = async (process: TrackedProcess) => { const name = process.windowTitle || process.displayName || process.name.replace('.exe', '') await addGame({ id: `proc_${Date.now()}`, name: name, executableName: process.name, executablePath: process.executablePath, }) setShowAddModal(false) setSearchQuery('') } const handleAddManualGame = async () => { if (!manualGame.name || !manualGame.executableName) return await addGame({ id: `manual_${Date.now()}`, name: manualGame.name, executableName: manualGame.executableName, }) setShowAddModal(false) setManualGame({ name: '', executableName: '' }) } const handleRemoveGame = async (gameId: string) => { if (confirm('Удалить игру из отслеживания?')) { await removeGame(gameId) } } return (
{/* Header */}

Игры

} onClick={() => setShowAddModal(true)} > Добавить
{/* Games list */} {trackedGames.length === 0 ? (

Нет игр

Добавьте игры для отслеживания времени

setShowAddModal(true)}> Добавить игру
) : (
{trackedGames.map((game) => (
{currentGame === game.name &&
}

{game.name}

{formatTime(game.totalTime)} наиграно {game.steamAppId && ' • Steam'}

))}
)} {/* Add game modal */} {showAddModal && (

Добавить игру

{/* Mode tabs */}
{addMode === 'process' && ( <>
setSearchQuery(e.target.value)} icon={} />

Запустите игру и нажмите обновить

{isLoadingProcesses ? (
) : filteredProcesses.length === 0 ? (

{processes.length === 0 ? 'Нет подходящих процессов' : 'Ничего не найдено'}

) : ( filteredProcesses.slice(0, 20).map((proc) => ( )) )}
)} {addMode === 'manual' && (
setManualGame({ ...manualGame, name: e.target.value })} /> setManualGame({ ...manualGame, executableName: e.target.value })} /> Добавить
)}
)}
) }