[chore] fix some sonarcloud code smells

This commit is contained in:
MathieuG-P
2023-07-01 16:48:30 +02:00
parent 8a99c412fd
commit 7e261fcb93
23 changed files with 88 additions and 100 deletions
+4 -5
View File
@@ -1,22 +1,21 @@
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';
import { IpcChannel } from 'shared/models/ipc/ipc-response.interface';
contextBridge.exposeInMainWorld('electron', {
ipcRenderer: {
sendMessage(channel: IpcChannel, args: unknown[]) {
sendMessage(channel: string, args: unknown[]) {
ipcRenderer.send(channel, args);
},
on(channel: IpcChannel, func: (...args: unknown[]) => void) {
on(channel: string, func: (...args: unknown[]) => void) {
const subscription = (_event: IpcRendererEvent, ...args: unknown[]) =>
func(...args);
ipcRenderer.on(channel, subscription);
return () => ipcRenderer.removeListener(channel, subscription);
},
once(channel: IpcChannel, func: (...args: unknown[]) => void) {
once(channel: string, func: (...args: unknown[]) => void) {
ipcRenderer.once(channel, (_event, ...args) => func(...args));
},
removeAllListeners(channel: IpcChannel) {
removeAllListeners(channel: string) {
ipcRenderer.removeAllListeners(channel);
}
},
+31 -37
View File
@@ -1,4 +1,3 @@
/* eslint-disable prefer-promise-reject-errors */
import { BS_APP_ID, BS_DEPOT } from "../constants";
import path from "path";
import { BSVersion, PartialBSVersion } from 'shared/bs-version.interface';
@@ -10,57 +9,52 @@ 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";
import { clean, satisfies } from "semver";
import { copy } from "fs-extra";
import { ensureFolderExist, pathExist } from "../helpers/fs.helpers";
export class BSInstallerService{
private static instance: BSInstallerService;
private static instance: BSInstallerService;
private readonly utils: UtilsService;
private readonly installLocationService: InstallationLocationService;
private readonly localVersionService: BSLocalVersionService;
private readonly windows: WindowManagerService;
private readonly utils: UtilsService;
private readonly installLocationService: InstallationLocationService;
private readonly localVersionService: BSLocalVersionService;
private readonly windows: WindowManagerService;
private downloadProcess: ChildProcessWithoutNullStreams;
private downloadProcess: ChildProcessWithoutNullStreams;
private constructor(){
this.utils = UtilsService.getInstance();
this.installLocationService = InstallationLocationService.getInstance();
this.localVersionService = BSLocalVersionService.getInstance();
this.windows = WindowManagerService.getInstance();
private constructor(){
this.utils = UtilsService.getInstance();
this.installLocationService = InstallationLocationService.getInstance();
this.localVersionService = BSLocalVersionService.getInstance();
this.windows = WindowManagerService.getInstance();
this.windows.getWindow("index.html")?.on("close", () => {
this.killDownloadProcess();
});
}
this.windows.getWindow("index.html")?.on("close", () => {
this.killDownloadProcess();
});
}
public static getInstance(){
if(!BSInstallerService.instance){ BSInstallerService.instance = new BSInstallerService(); }
return BSInstallerService.instance;
}
private escapeSpaces(path: string): string{
return `\"${path}\"`
public static getInstance(){
if(!BSInstallerService.instance){ BSInstallerService.instance = new BSInstallerService(); }
return BSInstallerService.instance;
}
private getDepotDownloaderExePath(): string{
return this.escapeSpaces(path.join(this.utils.getAssetsScriptsPath(), 'depot-downloader', 'DepotDownloader.exe'));
return path.join(this.utils.getAssetsScriptsPath(), 'depot-downloader', 'DepotDownloader.exe');
}
private removeSpecialSchar(txt: string): string{ return txt.replaceAll(/\[|\]/g, ""); }
private removeSpecialSchar(txt: string): string{ return txt.replaceAll(/[\[\]]/g, ""); }
private sendDownloadEvent(event: DownloadEventType, data?: string|number, success = true): void{
if(typeof data === "string"){ data = this.removeSpecialSchar(data); }
this.utils.ipcSend(`bs-download.${event}`, { success, data });
}
public sendInputProcess(input: string){
if(this.downloadProcess.stdin.writable){
this.downloadProcess.stdin.write(`${input}\n`);
public sendInputProcess(input: string){
if(this.downloadProcess.stdin.writable){
this.downloadProcess.stdin.write(`${input}\n`);
}
}
}
public killDownloadProcess(): Promise<boolean>{
return new Promise(resolve => {
@@ -78,7 +72,7 @@ export class BSInstallerService{
public async isDotNet6Installed(): Promise<boolean>{
try{
const process = spawnSync(this.getDepotDownloaderExePath(), {shell: true});
const process = spawnSync(`"${this.getDepotDownloaderExePath()}"`, {shell: true});
if(process.stderr.toString()){
log.error("no dotnet", process.stderr.toString());
return false;
@@ -93,9 +87,9 @@ export class BSInstallerService{
public async downloadBsVersion(downloadInfos: DownloadInfo): Promise<DownloadEvent>{
// TODO : Can be a lot improved by using ipcV2 and Observable
// TODO : Can be a lot improved by using ipcV2 and Observable -- This will be reworked for qrCode login
if(this.downloadProcess && this.downloadProcess.connected){ throw "AlreadyDownloading"; }
if(this.downloadProcess?.connected){ throw "AlreadyDownloading"; }
const {bsVersion} = downloadInfos;
if(!bsVersion){ return {type: "[Error]"}; }
if(!(await isOnline({timeout: 1500}))){ throw "no-internet"; }
@@ -109,13 +103,13 @@ export class BSInstallerService{
const downloadVersion: BSVersion = {...downloadInfos.bsVersion, ...(path.basename(dest) !== downloadInfos.bsVersion.BSVersion && {name: path.basename(dest)})}
this.downloadProcess = spawn(
this.getDepotDownloaderExePath(),
`"${this.getDepotDownloaderExePath()}"`,
[
`-app ${BS_APP_ID}`,
`-depot ${BS_DEPOT}`,
`-manifest ${bsVersion.BSManifest}`,
`-username \"${downloadInfos.username}\"`,
`-dir \"${this.localVersionService.getVersionFolder(downloadVersion)}\"`
`-username "${downloadInfos.username}"`,
`-dir "${this.localVersionService.getVersionFolder(downloadVersion)}"`
],
{shell: true, cwd: this.installLocationService.versionsDirectory}
);
+2 -2
View File
@@ -106,10 +106,10 @@ export class BSLauncherService{
}
if(launchOptions.debug){
this.bsProcess = spawn(`\"${exePath}\"`, launchArgs, {shell: true, cwd, env: {...process.env, "SteamAppId": BS_APP_ID}, detached: true, windowsVerbatimArguments: true });
this.bsProcess = spawn(`"${exePath}"`, launchArgs, {shell: true, cwd, env: {...process.env, "SteamAppId": BS_APP_ID}, detached: true, windowsVerbatimArguments: true });
}
else{
this.bsProcess = spawn(`\"${exePath}\"`, launchArgs, {shell: true, cwd, env: {...process.env, "SteamAppId": BS_APP_ID} });
this.bsProcess = spawn(`"${exePath}"`, launchArgs, {shell: true, cwd, env: {...process.env, "SteamAppId": BS_APP_ID} });
}
this.bsProcess.on('error', err => log.error(err));
+6 -6
View File
@@ -52,16 +52,16 @@ export class BSVersionLibService{
], {keepStructure: true});
let resVersions = localVersions;
if(remoteVersions && remoteVersions.length){ resVersions = remoteVersions; this.updateLocalVersions(resVersions); }
if(remoteVersions?.length){ resVersions = remoteVersions; this.updateLocalVersions(resVersions); }
this.bsVersions = resVersions;
return this.bsVersions;
}
public async getAvailableVersions(): Promise<BSVersion[]>{
const bsVersions = await this.loadBsVersions();
if(!bsVersions || !bsVersions.length){ return []; }
return bsVersions;
}
public async getAvailableVersions(): Promise<BSVersion[]>{
const bsVersions = await this.loadBsVersions();
if(!bsVersions?.length){ return []; }
return bsVersions;
}
public async getVersionDetails(version: string): Promise<BSVersion>{
const versions = await this.getAvailableVersions();
+11 -9
View File
@@ -1,7 +1,7 @@
import { IpcRequest } from "shared/models/ipc";
import { ipcMain } from "electron";
import { Observable } from "rxjs";
import { IpcChannel, IpcCompleteChannel, IpcErrorChannel } from "shared/models/ipc/ipc-response.interface";
import { IpcCompleteChannel, IpcErrorChannel } from "shared/models/ipc/ipc-response.interface";
import { AppWindow } from "shared/models/window-manager/app-window.model";
import { WindowManagerService } from "./window-manager.service";
import { IpcReplier } from "shared/models/ipc/ipc-request.interface";
@@ -22,15 +22,15 @@ export class IpcService {
this.windows = WindowManagerService.getInstance();
}
private getErrorChannel(channel: IpcChannel): IpcErrorChannel {
private getErrorChannel(channel: string): IpcErrorChannel {
return `${channel}_error`;
}
private getCompleteChannel(channel: IpcChannel): IpcCompleteChannel {
private getCompleteChannel(channel: string): IpcCompleteChannel {
return `${channel}_complete`;
}
private buildProxyListener<T>(listener: (req: IpcRequest<T>, replier: IpcReplier) => void) {
private buildProxyListener<T>(listener: IpcListener<T>) {
return (event: Electron.IpcMainEvent, req: IpcRequest<T>) => {
const window = this.windows.getAppWindowFromWebContents(event.sender);
@@ -40,11 +40,11 @@ export class IpcService {
}
public send<T>(channel: IpcChannel, window: AppWindow, response?: T|Error): void{
public send<T>(channel: string, window: AppWindow, response?: T|Error): void{
this.windows.getWindow(window)?.webContents?.send(channel, response);
}
private connectStream(channel: IpcChannel, window: AppWindow, observable: Observable<unknown>): void{
private connectStream(channel: string, window: AppWindow, observable: Observable<unknown>): void{
observable.subscribe(data => {
this.send(channel, window, data);
}, error => {
@@ -55,12 +55,14 @@ export class IpcService {
});
}
public on<T>(channel: IpcChannel, listener: (req: IpcRequest<T>, replier: IpcReplier) => void): void{
public on<T>(channel: string, listener: IpcListener<T>): void{
ipcMain.on(channel, this.buildProxyListener(listener));
}
public once<T>(channel: IpcChannel, listener: (req: IpcRequest<T>, replier: IpcReplier) => void): void{
public once<T>(channel: string, listener: IpcListener<T>): void{
ipcMain.once(channel, this.buildProxyListener(listener));
}
}
}
type IpcListener<T = unknown> = (req: IpcRequest<T>, replier: IpcReplier) => void|Promise<void>;
@@ -269,7 +269,7 @@ export class BsModsManagerService {
}
public async installMods(mods: Mod[], version: BSVersion): Promise<InstallModsResult>{
if(!mods || !mods.length){ throw "no-mods"; }
if(!mods?.length){ throw "no-mods"; }
const deps = await this.resolveDependencies(mods, version);
mods.push(...deps);
@@ -296,7 +296,7 @@ export class BsModsManagerService {
}
public async uninstallMods(mods: Mod[], version: BSVersion): Promise<UninstallModsResult>{
if(!mods || !mods.length){ throw "no-mods"; }
if(!mods?.length){ throw "no-mods"; }
this.nbModsToUninstall = mods.length;
this.nbUninstalledMods = 0;
@@ -314,7 +314,7 @@ export class BsModsManagerService {
public async uninstallAllMods(version: BSVersion): Promise<UninstallModsResult>{
const mods = await this.getInstalledMods(version);
if(!mods || !mods.length){ throw "no-mods"; }
if(!mods?.length){ throw "no-mods"; }
this.nbModsToUninstall = mods.length;
this.nbUninstalledMods = 0;
@@ -329,8 +329,6 @@ export class BsModsManagerService {
await deleteFolder(path.join(versionPath, ModsInstallFolder.LIBS));
await deleteFolder(path.join(versionPath, ModsInstallFolder.IPA));
path.resolve
return {
nbModsToUninstall: this.nbModsToUninstall,
nbUninstalledMods: this.nbUninstalledMods
@@ -92,9 +92,9 @@ export class ModelSaberService {
const res = await this.modelSaberApi.searchModel(query);
if(res.status !== 200){ observer.error(res.status); }
observer.next(Object.values(res.data).map(model => {
if(!model || !model.name){ return model; }
(model as MSModel).name = striptags(model.name);
(model as MSModel).author = striptags(model.author);
if(!model?.name){ return null; }
model.name = striptags(model.name);
model.author = striptags(model.author);
return model;
}));
})().catch(e => observer.error(e)).then(() => observer.complete());
@@ -67,7 +67,7 @@ export const MapsRow = memo(({maps, style, selectedMaps$, onMapSelect, onMapDele
return (
<ul className="h-fit w-full flex flex-nowrap basis-0 gap-x-[8px] py-1 px-3" style={style}>
{maps && maps.map(renderMapItem)}
{maps?.map(renderMapItem)}
</ul>
)
}, equal);
@@ -17,7 +17,7 @@ export const WhyCredentialsModal: ModalComponent<void> = () => {
<p>{t("modals.steam-credentials.p-1")}</p>
{ /* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<a onClick={e => {e.preventDefault; openTutorial()}} className="underline text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-600 mb-2 block cursor-pointer">
<a onClick={e => {e.preventDefault(); openTutorial()}} className="underline text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-600 mb-2 block cursor-pointer">
https://steamcommunity.com/sharedfiles/filedetails/?id=1805934840
</a>
<p>{t("modals.steam-credentials.p-2")}</p>
@@ -138,7 +138,7 @@ function ModelItemElement<T = unknown>(props: Props<T>) {
<span className="mt-0.5 cursor-copy block w-full max-w-fit overflow-hidden whitespace-nowrap text-ellipsis bg-main-color-1 rounded-md p-1 uppercase text-xs" onClick={() => copyContent(`${props.hash}`, 'hash')}>{props.hash}</span>
</Tippy>
<div className="flex gap-1">
{props.id && (
{!!props.id && (
<Tippy placement="top" content={idContentCopied === "id" ? t("misc.copied") : t("misc.copy")} followCursor="horizontal" plugins={[followCursor]} hideOnClick={false}>
<span className="cursor-copy w-fit shrink-0 max-w-full overflow-hidden whitespace-nowrap text-ellipsis bg-main-color-1 rounded-md p-1 uppercase text-xs" onClick={() => copyContent(`${props.id}`, 'id')}>{props.id}</span>
</Tippy>
@@ -68,7 +68,7 @@ export const ModelsGrid = forwardRef(({className, version, type, search, active,
useOnUpdate(() => {
if(!active){ return; }
if(models && models.length){ return; }
if(models?.length){ return; }
loadModels();
}, [active]);
@@ -28,7 +28,7 @@ export function NavBar() {
<ol id='versions' className='w-fit max-w-[120px] relative left-[2px] grow overflow-y-hidden scrollbar-track-transparent scrollbar-thin scrollbar-thumb-rounded-full scrollbar-thumb-neutral-900 hover:overflow-y-scroll'>
<SharedNavBarItem/>
<NavBarSpliter/>
{installedVersions && installedVersions.map((version) => <BsVersionItem key={JSON.stringify(version)} version={version}/>)}
{installedVersions?.map((version) => <BsVersionItem key={JSON.stringify(version)} version={version}/>)}
</ol>
<NavBarSpliter/>
<div className='w-full pb-2 flex flex-col items-center content-center justify-start gap-1'>
@@ -15,7 +15,7 @@ export function BsmCheckbox({className, checked, onChange, disabled} : Props) {
const handleClick = () => {
if(disabled){ return; }
onChange && onChange(!checked);
onChange?.(!checked);
}
return (
@@ -56,7 +56,7 @@ export function BsmRange({colorType = "first-color", values, onChange, onFinalCh
color: labelTextColor,
}}
>
{renderLabel && renderLabel(values[index])}
{renderLabel?.(values[index])}
</div>
)}
/>
@@ -19,7 +19,7 @@ export function BsmSelect<T = unknown>(props: Props<T>) {
return (
<select {...props} onChange={handleChange} defaultValue={props.options?.findIndex(opt => equal(opt.value, props.selected))}>
{props.options && props.options.map((option, index) => (
{props.options?.map((option, index) => (
<option key={JSON.stringify(option)} value={index}>{t(option.text)}</option>
))}
</select>
@@ -20,7 +20,7 @@ export function ModsGrid({modsMap, installed, modsSelected, onModChange, moreInf
const t = useTranslation();
const installedModVersion = (key: string, mod: Mod): string => {
if(!installed || !installed.get(key)){ return undefined; }
if(!installed?.get(key)){ return undefined; }
const installedMod = installed.get(key).find(m => m.name === mod.name);
if(!installedMod){ return undefined }
return installedMod.version
@@ -62,7 +62,7 @@ export function ModsSlide({version, onDisclamerDecline}: {version: BSVersion, on
}
const handleOpenMoreInfo = () => {
if(!moreInfoMod || !moreInfoMod.link){ return; }
if(!moreInfoMod?.link){ return; }
linkOpener.open(moreInfoMod.link);
}
+4 -6
View File
@@ -1,16 +1,14 @@
import { IpcChannel } from "shared/models/ipc/ipc-response.interface";
declare global {
interface Window {
electron: {
ipcRenderer: {
sendMessage(channel: IpcChannel, args: any): void;
sendMessage(channel: string, args: any): void;
on(
channel: IpcChannel,
channel: string,
func: (...args: any) => void
): (() => void) | undefined;
once(channel: IpcChannel, func: (...args: any) => void): void;
removeAllListeners(channel: IpcChannel): void;
once(channel: string, func: (...args: any) => void): void;
removeAllListeners(channel: string): void;
};
};
}
@@ -32,7 +32,7 @@ export class BSVersionManagerService {
}
public setInstalledVersions(versions: BSVersion[]){
const sorted: BSVersion[] = versions.sort((a, b) => +b.ReleaseDate - +a.ReleaseDate)
const sorted: BSVersion[] = [...versions].sort((a, b) => +b.ReleaseDate - +a.ReleaseDate)
const steamIndex = sorted.findIndex(v => v.steam);
const oculusIndex = sorted.findIndex(v => v.oculus);
if(steamIndex > 0){
+9 -9
View File
@@ -51,15 +51,15 @@ export class I18nService {
this.configService.set("language" as DefaultConfigKey, this.getSupportedLanguages().includes(lang) ? lang : this.LANG_FALLBACK);
}
public translate(translationKey: string, args?: Record<string, string>): string{
let translated = this.cache.get(translationKey);
if(!translated){
translated = getProperty(this.dictionary, translationKey);
translated ? this.cache.set(translated, translationKey) : translated = translationKey;
}
args && Object.keys(args).forEach(key => {translated = translated.replaceAll(`{${key}}`, args[key])});
return translated;
}
public translate(translationKey: string, args?: Record<string, string>): string{
let translated = this.cache.get(translationKey);
if(!translated){
translated = getProperty(this.dictionary, translationKey) ?? translationKey;
this.cache.set(translationKey, translated);
}
args && Object.keys(args).forEach(key => {translated = translated.replaceAll(`{${key}}`, args[key])});
return translated;
}
@@ -48,7 +48,7 @@ export class ProgressBarService{
public unsubscribe(){
this._progression$.next({progression: 0});
this.subscription && this.subscription.unsubscribe();
this.subscription?.unsubscribe();
this.subscription = null;
}
@@ -6,6 +6,5 @@ export interface IpcResponse<T>{
success: boolean,
}
export type IpcChannel = string;
export type IpcErrorChannel = IpcChannel & `${string}_error`;
export type IpcCompleteChannel = IpcChannel & `${string}_complete`;
export type IpcErrorChannel = string & `${string}_error`;
export type IpcCompleteChannel = string & `${string}_complete`;
@@ -12,13 +12,11 @@ export interface MSModel {
discord?: string,
variationid?: number,
platform: MSModelPlatform,
download: ModelDownloadURL,
download: string,
install_link: string,
date: string
}
export type ModelDownloadURL = string;
export enum MSModelType {
Avatar = "avatar",
Saber = "saber",