Files
houseassassin 35d46f532a feat: v1.1.0 — Epic Games detection, favorites, recent, UI improvements
- electron/epic.ts: auto-detect Epic Games from Manifests/*.item (skip DLCs)
- electron/favorites.ts: persist favorites + recent (last 20) in userData
- electron/steam.ts: replace winreg callbacks with reg query execSync + fallback paths
- electron: new IPC handlers — favorites:get/toggle, recent:get; launch tracks recent
- UI: star button on cards (favorites), sort A→Z/Z→A toggle, skeleton loading,
  fade-in card animation, Epic/Favorites/Recent filter tabs, SVG placeholder with initials

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 12:28:52 +00:00

72 lines
1.6 KiB
TypeScript

import { existsSync, readdirSync, readFileSync } from 'fs'
import { join } from 'path'
export interface EpicGame {
id: string
name: string
appName: string
source: 'epic'
image: string
installed: true
}
interface EpicManifest {
DisplayName?: string
AppName?: string
MainGameAppName?: string
bIsIncompleteInstall?: boolean
AppCategories?: string[]
}
const MANIFESTS_DIR = 'C:\\ProgramData\\Epic\\EpicGamesLauncher\\Data\\Manifests'
export function detectEpicGames(): EpicGame[] {
if (process.platform !== 'win32') return []
if (!existsSync(MANIFESTS_DIR)) return []
let entries: string[]
try {
entries = readdirSync(MANIFESTS_DIR)
} catch {
return []
}
const games: EpicGame[] = []
for (const entry of entries) {
if (!entry.endsWith('.item')) continue
try {
const raw = readFileSync(join(MANIFESTS_DIR, entry), 'utf-8')
const m: EpicManifest = JSON.parse(raw)
const name = m.DisplayName
const appName = m.AppName
const mainApp = m.MainGameAppName
if (!name || !appName) continue
if (m.bIsIncompleteInstall) continue
// Skip DLCs
if (mainApp && appName !== mainApp) continue
// Only game categories
const cats = m.AppCategories ?? []
const isGame = cats.length === 0 || cats.some((c) => c.startsWith('games'))
if (!isGame) continue
games.push({
id: `epic_${appName}`,
name,
appName,
source: 'epic',
image: '',
installed: true,
})
} catch {
// skip bad manifests
}
}
games.sort((a, b) => a.name.localeCompare(b.name, 'ru'))
return games
}