This commit is contained in:
Tickbase
2026-07-11 12:21:12 +02:00
parent f3ecca6cb0
commit 16b2cbf32a
+65 -30
View File
@@ -1,7 +1,8 @@
import { useState } from 'react' import { useState, useEffect } from 'react'
import { invoke } from '@tauri-apps/api/core' import { invoke } from '@tauri-apps/api/core'
import { useAppContext } from '@/contexts/useAppContext' import { useAppContext } from '@/contexts/useAppContext'
import { useAppLogic, useConflictDetection, useDisclaimer } from '@/hooks' import { useAppLogic, useConflictDetection, useDisclaimer } from '@/hooks'
import { GameVotes } from '@/components/common/VotesDisplay'
import './styles/main.scss' import './styles/main.scss'
// Layout components // Layout components
@@ -11,19 +12,20 @@ import {
InitialLoadingScreen, InitialLoadingScreen,
ErrorBoundary, ErrorBoundary,
UpdateScreen, UpdateScreen,
AnimatedBackground,
} from '@/components/layout' } from '@/components/layout'
// Dialog components // Dialog components
import { import {
ProgressDialog, ProgressDialog,
DlcSelectionDialog, DlcSelectionDialog,
SettingsDialog,
ConflictDialog, ConflictDialog,
DisclaimerDialog, DisclaimerDialog,
UnlockerSelectionDialog, UnlockerChoiceDialog,
} from '@/components/dialogs' } from '@/components/dialogs'
// Page components (Overview and Settings)
import { OverviewPage, SettingsPage } from '@/components/pages'
// Game components // Game components
import { GameList, EpicGameList } from '@/components/games' import { GameList, EpicGameList } from '@/components/games'
@@ -32,6 +34,8 @@ import { GameList, EpicGameList } from '@/components/games'
*/ */
function App() { function App() {
const [updateComplete, setUpdateComplete] = useState(false) const [updateComplete, setUpdateComplete] = useState(false)
const [creamVotes, setCreamVotes] = useState<GameVotes | null>(null)
const [smokeVotes, setSmokeVotes] = useState<GameVotes | null>(null)
const { showDisclaimer, handleDisclaimerClose } = useDisclaimer() const { showDisclaimer, handleDisclaimerClose } = useDisclaimer()
@@ -47,7 +51,7 @@ function App() {
handleRefresh, handleRefresh,
isLoading, isLoading,
error, error,
} = useAppLogic({ autoLoad: updateComplete }) } = useAppLogic()
// Get action handlers from context // Get action handlers from context
const { const {
@@ -60,9 +64,6 @@ function App() {
handleDlcConfirm, handleDlcConfirm,
handleGameEdit, handleGameEdit,
handleUpdateDlcs, handleUpdateDlcs,
settingsDialog,
handleSettingsOpen,
handleSettingsClose,
handleSmokeAPISettingsOpen, handleSmokeAPISettingsOpen,
handleOpenRating, handleOpenRating,
reportingEnabled, reportingEnabled,
@@ -84,6 +85,28 @@ function App() {
// Conflict detection // Conflict detection
const { conflicts, showDialog, resolveConflict, closeDialog } = useConflictDetection(games) const { conflicts, showDialog, resolveConflict, closeDialog } = useConflictDetection(games)
// Community vote data for the Steam unlocker choice dialog (Epic's
// equivalent choice has no vote data, so it skips this entirely)
useEffect(() => {
const gameId = unlockerSelectionDialog.gameId
if (!unlockerSelectionDialog.visible || !gameId) {
setCreamVotes(null)
setSmokeVotes(null)
return
}
invoke<GameVotes[]>('get_game_votes', { gameId })
.then((results) => {
setCreamVotes(results.find((v) => v.unlocker === 'creamlinux') ?? null)
setSmokeVotes(results.find((v) => v.unlocker === 'smokeapi') ?? null)
})
.catch(() => {
// Votes are non-critical, silently fall back to "No votes yet"
setCreamVotes(null)
setSmokeVotes(null)
})
}, [unlockerSelectionDialog.visible, unlockerSelectionDialog.gameId])
const handleSetFilter = async (f: string) => { const handleSetFilter = async (f: string) => {
setFilter(f) setFilter(f)
if (f === 'epic' && epicGames.length === 0 && !epicLoading) { if (f === 'epic' && epicGames.length === 0 && !epicLoading) {
@@ -126,26 +149,18 @@ function App() {
return ( return (
<ErrorBoundary> <ErrorBoundary>
<div className="app-container"> <div className="app-container">
{/* Animated background */}
<AnimatedBackground />
{/* Header with search */} {/* Header with search */}
<Header <Header onSearch={handleSearchChange} searchQuery={searchQuery} />
onRefresh={handleRefresh}
onSearch={handleSearchChange}
searchQuery={searchQuery}
refreshDisabled={isLoading}
/>
<div className="main-content"> <div className="main-content">
{/* Sidebar for filtering */} {/* Sidebar for filtering */}
<Sidebar <Sidebar setFilter={handleSetFilter} currentFilter={filter} />
setFilter={handleSetFilter}
currentFilter={filter}
onSettingsClick={handleSettingsOpen}
/>
{filter === 'epic' ? ( {filter === 'overview' ? (
<OverviewPage />
) : filter === 'settings' ? (
<SettingsPage />
) : filter === 'epic' ? (
<EpicGameList <EpicGameList
games={epicGames} games={epicGames}
isLoading={epicLoading} isLoading={epicLoading}
@@ -154,6 +169,7 @@ function App() {
onUninstallScream={handleEpicUninstallScream} onUninstallScream={handleEpicUninstallScream}
onUninstallKoaloader={handleEpicUninstallKoaloader} onUninstallKoaloader={handleEpicUninstallKoaloader}
onSettings={handleEpicSettings} onSettings={handleEpicSettings}
onRefresh={loadEpicGames}
/> />
) : error ? ( ) : error ? (
<div className="error-message"> <div className="error-message">
@@ -169,6 +185,7 @@ function App() {
onEdit={handleGameEdit} onEdit={handleGameEdit}
onSmokeAPISettings={handleSmokeAPISettingsOpen} onSmokeAPISettings={handleSmokeAPISettingsOpen}
onRate={handleOpenRating} onRate={handleOpenRating}
onRefresh={handleRefresh}
reportingEnabled={reportingEnabled} reportingEnabled={reportingEnabled}
/> />
)} )}
@@ -203,9 +220,6 @@ function App() {
onUpdate={handleUpdateDlcs} onUpdate={handleUpdateDlcs}
/> />
{/* Settings Dialog */}
<SettingsDialog visible={settingsDialog.visible} onClose={handleSettingsClose} />
{/* Conflict Detection Dialog */} {/* Conflict Detection Dialog */}
<ConflictDialog <ConflictDialog
visible={showDialog} visible={showDialog}
@@ -215,13 +229,34 @@ function App() {
/> />
{/* Unlocker Selection Dialog */} {/* Unlocker Selection Dialog */}
<UnlockerSelectionDialog <UnlockerChoiceDialog
visible={unlockerSelectionDialog.visible} visible={unlockerSelectionDialog.visible}
gameId={unlockerSelectionDialog.gameId}
gameTitle={unlockerSelectionDialog.gameTitle || ''} gameTitle={unlockerSelectionDialog.gameTitle || ''}
onClose={closeUnlockerDialog} onClose={closeUnlockerDialog}
onSelectCreamLinux={handleSelectCreamLinux} options={[
onSelectSmokeAPI={handleSelectSmokeAPI} {
key: 'cream',
title: 'CreamLinux',
badge: 'recommended',
description:
'Native Linux DLC unlocker. Works best with most native Linux games and provides better compatibility.',
votes: creamVotes,
buttonLabel: 'Install CreamLinux',
buttonVariant: 'primary',
onSelect: handleSelectCreamLinux,
},
{
key: 'smoke',
title: 'SmokeAPI',
badge: 'alternative',
description:
"Cross-platform DLC unlocker. Try this if CreamLinux doesn't work for your game. Automatically fetches DLC information.",
votes: smokeVotes,
buttonLabel: 'Install SmokeAPI',
buttonVariant: 'secondary',
onSelect: handleSelectSmokeAPI,
},
]}
/> />
{/* Disclaimer Dialog - Shows AFTER everything is loaded */} {/* Disclaimer Dialog - Shows AFTER everything is loaded */}