mirror of
https://github.com/Novattz/creamlinux-installer.git
synced 2026-05-02 13:02:04 -04:00
bits and bob
This commit is contained in:
@@ -117,8 +117,10 @@ const DlcSelectionDialog = ({
|
|||||||
|
|
||||||
// Submit selected DLCs to parent component
|
// Submit selected DLCs to parent component
|
||||||
const handleConfirm = useCallback(() => {
|
const handleConfirm = useCallback(() => {
|
||||||
onConfirm(selectedDlcs)
|
// Create a deep copy to prevent reference issues
|
||||||
}, [onConfirm, selectedDlcs])
|
const dlcsCopy = JSON.parse(JSON.stringify(selectedDlcs));
|
||||||
|
onConfirm(dlcsCopy);
|
||||||
|
}, [onConfirm, selectedDlcs]);
|
||||||
|
|
||||||
// Count selected DLCs
|
// Count selected DLCs
|
||||||
const selectedCount = selectedDlcs.filter((dlc) => dlc.enabled).length
|
const selectedCount = selectedDlcs.filter((dlc) => dlc.enabled).length
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ const Icon: React.FC<IconProps> = ({
|
|||||||
if (BRAND_ICON_NAMES.has(name)) {
|
if (BRAND_ICON_NAMES.has(name)) {
|
||||||
defaultVariant = 'brand'
|
defaultVariant = 'brand'
|
||||||
} else {
|
} else {
|
||||||
defaultVariant = 'bold' // Default to outline for non-brand icons
|
defaultVariant = 'bold' // Default to bold for non-brand icons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Bold variant icons
|
// Bold variant icons
|
||||||
export { ReactComponent as Linux } from './linux.svg'
|
export { ReactComponent as Linux } from './linux.svg'
|
||||||
export { ReactComponent as steam } from './steam.svg'
|
export { ReactComponent as Steam } from './steam.svg'
|
||||||
export { ReactComponent as windows } from './windows.svg'
|
export { ReactComponent as Windows } from './windows.svg'
|
||||||
export { ReactComponent as github } from './github.svg'
|
export { ReactComponent as Github } from './github.svg'
|
||||||
export { ReactComponent as discord } from './discord.svg'
|
export { ReactComponent as Discord } from './discord.svg'
|
||||||
|
export { ReactComponent as Proton } from './proton.svg'
|
||||||
1
src/components/icons/brands/proton.svg
Normal file
1
src/components/icons/brands/proton.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 10 KiB |
@@ -27,11 +27,13 @@ export const search = 'Search'
|
|||||||
export const trash = 'Trash'
|
export const trash = 'Trash'
|
||||||
export const warning = 'Warning'
|
export const warning = 'Warning'
|
||||||
export const wine = 'Wine'
|
export const wine = 'Wine'
|
||||||
|
export const diamond = 'Diamond'
|
||||||
|
|
||||||
// Brand icons
|
// Brand icons
|
||||||
export const discord = 'Discord'
|
export const discord = 'Discord'
|
||||||
export const github = 'GitHub'
|
export const github = 'GitHub'
|
||||||
export const linux = 'Linux'
|
export const linux = 'Linux'
|
||||||
|
export const proton = 'Proton'
|
||||||
export const steam = 'Steam'
|
export const steam = 'Steam'
|
||||||
export const windows = 'Windows'
|
export const windows = 'Windows'
|
||||||
|
|
||||||
@@ -54,11 +56,13 @@ export const IconNames = {
|
|||||||
Trash: trash,
|
Trash: trash,
|
||||||
Warning: warning,
|
Warning: warning,
|
||||||
Wine: wine,
|
Wine: wine,
|
||||||
|
Diamond: diamond,
|
||||||
|
|
||||||
// Brand icons
|
// Brand icons
|
||||||
Discord: discord,
|
Discord: discord,
|
||||||
GitHub: github,
|
GitHub: github,
|
||||||
Linux: linux,
|
Linux: linux,
|
||||||
|
Proton: proton,
|
||||||
Steam: steam,
|
Steam: steam,
|
||||||
Windows: windows,
|
Windows: windows,
|
||||||
} as const
|
} as const
|
||||||
|
|||||||
1
src/components/icons/ui/bold/diamond.svg
Normal file
1
src/components/icons/ui/bold/diamond.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M9.2 8.25h5.6L12.15 3h-.3zm2.05 11.85V9.75H2.625zm1.5 0l8.625-10.35H12.75zm3.7-11.85h5.175L19.55 4.1q-.275-.5-.737-.8T17.775 3H13.85zm-14.075 0H7.55L10.15 3H6.225q-.575 0-1.037.3t-.738.8z"/></svg>
|
||||||
|
After Width: | Height: | Size: 308 B |
@@ -15,3 +15,4 @@ export { ReactComponent as Search } from './search.svg'
|
|||||||
export { ReactComponent as Trash } from './trash.svg'
|
export { ReactComponent as Trash } from './trash.svg'
|
||||||
export { ReactComponent as Warning } from './warning.svg'
|
export { ReactComponent as Warning } from './warning.svg'
|
||||||
export { ReactComponent as Wine } from './wine.svg'
|
export { ReactComponent as Wine } from './wine.svg'
|
||||||
|
export { ReactComponent as Diamond } from './diamond.svg'
|
||||||
1
src/components/icons/ui/outline/diamond.svg
Normal file
1
src/components/icons/ui/outline/diamond.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M12 19.875q-.425 0-.825-.187t-.7-.538L2.825 10q-.225-.275-.337-.6t-.113-.675q0-.225.038-.462t.162-.438L4.45 4.1q.275-.5.738-.8T6.225 3h11.55q.575 0 1.038.3t.737.8l1.875 3.725q.125.2.163.437t.037.463q0 .35-.112.675t-.338.6l-7.65 9.15q-.3.35-.7.538t-.825.187M9.625 8h4.75l-1.5-3h-1.75zM11 16.675V10H5.45zm2 0L18.55 10H13zM16.6 8h2.65l-1.5-3H15.1zM4.75 8H7.4l1.5-3H6.25z"/></svg>
|
||||||
|
After Width: | Height: | Size: 488 B |
@@ -15,3 +15,4 @@ export { ReactComponent as Search } from './search.svg'
|
|||||||
export { ReactComponent as Trash } from './trash.svg'
|
export { ReactComponent as Trash } from './trash.svg'
|
||||||
export { ReactComponent as Warning } from './warning.svg'
|
export { ReactComponent as Warning } from './warning.svg'
|
||||||
export { ReactComponent as Wine } from './wine.svg'
|
export { ReactComponent as Wine } from './wine.svg'
|
||||||
|
export { ReactComponent as Diamond } from './diamond.svg'
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Button } from '@/components/buttons'
|
import { Button } from '@/components/buttons'
|
||||||
import { Icon, info, refresh, search } from '@/components/icons'
|
import { Icon, diamond, refresh, search } from '@/components/icons'
|
||||||
|
|
||||||
interface HeaderProps {
|
interface HeaderProps {
|
||||||
onRefresh: () => void
|
onRefresh: () => void
|
||||||
@@ -21,7 +21,7 @@ const Header = ({
|
|||||||
return (
|
return (
|
||||||
<header className="app-header">
|
<header className="app-header">
|
||||||
<div className="app-title">
|
<div className="app-title">
|
||||||
<Icon name={info} variant="bold" size="md" className="app-logo-icon" />
|
<Icon name={diamond} variant="bold" size="lg" className="app-logo-icon" />
|
||||||
<h1>CreamLinux</h1>
|
<h1>CreamLinux</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="header-controls">
|
<div className="header-controls">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
interface InitialLoadingScreenProps {
|
interface InitialLoadingScreenProps {
|
||||||
message: string;
|
message: string;
|
||||||
@@ -9,21 +9,32 @@ interface InitialLoadingScreenProps {
|
|||||||
/**
|
/**
|
||||||
* Initial loading screen displayed when the app first loads
|
* Initial loading screen displayed when the app first loads
|
||||||
*/
|
*/
|
||||||
const InitialLoadingScreen = ({
|
const InitialLoadingScreen = ({ message, progress, onComplete }: InitialLoadingScreenProps) => {
|
||||||
message,
|
const [detailedStatus, setDetailedStatus] = useState<string[]>([
|
||||||
progress,
|
"Initializing application...",
|
||||||
onComplete
|
"Setting up Steam integration...",
|
||||||
}: InitialLoadingScreenProps) => {
|
"Preparing DLC management..."
|
||||||
// Call onComplete when progress reaches 100%
|
]);
|
||||||
useEffect(() => {
|
|
||||||
if (progress >= 100 && onComplete) {
|
|
||||||
const timer = setTimeout(() => {
|
|
||||||
onComplete();
|
|
||||||
}, 500); // Small delay to show completion
|
|
||||||
|
|
||||||
return () => clearTimeout(timer);
|
// Use a sequence of messages based on progress
|
||||||
|
useEffect(() => {
|
||||||
|
const messages = [
|
||||||
|
{ threshold: 10, message: "Checking system requirements..." },
|
||||||
|
{ threshold: 30, message: "Scanning Steam libraries..." },
|
||||||
|
{ threshold: 50, message: "Discovering games..." },
|
||||||
|
{ threshold: 70, message: "Analyzing game configurations..." },
|
||||||
|
{ threshold: 90, message: "Preparing user interface..." },
|
||||||
|
{ threshold: 100, message: "Ready to launch!" }
|
||||||
|
];
|
||||||
|
|
||||||
|
// Find current status message based on progress
|
||||||
|
const currentMessage = messages.find(m => progress <= m.threshold)?.message || "Loading...";
|
||||||
|
|
||||||
|
// Add new messages to the log as progress increases
|
||||||
|
if (currentMessage && !detailedStatus.includes(currentMessage)) {
|
||||||
|
setDetailedStatus(prev => [...prev, currentMessage]);
|
||||||
}
|
}
|
||||||
}, [progress, onComplete]);
|
}, [progress, detailedStatus]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="initial-loading-screen">
|
<div className="initial-loading-screen">
|
||||||
@@ -31,6 +42,7 @@ const InitialLoadingScreen = ({
|
|||||||
<h1>CreamLinux</h1>
|
<h1>CreamLinux</h1>
|
||||||
|
|
||||||
<div className="loading-animation">
|
<div className="loading-animation">
|
||||||
|
{/* Enhanced animation with SVG or more elaborate CSS animation */}
|
||||||
<div className="loading-circles">
|
<div className="loading-circles">
|
||||||
<div className="circle circle-1"></div>
|
<div className="circle circle-1"></div>
|
||||||
<div className="circle circle-2"></div>
|
<div className="circle circle-2"></div>
|
||||||
@@ -40,6 +52,16 @@ const InitialLoadingScreen = ({
|
|||||||
|
|
||||||
<p className="loading-message">{message}</p>
|
<p className="loading-message">{message}</p>
|
||||||
|
|
||||||
|
{/* Add a detailed status log that shows progress steps */}
|
||||||
|
<div className="loading-status-log">
|
||||||
|
{detailedStatus.slice(-4).map((status, index) => (
|
||||||
|
<div key={index} className="status-line">
|
||||||
|
<span className="status-indicator">○</span>
|
||||||
|
<span className="status-text">{status}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="progress-bar-container">
|
<div className="progress-bar-container">
|
||||||
<div className="progress-bar" style={{ width: `${progress}%` }} />
|
<div className="progress-bar" style={{ width: `${progress}%` }} />
|
||||||
</div>
|
</div>
|
||||||
@@ -47,7 +69,7 @@ const InitialLoadingScreen = ({
|
|||||||
<div className="progress-percentage">{Math.round(progress)}%</div>
|
<div className="progress-percentage">{Math.round(progress)}%</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default InitialLoadingScreen
|
export default InitialLoadingScreen
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Icon, layers, linux, wine } from '@/components/icons'
|
import { Icon, layers, linux, proton } from '@/components/icons'
|
||||||
|
|
||||||
interface SidebarProps {
|
interface SidebarProps {
|
||||||
setFilter: (filter: string) => void
|
setFilter: (filter: string) => void
|
||||||
@@ -22,7 +22,7 @@ const Sidebar = ({ setFilter, currentFilter }: SidebarProps) => {
|
|||||||
const filters: FilterItem[] = [
|
const filters: FilterItem[] = [
|
||||||
{ id: 'all', label: 'All Games', icon: layers, variant: 'bold' },
|
{ id: 'all', label: 'All Games', icon: layers, variant: 'bold' },
|
||||||
{ id: 'native', label: 'Native', icon: linux, variant: 'brand' },
|
{ id: 'native', label: 'Native', icon: linux, variant: 'brand' },
|
||||||
{ id: 'proton', label: 'Proton Required', icon: wine, variant: 'bold' }
|
{ id: 'proton', label: 'Proton Required', icon: proton, variant: 'brand' }
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -23,13 +23,17 @@ const Toast = ({
|
|||||||
onDismiss
|
onDismiss
|
||||||
}: ToastProps) => {
|
}: ToastProps) => {
|
||||||
const [visible, setVisible] = useState(false)
|
const [visible, setVisible] = useState(false)
|
||||||
|
const [isClosing, setIsClosing] = useState(false);
|
||||||
|
|
||||||
// Use useCallback to memoize the handleDismiss function
|
// Use useCallback to memoize the handleDismiss function
|
||||||
const handleDismiss = useCallback(() => {
|
const handleDismiss = useCallback(() => {
|
||||||
setVisible(false)
|
setIsClosing(true);
|
||||||
// Give time for exit animation
|
// Give time for exit animation
|
||||||
setTimeout(() => onDismiss(id), 300)
|
setTimeout(() => {
|
||||||
}, [id, onDismiss])
|
setVisible(false);
|
||||||
|
setTimeout(() => onDismiss(id), 50);
|
||||||
|
}, 300);
|
||||||
|
}, [id, onDismiss]);
|
||||||
|
|
||||||
// Handle animation on mount/unmount
|
// Handle animation on mount/unmount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -69,7 +73,7 @@ const Toast = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`toast toast-${type} ${visible ? 'visible' : ''}`}>
|
<div className={`toast toast-${type} ${visible ? 'visible' : ''} ${isClosing ? 'closing' : ''}`}>
|
||||||
<div className="toast-icon">{getIcon()}</div>
|
<div className="toast-icon">{getIcon()}</div>
|
||||||
<div className="toast-content">
|
<div className="toast-content">
|
||||||
{title && <h4 className="toast-title">{title}</h4>}
|
{title && <h4 className="toast-title">{title}</h4>}
|
||||||
|
|||||||
@@ -107,15 +107,25 @@ export const AppProvider = ({ children }: AppProviderProps) => {
|
|||||||
|
|
||||||
// DLC confirmation wrapper
|
// DLC confirmation wrapper
|
||||||
const handleDlcConfirm = (selectedDlcs: DlcInfo[]) => {
|
const handleDlcConfirm = (selectedDlcs: DlcInfo[]) => {
|
||||||
closeDlcDialog()
|
|
||||||
const { gameId, isEditMode } = dlcDialog
|
const { gameId, isEditMode } = dlcDialog
|
||||||
|
|
||||||
|
// MODIFIED: Create a deep copy to ensure we don't have reference issues
|
||||||
|
const dlcsCopy = selectedDlcs.map(dlc => ({...dlc}))
|
||||||
|
|
||||||
|
// Log detailed info before closing dialog
|
||||||
|
console.log(`Saving ${dlcsCopy.filter(d => d.enabled).length} enabled and ${
|
||||||
|
dlcsCopy.length - dlcsCopy.filter(d => d.enabled).length
|
||||||
|
} disabled DLCs`)
|
||||||
|
|
||||||
|
// Close dialog FIRST to avoid UI state issues
|
||||||
|
closeDlcDialog()
|
||||||
|
|
||||||
// Update game state to show it's installing
|
// Update game state to show it's installing
|
||||||
setGames(prevGames =>
|
setGames(prevGames =>
|
||||||
prevGames.map(g => g.id === gameId ? { ...g, installing: true } : g)
|
prevGames.map(g => g.id === gameId ? { ...g, installing: true } : g)
|
||||||
)
|
)
|
||||||
|
|
||||||
executeDlcConfirm(selectedDlcs, gameId, isEditMode, games)
|
executeDlcConfirm(dlcsCopy, gameId, isEditMode, games)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
success(isEditMode
|
success(isEditMode
|
||||||
? "DLC configuration updated successfully"
|
? "DLC configuration updated successfully"
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export function useDlcManager() {
|
|||||||
const [isFetchingDlcs, setIsFetchingDlcs] = useState(false)
|
const [isFetchingDlcs, setIsFetchingDlcs] = useState(false)
|
||||||
const dlcFetchController = useRef<AbortController | null>(null)
|
const dlcFetchController = useRef<AbortController | null>(null)
|
||||||
const activeDlcFetchId = useRef<string | null>(null)
|
const activeDlcFetchId = useRef<string | null>(null)
|
||||||
|
const [forceReload, setForceReload] = useState(false) // Add this state to force reloads
|
||||||
|
|
||||||
// DLC selection dialog state
|
// DLC selection dialog state
|
||||||
const [dlcDialog, setDlcDialog] = useState<DlcDialogState>({
|
const [dlcDialog, setDlcDialog] = useState<DlcDialogState>({
|
||||||
@@ -155,7 +156,7 @@ export function useDlcManager() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle game edit (show DLC management dialog)
|
// MODIFIED: Handle game edit (show DLC management dialog) with proper reloading
|
||||||
const handleGameEdit = async (gameId: string, games: Game[]) => {
|
const handleGameEdit = async (gameId: string, games: Game[]) => {
|
||||||
const game = games.find((g) => g.id === gameId)
|
const game = games.find((g) => g.id === gameId)
|
||||||
if (!game || !game.cream_installed) return
|
if (!game || !game.cream_installed) return
|
||||||
@@ -172,7 +173,7 @@ export function useDlcManager() {
|
|||||||
visible: true,
|
visible: true,
|
||||||
gameId,
|
gameId,
|
||||||
gameTitle: game.title,
|
gameTitle: game.title,
|
||||||
dlcs: [],
|
dlcs: [], // Always start with empty DLCs to force a fresh load
|
||||||
enabledDlcs: [],
|
enabledDlcs: [],
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
isEditMode: true, // This is an edit operation
|
isEditMode: true, // This is an edit operation
|
||||||
@@ -182,23 +183,33 @@ export function useDlcManager() {
|
|||||||
error: null,
|
error: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Try to read all DLCs from the configuration file first (including disabled ones)
|
// MODIFIED: Always get a fresh copy from the config file
|
||||||
|
console.log('Loading DLC configuration from disk...')
|
||||||
try {
|
try {
|
||||||
const allDlcs = await invoke<DlcInfo[]>('get_all_dlcs_command', {
|
const allDlcs = await invoke<DlcInfo[]>('get_all_dlcs_command', {
|
||||||
gamePath: game.path,
|
gamePath: game.path,
|
||||||
}).catch(() => [] as DlcInfo[])
|
}).catch((e) => {
|
||||||
|
console.error('Error loading DLCs:', e)
|
||||||
|
return [] as DlcInfo[]
|
||||||
|
})
|
||||||
|
|
||||||
if (allDlcs.length > 0) {
|
if (allDlcs.length > 0) {
|
||||||
// If we have DLCs from the config file, use them
|
// Log the fresh DLC config
|
||||||
console.log('Loaded existing DLC configuration:', allDlcs)
|
console.log('Loaded existing DLC configuration:', allDlcs)
|
||||||
|
|
||||||
|
// IMPORTANT: Create a completely new array to avoid reference issues
|
||||||
|
const freshDlcs = allDlcs.map(dlc => ({...dlc}))
|
||||||
|
|
||||||
setDlcDialog((prev) => ({
|
setDlcDialog((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
dlcs: allDlcs,
|
dlcs: freshDlcs,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
progress: 100,
|
progress: 100,
|
||||||
progressMessage: 'Loaded existing DLC configuration',
|
progressMessage: 'Loaded existing DLC configuration',
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// Reset force reload flag
|
||||||
|
setForceReload(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -245,7 +256,7 @@ export function useDlcManager() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle DLC selection dialog close
|
// MODIFIED: Handle DLC selection dialog close
|
||||||
const handleDlcDialogClose = () => {
|
const handleDlcDialogClose = () => {
|
||||||
// Cancel any in-progress DLC fetching
|
// Cancel any in-progress DLC fetching
|
||||||
if (isFetchingDlcs && activeDlcFetchId.current) {
|
if (isFetchingDlcs && activeDlcFetchId.current) {
|
||||||
@@ -267,8 +278,15 @@ export function useDlcManager() {
|
|||||||
dlcFetchController.current = null
|
dlcFetchController.current = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close dialog
|
// Close dialog and reset state
|
||||||
setDlcDialog((prev) => ({ ...prev, visible: false }))
|
setDlcDialog((prev) => ({
|
||||||
|
...prev,
|
||||||
|
visible: false,
|
||||||
|
dlcs: [], // Clear DLCs to force a reload next time
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Set flag to force reload next time
|
||||||
|
setForceReload(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update DLCs being streamed with enabled state
|
// Update DLCs being streamed with enabled state
|
||||||
@@ -291,5 +309,6 @@ export function useDlcManager() {
|
|||||||
streamGameDlcs,
|
streamGameDlcs,
|
||||||
handleGameEdit,
|
handleGameEdit,
|
||||||
handleDlcDialogClose,
|
handleDlcDialogClose,
|
||||||
|
forceReload,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,9 @@ export function useGameActions() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (isEditMode) {
|
if (isEditMode) {
|
||||||
// If in edit mode, we're updating existing cream_api.ini
|
// MODIFIED: Create a deep copy to ensure we don't have reference issues
|
||||||
|
const dlcsCopy = selectedDlcs.map(dlc => ({...dlc}));
|
||||||
|
|
||||||
// Show progress dialog for editing
|
// Show progress dialog for editing
|
||||||
setProgressDialog({
|
setProgressDialog({
|
||||||
visible: true,
|
visible: true,
|
||||||
@@ -162,10 +164,12 @@ export function useGameActions() {
|
|||||||
instructions: undefined,
|
instructions: undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log('Saving DLC configuration:', dlcsCopy)
|
||||||
|
|
||||||
// Call the backend to update the DLC configuration
|
// Call the backend to update the DLC configuration
|
||||||
await invoke('update_dlc_configuration_command', {
|
await invoke('update_dlc_configuration_command', {
|
||||||
gamePath: game.path,
|
gamePath: game.path,
|
||||||
dlcs: selectedDlcs,
|
dlcs: dlcsCopy,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Update progress dialog for completion
|
// Update progress dialog for completion
|
||||||
|
|||||||
@@ -109,6 +109,10 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@include custom-scrollbar;
|
@include custom-scrollbar;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dialog footer
|
// Dialog footer
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
// Instruction container
|
// Instruction container
|
||||||
.instruction-container {
|
.instruction-container {
|
||||||
margin-top: 1.5rem;
|
margin-top: 1rem;
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
border-top: 1px solid var(--border-soft);
|
border-top: 1px solid var(--border-soft);
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,44 @@
|
|||||||
min-height: 3rem;
|
min-height: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loading-status-log {
|
||||||
|
margin: 1rem 0;
|
||||||
|
text-align: left;
|
||||||
|
max-height: 100px;
|
||||||
|
overflow-y: auto;
|
||||||
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
padding: 0.5rem;
|
||||||
|
|
||||||
|
.status-line {
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.status-indicator {
|
||||||
|
color: var(--primary-color);
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-text {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
.status-indicator {
|
||||||
|
color: var(--success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-text {
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.progress-bar-container {
|
.progress-bar-container {
|
||||||
height: 8px;
|
height: 8px;
|
||||||
background-color: var(--border-soft);
|
background-color: var(--border-soft);
|
||||||
|
|||||||
@@ -77,6 +77,11 @@
|
|||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.closing {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
|
||||||
// Type-specific styling
|
// Type-specific styling
|
||||||
&.toast-success {
|
&.toast-success {
|
||||||
border-color: var(--success);
|
border-color: var(--success);
|
||||||
|
|||||||
Reference in New Issue
Block a user