From 0ff8e865aa189150028523ca5b9b83ed6cce06d7 Mon Sep 17 00:00:00 2001 From: MathieuG-P <40181755+Zagrios@users.noreply.github.com> Date: Mon, 23 Jan 2023 00:56:49 +0100 Subject: [PATCH 1/2] possibility to import version + cpu usage optimization --- assets/jsons/translations/en.json | 29 +++++- assets/jsons/translations/es.json | 29 +++++- assets/jsons/translations/fr.json | 29 +++++- src/main/ipcs/bs-download-ipcs.ts | 10 +++ src/main/ipcs/os-controls-ipcs.ts | 2 +- src/main/services/bs-installer.service.ts | 26 +++++- src/main/services/bs-local-version.service.ts | 37 ++++---- .../available-version-item.component.tsx | 9 +- .../available-versions-slide.component.tsx | 4 +- .../available-versions-slider.component.tsx | 28 +++--- .../filter-panel.component.tsx | 3 +- .../map-item.component.tsx | 3 +- .../import-version-modal.component.tsx | 22 +++++ .../components/nav-bar/nav-bar.component.tsx | 2 +- .../shared/bsm-checkbox.component.tsx | 10 ++- .../shared/glow-effect.component.tsx | 14 +++ .../components/svgs/bsm-icon.component.tsx | 4 +- .../svgs/icons/sync-icon.component.tsx | 9 ++ .../launch/launch-mod-toogle.component.tsx | 3 +- src/renderer/index.css | 2 - .../available-versions-list.components.tsx | 90 +++++++++++++++---- .../services/bs-downloader.service.ts | 5 ++ src/shared/bs-version.interface.ts | 9 +- 23 files changed, 307 insertions(+), 72 deletions(-) create mode 100644 src/renderer/components/modal/modal-types/import-version-modal.component.tsx create mode 100644 src/renderer/components/shared/glow-effect.component.tsx create mode 100644 src/renderer/components/svgs/icons/sync-icon.component.tsx diff --git a/assets/jsons/translations/en.json b/assets/jsons/translations/en.json index 066dac28..aeab9e36 100644 --- a/assets/jsons/translations/en.json +++ b/assets/jsons/translations/en.json @@ -85,7 +85,11 @@ }, "available-versions": { "title": "Select a version", - "steam-release": "Release page" + "steam-release": "Release page", + "dropdown": { + "refresh": "Refresh list", + "import-version" :"Import a version" + } }, "settings": { "steam": { @@ -233,6 +237,22 @@ } } }, + "bs-import-version":{ + "success":{ + "start-import": { + "title": "Import in progress 馃憣", + "desc": "The import may take several minutes depending on your configuration." + }, + "imported": { + "title": "Imported version 馃帀" + } + }, + "errors":{ + "import-error":{ + "desc": "Check that the selected folder is a BeatSaber installation." + } + } + }, "settings": { "move-folder": { "success": { @@ -427,6 +447,13 @@ "submit": "Login" } }, + "bs-import-version":{ + "title": "Import a version", + "description": "Imports a version of BeatSaber to use with BSManager. The import will copy the selected BeatSaber installation folder to the BSManager versions folder.", + "buttons":{ + "submit": "Import a version" + } + }, "bs-uninstall": { "title": "Uninstall", "description": "Are you sure you want to uninstall BeatSaber {version} ? You will have to download it again to play it.", diff --git a/assets/jsons/translations/es.json b/assets/jsons/translations/es.json index 543c3309..f4949e43 100644 --- a/assets/jsons/translations/es.json +++ b/assets/jsons/translations/es.json @@ -85,7 +85,11 @@ }, "available-versions": { "title": "Seleccione una versi贸n", - "steam-release": "Publicaci贸n P谩gina" + "steam-release": "Publicaci贸n P谩gina", + "dropdown": { + "refresh": "Actualizar la lista", + "import-version" :"Importar una versi贸n" + } }, "settings": { "steam": { @@ -233,6 +237,22 @@ } } }, + "bs-import-version":{ + "success":{ + "start-import": { + "title": "Importaci贸n en curso 馃憣", + "desc": "La importaci贸n puede tardar varios minutos dependiendo de su configuraci贸n." + }, + "imported": { + "title": "Versi贸n importada 馃帀" + } + }, + "errors":{ + "import-error":{ + "desc": "Compruebe que la carpeta seleccionada es una instalaci贸n de BeatSaber." + } + } + }, "settings": { "move-folder": { "success": { @@ -427,6 +447,13 @@ "submit": "Inicio de sesi贸n" } }, + "bs-import-version":{ + "title": "Importar una versi贸n", + "description": "Importa una versi贸n de BeatSaber para usar con BSManager. La importaci贸n copiar谩 la carpeta de instalaci贸n seleccionada de BeatSaber en la carpeta de versiones de BSManager.", + "buttons":{ + "submit": "Importar una versi贸n" + } + }, "bs-uninstall": { "title": "Desinstalar", "description": "驴Est谩s seguro de que quieres desinstalar BeatSaber {version}? Tendr谩s que descargarlo de nuevo para poder jugar.", diff --git a/assets/jsons/translations/fr.json b/assets/jsons/translations/fr.json index a2492f90..1730df61 100644 --- a/assets/jsons/translations/fr.json +++ b/assets/jsons/translations/fr.json @@ -85,7 +85,11 @@ }, "available-versions": { "title": "Choisi une version", - "steam-release": "Notes de version" + "steam-release": "Notes de version", + "dropdown": { + "refresh": "Rafraichir la liste", + "import-version" :"Importer une version" + } }, "settings": { "steam": { @@ -233,6 +237,22 @@ } } }, + "bs-import-version":{ + "success":{ + "start-import": { + "title": "Importation en cours 馃憣", + "desc": "L'importation peut durer plusieurs minutes selon votre configuration." + }, + "imported": { + "title": "Version import茅e 馃帀" + } + }, + "errors":{ + "import-error":{ + "desc": "V茅rifier que le dossier s茅lectionn茅 est une installation de BeatSaber." + } + } + }, "settings": { "move-folder": { "success": { @@ -427,6 +447,13 @@ "submit": "Se connecter" } }, + "bs-import-version":{ + "title": "Importer une version", + "description": "Importe une version de BeatSaber pour profiter des fonctionnalit茅s de BSManager. L'importation copiera le dossier d'installation de BeatSaber s茅lectionn茅 dans le dossier de versions de BSManager.", + "buttons":{ + "submit": "Importer une version" + } + }, "bs-uninstall": { "title": "D茅sinstaller", "description": "Est-tu s没r de vouloir d茅sinstaller BeatSaber {version} ? Tu vas devoir la ret茅l茅charger pour y jouer.", diff --git a/src/main/ipcs/bs-download-ipcs.ts b/src/main/ipcs/bs-download-ipcs.ts index 80acc27b..761bfb21 100644 --- a/src/main/ipcs/bs-download-ipcs.ts +++ b/src/main/ipcs/bs-download-ipcs.ts @@ -65,4 +65,14 @@ ipcMain.on('bs-download.set-installation-folder', (event, request: IpcRequest) => { + const utils = UtilsService.getInstance(); + const installer = BSInstallerService.getInstance(); + installer.importVersion(request.args).catch(e => { + utils.ipcSend(request.responceChannel, {success: false, error: e}); + }).then(() => { + utils.ipcSend(request.responceChannel, {success: true}); + }); +}) + diff --git a/src/main/ipcs/os-controls-ipcs.ts b/src/main/ipcs/os-controls-ipcs.ts index aaec73c8..d84f209f 100644 --- a/src/main/ipcs/os-controls-ipcs.ts +++ b/src/main/ipcs/os-controls-ipcs.ts @@ -33,7 +33,7 @@ ipcMain.on('new-window', async (event, request: IpcRequest) => { }); ipcMain.on('choose-folder', async (event, request: IpcRequest) => { - dialog.showOpenDialog({properties: ['openDirectory']}).then(res => { + dialog.showOpenDialog({properties: ['openDirectory'],}).then(res => { UtilsService.getInstance().ipcSend(request.responceChannel, {success: true, data: res}); }); }); diff --git a/src/main/services/bs-installer.service.ts b/src/main/services/bs-installer.service.ts index ffdfd5b4..8d969a2b 100644 --- a/src/main/services/bs-installer.service.ts +++ b/src/main/services/bs-installer.service.ts @@ -1,6 +1,6 @@ import { BS_APP_ID, BS_DEPOT } from "../constants"; import path from "path"; -import { BSVersion } from 'shared/bs-version.interface'; +import { BSVersion, PartialBSVersion } from 'shared/bs-version.interface'; import { UtilsService } from "./utils.service"; import { ChildProcessWithoutNullStreams, spawn, spawnSync } from "child_process"; import log from "electron-log"; @@ -9,6 +9,7 @@ import { ctrlc } from "ctrlc-windows"; import { BSLocalVersionService } from "./bs-local-version.service"; import isOnline from 'is-online'; import { WindowManagerService } from "./window-manager.service"; +import { copy, copySync } from "fs-extra"; export class BSInstallerService{ @@ -159,6 +160,29 @@ export class BSInstallerService{ }) } + public async importVersion(path: string): Promise{ + + const rawBsVersion = await this.localVersionService.getVersionOfBSFolder(path); + + if(!rawBsVersion){ throw new Error("NOT_BS_FOLDER"); } + + const originalPath = await this.localVersionService.getVersionPath(rawBsVersion); + let destPath = originalPath; + let folderExist = this.utils.pathExist(destPath); + let i = 0; + + while(folderExist){ + i++; + destPath = `${originalPath} (${i})`; + folderExist = this.utils.pathExist(destPath); + } + + await copy(path, destPath, {dereference: true}); + + return rawBsVersion; + + } + } diff --git a/src/main/services/bs-local-version.service.ts b/src/main/services/bs-local-version.service.ts index 08fb4f06..e58ebfeb 100644 --- a/src/main/services/bs-local-version.service.ts +++ b/src/main/services/bs-local-version.service.ts @@ -1,5 +1,5 @@ import { BSVersionLibService } from "./bs-version-lib.service"; -import { BSVersion } from 'shared/bs-version.interface'; +import { BSVersion, PartialBSVersion } from 'shared/bs-version.interface'; import { InstallationLocationService } from "./installation-location.service"; import { SteamService } from "./steam.service"; import { UtilsService } from "./utils.service"; @@ -33,27 +33,32 @@ export class BSLocalVersionService{ return BSLocalVersionService.instance; } - private constructor(){ - this.installLocationService = InstallationLocationService.getInstance(); - this.utilsService = UtilsService.getInstance(); - this.steamService = SteamService.getInstance(); - this.oculusService = OculusService.getInstance(); - this.remoteVersionService = BSVersionLibService.getInstance(); - this.configService = ConfigurationService.getInstance(); - } + private constructor(){ + this.installLocationService = InstallationLocationService.getInstance(); + this.utilsService = UtilsService.getInstance(); + this.steamService = SteamService.getInstance(); + this.oculusService = OculusService.getInstance(); + this.remoteVersionService = BSVersionLibService.getInstance(); + this.configService = ConfigurationService.getInstance(); + } - private async getVersionOfBSFolder(bsPath: string): Promise{ + + + public async getVersionOfBSFolder(bsPath: string): Promise{ const versionFilePath = path.join(bsPath, 'Beat Saber_Data', 'globalgamemanagers'); if(!this.utilsService.pathExist(versionFilePath)){ return null; } const versionsAvailable = await this.remoteVersionService.getAvailableVersions(); - return new Promise(resolve => { + return new Promise(resolve => { const stream = createReadStream(versionFilePath); - let findVersion: string = null; + let findVersion: PartialBSVersion = null; stream.on('data', (line) => { line = line.toString(); for(const version of versionsAvailable){ if(line.includes(version.BSVersion)){ - findVersion = version.BSVersion; + findVersion = {BSVersion: version.BSVersion}; + if(findVersion.BSVersion !== path.basename(bsPath)){ + findVersion.name = path.basename(bsPath); + } stream.close(); stream.destroy(); break; @@ -118,7 +123,7 @@ export class BSLocalVersionService{ const steamBsVersion = await this.getVersionOfBSFolder(steamBsFolder); if(!steamBsVersion){ return null; } - const version = await this.remoteVersionService.getVersionDetails(steamBsVersion); + const version = await this.remoteVersionService.getVersionDetails(steamBsVersion.BSVersion); if(!version){ return null; } return {...version, steam: true}; } @@ -128,7 +133,7 @@ export class BSLocalVersionService{ if(!oculusBsFolder){ return null; } const oculusBsVersion = await this.getVersionOfBSFolder(oculusBsFolder); if(!oculusBsVersion){ return null; } - const version = await this.remoteVersionService.getVersionDetails(oculusBsVersion); + const version = await this.remoteVersionService.getVersionDetails(oculusBsVersion.BSVersion); if(!version){ return null; } return {...version, oculus: true}; } @@ -151,7 +156,7 @@ export class BSLocalVersionService{ log.info("try get version from folder", f); const rawVersion = await this.getVersionOfBSFolder(f); if(!rawVersion){ continue; } - const bsVersion = {...await this.remoteVersionService.getVersionDetails(rawVersion)}; + const bsVersion = {...await this.remoteVersionService.getVersionDetails(rawVersion.BSVersion)}; if(!bsVersion){ continue; } bsVersion.name = path.basename(f) !== bsVersion.BSVersion ? path.basename(f) : undefined; diff --git a/src/renderer/components/available-versions/available-version-item.component.tsx b/src/renderer/components/available-versions/available-version-item.component.tsx index 30c200b3..033f4cb8 100644 --- a/src/renderer/components/available-versions/available-version-item.component.tsx +++ b/src/renderer/components/available-versions/available-version-item.component.tsx @@ -8,6 +8,8 @@ import { BsmImage } from "../shared/bsm-image.component"; import { useTranslation } from "renderer/hooks/use-translation.hook"; import { BsmIcon } from "../svgs/bsm-icon.component"; import { LinkOpenerService } from 'renderer/services/link-opener.service'; +import { motion } from 'framer-motion'; +import { GlowEffect } from '../shared/glow-effect.component'; export const AvailableVersionItem = memo(function AvailableVersionItem(props: {version: BSVersion}) { @@ -15,6 +17,7 @@ export const AvailableVersionItem = memo(function AvailableVersionItem(props: {v const linkOpener = LinkOpenerService.getInstance(); const [selected, setSelected] = useState(false); + const [hovered, setHovered] = useState(false); const t = useTranslation(); const formatedDate = (() => { return dateFormat(+props.version.ReleaseDate*1000, "ddd. d mmm yyyy"); })() @@ -38,8 +41,8 @@ export const AvailableVersionItem = memo(function AvailableVersionItem(props: {v }, []) return ( -
  • - + setHovered(true)} onHoverEnd={() => setHovered(false)}> +
    @@ -56,6 +59,6 @@ export const AvailableVersionItem = memo(function AvailableVersionItem(props: {v )}
    -
  • + ) }) diff --git a/src/renderer/components/available-versions/available-versions-slide.component.tsx b/src/renderer/components/available-versions/available-versions-slide.component.tsx index 5cbb3484..81921683 100644 --- a/src/renderer/components/available-versions/available-versions-slide.component.tsx +++ b/src/renderer/components/available-versions/available-versions-slide.component.tsx @@ -1,7 +1,7 @@ import { BSVersion } from 'shared/bs-version.interface'; import { useEffect, useState } from "react" import { BSVersionManagerService } from "renderer/services/bs-version-manager.service"; -import { filter, take } from "rxjs/operators"; +import { filter } from "rxjs/operators"; import { AvailableVersionItem } from "./available-version-item.component"; export function AvailableVersionsSlide(props: {year: string}) { @@ -11,7 +11,7 @@ export function AvailableVersionsSlide(props: {year: string}) { const versionsService = BSVersionManagerService.getInstance(); useEffect(() => { - versionsService.availableVersions$.pipe(filter(versions => !!versions?.length), take(1)).subscribe(() => { + versionsService.availableVersions$.pipe(filter(versions => !!versions?.length)).subscribe(() => { setAvailableVersions(versionsService.getAvaibleVersionsOfYear(props.year)); }); }, []) diff --git a/src/renderer/components/available-versions/available-versions-slider.component.tsx b/src/renderer/components/available-versions/available-versions-slider.component.tsx index e87439ce..7fc81a90 100644 --- a/src/renderer/components/available-versions/available-versions-slider.component.tsx +++ b/src/renderer/components/available-versions/available-versions-slider.component.tsx @@ -1,29 +1,29 @@ import { useEffect, useState } from "react" import { BSVersionManagerService } from "../../services/bs-version-manager.service"; import { AvailableVersionsSlide } from "./available-versions-slide.component"; -import { filter, take } from "rxjs/operators"; +import { filter} from "rxjs/operators"; import { TabNavBar } from "../shared/tab-nav-bar.component"; export function AvailableVersionsSlider() { - const [availableYears, setAvailableYears] = useState([]); - const [yearIndex, setYearIndex] = useState(0); + const versionManagerService = BSVersionManagerService.getInstance(); - const versionManagerService = BSVersionManagerService.getInstance(); + const [availableYears, setAvailableYears] = useState([]); + const [yearIndex, setYearIndex] = useState(0); - const setSelectedYear = (index: number) => { - setYearIndex(index); - } + const setSelectedYear = (index: number) => { + setYearIndex(index); + } - useEffect(() => { - versionManagerService.availableVersions$.pipe(filter(versions => !!versions?.length), take(1)).subscribe(() => { - setAvailableYears(versionManagerService.getAvailableYears()); - }); - }, []) + useEffect(() => { + versionManagerService.availableVersions$.pipe(filter(versions => !!versions?.length)).subscribe(() => { + setAvailableYears(versionManagerService.getAvailableYears()); + }); + }, []) return ( -
    - +
    +
      { availableYears.map(year => diff --git a/src/renderer/components/maps-mangement-components/filter-panel.component.tsx b/src/renderer/components/maps-mangement-components/filter-panel.component.tsx index 848923dc..23bd8477 100644 --- a/src/renderer/components/maps-mangement-components/filter-panel.component.tsx +++ b/src/renderer/components/maps-mangement-components/filter-panel.component.tsx @@ -14,6 +14,7 @@ import { MAP_DIFFICULTIES_COLORS } from "renderer/partials/maps/map-difficulties import { BsmButton } from "../shared/bsm-button.component" import equal from "fast-deep-equal/es6"; import clone from "rfdc"; +import { GlowEffect } from "../shared/glow-effect.component" export type Props = { className?: string, @@ -214,7 +215,7 @@ export function FilterPanel({className, ref, playlist = false, filter, onChange, {onApply && (
      - {haveChanged &&
      } +
      )} diff --git a/src/renderer/components/maps-mangement-components/map-item.component.tsx b/src/renderer/components/maps-mangement-components/map-item.component.tsx index 6a8d64b0..e915a278 100644 --- a/src/renderer/components/maps-mangement-components/map-item.component.tsx +++ b/src/renderer/components/maps-mangement-components/map-item.component.tsx @@ -20,6 +20,7 @@ import { useTranslation } from "renderer/hooks/use-translation.hook"; import { MAP_DIFFICULTIES } from "renderer/partials/maps/map-difficulties/map-difficulties"; import { MAP_DIFFICULTIES_COLORS } from "renderer/partials/maps/map-difficulties/map-difficulties-colors" import useDoubleClick from "use-double-click"; +import { GlowEffect } from "../shared/glow-effect.component"; export type ParsedMapDiff = {type: BsvMapDifficultyType, name: string, stars: number} @@ -148,7 +149,7 @@ export const MapItem = memo(({hash, title, autor, songAutor, coverUrl, songUrl, return ( setHovered(true)} onHoverEnd={() => setHovered(false)} style={{zIndex: hovered && 5, transform: "translateZ(0) scale(1.0, 1.0)", backfaceVisibility: "hidden"}}> - {(hovered || selected) && onSelected && } + {(diffsPanelHovered || bottomBarHovered) && ( diff --git a/src/renderer/components/modal/modal-types/import-version-modal.component.tsx b/src/renderer/components/modal/modal-types/import-version-modal.component.tsx new file mode 100644 index 00000000..2f8424a7 --- /dev/null +++ b/src/renderer/components/modal/modal-types/import-version-modal.component.tsx @@ -0,0 +1,22 @@ +import { BsmButton } from 'renderer/components/shared/bsm-button.component' +import { BsmImage } from 'renderer/components/shared/bsm-image.component' +import { useTranslation } from 'renderer/hooks/use-translation.hook' +import { ModalComponent, ModalExitCode } from 'renderer/services/modale.service' +import BeatImpatient from "../../../../../assets/images/apngs/beat-impatient.png" + +export const ImportVersionModal: ModalComponent = ({resolver}) => { + + const t = useTranslation(); + + return ( +
      +

      {t("modals.bs-import-version.title")}

      + +

      {t("modals.bs-import-version.description")}

      +
      + resolver({exitCode: ModalExitCode.CANCELED})} withBar={false} text="misc.cancel"/> + resolver({exitCode: ModalExitCode.COMPLETED})} withBar={false} text="modals.bs-import-version.buttons.submit"/> +
      + + ) +} diff --git a/src/renderer/components/nav-bar/nav-bar.component.tsx b/src/renderer/components/nav-bar/nav-bar.component.tsx index f0b3b9cf..a6062ccd 100644 --- a/src/renderer/components/nav-bar/nav-bar.component.tsx +++ b/src/renderer/components/nav-bar/nav-bar.component.tsx @@ -20,7 +20,7 @@ export function NavBar() { const color = useThemeColor("first-color"); const t = useTranslation(); - const _ = useObservable(I18nService.getInstance().currentLanguage$) + useObservable(I18nService.getInstance().currentLanguage$) return (