diff --git a/assets/jsons/translations/de.json b/assets/jsons/translations/de.json index ad8d1d1c..2b4afade 100644 --- a/assets/jsons/translations/de.json +++ b/assets/jsons/translations/de.json @@ -179,6 +179,9 @@ "description-plural": "Diese Version enthält {nb} veraltete Mods. Möchten Sie sie aktualisieren?", "dont-remind-me": "Nicht mehr daran erinnern", "update": "Aktualisieren" + }, + "third-party-mod-source-not-avaliable": { + "description": "Die Drittanbieter-Datenquelle „{name}“ ist nicht verfügbar. Bitte wechseln Sie in den Einstellungen zurück zu BeatMods und versuchen Sie es erneut." } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "Modulquelle", + "description": "Wähle eine andere Quelle als BeatMods.", + "website": "Webseite" + }, "patreon": { "title": "BSManager Unterstützen 💖", "description": "Unterstütze das Projekt und helfe uns, BSManager kontinuierlich zu verbessern.", diff --git a/assets/jsons/translations/en.json b/assets/jsons/translations/en.json index e117f972..d6d4f398 100644 --- a/assets/jsons/translations/en.json +++ b/assets/jsons/translations/en.json @@ -179,6 +179,9 @@ "description-plural": "This version has {nb} outdated mods. Do you want to update them?", "dont-remind-me": "Don't remind me", "update": "Update" + }, + "third-party-mod-source-not-avaliable": { + "description": "The third party mod source \"{name}\" is not avaliable. Please switch to BeatMods at setthings and try again." } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "Mod Source", + "description": "Choose a source other than BeatMods.", + "website": "website" + }, "patreon": { "title": "Support BSManager 💖", "description": "Support the project and help us to provide continuous improvements to BSManager.", diff --git a/assets/jsons/translations/es.json b/assets/jsons/translations/es.json index 7b29a743..a5ce3039 100644 --- a/assets/jsons/translations/es.json +++ b/assets/jsons/translations/es.json @@ -179,6 +179,9 @@ "description-plural": "Esta versión tiene {nb} mods desactualizados. ¿Quieres actualizarlos?", "dont-remind-me": "No me lo recuerdes", "update": "Actualizar" + }, + "third-party-mod-source-not-avaliable": { + "description": "La fuente de datos de terceros \"{name}\" no está disponible. Vuelve a BeatMods en la configuración e inténtalo de nuevo." } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "Fuente del módulo", + "description": "Elija una fuente distinta a BeatMods.", + "website": "sitio web" + }, "patreon": { "title": "Apoya BSManager 💖", "description": "Apoya el proyecto y ayúdanos a proporcionar mejoras continuas a BSManager.", diff --git a/assets/jsons/translations/fr.json b/assets/jsons/translations/fr.json index 83f35979..e35ec063 100644 --- a/assets/jsons/translations/fr.json +++ b/assets/jsons/translations/fr.json @@ -179,6 +179,9 @@ "description-plural": "Cette version contient {nb} mods obsolètes. Voulez-vous les mettre à jour ?", "dont-remind-me": "Ne plus me rappeler", "update": "Mettre à jour" + }, + "third-party-mod-source-not-avaliable": { + "description": "La source de données tierce « {name} » est indisponible. Veuillez revenir à Beatmods dans les paramètres et réessayer." } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "Source du module", + "description": "Choisissez une autre source que BeatMods.", + "website": "site web" + }, "patreon": { "title": "Soutenir BSManager 💖", "description": "Soutiens le projet et aide-nous à fournir des améliorations continues à BSManager.", diff --git a/assets/jsons/translations/it.json b/assets/jsons/translations/it.json index 8ed85b3b..f8466e44 100644 --- a/assets/jsons/translations/it.json +++ b/assets/jsons/translations/it.json @@ -179,6 +179,9 @@ "description-plural": "Questa versione ha {nb} mod obsoleti. Vuoi aggiornarli?", "dont-remind-me": "Non ricordarmelo", "update": "Aggiorna" + }, + "third-party-mod-source-not-avaliable": { + "description": "La fonte dati di terze parti \"{name}\" non è disponibile. Torna a BeatMods nelle impostazioni e riprova." } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "Sorgente del modulo", + "description": "Scegli una fonte diversa da BeatMods.", + "website": "sito web" + }, "patreon": { "title": "Sostieni BSManager 💖", "description": "Supporta il progetto e aiutaci a provvedere continui miglioramenti a BSManager.", diff --git a/assets/jsons/translations/ja.json b/assets/jsons/translations/ja.json index dadca05a..eb893494 100644 --- a/assets/jsons/translations/ja.json +++ b/assets/jsons/translations/ja.json @@ -179,6 +179,9 @@ "description-plural": "このバージョンには古いModが{nb}個あります。更新しますか?", "dont-remind-me": "もう知らせない", "update": "更新する" + }, + "third-party-mod-source-not-avaliable": { + "description": "サードパーティのデータソース「{name}」は利用できません。設定でBeatModsに切り替えて、もう一度お試しください。" } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "モジュールソース", + "description": "BeatMods以外のソースを選択してください。", + "website": "Webサイト" + }, "patreon": { "title": "BSManagerをサポートする 💖", "description": "プロジェクトをサポートし、BSManagerの継続的な応援にご協力ください!", diff --git a/assets/jsons/translations/ko.json b/assets/jsons/translations/ko.json index 568c42fc..66a81d40 100644 --- a/assets/jsons/translations/ko.json +++ b/assets/jsons/translations/ko.json @@ -179,6 +179,9 @@ "description-plural": "이 버전에는 {nb}개의 구식 모드가 있습니다. 업데이트하시겠습니까?", "dont-remind-me": "다시는 알리지 않기", "update": "업데이트" + }, + "third-party-mod-source-not-avaliable": { + "description": "타사 데이터 소스 \"{name}\"을 사용할 수 없습니다. 설정에서 BeatMods로 다시 전환한 후 다시 시도해 주세요." } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "모듈 소스", + "description": "BeatMods 이외의 소스를 선택하세요.", + "website": "웹사이트" + }, "patreon": { "title": "BSManager를 지원하기 💖", "description": "프로젝트를 지원하고 BSManager의 지속적인 응원을 부탁드립니다!", diff --git a/assets/jsons/translations/pt-br.json b/assets/jsons/translations/pt-br.json index ba13d33b..2c514599 100644 --- a/assets/jsons/translations/pt-br.json +++ b/assets/jsons/translations/pt-br.json @@ -179,6 +179,9 @@ "description-plural": "Esta versão possui {nb} mods desatualizados. Deseja atualizá-los?", "dont-remind-me": "Não me lembre", "update": "Atualizar" + }, + "third-party-mod-source-not-avaliable": { + "description": "A fonte de dados de terceiros \"{name}\" está indisponível. Por favor, volte para BeatMods nas configurações e tente novamente." } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "Fonte do módulo", + "description": "Escolha uma fonte diferente de BeatMods.", + "website": "site" + }, "patreon": { "title": "Apoie BSManager 💖", "description": "Apoie o projeto e nos ajude a continuar trazendo melhorias para o BSManager.", diff --git a/assets/jsons/translations/ru.json b/assets/jsons/translations/ru.json index 25f2ce95..2cb3d87a 100644 --- a/assets/jsons/translations/ru.json +++ b/assets/jsons/translations/ru.json @@ -179,6 +179,9 @@ "description-plural": "В этой версии есть {nb} устаревших модов. Хотите их обновить?", "dont-remind-me": "Не напоминать мне", "update": "Обновить" + }, + "third-party-mod-source-not-avaliable": { + "description": "Сторонний источник данных \"{name}\" недоступен. Пожалуйста, переключитесь обратно на BeatMods в настройках и попробуйте снова." } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "Исходный код модуля", + "description": "Выберите источник, отличный от BeatMods.", + "website": "веб-сайт" + }, "patreon": { "title": "Поддержи BSManager 💖", "description": "Поддержи проект, чтобы мы могли дальше улучшать BSManager.", diff --git a/assets/jsons/translations/tl.json b/assets/jsons/translations/tl.json index 0c3731a9..c78d9a1f 100644 --- a/assets/jsons/translations/tl.json +++ b/assets/jsons/translations/tl.json @@ -179,6 +179,9 @@ "description-plural": "Ang bersyon na ito ay may {nb} lipas na mga mod. Gusto mo bang i-update ang mga ito?", "dont-remind-me": "Huwag akong paalalahanan", "update": "I-update" + }, + "third-party-mod-source-not-avaliable": { + "description": "Hindi magagamit ang third-party data source na \"{name}\". Bumalik sa BeatMods sa mga setting at subukang muli." } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "Pinagmulan ng modyul", + "description": "Pumili ng ibang mapagkukunan maliban sa BeatMods.", + "website": "website" + }, "patreon": { "title": "Supportahan ang BSManager 💖", "description": "Suportahan ang proyekto at tulungan kami na magbigay ng patuloy na mga pagdagdag ng feature sa BSManager.", diff --git a/assets/jsons/translations/uk.json b/assets/jsons/translations/uk.json index 967eeead..0074aa3d 100644 --- a/assets/jsons/translations/uk.json +++ b/assets/jsons/translations/uk.json @@ -179,6 +179,9 @@ "description-plural": "Ця версія має {nb} застаріл(-ий/-і/-их) мод(-и/-ів). Ви хочете оновити їх?", "dont-remind-me": "Не нагадувати", "update": "Оновити" + }, + "third-party-mod-source-not-avaliable": { + "description": "Джерело даних стороннього розробника \"{name}\" недоступне. Будь ласка, поверніться до BeatMods у налаштуваннях і спробуйте ще раз." } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "Джерело модуля", + "description": "Виберіть джерело, відмінне від BeatMods.", + "website": "вебсайт" + }, "patreon": { "title": "Підтримайте BSManager 💖", "description": "Підтримайте проєкт і допоможіть нам продовжувати вдосконалювати BSManager.", diff --git a/assets/jsons/translations/zh-tw.json b/assets/jsons/translations/zh-tw.json index 66f2246d..6c962438 100644 --- a/assets/jsons/translations/zh-tw.json +++ b/assets/jsons/translations/zh-tw.json @@ -179,6 +179,9 @@ "description-plural": "此版本有 {nb} 個過時的模組。您想更新它們嗎?", "dont-remind-me": "不要提醒我", "update": "更新" + }, + "third-party-mod-source-not-avaliable": { + "description": "第三方資料來源「{name}」不可用,請在設定中切換回BeatMods再試。" } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "模組來源", + "description": "選擇一個除BeatMods之外的來源", + "website": "網站" + }, "patreon": { "title": "支持 BSManager 💖", "description": "支持該項目並幫助我們持續改進 BSManager。", diff --git a/assets/jsons/translations/zh.json b/assets/jsons/translations/zh.json index 2ab8d74e..fc42e988 100644 --- a/assets/jsons/translations/zh.json +++ b/assets/jsons/translations/zh.json @@ -179,6 +179,9 @@ "description-plural": "此版本有 {nb} 个过时的模组。您想更新它们吗?", "dont-remind-me": "不要提醒我", "update": "更新" + }, + "third-party-mod-source-not-avaliable": { + "description": "第三方数据源“{name}”不可用,请在设置中切换回BeatMods再试。" } }, "drop-zone": { @@ -284,6 +287,11 @@ } } }, + "mod-repos": { + "title": "模组源", + "description": "选择一个除BeatMods之外的源", + "website": "网站" + }, "patreon": { "title": "支持 BSManager 💖", "description": "支持该项目并帮助我们持续改进 BSManager。", diff --git a/src/main/ipcs/bs-mods-ipcs.ts b/src/main/ipcs/bs-mods-ipcs.ts index 476f4c55..f75db92f 100644 --- a/src/main/ipcs/bs-mods-ipcs.ts +++ b/src/main/ipcs/bs-mods-ipcs.ts @@ -39,3 +39,17 @@ ipc.on("bs-mods.beatmods-up", (_, reply) => { const beatMods = BeatModsApiService.getInstance(); reply(from(beatMods.isUp())); }) + +ipc.on("bs-mods.mod-repo.get-repo-list", (_, reply) => { + const beatMods = BeatModsApiService.getInstance(); + reply(from(beatMods.getModRepoList())); +}) +ipc.on("bs-mods.mod-repo.get-name", (_, reply) => { + const beatMods = BeatModsApiService.getInstance(); + reply(from(beatMods.getSelectedModRepoAsync())); +}) + +ipc.on("bs-mods.mod-repo.select-name", (args, reply) => { + const beatMods = BeatModsApiService.getInstance(); + reply(from(beatMods.selectModRepo(args))); +}) \ No newline at end of file diff --git a/src/main/services/mods/beat-mods-api.service.ts b/src/main/services/mods/beat-mods-api.service.ts index 8e63f141..463b8b3e 100644 --- a/src/main/services/mods/beat-mods-api.service.ts +++ b/src/main/services/mods/beat-mods-api.service.ts @@ -3,18 +3,47 @@ import { BbmFullMod, BbmMod, BbmModVersion, BbmPlatform } from "../../../shared/ import { RequestService } from "../request.service"; import { BsStore } from "../../../shared/models/bs-store.enum"; import log from "electron-log" +import { StaticConfigurationService } from "../static-configuration.service"; +import { ModRepo } from "shared/models/mods/repo.model"; export class BeatModsApiService { private static instance: BeatModsApiService; + private readonly staticConfig: StaticConfigurationService; + private readonly requestService: RequestService; - public readonly MODS_REPO_URL = "https://beatmods.com"; - private readonly MODS_REPO_API_URL = `${this.MODS_REPO_URL}/api`; + private static readonly MOD_REPO_LIST:ModRepo[] = [ + { + id: "beatmods", + mods_repo_url: "https://beatmods.com", + mods_repo_api_url: "https://beatmods.com/api", + display_name: "BeatMods", + website: "https://beatmods.com" + }, + { + id: "beatsabercn", + mods_repo_url: "https://beatmods.bsaber.cn", + mods_repo_api_url: "https://beatmods.bsaber.cn/api", + display_name: "CN中文镜像源", + website: "https://beatmods.bsaber.cn/front/mods" + } + ]; + + private selectedModRepo: ModRepo = BeatModsApiService.MOD_REPO_LIST.find(repo => repo.default) || BeatModsApiService.MOD_REPO_LIST[0]; + + public getSelectedModRepo(): ModRepo { + return this.selectedModRepo; + } private readonly versionModsCache = new Map(); private readonly modsHashCache = new Map(); + private resetCache(){ + this.versionModsCache.clear(); + this.modsHashCache.clear(); + } + public static getInstance(): BeatModsApiService { if (!BeatModsApiService.instance) { BeatModsApiService.instance = new BeatModsApiService(); @@ -23,23 +52,49 @@ export class BeatModsApiService { } private constructor() { + this.staticConfig = StaticConfigurationService.getInstance(); this.requestService = RequestService.getInstance(); + + const repoId = this.staticConfig.get("selected-mod-repo"); + if(repoId){ + this.selectedModRepo = BeatModsApiService.MOD_REPO_LIST.find(repo => repo.id === repoId) || BeatModsApiService.MOD_REPO_LIST[0]; + } } public async isUp(): Promise { try { // The data in status can be dropped - await this.requestService.getJSON<{}>(`${this.MODS_REPO_API_URL}/status`); + await this.requestService.getJSON<{}>(`${this.getSelectedModRepo().mods_repo_api_url}/status`); return true; } catch (error) { - log.error("Could not connect to beatmods", error); + log.error(`Could not connect to ${this.selectedModRepo.mods_repo_api_url}`, error); return false; } } private getVersionModsUrl(version: BSVersion): string { const platform: BbmPlatform = version.oculus || version.metadata?.store === BsStore.OCULUS ? BbmPlatform.OculusPC : BbmPlatform.SteamPC; - return `${this.MODS_REPO_API_URL}/mods?status=verified&gameVersion=${version.BSVersion}&gameName=BeatSaber&platform=${platform}`; + return `${this.getSelectedModRepo().mods_repo_api_url}/mods?status=verified&gameVersion=${version.BSVersion}&gameName=BeatSaber&platform=${platform}`; + } + + public async getModRepoList():Promise{ + return BeatModsApiService.MOD_REPO_LIST; + } + + public async getSelectedModRepoAsync():Promise{ + return this.getSelectedModRepo(); + } + public async selectModRepo(repoId:string): Promise{ + const selectedRepo = BeatModsApiService.MOD_REPO_LIST.find(repo => repo.id === repoId); + + if(!selectedRepo){ + return false; + } + + this.selectedModRepo = selectedRepo; + this.staticConfig.set("selected-mod-repo", repoId); + this.resetCache() + return true; } private updateModsHashCache(mods: BbmModVersion[]): void { @@ -76,7 +131,7 @@ export class BeatModsApiService { } return this.requestService.getJSON<{ modVersions: BbmModVersion[] }>( - `${this.MODS_REPO_API_URL}/hashlookup?hash=${hash}` + `${this.getSelectedModRepo().mods_repo_api_url}/hashlookup?hash=${hash}` ).then(({ data }) => { this.updateModsHashCache(data?.modVersions ?? []); return data?.modVersions?.at(0); diff --git a/src/main/services/mods/bs-mods-manager.service.ts b/src/main/services/mods/bs-mods-manager.service.ts index 2562120a..ea2651a3 100644 --- a/src/main/services/mods/bs-mods-manager.service.ts +++ b/src/main/services/mods/bs-mods-manager.service.ts @@ -128,7 +128,7 @@ export class BsModsManagerService { } private async downloadZip(zipUrl: string): Promise { - zipUrl = new URL(zipUrl, this.beatModsApi.MODS_REPO_URL).href; + zipUrl = new URL(zipUrl, this.beatModsApi.getSelectedModRepo().mods_repo_url).href; log.info("Download mod zip", zipUrl); diff --git a/src/main/services/static-configuration.service.ts b/src/main/services/static-configuration.service.ts index 4244f5a2..d91372fa 100644 --- a/src/main/services/static-configuration.service.ts +++ b/src/main/services/static-configuration.service.ts @@ -92,6 +92,7 @@ export interface StaticConfigKeyValues { "use-system-proxy": boolean; "last-version-launched": BSVersion; "auto-update": AutoUpdate; + "selected-mod-repo": string; // Linux Specific static configs "proton-folder": string; 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 6a985fe1..5c9dffbc 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 @@ -23,6 +23,7 @@ import { Dropzone } from "renderer/components/shared/dropzone.component"; import { ModsGridStatus } from "shared/models/mods/mod-ipc.model"; import { BsmLink } from "renderer/components/shared/bsm-link.component"; import { DISCORD_URL, GITHUB_URL } from "shared/constants"; +import { ModRepo } from "shared/models/mods/repo.model"; export type ModsSlideRef = { loadMods: () => Promise; @@ -55,6 +56,8 @@ export const ModsSlide = forwardRef(({ version, isActive, o const downloadRef = useRef(null); const [downloadWith, setDownloadWidth] = useState(0); + const [selectedModRepo, setSelectedModRepo] = useState(null as ModRepo) + const modsToCategoryMap = (mods: BbmFullMod[]): Map => { if (!mods) { return new Map(); @@ -218,6 +221,10 @@ export const ModsSlide = forwardRef(({ version, isActive, o loadMods }), [version]); + useEffect(()=>{ + modsManager.getSelectedModRepo().then(repo=>setSelectedModRepo(repo)); + }, []); + useEffect(() => { let isCancelled = false; @@ -284,6 +291,18 @@ export const ModsSlide = forwardRef(({ version, isActive, o const renderStatus = () => { if (gridStatus === ModsGridStatus.BEATMODS_DOWN) { + if(selectedModRepo && selectedModRepo.id !== "beatmods"){ + return + + { + t("pages.version-viewer.mods.notifications.third-party-mod-source-not-avaliable.description", + {name:selectedModRepo ? selectedModRepo.display_name : "null"} + ) + } + + + } + return {te("pages.version-viewer.mods.status.beatmods-down", {links: (<> diff --git a/src/renderer/pages/settings-page.component.tsx b/src/renderer/pages/settings-page.component.tsx index e6f40f4a..d7b406ac 100644 --- a/src/renderer/pages/settings-page.component.tsx +++ b/src/renderer/pages/settings-page.component.tsx @@ -49,6 +49,8 @@ import { AutoUpdaterService } from "renderer/services/auto-updater.service"; import { OculusDownloaderService } from "renderer/services/bs-version-download/oculus-downloader.service"; import { DISCORD_URL } from "shared/constants"; import { AutoUpdate } from "shared/models/config"; +import { BsModsManagerService } from "renderer/services/bs-mods-manager.service"; +import { ModRepo } from "shared/models/mods/repo.model"; export function SettingsPage() { @@ -69,6 +71,7 @@ export function SettingsPage() { const versionLinker = useService(VersionFolderLinkerService); const staticConfig = useService(StaticConfigurationService); const installationLocationService = useService(InstallationLocationService); + const bsModManagerService = useService(BsModsManagerService); const autoUpdater = useService(AutoUpdaterService); const { firstColor, secondColor } = useThemeColor(); @@ -100,6 +103,8 @@ export function SettingsPage() { const [playlistsDeepLinkEnabled, setPlaylistsDeepLinkEnabled] = useState(false); const [modelsDeepLinkEnabled, setModelsDeepLinkEnabled] = useState(false); const [hasDownloaderSession, setHasDownloaderSession] = useState(false); + const [modRepoList, setModRepoList] = useState([] as ModRepo[]); + const [modRepo, setModRepo] = useState(""); const appVersion = useObservable(() => autoUpdater.getAppVersion()); useEffect(() => { @@ -109,6 +114,15 @@ export function SettingsPage() { playlistsManager.isDeepLinksEnabled().then(enabled => setPlaylistsDeepLinkEnabled(() => enabled)); modelsManager.isDeepLinksEnabled().then(enabled => setModelsDeepLinkEnabled(() => enabled)); + + bsModManagerService.getModRepoList().then(list =>{ + setModRepoList(list); + bsModManagerService.getSelectedModRepo().then(repo => { + setModRepo(repo.id); + }) + }); + + staticConfig.get("proton-folder").then(setProtonFolder); }, []); @@ -157,6 +171,13 @@ export function SettingsPage() { i18nService.setLanguage(item.value); }; + const handleChangeModRepo = (repo: RadioItem) => { + bsModManagerService.selectModRepo(repo.value).then(result=>{ + if(result){ + setModRepo(repo.value) + } + }) + } const setDefaultProtonFolder = async () => { if (!progressBarService.require()) { return; @@ -508,6 +529,17 @@ export function SettingsPage() { + + ({ + id:index, + value: repo.id, + text: repo.display_name, + icon: repo.website ? + linkOpener.open(repo.website, false)} className="px-2 font-bold italic text-sm rounded-md" text="pages.settings.mod-repos.website" withBar={false} /> + : null + }))} selectedItemValue={modRepo} onItemSelected={handleChangeModRepo} /> + +
diff --git a/src/renderer/services/bs-mods-manager.service.ts b/src/renderer/services/bs-mods-manager.service.ts index b1d5cf16..b9c95bf8 100644 --- a/src/renderer/services/bs-mods-manager.service.ts +++ b/src/renderer/services/bs-mods-manager.service.ts @@ -1,4 +1,4 @@ -import { Observable, BehaviorSubject, throwError, of, lastValueFrom } from "rxjs"; +import { Observable, BehaviorSubject, throwError, of, lastValueFrom, from } from "rxjs"; import { catchError, map, tap } from "rxjs/operators"; import { BSVersion } from "shared/bs-version.interface"; import { IpcService } from "./ipc.service"; @@ -10,6 +10,7 @@ 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"; +import { ModRepo } from "shared/models/mods/repo.model"; export class BsModsManagerService { private static instance: BsModsManagerService; @@ -226,4 +227,18 @@ export class BsModsManagerService { return ModsGridStatus.OK; } + public async getModRepoList(): Promise { + return lastValueFrom(this.ipcService.sendV2("bs-mods.mod-repo.get-repo-list")).catch(() => [] as ModRepo[]); + } + + public async getSelectedModRepo(): Promise { + return lastValueFrom(this.ipcService.sendV2("bs-mods.mod-repo.get-name").pipe( + catchError(() => from(this.getModRepoList()).pipe(map(list => list.find(repo => repo.default) || list[0]))) + )); + } + + public async selectModRepo(name:string): Promise { + return lastValueFrom(this.ipcService.sendV2("bs-mods.mod-repo.select-name", name)).catch(() => false); + } + } diff --git a/src/shared/models/ipc/ipc-routes.ts b/src/shared/models/ipc/ipc-routes.ts index 8942761d..5d050b2e 100644 --- a/src/shared/models/ipc/ipc-routes.ts +++ b/src/shared/models/ipc/ipc-routes.ts @@ -22,6 +22,7 @@ import { StaticConfigGetIpcRequestResponse, StaticConfigKeys, StaticConfigSetIpc import { BbmFullMod, BbmModVersion, ExternalMod } from "../mods/mod.interface"; import { OculusDownloadInfo } from "main/services/bs-version-download/bs-oculus-downloader.service"; import { UpdateInfo } from "electron-updater"; +import { ModRepo } from "../mods/repo.model"; export type IpcReplier = (data: Observable) => void; @@ -90,6 +91,9 @@ export interface IpcChannelMapping { "bs-mods.uninstall-mods": { request: { mods: BbmFullMod[]; version: BSVersion }, response: Progression }; "bs-mods.uninstall-all-mods": { request: BSVersion, response: Progression }; "bs-mods.beatmods-up": { request: void, response: boolean }; + "bs-mods.mod-repo.get-repo-list": { request: void, response: ModRepo[]}; + "bs-mods.mod-repo.get-name": { request: void, response: ModRepo}; + "bs-mods.mod-repo.select-name": { request: string, response: boolean}; /* ** bs-playlist-ipcs ** */ "one-click-install-playlist": { request: string, response: Progression }; diff --git a/src/shared/models/mods/repo.model.ts b/src/shared/models/mods/repo.model.ts new file mode 100644 index 00000000..2ff61f05 --- /dev/null +++ b/src/shared/models/mods/repo.model.ts @@ -0,0 +1,8 @@ +export interface ModRepo { + id: string + mods_repo_url: string + mods_repo_api_url: string + display_name: string + website?: string + default?: boolean +}