Merge branch 'master' into feature/fileSizes+OversizeWarning

This commit is contained in:
Unifox
2025-02-12 13:17:38 -07:00
committed by GitHub
29 changed files with 3078 additions and 430 deletions
+1
View File
@@ -33,3 +33,4 @@ ipc.on("bs-mods.uninstall-all-mods", (args, reply) => {
const modsManager = BsModsManagerService.getInstance();
reply(modsManager.uninstallAllMods(args));
});
+5
View File
@@ -9,3 +9,8 @@ ipc.on("linux.verify-proton-folder", (_, reply) => {
reply(of(linuxService.verifyProtonPath()));
});
ipc.on("linux.get-wine-prefix-path", (_, reply) => {
const linuxService = LinuxService.getInstance();
reply(of(linuxService.getWinePrefixPath()));
});
@@ -106,10 +106,10 @@ export class BSLocalVersionService {
const versionFilePath = path.join(bsPath, 'Beat Saber_Data', 'globalgamemanagers');
const folderVersion = await this.getVersionFromGlobalGameManagerFile(versionFilePath);
folderVersion.path = bsPath;
if(!folderVersion){ return null; }
folderVersion.path = bsPath;
if(options?.steam || options?.oculus){
return {...folderVersion, ...options};
}
@@ -158,11 +158,10 @@ export class BsModsManagerService {
winePath = `"${winePathResult}"`;
const winePrefix = this.linuxService.getWinePrefixPath();
if (winePrefix) {
env.WINEPREFIX = winePrefix;
} else {
log.warn("Could not find BSManager WINEPREFIX path, using system's default value instead");
if (!winePrefix) {
throw new CustomError("Could not find BSManager WINEPREFIX path", "no-wineprefix");
}
env.WINEPREFIX = winePrefix;
}
return new Promise<boolean>(resolve => {
@@ -12,7 +12,7 @@ import { FranceIcon } from "./flags/france-icon.component";
import { SpainIcon } from "./flags/spain-icon.component";
import { ItalyIcon } from "./flags/italy-icon.component";
import { UsaIcon } from "./flags/usa-icon.component";
import { UkIcon } from "./flags/uk-icon.component";
import { UkraineIcon } from "./flags/ukraine-icon.component";
import { TaskIcon } from "./icons/task-icon.component";
import { CopyIcon } from "./icons/copy-icon.component";
import { SteamIcon } from "./icons/steam-icon.component";
@@ -70,10 +70,12 @@ import { AddFileIcon } from "./icons/add-file-icon.component";
import { CancelIcon } from "./icons/cancel-icon.component";
import { WarningIcon } from "./icons/warning-icon.component";
import { ArrowUpwardIcon } from "./icons/arrow-upward-icon.component";
import { UkIcon } from "./flags/uk-icon.component";
import { PhilippineIcon } from "./flags/philippine-icon.component";
export type BsmIconType = SongDetailDiffCharactertistic | ("settings" | "trash" | "favorite" | "folder" | "bsNote" | "check" | "three-dots" | "twitch" | "eye" | "play" | "checkCircleIcon" | "discord" | "info" | "eye-cross" | "terminal" | "desktop" | "oculus" | "add" | "cross" | "task" | "github" | "close" | "thumbUpFill" | "timerFill" | "pause" | "twitter" | "sync" | "chevron-top" | "copy" | "steam" | "edit" | "export" | "patreon" | "search" | "bsMapDifficulty" | "link" | "unlink" | "download" | "filter" | "mee6" | "volume-up" | "volume-off" | "volume-down" | "shortcut" | "backup-restore" | "web-site" | "clean" | "browse" | "add-file" | "arrow-upward" | "cancel" | "warning" | "fr-FR-flag" | "es-ES-flag" | "it-IT-flag" | "en-US-flag" | "en-EN-flag" | "de-DE-flag" | "ru-RU-flag" | "zh-CN-flag" | "zh-TW-flag" | "ja-JP-flag" | "ko-KR-flag" | "pt-BR-flag" | "uk-UA-flag" | "tl-PH-flag" | "null" );
export type BsmIconType = SongDetailDiffCharactertistic | ("settings" | "trash" | "favorite" | "folder" | "bsNote" | "check" | "three-dots" | "twitch" | "eye" | "play" | "checkCircleIcon" | "discord" | "info" | "eye-cross" | "terminal" | "desktop" | "oculus" | "add" | "cross" | "task" | "github" | "close" | "thumbUpFill" | "timerFill" | "pause" | "twitter" | "sync" | "chevron-top" | "copy" | "steam" | "edit" | "export" | "patreon" | "search" | "bsMapDifficulty" | "link" | "unlink" | "download" | "filter" | "mee6" | "volume-up" | "volume-off" | "volume-down" | "shortcut" | "backup-restore" | "web-site" | "clean" | "browse" | "add-file" | "arrow-upward" | "cancel" | "warning" | "fr-FR-flag" | "es-ES-flag" | "it-IT-flag" | "en-US-flag" | "en-EN-flag" | "de-DE-flag" | "ru-RU-flag" | "zh-CN-flag" | "zh-TW-flag" | "ja-JP-flag" | "ko-KR-flag" | "pt-BR-flag" | "null" );
export const BsmIcon = memo(({ className, icon, style }: { className?: string; icon: BsmIconType; style?: CSSProperties }) => {
// TODO : Very ugly very messy, need to find a better way to do this
@@ -146,6 +148,12 @@ export const BsmIcon = memo(({ className, icon, style }: { className?: string; i
if (icon === "pt-BR-flag"){
return <BrazilIcon className={className} style={style} />;
}
if (icon === "uk-UA-flag"){
return <UkraineIcon className={className} style={style} />;
}
if (icon === "tl-PH-flag") {
return <PhilippineIcon className={className} style={style} />;
}
if (icon === "task") {
return <TaskIcon className={className} style={style} />;
@@ -0,0 +1,14 @@
import { createSvgIcon } from "../svg-icon.type";
export const PhilippineIcon = createSvgIcon((props, ref) => {
return (
<svg ref={ref} {...props} width="71" height="48" viewBox="0 0 71 48" xmlns="http://www.w3.org/2000/svg">
<g fill="none">
<path d="M63.89.12H6.61A6.36 6.36 0 0 0 .25 6.48v17.64h70V6.48A6.36 6.36 0 0 0 63.89.12" fill="#4758A9"/>
<path d="M.25 40.75a6.36 6.36 0 0 0 6.36 6.36h57.27a6.36 6.36 0 0 0 6.36-6.36V24.12h-70z" fill="#ED5565"/>
<path d="M2.15 1.95a6.34 6.34 0 0 0-1.9 4.54v34.27a6.34 6.34 0 0 0 1.95 4.57l23.05-21.21z" fill="#FFF"/>
<circle fill="#F6D660" cx="10.25" cy="23.62" r="4"/>
</g>
</svg>
);
});
@@ -0,0 +1,14 @@
import { createSvgIcon } from "../svg-icon.type";
// Uploaded from: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools
export const UkraineIcon = createSvgIcon((props, ref) => {
return (
<svg ref={ref} {...props} width="71" height="48" viewBox="0 0 71 48" xmlns="http://www.w3.org/2000/svg">
<g fill="none">
<path d="M64.27 47.7H7a6.36 6.36 0 0 1-6.36-6.36V23.7h70v17.64a6.36 6.36 0 0 1-6.37 6.36" fill="#F6D660"/>
<path d="M.63 7.06A6.36 6.36 0 0 1 7 .7h57.27a6.36 6.36 0 0 1 6.36 6.36V23.7h-70z" fill="#4A89DC"/>
</g>
</svg>
);
})
@@ -22,6 +22,7 @@ import { UninstallAllModsModal } from "renderer/components/modal/modal-types/uni
import Tippy from "@tippyjs/react";
import { ProgressBarService } from "renderer/services/progress-bar.service";
import { Dropzone } from "renderer/components/shared/dropzone.component";
import { ModsGridStatus } from "shared/models/mods/mod-ipc.model";
export type ModsSlideRef = {
loadMods: () => Promise<void>;
@@ -42,6 +43,7 @@ export const ModsSlide = forwardRef<ModsSlideRef, Props>(({ version, isActive, o
const os = useService(OsDiagnosticService);
const progress = useService(ProgressBarService);
const [gridStatus, setGridStatus] = useState(ModsGridStatus.OK);
const [modsAvailable, setModsAvailable] = useState(null as Map<BbmCategories, BbmFullMod[]>);
const [modsInstalled, setModsInstalled] = useState(null as Map<BbmCategories, BbmFullMod[]>);
const [modsSelected, setModsSelected] = useState([] as BbmFullMod[]);
@@ -185,8 +187,23 @@ export const ModsSlide = forwardRef<ModsSlideRef, Props>(({ version, isActive, o
setModsSelected(() => []);
}
const ensureDisclaimerAccepted = async (): Promise<boolean> => {
if (configService.get<boolean>(ACCEPTED_DISCLAIMER_KEY)) {
return true;
}
const res = await modals.openModal(ModsDisclaimerModal);
const haveAccepted = res.exitCode === ModalExitCode.COMPLETED;
if (haveAccepted) {
configService.set(ACCEPTED_DISCLAIMER_KEY, true);
}
return haveAccepted;
}
const loadMods = async (): Promise<void> => {
if (os.isOffline) {
if (os.isOffline || gridStatus !== ModsGridStatus.OK) {
return Promise.resolve();
}
@@ -209,24 +226,14 @@ export const ModsSlide = forwardRef<ModsSlideRef, Props>(({ version, isActive, o
return noop();
}
(async () => {
if (configService.get<boolean>(ACCEPTED_DISCLAIMER_KEY)) {
return true;
}
const res = await modals.openModal(ModsDisclaimerModal);
const haveAccepted = res.exitCode === ModalExitCode.COMPLETED;
if (haveAccepted) {
configService.set(ACCEPTED_DISCLAIMER_KEY, true);
}
return haveAccepted;
})().then(canLoad => {
ensureDisclaimerAccepted().then(async canLoad => {
if (!canLoad) {
return onDisclamerDecline?.();
}
const status = await modsManager.getModsGridStatus();
setGridStatus(() => status);
loadMods();
});
@@ -234,6 +241,7 @@ export const ModsSlide = forwardRef<ModsSlideRef, Props>(({ version, isActive, o
setMoreInfoMod(null);
setModsAvailable(null);
setModsInstalled(null);
setGridStatus(ModsGridStatus.OK);
};
}, [isActive, isOnline, version]);
@@ -262,6 +270,9 @@ export const ModsSlide = forwardRef<ModsSlideRef, Props>(({ version, isActive, o
if (!isOnline) {
return <ModStatus text="pages.version-viewer.mods.no-internet" image={BeatConflictImg} />;
}
if (gridStatus !== ModsGridStatus.OK) {
return <ModStatus text={`pages.version-viewer.mods.status.${gridStatus}`} image={BeatConflictImg} />;
}
if (!modsAvailable) {
return <ModStatus text="pages.version-viewer.mods.loading-mods" image={BeatWaitingImg} spin />;
}
@@ -337,7 +348,7 @@ function ModStatus({ text, image, spin = false, children }: { text: string; imag
return (
<div className="w-full h-full flex flex-col items-center justify-center text-gray-800 dark:text-gray-200">
<img className={`w-32 h-32 ${spin ? "spin-loading" : ""}`} src={image} alt=" " />
<span className="text-xl mt-3 italic">{t(text)}</span>
<span className="text-xl mt-3 italic text-center">{t(text)}</span>
{children}
</div>
);
@@ -25,7 +25,7 @@ export const defaultConfiguration: {
"second-color": "#ff4444",
theme: "os",
language: window.navigator.language.length <= 2 ? `${window.navigator.language}-${window.navigator.language.toLocaleUpperCase()}` : window.navigator.language,
supported_languages: ["en-US", "en-EN", "fr-FR", "es-ES", "it-IT", "de-DE", "ru-RU", "zh-CN", "zh-TW", "ja-JP", "ko-KR", "pt-BR"],
supported_languages: ["en-US", "en-EN", "fr-FR", "es-ES", "it-IT", "de-DE", "ru-RU", "zh-CN", "zh-TW", "ja-JP", "ko-KR", "pt-BR", "uk-UA", "tl-PH"],
default_mods: ["SongCore", "WhyIsThereNoLeaderboard", "BeatSaverDownloader", "BeatSaverVoting", "PlaylistManager"],
"default-shared-folders": [
window.electron.path.join("Beat Saber_Data", "CustomLevels"),
@@ -8,6 +8,8 @@ import { Progression } from "main/helpers/fs.helpers";
import { ProgressionInterface } from "shared/models/progress-bar";
import { BbmFullMod, BbmModVersion } from "shared/models/mods/mod.interface";
import { logRenderError } from "renderer";
import { ModsGridStatus } from "shared/models/mods/mod-ipc.model";
import { LinuxService } from "./linux.service";
export class BsModsManagerService {
private static instance: BsModsManagerService;
@@ -17,6 +19,7 @@ export class BsModsManagerService {
private readonly ipcService: IpcService;
private readonly progressBar: ProgressBarService;
private readonly notifications: NotificationService;
private readonly linux: LinuxService
public readonly isUninstalling$: BehaviorSubject<boolean> = new BehaviorSubject(false);
@@ -31,6 +34,7 @@ export class BsModsManagerService {
this.ipcService = IpcService.getInstance();
this.progressBar = ProgressBarService.getInstance();
this.notifications = NotificationService.getInstance();
this.linux = LinuxService.getInstance();
}
public getAvailableMods(version: BSVersion): Observable<BbmFullMod[]> {
@@ -204,4 +208,17 @@ export class BsModsManagerService {
return { available: (available ?? []), installed: (installedMods ?? []) };
}
public async getModsGridStatus(): Promise<ModsGridStatus> {
if(window.electron.platform === "linux"){
const winePrefix = await lastValueFrom(this.linux.getWinePrefixPath());
if(!winePrefix){
logRenderError("Could not find BSManager WINEPREFIX path");
return ModsGridStatus.NO_WINEPREFIX;
}
}
return ModsGridStatus.OK;
}
}
+26
View File
@@ -0,0 +1,26 @@
import { Observable } from "rxjs";
import { IpcService } from "./ipc.service";
export class LinuxService {
private static instance: LinuxService;
public static getInstance(): LinuxService {
if (!LinuxService.instance) {
LinuxService.instance = new LinuxService();
}
return LinuxService.instance;
}
private readonly ipc: IpcService;
private constructor() {
this.ipc = IpcService.getInstance();
}
public getWinePrefixPath(): Observable<string> {
return this.ipc.sendV2("linux.get-wine-prefix-path");
}
}
+1
View File
@@ -159,6 +159,7 @@ export interface IpcChannelMapping {
/* ** linux.ipcs ** */
"linux.verify-proton-folder": { request: void, response: boolean };
"linux.get-wine-prefix-path": { request: void, response: string };
/* ** oculus.ipcs ** */
"is-oculus-sideloaded-apps-enabled": { request: void, response: boolean };
+7
View File
@@ -12,3 +12,10 @@ export interface UninstallModsResult {
nbModsToUninstall: number;
nbUninstalledMods: number;
}
export enum ModsGridStatus {
OK = "",
NO_WINEPREFIX = "no-wineprefix",
UNKNOWN = "unknown"
}