Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] Steam now launch automatically if it not running then BS launch just after #255

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assets/jsons/translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion assets/jsons/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion assets/jsons/translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion assets/jsons/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
1 change: 0 additions & 1 deletion src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down
20 changes: 18 additions & 2 deletions src/main/services/bs-launcher.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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{

Expand All @@ -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;

Expand All @@ -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>{
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/main/services/ipc.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down
17 changes: 16 additions & 1 deletion src/main/services/notification.service.ts
Original file line number Diff line number Diff line change
@@ -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 {

Expand All @@ -14,14 +16,27 @@ 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");
}

public notify(options: SystemNotificationOptions){
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);
}

}

}
38 changes: 31 additions & 7 deletions src/main/services/steam.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>{

Expand Down Expand Up @@ -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);
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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";
Expand Down
17 changes: 3 additions & 14 deletions src/renderer/services/bs-launcher.service.ts
Original file line number Diff line number Diff line change
@@ -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{

Expand Down Expand Up @@ -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"}); }
Expand All @@ -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});
Expand Down
3 changes: 2 additions & 1 deletion src/renderer/services/bs-mods-manager.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down
1 change: 1 addition & 0 deletions src/renderer/services/ipc.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>>; }

Expand Down
32 changes: 6 additions & 26 deletions src/renderer/services/notification.service.ts
Original file line number Diff line number Diff line change
@@ -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{

Expand All @@ -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>{
Expand Down Expand Up @@ -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,
Expand Down
25 changes: 25 additions & 0 deletions src/shared/models/notification/notification.model.ts
Original file line number Diff line number Diff line change
@@ -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",
}