From ad19d5b05fe2296e86f6012a81ffd2e05165e300 Mon Sep 17 00:00:00 2001 From: silentrald Date: Sat, 4 Jan 2025 12:14:55 +0800 Subject: [PATCH] [feat-684] applied changes with BadBeatMods API migration --- assets/jsons/translations/en.json | 3 +- .../mods-version-compare-modal.component.tsx | 165 +++++++++++------- .../slides/mods/mods-slide.component.tsx | 4 +- src/shared/helpers/bs-version.helpers.ts | 10 ++ 4 files changed, 114 insertions(+), 68 deletions(-) create mode 100644 src/shared/helpers/bs-version.helpers.ts diff --git a/assets/jsons/translations/en.json b/assets/jsons/translations/en.json index 8fe6985a1..30d9fb1d2 100644 --- a/assets/jsons/translations/en.json +++ b/assets/jsons/translations/en.json @@ -909,7 +909,8 @@ "mod-types": { "all": "All", "installed": "Installed", - "not-installed": "Not Installed" + "not-installed": "Not Installed", + "missing": "Missing" } } }, diff --git a/src/renderer/components/modal/modal-types/mods/mods-version-compare-modal.component.tsx b/src/renderer/components/modal/modal-types/mods/mods-version-compare-modal.component.tsx index e35841764..57b289ab8 100644 --- a/src/renderer/components/modal/modal-types/mods/mods-version-compare-modal.component.tsx +++ b/src/renderer/components/modal/modal-types/mods/mods-version-compare-modal.component.tsx @@ -13,15 +13,30 @@ import { IpcService } from "renderer/services/ipc.service"; import { ModalComponent } from "renderer/services/modale.service"; import { lastValueFrom } from "rxjs"; import { BSVersion } from "shared/bs-version.interface"; +import { getVersionName } from "shared/helpers/bs-version.helpers"; import { safeLt } from "shared/helpers/semver.helpers"; -import { Mod } from "shared/models/mods"; +import { BbmCategories, BbmFullMod, BbmModVersion } from "shared/models/mods/mod.interface"; enum Mode { All = "all", Installed = "installed", NotInstalled = "not-installed", + Missing = "missing", // If mod is not found from the other version } +// To save memory when caching +export interface ModCompareType { + id: number; + name: string; + version: string; +} + +const simplifyFullMod = (mod: BbmFullMod) => ({ + id: mod.mod.id, + name: mod.mod.name, + version: mod.version.modVersion +}); + function useHeader({ version, loading, @@ -35,11 +50,11 @@ function useHeader({ const [mode, setMode] = useState(Mode.All); const [otherVersion, setOtherVersion] = useState(null as BSVersion | null); - const [otherAvailableModsMap, setOtherAvailableModsMap] = useState(new Map()); - const [otherInstalledModsMap, setOtherInstalledModsMap] = useState(new Map()); + const [otherAvailableModsMap, setOtherAvailableModsMap] = useState(null as Map); + const [otherInstalledModsMap, setOtherInstalledModsMap] = useState(null as Map); const [modsMapCache, setModsMapCache] = useState(new Map; - installedModsMap: Map; + availableModsMap: Map; + installedModsMap: Map; }>>()); const modeOptions: BsmSelectOption[] = useConstant(() => @@ -76,19 +91,10 @@ function useHeader({ return v1.name.localeCompare(v2.name); return safeLt(v1.BSVersion, v2.BSVersion) ? 1 : -1; }) - .map(v => { - let { name } = v; - if (v.steam) { - name = "Steam"; - } else if (v.oculus) { - name = "Oculus"; - } - - return { - text: `${v.BSVersion} - ${name}`, - value: v - }; - }), + .map(v => ({ + text: getVersionName(v), + value: v + })), ...availableVersions .filter(v => v.BSVersion !== version.BSVersion) .map(v => ({ text: v.BSVersion, value: v })) @@ -100,39 +106,53 @@ function useHeader({ useEffect(() => { if (!otherVersion) { - const empty = new Map(); - setOtherAvailableModsMap(empty); - setOtherInstalledModsMap(empty); + setOtherAvailableModsMap(null); + setOtherInstalledModsMap(null); return; } - const cached = modsMapCache.get(otherVersion); - if (cached) { - setOtherAvailableModsMap(cached.availableModsMap); - setOtherInstalledModsMap(cached.installedModsMap); + const cache = modsMapCache.get(otherVersion); + if (cache) { + setOtherAvailableModsMap(cache.availableModsMap); + setOtherInstalledModsMap(cache.installedModsMap); return; } setLoading(true); - const promises = [lastValueFrom(ipc.sendV2("bs-mods.get-available-mods", otherVersion))]; + const promises: Promise[] = [ + lastValueFrom(ipc.sendV2("bs-mods.get-available-mods", otherVersion)) + ]; if (otherVersion.path) { promises.push(lastValueFrom(ipc.sendV2("bs-mods.get-installed-mods", otherVersion))) } Promise.all(promises).then(([availableMods, installedMods]) => { - const availableModsMap = new Map(); - const installedModsMap = new Map(); - - availableMods.forEach(mod => availableModsMap.set( - mod.category, - [...(availableModsMap.get(mod.category) ?? []), mod] + const availableModsMap = new Map(); + const installedModsMap = new Map(); + + (availableMods as BbmFullMod[]).forEach(fullMod => availableModsMap.set( + fullMod.mod.category, + [ + ...(availableModsMap.get(fullMod.mod.category) ?? []), + simplifyFullMod(fullMod) + ] )); if (installedMods) { - installedMods.forEach(mod => installedModsMap.set( - mod.category, - [...(installedModsMap.get(mod.category) ?? []), mod] - )); + (installedMods as BbmModVersion[]) + .map(mod => (availableMods as BbmFullMod[]) + .find(availMod => availMod.mod.id === mod.id) + ) + .forEach(fullMod => { + if (!fullMod) { return; } + installedModsMap.set( + fullMod.mod.category, + [ + ...(availableModsMap.get(fullMod.mod.category) ?? []), + simplifyFullMod(fullMod) + ] + ); + }); } // Manual in-memory caching @@ -148,14 +168,13 @@ function useHeader({ }); }, [otherVersion]); - return { mode, otherVersion, otherAvailableModsMap, otherInstalledModsMap, renderHeader: () =>
-
{version.BSVersion} - {version.name}
+
{getVersionName(version)}
) { const otherInstalledLocal = !!otherVersion?.path; - let combinedMods: Mod[] = []; + let combinedMods: ModCompareType[] = []; switch (mode) { case Mode.All: combinedMods = [...availableMods]; @@ -301,13 +320,15 @@ function ModCategory({ } combinedMods.push(...otherAvailableMods.filter( - mod => combinedMods.findIndex(cm => cm.name === mod.name) === -1 + mod => combinedMods.findIndex(cm => cm.id === mod.id) === -1 )); combinedMods.sort((m1, m2) => m1.name.localeCompare(m2.name)); break; case Mode.Installed: - combinedMods = [...installedMods]; + combinedMods = availableMods.filter( + mod => installedMods.findIndex(im => im.name === mod.name) > -1 + ); break; case Mode.NotInstalled: @@ -316,6 +337,15 @@ function ModCategory({ ); break; + case Mode.Missing: + if (otherAvailableMods.length === 0) { + break; + } + combinedMods = otherAvailableMods.filter( + mod => availableMods.findIndex(am => am.name === mod.name) === -1 + ); + break; + default: } @@ -324,7 +354,7 @@ function ModCategory({ } return
-

+

{category}

@@ -348,8 +378,8 @@ function ModCategory({ export const ModsVersionCompareModal: ModalComponent; - installedModsMap: Map; + availableModsMap: Map; + installedModsMap: Map; }>> = ({ options: { data: { version, availableModsMap, @@ -357,6 +387,21 @@ export const ModsVersionCompareModal: ModalComponent { const { text: t } = useTranslationV2(); + const simpleAvailableModsMap = useConstant(() => { + const map = new Map(); + availableModsMap.forEach((mods, category) => + map.set(category, mods.map(simplifyFullMod)) + ); + return map; + }); + const simpleInstalledModsMap = useConstant(() => { + const map = new Map(); + installedModsMap.forEach((mods, category) => + map.set(category, mods.map(simplifyFullMod)) + ); + return map; + }); + const [loading, setLoading] = useState(false); const { mode, @@ -364,16 +409,6 @@ export const ModsVersionCompareModal: ModalComponent 0) { - categories = [...new Set([ - ...categories, ...otherAvailableModsMap.keys() - ])]; - categories.sort((c1, c2) => c1.localeCompare(c2)); - } - return (

@@ -383,16 +418,16 @@ export const ModsVersionCompareModal: ModalComponent - {categories.map(category => + {Object.values(BbmCategories).map(category => )} diff --git a/src/renderer/components/version-viewer/slides/mods/mods-slide.component.tsx b/src/renderer/components/version-viewer/slides/mods/mods-slide.component.tsx index 98ca9557b..0aac23038 100644 --- a/src/renderer/components/version-viewer/slides/mods/mods-slide.component.tsx +++ b/src/renderer/components/version-viewer/slides/mods/mods-slide.component.tsx @@ -9,7 +9,7 @@ import BeatWaitingImg from "../../../../../../assets/images/apngs/beat-waiting.p import BeatConflictImg from "../../../../../../assets/images/apngs/beat-conflict.png"; import { useObservable } from "renderer/hooks/use-observable.hook"; import { lastValueFrom } from "rxjs"; -import { useTranslation, useTranslationV2 } from "renderer/hooks/use-translation.hook"; +import { useTranslationV2 } from "renderer/hooks/use-translation.hook"; import { LinkOpenerService } from "renderer/services/link-opener.service"; import { useInView } from "framer-motion"; import { ModalExitCode, ModalService } from "renderer/services/modale.service"; @@ -319,7 +319,7 @@ export function ModsSlide({ version, onDisclamerDecline }: { version: BSVersion; } function ModStatus({ text, image, spin = false, children }: { text: string; image: string; spin?: boolean, children?: ReactNode}) { - const t = useTranslation(); + const { text: t } = useTranslationV2(); return (
diff --git a/src/shared/helpers/bs-version.helpers.ts b/src/shared/helpers/bs-version.helpers.ts new file mode 100644 index 000000000..63cd92455 --- /dev/null +++ b/src/shared/helpers/bs-version.helpers.ts @@ -0,0 +1,10 @@ +import { BSVersion } from "shared/bs-version.interface"; + +export function getVersionName(version: BSVersion) { + let { name } = version; + if (!name) { + name = version.steam + ? "Steam" : "Oculus"; + } + return `${version.BSVersion} - ${name}`; +}