From 5e6837b8cd2ce6c3ebb72663e2450331d3c59e65 Mon Sep 17 00:00:00 2001 From: silentrald Date: Fri, 23 Aug 2024 22:09:32 +0800 Subject: [PATCH 1/8] [feat-560] ask user for installation folder/path --- assets/jsons/translations/de.json | 8 +- assets/jsons/translations/en.json | 8 +- assets/jsons/translations/es.json | 8 +- assets/jsons/translations/fr.json | 8 +- assets/jsons/translations/ja.json | 8 +- assets/jsons/translations/ru.json | 8 +- assets/jsons/translations/zh-tw.json | 8 +- assets/jsons/translations/zh.json | 8 +- src/main/ipcs/bs-installer-ipcs.ts | 27 +++++ .../bs-version-download/bs-download-ipcs.ts | 13 +-- src/main/ipcs/index.ts | 1 + src/main/preload.ts | 3 + src/main/services/configuration.service.ts | 11 +- .../services/installation-location.service.ts | 6 + .../ask-install-path.component.tsx | 103 ++++++++++++++++++ .../components/modal/modal.component.tsx | 36 ++++-- src/renderer/preload.d.ts | 1 + .../steam-downloader.service.ts | 9 +- src/renderer/services/modale.service.ts | 2 +- src/renderer/services/setup.service.ts | 66 +++++++++++ src/renderer/windows/App.tsx | 7 +- src/shared/models/ipc/ipc-routes.ts | 8 +- 22 files changed, 314 insertions(+), 43 deletions(-) create mode 100644 src/main/ipcs/bs-installer-ipcs.ts create mode 100644 src/renderer/components/modal/modal-types/ask-install-path.component.tsx create mode 100644 src/renderer/services/setup.service.ts diff --git a/assets/jsons/translations/de.json b/assets/jsons/translations/de.json index f3edef0c..0b6ec058 100644 --- a/assets/jsons/translations/de.json +++ b/assets/jsons/translations/de.json @@ -14,7 +14,8 @@ "refuse": "Ablehnen", "apply": "Übernehmen", "copy": "Kopieren", - "copied": "Kopiert!" + "copied": "Kopiert!", + "confirm": "Confirm" }, "nav-bar": { "add-version": "Version hinzufügen", @@ -767,6 +768,11 @@ }, "launch-as-admin": "Als Administrator starten", "not-remind-me": "Nicht mehr erinnern" + }, + "ask-install-path": { + "title": "Installations Ordner", + "choose-folder": "Ordner Wählen", + "default": "Default" } }, "maps": { diff --git a/assets/jsons/translations/en.json b/assets/jsons/translations/en.json index 3d9b1392..e80af42c 100644 --- a/assets/jsons/translations/en.json +++ b/assets/jsons/translations/en.json @@ -14,7 +14,8 @@ "refuse": "Refuse", "apply": "Apply", "copy": "Copy", - "copied": "Copied!" + "copied": "Copied!", + "confirm": "Confirm" }, "nav-bar": { "add-version": "Add a version", @@ -774,6 +775,11 @@ }, "launch-as-admin": "Launch as Administrator", "not-remind-me": "Do not remind me" + }, + "ask-install-path": { + "title": "Installation folder", + "choose-folder": "Choose folder", + "default": "Default" } }, "maps": { diff --git a/assets/jsons/translations/es.json b/assets/jsons/translations/es.json index e3122355..c0d85e29 100644 --- a/assets/jsons/translations/es.json +++ b/assets/jsons/translations/es.json @@ -14,7 +14,8 @@ "refuse": "Rechazar", "apply": "Aplicar", "copy": "Copiar", - "copied": "¡Copiado!" + "copied": "¡Copiado!", + "confirm": "Confirm" }, "nav-bar": { "add-version": "Agregar una versión", @@ -767,6 +768,11 @@ }, "launch-as-admin": "Iniciar como Administrador", "not-remind-me": "No volver a recordármelo" + }, + "ask-install-path": { + "title": "Carpeta de instalación", + "choose-folder": "Elige la carpeta", + "default": "Default" } }, "maps": { diff --git a/assets/jsons/translations/fr.json b/assets/jsons/translations/fr.json index d2748d53..1cfca14c 100644 --- a/assets/jsons/translations/fr.json +++ b/assets/jsons/translations/fr.json @@ -14,7 +14,8 @@ "refuse": "Refuser", "apply": "Appliquer", "copy": "Copier", - "copied": "Copié !" + "copied": "Copié !", + "confirm": "Confirm" }, "nav-bar": { "add-version": "Ajouter une version", @@ -768,6 +769,11 @@ }, "launch-as-admin": "Lancer en administateur", "not-remind-me": "Ne plus me rappeler" + }, + "ask-install-path": { + "title": "Dossier d'installation", + "choose-folder": "Choisir un dossier", + "default": "Default" } }, "maps": { diff --git a/assets/jsons/translations/ja.json b/assets/jsons/translations/ja.json index 948f31e8..981d3bd0 100644 --- a/assets/jsons/translations/ja.json +++ b/assets/jsons/translations/ja.json @@ -14,7 +14,8 @@ "refuse": "拒否する", "apply": "適用", "copy": "コピー", - "copied": "コピー済み!" + "copied": "コピー済み!", + "confirm": "Confirm" }, "nav-bar": { "add-version": "バージョンを追加", @@ -767,6 +768,11 @@ }, "launch-as-admin": "管理者として起動", "not-remind-me": "Больше не напоминать" + }, + "ask-install-path": { + "title": "インストールフォルダー", + "choose-folder": "フォルダーを選択", + "default": "Default" } }, "maps": { diff --git a/assets/jsons/translations/ru.json b/assets/jsons/translations/ru.json index c246de4e..48ae1bd7 100644 --- a/assets/jsons/translations/ru.json +++ b/assets/jsons/translations/ru.json @@ -14,7 +14,8 @@ "refuse": "Отказаться", "apply": "Применить", "copy": "Скопировать", - "copied": "Скопировано!" + "copied": "Скопировано!", + "confirm": "Confirm" }, "nav-bar": { "add-version": "Добавить версию игры", @@ -766,6 +767,11 @@ "info-3": "Обратите внимание, что не рекомендуется предоставлять права администратора Steam, так как это также влияет на установленные игры и моды, представляя угрозу безопасности." }, "launch-as-admin": "Запустить от имени администратора" + }, + "ask-install-path": { + "title": "Папка установок", + "choose-folder": "Изменить папку", + "default": "Default" } }, "maps": { diff --git a/assets/jsons/translations/zh-tw.json b/assets/jsons/translations/zh-tw.json index 95ab1ff8..6d23db13 100644 --- a/assets/jsons/translations/zh-tw.json +++ b/assets/jsons/translations/zh-tw.json @@ -14,7 +14,8 @@ "refuse": "拒絕", "apply": "應用", "copy": "複製", - "copied": "已複製!" + "copied": "已複製!", + "confirm": "Confirm" }, "nav-bar": { "add-version": "新增版本", @@ -767,6 +768,11 @@ }, "launch-as-admin": "以管理員身份啟動", "not-remind-me": "不再提醒我" + }, + "ask-install-path": { + "title": "安裝文件夾", + "choose-folder": "選擇文件夾", + "default": "Default" } }, "maps": { diff --git a/assets/jsons/translations/zh.json b/assets/jsons/translations/zh.json index b052d4c2..86bfac7e 100644 --- a/assets/jsons/translations/zh.json +++ b/assets/jsons/translations/zh.json @@ -14,7 +14,8 @@ "refuse": "拒绝", "apply": "应用", "copy": "复制", - "copied": "已复制!" + "copied": "已复制!", + "confirm": "Confirm" }, "nav-bar": { "add-version": "添加版本", @@ -767,6 +768,11 @@ }, "launch-as-admin": "以管理员身份启动", "not-remind-me": "不再提醒我" + }, + "ask-install-path": { + "title": "安装文件夹", + "choose-folder": "选择文件夹", + "default": "Default" } }, "maps": { diff --git a/src/main/ipcs/bs-installer-ipcs.ts b/src/main/ipcs/bs-installer-ipcs.ts new file mode 100644 index 00000000..25672b13 --- /dev/null +++ b/src/main/ipcs/bs-installer-ipcs.ts @@ -0,0 +1,27 @@ +import { pathExistsSync } from "fs-extra"; +import { from, of } from "rxjs"; + +import { InstallationLocationService } from "main/services/installation-location.service"; +import { IpcService } from "main/services/ipc.service"; + +const ipc = IpcService.getInstance(); + +ipc.on("bs-installer.folder-exists", (_, reply) => { + const service = InstallationLocationService.getInstance(); + reply(of(pathExistsSync(service.installationDirectory()))); +}); + +ipc.on("bs-installer.default-install-path", (_, reply) => { + const service = InstallationLocationService.getInstance(); + reply(of(service.defaultInstallationDirectory())); +}); + +ipc.on("bs-installer.install-path", (_, reply) => { + const service = InstallationLocationService.getInstance(); + reply(of(service.installationDirectory())); +}); + +ipc.on("bs-installer.set-install-path", (args, reply) => { + const service = InstallationLocationService.getInstance(); + reply(from(service.setInstallationDirectory(args))); +}); diff --git a/src/main/ipcs/bs-version-download/bs-download-ipcs.ts b/src/main/ipcs/bs-version-download/bs-download-ipcs.ts index c27c591d..dfc4e682 100644 --- a/src/main/ipcs/bs-version-download/bs-download-ipcs.ts +++ b/src/main/ipcs/bs-version-download/bs-download-ipcs.ts @@ -1,8 +1,7 @@ import { BsOculusDownloaderService } from "../../services/bs-version-download/bs-oculus-downloader.service"; import { BsSteamDownloaderService } from "../../services/bs-version-download/bs-steam-downloader.service"; -import { InstallationLocationService } from "../../services/installation-location.service"; import { IpcService } from "../../services/ipc.service"; -import { from, of } from "rxjs"; +import { of } from "rxjs"; import { BSLocalVersionService } from "../../services/bs-local-version.service"; const ipc = IpcService.getInstance(); @@ -14,16 +13,6 @@ ipc.on("import-version", (args, reply) => { // #region Steam -ipc.on("bs-download.installation-folder", (_, reply) => { - const installLocation = InstallationLocationService.getInstance(); - reply(of(installLocation.installationDirectory())); -}); - -ipc.on("bs-download.set-installation-folder", (args, reply) => { - const installerService = InstallationLocationService.getInstance(); - reply(from(installerService.setInstallationDirectory(args))); -}); - ipc.on("auto-download-bs-version", (args, reply) => { const bsInstaller = BsSteamDownloaderService.getInstance(); reply(bsInstaller.autoDownloadBsVersion(args)); diff --git a/src/main/ipcs/index.ts b/src/main/ipcs/index.ts index 38384c27..f80cf9f8 100644 --- a/src/main/ipcs/index.ts +++ b/src/main/ipcs/index.ts @@ -1,4 +1,5 @@ import "./os-controls-ipcs"; +import "./bs-installer-ipcs.ts"; import "./bs-launcher-ipcs"; import "./bs-version-ipcs"; import "./bs-uninstall-ipcs"; diff --git a/src/main/preload.ts b/src/main/preload.ts index 243f5e76..a4958a7f 100644 --- a/src/main/preload.ts +++ b/src/main/preload.ts @@ -24,6 +24,9 @@ contextBridge.exposeInMainWorld("electron", { }, path: { sep, + basename: (path: string): string => { + return !path ? "" : path.split(sep).at(-1); + }, join: (...args: string[]): string => { return args.join(sep); } diff --git a/src/main/services/configuration.service.ts b/src/main/services/configuration.service.ts index 9049a009..a299d281 100644 --- a/src/main/services/configuration.service.ts +++ b/src/main/services/configuration.service.ts @@ -1,4 +1,5 @@ import ElectronStore from "electron-store"; +import fs from "fs-extra"; import { InstallationLocationService } from "./installation-location.service"; export class ConfigurationService { @@ -17,13 +18,17 @@ export class ConfigurationService { private constructor() { this.locations = InstallationLocationService.getInstance(); - this.initStore(); + this.initStore(false); - this.locations.onInstallLocationUpdate(() => { this.initStore() }); + this.locations.onInstallLocationUpdate(() => this.initStore(true)); } - private async initStore() { + private async initStore(createFolder: boolean) { const contentPath = this.locations.installationDirectory(); + if (!createFolder && !fs.pathExistsSync(contentPath)) { + return; + } + this.store = new ElectronStore({ cwd: contentPath, name: "config", diff --git a/src/main/services/installation-location.service.ts b/src/main/services/installation-location.service.ts index f1c012f1..1696ea0d 100644 --- a/src/main/services/installation-location.service.ts +++ b/src/main/services/installation-location.service.ts @@ -59,6 +59,12 @@ export class InstallationLocationService { this.updateListeners.add(fn); } + public defaultInstallationDirectory(): string { + const { result: oldPath } = tryit(() => path.join(app.getPath("documents"), this.INSTALLATION_FOLDER)); + const installationDirectory = (oldPath && pathExistsSync(oldPath)) ? app.getPath("documents") : app.getPath("home"); + return path.join(installationDirectory, this.INSTALLATION_FOLDER); + } + public installationDirectory(): string { const installParentPath = () => { diff --git a/src/renderer/components/modal/modal-types/ask-install-path.component.tsx b/src/renderer/components/modal/modal-types/ask-install-path.component.tsx new file mode 100644 index 00000000..eb94fcde --- /dev/null +++ b/src/renderer/components/modal/modal-types/ask-install-path.component.tsx @@ -0,0 +1,103 @@ +import { lastValueFrom } from "rxjs"; +import { useEffect, useState } from "react"; +import { useTranslation } from "renderer/hooks/use-translation.hook"; +import { useService } from "renderer/hooks/use-service.hook"; + +import { IpcService } from "renderer/services/ipc.service"; +import { ModalComponent, ModalExitCode } from "renderer/services/modale.service"; + +import { BsmButton } from "renderer/components/shared/bsm-button.component"; + +export const AskInstallPathModal: ModalComponent<{ installPath: string }, {}> = ({ resolver }) => { + + const t = useTranslation(); + const ipcService = useService(IpcService); + + const [installPath, setInstallPath] = useState(""); + const [installFolder, setInstallFolder] = useState(""); + const [defaultInstallPath, setDefaultInstallPath] = useState(""); + + useEffect(() => { + lastValueFrom(ipcService.sendV2("bs-installer.default-install-path")) + .then(defaultPath => { + setInstallPath(defaultPath); + setDefaultInstallPath(defaultPath); + setInstallFolder(window.electron.path.basename(defaultPath)); + }); + }, []); + + const selectInstallPath = async () => { + const response = await lastValueFrom(ipcService.sendV2("choose-folder")); + if (response.canceled || !response.filePaths?.length) { + return; + } + + const path = response.filePaths[0]; + setInstallPath( + window.electron.path.basename(path) === installFolder ? + path : + window.electron.path.join(response.filePaths[0], installFolder) + ); + } + + const onDefaultButtonPressed = () => { + setInstallPath(defaultInstallPath); + } + + const onConfirmButtonPressed = () => { + resolver({ + data: { installPath }, + exitCode: ModalExitCode.COMPLETED + }); + } + + return ( +
{ + event.preventDefault(); + onConfirmButtonPressed(); + }}> + +

+ {t("modals.ask-install-path.title")} +

+ +
+ + {installPath} + + +
+ +
+ + +
+
+ ) +} diff --git a/src/renderer/components/modal/modal.component.tsx b/src/renderer/components/modal/modal.component.tsx index fe047633..2d06fbe3 100644 --- a/src/renderer/components/modal/modal.component.tsx +++ b/src/renderer/components/modal/modal.component.tsx @@ -17,7 +17,7 @@ export function Modal() { useEffect(() => { const onEscape = (e: KeyboardEvent) => { - if (e.key !== "Escape") { + if (currentModal.options.closable === false || e.key !== "Escape") { return; } currentModal.resolver({ exitCode: ModalExitCode.CLOSED }); @@ -34,6 +34,20 @@ export function Modal() { }; }, [currentModal]); + const renderCloseButton = (modal: ModalObject) => { + return ( +
{ + e.stopPropagation(); + modal.resolver({ exitCode: ModalExitCode.CLOSED }); + }} + > + +
+ ) + } + const renderModal = (modal: ModalObject) => { if (!modal?.modal) { return null; } @@ -44,23 +58,23 @@ export function Modal() { return (
-
{ - e.stopPropagation(); - modal.resolver({ exitCode: ModalExitCode.CLOSED }); - }} - > - -
+ {modal.options?.closable === false ? undefined : renderCloseButton(modal)}
) } + const onOverlayClicked = () => { + if (currentModal.options.closable === false) { + return; + } + + currentModal.resolver({ exitCode: ModalExitCode.NO_CHOICE }); + } + return ( - {currentModal ? currentModal.resolver({ exitCode: ModalExitCode.NO_CHOICE })} className="fixed size-full bg-black z-[90]" initial={{ opacity: 0 }} animate={{ opacity: currentModal && 0.6 }} exit={{ opacity: 0 }} transition={{ duration: 0.2 }} /> : undefined} + {currentModal ? : undefined} {modals?.map(modal => ( {renderModal(modal)} diff --git a/src/renderer/preload.d.ts b/src/renderer/preload.d.ts index 29aace8b..51f2568b 100644 --- a/src/renderer/preload.d.ts +++ b/src/renderer/preload.d.ts @@ -10,6 +10,7 @@ declare global { }; path: { sep: "/"|"\\"; + basename: (path: string) => string; join: (...args: string[]) => string; }; }; diff --git a/src/renderer/services/bs-version-download/steam-downloader.service.ts b/src/renderer/services/bs-version-download/steam-downloader.service.ts index 56e3e7c3..7e10de70 100644 --- a/src/renderer/services/bs-version-download/steam-downloader.service.ts +++ b/src/renderer/services/bs-version-download/steam-downloader.service.ts @@ -8,7 +8,6 @@ import { NotificationService } from "../notification.service"; import { ProgressBarService } from "../progress-bar.service"; import { LoginToSteamModal } from "renderer/components/modal/modal-types/bs-downgrade/login-to-steam-modal.component"; import { SteamGuardModal } from "renderer/components/modal/modal-types/bs-downgrade/steam-guard-modal.component"; -import { LinkOpenerService } from "../link-opener.service"; import { DepotDownloaderErrorEvent, DepotDownloaderEvent, DepotDownloaderEventType, DepotDownloaderInfoEvent, DepotDownloaderWarningEvent } from "../../../shared/models/bs-version-download/depot-downloader.model"; import { SteamMobileApproveModal } from "renderer/components/modal/modal-types/bs-downgrade/steam-mobile-approve-modal.component"; import { DownloaderServiceInterface } from "./bs-store-downloader.interface"; @@ -30,7 +29,6 @@ export class SteamDownloaderService extends AbstractBsDownloaderService implemen private readonly ipcService: IpcService; private readonly progressBarService: ProgressBarService; private readonly notificationService: NotificationService; - private readonly linkOpener: LinkOpenerService; private readonly STEAM_SESSION_USERNAME_KEY = "STEAM-USERNAME"; @@ -42,7 +40,6 @@ export class SteamDownloaderService extends AbstractBsDownloaderService implemen this.modalService = ModalService.getInstance(); this.progressBarService = ProgressBarService.getInstance(); this.notificationService = NotificationService.getInstance(); - this.linkOpener = LinkOpenerService.getInstance(); } private setSteamSession(username: string): void { localStorage.setItem(this.STEAM_SESSION_USERNAME_KEY, username); } @@ -50,12 +47,14 @@ export class SteamDownloaderService extends AbstractBsDownloaderService implemen public deleteSteamSession(): void { localStorage.removeItem(this.STEAM_SESSION_USERNAME_KEY); } public sessionExist(): boolean { return !!localStorage.getItem(this.STEAM_SESSION_USERNAME_KEY); } + // TODO: Move to another service in the future public async getInstallationFolder(): Promise { - return lastValueFrom(this.ipcService.sendV2("bs-download.installation-folder")); + return lastValueFrom(this.ipcService.sendV2("bs-installer.install-path")); } + // TODO: Move to another service in the future public setInstallationFolder(path: string): Observable { - return this.ipcService.sendV2("bs-download.set-installation-folder", path); + return this.ipcService.sendV2("bs-installer.set-install-path", path); } // ### Downloading diff --git a/src/renderer/services/modale.service.ts b/src/renderer/services/modale.service.ts index f1391b81..2ff9e6f9 100644 --- a/src/renderer/services/modale.service.ts +++ b/src/renderer/services/modale.service.ts @@ -39,7 +39,7 @@ export class ModalService { } } -export type ModalOptions = { readonly data?: T, readonly noStyle?: boolean } +export type ModalOptions = { readonly data?: T, readonly noStyle?: boolean, readonly closable?: boolean } export type ModalComponent = ({ resolver, options }: { readonly resolver: (x: ModalResponse) => void; readonly options?: ModalOptions }) => JSX.Element; export type ModalObject = {modal: ModalComponent, resolver: (value: ModalResponse | PromiseLike) => void, options: ModalOptions}; diff --git a/src/renderer/services/setup.service.ts b/src/renderer/services/setup.service.ts new file mode 100644 index 00000000..92448a8c --- /dev/null +++ b/src/renderer/services/setup.service.ts @@ -0,0 +1,66 @@ +import { lastValueFrom } from "rxjs"; +import { logRenderError } from "renderer"; + +import { BSVersionManagerService } from "./bs-version-manager.service"; +import { IpcService } from "./ipc.service"; +import { ModalExitCode, ModalResponse, ModalService } from "./modale.service"; +import { SteamDownloaderService } from "./bs-version-download/steam-downloader.service"; + +import { AskInstallPathModal } from "renderer/components/modal/modal-types/ask-install-path.component"; + +// Handle setup modals/prompts, ordering of the modals/prompts may be done here +export class SetupService { + private static instance: SetupService; + + private readonly ipcService: IpcService; + private readonly modalService: ModalService; + private readonly steamDownloaderService: SteamDownloaderService; + private readonly versionManagerService: BSVersionManagerService; + + private constructor() { + this.ipcService = IpcService.getInstance(); + this.modalService = ModalService.getInstance(); + this.steamDownloaderService = SteamDownloaderService.getInstance(); + this.versionManagerService = BSVersionManagerService.getInstance(); + } + + public static getInstance(): SetupService { + if (!SetupService.instance) { + SetupService.instance = new SetupService(); + } + return SetupService.instance; + } + + public async check(): Promise { + try { + await this.checkInstallationPath(); + } catch (error) { + logRenderError(error); + } + } + + private async checkInstallationPath(): Promise { + try { + const exists = await lastValueFrom(this.ipcService.sendV2("bs-installer.folder-exists")) + if (exists) { + return; + } + + let modalResponse: ModalResponse<{ installPath: string }> = { exitCode: ModalExitCode.NO_CHOICE }; + while (modalResponse.exitCode !== ModalExitCode.COMPLETED) { + modalResponse = await this.modalService.openModal( + AskInstallPathModal, + { closable: false } + ); + } + + await lastValueFrom(this.steamDownloaderService.setInstallationFolder(modalResponse.data.installPath)); + + // Refresh the versions tab + await this.versionManagerService.askInstalledVersions() + } catch (error) { + logRenderError(error); + } + } + +} diff --git a/src/renderer/windows/App.tsx b/src/renderer/windows/App.tsx index e7812ca5..44addcde 100644 --- a/src/renderer/windows/App.tsx +++ b/src/renderer/windows/App.tsx @@ -23,6 +23,7 @@ import { ConfigurationService } from "renderer/services/configuration.service"; import { OsDiagnosticService } from "renderer/services/os-diagnostic.service"; import { useService } from "renderer/hooks/use-service.hook"; import { AutoUpdaterService } from "renderer/services/auto-updater.service"; +import { SetupService } from "renderer/services/setup.service"; import { gt, parse } from "semver" import { logRenderError } from "renderer"; @@ -35,13 +36,17 @@ export default function App() { const notification = useService(NotificationService); const config = useService(ConfigurationService); const autoUpdater = useService(AutoUpdaterService); + const setup = useService(SetupService); const location = useLocation(); const navigate = useNavigate(); useEffect(() => { checkIsUpdated(); - checkOneClicks(); + setup.check() + .then(() => { + checkOneClicks(); + }) }, []); const checkIsUpdated = async () => { diff --git a/src/shared/models/ipc/ipc-routes.ts b/src/shared/models/ipc/ipc-routes.ts index 2589a7c0..63a128bb 100644 --- a/src/shared/models/ipc/ipc-routes.ts +++ b/src/shared/models/ipc/ipc-routes.ts @@ -27,8 +27,6 @@ export interface IpcChannelMapping { /* ** bs-download-ipcs ** */ "import-version": { request: ImportVersionOptions, response: Progression}; - "bs-download.installation-folder": { request: void, response: string}; - "bs-download.set-installation-folder": { request: string, response: string}; "auto-download-bs-version": { request: DownloadSteamInfo, response: DepotDownloaderEvent}; "download-bs-version": { request: DownloadSteamInfo, response: DepotDownloaderEvent}; "download-bs-version-qr": { request: DownloadSteamInfo, response: DepotDownloaderEvent}; @@ -44,6 +42,12 @@ export interface IpcChannelMapping { "bsv-search-playlist": {request: PlaylistSearchParams, response: BsvPlaylist[]}; "bsv-get-playlist-details-by-id": {request: {id: string, page: number}, response: BsvPlaylistPage}; + /* ** bs-installer-ipcs ** */ + "bs-installer.folder-exists": { require: void, response: boolean }; + "bs-installer.default-install-path": { request: void, response: string }; + "bs-installer.install-path": { request: void, response: string}; + "bs-installer.set-install-path": { request: string, response: string}; + /* ** bs-launcher-ipcs ** */ "create-launch-shortcut": { request: LaunchOption, response: boolean }; "bs-launch.need-start-as-admin": { request: void, response: boolean }; From d3c797041f1483a2b4a40e0b62b8253f98a45244 Mon Sep 17 00:00:00 2001 From: silentrald Date: Sat, 24 Aug 2024 00:40:10 +0800 Subject: [PATCH 2/8] [feat-560] delay song details cache loading after user setup is done added check if ElectronStore is null --- src/main/services/configuration.service.ts | 13 +++++++++++++ .../modal-types/ask-install-path.component.tsx | 6 +++--- src/renderer/services/setup.service.ts | 3 ++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/services/configuration.service.ts b/src/main/services/configuration.service.ts index a299d281..c1270769 100644 --- a/src/main/services/configuration.service.ts +++ b/src/main/services/configuration.service.ts @@ -1,6 +1,7 @@ import ElectronStore from "electron-store"; import fs from "fs-extra"; import { InstallationLocationService } from "./installation-location.service"; +import { CustomError } from "shared/models/exceptions/custom-error.class"; export class ConfigurationService { private static instance: ConfigurationService; @@ -14,6 +15,7 @@ export class ConfigurationService { private readonly locations: InstallationLocationService; + private contentPath: string; private store: ElectronStore; private constructor() { @@ -29,6 +31,7 @@ export class ConfigurationService { return; } + this.contentPath = contentPath; this.store = new ElectronStore({ cwd: contentPath, name: "config", @@ -37,15 +40,25 @@ export class ConfigurationService { }); } + private checkStore(): void { + // Can be null if config.cfg does not exist or corrupted + if (!this.store) { + throw CustomError.fromError(new Error(`Can't read config.cfg on ${this.contentPath}`)); + } + } + public set(key: string, value: unknown): void { + this.checkStore(); this.store.set(key, value); } public get(key: string): T { + this.checkStore(); return this.store.get(key) as T; } public delete(key: string): void { + this.checkStore(); this.store.delete(key); } } diff --git a/src/renderer/components/modal/modal-types/ask-install-path.component.tsx b/src/renderer/components/modal/modal-types/ask-install-path.component.tsx index eb94fcde..c712b118 100644 --- a/src/renderer/components/modal/modal-types/ask-install-path.component.tsx +++ b/src/renderer/components/modal/modal-types/ask-install-path.component.tsx @@ -77,7 +77,7 @@ export const AskInstallPathModal: ModalComponent<{ installPath: string }, {}> = @@ -88,14 +88,14 @@ export const AskInstallPathModal: ModalComponent<{ installPath: string }, {}> = className="col-start-3 rounded-md text-center transition-all" onClick={onDefaultButtonPressed} withBar={false} - text={"modals.ask-install-path.default"} + text="modals.ask-install-path.default" /> diff --git a/src/renderer/services/setup.service.ts b/src/renderer/services/setup.service.ts index 92448a8c..316e1710 100644 --- a/src/renderer/services/setup.service.ts +++ b/src/renderer/services/setup.service.ts @@ -33,6 +33,7 @@ export class SetupService { public async check(): Promise { try { + // NOTE: for modal sequencing await this.checkInstallationPath(); } catch (error) { logRenderError(error); @@ -57,7 +58,7 @@ export class SetupService { await lastValueFrom(this.steamDownloaderService.setInstallationFolder(modalResponse.data.installPath)); // Refresh the versions tab - await this.versionManagerService.askInstalledVersions() + await this.versionManagerService.askInstalledVersions(); } catch (error) { logRenderError(error); } From 6258de5b06d8c2177d6096166bf06c26651ae0e1 Mon Sep 17 00:00:00 2001 From: silentrald Date: Sun, 25 Aug 2024 11:57:03 +0800 Subject: [PATCH 3/8] [feat-560] added description text and default button tooltip added tooltip support in BsmButton component --- assets/jsons/translations/de.json | 6 ++-- assets/jsons/translations/en.json | 6 ++-- assets/jsons/translations/es.json | 6 ++-- assets/jsons/translations/fr.json | 8 +++-- assets/jsons/translations/ja.json | 6 ++-- assets/jsons/translations/ru.json | 6 ++-- assets/jsons/translations/zh-tw.json | 6 ++-- assets/jsons/translations/zh.json | 6 ++-- .../ask-install-path.component.tsx | 21 +++++------ .../shared/bsm-button.component.tsx | 36 ++++++++++++++++--- 10 files changed, 73 insertions(+), 34 deletions(-) diff --git a/assets/jsons/translations/de.json b/assets/jsons/translations/de.json index 0b6ec058..32dcf2eb 100644 --- a/assets/jsons/translations/de.json +++ b/assets/jsons/translations/de.json @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "Installations-Ordner", - "description": "Ändere den Standardordner für Beat Saber-Versionen und andere kommende Funktionen.", + "description": "Change the folder that will contain all the content downloaded by BSManager.", "choose-folder": "Ordner wählen" }, "additional-content": { @@ -771,8 +771,10 @@ }, "ask-install-path": { "title": "Installations Ordner", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", "choose-folder": "Ordner Wählen", - "default": "Default" + "default": "Default", + "default-tooltip": "Defaults to your home folder" } }, "maps": { diff --git a/assets/jsons/translations/en.json b/assets/jsons/translations/en.json index e80af42c..02eda720 100644 --- a/assets/jsons/translations/en.json +++ b/assets/jsons/translations/en.json @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "Installation folder", - "description": "Change the default folder for Beat Saber versions and other upcoming features.", + "description": "Change the folder that will contain all the content downloaded by BSManager.", "choose-folder": "Choose folder" }, "proton-path": { @@ -778,8 +778,10 @@ }, "ask-install-path": { "title": "Installation folder", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", "choose-folder": "Choose folder", - "default": "Default" + "default": "Default", + "default-tooltip": "Defaults to your home folder" } }, "maps": { diff --git a/assets/jsons/translations/es.json b/assets/jsons/translations/es.json index c0d85e29..7f05e99c 100644 --- a/assets/jsons/translations/es.json +++ b/assets/jsons/translations/es.json @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "Carpeta de instalación", - "description": "Cambia la carpeta por defecto para las versiones de Beat Saber y próximas funciones.", + "description": "Change the folder that will contain all the content downloaded by BSManager.", "choose-folder": "Elige la carpeta" }, "additional-content": { @@ -771,8 +771,10 @@ }, "ask-install-path": { "title": "Carpeta de instalación", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", "choose-folder": "Elige la carpeta", - "default": "Default" + "default": "Default", + "default-tooltip": "Defaults to your home folder" } }, "maps": { diff --git a/assets/jsons/translations/fr.json b/assets/jsons/translations/fr.json index 1cfca14c..d5389053 100644 --- a/assets/jsons/translations/fr.json +++ b/assets/jsons/translations/fr.json @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "Dossier d'installation", - "description": "Change le dossier par défaut pour les versions de Beat Saber et d'autres fonctionnalités à venir.", + "description": "Change the folder that will contain all the content downloaded by BSManager.", "choose-folder": "Choisir un dossier" }, "additional-content": { @@ -771,9 +771,11 @@ "not-remind-me": "Ne plus me rappeler" }, "ask-install-path": { - "title": "Dossier d'installation", + "title": "Dossier d'installation", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", "choose-folder": "Choisir un dossier", - "default": "Default" + "default": "Default", + "default-tooltip": "Defaults to your home folder" } }, "maps": { diff --git a/assets/jsons/translations/ja.json b/assets/jsons/translations/ja.json index 981d3bd0..09d4c926 100644 --- a/assets/jsons/translations/ja.json +++ b/assets/jsons/translations/ja.json @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "インストールフォルダー", - "description": "BeatSaberのバージョンとその他の今後の機能を入れるフォルダを変更します。", + "description": "Change the folder that will contain all the content downloaded by BSManager.", "choose-folder": "フォルダーを選択" }, "additional-content": { @@ -771,8 +771,10 @@ }, "ask-install-path": { "title": "インストールフォルダー", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", "choose-folder": "フォルダーを選択", - "default": "Default" + "default": "Default", + "default-tooltip": "Defaults to your home folder" } }, "maps": { diff --git a/assets/jsons/translations/ru.json b/assets/jsons/translations/ru.json index 48ae1bd7..e51abe3d 100644 --- a/assets/jsons/translations/ru.json +++ b/assets/jsons/translations/ru.json @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "Папка установок", - "description": "Измените стандартную папку, где будут версии Beat Saber и прочее.", + "description": "Change the folder that will contain all the content downloaded by BSManager.", "choose-folder": "Изменить папку" }, "additional-content": { @@ -770,8 +770,10 @@ }, "ask-install-path": { "title": "Папка установок", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", "choose-folder": "Изменить папку", - "default": "Default" + "default": "Default", + "default-tooltip": "Defaults to your home folder" } }, "maps": { diff --git a/assets/jsons/translations/zh-tw.json b/assets/jsons/translations/zh-tw.json index 6d23db13..cf1abe80 100644 --- a/assets/jsons/translations/zh-tw.json +++ b/assets/jsons/translations/zh-tw.json @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "安裝文件夾", - "description": "為 BeatSaber 不同版本及未來其他特性修改預設文件夾", + "description": "Change the folder that will contain all the content downloaded by BSManager.", "choose-folder": "選擇文件夾" }, "additional-content": { @@ -771,8 +771,10 @@ }, "ask-install-path": { "title": "安裝文件夾", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", "choose-folder": "選擇文件夾", - "default": "Default" + "default": "Default", + "default-tooltip": "Defaults to your home folder" } }, "maps": { diff --git a/assets/jsons/translations/zh.json b/assets/jsons/translations/zh.json index 86bfac7e..c881232d 100644 --- a/assets/jsons/translations/zh.json +++ b/assets/jsons/translations/zh.json @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "安装文件夹", - "description": "为 BeatSaber 不同版本及未来其他特性修改默认文件夹", + "description": "Change the folder that will contain all the content downloaded by BSManager.", "choose-folder": "选择文件夹" }, "additional-content": { @@ -771,8 +771,10 @@ }, "ask-install-path": { "title": "安装文件夹", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", "choose-folder": "选择文件夹", - "default": "Default" + "default": "Default", + "default-tooltip": "Defaults to your home folder" } }, "maps": { diff --git a/src/renderer/components/modal/modal-types/ask-install-path.component.tsx b/src/renderer/components/modal/modal-types/ask-install-path.component.tsx index c712b118..347868b6 100644 --- a/src/renderer/components/modal/modal-types/ask-install-path.component.tsx +++ b/src/renderer/components/modal/modal-types/ask-install-path.component.tsx @@ -59,18 +59,14 @@ export const AskInstallPathModal: ModalComponent<{ installPath: string }, {}> = onConfirmButtonPressed(); }}> -

+

{t("modals.ask-install-path.title")}

-
+

+ {t("modals.ask-install-path.choose-folder-description")} +

+
{installPath} @@ -82,17 +78,18 @@ export const AskInstallPathModal: ModalComponent<{ installPath: string }, {}> = />
-
+
(({ className, style, iconStyle, imgClassName, iconClassName, icon, image, text, type, active, withBar = true, disabled, onClickOutside, onClick, typeColor, color, title, iconColor, textClassName }, forwardedRef) => { +export const BsmButton = forwardRef(({ + className, style, iconStyle, imgClassName, iconClassName, + icon, image, text, type, active, withBar = true, disabled, + onClickOutside, onClick, + typeColor, color, title, iconColor, textClassName, + tooltip, tooltipIcon +}, forwardedRef) => { const t = useTranslation(); const { firstColor, secondColor } = useThemeColor(); const ref = useRef(null); @@ -84,18 +93,35 @@ export const BsmButton = forwardRef(({ className, style, iconSty const handleClick = (e: MouseEvent) => !disabled && onClick?.(e); + const renderTooltip = () => { + return ( + +
+ +
+
+ ); + } + return (
{image && } {icon && } {text && (type === "submit" ? ( - ) : ( - - {t(text)} + + {t(text)} + {tooltip && renderTooltip()} ))} {withBar && ( From 9c86adf2d44fe18cf6869b64e3b807f164f21d76 Mon Sep 17 00:00:00 2001 From: silentrald Date: Sun, 25 Aug 2024 20:55:50 +0800 Subject: [PATCH 4/8] [feat-560] applied PR comments --- .../ask-install-path.component.tsx | 26 +++++++++----- .../shared/bsm-button.component.tsx | 36 +++---------------- src/renderer/services/setup.service.ts | 15 ++++---- src/shared/models/ipc/ipc-routes.ts | 2 +- 4 files changed, 29 insertions(+), 50 deletions(-) diff --git a/src/renderer/components/modal/modal-types/ask-install-path.component.tsx b/src/renderer/components/modal/modal-types/ask-install-path.component.tsx index 347868b6..828c49b9 100644 --- a/src/renderer/components/modal/modal-types/ask-install-path.component.tsx +++ b/src/renderer/components/modal/modal-types/ask-install-path.component.tsx @@ -2,6 +2,7 @@ import { lastValueFrom } from "rxjs"; import { useEffect, useState } from "react"; import { useTranslation } from "renderer/hooks/use-translation.hook"; import { useService } from "renderer/hooks/use-service.hook"; +import Tippy from "@tippyjs/react"; import { IpcService } from "renderer/services/ipc.service"; import { ModalComponent, ModalExitCode } from "renderer/services/modale.service"; @@ -79,17 +80,24 @@ export const AskInstallPathModal: ModalComponent<{ installPath: string }, {}> =
- + + + (({ - className, style, iconStyle, imgClassName, iconClassName, - icon, image, text, type, active, withBar = true, disabled, - onClickOutside, onClick, - typeColor, color, title, iconColor, textClassName, - tooltip, tooltipIcon -}, forwardedRef) => { +export const BsmButton = forwardRef(({ className, style, iconStyle, imgClassName, iconClassName, icon, image, text, type, active, withBar = true, disabled, onClickOutside, onClick, typeColor, color, title, iconColor, textClassName }, forwardedRef) => { const t = useTranslation(); const { firstColor, secondColor } = useThemeColor(); const ref = useRef(null); @@ -93,35 +84,18 @@ export const BsmButton = forwardRef(({ const handleClick = (e: MouseEvent) => !disabled && onClick?.(e); - const renderTooltip = () => { - return ( - -
- -
-
- ); - } - return (
{image && } {icon && } {text && (type === "submit" ? ( - ) : ( - - {t(text)} - {tooltip && renderTooltip()} + + {t(text)} ))} {withBar && ( diff --git a/src/renderer/services/setup.service.ts b/src/renderer/services/setup.service.ts index 316e1710..e2d105d1 100644 --- a/src/renderer/services/setup.service.ts +++ b/src/renderer/services/setup.service.ts @@ -3,7 +3,7 @@ import { logRenderError } from "renderer"; import { BSVersionManagerService } from "./bs-version-manager.service"; import { IpcService } from "./ipc.service"; -import { ModalExitCode, ModalResponse, ModalService } from "./modale.service"; +import { ModalService } from "./modale.service"; import { SteamDownloaderService } from "./bs-version-download/steam-downloader.service"; import { AskInstallPathModal } from "renderer/components/modal/modal-types/ask-install-path.component"; @@ -42,18 +42,15 @@ export class SetupService { private async checkInstallationPath(): Promise { try { - const exists = await lastValueFrom(this.ipcService.sendV2("bs-installer.folder-exists")) + const exists = await lastValueFrom(this.ipcService.sendV2("bs-installer.folder-exists")); if (exists) { return; } - let modalResponse: ModalResponse<{ installPath: string }> = { exitCode: ModalExitCode.NO_CHOICE }; - while (modalResponse.exitCode !== ModalExitCode.COMPLETED) { - modalResponse = await this.modalService.openModal( - AskInstallPathModal, - { closable: false } - ); - } + const modalResponse = await this.modalService.openModal( + AskInstallPathModal, + { closable: false } + ); await lastValueFrom(this.steamDownloaderService.setInstallationFolder(modalResponse.data.installPath)); diff --git a/src/shared/models/ipc/ipc-routes.ts b/src/shared/models/ipc/ipc-routes.ts index 63a128bb..b7871cdd 100644 --- a/src/shared/models/ipc/ipc-routes.ts +++ b/src/shared/models/ipc/ipc-routes.ts @@ -43,7 +43,7 @@ export interface IpcChannelMapping { "bsv-get-playlist-details-by-id": {request: {id: string, page: number}, response: BsvPlaylistPage}; /* ** bs-installer-ipcs ** */ - "bs-installer.folder-exists": { require: void, response: boolean }; + "bs-installer.folder-exists": { request: void, response: boolean }; "bs-installer.default-install-path": { request: void, response: string }; "bs-installer.install-path": { request: void, response: string}; "bs-installer.set-install-path": { request: string, response: string}; From 9734d714d7356eead3c34a1a16153dfb657ac7e2 Mon Sep 17 00:00:00 2001 From: silentrald Date: Wed, 28 Aug 2024 19:24:56 +0800 Subject: [PATCH 5/8] [refactor] created installation-location.service.ts on client side --- .../pages/settings-page.component.tsx | 6 ++-- .../steam-downloader.service.ts | 10 ------- .../services/installation-location.service.ts | 29 +++++++++++++++++++ src/renderer/services/setup.service.ts | 8 ++--- 4 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 src/renderer/services/installation-location.service.ts diff --git a/src/renderer/pages/settings-page.component.tsx b/src/renderer/pages/settings-page.component.tsx index ea059fa7..1cea476e 100644 --- a/src/renderer/pages/settings-page.component.tsx +++ b/src/renderer/pages/settings-page.component.tsx @@ -48,6 +48,7 @@ import { SettingToogleSwitchGrid } from "renderer/components/settings/setting-to import { BasicModal } from "renderer/components/modal/basic-modal.component"; import { StaticConfigurationService } from "renderer/services/static-configuration.service"; import { tryit } from "shared/helpers/error.helpers"; +import { InstallationLocationService } from "renderer/services/installation-location.service"; export function SettingsPage() { @@ -68,6 +69,7 @@ export function SettingsPage() { const versionLinker = useService(VersionFolderLinkerService); const autoUpdater = useService(AutoUpdaterService); const staticConfig = useService(StaticConfigurationService); + const installationLocationService = useService(InstallationLocationService); const { firstColor, secondColor } = useThemeColor(); @@ -124,7 +126,7 @@ export function SettingsPage() { }; const loadInstallationFolder = () => { - steamDownloader.getInstallationFolder().then(res => { + installationLocationService.getInstallationFolder().then(res => { setInstallationFolder(res); }); }; @@ -202,7 +204,7 @@ export function SettingsPage() { notificationService.notifySuccess({ title: "notifications.settings.move-folder.success.titles.transfer-started", desc: "notifications.settings.move-folder.success.descs.transfer-started" }); - lastValueFrom(steamDownloader.setInstallationFolder(fileChooserRes.filePaths[0])).then(res => { + lastValueFrom(installationLocationService.setInstallationFolder(fileChooserRes.filePaths[0])).then(res => { progressBarService.complete(); progressBarService.hide(true); diff --git a/src/renderer/services/bs-version-download/steam-downloader.service.ts b/src/renderer/services/bs-version-download/steam-downloader.service.ts index 7e10de70..313a1e4a 100644 --- a/src/renderer/services/bs-version-download/steam-downloader.service.ts +++ b/src/renderer/services/bs-version-download/steam-downloader.service.ts @@ -47,16 +47,6 @@ export class SteamDownloaderService extends AbstractBsDownloaderService implemen public deleteSteamSession(): void { localStorage.removeItem(this.STEAM_SESSION_USERNAME_KEY); } public sessionExist(): boolean { return !!localStorage.getItem(this.STEAM_SESSION_USERNAME_KEY); } - // TODO: Move to another service in the future - public async getInstallationFolder(): Promise { - return lastValueFrom(this.ipcService.sendV2("bs-installer.install-path")); - } - - // TODO: Move to another service in the future - public setInstallationFolder(path: string): Observable { - return this.ipcService.sendV2("bs-installer.set-install-path", path); - } - // ### Downloading private handleInfoEvents(events$: Observable): Subscription[] { diff --git a/src/renderer/services/installation-location.service.ts b/src/renderer/services/installation-location.service.ts new file mode 100644 index 00000000..db1d01ad --- /dev/null +++ b/src/renderer/services/installation-location.service.ts @@ -0,0 +1,29 @@ +import { Observable, lastValueFrom } from "rxjs"; +import { IpcService } from "./ipc.service"; + + +export class InstallationLocationService { + + private static instance: InstallationLocationService; + + private readonly ipcService: IpcService; + + public static getInstance(): InstallationLocationService { + if (!InstallationLocationService.instance) { + InstallationLocationService.instance = new InstallationLocationService(); + } + return InstallationLocationService.instance; + } + + private constructor() { + this.ipcService = IpcService.getInstance(); + } + + public async getInstallationFolder(): Promise { + return lastValueFrom(this.ipcService.sendV2("bs-installer.install-path")); + } + + public setInstallationFolder(path: string): Observable { + return this.ipcService.sendV2("bs-installer.set-install-path", path); + } +} diff --git a/src/renderer/services/setup.service.ts b/src/renderer/services/setup.service.ts index e2d105d1..c88f3c97 100644 --- a/src/renderer/services/setup.service.ts +++ b/src/renderer/services/setup.service.ts @@ -2,9 +2,9 @@ import { lastValueFrom } from "rxjs"; import { logRenderError } from "renderer"; import { BSVersionManagerService } from "./bs-version-manager.service"; +import { InstallationLocationService } from "./installation-location.service"; import { IpcService } from "./ipc.service"; import { ModalService } from "./modale.service"; -import { SteamDownloaderService } from "./bs-version-download/steam-downloader.service"; import { AskInstallPathModal } from "renderer/components/modal/modal-types/ask-install-path.component"; @@ -12,15 +12,15 @@ import { AskInstallPathModal } from "renderer/components/modal/modal-types/ask-i export class SetupService { private static instance: SetupService; + private readonly installationLocationService: InstallationLocationService; private readonly ipcService: IpcService; private readonly modalService: ModalService; - private readonly steamDownloaderService: SteamDownloaderService; private readonly versionManagerService: BSVersionManagerService; private constructor() { + this.installationLocationService = InstallationLocationService.getInstance(); this.ipcService = IpcService.getInstance(); this.modalService = ModalService.getInstance(); - this.steamDownloaderService = SteamDownloaderService.getInstance(); this.versionManagerService = BSVersionManagerService.getInstance(); } @@ -52,7 +52,7 @@ export class SetupService { { closable: false } ); - await lastValueFrom(this.steamDownloaderService.setInstallationFolder(modalResponse.data.installPath)); + await lastValueFrom(this.installationLocationService.setInstallationFolder(modalResponse.data.installPath)); // Refresh the versions tab await this.versionManagerService.askInstalledVersions(); From 7ae097b99011b8f017580535a2a4b4d4ea4f76f7 Mon Sep 17 00:00:00 2001 From: MathieuG-P <40181755+Zagrios@users.noreply.github.com> Date: Wed, 4 Sep 2024 20:45:28 +0200 Subject: [PATCH 6/8] [feature-560] some adjustments --- assets/jsons/translations/de.json | 2 +- assets/jsons/translations/en.json | 2 +- assets/jsons/translations/es.json | 2 +- assets/jsons/translations/fr.json | 2 +- assets/jsons/translations/ja.json | 2 +- assets/jsons/translations/ru.json | 2 +- assets/jsons/translations/zh-tw.json | 2 +- assets/jsons/translations/zh.json | 2 +- .../ask-install-path.component.tsx | 21 ++++++++++--------- 9 files changed, 19 insertions(+), 18 deletions(-) diff --git a/assets/jsons/translations/de.json b/assets/jsons/translations/de.json index 32dcf2eb..123c66f3 100644 --- a/assets/jsons/translations/de.json +++ b/assets/jsons/translations/de.json @@ -771,7 +771,7 @@ }, "ask-install-path": { "title": "Installations Ordner", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", "choose-folder": "Ordner Wählen", "default": "Default", "default-tooltip": "Defaults to your home folder" diff --git a/assets/jsons/translations/en.json b/assets/jsons/translations/en.json index 02eda720..b4dd5445 100644 --- a/assets/jsons/translations/en.json +++ b/assets/jsons/translations/en.json @@ -778,7 +778,7 @@ }, "ask-install-path": { "title": "Installation folder", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", "choose-folder": "Choose folder", "default": "Default", "default-tooltip": "Defaults to your home folder" diff --git a/assets/jsons/translations/es.json b/assets/jsons/translations/es.json index 7f05e99c..f3e46eaa 100644 --- a/assets/jsons/translations/es.json +++ b/assets/jsons/translations/es.json @@ -771,7 +771,7 @@ }, "ask-install-path": { "title": "Carpeta de instalación", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", "choose-folder": "Elige la carpeta", "default": "Default", "default-tooltip": "Defaults to your home folder" diff --git a/assets/jsons/translations/fr.json b/assets/jsons/translations/fr.json index d5389053..0db23bb8 100644 --- a/assets/jsons/translations/fr.json +++ b/assets/jsons/translations/fr.json @@ -772,7 +772,7 @@ }, "ask-install-path": { "title": "Dossier d'installation", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", "choose-folder": "Choisir un dossier", "default": "Default", "default-tooltip": "Defaults to your home folder" diff --git a/assets/jsons/translations/ja.json b/assets/jsons/translations/ja.json index 09d4c926..06f8541d 100644 --- a/assets/jsons/translations/ja.json +++ b/assets/jsons/translations/ja.json @@ -771,7 +771,7 @@ }, "ask-install-path": { "title": "インストールフォルダー", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", "choose-folder": "フォルダーを選択", "default": "Default", "default-tooltip": "Defaults to your home folder" diff --git a/assets/jsons/translations/ru.json b/assets/jsons/translations/ru.json index e51abe3d..d39cfb3d 100644 --- a/assets/jsons/translations/ru.json +++ b/assets/jsons/translations/ru.json @@ -770,7 +770,7 @@ }, "ask-install-path": { "title": "Папка установок", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", "choose-folder": "Изменить папку", "default": "Default", "default-tooltip": "Defaults to your home folder" diff --git a/assets/jsons/translations/zh-tw.json b/assets/jsons/translations/zh-tw.json index cf1abe80..472e5e4a 100644 --- a/assets/jsons/translations/zh-tw.json +++ b/assets/jsons/translations/zh-tw.json @@ -771,7 +771,7 @@ }, "ask-install-path": { "title": "安裝文件夾", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", "choose-folder": "選擇文件夾", "default": "Default", "default-tooltip": "Defaults to your home folder" diff --git a/assets/jsons/translations/zh.json b/assets/jsons/translations/zh.json index c881232d..50b1e626 100644 --- a/assets/jsons/translations/zh.json +++ b/assets/jsons/translations/zh.json @@ -771,7 +771,7 @@ }, "ask-install-path": { "title": "安装文件夹", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager.", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", "choose-folder": "选择文件夹", "default": "Default", "default-tooltip": "Defaults to your home folder" diff --git a/src/renderer/components/modal/modal-types/ask-install-path.component.tsx b/src/renderer/components/modal/modal-types/ask-install-path.component.tsx index 828c49b9..4df0691d 100644 --- a/src/renderer/components/modal/modal-types/ask-install-path.component.tsx +++ b/src/renderer/components/modal/modal-types/ask-install-path.component.tsx @@ -54,42 +54,43 @@ export const AskInstallPathModal: ModalComponent<{ installPath: string }, {}> = return (
{ event.preventDefault(); onConfirmButtonPressed(); }}> -

+

{t("modals.ask-install-path.title")}

-

+

{t("modals.ask-install-path.choose-folder-description")}

-
- + +
+ {installPath}
-
+
= Date: Thu, 5 Sep 2024 09:37:32 +0800 Subject: [PATCH 7/8] [bugfix-560] don't move old installation path if it doesn't exist --- src/main/ipcs/bs-installer-ipcs.ts | 2 +- .../services/installation-location.service.ts | 16 ++++++++++------ src/renderer/pages/settings-page.component.tsx | 2 +- .../services/installation-location.service.ts | 10 ++++++++-- src/renderer/services/setup.service.ts | 2 +- src/shared/models/ipc/ipc-routes.ts | 2 +- 6 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/main/ipcs/bs-installer-ipcs.ts b/src/main/ipcs/bs-installer-ipcs.ts index 25672b13..893b697e 100644 --- a/src/main/ipcs/bs-installer-ipcs.ts +++ b/src/main/ipcs/bs-installer-ipcs.ts @@ -23,5 +23,5 @@ ipc.on("bs-installer.install-path", (_, reply) => { ipc.on("bs-installer.set-install-path", (args, reply) => { const service = InstallationLocationService.getInstance(); - reply(from(service.setInstallationDirectory(args))); + reply(from(service.setInstallationDirectory(args.path, args.move))); }); diff --git a/src/main/services/installation-location.service.ts b/src/main/services/installation-location.service.ts index 1696ea0d..6acb0ace 100644 --- a/src/main/services/installation-location.service.ts +++ b/src/main/services/installation-location.service.ts @@ -40,18 +40,22 @@ export class InstallationLocationService { this.updateListeners.forEach(listener => listener()); } - public async setInstallationDirectory(newDir: string): Promise { + /** + * @param move - if true, move the old installation path to the path param + */ + public async setInstallationDirectory(newDir: string, move: boolean): Promise { newDir = path.basename(newDir) === this.INSTALLATION_FOLDER ? path.join(newDir, "..") : newDir; - const oldDir = this.installationDirectory(); - await ensureFolderExist(oldDir); - await copyDirectoryWithJunctions(oldDir, path.join(newDir, this.INSTALLATION_FOLDER), { overwrite: true }); + if (move) { + const oldDir = this.installationDirectory(); + await ensureFolderExist(oldDir); + await copyDirectoryWithJunctions(oldDir, path.join(newDir, this.INSTALLATION_FOLDER), { overwrite: true }); + deleteFolder(oldDir); + } this._installationDirectory = newDir; this.staticConfig.set(this.STORE_INSTALLATION_PATH_KEY, newDir); - deleteFolder(oldDir); - return this.installationDirectory(); } diff --git a/src/renderer/pages/settings-page.component.tsx b/src/renderer/pages/settings-page.component.tsx index 1cea476e..f7a1fd1b 100644 --- a/src/renderer/pages/settings-page.component.tsx +++ b/src/renderer/pages/settings-page.component.tsx @@ -204,7 +204,7 @@ export function SettingsPage() { notificationService.notifySuccess({ title: "notifications.settings.move-folder.success.titles.transfer-started", desc: "notifications.settings.move-folder.success.descs.transfer-started" }); - lastValueFrom(installationLocationService.setInstallationFolder(fileChooserRes.filePaths[0])).then(res => { + lastValueFrom(installationLocationService.setInstallationFolder(fileChooserRes.filePaths[0], true)).then(res => { progressBarService.complete(); progressBarService.hide(true); diff --git a/src/renderer/services/installation-location.service.ts b/src/renderer/services/installation-location.service.ts index db1d01ad..45445e07 100644 --- a/src/renderer/services/installation-location.service.ts +++ b/src/renderer/services/installation-location.service.ts @@ -23,7 +23,13 @@ export class InstallationLocationService { return lastValueFrom(this.ipcService.sendV2("bs-installer.install-path")); } - public setInstallationFolder(path: string): Observable { - return this.ipcService.sendV2("bs-installer.set-install-path", path); + /** + * @param move - if true, move the old installation path to the path param + */ + public setInstallationFolder(path: string, move: boolean): Observable { + return this.ipcService.sendV2( + "bs-installer.set-install-path", + { path, move } + ); } } diff --git a/src/renderer/services/setup.service.ts b/src/renderer/services/setup.service.ts index c88f3c97..5bb38f18 100644 --- a/src/renderer/services/setup.service.ts +++ b/src/renderer/services/setup.service.ts @@ -52,7 +52,7 @@ export class SetupService { { closable: false } ); - await lastValueFrom(this.installationLocationService.setInstallationFolder(modalResponse.data.installPath)); + await lastValueFrom(this.installationLocationService.setInstallationFolder(modalResponse.data.installPath, false)); // Refresh the versions tab await this.versionManagerService.askInstalledVersions(); diff --git a/src/shared/models/ipc/ipc-routes.ts b/src/shared/models/ipc/ipc-routes.ts index b7871cdd..b145955f 100644 --- a/src/shared/models/ipc/ipc-routes.ts +++ b/src/shared/models/ipc/ipc-routes.ts @@ -46,7 +46,7 @@ export interface IpcChannelMapping { "bs-installer.folder-exists": { request: void, response: boolean }; "bs-installer.default-install-path": { request: void, response: string }; "bs-installer.install-path": { request: void, response: string}; - "bs-installer.set-install-path": { request: string, response: string}; + "bs-installer.set-install-path": { request: { path: string, move: boolean }, response: string}; /* ** bs-launcher-ipcs ** */ "create-launch-shortcut": { request: LaunchOption, response: boolean }; From e14ba2727b0e14538cf7ef90d03c8ba0da0f4bfa Mon Sep 17 00:00:00 2001 From: MathieuG-P <40181755+Zagrios@users.noreply.github.com> Date: Tue, 10 Sep 2024 21:18:46 +0200 Subject: [PATCH 8/8] [feature-560] translations --- assets/jsons/translations/de.json | 10 +++++----- assets/jsons/translations/en.json | 2 +- assets/jsons/translations/es.json | 10 +++++----- assets/jsons/translations/fr.json | 10 +++++----- assets/jsons/translations/ja.json | 10 +++++----- assets/jsons/translations/ru.json | 10 +++++----- assets/jsons/translations/zh-tw.json | 10 +++++----- assets/jsons/translations/zh.json | 10 +++++----- 8 files changed, 36 insertions(+), 36 deletions(-) diff --git a/assets/jsons/translations/de.json b/assets/jsons/translations/de.json index 123c66f3..9c91e605 100644 --- a/assets/jsons/translations/de.json +++ b/assets/jsons/translations/de.json @@ -15,7 +15,7 @@ "apply": "Übernehmen", "copy": "Kopieren", "copied": "Kopiert!", - "confirm": "Confirm" + "confirm": "Bestätigen" }, "nav-bar": { "add-version": "Version hinzufügen", @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "Installations-Ordner", - "description": "Change the folder that will contain all the content downloaded by BSManager.", + "description": "Ändern Sie den Ordner, der alle von BSManager heruntergeladenen Inhalte enthalten wird.", "choose-folder": "Ordner wählen" }, "additional-content": { @@ -771,10 +771,10 @@ }, "ask-install-path": { "title": "Installations Ordner", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", + "choose-folder-description": "Wählen Sie den Ordner aus, der alle von BSManager heruntergeladenen Inhalte enthalten soll. (Versionen, Mods, Karten, Playlists, etc.)", "choose-folder": "Ordner Wählen", - "default": "Default", - "default-tooltip": "Defaults to your home folder" + "default": "Standard", + "default-tooltip": "Standardmäßig in Ihrem persönlichen Ordner" } }, "maps": { diff --git a/assets/jsons/translations/en.json b/assets/jsons/translations/en.json index b4dd5445..fcfdaa82 100644 --- a/assets/jsons/translations/en.json +++ b/assets/jsons/translations/en.json @@ -778,7 +778,7 @@ }, "ask-install-path": { "title": "Installation folder", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", + "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (versions, mods, maps, playlists, etc.)", "choose-folder": "Choose folder", "default": "Default", "default-tooltip": "Defaults to your home folder" diff --git a/assets/jsons/translations/es.json b/assets/jsons/translations/es.json index f3e46eaa..9494b412 100644 --- a/assets/jsons/translations/es.json +++ b/assets/jsons/translations/es.json @@ -15,7 +15,7 @@ "apply": "Aplicar", "copy": "Copiar", "copied": "¡Copiado!", - "confirm": "Confirm" + "confirm": "Confirmar" }, "nav-bar": { "add-version": "Agregar una versión", @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "Carpeta de instalación", - "description": "Change the folder that will contain all the content downloaded by BSManager.", + "description": "Cambiar la carpeta que contendrá todo el contenido descargado por BSManager.", "choose-folder": "Elige la carpeta" }, "additional-content": { @@ -771,10 +771,10 @@ }, "ask-install-path": { "title": "Carpeta de instalación", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", + "choose-folder-description": "Elija la carpeta que contendrá todo el contenido descargado por BSManager. (versiones, mods, mapas, listas de reproducción, etc.)", "choose-folder": "Elige la carpeta", - "default": "Default", - "default-tooltip": "Defaults to your home folder" + "default": "Predeterminado", + "default-tooltip": "Por defecto, en su carpeta personal" } }, "maps": { diff --git a/assets/jsons/translations/fr.json b/assets/jsons/translations/fr.json index 0db23bb8..2a4c5e14 100644 --- a/assets/jsons/translations/fr.json +++ b/assets/jsons/translations/fr.json @@ -15,7 +15,7 @@ "apply": "Appliquer", "copy": "Copier", "copied": "Copié !", - "confirm": "Confirm" + "confirm": "Confirmer" }, "nav-bar": { "add-version": "Ajouter une version", @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "Dossier d'installation", - "description": "Change the folder that will contain all the content downloaded by BSManager.", + "description": "Changer le dossier qui contiendra tout le contenu téléchargé par BSManager.", "choose-folder": "Choisir un dossier" }, "additional-content": { @@ -772,10 +772,10 @@ }, "ask-install-path": { "title": "Dossier d'installation", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", + "choose-folder-description": "Choisissez le dossier qui contiendra tout le contenu téléchargé par BSManager. (versions, mods, cartes, playlists, etc.)", "choose-folder": "Choisir un dossier", - "default": "Default", - "default-tooltip": "Defaults to your home folder" + "default": "Par défaut", + "default-tooltip": "Par défaut, dans votre dossier personnel" } }, "maps": { diff --git a/assets/jsons/translations/ja.json b/assets/jsons/translations/ja.json index 06f8541d..5fb10e10 100644 --- a/assets/jsons/translations/ja.json +++ b/assets/jsons/translations/ja.json @@ -15,7 +15,7 @@ "apply": "適用", "copy": "コピー", "copied": "コピー済み!", - "confirm": "Confirm" + "confirm": "確認" }, "nav-bar": { "add-version": "バージョンを追加", @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "インストールフォルダー", - "description": "Change the folder that will contain all the content downloaded by BSManager.", + "description": "BSManager によってダウンロードされたすべてのコンテンツを含むフォルダを変更します。", "choose-folder": "フォルダーを選択" }, "additional-content": { @@ -771,10 +771,10 @@ }, "ask-install-path": { "title": "インストールフォルダー", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", + "choose-folder-description": "BSManager によってダウンロードされたすべてのコンテンツ (バージョン、MOD、マップ、プレイリストなど) を含むフォルダを選択してください。", "choose-folder": "フォルダーを選択", - "default": "Default", - "default-tooltip": "Defaults to your home folder" + "default": "デフォルト", + "default-tooltip": "デフォルトでは、ホームフォルダに設定されます" } }, "maps": { diff --git a/assets/jsons/translations/ru.json b/assets/jsons/translations/ru.json index d39cfb3d..4442078a 100644 --- a/assets/jsons/translations/ru.json +++ b/assets/jsons/translations/ru.json @@ -15,7 +15,7 @@ "apply": "Применить", "copy": "Скопировать", "copied": "Скопировано!", - "confirm": "Confirm" + "confirm": "Подтвердить" }, "nav-bar": { "add-version": "Добавить версию игры", @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "Папка установок", - "description": "Change the folder that will contain all the content downloaded by BSManager.", + "description": "Изменить папку, которая будет содержать весь контент, загруженный BSManager.", "choose-folder": "Изменить папку" }, "additional-content": { @@ -770,10 +770,10 @@ }, "ask-install-path": { "title": "Папка установок", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", + "choose-folder-description": "Выберите папку, которая будет содержать весь контент, загруженный BSManager. (версии, моды, карты, плейлисты и т.д.)", "choose-folder": "Изменить папку", - "default": "Default", - "default-tooltip": "Defaults to your home folder" + "default": "По умолчанию", + "default-tooltip": "По умолчанию в вашей домашней папке" } }, "maps": { diff --git a/assets/jsons/translations/zh-tw.json b/assets/jsons/translations/zh-tw.json index 472e5e4a..ce36d636 100644 --- a/assets/jsons/translations/zh-tw.json +++ b/assets/jsons/translations/zh-tw.json @@ -15,7 +15,7 @@ "apply": "應用", "copy": "複製", "copied": "已複製!", - "confirm": "Confirm" + "confirm": "確認" }, "nav-bar": { "add-version": "新增版本", @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "安裝文件夾", - "description": "Change the folder that will contain all the content downloaded by BSManager.", + "description": "更改將包含 BSManager 下載的所有內容的文件夾。", "choose-folder": "選擇文件夾" }, "additional-content": { @@ -771,10 +771,10 @@ }, "ask-install-path": { "title": "安裝文件夾", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", + "choose-folder-description": "選擇將包含 BSManager 下載的所有內容的文件夾。(版本、mod、地圖、播放列表等)", "choose-folder": "選擇文件夾", - "default": "Default", - "default-tooltip": "Defaults to your home folder" + "default": "預設", + "default-tooltip": "預設為您的主資料夾" } }, "maps": { diff --git a/assets/jsons/translations/zh.json b/assets/jsons/translations/zh.json index 50b1e626..8be7a687 100644 --- a/assets/jsons/translations/zh.json +++ b/assets/jsons/translations/zh.json @@ -15,7 +15,7 @@ "apply": "应用", "copy": "复制", "copied": "已复制!", - "confirm": "Confirm" + "confirm": "确认" }, "nav-bar": { "add-version": "添加版本", @@ -139,7 +139,7 @@ }, "installation-folder": { "title": "安装文件夹", - "description": "Change the folder that will contain all the content downloaded by BSManager.", + "description": "更改将包含 BSManager 下载的所有内容的文件夹。", "choose-folder": "选择文件夹" }, "additional-content": { @@ -771,10 +771,10 @@ }, "ask-install-path": { "title": "安装文件夹", - "choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (e.g. versions, mods, maps, playlists, etc.)", + "choose-folder-description": "选择将包含 BSManager 下载的所有内容的文件夹。(版本、mod、地图、播放列表等)", "choose-folder": "选择文件夹", - "default": "Default", - "default-tooltip": "Defaults to your home folder" + "default": "默认", + "default-tooltip": "默认为您的主文件夹" } }, "maps": {