diff --git a/src/App.tsx b/src/App.tsx
index 6abfe13..2e03e69 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -21,6 +21,7 @@ import {
SettingsDialog,
ConflictDialog,
DisclaimerDialog,
+ UnlockerSelectionDialog,
} from '@/components/dialogs'
// Game components
@@ -64,6 +65,10 @@ function App() {
handleSettingsClose,
handleSmokeAPISettingsOpen,
showToast,
+ unlockerSelectionDialog,
+ handleSelectCreamLinux,
+ handleSelectSmokeAPI,
+ closeUnlockerDialog,
} = useAppContext()
// Conflict detection
@@ -182,6 +187,15 @@ function App() {
onClose={closeDialog}
/>
+ {/* Unlocker Selection Dialog */}
+
+
{/* Disclaimer Dialog - Shows AFTER everything is loaded */}
diff --git a/src/components/games/GameItem.tsx b/src/components/games/GameItem.tsx
index 0cbd647..8e552f9 100644
--- a/src/components/games/GameItem.tsx
+++ b/src/components/games/GameItem.tsx
@@ -51,11 +51,14 @@ const GameItem = ({ game, onAction, onEdit, onSmokeAPISettings }: GameItemProps)
}, [game.id, imageUrl])
// Determine if we should show CreamLinux buttons (only for native games)
- const shouldShowCream = game.native === true
+ const shouldShowCream = game.native && game.cream_installed // Only show if installed (for uninstall)
// Determine if we should show SmokeAPI buttons (only for non-native games with API files)
const shouldShowSmoke = !game.native && game.api_files && game.api_files.length > 0
+ // Show generic button if nothing installed
+ const shouldShowUnlocker = game.native && !game.cream_installed && !game.smoke_installed
+
// Check if this is a Proton game without API files
const isProtonNoApi = !game.native && (!game.api_files || game.api_files.length === 0)
@@ -71,6 +74,11 @@ const GameItem = ({ game, onAction, onEdit, onSmokeAPISettings }: GameItemProps)
onAction(game.id, action)
}
+ const handleUnlockerAction = () => {
+ if (game.installing) return
+ onAction(game.id, 'install_unlocker')
+ }
+
// Handle edit button click
const handleEdit = () => {
if (onEdit && game.cream_installed) {
@@ -116,17 +124,27 @@ const GameItem = ({ game, onAction, onEdit, onSmokeAPISettings }: GameItemProps)
- {/* Show CreamLinux button only for native games */}
+ {/* Show generic "Install" button for native games with nothing installed */}
+ {shouldShowUnlocker && (
+
+ )}
+
+ {/* Show CreamLinux uninstall button if CreamLinux is installed */}
{shouldShowCream && (
)}
- {/* Show SmokeAPI button only for Proton/Windows games with API files */}
+ {/* Show SmokeAPI button for Proton games OR native games with SmokeAPI installed */}
{shouldShowSmoke && (
)}
+ {/* Show SmokeAPI uninstall for native games if installed */}
+ {game.native && game.smoke_installed && (
+
+ )}
+
{/* Show message for Proton games without API files */}
{isProtonNoApi && (
diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx
index 10b0f0f..911150b 100644
--- a/src/contexts/AppContext.tsx
+++ b/src/contexts/AppContext.tsx
@@ -62,6 +62,16 @@ export interface AppContextType {
type: 'success' | 'error' | 'warning' | 'info',
options?: Record
) => void
+
+ // Unlocker selection
+ unlockerSelectionDialog: {
+ visible: boolean
+ gameId: string | null
+ gameTitle: string | null
+ }
+ handleSelectCreamLinux: () => void
+ handleSelectSmokeAPI: () => void
+ closeUnlockerDialog: () => void
}
// Create the context with a default value
diff --git a/src/contexts/AppProvider.tsx b/src/contexts/AppProvider.tsx
index 12e1e4f..8302206 100644
--- a/src/contexts/AppProvider.tsx
+++ b/src/contexts/AppProvider.tsx
@@ -33,6 +33,10 @@ export const AppProvider = ({ children }: AppProviderProps) => {
handleCloseProgressDialog,
handleGameAction: executeGameAction,
handleDlcConfirm: executeDlcConfirm,
+ unlockerSelectionDialog,
+ handleSelectCreamLinux,
+ handleSelectSmokeAPI,
+ closeUnlockerDialog,
} = useGameActions()
const { toasts, removeToast, success, error: showError, warning, info } = useToasts()
@@ -241,6 +245,12 @@ export const AppProvider = ({ children }: AppProviderProps) => {
// Toast notifications
showToast,
+
+ // Unlocker selection
+ unlockerSelectionDialog,
+ handleSelectCreamLinux,
+ handleSelectSmokeAPI,
+ closeUnlockerDialog,
}
return (