mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
Merge pull request #255 from Zagrios/feature/start-steam-if-not-running-and-bs-automatically-after
[feature] Steam now launch automatically if it not running then BS launch just after
This commit is contained in:
@@ -362,7 +362,7 @@
|
||||
"steam":{
|
||||
"steam-launching":{
|
||||
"title": "Steam startet!",
|
||||
"description": "Abhängig von deiner Konfiguration kann es einige Zeit dauern, bis Steam gestartet wird."
|
||||
"description": "Beat Saber wird automatisch nach Steam gestartet."
|
||||
}
|
||||
},
|
||||
"custom-version": {
|
||||
|
||||
@@ -362,7 +362,7 @@
|
||||
"steam":{
|
||||
"steam-launching":{
|
||||
"title": "Steam is launching!",
|
||||
"description": "Steam may take some time to launch depending on your configuration."
|
||||
"description": "Beat Saber will automatically launch after Steam."
|
||||
}
|
||||
},
|
||||
"custom-version": {
|
||||
|
||||
@@ -361,7 +361,7 @@
|
||||
"steam":{
|
||||
"steam-launching":{
|
||||
"title": "¡Steam se está iniciando!",
|
||||
"description": "Steam puede tardar un poco en iniciarse dependiendo de tu configuración."
|
||||
"description": "Beat Saber se lanzará automáticamente después de Steam."
|
||||
}
|
||||
},
|
||||
"custom-version": {
|
||||
|
||||
@@ -361,7 +361,7 @@
|
||||
"steam":{
|
||||
"steam-launching":{
|
||||
"title": "Steam se lance !",
|
||||
"description": "Steam peut mettre quelque temps à se lancer selon votre configuration."
|
||||
"description": "Beat Saber se lancera automatiquement après Steam."
|
||||
}
|
||||
},
|
||||
"custom-version": {
|
||||
|
||||
@@ -21,7 +21,6 @@ import { LocalModelsManagerService } from './services/additional-content/local-m
|
||||
import { APP_NAME } from './constants';
|
||||
import { BSLauncherService } from './services/bs-launcher.service';
|
||||
import { IpcRequest } from 'shared/models/ipc';
|
||||
import { MSModelType } from '../shared/models/models/model-saber.model';
|
||||
|
||||
const isDebug = process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true';
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ import { pathExist } from "../helpers/fs.helpers";
|
||||
import { rename } from "fs/promises";
|
||||
import log from "electron-log";
|
||||
import { timer } from "rxjs";
|
||||
import { NotificationService } from "./notification.service";
|
||||
import { NotificationType } from "../../shared/models/notification/notification.model";
|
||||
|
||||
export class BSLauncherService{
|
||||
|
||||
@@ -19,6 +21,7 @@ export class BSLauncherService{
|
||||
private readonly steamService: SteamService;
|
||||
private readonly oculusService: OculusService;
|
||||
private readonly localVersionService: BSLocalVersionService;
|
||||
private readonly notification: NotificationService;
|
||||
|
||||
private bsProcess: ChildProcessWithoutNullStreams;
|
||||
|
||||
@@ -32,6 +35,7 @@ export class BSLauncherService{
|
||||
this.steamService = SteamService.getInstance();
|
||||
this.oculusService = OculusService.getInstance();
|
||||
this.localVersionService = BSLocalVersionService.getInstance();
|
||||
this.notification = NotificationService.getInstance();
|
||||
}
|
||||
|
||||
private getSteamVRPath(): Promise<string>{
|
||||
@@ -55,10 +59,22 @@ export class BSLauncherService{
|
||||
return this.bsProcess?.connected || this.utilsService.taskRunning(BS_EXECUTABLE) === true;
|
||||
}
|
||||
|
||||
// TODO : Rework with shortcuts implementation
|
||||
public async launch(launchOptions: LauchOption): Promise<LaunchResult>{
|
||||
if(launchOptions.version.oculus && this.oculusService.oculusRunning() === false){ return "OCULUS_NOT_RUNNING" }
|
||||
if(!launchOptions.version.oculus && this.steamService.steamRunning() === false){ return "STEAM_NOT_RUNNING" }
|
||||
if(this.isBsRunning() === true){ return "BS_ALREADY_RUNNING" }
|
||||
if(launchOptions.version.oculus && this.oculusService.oculusRunning() === false){ return "OCULUS_NOT_RUNNING" }
|
||||
|
||||
const steamRunning = await this.steamService.steamRunning().catch(() => true); // True if error (error not not means that steam is not running)
|
||||
if(!launchOptions.version.oculus && !steamRunning){
|
||||
|
||||
this.notification.notifyRenderer({
|
||||
title: "notifications.steam.steam-launching.title",
|
||||
desc: "notifications.steam.steam-launching.description",
|
||||
type: NotificationType.SUCCESS,
|
||||
});
|
||||
|
||||
await this.steamService.openSteam().catch(log.error);
|
||||
}
|
||||
|
||||
const cwd = await this.localVersionService.getVersionPath(launchOptions.version);
|
||||
const exePath = path.join(cwd, BS_EXECUTABLE);
|
||||
|
||||
@@ -44,7 +44,7 @@ export class IpcService {
|
||||
this.windows.getWindow(window)?.webContents?.send(channel, response);
|
||||
}
|
||||
|
||||
public connectStream(channel: IpcChannel, window: AppWindow, observable: Observable<unknown>): void{
|
||||
private connectStream(channel: IpcChannel, window: AppWindow, observable: Observable<unknown>): void{
|
||||
observable.subscribe(data => {
|
||||
this.send(channel, window, data);
|
||||
}, error => {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Notification } from "electron";
|
||||
import { SystemNotificationOptions } from "shared/models/notification/system-notification.model";
|
||||
import { UtilsService } from "./utils.service";
|
||||
import { Notification } from "electron";
|
||||
import { Notification as NotificationRenderer } from "../../shared/models/notification/notification.model";
|
||||
import { IpcService } from "./ipc.service";
|
||||
|
||||
export class NotificationService {
|
||||
|
||||
@@ -14,9 +16,11 @@ export class NotificationService {
|
||||
private readonly APP_ICON: string;
|
||||
|
||||
private readonly utils: UtilsService;
|
||||
private readonly ipc: IpcService;
|
||||
|
||||
private constructor(){
|
||||
this.utils = UtilsService.getInstance();
|
||||
this.ipc = IpcService.getInstance();
|
||||
this.APP_ICON = this.utils.getAssetsPath("favicon.ico");
|
||||
}
|
||||
|
||||
@@ -24,4 +28,15 @@ export class NotificationService {
|
||||
new Notification({...options, icon: this.APP_ICON}).show();
|
||||
}
|
||||
|
||||
// TODO : Make actions work
|
||||
public notifyRenderer(notification: Omit<NotificationRenderer, "actions">){
|
||||
try{
|
||||
this.ipc.send("show-notification", "index.html", notification);
|
||||
}
|
||||
catch(e){
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,9 +25,20 @@ export class SteamService{
|
||||
return SteamService.instance;
|
||||
}
|
||||
|
||||
public steamRunning(): boolean | null{
|
||||
return this.utils.taskRunning('steam.exe');
|
||||
}
|
||||
public async getActiveUser(): Promise<number>{
|
||||
const res = await regedit.promisified.list(["HKCU\\Software\\Valve\\Steam\\ActiveProcess"]);
|
||||
const keys = res?.["HKCU\\Software\\Valve\\Steam\\ActiveProcess"];
|
||||
|
||||
if(!keys?.exists){ throw "Key \"HKCU\\Software\\Valve\\Steam\\ActiveProcess\" not exist"; }
|
||||
|
||||
return (keys.values?.ActiveUser.value || undefined) as number;
|
||||
}
|
||||
|
||||
public steamRunning(): Promise<boolean>{
|
||||
return this.getActiveUser()
|
||||
.then(userId => !!userId)
|
||||
.catch(e => {log.error(e); throw e})
|
||||
}
|
||||
|
||||
public async getSteamPath(): Promise<string>{
|
||||
|
||||
@@ -71,12 +82,25 @@ export class SteamService{
|
||||
}
|
||||
}
|
||||
|
||||
public openSteam(): Promise<boolean>{
|
||||
public openSteam(): Promise<void>{
|
||||
const process = spawn("start", ["steam://open/games"], {shell: true});
|
||||
|
||||
return new Promise(resolve => {
|
||||
process.on("exit", () => resolve(true));
|
||||
process.on("error", () => resolve(false));
|
||||
process.on("error", log.error);
|
||||
|
||||
return new Promise(async (resolve, reject) => {
|
||||
// Every 3 seconds check if steam is running
|
||||
const interval = setInterval(async () => {
|
||||
const steamRunning = await this.steamRunning().catch(() => false);
|
||||
if(!steamRunning){ return; }
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
}, 3000);
|
||||
|
||||
// If steam is not running after 60 seconds, reject
|
||||
setTimeout(() => {
|
||||
clearInterval(interval);
|
||||
reject("Unable to open steam");
|
||||
}, 60_000);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { NotificationResult, NotificationType, Notification } from "renderer/services/notification.service"
|
||||
import { NotificationResult, NotificationType, Notification } from "../../../shared/models/notification/notification.model"
|
||||
import { motion, PanInfo } from "framer-motion"
|
||||
import { BsmImage } from "../shared/bsm-image.component";
|
||||
import BeatRunningImg from "../../../../assets/images/apngs/beat-running.png";
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { LauchOption, LaunchResult } from "shared/models/bs-launch";
|
||||
import { BSVersion } from 'shared/bs-version.interface';
|
||||
import { IpcService } from "./ipc.service";
|
||||
import { NotificationResult, NotificationService } from "./notification.service";
|
||||
import { NotificationService } from "./notification.service";
|
||||
import { BsDownloaderService } from "./bs-downloader.service";
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
import { NotificationResult } from "shared/models/notification/notification.model";
|
||||
|
||||
export class BSLauncherService{
|
||||
|
||||
@@ -39,7 +40,7 @@ export class BSLauncherService{
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO : Rework with shortcuts implementation
|
||||
public launch(version: BSVersion, oculus: boolean, desktop: boolean, debug: boolean, additionalArgs?: string[]): Promise<NotificationResult|string>{
|
||||
const lauchOption: LauchOption = {debug, oculus, desktop, version, additionalArgs};
|
||||
if(this.launchState$.value){ return this.notificationService.notifyError({title: "notifications.bs-launch.errors.titles.BS_ALREADY_RUNNING"}); }
|
||||
@@ -59,18 +60,6 @@ export class BSLauncherService{
|
||||
});
|
||||
}
|
||||
if(res.data){
|
||||
// TODO : too much nesting here, need refactor
|
||||
if(res.data === "STEAM_NOT_RUNNING"){
|
||||
return new Promise(async resolve => {
|
||||
const notif = await this.notificationService.notifyError({title: `notifications.bs-launch.errors.titles.${res.data}`, actions: [{id: "0", title: `notifications.bs-launch.errors.actions.${res.data}`}]});
|
||||
if(notif === "0"){
|
||||
await this.ipcService.send<boolean>("open-steam");
|
||||
const lastNotif = await this.notificationService.notifySuccess({title: "notifications.steam.steam-launching.title", desc: "notifications.steam.steam-launching.description"});
|
||||
resolve(lastNotif);
|
||||
}
|
||||
resolve(notif)
|
||||
})
|
||||
}
|
||||
return this.notificationService.notifyError({title: `notifications.bs-launch.errors.titles.${res.data}`});
|
||||
}
|
||||
return this.notificationService.notifyError({title: res.data || res.error.title});
|
||||
|
||||
@@ -9,9 +9,10 @@ import { Mod, ModInstallProgression } from "shared/models/mods";
|
||||
import { ProgressionInterface } from "shared/models/progress-bar";
|
||||
import { IpcService } from "./ipc.service";
|
||||
import { ModalExitCode, ModalService } from "./modale.service";
|
||||
import { NotificationService, NotificationType } from "./notification.service";
|
||||
import { NotificationType } from "../../shared/models/notification/notification.model";
|
||||
import { OsDiagnosticService } from "./os-diagnostic.service";
|
||||
import { ProgressBarService } from "./progress-bar.service";
|
||||
import { NotificationService } from "./notification.service";
|
||||
|
||||
export class BsModsManagerService {
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ export class IpcService{
|
||||
window.electron.ipcRenderer.sendMessage(channel, request);
|
||||
}
|
||||
|
||||
// Also need a rework
|
||||
public watch<T>(channel: string): Observable<IpcResponse<T>>{
|
||||
if(this.channelObservables.has(channel)){ return this.channelObservables.get(channel) as Observable<IpcResponse<T>>; }
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
import { SystemNotificationOptions } from "shared/models/notification/system-notification.model";
|
||||
import { IpcService } from "./ipc.service";
|
||||
import { NotificationResult, NotificationType, Notification } from "../../shared/models/notification/notification.model";
|
||||
|
||||
export class NotificationService{
|
||||
|
||||
@@ -20,6 +21,11 @@ export class NotificationService{
|
||||
private constructor(){
|
||||
this.ipc = IpcService.getInstance();
|
||||
this.notifications$ = new BehaviorSubject<ResolvableNotification[]>([]);
|
||||
|
||||
// TODO : Make actions work and adapt with "watch" remork
|
||||
this.ipc.watch<Notification>("show-notification").subscribe(notification => {
|
||||
this.notify(notification as any as Notification);
|
||||
});
|
||||
}
|
||||
|
||||
public notify(notification: Notification): Promise<NotificationResult|string>{
|
||||
@@ -64,32 +70,6 @@ export class NotificationService{
|
||||
|
||||
}
|
||||
|
||||
export interface Notification {
|
||||
title: string,
|
||||
type?: NotificationType
|
||||
desc?: string,
|
||||
actions?: NotificationAction[],
|
||||
duration?: number,
|
||||
}
|
||||
|
||||
export enum NotificationType {
|
||||
SUCCESS = 0,
|
||||
WARNING = 1,
|
||||
ERROR = 2,
|
||||
INFO = 3,
|
||||
}
|
||||
|
||||
export interface NotificationAction {
|
||||
id: string,
|
||||
title: string,
|
||||
cancel?: boolean
|
||||
}
|
||||
|
||||
export enum NotificationResult {
|
||||
NO_CHOICE = "no_choice",
|
||||
CLOSE = "close",
|
||||
}
|
||||
|
||||
interface ResolvableNotification{
|
||||
id: string,
|
||||
resolver: (value: NotificationResult|string) => void,
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
export interface Notification {
|
||||
title: string,
|
||||
type?: NotificationType
|
||||
desc?: string,
|
||||
actions?: NotificationAction[],
|
||||
duration?: number,
|
||||
}
|
||||
|
||||
export enum NotificationType {
|
||||
SUCCESS = 0,
|
||||
WARNING = 1,
|
||||
ERROR = 2,
|
||||
INFO = 3,
|
||||
}
|
||||
|
||||
export interface NotificationAction {
|
||||
id: string,
|
||||
title: string,
|
||||
cancel?: boolean
|
||||
}
|
||||
|
||||
export enum NotificationResult {
|
||||
NO_CHOICE = "no_choice",
|
||||
CLOSE = "close",
|
||||
}
|
||||
Reference in New Issue
Block a user