-
Loading DLCs: {loadingProgress}%
+
{isUpdating ? 'Updating DLC list' : 'Loading DLCs'}: {loadingProgress}%
{estimatedTimeLeft && (
Est. time left: {estimatedTimeLeft}
)}
@@ -211,15 +220,36 @@ const DlcSelectionDialog = ({
+ {/* Show update results if we found new DLCs */}
+ {newDlcsCount > 0 && !isUpdating && (
+
+
+ Found {newDlcsCount} new DLC{newDlcsCount > 1 ? 's' : ''}!
+
+
+ )}
+
-
@@ -228,4 +258,4 @@ const DlcSelectionDialog = ({
)
}
-export default DlcSelectionDialog
+export default DlcSelectionDialog
\ No newline at end of file
diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx
index 9f4232e..10b0f0f 100644
--- a/src/contexts/AppContext.tsx
+++ b/src/contexts/AppContext.tsx
@@ -1,6 +1,7 @@
import { createContext } from 'react'
import { Game, DlcInfo } from '@/types'
import { ActionType } from '@/components/buttons/ActionButton'
+import { DlcDialogState } from '@/hooks/useDlcManager'
// Types for context sub-components
export interface InstallationInstructions {
@@ -10,17 +11,6 @@ export interface InstallationInstructions {
dlc_count?: number
}
-export interface DlcDialogState {
- visible: boolean
- gameId: string
- gameTitle: string
- dlcs: DlcInfo[]
- isLoading: boolean
- isEditMode: boolean
- progress: number
- timeLeft?: string
-}
-
export interface ProgressDialogState {
visible: boolean
title: string
@@ -49,6 +39,7 @@ export interface AppContextType {
dlcDialog: DlcDialogState
handleGameEdit: (gameId: string) => void
handleDlcDialogClose: () => void
+ handleUpdateDlcs: (gameId: string) => Promise
// Game actions
progressDialog: ProgressDialogState
@@ -74,4 +65,4 @@ export interface AppContextType {
}
// Create the context with a default value
-export const AppContext = createContext(undefined)
+export const AppContext = createContext(undefined)
\ No newline at end of file
diff --git a/src/contexts/AppProvider.tsx b/src/contexts/AppProvider.tsx
index df09bd5..12e1e4f 100644
--- a/src/contexts/AppProvider.tsx
+++ b/src/contexts/AppProvider.tsx
@@ -25,6 +25,7 @@ export const AppProvider = ({ children }: AppProviderProps) => {
handleDlcDialogClose: closeDlcDialog,
streamGameDlcs,
handleGameEdit,
+ handleUpdateDlcs,
} = useDlcManager()
const {
@@ -220,6 +221,7 @@ export const AppProvider = ({ children }: AppProviderProps) => {
handleGameEdit(gameId, games)
},
handleDlcDialogClose: closeDlcDialog,
+ handleUpdateDlcs: (gameId: string) => handleUpdateDlcs(gameId),
// Game actions
progressDialog,
diff --git a/src/hooks/useDlcManager.ts b/src/hooks/useDlcManager.ts
index f403bac..4be1468 100644
--- a/src/hooks/useDlcManager.ts
+++ b/src/hooks/useDlcManager.ts
@@ -11,10 +11,12 @@ export interface DlcDialogState {
enabledDlcs: string[]
isLoading: boolean
isEditMode: boolean
+ isUpdating: boolean
progress: number
progressMessage: string
timeLeft: string
error: string | null
+ newDlcsCount: number
}
/**
@@ -36,10 +38,12 @@ export function useDlcManager() {
enabledDlcs: [],
isLoading: false,
isEditMode: false,
+ isUpdating: false,
progress: 0,
progressMessage: '',
timeLeft: '',
error: null,
+ newDlcsCount: 0,
})
// Set up event listeners for DLC streaming
@@ -80,6 +84,7 @@ export function useDlcManager() {
setDlcDialog((prev) => ({
...prev,
isLoading: false,
+ isUpdating: false,
}))
// Reset fetch state
@@ -177,10 +182,12 @@ export function useDlcManager() {
enabledDlcs: [],
isLoading: true,
isEditMode: true,
+ isUpdating: false,
progress: 0,
progressMessage: 'Reading DLC configuration...',
timeLeft: '',
error: null,
+ newDlcsCount: 0,
})
// Always get a fresh copy from the config file
@@ -302,6 +309,54 @@ export function useDlcManager() {
}
}, [dlcDialog.dlcs, dlcDialog.enabledDlcs])
+ // Function to update DLC list (refetch from Steam API)
+ const handleUpdateDlcs = async (gameId: string) => {
+ try {
+ // Store current app IDs to identify new DLCs later
+ const currentAppIds = new Set(dlcDialog.dlcs.map((dlc) => dlc.appid))
+
+ // Set updating state and clear DLCs
+ setDlcDialog((prev) => ({
+ ...prev,
+ isUpdating: true,
+ isLoading: true,
+ progress: 0,
+ progressMessage: 'Checking for new DLCs...',
+ newDlcsCount: 0,
+ dlcs: [], // Clear current DLCs to start fresh
+ }))
+
+ // Mark that we're fetching DLCs for this game
+ setIsFetchingDlcs(true)
+ activeDlcFetchId.current = gameId
+
+ // Start streaming DLCs
+ await streamGameDlcs(gameId)
+
+ // After streaming, calculate new DLCs
+ // This will be done when progress reaches 100% in the listener
+ setTimeout(() => {
+ setDlcDialog((prev) => {
+ const actualNewCount = prev.dlcs.filter(dlc => !currentAppIds.has(dlc.appid)).length
+
+ return {
+ ...prev,
+ newDlcsCount: actualNewCount > 0 ? actualNewCount : 0,
+ }
+ })
+ }, 1000)
+
+ } catch (error) {
+ console.error('Error updating DLCs:', error)
+ setDlcDialog((prev) => ({
+ ...prev,
+ error: `Failed to update DLCs: ${error}`,
+ isLoading: false,
+ isUpdating: false,
+ }))
+ }
+ }
+
return {
dlcDialog,
setDlcDialog,
@@ -309,6 +364,7 @@ export function useDlcManager() {
streamGameDlcs,
handleGameEdit,
handleDlcDialogClose,
+ handleUpdateDlcs,
forceReload,
}
-}
+}
\ No newline at end of file
diff --git a/src/styles/components/dialogs/_dlc_dialog.scss b/src/styles/components/dialogs/_dlc_dialog.scss
index 62c8123..36449c6 100644
--- a/src/styles/components/dialogs/_dlc_dialog.scss
+++ b/src/styles/components/dialogs/_dlc_dialog.scss
@@ -154,6 +154,28 @@
color: var(--text-secondary);
}
+// Update results message
+.dlc-update-results {
+ padding: 0.75rem 1.5rem;
+ background-color: var(--elevated-bg);
+ border: 1px solid var(--border-soft);
+ border-radius: var(--radius-sm);
+ margin-bottom: 0.75rem;
+
+ .update-success-message {
+ color: var(--text-primary);
+ font-weight: 600;
+ font-size: 0.9rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+
+ .dlc-update-icon {
+ color: var(--success);
+ }
+ }
+}
+
// Game information in DLC dialog
.dlc-game-info {
display: flex;