Merge branch 'master' into chore/add-beatsaber-desktop-version-info

This commit is contained in:
Zagrios
2025-02-25 14:42:24 +01:00
21 changed files with 157 additions and 72 deletions
+6
View File
@@ -142,5 +142,11 @@
{
"username": "Arts Rimuro Suraimu",
"type": "gold"
},
{
"username": "Ricardo Boss"
},
{
"username": "Jesper Norsted"
}
]
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "Name",
"size": "Größe",
"installed": "Installiert",
"latest": "Neueste",
"description": "Beschreibung",
@@ -152,6 +153,10 @@
"uninstall-all": "Alle deinstallieren",
"unselect-all": "Alle abwählen"
}
},
"mod-item": {
"this-is-a-large-mod": "Das ist ein großer Mod!",
"this-is-a-very-large-mod": "Das ist ein sehr großer Mod!"
}
},
"notifications": {
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "Name",
"size": "Size",
"installed": "Installed",
"latest": "Latest",
"description": "Description",
@@ -152,6 +153,10 @@
"uninstall-all": "Uninstall all",
"unselect-all": "Unselect all"
}
},
"mod-item":{
"this-is-a-large-mod": "This is a large mod!",
"this-is-a-very-large-mod": "This is a very large mod!"
}
},
"notifications": {
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "Nombre",
"size": "Tamaño",
"installed": "Instalado",
"latest": "Último",
"description": "Descripción",
@@ -152,6 +153,10 @@
"uninstall-all": "Desinstalar todos",
"unselect-all": "Deseleccionar todo"
}
},
"mod-item": {
"this-is-a-large-mod": "¡Este es un mod grande!",
"this-is-a-very-large-mod": "¡Este es un mod muy grande!"
}
},
"notifications": {
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "Nom",
"size": "Taille",
"installed": "Installé",
"latest": "Récent",
"description": "Description",
@@ -152,6 +153,10 @@
"uninstall-all": "Tout désinstaller",
"unselect-all": "Tout désélectionner"
}
},
"mod-item": {
"this-is-a-large-mod": "C'est un mod volumineux !",
"this-is-a-very-large-mod": "C'est un mod très volumineux !"
}
},
"notifications": {
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "Nome",
"size": "Dimensione",
"installed": "Installata",
"latest": "Ultima Versione",
"description": "Descrizione",
@@ -152,6 +153,10 @@
"uninstall-all": "Disinstalla tutto",
"unselect-all": "Deseleziona tutto"
}
},
"mod-item": {
"this-is-a-large-mod": "Questo è un mod grande!",
"this-is-a-very-large-mod": "Questo è un mod molto grande!"
}
},
"notifications": {
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "名前",
"size": "サイズ",
"installed": "インストール済み",
"latest": "最新",
"description": "說明",
@@ -152,6 +153,10 @@
"uninstall-all": "全てアンインストールする",
"unselect-all": "すべて選択解除"
}
},
"mod-item": {
"this-is-a-large-mod": "これは大きなModです!",
"this-is-a-very-large-mod": "これは非常に大きなModです!"
}
},
"notifications": {
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "이름",
"size": "크기",
"installed": "설치됨",
"latest": "최신",
"description": "설명",
@@ -152,6 +153,10 @@
"uninstall-all": "모두 제거",
"unselect-all": "모두 선택 해제"
}
},
"mod-item": {
"this-is-a-large-mod": "이것은 큰 모드입니다!",
"this-is-a-very-large-mod": "이것은 매우 큰 모드입니다!"
}
},
"notifications": {
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "Nome",
"size": "tamanho",
"installed": "Instalado",
"latest": "Mais recente",
"description": "Descrição",
@@ -152,6 +153,10 @@
"uninstall-all": "Desinstalar todos",
"unselect-all": "Desmarcar todos"
}
},
"mod-item": {
"this-is-a-large-mod": "Este é um mod grande!",
"this-is-a-very-large-mod": "Este é um mod muito grande!"
}
},
"notifications": {
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "Имя",
"size": "Размер",
"installed": "Установлено",
"latest": "Latest",
"description": "Описание",
@@ -152,6 +153,10 @@
"uninstall-all": "Удалить всё",
"unselect-all": "Снять все выделения"
}
},
"mod-item": {
"this-is-a-large-mod": "Это большой мод!",
"this-is-a-very-large-mod": "Это очень большой мод!"
}
},
"notifications": {
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "Pangalan",
"size": "laki",
"installed": "Naka-install",
"latest": "Pinakabago",
"description": "Deskripsyon",
@@ -152,6 +153,10 @@
"uninstall-all": "I-uninstall ang lahat",
"unselect-all": "I-unselect and lahat"
}
},
"mod-item": {
"this-is-a-large-mod": "Ito ay isang malaking mod!",
"this-is-a-very-large-mod": "Ito ay isang napakalaking mod!"
}
},
"notifications": {
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "Назва",
"size": "розмір",
"installed": "Встановлено",
"latest": "Остання",
"description": "Опис",
@@ -152,6 +153,10 @@
"uninstall-all": "Видалити всі",
"unselect-all": "Зняти виділення з всіх"
}
},
"mod-item": {
"this-is-a-large-mod": "Це великий мод!",
"this-is-a-very-large-mod": "Це дуже великий мод!"
}
},
"notifications": {
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "名稱",
"size": "大小",
"installed": "已安裝",
"latest": "最新",
"description": "描述",
@@ -152,6 +153,10 @@
"uninstall-all": "全部移除",
"unselect-all": "取消全選"
}
},
"mod-item": {
"this-is-a-large-mod": "這是一個大型Mod!",
"this-is-a-very-large-mod": "這是一個非常大型的Mod!"
}
},
"notifications": {
+5
View File
@@ -144,6 +144,7 @@
"mods-grid": {
"header-bar": {
"name": "名称",
"size": "大小",
"installed": "已安装",
"latest": "最新",
"description": "描述",
@@ -152,6 +153,10 @@
"uninstall-all": "全部卸载",
"unselect-all": "取消全选"
}
},
"mod-item": {
"this-is-a-large-mod": "这是一个大型Mod!",
"this-is-a-very-large-mod": "这是一个非常大型的Mod!"
}
},
"notifications": {
-67
View File
@@ -1,67 +0,0 @@
import log from "electron-log";
import { isPromise } from "../../shared/helpers/promise.helpers";
import { tryit } from "../../shared/helpers/error.helpers";
type LogOptions = {
logInput?: boolean;
logOutput?: boolean;
logArgs?: boolean;
};
const stringifyArgs = (args: unknown[]) => {
return args?.map(a => JSON.stringify(a)).join(', ');
};
const logInfo = (message: string, propertyKey: string, args: unknown[], logArgs: boolean, result: unknown) => {
log.info(`[${message}] ${propertyKey}(${logArgs ? stringifyArgs(args) : ''})`, result);
};
const logError = (propertyKey: string, args: unknown[], logArgs: boolean, error: unknown) => {
log.error(`[ERROR] ${propertyKey}(${logArgs ? stringifyArgs(args) : ''})`, error);
throw error;
};
export function Log(options?: LogOptions){
const logInput = options?.logInput ?? false;
const logOutput = options?.logOutput ?? true;
const logArgs = options?.logArgs ?? true;
return (target: unknown, propertyKey: string, descriptor: PropertyDescriptor) => {
const originalMethod = descriptor.value;
descriptor.value = function(...args: unknown[]) {
if (logInput) {
logInfo('INPUT', propertyKey, args, logArgs, null);
}
const outcome = tryit(() => originalMethod.apply(this, args));
if (isPromise(outcome)) {
return outcome.then(({ result, error }) => {
if (error) {
logError(propertyKey, args, logArgs, error);
}
if (logOutput) {
logInfo('OUTPUT', propertyKey, args, logArgs, result);
}
return result;
});
}
const { result, error } = outcome;
if (error) {
logError(propertyKey, args, logArgs, error);
}
if (logOutput) {
logInfo('OUTPUT', propertyKey, args, logArgs, result);
}
return result;
};
};
}
+1 -2
View File
@@ -3,7 +3,6 @@ import { access, mkdir, readdir, lstat, readlink } from "fs/promises";
import path from "path";
import { Observable, concatMap, from } from "rxjs";
import log from "electron-log";
import { BsmException } from "shared/models/bsm-exception.model";
import crypto from "crypto";
import { execSync } from "child_process";
import { tryit } from "../../shared/helpers/error.helpers";
@@ -181,7 +180,7 @@ export function isSubdirectory(parent: string, child: string): boolean {
export async function copyDirectoryWithJunctions(src: string, dest: string, options?: CopyOptions): Promise<void> {
if (isSubdirectory(src, dest)) {
throw { message: `Cannot copy directory '${src}' into itself '${dest}'.`, code: "COPY_TO_SUBPATH" } as BsmException;
throw new CustomError(`Cannot copy directory '${src}' into itself '${dest}'.`, "COPY_TO_SUBPATH");
}
await ensureDir(dest);
@@ -19,7 +19,6 @@ export class SongCacheService {
private readonly mapsInfoCache: JsonCache<CachedMapInfoWithHash>;
private constructor(){
console.log(this.MAPS_INFO_CACHE_PATH);
this.mapsInfoCache = new JsonCache(this.MAPS_INFO_CACHE_PATH);
}
@@ -7,6 +7,8 @@ import useDoubleClick from "use-double-click";
import { useOnUpdate } from "renderer/hooks/use-on-update.hook";
import striptags from "striptags";
import { safeGt } from "shared/helpers/semver.helpers";
import Tippy from "@tippyjs/react";
import { useTranslationV2 } from "renderer/hooks/use-translation.hook";
type Props = {
className?: string;
@@ -21,6 +23,68 @@ type Props = {
onUninstall?: () => void;
};
type FileSizeProps = {
fileSize?: number;
wantInfoStyle: CSSProperties;
};
function FileSizeText({ fileSize, wantInfoStyle }: Readonly<FileSizeProps>) {
const { text: t } = useTranslationV2();
const verifyFileSize = fileSize !== undefined;
const isMediumMod = verifyFileSize && fileSize > 1024 * 1024 * 50; // 50MB
const isLargeMod = verifyFileSize && fileSize > 1024 * 1024 * 100; // 100MB
const getFormattedSize = () : string => {
if (!verifyFileSize || fileSize === 0)
return `-`;
if (fileSize < 1024 * 1024)
return `${(fileSize/1024).toFixed(2)}KB`;
return `${(fileSize/1024/1024).toFixed(2)}MB`;
};
const getWarningText = () : string => {
if (isLargeMod)
return `pages.version-viewer.mods.mods-grid.mod-item.this-is-a-very-large-mod`;
if (isMediumMod)
return `pages.version-viewer.mods.mods-grid.mod-item.this-is-a-large-mod`;
return "";
};
const getTheme = () : string => {
if (isLargeMod)
return 'red';
if (isMediumMod)
return 'yellow';
return "";
};
const getTextColor = () : string => {
if (isLargeMod)
return "text-red-400";
if (isMediumMod)
return "text-yellow-400";
return "";
};
return (
<Tippy
content={t(getWarningText())}
placement="left"
theme={getTheme()}
disabled={!(isLargeMod || isMediumMod)}
delay={[50, 0]} >
<span className={`min-w-0 text-center bg-inherit py-2 px-1 text-sm border-t-2 border-b-2 group-hover:brightness-90 ${getTextColor()}`} style={wantInfoStyle}>
{getFormattedSize()}
</span>
</Tippy>
);
}
export function ModItem({ className, mod, installedVersion, isDependency, isSelected, onChange, wantInfo, onWantInfo, disabled, onUninstall }: Props) {
const themeColor = useThemeColor("second-color");
@@ -65,6 +129,7 @@ export function ModItem({ className, mod, installedVersion, isDependency, isSele
<span className="min-w-0 text-center bg-inherit py-2 px-1 text-sm border-t-2 border-b-2 group-hover:brightness-90" style={wantInfoStyle}>
{mod.version.modVersion}
</span>
<FileSizeText fileSize={mod.version.fileSize} wantInfoStyle={wantInfoStyle} />
<span title={striptags(mod.mod?.description ?? "", { tagReplacementText: " " })} className="px-3 bg-inherit whitespace-nowrap text-ellipsis overflow-hidden py-2 text-sm border-t-2 border-b-2 group-hover:brightness-90" style={wantInfoStyle}>
{striptags(mod.mod?.summary ?? "", { tagReplacementText: " " })}
</span>
@@ -58,14 +58,15 @@ export function ModsGrid({ modsMap, installed, modsSelected, onModChange, moreIn
return (
modsMap && (
<div className="grid gap-y-1 grid-cols-[40px_min-content_min-content_min-content_1fr_min-content] bg-light-main-color-2 dark:bg-main-color-2 text-main-color-1 dark:text-light-main-color-1">
<div className="grid gap-y-1 grid-cols-[40px_min-content_min-content_min-content_min-content_1fr_min-content] bg-light-main-color-2 dark:bg-main-color-2 text-main-color-1 dark:text-light-main-color-1">
<span className="absolute z-10 top-0 w-full h-8 bg-inherit rounded-tl-md" />
<span className="z-10 sticky flex items-center justify-end top-0 bg-inherit border-b-2 border-main-color-1 rounded-tl-md">
<BsmButton className="rounded-full h-6 w-6 p-[2px]" withBar={false} icon="search" onClick={handleToogleFilter} />
</span>
<span className="z-10 sticky top-0 flex items-center bg-inherit border-main-color-1 border-b-2 h-8 px-1 whitespace-nowrap">{filterEnabled ? <motion.input autoFocus className="bg-light-main-color-1 dark:bg-main-color-1 rounded-md h-6 px-2" initial={{ width: 0 }} animate={{ width: "250px" }} transition={{ ease: "easeInOut", duration: 0.15 }} onChange={e => handleInput(e.target.value)} /> : <span className="w-full text-center">{t("pages.version-viewer.mods.mods-grid.header-bar.name")}</span>}</span>
<span className="z-10 sticky top-0 flex items-center bg-inherit border-main-color-1 border-b-2 h-8 px-1 whitespace-nowrap">{filterEnabled ? <motion.input autoFocus className="bg-light-main-color-1 dark:bg-main-color-1 rounded-md h-6 px-2" initial={{ width: 0 }} animate={{ width: "200px" }} transition={{ ease: "easeInOut", duration: 0.15 }} onChange={e => handleInput(e.target.value)} /> : <span className="w-full text-center">{t("pages.version-viewer.mods.mods-grid.header-bar.name")}</span>}</span>
<span className="z-10 sticky flex items-center justify-center top-0 bg-inherit border-b-2 border-main-color-1 h-8 px-2 whitespace-nowrap">{t("pages.version-viewer.mods.mods-grid.header-bar.installed")}</span>
<span className="z-10 sticky flex items-center justify-center top-0 bg-inherit border-b-2 border-main-color-1 h-8 px-2 whitespace-nowrap">{t("pages.version-viewer.mods.mods-grid.header-bar.latest")}</span>
<span className="z-10 sticky flex items-center justify-center top-0 bg-inherit border-b-2 border-main-color-1 h-8 px-2 whitespace-nowrap">{t("pages.version-viewer.mods.mods-grid.header-bar.size")}</span>
<span className="z-10 sticky flex items-center justify-center top-0 bg-inherit border-b-2 border-main-color-1 h-8 whitespace-nowrap">{t("pages.version-viewer.mods.mods-grid.header-bar.description")}</span>
<span className="z-10 sticky top-0 bg-inherit border-b-2 border-main-color-1 h-8 flex justify-start items-center py-1 pl-[3px] min-w-[50px]">
<BsmDropdownButton className="h-full aspect-square relative rounded-full bg-light-main-color-1 dark:bg-main-color-3" withBar={false} icon="three-dots" buttonClassName="!rounded-full !p-[2px] !bg-light-main-color-2 dark:!bg-main-color-2 hover:!bg-light-main-color-1 dark:hover:!bg-main-color-3" menuTranslationY="5px" items={[
+16
View File
@@ -114,6 +114,22 @@
@apply border-r-neutral-900;
}
.tippy-box[data-theme~='red'] {
@apply bg-neutral-900;
@apply text-red-400;
}
.tippy-box[data-theme~='red'][data-placement^='left'] > .tippy-arrow::before {
@apply border-l-neutral-900;
}
.tippy-box[data-theme~='yellow'] {
@apply bg-neutral-900;
@apply text-yellow-400;
}
.tippy-box[data-theme~='yellow'][data-placement^='left'] > .tippy-arrow::before {
@apply border-l-neutral-900;
}
.bg-theme-1 { @apply bg-light-main-color-1 dark:bg-main-color-1; }
.bg-theme-2 { @apply bg-light-main-color-2 dark:bg-main-color-2; }
.bg-theme-3 { @apply bg-light-main-color-3 dark:bg-main-color-3; }
+1
View File
@@ -42,6 +42,7 @@ export interface BbmModVersion {
downloadCount: number;
lastApprovedById?: number;
lastUpdatedById?: number;
fileSize?: number;
createdAt?: Date;
updatedAt?: Date;
}