diff --git a/src/main/ipcs/bs-download-ipcs.ts b/src/main/ipcs/bs-download-ipcs.ts index 65167fdc..8a5a192b 100644 --- a/src/main/ipcs/bs-download-ipcs.ts +++ b/src/main/ipcs/bs-download-ipcs.ts @@ -35,6 +35,11 @@ ipcMain.on(`bs-download.${"[2FA]" as DownloadEventType}`, async (event, args: Ip BSInstallerService.getInstance().sendInputProcess(args.args); }); +ipcMain.on('bs-download.kill', async (event, request: IpcRequest) => { + const res = await BSInstallerService.getInstance().killDownloadProcess(); + if(request.responceChannel){ UtilsService.getInstance().newIpcSenc(request.responceChannel, {success: res}); } +}); + ipcMain.on('bs-download.installation-folder', async (event, request: IpcRequest) => { const installationFolder = InstallationLocationService.getInstance().installationDirectory; UtilsService.getInstance().newIpcSenc(request.responceChannel, {success: true, data: installationFolder}); diff --git a/src/main/ipcs/bs-uninstall-ipcs.ts b/src/main/ipcs/bs-uninstall-ipcs.ts index 96e3662d..386c5b8b 100644 --- a/src/main/ipcs/bs-uninstall-ipcs.ts +++ b/src/main/ipcs/bs-uninstall-ipcs.ts @@ -2,17 +2,15 @@ import { ipcMain } from "electron"; import { BSUninstallerService } from "../services/bs-uninstaller.service"; import { BSVersion } from "main/services/bs-version-manager.service"; import { UtilsService } from "../services/utils.service"; +import { IpcRequest } from "shared/models/ipc-models.model"; -ipcMain.on('bs.uninstall', async (event, args: BSVersion) => { +ipcMain.on('bs.uninstall', async (event, request: IpcRequest) => { const bsUninstallerService = BSUninstallerService.getInstance(); const utilsService = UtilsService.getInstance(); - bsUninstallerService.uninstall(args) - .then(() => { - utilsService.ipcSend("bs.uninstall.success"); - }) - .catch((e) => { - utilsService.ipcSend("bs.uninstall.error", e) - }) + if(!request.args){ utilsService.newIpcSenc(request.responceChannel, {success: false}); } + + const res = await bsUninstallerService.uninstall(request.args); + utilsService.newIpcSenc(request.responceChannel, {success: res}); }); \ No newline at end of file diff --git a/src/main/services/bs-uninstaller.service.ts b/src/main/services/bs-uninstaller.service.ts index ea55c51b..7ca0d1c8 100644 --- a/src/main/services/bs-uninstaller.service.ts +++ b/src/main/services/bs-uninstaller.service.ts @@ -20,12 +20,14 @@ export class BSUninstallerService { this.bsInstallerService = BSInstallerService.getInstance(); } - public async uninstall(version :BSVersion){ - if(version.steam){ throw "Cannot uninstall steam version"; } - const versionFolder = path.join(this.bsInstallerService.installationFolder, version.BSVersion); - if(!this.utilsService.folderExist(versionFolder)){ throw "Version folder not exist"; } + public async uninstall(version :BSVersion): Promise{ + if(version.steam){ return false; } + const versionFolder = path.join(this.bsInstallerService.installationFolder, version.BSVersion); + if(!this.utilsService.folderExist(versionFolder)){ return true; } - return await this.utilsService.deleteFolder(versionFolder); - } + return this.utilsService.deleteFolder(versionFolder) + .then(() => { return true; }) + .catch(() => { return false; }) + } } \ No newline at end of file diff --git a/src/renderer/components/modal/modal-types/guard-modal.component.tsx b/src/renderer/components/modal/modal-types/guard-modal.component.tsx index 11071f2f..3e123ae3 100644 --- a/src/renderer/components/modal/modal-types/guard-modal.component.tsx +++ b/src/renderer/components/modal/modal-types/guard-modal.component.tsx @@ -24,8 +24,8 @@ export function GuardModal({resolver}: {resolver: (x: ModalResponse) => void}) { setGuardCode(e.target.value.toUpperCase())} value={guardCode} type="guard" name="guard" id="guard" placeholder={t("modals.guard.inputs.guard-code.placeholder")}/>
- {resolver({exitCode: ModalExitCode.CANCELED})}} withBar={false} text={t("misc.cancel")}/> - + {resolver({exitCode: ModalExitCode.CANCELED})}} withBar={false} text="misc.cancel"/> +
) diff --git a/src/renderer/components/nav-bar/bs-version-item.component.tsx b/src/renderer/components/nav-bar/bs-version-item.component.tsx index ed4aac8e..060d4a8b 100644 --- a/src/renderer/components/nav-bar/bs-version-item.component.tsx +++ b/src/renderer/components/nav-bar/bs-version-item.component.tsx @@ -7,17 +7,22 @@ import { useEffect, useState } from "react"; import { combineLatest } from "rxjs"; import { BSLauncherService, LaunchMods } from "renderer/services/bs-launcher.service"; import { ConfigurationService } from "renderer/services/configuration.service"; +import { BsmButton } from "../shared/bsm-button.component"; +import { BSUninstallerService } from "renderer/services/bs-uninstaller.service"; +import { BSVersionManagerService } from "renderer/services/bs-version-manager.service"; -export default function BsVersionItem(props: {version: BSVersion}) { +export function BsVersionItem(props: {version: BSVersion}) { const { state } = useLocation() as { state: BSVersion}; - const [downloading, setDownloading] = useState(false); + const [downloading, setDownloading] = useState(true); const [downloadPercent, setDownloadPercent] = useState(0); const downloaderService = BsDownloaderService.getInstance(); + const verionManagerService = BSVersionManagerService.getInstance(); const launcherService = BSLauncherService.getInstance(); const configService = ConfigurationService.getInstance(); + const bsUninstallerService = BSUninstallerService.getInstance(); const isActive = (): boolean => { return props.version?.BSVersion === state?.BSVersion && props?.version.steam === state?.steam; @@ -33,6 +38,16 @@ export default function BsVersionItem(props: {version: BSVersion}) { ) } + const cancel = () => { + const versionDownload = downloaderService.currentBsVersionDownload$.value; + downloaderService.cancelDownload().then(async res => { + if(!res.success){ return; } + if(!downloaderService.isVerification){ + bsUninstallerService.uninstall(versionDownload).then(res => res && verionManagerService.askInstalledVersions()); + } + }); + } + useEffect(() => { combineLatest([downloaderService.currentBsVersionDownload$, downloaderService.downloadProgress$]).subscribe(vals => { if(vals[0]?.BSVersion === props.version.BSVersion && vals[0]?.steam === props.version.steam){ @@ -48,14 +63,19 @@ export default function BsVersionItem(props: {version: BSVersion}) { return ( -
-
- - {props.version.steam && } - {!props.version.steam && } - {props.version.BSVersion} - +
+
+
+ + {props.version.steam && } + {!props.version.steam && } + {props.version.BSVersion} + + {downloading && } +
) } + +// className={`z-[1] flex cursor-pointer w-full justify-center content-center rounded-full items-center p-[3px] pl-2 pr-2 active:translate-y-[1px] hover:bg-light-main-color-3 dark:hover:bg-main-color-3 ${downloading && 'bg-black'} ${(isActive() && !downloading) && "bg-light-main-color-3 dark:bg-main-color-3"}`} diff --git a/src/renderer/components/nav-bar/nav-bar.component.css b/src/renderer/components/nav-bar/nav-bar.component.css index a54921da..5cd7d329 100644 --- a/src/renderer/components/nav-bar/nav-bar.component.css +++ b/src/renderer/components/nav-bar/nav-bar.component.css @@ -26,13 +26,13 @@ scrollbar-gutter: stable; } -.nav-item-download > div{ +.nav-item-download > .progress{ background-size: 500% !important; background: linear-gradient(90deg, rgb(62, 51, 255), rgb(255, 0, 0), rgb(62, 51, 255), rgb(255, 0, 0)); animation: rainbow 2s linear 0s infinite; } -.nav-item-download > a > *{ +.nav-item-download > .wrapper > a > *{ animation: opacity 3s ease-in-out 0s infinite; } diff --git a/src/renderer/components/nav-bar/nav-bar.component.tsx b/src/renderer/components/nav-bar/nav-bar.component.tsx index a90d08cd..353ccc3f 100644 --- a/src/renderer/components/nav-bar/nav-bar.component.tsx +++ b/src/renderer/components/nav-bar/nav-bar.component.tsx @@ -1,5 +1,5 @@ import './nav-bar.component.css' -import BsVersionItem from './bs-version-item.component'; +import { BsVersionItem } from './bs-version-item.component'; import { BSVersionManagerService } from '../../services/bs-version-manager.service'; import { Link } from 'react-router-dom'; import { ConfigurationService } from 'renderer/services/configuration.service'; @@ -25,7 +25,7 @@ export function NavBar() {
- {installedVersions && installedVersions.map((version) => )} + {installedVersions && installedVersions.map((version) => )}
diff --git a/src/renderer/components/shared/bsm-button.component.tsx b/src/renderer/components/shared/bsm-button.component.tsx index a43ed906..b0950461 100644 --- a/src/renderer/components/shared/bsm-button.component.tsx +++ b/src/renderer/components/shared/bsm-button.component.tsx @@ -4,13 +4,15 @@ import React from "react"; import { BsmImage } from "./bsm-image.component"; import { useTranslation } from "renderer/hooks/use-translation.hook"; -export function BsmButton({className, style, imgClassName, icon, image, text, type, active, withBar = true, disabled, onClickOutside, onClick}: {className?: string, style?: React.CSSProperties, imgClassName?: string, icon?: BsmIconType, image?: string, text?: string, type?: string, active?: boolean, withBar?: boolean, disabled?: boolean, onClickOutside?: (e: MouseEvent) => void, onClick?: (e: React.MouseEvent) => void}) { +type BsmButtonType = "primary"|"success"|"cancel"|"error"; + +export function BsmButton({className, style, imgClassName, icon, image, text, type, active, withBar = true, disabled, onClickOutside, onClick, typeColor}: {className?: string, style?: React.CSSProperties, imgClassName?: string, icon?: BsmIconType, image?: string, text?: string, type?: string, active?: boolean, withBar?: boolean, disabled?: boolean, onClickOutside?: (e: MouseEvent) => void, onClick?: (e: React.MouseEvent) => void, typeColor?:BsmButtonType}) { const t = useTranslation(); return ( onClickOutside && onClickOutside(e)}> -
onClick && onClick(e)} className={`${className} overflow-hidden cursor-pointer group ${disabled && "brightness-75 cursor-not-allowed"}`} style={style}> +
onClick && onClick(e)} className={`${className} overflow-hidden cursor-pointer group ${disabled && "brightness-75 cursor-not-allowed"} ${typeColor == "error" && 'bg-red-500'}`} style={style}> { image && } { icon && } {text && (type === "submit" ? : {t(text)})} diff --git a/src/renderer/services/bs-downloader.service.ts b/src/renderer/services/bs-downloader.service.ts index c50085a6..2317919d 100644 --- a/src/renderer/services/bs-downloader.service.ts +++ b/src/renderer/services/bs-downloader.service.ts @@ -20,12 +20,10 @@ export class BsDownloaderService{ private readonly progressBarService: ProgressBarService; private readonly notificationService: NotificationService; + private _isVerification: boolean = false; + public readonly currentBsVersionDownload$: BehaviorSubject = new BehaviorSubject(null); - public readonly downloadProgress$: BehaviorSubject = new BehaviorSubject(0); - public readonly downloadWarning$: BehaviorSubject = new BehaviorSubject(null); - public readonly downloadError$: BehaviorSubject = new BehaviorSubject(null); - public readonly selectedBsVersion$: BehaviorSubject = new BehaviorSubject(null); public static getInstance(): BsDownloaderService{ @@ -57,9 +55,9 @@ export class BsDownloaderService{ }); this.ipcService.watch("bs-download.[2FA]").subscribe(async response => { - if(!response.success){ return; } + if(!response.success){ this.ipcService.sendLazy("bs-download.kill"); return; } const res = await this.modalService.openModal(ModalType.GUARD_CODE); - if(res.exitCode !== ModalExitCode.COMPLETED){ return; } + if(res.exitCode !== ModalExitCode.COMPLETED){ this.ipcService.sendLazy("bs-download.kill"); return; } this.ipcService.sendLazy('bs-download.[2FA]', {args: res.data}); }); @@ -75,13 +73,13 @@ export class BsDownloaderService{ this.selectedBsVersion$.next(null); } - public async download(bsVersion: BSVersion, isVerification?: boolean): Promise>{ - if(this.progressBarService.visible$.value){ - this.notificationService.notifyError({title: "notifications.bs-download.errors.titles.already-downloading"}); - return {success: false}; - } + public cancelDownload(): Promise>{ + return this.ipcService.send("bs-download.kill"); + } + public async download(bsVersion: BSVersion, isVerification?: boolean): Promise>{ this.progressBarService.show(this.downloadProgress$); + this._isVerification = !!isVerification; let promise; if(!this.authService.sessionExist()){ @@ -106,12 +104,12 @@ export class BsDownloaderService{ this.progressBarService.hide(true); this.resetDownload(); res.success && this.notificationService.notifySuccess({title: `notifications.bs-download.success.titles.${isVerification ? "verification-finished" : "download-success"}`, duration: 3000}); + return res; } - public get isDownloading(): boolean{ - return !!this.currentBsVersionDownload$.value; - } + public get isDownloading(): boolean{ return !!this.currentBsVersionDownload$.value; } + public get isVerification(): boolean{ return this._isVerification; } public async getInstallationFolder(): Promise{ const res = await this.ipcService.send("bs-download.installation-folder"); diff --git a/src/renderer/services/bs-uninstaller.service.ts b/src/renderer/services/bs-uninstaller.service.ts index 0a83299a..7ea19404 100644 --- a/src/renderer/services/bs-uninstaller.service.ts +++ b/src/renderer/services/bs-uninstaller.service.ts @@ -1,31 +1,23 @@ import { BSVersion } from "main/services/bs-version-manager.service"; +import { IpcService } from "./ipc.service"; export class BSUninstallerService{ private static instance: BSUninstallerService; + private readonly ipcService: IpcService; + public static getInstance(): BSUninstallerService{ if(!BSUninstallerService.instance){ BSUninstallerService.instance = new BSUninstallerService(); } return BSUninstallerService.instance; } - private constructor(){}; + private constructor(){ + this.ipcService = IpcService.getInstance(); + }; - public async uninstall(version: BSVersion){ - - const promise = new Promise((reslove, reject) => { - window.electron.ipcRenderer.once("bs.uninstall.error", (e) => { - reject(e); - }) - - window.electron.ipcRenderer.once("bs.uninstall.success", () => { - reslove(); - }) - }); - - window.electron.ipcRenderer.sendMessage("bs.uninstall", version); - - return promise; - } + public async uninstall(version: BSVersion): Promise{ + return (await this.ipcService.send("bs.uninstall", {args: version})).success; + } } \ No newline at end of file