diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index c57488485..ddf88738a 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -1,4 +1,5 @@ { + "16GB of RAM": "16GB of RAM", "accessibility": { "actions_font_family_no_default": "Actions Font Family (Default: ", "all_tiles_in_color": "Show all game tiles in color", @@ -26,8 +27,9 @@ "status": "Status", "title": "This game includes anticheat software" }, - "At the end make sure to": "At the end make sure to", + "Apple Silicon M1 or above": "Apple Silicon M1 or above", "back_to_game": "Back to game", + "Be aware that not all games will work, and even if they do, they may not run as expected": "Be aware that not all games will work, and even if they do, they may not run as expected.", "box": { "cache-cleared": { "message": "HyperPlay cache cleared.", @@ -232,6 +234,7 @@ }, "title_dm": "Download Manager" }, + "Downloading": "Downloading {{percent}}%", "email_subscription": { "subtitle": "You’re now a part of our community, and we’re excited to share valuable updates and insights with you.", "title": "Thank you for subscribing!" @@ -461,9 +464,6 @@ "viewPortfolio": "View portfolio" }, "HyperPlay": "", - "HyperPlay will download and start the Steam Setup for you": { - " Please follow Steam instructions on their installer;": "HyperPlay will download and start the Steam Setup for you. Please follow Steam instructions on their installer;" - }, "HyperPlay will notify you once the installation is done;": "HyperPlay will notify you once the installation is done;", "hyperplayOverlay": { "chainRequest": { @@ -502,7 +502,7 @@ "INITIATED": "Add custom token request pending" } }, - "If you wish to continue, be patient since it can take a few minutes to finish depending on your internet connection and system configuration;": "If you wish to continue, be patient since it can take a few minutes to finish depending on your internet connection and system configuration;", + "If you wish to continue, please be patient since it can take a few minutes to finish depending on your internet connection and system configuration": "If you wish to continue, please be patient since it can take a few minutes to finish depending on your internet connection and system configuration.", "import-game-folder": { "cta": "Import Game Folder", "dialog": { @@ -544,6 +544,7 @@ "path": "Select Install Path" }, "Install Steam": "Install Steam", + "Installing": "Installing", "Installing Steam": "Installing Steam...", "Launch Steam": "Launch Steam", "Launching Steam": "Launching Steam...", @@ -565,6 +566,9 @@ "message": "Login with your platform. You can login to more than one platform at the same time.", "old-mac": "Your macOS version is {{version}}. macOS 12 or newer is required to log in." }, + "macOS 14": { + "0 or above": "macOS 14.0 or above" + }, "message": { "sync": "Sync Complete", "unsync": "Unsync Complete" @@ -680,7 +684,6 @@ "offline-retry-in": "Offline. Retrying in {{seconds}} seconds.", "retrying": "Retrying" }, - "On first launch Steam will download the necessary files and will take a few minutes to finish and the login screen to appear;": "On first launch Steam will download the necessary files and will take a few minutes to finish and the login screen to appear;", "options": { "advanced": { "key": "Variable Name", @@ -736,6 +739,7 @@ "prefered_language": "2-char code (i.e.: \"en\" or \"fr\")" }, "Please connect to the internet to access the stores": "", + "Please Wait": "Please Wait", "please-wait": "Please wait...", "profile": "Profile", "progress": "Progress", @@ -846,6 +850,7 @@ } }, "Recent": "Played Recently", + "Recommended specs for a better experience": "Recommended specs for a better experience", "search": "Search for Games", "setting": { "adddesktopshortcuts": "Add desktop shortcuts automatically", @@ -1038,7 +1043,6 @@ "warningMessage": "Side-loading a game is a feature intended for developers and experienced power users. Side-loading an installer that contains malware could compromise your computer and lead to theft of funds.", "warningTitle": "Important" }, - "since it will block HyperPlay configuration until Steam is closed;": "", "status": { "installing": "Installing", "logging": "Logging In...", @@ -1075,7 +1079,6 @@ "two_col_table": { "save_hint": "Changes in this table are not saved automatically. Click the + button" }, - "UNCHECK 'Run Steam'": "UNCHECK 'Run Steam'", "userselector": { "logging_out": "Logging out", "logIn": "Log in", diff --git a/src/backend/tools.ts b/src/backend/tools.ts index 063bf6137..c84092ca0 100644 --- a/src/backend/tools.ts +++ b/src/backend/tools.ts @@ -15,6 +15,7 @@ import { downloadFile, execAsync, getWineFromProton, + spawnAsync, writeConfig } from './utils' import { @@ -31,7 +32,7 @@ import { dirname, join } from 'path' import { isOnline } from './online_monitor' import { showDialogBoxModalAuto } from './dialog/dialog' import { runWineCommand, validWine } from './launcher' -import { chmod } from 'fs/promises' +import { chmod, mkdir } from 'fs/promises' import { any_gpu_supports_version, get_nvngx_path, @@ -599,9 +600,9 @@ export const SteamWindows = { } const steamURL = - 'https://cdn.cloudflare.steamstatic.com/client/installer/SteamSetup.exe' + 'https://drive.usercontent.google.com/download?id=1MXowtPBihbljXFs_5cM1AfyOjnC3raaT&export=download&authuser=0&confirm=t&uuid=e159346a-5836-4f7d-8aed-af3d8340fef7&at=AENtkXa2d83g4dE_UZYQKKLoEUje%3A1732794843031' const directory = `${toolsPath}/steam` - const fileName = 'SteamSetup.exe' + const fileName = 'Steam.zip' const window = getMainWindow() if (!isOnline() || existsSync(join(directory, fileName)) || !window) { @@ -618,13 +619,13 @@ export const SteamWindows = { ) { const currentProgress = calculateProgress( downloadedBytes, - Number.parseInt('2380800'), + Number.parseInt('718394478'), downloadSpeed, diskWriteSpeed, progress ) - window?.webContents.send(`progressUpdate-steam}`, { + window?.webContents.send(`progressUpdate-steam`, { appName: 'steam', status: 'installing', runner: 'hyperplay', @@ -634,19 +635,19 @@ export const SteamWindows = { }) } - try { - logInfo('Downloading Steam', LogPrefix.Backend) - await downloadFile( + return new Promise((resolve, reject) => { + downloadFile( steamURL, directory, fileName, abortController, - handleProgess - ) - return - } catch (error) { - return logWarning(['Error Downloading Steam', error], LogPrefix.Backend) - } + handleProgess, + () => resolve() + ).catch((error) => { + logWarning(['Error Downloading Steam', error], LogPrefix.Backend) + reject(error) + }) + }) }, installSteam: async () => { if (!isMac) { @@ -655,7 +656,7 @@ export const SteamWindows = { const steamCoverArt = 'https://cdn2.steamgriddb.com/file/sgdb-cdn/grid/a7e8ba67562ea4d4ca0421066466ece4.png' - const steamSetupPath = `${toolsPath}/steam/SteamSetup.exe` + const steamSetupPath = `${toolsPath}/steam/Steam.zip` const { defaultWinePrefix, wineVersion } = GlobalConfig.get().getSettings() // won't use just Steam here to avoid issue with people that already has a prefix with this name const winePrefix = join(dirname(defaultWinePrefix), 'SteamHyperPlay') @@ -664,16 +665,21 @@ export const SteamWindows = { await SteamWindows.downloadSteam() } - // Run Steam Setup and write settings const gameSettings = await gameManagerMap['sideload'].getSettings('steam') if (!gameSettings) { return } - writeConfig('steam', { ...gameSettings, winePrefix, wineVersion }) + writeConfig('steam', { + ...gameSettings, + winePrefix, + wineVersion, + launcherArgs: + '-noverifyfiles -nobootstrapupdate -skipinitialbootstrap -norepairfiles -overridepackageurl' + }) try { await runWineCommand({ - commandParts: [steamSetupPath], + commandParts: ['wineboot', '-init'], wait: true, gameSettings: { ...gameSettings, @@ -682,8 +688,17 @@ export const SteamWindows = { } }) + const unzipFile = join(toolsPath, 'steam', 'Steam.zip') + const unzipPath = `${winePrefix}/drive_c/Program Files (x86)/Steam` + if (!existsSync(unzipPath)) { + await mkdir(unzipPath, { recursive: true }) + } + + logInfo('Extracting Steam...', LogPrefix.Backend) + await spawnAsync('unzip', ['-o', unzipFile, '-d', unzipPath]) + // Add Steam to the library - const executable = `${winePrefix}/drive_c/Program Files (x86)/Steam/Steam.exe` + const executable = join(unzipPath, 'Steam.exe') if (!existsSync(executable)) { logError(['Steam executable not found', executable], LogPrefix.Backend) diff --git a/src/frontend/screens/Library/components/SteamInstall/SteamInstallDialog.tsx b/src/frontend/screens/Library/components/SteamInstall/SteamInstallDialog.tsx index 7a151c906..bd01dc5fd 100644 --- a/src/frontend/screens/Library/components/SteamInstall/SteamInstallDialog.tsx +++ b/src/frontend/screens/Library/components/SteamInstall/SteamInstallDialog.tsx @@ -1,9 +1,9 @@ import React from 'react' import { useTranslation } from 'react-i18next' +import { TFunction } from 'i18next' import { Button } from '@hyperplay/ui' import { Dialog } from 'frontend/components/UI/Dialog' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faSpinner } from '@fortawesome/free-solid-svg-icons' +import { hasProgress } from 'frontend/hooks/hasProgress' interface SteamInstallDialogProps { isInstalling: boolean @@ -11,12 +11,28 @@ interface SteamInstallDialogProps { onInstall: () => void } +const getProgressMessage = (percent: number, t: TFunction) => { + if (!percent) { + return t('Please Wait', 'Please Wait') + } + if (percent > 95) { + return t('Installing', 'Installing') + } + return t('Downloading', 'Downloading {{percent}}%', { + percent: percent.toFixed(0) + }) +} + const SteamInstallDialog: React.FC = ({ isInstalling, onClose, onInstall }) => { const { t } = useTranslation() + const { progress } = hasProgress('steam') + + const percent = progress.percent ?? 0 + const downloadMessage = getProgressMessage(percent, t) return ( @@ -27,33 +43,34 @@ const SteamInstallDialog: React.FC = ({
  • {t( - 'If you wish to continue, be patient since it can take a few minutes to finish depending on your internet connection and system configuration;', - 'If you wish to continue, be patient since it can take a few minutes to finish depending on your internet connection and system configuration;' + 'Recommended specs for a better experience', + 'Recommended specs for a better experience' )} + :
  • +
      +
    • + {t('Apple Silicon M1 or above', 'Apple Silicon M1 or above')} +
    • +
    • {t('macOS 14.0 or above', 'macOS 14.0 or above')}
    • +
    • {t('16GB of RAM', '16GB of RAM')}
    • +
  • {t( - 'HyperPlay will download and start the Steam Setup for you. Please follow Steam instructions on their installer;', - 'HyperPlay will download and start the Steam Setup for you. Please follow Steam instructions on their installer;' + 'Be aware that not all games will work, and even if they do, they may not run as expected.', + 'Be aware that not all games will work, and even if they do, they may not run as expected.' )}
  • - {t('At the end make sure to', 'At the end make sure to')}{' '} - {t("UNCHECK 'Run Steam'", "UNCHECK 'Run Steam'")},{' '} {t( - 'since it will block HyperPlay configuration until Steam is closed;' + 'If you wish to continue, please be patient since it can take a few minutes to finish depending on your internet connection and system configuration.', + 'If you wish to continue, please be patient since it can take a few minutes to finish depending on your internet connection and system configuration.' )}
  • {t( 'HyperPlay will notify you once the installation is done;', - 'HyperPlay will notify you once the installation is done;' - )} -
  • -
  • - {t( - 'On first launch Steam will download the necessary files and will take a few minutes to finish and the login screen to appear;', - 'On first launch Steam will download the necessary files and will take a few minutes to finish and the login screen to appear;' + 'HyperPlay will notify you once the installation is done.' )}
@@ -66,7 +83,7 @@ const SteamInstallDialog: React.FC = ({ disabled={isInstalling} > {isInstalling ? ( - + {downloadMessage} ) : ( t('Install Steam', 'Install Steam') )}