[feature] can now launch beat saber from shortcut

This commit is contained in:
MathieuG-P
2023-07-14 14:18:23 +02:00
parent 8a7ffdc264
commit 2f3b5bf610
32 changed files with 2119 additions and 347 deletions
@@ -32,7 +32,12 @@ export function BsVersionItem(props: { version: BSVersion }) {
};
const handleDoubleClick = () => {
launcherService.launch(state, !!configService.get<boolean>(LaunchMods.OCULUS_MOD), !!configService.get<boolean>(LaunchMods.DESKTOP_MOD), !!configService.get<boolean>(LaunchMods.DEBUG_MOD));
launcherService.launch({
version: state,
oculus: !!configService.get<boolean>(LaunchMods.OCULUS_MOD),
desktop: !!configService.get<boolean>(LaunchMods.DESKTOP_MOD),
debug: !!configService.get<boolean>(LaunchMods.DEBUG_MOD),
});
};
const cancel = () => {
@@ -2,7 +2,7 @@ import { CSSProperties } from "react";
export function BsNoteFill(props: { className?: string; style?: CSSProperties }) {
return (
<svg className={props.className} style={props.style} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 406.4 406.4" height="406.4" width="406.4">
<svg className={props.className} style={props.style} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 406.4 406.4">
<g>
<rect rx="69.453" height="406.4" width="406.4" fill="currentColor" fillRule="evenodd" paintOrder="fill markers stroke" />
<path transform="translate(-70 170)" d="M135.467-109.4H406.4v33.867L270.933-7.8 135.467-75.533z" fill="white" />
@@ -116,7 +116,7 @@ export default function TitleBar({ template = "index.html" }: { template: AppWin
</header>
);
}
if (template === "oneclick-download-map.html" || template === "oneclick-download-playlist.html" || template === "oneclick-download-model.html") {
if (template === "oneclick-download-map.html" || template === "oneclick-download-playlist.html" || template === "oneclick-download-model.html" || "shortcut-launch.html") {
return (
<header id="titlebar" className="min-h-[22px] bg-transparent w-screen h-[22px] flex content-center items-center justify-start z-10">
<div id="drag-region" className="grow h-full">
@@ -127,9 +127,7 @@ export default function TitleBar({ template = "index.html" }: { template: AppWin
<div id="window-controls" className="h-full flex shrink-0">
<div onClick={closeWindow} className="text-gray-200 cursor-pointer w-7 h-full shrink-0 flex justify-center items-center rounded-bl-md" id="close-button" draggable="false">
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12">
<polygon fill="currentColor" fillRule="evenodd" points="11 1.576 6.583 6 11 10.424 10.424 11 6 6.583 1.576 11 1 10.424 5.417 6 1 1.576 1.576 1 6 5.417 10.424 1">
{" "}
</polygon>
<polygon fill="currentColor" fillRule="evenodd" points="11 1.576 6.583 6 11 10.424 10.424 11 6 6.583 1.576 11 1 10.424 5.417 6 1 1.576 1.576 1 6 5.417 10.424 1"/>
</svg>
</div>
</div>
@@ -50,7 +50,14 @@ export function LaunchSlide({ version }: Props) {
.map(arg => arg.trim())
.filter(arg => arg.length > 0)
: undefined;
bsLauncherService.launch(version, version.oculus ? false : oculusMode, desktopMode, debugMode, additionalArgs);
bsLauncherService.launch({
version,
oculus: version.oculus ? false : oculusMode,
desktop: desktopMode,
debug: debugMode,
additionalArgs
})
};
return (
+5
View File
@@ -8,6 +8,7 @@ const launcherContainer = document.getElementById("launcher");
const oneclickDownloadMapContainer = document.getElementById("oneclick-download-map");
const oneclickDownloadPlaylistContainer = document.getElementById("oneclick-download-playlist");
const oneclickDownloadModelContainer = document.getElementById("oneclick-download-model");
const shortcutLaunchContainer = document.getElementById("shortcut-launch");
const ipc = IpcService.getInstance();
@@ -31,6 +32,10 @@ if (launcherContainer) {
import("./windows/OneClick/OneClickDownloadModel").then(reactWindow => {
createRoot(oneclickDownloadModelContainer).render(<reactWindow.default />);
});
} else if (shortcutLaunchContainer) {
import("./windows/ShortcutLaunch").then(reactWindow => {
createRoot(shortcutLaunchContainer).render(<reactWindow.default />);
});
} else {
const root = document.getElementById("root");
import("./windows/App").then(reactWindow => {
+18 -12
View File
@@ -1,9 +1,9 @@
import { LaunchOption, LaunchResult, BSLaunchErrorEvent, BSLaunchErrorType, BSLaunchEvent } from "shared/models/bs-launch";
import { LaunchOption, LaunchResult, BSLaunchEvent, BSLaunchWarning, BSLaunchEventData, BSLaunchErrorData, BSLaunchError } from "shared/models/bs-launch";
import { BSVersion } from 'shared/bs-version.interface';
import { IpcService } from "./ipc.service";
import { NotificationService } from "./notification.service";
import { BsDownloaderService } from "./bs-downloader.service";
import { BehaviorSubject, Observable } from "rxjs";
import { BehaviorSubject, Observable, filter } from "rxjs";
import { NotificationResult } from "shared/models/notification/notification.model";
export class BSLauncherService {
@@ -66,26 +66,32 @@ export class BSLauncherService {
});
}
public launch(version: BSVersion, oculus: boolean, desktop: boolean, debug: boolean, additionalArgs?: string[]): Observable<BSLaunchEvent> {
const launchState$ = this.ipcService.sendV2<BSLaunchEvent, LaunchOption>("bs-launch.launch", {args: {debug, oculus, desktop, version, additionalArgs}});
public doLaunch(launchOptions: LaunchOption): Observable<BSLaunchEventData>{
return this.ipcService.sendV2<BSLaunchEventData, LaunchOption>("bs-launch.launch", {args: launchOptions});
}
this.versionRunning$.next(version);
public launch(launchOptions: LaunchOption): Observable<BSLaunchEventData> {
const launchState$ = this.doLaunch(launchOptions);
launchState$.subscribe({
this.versionRunning$.next(launchOptions.version);
launchState$.pipe(filter(event => {
const eventToFilter = [...Object.values(BSLaunchWarning), BSLaunchEvent.STEAM_LAUNCHED]
return !eventToFilter.includes(event.type);
})).subscribe({
next: event => {
this.notificationService.notifySuccess({title: `notifications.bs-launch.success.titles.${event.type}`, desc: `notifications.bs-launch.success.msg.${event.type}`});
},
error: (err: BSLaunchErrorEvent) => {
if(!Object.values(BSLaunchErrorType).includes(err.type)){
error: (err: BSLaunchErrorData) => {
if(!Object.values(BSLaunchError).includes(err.type)){
this.notificationService.notifyError({title: "notifications.bs-launch.errors.titles.UNKNOWN_ERROR", desc: "notifications.bs-launch.errors.msg.UNKNOWN_ERROR"});
} else {
this.notificationService.notifyError({title: `notifications.bs-launch.errors.titles.${err.type}`, desc: `notifications.bs-launch.errors.msg.${err.type}`})
}
},
complete: () => {
this.versionRunning$.next(null);
}
})
}).add(() => {
this.versionRunning$.next(null);
});
return launchState$;
}
@@ -1,5 +1,6 @@
import { AppWindow } from "shared/models/window-manager/app-window.model";
import { IpcService } from "./ipc.service";
import { lastValueFrom } from "rxjs";
export class WindowManagerService {
private static instance: WindowManagerService;
@@ -28,4 +29,9 @@ export class WindowManagerService {
public close(...win: AppWindow[]) {
this.ipcService.sendLazy<AppWindow[]>("close-windows", { args: win });
}
public openWindowOrFocus(window: AppWindow): Promise<void> {
return lastValueFrom(this.ipcService.sendV2<void, AppWindow>("open-window-or-focus", { args: window }));
}
}
+14
View File
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://use.typekit.net/okr8ven.css">
<meta charset="utf-8" />
<meta
http-equiv="Content-Security-Policy"
content="script-src 'self' 'unsafe-inline'"
/>
</head>
<body>
<div id="shortcut-launch"></div>
</body>
</html>
+115
View File
@@ -0,0 +1,115 @@
import TitleBar from "renderer/components/title-bar/title-bar.component";
import { useService } from "renderer/hooks/use-service.hook";
import { ThemeService } from "renderer/services/theme.service";
import { useEffect, useState } from "react"
import { WindowManagerService } from "renderer/services/window-manager.service";
import { IpcService } from "renderer/services/ipc.service";
import { take } from "rxjs";
import { BSLauncherService } from "renderer/services/bs-launcher.service";
import { BsmImage } from "renderer/components/shared/bsm-image.component";
import defaultImage from "../../../assets/images/default-version-img.jpg";
import { useObservable } from "renderer/hooks/use-observable.hook";
import { useOnUpdate } from "renderer/hooks/use-on-update.hook";
import { BsNoteFill } from "renderer/components/svgs/icons/bs-note-fill.component";
import { useThemeColor } from "renderer/hooks/use-theme-color.hook";
import { BsmButton } from "renderer/components/shared/bsm-button.component";
import { motion } from "framer-motion"
import { BSLaunchError, BSLaunchEventType, LaunchOption } from "shared/models/bs-launch";
import { NotificationService } from "renderer/services/notification.service";
import { useTranslation } from "renderer/hooks/use-translation.hook";
export default function ShortcutLaunch() {
const themeService = useService(ThemeService);
const windows = useService(WindowManagerService);
const ipc = useService(IpcService);
const bsLauncher = useService(BSLauncherService);
const notification = useService(NotificationService);
const t = useTranslation();
const color = useThemeColor("second-color");
const launchOptions = useObservable(ipc.sendV2<LaunchOption>("shortcut-launch-options").pipe(take(1)), null)
const [rotation, setRotation] = useState(0);
const [status, setStatus] = useState<BSLaunchEventType>();
useEffect(() => {
const sub = themeService.theme$.subscribe(() => {
if (themeService.isDark || (themeService.isOS && window.matchMedia("(prefers-color-scheme: dark)").matches)) {
document.documentElement.classList.add("dark");
} else {
document.documentElement.classList.remove("dark");
}
});
const interval = setInterval(() => {
setRotation(rotation => rotation + 45 * 3);
}, 1500);
return () => {
sub.unsubscribe();
clearInterval(interval);
}
}, []);
useOnUpdate(() => {
if(!launchOptions) { return; }
launchOptions.skipAlreadyRunning = true;
const sub = bsLauncher.doLaunch(launchOptions).subscribe({
next: event => {
setStatus(event.type);
},
error: err => {
if(!Object.values(BSLaunchError).includes(err.type)){
notification.notifySystem({title: t("bs-launch.errors.titles.UNKNOWN_ERROR"), body: t("bs-launch.errors.msg.UNKNOWN_ERROR")});
} else {
notification.notifySystem({title: t(`bs-launch.errors.titles.${err.type}`), body: t(`bs-launch.errors.msg.${err.type}`)})
}
}
});
sub.add(() => {
windows.close("shortcut-launch.html");
});
return () => sub.unsubscribe();
}, [launchOptions]);
return (
<div className="relative w-screen h-screen overflow-hidden ">
<BsmImage className="absolute top-0 left-0 w-full h-full object-cover" placeholder={defaultImage} image={launchOptions?.version?.ReleaseImg ?? defaultImage}/>
<div className="w-full h-full backdrop-blur-lg flex flex-col">
<TitleBar template="shortcut-launch.html"/>
<div className="grow px-6 pb-6 pt-3 flex gap-6">
<div className="h-full w-40 relative flex items-center justify-center">
<BsmImage className="absolute top-0 left-0 w-full h-full object-cover shadow-black shadow-center" placeholder={defaultImage} image={launchOptions?.version?.ReleaseImg ?? defaultImage}/>
<motion.div className="shadow-black shadow-[0px_0px_11px_5px] rounded-2xl aspect-square w-20 z-[1]" animate={{
rotate: rotation,
transition: {
type: "spring",
}
}}>
<BsNoteFill className="w-full h-full" style={{color: launchOptions?.version?.color ?? color}}/>
</motion.div>
</div>
<div className="grow flex flex-col py-3">
<div className="w-full h-full bg-main-color-2 rounded-md shadow-black shadow-md p-3 flex flex-col gap-3">
<h1 className="text-neutral-300 tracking-wide italic">{t("bs-shortcut-launch.beat-saber-launching")}</h1>
<h2 className="text-light-main-color-2 font-bold text-3xl">{[launchOptions?.version?.BSVersion, launchOptions?.version?.name].join(" ")}</h2>
<div className="flex flex-col grow justify-center text-neutral-400">
<span className="uppercase text-neutral-300 tracking-wide">{t("bs-shortcut-launch.launching")}</span>
<span className="italic text-neutral-400 leading-4 text-sm font-bold">{(
status ? t(`bs-shortcut-launch.status-text.success.${status}`) : t("bs-shortcut-launch.status-text.init")
)}
</span>
</div>
<BsmButton className="shrink-0 h-10 rounded-md flex items-center justify-center" text="bs-shortcut-launch.open-bsmanager" typeColor="cancel" withBar={false} onClick={() => windows.openWindowOrFocus("index.html")}/>
</div>
</div>
</div>
</div>
</div>
)
}