mirror of
https://github.com/Novattz/creamlinux-installer.git
synced 2026-01-24 12:22:49 -05:00
update creamlinux config #64
This commit is contained in:
@@ -40,6 +40,7 @@ function App() {
|
|||||||
handleGameAction,
|
handleGameAction,
|
||||||
handleDlcConfirm,
|
handleDlcConfirm,
|
||||||
handleGameEdit,
|
handleGameEdit,
|
||||||
|
handleUpdateDlcs,
|
||||||
settingsDialog,
|
settingsDialog,
|
||||||
handleSettingsOpen,
|
handleSettingsOpen,
|
||||||
handleSettingsClose,
|
handleSettingsClose,
|
||||||
@@ -107,13 +108,17 @@ function App() {
|
|||||||
<DlcSelectionDialog
|
<DlcSelectionDialog
|
||||||
visible={dlcDialog.visible}
|
visible={dlcDialog.visible}
|
||||||
gameTitle={dlcDialog.gameTitle}
|
gameTitle={dlcDialog.gameTitle}
|
||||||
|
gameId={dlcDialog.gameId}
|
||||||
dlcs={dlcDialog.dlcs}
|
dlcs={dlcDialog.dlcs}
|
||||||
isLoading={dlcDialog.isLoading}
|
isLoading={dlcDialog.isLoading}
|
||||||
isEditMode={dlcDialog.isEditMode}
|
isEditMode={dlcDialog.isEditMode}
|
||||||
|
isUpdating={dlcDialog.isUpdating}
|
||||||
loadingProgress={dlcDialog.progress}
|
loadingProgress={dlcDialog.progress}
|
||||||
estimatedTimeLeft={dlcDialog.timeLeft}
|
estimatedTimeLeft={dlcDialog.timeLeft}
|
||||||
|
newDlcsCount={dlcDialog.newDlcsCount}
|
||||||
onClose={handleDlcDialogClose}
|
onClose={handleDlcDialogClose}
|
||||||
onConfirm={handleDlcConfirm}
|
onConfirm={handleDlcConfirm}
|
||||||
|
onUpdate={handleUpdateDlcs}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Settings Dialog */}
|
{/* Settings Dialog */}
|
||||||
|
|||||||
@@ -6,17 +6,22 @@ import DialogFooter from './DialogFooter'
|
|||||||
import DialogActions from './DialogActions'
|
import DialogActions from './DialogActions'
|
||||||
import { Button, AnimatedCheckbox } from '@/components/buttons'
|
import { Button, AnimatedCheckbox } from '@/components/buttons'
|
||||||
import { DlcInfo } from '@/types'
|
import { DlcInfo } from '@/types'
|
||||||
|
import { Icon, check } from '@/components/icons'
|
||||||
|
|
||||||
export interface DlcSelectionDialogProps {
|
export interface DlcSelectionDialogProps {
|
||||||
visible: boolean
|
visible: boolean
|
||||||
gameTitle: string
|
gameTitle: string
|
||||||
|
gameId: string
|
||||||
dlcs: DlcInfo[]
|
dlcs: DlcInfo[]
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
onConfirm: (selectedDlcs: DlcInfo[]) => void
|
onConfirm: (selectedDlcs: DlcInfo[]) => void
|
||||||
|
onUpdate?: (gameId: string) => void
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
isEditMode?: boolean
|
isEditMode?: boolean
|
||||||
|
isUpdating?: boolean
|
||||||
loadingProgress?: number
|
loadingProgress?: number
|
||||||
estimatedTimeLeft?: string
|
estimatedTimeLeft?: string
|
||||||
|
newDlcsCount?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,13 +32,17 @@ export interface DlcSelectionDialogProps {
|
|||||||
const DlcSelectionDialog = ({
|
const DlcSelectionDialog = ({
|
||||||
visible,
|
visible,
|
||||||
gameTitle,
|
gameTitle,
|
||||||
|
gameId,
|
||||||
dlcs,
|
dlcs,
|
||||||
onClose,
|
onClose,
|
||||||
onConfirm,
|
onConfirm,
|
||||||
|
onUpdate,
|
||||||
isLoading,
|
isLoading,
|
||||||
isEditMode = false,
|
isEditMode = false,
|
||||||
|
isUpdating = false,
|
||||||
loadingProgress = 0,
|
loadingProgress = 0,
|
||||||
estimatedTimeLeft = '',
|
estimatedTimeLeft = '',
|
||||||
|
newDlcsCount = 0,
|
||||||
}: DlcSelectionDialogProps) => {
|
}: DlcSelectionDialogProps) => {
|
||||||
// State for DLC management
|
// State for DLC management
|
||||||
const [selectedDlcs, setSelectedDlcs] = useState<DlcInfo[]>([])
|
const [selectedDlcs, setSelectedDlcs] = useState<DlcInfo[]>([])
|
||||||
@@ -169,13 +178,13 @@ const DlcSelectionDialog = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isLoading && loadingProgress > 0 && (
|
{(isLoading || isUpdating) && loadingProgress > 0 && (
|
||||||
<div className="dlc-loading-progress">
|
<div className="dlc-loading-progress">
|
||||||
<div className="progress-bar-container">
|
<div className="progress-bar-container">
|
||||||
<div className="progress-bar" style={{ width: `${loadingProgress}%` }} />
|
<div className="progress-bar" style={{ width: `${loadingProgress}%` }} />
|
||||||
</div>
|
</div>
|
||||||
<div className="loading-details">
|
<div className="loading-details">
|
||||||
<span>Loading DLCs: {loadingProgress}%</span>
|
<span>{isUpdating ? 'Updating DLC list' : 'Loading DLCs'}: {loadingProgress}%</span>
|
||||||
{estimatedTimeLeft && (
|
{estimatedTimeLeft && (
|
||||||
<span className="time-left">Est. time left: {estimatedTimeLeft}</span>
|
<span className="time-left">Est. time left: {estimatedTimeLeft}</span>
|
||||||
)}
|
)}
|
||||||
@@ -211,15 +220,36 @@ const DlcSelectionDialog = ({
|
|||||||
</DialogBody>
|
</DialogBody>
|
||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
|
{/* Show update results if we found new DLCs */}
|
||||||
|
{newDlcsCount > 0 && !isUpdating && (
|
||||||
|
<div className="dlc-update-results">
|
||||||
|
<span className="update-success-message">
|
||||||
|
<Icon name={check} size="sm" variant="solid" className="dlc-update-icon" /> Found {newDlcsCount} new DLC{newDlcsCount > 1 ? 's' : ''}!
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
disabled={isLoading && loadingProgress < 10}
|
disabled={(isLoading || isUpdating) && loadingProgress < 10}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="primary" onClick={handleConfirm} disabled={isLoading}>
|
|
||||||
|
{/* Update button - only show in edit mode */}
|
||||||
|
{isEditMode && onUpdate && (
|
||||||
|
<Button
|
||||||
|
variant="warning"
|
||||||
|
onClick={() => onUpdate(gameId)}
|
||||||
|
disabled={isLoading || isUpdating}
|
||||||
|
>
|
||||||
|
{isUpdating ? 'Updating...' : 'Update DLC List'}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Button variant="primary" onClick={handleConfirm} disabled={isLoading || isUpdating}>
|
||||||
{actionButtonText}
|
{actionButtonText}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { createContext } from 'react'
|
import { createContext } from 'react'
|
||||||
import { Game, DlcInfo } from '@/types'
|
import { Game, DlcInfo } from '@/types'
|
||||||
import { ActionType } from '@/components/buttons/ActionButton'
|
import { ActionType } from '@/components/buttons/ActionButton'
|
||||||
|
import { DlcDialogState } from '@/hooks/useDlcManager'
|
||||||
|
|
||||||
// Types for context sub-components
|
// Types for context sub-components
|
||||||
export interface InstallationInstructions {
|
export interface InstallationInstructions {
|
||||||
@@ -10,17 +11,6 @@ export interface InstallationInstructions {
|
|||||||
dlc_count?: number
|
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 {
|
export interface ProgressDialogState {
|
||||||
visible: boolean
|
visible: boolean
|
||||||
title: string
|
title: string
|
||||||
@@ -49,6 +39,7 @@ export interface AppContextType {
|
|||||||
dlcDialog: DlcDialogState
|
dlcDialog: DlcDialogState
|
||||||
handleGameEdit: (gameId: string) => void
|
handleGameEdit: (gameId: string) => void
|
||||||
handleDlcDialogClose: () => void
|
handleDlcDialogClose: () => void
|
||||||
|
handleUpdateDlcs: (gameId: string) => Promise<void>
|
||||||
|
|
||||||
// Game actions
|
// Game actions
|
||||||
progressDialog: ProgressDialogState
|
progressDialog: ProgressDialogState
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export const AppProvider = ({ children }: AppProviderProps) => {
|
|||||||
handleDlcDialogClose: closeDlcDialog,
|
handleDlcDialogClose: closeDlcDialog,
|
||||||
streamGameDlcs,
|
streamGameDlcs,
|
||||||
handleGameEdit,
|
handleGameEdit,
|
||||||
|
handleUpdateDlcs,
|
||||||
} = useDlcManager()
|
} = useDlcManager()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -220,6 +221,7 @@ export const AppProvider = ({ children }: AppProviderProps) => {
|
|||||||
handleGameEdit(gameId, games)
|
handleGameEdit(gameId, games)
|
||||||
},
|
},
|
||||||
handleDlcDialogClose: closeDlcDialog,
|
handleDlcDialogClose: closeDlcDialog,
|
||||||
|
handleUpdateDlcs: (gameId: string) => handleUpdateDlcs(gameId),
|
||||||
|
|
||||||
// Game actions
|
// Game actions
|
||||||
progressDialog,
|
progressDialog,
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ export interface DlcDialogState {
|
|||||||
enabledDlcs: string[]
|
enabledDlcs: string[]
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
isEditMode: boolean
|
isEditMode: boolean
|
||||||
|
isUpdating: boolean
|
||||||
progress: number
|
progress: number
|
||||||
progressMessage: string
|
progressMessage: string
|
||||||
timeLeft: string
|
timeLeft: string
|
||||||
error: string | null
|
error: string | null
|
||||||
|
newDlcsCount: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,10 +38,12 @@ export function useDlcManager() {
|
|||||||
enabledDlcs: [],
|
enabledDlcs: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isEditMode: false,
|
isEditMode: false,
|
||||||
|
isUpdating: false,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
progressMessage: '',
|
progressMessage: '',
|
||||||
timeLeft: '',
|
timeLeft: '',
|
||||||
error: null,
|
error: null,
|
||||||
|
newDlcsCount: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Set up event listeners for DLC streaming
|
// Set up event listeners for DLC streaming
|
||||||
@@ -80,6 +84,7 @@ export function useDlcManager() {
|
|||||||
setDlcDialog((prev) => ({
|
setDlcDialog((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
|
isUpdating: false,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Reset fetch state
|
// Reset fetch state
|
||||||
@@ -177,10 +182,12 @@ export function useDlcManager() {
|
|||||||
enabledDlcs: [],
|
enabledDlcs: [],
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
isEditMode: true,
|
isEditMode: true,
|
||||||
|
isUpdating: false,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
progressMessage: 'Reading DLC configuration...',
|
progressMessage: 'Reading DLC configuration...',
|
||||||
timeLeft: '',
|
timeLeft: '',
|
||||||
error: null,
|
error: null,
|
||||||
|
newDlcsCount: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Always get a fresh copy from the config file
|
// Always get a fresh copy from the config file
|
||||||
@@ -302,6 +309,54 @@ export function useDlcManager() {
|
|||||||
}
|
}
|
||||||
}, [dlcDialog.dlcs, dlcDialog.enabledDlcs])
|
}, [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 {
|
return {
|
||||||
dlcDialog,
|
dlcDialog,
|
||||||
setDlcDialog,
|
setDlcDialog,
|
||||||
@@ -309,6 +364,7 @@ export function useDlcManager() {
|
|||||||
streamGameDlcs,
|
streamGameDlcs,
|
||||||
handleGameEdit,
|
handleGameEdit,
|
||||||
handleDlcDialogClose,
|
handleDlcDialogClose,
|
||||||
|
handleUpdateDlcs,
|
||||||
forceReload,
|
forceReload,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,6 +154,28 @@
|
|||||||
color: var(--text-secondary);
|
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
|
// Game information in DLC dialog
|
||||||
.dlc-game-info {
|
.dlc-game-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in New Issue
Block a user