Compare commits

...

53 Commits

Author SHA1 Message Date
MathieuG-P b2b7002a8e Merge branch 'master' of https://github.com/Zagrios/bs-manager 2023-09-18 14:37:43 +02:00
MathieuG-P 1776f5f769 [chore] update code sign sha 2023-09-18 14:37:40 +02:00
MathieuG-P f17c8a27cc for code sign verification 2023-09-15 17:05:43 +02:00
MathieuG-P 1b8e009a62 bumb to 1.3.1-alpha.1 2023-09-15 16:58:50 +02:00
MathieuG-P 3a44779ade Merge pull request #320 from Zagrios/feature/liv-shortcuts
[feature] Liv shortcuts
2023-09-15 09:51:13 +02:00
MathieuG-P c407997dc2 [feature] remove code smells 2023-09-15 09:44:55 +02:00
MathieuG-P d61c1a519f [feature] remove unused function, and add logs 2023-09-15 09:39:08 +02:00
MathieuG-P 46eb8d065b [feature] Start LIV service on startup 2023-09-14 22:36:59 +02:00
MathieuG-P 9ee036527c [feature] LIV shortcut synchronise with installed BSM versions 2023-09-13 23:41:46 +02:00
MathieuG-P 825b35d164 [feature] create LIV service 2023-09-13 00:14:38 +02:00
MathieuG-P 9de0a4a821 [chore] update deps 2023-09-12 22:38:18 +02:00
MathieuG-P e01fe02c08 Merge pull request #319 from Zagrios/chore/change-default-contents-path
[chore] Change default contents path to avoid OneDrive issues
2023-09-11 22:08:17 +02:00
MathieuG-P 2e376b03fc [chore] fix sonarcloud bug 2023-09-11 21:53:58 +02:00
MathieuG-P 6bdf47678e [chore] Change default contents path to avoid OneDrive issues 2023-09-11 21:49:43 +02:00
Iluhadesu c9bcdc8da6 Add v1.31.1 to bs_versions.json 2023-09-04 13:34:54 +02:00
MathieuG-P 7d21ba5bca add patreon 2023-09-03 17:14:58 +02:00
MathieuG-P 7fb19f46d0 Merge pull request #314 from Zagrios/bugfix/steamvr-not-retored-after-fpfc-mode/313
[bugfix-313] Restore SteamVR shortly after launching BS and on disabl…
2023-08-28 16:45:18 +02:00
MathieuG-P 195bc1ad64 [bugfix-313] remove unused imports 2023-08-28 16:36:31 +02:00
MathieuG-P ccc133cf6d [bugfix-313] Restore SteamVR shortly after launching BS and on disabling FPFC Mode 2023-08-28 16:33:53 +02:00
MathieuG-P 549d4473ab Merge pull request #312 from Zagrios/feature/use-arcviewer/237
[feature-237] use ArcViewer
2023-08-28 00:36:09 +02:00
MathieuG-P 23d7f8ad64 [feature-237] remove unused import 2023-08-28 00:29:56 +02:00
MathieuG-P 3edb3f583b [feature-237] use ArcViewer 2023-08-28 00:25:43 +02:00
MathieuG-P 71a2a01aca [chore] update electron 2023-08-27 23:33:42 +02:00
MathieuG-P e3468fac0a Merge pull request #311 from Zagrios/bugfix/song-not-goes-in-custom-symlink/310
[bugfix] one click install contents not goes in custom symlinks
2023-08-27 20:54:13 +02:00
MathieuG-P 8d2075012b [bugfix] one click install contents not goes in custom symlinks 2023-08-27 20:39:21 +02:00
MathieuG-P f3ed2a8477 Merge pull request #309 from GabiRP/master
Better spanish translations
2023-08-17 13:07:42 +02:00
GabiRP 5355f84bc6 better spanish translations 2023-08-16 21:11:26 +02:00
MathieuG-P 6758e5937e Merge pull request #308 from Zagrios/chore/no-need-to-delete-cetrificateSha1-in-packagejson-to-test-a-build
[chore] no need to delete "certificateSha1" in package.json to run "npm run package" when don't have certificate
2023-08-14 19:04:18 +02:00
MathieuG-P de2d38bd45 [chore] no need to delete "certificateSha1" in package.json to run "npm run package" when don't have certificate 2023-08-14 19:00:54 +02:00
MathieuG-P 7b8c98e809 Merge pull request #307 from Zagrios/bugfix/installing-version-disappear-on-uninstall-another/304
[bugfix] On uninstalling a version, downloading version disappears
2023-08-14 16:21:05 +02:00
MathieuG-P bda7c6719a Merge pull request #303 from slinkstr/chore/registered-typo
typo: isDeepLinkRegistred -> isDeepLinkRegistered
2023-08-14 16:07:27 +02:00
MathieuG-P 254047e99e remove useless import 2023-08-14 16:03:42 +02:00
MathieuG-P 578f2ec335 [bugfix] On uninstalling a version, downloading version disappears 2023-08-14 16:00:05 +02:00
MathieuG-P 8cc5449818 Merge pull request #305 from Zagrios/chore/update-packages
Chore/update packages
2023-08-13 20:42:19 +02:00
MathieuG-P 323e666d5a [chore] update semver 2023-08-13 20:40:00 +02:00
MathieuG-P cbe6cb06c0 [chore] update framer-motion 2023-08-13 20:33:48 +02:00
MathieuG-P 3e36321ba5 [chore] update dot-prop 2023-08-13 20:30:27 +02:00
MathieuG-P c9677b1224 [chore] update electron 2023-08-13 20:26:58 +02:00
MathieuG-P e6387b45c5 Add patreon 2023-08-12 12:37:24 +02:00
slinky 8b4a5f15e7 typo: isDeepLinkRegistred -> isDeepLinkRegistered 2023-08-11 20:04:46 -07:00
MathieuG-P 4b741ead15 bumb to 1.3.0 2023-08-10 19:02:14 +02:00
MathieuG-P de03044ff9 remove diamond rank 2023-08-10 18:52:43 +02:00
MathieuG-P b3a3955f69 [hotfix] useless word in EN translation 2023-08-10 18:51:40 +02:00
MathieuG-P f5c83ee9ca bumb to 1.3.0-alpha.6 2023-08-10 01:31:42 +02:00
MathieuG-P e1546d0975 Merge pull request #301 from Zagrios/chore/add-logs-for-depotdownloader-events
[chore] add logs for depotdownloader events
2023-08-10 01:26:09 +02:00
MathieuG-P d69ecac496 [chore] add logs for depotdownloader events 2023-08-10 01:19:06 +02:00
MathieuG-P 8f1a2015bd Merge pull request #300 from Zagrios/bugfix/change-token-rejected-translation
[bugfix] change error message for TokenReject error from DepotDownloader
2023-08-10 00:40:22 +02:00
MathieuG-P 3e4afe5a07 [bugfix] change error message for TokenReject error from DepotDownloader 2023-08-10 00:34:44 +02:00
MathieuG-P 288c219417 Merge pull request #297 from Insprill/fix/depot-downloader-linux
Fix Depot Downloader not working on Linux
2023-08-09 23:50:45 +02:00
Pierce Thompson 31db079b08 Fix process command/args 2023-08-09 17:16:15 -04:00
MathieuG-P 5e1eff7143 Merge pull request #299 from Zagrios/bugfix/fix-focus-outside-element-with-tabs/298
[bugfix-298] fix focus outside element with tab key
2023-08-09 23:01:39 +02:00
MathieuG-P 301d2fdfc4 [bugfix-298] fix focus outside element with tab key 2023-08-09 22:46:10 +02:00
Pierce Thompson 9638c65407 Fix Depot Downloader not working on Linux 2023-08-08 23:51:38 -04:00
40 changed files with 739 additions and 433 deletions
+1 -1
View File
@@ -218,7 +218,7 @@ https://user-images.githubusercontent.com/40648115/213435051-7feb815d-f32b-4135-
<div>
<h1><b>Credits</b></h1>
<ul>
<li><a href="https://github.com/Zagrios">Zagrios</a> - Founder & Lead Developer</li>
<li><a href="https://github.com/Zagrios">Zagrios</a> - Founder & Lead Developer (Mathieu GRIES)</li>
<li><a href="https://github.com/Iluhadesu">Iluhadesu</a> - Project Team & Developpement help</li>
<li><a href="https://github.com/GaetanGrd">GaetanGrd</a> - Project Team & Developpement help</li>
<li><a href="https://github.com/cheddZy">cheddZy</a> - Icon creator</li>
+8
View File
@@ -565,5 +565,13 @@
"ReleaseImg": "https://clan.cloudflare.steamstatic.com/images/32055887/28993aecc56a75c52295fa07620f58cb0e4b09e8.png",
"ReleaseDate": "1688050646",
"year": "2023"
},
{
"BSVersion": "1.31.1",
"BSManifest": "5239818041644201119",
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/3664295677895178184",
"ReleaseImg": "https://clan.akamai.steamstatic.com/images/32055887/58621b3cb8bf42fcfbf3b97fe47aa91b290eea04.png",
"ReleaseDate": "1693824747",
"year": "2023"
}
]
+4 -2
View File
@@ -1,6 +1,6 @@
[
{"username": "Shidorien"},
{"username": "iPixelGalaxy", "type": "diamond", "link": "https://twitch.tv/ipixelgalaxy"},
{"username": "iPixelGalaxy"},
{"username": "Emyte", "type": "gold"},
{"username": "GoodOldNervy"},
{"username": "Naysy"},
@@ -15,5 +15,7 @@
{"username": "Ilnahro"},
{"username": "T3chLog"},
{"username": "Phil", "type": "gold"},
{"username": "Protocrush", "type": "gold"}
{"username": "Protocrush", "type": "gold"},
{"username": "ServerMensch", "type": "gold"},
{"username": "policepigou"}
]
+1 -1
View File
@@ -248,7 +248,7 @@
"ConnectionError": "Kann nach 10 Versuchen keine Verbindung zu Steam herstellen 🤯",
"LicenceError": "Die Liste der Lizenzen kann nicht abgerufen werden.",
"RateLimitExceeded": "Du hast es zu oft versucht, warte eine Weile und versuche es später erneut.",
"TokenRejected": "BeatSaber kann nicht heruntergeladen werden 😥 versuche es später noch einmal 😕",
"TokenRejected": "Ihr Anmeldetoken wurde abgelehnt 😕 Bitte versuchen Sie es erneut.",
"AccessDenied": "Der Zugang zu Steam wurde verweigert.",
"dotnet-required": ".NET 6 Runtime muss installiert sein, um eine Version von BeatSaber herunterzuladen. Lade es herunter, indem Du auf die Schaltfläche unten klickst."
},
+2 -2
View File
@@ -248,7 +248,7 @@
"ConnectionError": "Unable to connect to Steam after 10 tries 🤯",
"LicenceError": "Unable to get the list of licenses.",
"RateLimitExceeded": "You've tried too many times, wait a while and try again later.",
"TokenRejected": "Unable to download Beat Saber 😥 try again later 😕",
"TokenRejected": "Your login token has been rejected 😕 Please try again.",
"AccessDenied": "Access to Steam has been denied.",
"dotnet-required": ".NET 6 Runtime must be installed in order to download a version of Beat Saber. Download it by clicking the button below."
},
@@ -496,7 +496,7 @@
"note":{
"use-the":"Use the ",
"steam-mobile-app": "Steam Mobile App",
"to-connect-with-qr": "to sign in with via QR code."
"to-connect-with-qr": "to sign in via QR code."
}
},
"stay": "Remember me"
+87 -87
View File
@@ -3,7 +3,7 @@
"download": "Descargar",
"add": "Añadir",
"verify": "Verificar",
"launch": "Lanzar",
"launch": "Iniciar",
"mods": "Mods",
"maps": "Mapas",
"playlists": "Playlists",
@@ -30,20 +30,20 @@
},
"version-viewer": {
"launch-mods": {
"oculus": "Oculus Mod",
"oculus": "Modo Oculus",
"oculus-description": "Si estás usando Beat Saber a través de Steam, te permite usar el compositor VR de Oculus sin pasar por SteamVR, para ganar prestaciones. Esto no es necesario para usar auriculares Oculus.",
"desktop": "FPFC Mod",
"desktop-description": "Esto te permite usar WASD y el mouse para navegar por el menú en juego. Esto hace que las pruebas sean mucho más fáciles, ¡porque no tienes que ponerte el auricular!",
"debug": "Debug Mod",
"desktop": "Modo FPFC",
"desktop-description": "El modo FPFC te permite usar WASD y el mouse para navegar por el menú en juego. Esto hace que las pruebas sean mucho más fáciles, ¡porque no tienes que ponerte las gafas VR!",
"debug": "Modo Depuración",
"debug-description": "Habilita la ventana de registro de salida para IPA. Esto mostrará la consola de depuración que usan los mods.",
"advanced-launch": {
"button": "Lanzamiento avanzado",
"button": "Opciones avanzadas",
"placeholder": "Argumentos adicionales ej: --revert; --no-wait"
}
},
"maps": {
"search-bar": {
"search-placeholder": "Buscar en un mapa",
"search-placeholder": "Buscar un mapa",
"filters-btn": "Filtros",
"dropdown": {
"export-maps": "Exportar mapas",
@@ -101,8 +101,8 @@
}
},
"available-versions": {
"title": "Seleccione una versión",
"steam-release": "Publicación Página",
"title": "Selecciona una versión",
"steam-release": "Anuncio en Steam",
"dropdown": {
"refresh": "Actualizar la lista",
"import-version": "Importar una versión"
@@ -111,12 +111,12 @@
"settings": {
"steam": {
"title": "Steam",
"description": "Si sales de Steam, tendrás que volver a entrar para descargar una nueva versión de Beat Saber.",
"logout": "Desconectar"
"description": "Si desconectas tu cuenta de Steam, tendrás que volver a conectarla para descargar una nueva versión de Beat Saber.",
"logout": "Cerrar sesión"
},
"appearance": {
"title": "Apariencia",
"description": "Elija los dos colores principales de BSManager.",
"description": "Elige los dos colores principales de BSManager.",
"reset": "Reiniciar",
"sub-title": "Tema",
"themes": {
@@ -127,12 +127,12 @@
},
"installation-folder": {
"title": "Carpeta de instalación",
"description": "Cambia la carpeta por defecto para las versiones de Beat Saber y otras características próximas.",
"choose-folder": "Elija la carpeta"
"description": "Cambia la carpeta por defecto para las versiones de Beat Saber y próximas funciones.",
"choose-folder": "Elige la carpeta"
},
"additional-content": {
"title": "Contenido adicional",
"description": El contenido adicional te permite personalizar BeatSaber!",
"description": Contenido adicional que te permite personalizar Beat Saber!",
"deep-links": {
"sub-title": "Instalaciones OneClick"
}
@@ -158,23 +158,23 @@
}
},
"patreon": {
"title": "Apoyo BSManager 💖",
"description": "Apoye el proyecto y ayúdenos a proporcionar mejoras continuas a BSManager.",
"title": "Apoya BSManager 💖",
"description": "Apoya el proyecto y ayúdanos a proporcionar mejoras continuas a BSManager.",
"buttons": {
"support": "Apoyo BSManager 🥰",
"supporters": "Apoyos 👀"
"support": "Apoya BSManager 🥰",
"supporters": "Donadores 👀"
},
"view": {
"no-supporters": "Todavía no hay apoyos",
"no-supporters": "Todavía no hay donadores",
"sponsors": "Patrocinadores",
"supporters": "Apoyos"
"supporters": "Donadores"
}
},
"discord": {
"description": "¡Únete a la comunidad de BSManager siguiéndonos en nuestras redes sociales!"
},
"contribution": {
"description": "¡Sugiera nuevas características o reporte un error para ayudar a mejorar BSManager!",
"description": "¡Sugiere nuevas características o reporta un error para ayudar a mejorar BSManager!",
"buttons": {
"request-features": "Proponer una funcionalidad",
"report-bug": "Informar de un error",
@@ -201,7 +201,7 @@
"no-internet": "Sin internet"
},
"msg": {
"operation-running": "Espere a que termine la operación actual y vuelva a empezar.",
"operation-running": "Espera a que termine la operación actual y vuelve a empezar.",
"no-internet": "Comprueba tu conexión a Internet e inténtalo de nuevo."
}
}
@@ -209,16 +209,16 @@
"bs-download": {
"success": {
"titles": {
"download-success": "Descargar completo",
"verification-finished": "Verificación completa"
"download-success": "Descarga completada",
"verification-finished": "Verificación completada"
}
},
"warnings": {
"msg": {
"ManifestChecksum": "El manifiesto descargado anteriormente no coincide con el nuevo 🤔",
"ConnectionTimeout": "Su conexión a Internet parece inestable 🥶",
"ConnectionLost": "Se ha perdido la conexión, inténtelo de nuevo...",
"ConnectionError": "No se puede conectar a Steam, reintentar...",
"ConnectionTimeout": "Tu conexión a Internet parece inestable 🥶",
"ConnectionLost": "Se ha perdido la conexión, inténtalo de nuevo...",
"ConnectionError": "No se puede conectar a Steam, reintentando...",
"Unknown": "Algo extraño ha ocurrido 🤔 Tu conexión es probablemente inestable."
}
},
@@ -227,29 +227,29 @@
"dotnet-required": ".NET 6 Requerido"
},
"msg": {
"401": "Parece que Steam no quiere dejarnos descargar BeatSaber 😢",
"401": "Parece que Steam no quiere dejarnos descargar Beat Saber 😢",
"404": "No se puede contactar con los servidores de Steam",
"Password": "La contraseña es inválida.",
"InvalidCredentials": "Credenciales de inicio de sesión inválidas, conexión no aprobada, o demasiados intentos de inicio de sesión.",
"InvalidCredentials": "Credenciales de inicio de sesión inválidas, conexión no aprobada o demasiados intentos de inicio de sesión.",
"NoManifest": "No se ha encontrado el manifiesto",
"DirectoryCreate": "No se pueden instalar las carpetas necesarias.",
"NotAvailableApp": "¿Intentas descargar BeatSaber cuando no lo tienes? 🤣",
"DepotNotFound": "No se puede descargar BeatSaber 😥 inténtalo más tarde 😕",
"NotAvailableApp": "¿Intentas descargar Beat Saber cuando no lo tienes? 🤣",
"DepotNotFound": "No se puede descargar Beat Saber 😥 inténtalo más tarde 😕",
"NotCompleted": "La descarga no pudo completarse ¯\\_(ツ)_/¯",
"InvalidManifest": "No se puede descargar BeatSaber 😥 inténtalo más tarde 😕",
"NoValidKey": "No se puede descargar BeatSaber 😥 inténtalo más tarde 😕",
"NoManifestCode": "No se puede descargar BeatSaber 😥 inténtalo más tarde 😕",
"InvalidManifest": "No se puede descargar Beat Saber 😥 inténtalo más tarde 😕",
"NoValidKey": "No se puede descargar Beat Saber 😥 inténtalo más tarde 😕",
"NoManifestCode": "No se puede descargar Beat Saber 😥 inténtalo más tarde 😕",
"Unknown": "Se ha producido un error desconocido ¯\\_(ツ)_/¯",
"NoServer": "No se puede contactar con los servidores de Steam.",
"NotAllowed": "Aparentemente no tienes permiso para descargar BeatSaber 🥱",
"NotAllowed": "Aparentemente no tienes permiso para descargar Beat Saber 🥱",
"ConnectionTimeout": "No se puede conectar a Steam 😕",
"SteamLib": "Si tienes este error, reporta el bug en GitHub con los logs por favor.",
"SteamLib": "Si tienes este error, reporta el bug en GitHub con los logs, por favor.",
"ConnectionError": "No se puede conectar a Steam después de 10 intentos 🤯",
"LicenceError": "No se puede obtener la lista de licencias.",
"RateLimitExceeded": "Lo has intentado demasiadas veces, espera un poco y vuelve a intentarlo más tarde.",
"TokenRejected": "No se puede descargar BeatSaber 😥 inténtalo más tarde 😕",
"TokenRejected": "Tu token de inicio de sesión ha sido rechazada 😕 Por favor, inténtalo de nuevo.",
"AccessDenied": "El acceso a Steam ha sido denegado.",
"dotnet-required": "Se debe instalar el tiempo de ejecución de .NET 6 para descargar una versión de BeatSaber. Descárguelo haciendo clic en el botón de abajo."
"dotnet-required": "Se debe instalar el tiempo de ejecución de .NET 6 para descargar una versión de Beat Saber. Descárgalo haciendo clic en el botón de abajo."
},
"actions": {
"download-dotnet": "Descargar .NET 6"
@@ -260,7 +260,7 @@
"success": {
"start-import": {
"title": "Importación en curso 👌",
"desc": "La importación puede tardar varios minutos dependiendo de su configuración."
"desc": "La importación puede tardar varios minutos dependiendo de tu configuración."
},
"imported": {
"title": "Versión importada 🎉"
@@ -268,7 +268,7 @@
},
"errors": {
"import-error": {
"desc": "Compruebe que la carpeta seleccionada es una instalación de BeatSaber."
"desc": "Comprueba que la carpeta seleccionada es una instalación de Beat Saber."
}
}
},
@@ -277,10 +277,10 @@
"success": {
"titles": {
"transfer-started": "Transferencia en curso",
"transfer-finished": "Transferencia completa"
"transfer-finished": "Transferencia completada"
},
"descs": {
"transfer-started": "La transferencia ha comenzado y puede tomar varios minutos dependiendo de su configuración."
"transfer-started": "La transferencia ha comenzado y puede tomar varios minutos dependiendo de tu configuración."
}
},
"errors": {
@@ -289,7 +289,7 @@
},
"descs": {
"COPY_TO_SUBPATH": "La carpeta de destino no puede ser una subcarpeta de la carpeta de origen.",
"restore-linked-folders": "Se produjo un error al restaurar las carpetas compartidas. Aún puede restaurarlas manualmente a través del menú 'Carpetas compartidas' en la página de versiones."
"restore-linked-folders": "Se produjo un error al restaurar las carpetas compartidas. Aún puedes restaurarlas manualmente a través del menú 'Carpetas compartidas' en la página de versiones."
}
}
},
@@ -318,12 +318,12 @@
"description": "Las instalaciones OneClick han sido desactivadas."
},
"error": {
"description": "Ocurrió un error desconocido."
"description": "Ha ocurrido un error desconocido."
}
},
"check-all-enabled": {
"title": "OneClick deshabilitado",
"description": "Una o más instalaciones de OneClick están deshabilitadas. Vaya a la configuración para habilitarlas.",
"description": "Una o más instalaciones de OneClick están deshabilitadas. Ve a la configuración para habilitarlas.",
"actions": {
"settings": "Ajustes",
"not-remind": "No volver a recordarme"
@@ -339,26 +339,26 @@
"STEAM_LAUNCHING": "¡Steam se está iniciando!"
},
"msg": {
"BS_LAUNCHING": "No olvides calentarte 😉",
"STEAM_LAUNCHING": "Beat Saber se lanzará automáticamente después de Steam."
"BS_LAUNCHING": "No olvides calentar 😉",
"STEAM_LAUNCHING": "Beat Saber se iniciará automáticamente después de Steam."
}
},
"errors": {
"titles": {
"UNKNOWN_ERROR": "No se puede lanzar",
"UNKNOWN_ERROR": "No se puede iniciar",
"STEAM_NOT_RUNNING": "Steam no funciona",
"OCULUS_NOT_RUNNING": "Oculus no funciona",
"BS_ALREADY_RUNNING": "BeatSaber ya está en marcha",
"EXE_NOT_FINDED": "Archivos perdidos",
"BS_ALREADY_RUNNING": "Beat Saber ya está en marcha",
"EXE_NOT_FINDED": "Archivos no encontrados",
"EXIT": "Parada abrupta"
},
"msg": {
"UNKNOWN_ERROR": "Se ha producido un error desconocido.",
"STEAM_NOT_RUNNING": "Para iniciar BeatSaber es necesario que Steam esté en funcionamiento.",
"OCULUS_NOT_RUNNING": "Oculus debe estar funcionando para lanzar BeatSaber.",
"BS_ALREADY_RUNNING": "Cierra BeatSaber antes de volver a lanzarlo.",
"EXE_NOT_FINDED": "Parece que faltan algunos archivos, intente verificar los archivos.",
"EXIT": "BeatSaber se detuvo abruptamente, trata de revisar los archivos."
"STEAM_NOT_RUNNING": "Para iniciar Beat Saber es necesario que Steam esté en funcionamiento.",
"OCULUS_NOT_RUNNING": "Oculus debe estar funcionando para iniciar Beat Saber.",
"BS_ALREADY_RUNNING": "Cierra Beat Saber antes de volver a iniciarlo.",
"EXE_NOT_FINDED": "Parece que faltan algunos archivos, intenta verificar los archivos.",
"EXIT": "Beat Saber se detuvo abruptamente, trata de verificar los archivos."
},
"actions": {
"STEAM_NOT_RUNNING": "Iniciar Steam"
@@ -368,14 +368,14 @@
"steam": {
"steam-launching": {
"title": "¡Steam se está iniciando!",
"description": "Beat Saber se lanzará automáticamente después de Steam."
"description": "Beat Saber se iniciará automáticamente después de Steam."
}
},
"custom-version": {
"errors": {
"titles": {
"CantEditSteam": "Imposible editar",
"CantRename": "El renombramiento es imposible",
"CantRename": "Cambio de nombre imposible",
"VersionAlreadExist": "Esta versión ya existe",
"CantClone": "Clonación imposible"
},
@@ -399,7 +399,7 @@
"success": "Todos los mods han sido instalados.",
"warning": "No se han podido instalar uno o más mods.",
"errors": {
"no-mods": "No hay que instalar mods.",
"no-mods": "No hay mods para instalar.",
"cannot-install-bsipa": "La instalación de BSIPA falló 😨"
}
}
@@ -421,7 +421,7 @@
"msg": {
"success": "Todos los mods han sido desinstalados.",
"errors": {
"no-mods": "No se instala ningún mod en esta versión 😑"
"no-mods": "No hay mods instalados en esta versión 😑"
}
}
}
@@ -448,7 +448,7 @@
"info": {
"userdata-backup-created": {
"title": "Backup creado",
"msg": "Compartir la carpeta 'UserData' puede generar errores, en caso de problemas desvincular la carpeta para restaurar la copia de seguridad"
"msg": "Compartir la carpeta 'UserData' puede generar errores, en caso de problemas desvincula la carpeta para restaurar la copia de seguridad"
}
}
},
@@ -470,19 +470,19 @@
"title": "Steam Guard",
"inputs": {
"guard-code": {
"label": "Guard Código",
"label": "Código Guard",
"placeholder": "Introduzca su código Guard"
}
},
"buttons": {
"submit": "Conéctate"
"submit": "Conectar"
}
},
"steam-login": {
"title": "Inicio de sesión Steam",
"inputs": {
"username": {
"label": "Iniciar sesión con un nombre de cuenta",
"label": "Inicia sesión con un nombre de cuenta",
"placeholder": "Introduce tu nombre de cuenta"
},
"password": {
@@ -514,19 +514,19 @@
},
"steam-credentials": {
"title": "Steam Credentials",
"p-1": "Las credenciales sólo se utilizan para descargar el juego porque steam necesita verificar que has pagado el juego para que se te permita descargarlo. No se guardan y se pasan directamente a DepotDownloader. Si no quieres introducir tus credenciales puedes seguir este tutorial :",
"p-1": "Las credenciales sólo se utilizan para descargar el juego porque steam necesita verificar que has pagado el juego para permitirte descargarlo. No se guardan y se pasan directamente a DepotDownloader. Si no quieres introducir tus credenciales puedes seguir este tutorial :",
"p-2": "y, a continuación, haga clic en el icono de engranaje en la esquina superior derecha y seleccione \"Importar una versión\", seleccione la carpeta donde se ha descargado beat saber (Si usted sigue el tutorial anterior debe tener la ubicación correcta)"
},
"bs-import-version": {
"title": "Importar una versión",
"description": "Importa una versión de BeatSaber para usar con BSManager. La importación copiará la carpeta de instalación seleccionada de BeatSaber en la carpeta de versiones de BSManager.",
"description": "Importa una versión de Beat Saber para usar con BSManager. La importación copiará la carpeta de instalación seleccionada de Beat Saber en la carpeta de versiones de BSManager.",
"buttons": {
"submit": "Importar una versión"
}
},
"bs-uninstall": {
"title": "Desinstalar",
"description": "¿Estás seguro de que quieres desinstalar BeatSaber {version}? Tendrás que descargarlo de nuevo para poder jugar.",
"description": "¿Estás seguro de que quieres desinstalar Beat Saber {version}? Tendrás que descargarlo de nuevo para poder jugar.",
"buttons": {
"submit": "Desinstalar"
}
@@ -546,7 +546,7 @@
},
"clone-version": {
"title": "Versión clonada",
"description": "La clonación de la versión le permite separar el contenido adicional de BeatSaber entre dos versiones.",
"description": "La clonación de la versión te permite separar el contenido adicional de Beat Saber entre dos versiones.",
"inputs": {
"name": {
"label": "Nombre",
@@ -602,7 +602,7 @@
},
"unlink-maps": {
"title": "Desvincular mapas",
"desc": "Tenga en cuenta que desvincular mapas no permitirá el uso de mapas compartidos para esta versión.",
"desc": "Ten en cuenta que desvincular mapas no permitirá el uso de mapas compartidos para esta versión.",
"keep-maps": {
"label": "Mantener mapas",
"title": "Mantener los mapas creará una copia de los mapas compartidos para la versión actual. De lo contrario, no se mantendrá ningún mapa para esta versión."
@@ -611,7 +611,7 @@
}
},
"download-maps": {
"search-btn": "buscar",
"search-btn": "Buscar",
"loading-maps": "Cargando mapas...",
"no-maps-found": "No se encontraron mapas",
"no-internet": "Sin internet"
@@ -626,7 +626,7 @@
},
"shared-folders": {
"title": "Carpetas Compartidas",
"description": "Enlace las carpetas de BeatSaber para sincronizar su contenido con las carpetas compartidas en otras versiones. Tenga en cuenta que la eliminación de contenido también se compartirá.",
"description": "Enlaza las carpetas de Beat Saber para sincronizar su contenido con las carpetas compartidas en otras versiones. Tenga en cuenta que la eliminación de contenido también se compartirá.",
"buttons": {
"add-folder": "Añadir Carpeta",
"link-folder": "Enlazar Carpeta",
@@ -656,7 +656,7 @@
"dancestyle": "baile",
"fitness": "fitness",
"speed": "speed",
"tech": "tec"
"tech": "tech"
},
"map-styles": {
"dance": "baile",
@@ -813,14 +813,14 @@
"valid-btn": "Vincular plataformas"
},
"bloq": {
"title": "Vincular bloqs",
"desc": "La vinculación de bloqs permite compartir bloqs entre todas las versiones. Una vez vinculada, esta versión se beneficiará de los bloqs compartidos",
"info": "La adición y eliminación de bloqs también se compartirá",
"title": "Vincular bloques",
"desc": "La vinculación de bloques permite compartir bloques entre todas las versiones. Una vez vinculada, esta versión se beneficiará de los bloques compartidos",
"info": "La adición y eliminación de bloques también se compartirá",
"keep-models": {
"label": "Conservar los bloqs",
"title": "Conservar los bloqs moverá los bloqs de la versión actual a la carpeta de bloqs compartidos. De lo contrario, se perderán"
"label": "Conservar los bloques",
"title": "Conservar los bloques moverá los bloques de la versión actual a la carpeta de bloques compartidos. De lo contrario, se perderán"
},
"valid-btn": "Vincular bloqs"
"valid-btn": "Vincular bloques"
}
},
"unlink-models": {
@@ -852,26 +852,26 @@
"valid-btn": "Desvincular plataformas"
},
"bloq": {
"title": "Desvincular bloqs",
"desc": "Atención, desvincular los bloqs ya no permitirá el uso de bloqs compartidos para esta versión.",
"title": "Desvincular bloques",
"desc": "Atención, desvincular los bloques ya no permitirá el uso de bloques compartidos para esta versión.",
"keep-models": {
"label": "Conservar los bloqs",
"title": "Conservar los bloqs creará una copia de los bloqs compartidos para la versión actual. En caso contrario, ningún bloq se conservará para esta versión."
"label": "Conservar los bloques",
"title": "Conservar los bloques creará una copia de los bloques compartidos para la versión actual. En caso contrario, ningún bloques se conservará para esta versión."
},
"valid-btn": "Desvincular bloqs"
"valid-btn": "Desvincular bloques"
}
}
},
"notifications": {
"prevent-for-mods": {
"title": "Mods necesarios",
"desc": "Asegúrate de haber instalado los mods necesarios para usar modelos en BeatSaber",
"desc": "Asegúrate de haber instalado los mods necesarios para usar modelos en Beat Saber",
"go-to-mods": "Ir a mods",
"not-remind": "No volver a recordarme"
},
"prevent-for-models-breaks": {
"title": "Modelos rotos",
"desc": "Desde la actualización del motor de BeatSaber, los modelos ya no son funcionales para esta versión."
"desc": "Desde la actualización del motor de Beat Saber, los modelos ya no son funcionales para esta versión."
},
"export-success": {
"title": "Exportación completada 🎉"
@@ -887,8 +887,8 @@
}
},
"auto-update": {
"checking": "Comprobar las actualizaciones",
"downloading": "Descargar actualizaciones"
"checking": "Comprobando actualizaciones",
"downloading": "Descargando actualizaciones"
},
"bs-shortcut-launch": {
"beat-saber-launching": "Iniciando Beat Saber",
+1 -1
View File
@@ -244,7 +244,7 @@
"ConnectionError": "Impossible de se connecter à Steam après 10 essais 🤯",
"LicenceError": "Impossible d'obtenir la liste des licences.",
"RateLimitExceeded": "Tu as essayé trop de fois attends un peu et recommence plus tard.",
"TokenRejected": "Impossible de télécharger Beat Saber 😥 réessaye plus tard 😕",
"TokenRejected": "Votre token de connexion a été rejeté 😕 Veuillez réessayer.",
"AccessDenied": "L'accès à Steam a été refusé.",
"dotnet-required": ".NET 6 Runtime doit être installé pour pouvoir télécharger une version de Beat Saber. Télécharge-le en cliquant sur le bouton ci-dessous."
},
+1 -1
View File
@@ -248,7 +248,7 @@
"ConnectionError": "Не удалось подключиться к Steam за 10 попыток 🤯",
"LicenceError": "Не удалось проверить наличие лицензии.",
"RateLimitExceeded": "Слишком много попыток, вернитесь позже и попробуйте снова.",
"TokenRejected": "Не удалось скачать Beat Saber 😥 повторите попытку позже 😕",
"TokenRejected": "Ваш токен для входа был отклонен 😕 Пожалуйста, попробуйте снова.",
"AccessDenied": "Доступ к Steam был отклонен.",
"dotnet-required": "Среда запуска .NET 6 должна быть установлена, чтобы скачать Beat Saber. Скачайте её с помощью кнопки ниже."
},
+227 -195
View File
@@ -10,16 +10,16 @@
"dependencies": {
"@node-steam/vdf": "^2.2.0",
"@tippyjs/react": "^4.2.6",
"archiver": "^5.3.1",
"archiver": "^6.0.1",
"color": "^4.2.3",
"dateformat": "^5.0.3",
"dot-prop": "^8.0.0",
"dot-prop": "^8.0.2",
"electron-debug": "^3.2.0",
"electron-log": "^4.4.8",
"electron-store": "^8.1.0",
"electron-updater": "^6.1.4",
"fast-deep-equal": "^3.1.3",
"framer-motion": "^10.12.16",
"framer-motion": "^10.16.4",
"fs-extra": "^11.1.1",
"history": "^5.3.0",
"jszip": "^3.10.1",
@@ -40,7 +40,7 @@
"rfdc": "^1.3.0",
"rxjs": "^7.8.0",
"sanitize-filename": "^1.6.3",
"semver": "^7.5.1",
"semver": "^7.5.4",
"striptags": "^4.0.0-alpha.4",
"tailwind-scrollbar-hide": "^1.1.7",
"tailwindcss-scoped-groups": "^2.0.0",
@@ -84,7 +84,7 @@
"css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^4.1.0",
"detect-port": "^1.3.0",
"electron": "^25.3.0",
"electron": "^26.2.1",
"electron-builder": "^24.6.3",
"electron-devtools-installer": "^3.2.0",
"electron-notarize": "^1.2.1",
@@ -3881,54 +3881,73 @@
"dev": true
},
"node_modules/archiver": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz",
"integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/archiver/-/archiver-6.0.1.tgz",
"integrity": "sha512-CXGy4poOLBKptiZH//VlWdFuUC1RESbdZjGjILwBuZ73P7WkAUN0htfSfBq/7k6FRFlpu7bg4JOkj1vU9G6jcQ==",
"dependencies": {
"archiver-utils": "^2.1.0",
"async": "^3.2.3",
"archiver-utils": "^4.0.1",
"async": "^3.2.4",
"buffer-crc32": "^0.2.1",
"readable-stream": "^3.6.0",
"readdir-glob": "^1.0.0",
"tar-stream": "^2.2.0",
"zip-stream": "^4.1.0"
"readdir-glob": "^1.1.2",
"tar-stream": "^3.0.0",
"zip-stream": "^5.0.1"
},
"engines": {
"node": ">= 10"
"node": ">= 12.0.0"
}
},
"node_modules/archiver-utils": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz",
"integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-4.0.1.tgz",
"integrity": "sha512-Q4Q99idbvzmgCTEAAhi32BkOyq8iVI5EwdO0PmBDSGIzzjYNdcFn7Q7k3OzbLy4kLUPXfJtG6fO2RjftXbobBg==",
"dependencies": {
"glob": "^7.1.4",
"glob": "^8.0.0",
"graceful-fs": "^4.2.0",
"lazystream": "^1.0.0",
"lodash.defaults": "^4.2.0",
"lodash.difference": "^4.5.0",
"lodash.flatten": "^4.4.0",
"lodash.isplainobject": "^4.0.6",
"lodash.union": "^4.6.0",
"lodash": "^4.17.15",
"normalize-path": "^3.0.0",
"readable-stream": "^2.0.0"
"readable-stream": "^3.6.0"
},
"engines": {
"node": ">= 6"
"node": ">= 12.0.0"
}
},
"node_modules/archiver-utils/node_modules/readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"node_modules/archiver-utils/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
"balanced-match": "^1.0.0"
}
},
"node_modules/archiver-utils/node_modules/glob": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^5.0.1",
"once": "^1.3.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/archiver-utils/node_modules/minimatch": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=10"
}
},
"node_modules/are-we-there-yet": {
@@ -4209,6 +4228,11 @@
"integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==",
"dev": true
},
"node_modules/b4a": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz",
"integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw=="
},
"node_modules/babel-jest": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz",
@@ -4335,6 +4359,7 @@
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"dev": true,
"funding": [
{
"type": "github",
@@ -4393,6 +4418,7 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"dev": true,
"dependencies": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
@@ -4592,6 +4618,7 @@
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"dev": true,
"funding": [
{
"type": "github",
@@ -5272,17 +5299,17 @@
}
},
"node_modules/compress-commons": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz",
"integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-5.0.1.tgz",
"integrity": "sha512-MPh//1cERdLtqwO3pOFLeXtpuai0Y2WCd5AhtKxznqM7WtaMYaOEMSgn45d9D10sIHSfIKE603HlOp8OPGrvag==",
"dependencies": {
"buffer-crc32": "^0.2.13",
"crc32-stream": "^4.0.2",
"crc-32": "^1.2.0",
"crc32-stream": "^5.0.0",
"normalize-path": "^3.0.0",
"readable-stream": "^3.6.0"
},
"engines": {
"node": ">= 10"
"node": ">= 12.0.0"
}
},
"node_modules/compressible": {
@@ -5601,15 +5628,15 @@
}
},
"node_modules/crc32-stream": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz",
"integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-5.0.0.tgz",
"integrity": "sha512-B0EPa1UK+qnpBZpG+7FgPCu0J2ETLpXq09o9BkLkEAhdB6Z61Qo4pJ3JYu0c+Qi+/SAL7QThqnzS06pmSSyZaw==",
"dependencies": {
"crc-32": "^1.2.0",
"readable-stream": "^3.4.0"
},
"engines": {
"node": ">= 10"
"node": ">= 12.0.0"
}
},
"node_modules/create-require": {
@@ -6591,9 +6618,9 @@
}
},
"node_modules/dot-prop": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-8.0.0.tgz",
"integrity": "sha512-XHcoBL9YPvqIz6K9m9TLf9+6Iyf2ix6yYN+sZ4AI8JPg+8XQpm05V6qzPFZYzyuHfr496TqKlhzHuEvW4ME7Pw==",
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-8.0.2.tgz",
"integrity": "sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ==",
"dependencies": {
"type-fest": "^3.8.0"
},
@@ -6676,9 +6703,9 @@
}
},
"node_modules/electron": {
"version": "25.3.0",
"resolved": "https://registry.npmjs.org/electron/-/electron-25.3.0.tgz",
"integrity": "sha512-cyqotxN+AroP5h2IxUsJsmehYwP5LrFAOO7O7k9tILME3Sa1/POAg3shrhx4XEnaAMyMqMLxzGvkzCVxzEErnA==",
"version": "26.2.1",
"resolved": "https://registry.npmjs.org/electron/-/electron-26.2.1.tgz",
"integrity": "sha512-SNT24Cf/wRvfcFZQoERXjzswUlg5ouqhIuA2t9x2L7VdTn+2Jbs0QXRtOfzcnOV/raVMz3e8ICyaU2GGeciKLg==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
@@ -6973,6 +7000,7 @@
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"dev": true,
"dependencies": {
"once": "^1.4.0"
}
@@ -8769,6 +8797,11 @@
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
"dev": true
},
"node_modules/fast-fifo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
"integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="
},
"node_modules/fast-glob": {
"version": "3.2.12",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
@@ -9066,9 +9099,9 @@
}
},
"node_modules/framer-motion": {
"version": "10.12.16",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.12.16.tgz",
"integrity": "sha512-w/SfWEIWJkYSgRHYBmln7EhcNo31ao8Xexol8lGXf1pR/tlnBtf1HcxoUmEiEh6pacB4/geku5ami53AAQWHMQ==",
"version": "10.16.4",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.16.4.tgz",
"integrity": "sha512-p9V9nGomS3m6/CALXqv6nFGMuFOxbWsmaOrdmhyQimMIlLl3LC7h7l86wge/Js/8cRu5ktutS/zlzgR7eBOtFA==",
"dependencies": {
"tslib": "^2.4.0"
},
@@ -9097,11 +9130,6 @@
"node": ">= 0.6"
}
},
"node_modules/fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
"node_modules/fs-extra": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz",
@@ -9292,6 +9320,7 @@
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -10008,6 +10037,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"dev": true,
"funding": [
{
"type": "github",
@@ -12523,9 +12553,9 @@
}
},
"node_modules/lazystream/node_modules/readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -12769,39 +12799,24 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"node_modules/lodash.defaults": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash.difference": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
"integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA=="
"integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
"dev": true
},
"node_modules/lodash.escaperegexp": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz",
"integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw=="
},
"node_modules/lodash.flatten": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
"integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g=="
},
"node_modules/lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
},
"node_modules/lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -12820,11 +12835,6 @@
"integrity": "sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==",
"dev": true
},
"node_modules/lodash.union": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
"integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw=="
},
"node_modules/lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@@ -15392,6 +15402,11 @@
}
]
},
"node_modules/queue-tick": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
"integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="
},
"node_modules/quick-lru": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
@@ -16902,6 +16917,15 @@
"node": ">= 0.8"
}
},
"node_modules/streamx": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz",
"integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==",
"dependencies": {
"fast-fifo": "^1.1.0",
"queue-tick": "^1.0.1"
}
},
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -17337,18 +17361,13 @@
}
},
"node_modules/tar-stream": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz",
"integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==",
"dependencies": {
"bl": "^4.0.3",
"end-of-stream": "^1.4.1",
"fs-constants": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.1.1"
},
"engines": {
"node": ">=6"
"b4a": "^1.6.4",
"fast-fifo": "^1.2.0",
"streamx": "^2.15.0"
}
},
"node_modules/temp-file": {
@@ -19127,16 +19146,16 @@
}
},
"node_modules/zip-stream": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz",
"integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-5.0.1.tgz",
"integrity": "sha512-UfZ0oa0C8LI58wJ+moL46BDIMgCQbnsb+2PoiJYtonhBsMh2bq1eRBVkvjfVsqbEHd9/EgKPUuL9saSSsec8OA==",
"dependencies": {
"archiver-utils": "^2.1.0",
"compress-commons": "^4.1.0",
"archiver-utils": "^4.0.1",
"compress-commons": "^5.0.1",
"readable-stream": "^3.6.0"
},
"engines": {
"node": ">= 10"
"node": ">= 12.0.0"
}
}
},
@@ -22167,48 +22186,58 @@
"dev": true
},
"archiver": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz",
"integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/archiver/-/archiver-6.0.1.tgz",
"integrity": "sha512-CXGy4poOLBKptiZH//VlWdFuUC1RESbdZjGjILwBuZ73P7WkAUN0htfSfBq/7k6FRFlpu7bg4JOkj1vU9G6jcQ==",
"requires": {
"archiver-utils": "^2.1.0",
"async": "^3.2.3",
"archiver-utils": "^4.0.1",
"async": "^3.2.4",
"buffer-crc32": "^0.2.1",
"readable-stream": "^3.6.0",
"readdir-glob": "^1.0.0",
"tar-stream": "^2.2.0",
"zip-stream": "^4.1.0"
"readdir-glob": "^1.1.2",
"tar-stream": "^3.0.0",
"zip-stream": "^5.0.1"
}
},
"archiver-utils": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz",
"integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-4.0.1.tgz",
"integrity": "sha512-Q4Q99idbvzmgCTEAAhi32BkOyq8iVI5EwdO0PmBDSGIzzjYNdcFn7Q7k3OzbLy4kLUPXfJtG6fO2RjftXbobBg==",
"requires": {
"glob": "^7.1.4",
"glob": "^8.0.0",
"graceful-fs": "^4.2.0",
"lazystream": "^1.0.0",
"lodash.defaults": "^4.2.0",
"lodash.difference": "^4.5.0",
"lodash.flatten": "^4.4.0",
"lodash.isplainobject": "^4.0.6",
"lodash.union": "^4.6.0",
"lodash": "^4.17.15",
"normalize-path": "^3.0.0",
"readable-stream": "^2.0.0"
"readable-stream": "^3.6.0"
},
"dependencies": {
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
"balanced-match": "^1.0.0"
}
},
"glob": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^5.0.1",
"once": "^1.3.0"
}
},
"minimatch": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"requires": {
"brace-expansion": "^2.0.1"
}
}
}
@@ -22418,6 +22447,11 @@
"integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==",
"dev": true
},
"b4a": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz",
"integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw=="
},
"babel-jest": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz",
@@ -22521,7 +22555,8 @@
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"dev": true
},
"batch": {
"version": "0.6.1",
@@ -22557,6 +22592,7 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"dev": true,
"requires": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
@@ -22724,6 +22760,7 @@
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"dev": true,
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
@@ -23231,12 +23268,12 @@
"dev": true
},
"compress-commons": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz",
"integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-5.0.1.tgz",
"integrity": "sha512-MPh//1cERdLtqwO3pOFLeXtpuai0Y2WCd5AhtKxznqM7WtaMYaOEMSgn45d9D10sIHSfIKE603HlOp8OPGrvag==",
"requires": {
"buffer-crc32": "^0.2.13",
"crc32-stream": "^4.0.2",
"crc-32": "^1.2.0",
"crc32-stream": "^5.0.0",
"normalize-path": "^3.0.0",
"readable-stream": "^3.6.0"
}
@@ -23479,9 +23516,9 @@
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="
},
"crc32-stream": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz",
"integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-5.0.0.tgz",
"integrity": "sha512-B0EPa1UK+qnpBZpG+7FgPCu0J2ETLpXq09o9BkLkEAhdB6Z61Qo4pJ3JYu0c+Qi+/SAL7QThqnzS06pmSSyZaw==",
"requires": {
"crc-32": "^1.2.0",
"readable-stream": "^3.4.0"
@@ -24198,9 +24235,9 @@
}
},
"dot-prop": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-8.0.0.tgz",
"integrity": "sha512-XHcoBL9YPvqIz6K9m9TLf9+6Iyf2ix6yYN+sZ4AI8JPg+8XQpm05V6qzPFZYzyuHfr496TqKlhzHuEvW4ME7Pw==",
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-8.0.2.tgz",
"integrity": "sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ==",
"requires": {
"type-fest": "^3.8.0"
},
@@ -24262,9 +24299,9 @@
}
},
"electron": {
"version": "25.3.0",
"resolved": "https://registry.npmjs.org/electron/-/electron-25.3.0.tgz",
"integrity": "sha512-cyqotxN+AroP5h2IxUsJsmehYwP5LrFAOO7O7k9tILME3Sa1/POAg3shrhx4XEnaAMyMqMLxzGvkzCVxzEErnA==",
"version": "26.2.1",
"resolved": "https://registry.npmjs.org/electron/-/electron-26.2.1.tgz",
"integrity": "sha512-SNT24Cf/wRvfcFZQoERXjzswUlg5ouqhIuA2t9x2L7VdTn+2Jbs0QXRtOfzcnOV/raVMz3e8ICyaU2GGeciKLg==",
"dev": true,
"requires": {
"@electron/get": "^2.0.0",
@@ -24514,6 +24551,7 @@
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"dev": true,
"requires": {
"once": "^1.4.0"
}
@@ -25808,6 +25846,11 @@
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
"dev": true
},
"fast-fifo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
"integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="
},
"fast-glob": {
"version": "3.2.12",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
@@ -26039,9 +26082,9 @@
"dev": true
},
"framer-motion": {
"version": "10.12.16",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.12.16.tgz",
"integrity": "sha512-w/SfWEIWJkYSgRHYBmln7EhcNo31ao8Xexol8lGXf1pR/tlnBtf1HcxoUmEiEh6pacB4/geku5ami53AAQWHMQ==",
"version": "10.16.4",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.16.4.tgz",
"integrity": "sha512-p9V9nGomS3m6/CALXqv6nFGMuFOxbWsmaOrdmhyQimMIlLl3LC7h7l86wge/Js/8cRu5ktutS/zlzgR7eBOtFA==",
"requires": {
"@emotion/is-prop-valid": "^0.8.2",
"tslib": "^2.4.0"
@@ -26053,11 +26096,6 @@
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"dev": true
},
"fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
"fs-extra": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz",
@@ -26199,6 +26237,7 @@
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -26739,7 +26778,8 @@
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"dev": true
},
"if-async": {
"version": "3.7.4",
@@ -28751,9 +28791,9 @@
},
"dependencies": {
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -28937,39 +28977,24 @@
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"lodash.defaults": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash.difference": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
"integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA=="
"integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
"dev": true
},
"lodash.escaperegexp": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz",
"integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw=="
},
"lodash.flatten": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
"integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g=="
},
"lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -28988,11 +29013,6 @@
"integrity": "sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==",
"dev": true
},
"lodash.union": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
"integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw=="
},
"lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@@ -30806,6 +30826,11 @@
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="
},
"queue-tick": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
"integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="
},
"quick-lru": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
@@ -31975,6 +32000,15 @@
"stream-to": "~0.2.0"
}
},
"streamx": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz",
"integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==",
"requires": {
"fast-fifo": "^1.1.0",
"queue-tick": "^1.0.1"
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -32289,15 +32323,13 @@
}
},
"tar-stream": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz",
"integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==",
"requires": {
"bl": "^4.0.3",
"end-of-stream": "^1.4.1",
"fs-constants": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.1.1"
"b4a": "^1.6.4",
"fast-fifo": "^1.2.0",
"streamx": "^2.15.0"
}
},
"temp-file": {
@@ -33612,12 +33644,12 @@
"dev": true
},
"zip-stream": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz",
"integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-5.0.1.tgz",
"integrity": "sha512-UfZ0oa0C8LI58wJ+moL46BDIMgCQbnsb+2PoiJYtonhBsMh2bq1eRBVkvjfVsqbEHd9/EgKPUuL9saSSsec8OA==",
"requires": {
"archiver-utils": "^2.1.0",
"compress-commons": "^4.1.0",
"archiver-utils": "^4.0.1",
"compress-commons": "^5.0.1",
"readable-stream": "^3.6.0"
}
}
+7 -8
View File
@@ -14,7 +14,7 @@
"start:preload": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.preload.dev.ts",
"start:renderer": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./.erb/configs/webpack.config.renderer.dev.ts",
"test": "jest",
"publish": "npm run build && electron-builder --publish always --win --x64"
"publish": "npm run build && electron-builder -c.win.certificateSha1=842a817a51e2a1d360fcd62f54bf5f9193e919e1 --publish always --win --x64"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
@@ -76,8 +76,7 @@
"nsis",
"nsis-web"
],
"icon": "assets/favicon.ico",
"certificateSha1": "f3363a89b084f8f6b616babea3c91f9d79e15000"
"icon": "assets/favicon.ico"
},
"linux": {
"target": [
@@ -179,7 +178,7 @@
"css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^4.1.0",
"detect-port": "^1.3.0",
"electron": "^25.3.0",
"electron": "^26.2.1",
"electron-builder": "^24.6.3",
"electron-devtools-installer": "^3.2.0",
"electron-notarize": "^1.2.1",
@@ -231,16 +230,16 @@
"dependencies": {
"@node-steam/vdf": "^2.2.0",
"@tippyjs/react": "^4.2.6",
"archiver": "^5.3.1",
"archiver": "^6.0.1",
"color": "^4.2.3",
"dateformat": "^5.0.3",
"dot-prop": "^8.0.0",
"dot-prop": "^8.0.2",
"electron-debug": "^3.2.0",
"electron-log": "^4.4.8",
"electron-store": "^8.1.0",
"electron-updater": "^6.1.4",
"fast-deep-equal": "^3.1.3",
"framer-motion": "^10.12.16",
"framer-motion": "^10.16.4",
"fs-extra": "^11.1.1",
"history": "^5.3.0",
"jszip": "^3.10.1",
@@ -261,7 +260,7 @@
"rfdc": "^1.3.0",
"rxjs": "^7.8.0",
"sanitize-filename": "^1.6.3",
"semver": "^7.5.1",
"semver": "^7.5.4",
"striptags": "^4.0.0-alpha.4",
"tailwind-scrollbar-hide": "^1.1.7",
"tailwindcss-scoped-groups": "^2.0.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "bs-manager",
"version": "1.3.0-alpha.5",
"version": "1.3.1-alpha.1",
"description": "BSManager",
"main": "./dist/main/main.js",
"author": {
+1 -1
View File
@@ -12,7 +12,7 @@ ipc.on("is-dotnet-6-installed", (_, reply) => {
ipc.on("bs-download.installation-folder", (_, reply) => {
const installLocation = InstallationLocationService.getInstance();
reply(of(installLocation.installationDirectory));
reply(from(installLocation.installationDirectory()));
});
ipc.on<string>("bs-download.set-installation-folder", (req, reply) => {
+6
View File
@@ -15,3 +15,9 @@ ipc.on<LaunchOption>("create-launch-shortcut", (req, reply) => {
const bsLauncher = BSLauncherService.getInstance();
reply(from(bsLauncher.createLaunchShortcut(req.args)));
});
ipc.on<void>("bs-launch.restore-steamvr", (_, reply) => {
const bsLauncher = BSLauncherService.getInstance();
reply(from(bsLauncher.restoreSteamVR()));
});
+2 -1
View File
@@ -19,6 +19,7 @@ import { LocalModelsManagerService } from "./services/additional-content/local-m
import { APP_NAME } from "./constants";
import { BSLauncherService } from "./services/bs-launcher.service";
import { IpcRequest } from "shared/models/ipc";
import { LivShortcut } from "./services/liv/liv-shortcut.service";
const isDebug = process.env.NODE_ENV === "development" || process.env.DEBUG_PROD === "true";
@@ -63,7 +64,7 @@ const initServicesMustBeInitialized = () => {
LocalMapsManagerService.getInstance();
LocalPlaylistsManagerService.getInstance();
LocalModelsManagerService.getInstance();
LivShortcut.getInstance();
BSLauncherService.getInstance();
}
+7 -2
View File
@@ -14,7 +14,6 @@ export class DepotDownloader {
},
logger?: Logger
){
this.processOut$ = new Observable<string>(subscriber => {
this.subscriber = subscriber;
@@ -24,7 +23,13 @@ export class DepotDownloader {
subscriber.next(`[Info]|[Start]|${JSON.stringify(options.echoStartData) ?? ""}`);
this.process.stdout.on("data", data => {
const lines: string[] = data.toString().split("\n");
const stringData: string = data.toString();
if(!stringData.includes(DepotDownloaderInfoEvent.Progress) && !stringData.includes(DepotDownloaderInfoEvent.Validated)){
logger?.info("DepotDownloader stdout:", stringData);
}
const lines: string[] = stringData.split("\n");
lines.forEach(line => subscriber.next(line));
});
@@ -6,8 +6,8 @@ import { BSLocalVersionService } from "../bs-local-version.service";
import { InstallationLocationService } from "../installation-location.service";
import { UtilsService } from "../utils.service";
import crypto from "crypto";
import { lstatSync, unlinkSync } from "fs";
import { copySync, createReadStream } from "fs-extra";
import { lstatSync } from "fs";
import { copy, createReadStream, ensureDir, unlink } from "fs-extra";
import StreamZip from "node-stream-zip";
import { RequestService } from "../request.service";
import sanitize from "sanitize-filename";
@@ -75,7 +75,7 @@ export class LocalMapsManagerService {
if (version) {
return path.join(await this.localVersion.getVersionPath(version), LocalMapsManagerService.LEVELS_ROOT_FOLDER, LocalMapsManagerService.CUSTOM_LEVELS_FOLDER);
}
const sharedMapsPath = path.join(this.installLocation.sharedContentPath, LocalMapsManagerService.SHARED_MAPS_FOLDER, LocalMapsManagerService.CUSTOM_LEVELS_FOLDER);
const sharedMapsPath = path.join(await this.installLocation.sharedContentPath(), LocalMapsManagerService.SHARED_MAPS_FOLDER, LocalMapsManagerService.CUSTOM_LEVELS_FOLDER);
if (!(await pathExist(sharedMapsPath))) {
await ensureFolderExist(sharedMapsPath);
}
@@ -252,20 +252,19 @@ export class LocalMapsManagerService {
const { zip, zipPath } = await this.downloadMapZip(zipUrl);
const mapFolderName = sanitize(`${map.id}-${map.name}`);
const mapPath = path.join(mapsFolder, mapFolderName);
if (!zip) {
throw `Cannot download ${zipUrl}`;
}
const mapFolderName = sanitize(`${map.id}-${map.name}`);
const mapPath = path.join(mapsFolder, mapFolderName);
await ensureFolderExist(mapPath);
await zip.extract(null, mapPath);
await zip.close();
unlinkSync(zipPath);
await unlink(zipPath);
const localMap = await this.loadMapInfoFromPath(mapPath);
localMap.bsaverInfo = map;
@@ -288,20 +287,14 @@ export class LocalMapsManagerService {
}
public async oneClickDownloadMap(map: BsvMapDetail): Promise<void> {
const downloadedMap = await this.downloadMap(map);
const versions = await this.localVersion.getInstalledVersions();
const downloadedMap = await this.downloadMap(map, versions.pop());
for (const version of versions) {
if (await this.versionIsLinked(version)) {
continue;
}
const versionMapsPath = await this.getMapsFolderPath(version);
await ensureFolderExist(versionMapsPath);
copySync(downloadedMap.path, path.join(versionMapsPath, path.basename(downloadedMap.path)), { overwrite: true });
await ensureDir(versionMapsPath);
await copy(downloadedMap.path, path.join(versionMapsPath, path.basename(downloadedMap.path)), { overwrite: true });
}
}
@@ -314,6 +307,6 @@ export class LocalMapsManagerService {
}
public isDeepLinksEnabled(): boolean {
return Array.from(Object.values(this.DEEP_LINKS)).every(link => this.deepLink.isDeepLinkRegistred(link));
return Array.from(Object.values(this.DEEP_LINKS)).every(link => this.deepLink.isDeepLinkRegistered(link));
}
}
@@ -73,7 +73,7 @@ export class LocalModelsManagerService {
}
private async getModelFolderPath(type: MSModelType, version?: BSVersion): Promise<string> {
const rootPath = version ? await this.localVersion.getVersionPath(version) : this.installPaths.sharedContentPath;
const rootPath = await (version ? this.localVersion.getVersionPath(version) : this.installPaths.sharedContentPath());
const modelFolderPath = path.join(rootPath, MODEL_TYPE_FOLDERS[type]);
await ensureFolderExist(modelFolderPath);
@@ -119,23 +119,13 @@ export class LocalModelsManagerService {
}
public async oneClickDownloadModel(model: MSModel): Promise<void> {
if (!model) {
return;
}
if (!model) { return; }
const versions = await this.localVersion.getInstalledVersions();
if (versions?.length === 0) {
return;
}
const fisrtVersion = versions.shift();
const downloaded = await lastValueFrom(this.downloadModel(model, fisrtVersion));
const downloaded = await lastValueFrom(this.downloadModel(model, versions.pop()));
for (const version of versions) {
const modelDest = path.join(await this.getModelFolderPath(model.type, version), path.basename(downloaded.data.path));
copyFileSync(downloaded.data.path, modelDest);
}
}
@@ -242,7 +232,7 @@ export class LocalModelsManagerService {
}
public isDeepLinksEnabled(): boolean {
return Array.from(Object.values(this.DEEP_LINKS)).every(link => this.deepLink.isDeepLinkRegistred(link));
return Array.from(Object.values(this.DEEP_LINKS)).every(link => this.deepLink.isDeepLinkRegistered(link));
}
}
@@ -178,20 +178,11 @@ export class LocalPlaylistsManagerService {
public async oneClickInstallPlaylist(bpListUrl: string): Promise<void> {
const versions = await this.versions.getInstalledVersions();
const firstVersion = versions.shift();
const fistVersionLinked = await this.maps.versionIsLinked(firstVersion);
const { bpListPath, mapsPath } = await this.downloadPlaylist(bpListUrl, firstVersion).toPromise();
const { bpListPath, mapsPath } = await lastValueFrom(this.downloadPlaylist(bpListUrl, versions.pop()));
for (const version of versions) {
await this.installBPListFile(bpListPath, version);
const versionIsLinked = await this.maps.versionIsLinked(version);
if (fistVersionLinked && versionIsLinked) {
continue;
}
for (const mapPath of mapsPath) {
const versionMapsFolder = await this.maps.getMapsFolderPath(version);
const mapDest = path.join(versionMapsFolder, path.basename(mapPath));
@@ -210,6 +201,6 @@ export class LocalPlaylistsManagerService {
}
public isDeepLinksEnabled(): boolean {
return Array.from(Object.values(this.DEEP_LINKS)).every(link => this.deepLink.isDeepLinkRegistred(link));
return Array.from(Object.values(this.DEEP_LINKS)).every(link => this.deepLink.isDeepLinkRegistered(link));
}
}
+15 -9
View File
@@ -42,14 +42,16 @@ export class BSInstallerService {
}
private getDepotDownloaderExePath(): string {
return path.join(this.utils.getAssetsScriptsPath(), "depot-downloader", "DepotDownloader.exe");
return path.join(this.utils.getAssetsScriptsPath(), "depot-downloader", `DepotDownloader.${process.platform === 'linux' ? 'dll' : 'exe'}`);
}
public async isDotNet6Installed(): Promise<boolean> {
try {
const process = spawnSync(this.getDepotDownloaderExePath());
if (process.stderr.toString()) {
log.error("no dotnet", process.stderr.toString());
const proc = process.platform === 'linux'
? spawnSync('dotnet', [this.getDepotDownloaderExePath()])
: spawnSync(this.getDepotDownloaderExePath());
if (proc.stderr?.toString()) {
log.error("no dotnet", proc.stderr.toString());
return false;
}
return true;
@@ -77,12 +79,16 @@ export class BSInstallerService {
qr
}
await ensureDir(this.installLocationService.versionsDirectory);
await ensureDir(await this.installLocationService.versionsDirectory());
const isLinux = process.platform === 'linux';
const exePath = this.getDepotDownloaderExePath();
const args = DepotDownloader.buildArgs(depotDownloaderOptions);
return new DepotDownloader({
command: this.getDepotDownloaderExePath(),
args: DepotDownloader.buildArgs(depotDownloaderOptions),
options: { cwd: this.installLocationService.versionsDirectory },
command: isLinux ? 'dotnet' : exePath,
args: isLinux ? [exePath, ...args] : args,
options: { cwd: await this.installLocationService.versionsDirectory() },
echoStartData: downloadVersion
}, log);
}
@@ -106,7 +112,7 @@ export class BSInstallerService {
}
return event;
})).subscribe(sub);
}).catch(err => sub.error({
type: DepotDownloaderEventType.Error,
subType: DepotDownloaderErrorEvent.Unknown,
+23 -8
View File
@@ -8,7 +8,7 @@ import { BSLocalVersionService } from "./bs-local-version.service";
import { pathExist } from "../helpers/fs.helpers";
import { rename } from "fs/promises";
import log from "electron-log";
import { Observable, lastValueFrom, of, timer } from "rxjs";
import { Observable, of } from "rxjs";
import { BsmProtocolService } from "./bsm-protocol.service";
import { app, shell} from "electron";
import { Resvg } from "@resvg/resvg-js";
@@ -50,8 +50,7 @@ export class BSLauncherService {
this.bsmProtocolService.on("launch", link => {
log.info("Launch from bsm protocol", link.toString());
const shortcutParams = objectFromEntries(link.searchParams.entries()) as ShortcutParams;
this.openShortcutLaunchWindow(shortcutParams).catch(log.error);
this.openShortcutLaunchWindow(this.shortcutLinkToShortcutParams(link)).catch(log.error);
});
}
@@ -144,7 +143,6 @@ export class BSLauncherService {
await this.backupSteamVR().catch(() => {
return this.restoreSteamVR();
});
await lastValueFrom(timer(2_000));
} else if(!launchOptions.version.oculus){
await this.restoreSteamVR();
}
@@ -163,13 +161,14 @@ export class BSLauncherService {
bsProcess.removeAllListeners("error");
bsProcess.removeAllListeners("exit");
resolve(-1);
}, 4000);
}, 15_000);
}).then(exitCode => {
log.info("BS process exit code", exitCode);
}).catch(err => {
log.error(err);
obs.error({type: BSLaunchError.BS_EXIT_ERROR, data: err} as BSLaunchErrorData);
}).finally(() => {
this.restoreSteamVR().catch(log.error);
});
})().then(() => {
@@ -179,6 +178,18 @@ export class BSLauncherService {
})});
}
public shortcutLinkToShortcutParams(shortcutLink: string|URL): ShortcutParams{
if(typeof shortcutLink === "string"){
shortcutLink = new URL(shortcutLink);
}
return objectFromEntries(shortcutLink.searchParams.entries()) as ShortcutParams;
}
public shortcutLinkToLaunchOptions(shortcutLink: string|URL): LaunchOption{
return this.shortcutParamsToLaunchOption(this.shortcutLinkToShortcutParams(shortcutLink));
}
private shortcutParamsToLaunchOption(params: ShortcutParams): LaunchOption{
const res: LaunchOption = {
version: {
@@ -263,9 +274,13 @@ export class BSLauncherService {
return iconPath;
}
public async createLaunchShortcut(launchOptions: LaunchOption): Promise<boolean>{
public createLaunchLink(launchOptions: LaunchOption): string{
const shortcutParams = this.launchOptionToShortcutParams(launchOptions);
const shortcutUrl = this.bsmProtocolService.buildLink("launch", shortcutParams).toString();
return this.bsmProtocolService.buildLink("launch", shortcutParams).toString();
}
public async createLaunchShortcut(launchOptions: LaunchOption): Promise<boolean>{
const shortcutUrl = this.createLaunchLink(launchOptions);
const shortcutName = ["Beat Saber", launchOptions.version.BSVersion, launchOptions.version.name].join(" ");
const shortcutIconColor = new Color(launchOptions.version.color, "hex");
+14 -4
View File
@@ -15,6 +15,7 @@ import { copyDirectoryWithJunctions, deleteFolder, getFoldersInFolder, pathExist
import { FolderLinkerService } from "./folder-linker.service";
import { ReadStream, createReadStream } from "fs-extra";
import readline from "readline";
import { Observable, Subject } from "rxjs";
export class BSLocalVersionService {
private static instance: BSLocalVersionService;
@@ -27,6 +28,7 @@ export class BSLocalVersionService {
private readonly remoteVersionService: BSVersionLibService;
private readonly configService: ConfigurationService;
private readonly linker: FolderLinkerService;
private readonly _loadedVersions$: Subject<BSVersion[]>;
public static getInstance(): BSLocalVersionService {
if (!BSLocalVersionService.instance) {
@@ -42,6 +44,8 @@ export class BSLocalVersionService {
this.remoteVersionService = BSVersionLibService.getInstance();
this.configService = ConfigurationService.getInstance();
this.linker = FolderLinkerService.getInstance();
this._loadedVersions$ = new Subject<BSVersion[]>();
}
private async getVersionFromGlobalGameManagerFile(versionFilePath: string): Promise<BSVersion> {
@@ -142,7 +146,7 @@ export class BSLocalVersionService {
if(version.oculus){ return this.oculusService.getGameFolder(OCULUS_BS_DIR); }
return path.join(
this.installLocationService.versionsDirectory,
await this.installLocationService.versionsDirectory(),
this.getVersionFolder(version)
);
}
@@ -156,7 +160,7 @@ export class BSLocalVersionService {
const versionPath = await this.getVersionPath(version);
if(await pathExist(versionPath)){ return versionPath; }
const versionFolders = await getFoldersInFolder(this.installLocationService.versionsDirectory);
const versionFolders = await getFoldersInFolder(await this.installLocationService.versionsDirectory());
for(const folder of versionFolders){
const stats = await lstat(folder);
@@ -215,11 +219,11 @@ export class BSLocalVersionService {
versions.push(oculusVersion);
}
if (!(await pathExist(this.installLocationService.versionsDirectory))) {
if (!(await pathExist(await this.installLocationService.versionsDirectory()))) {
return versions;
}
const folderInInstallation = await getFoldersInFolder(this.installLocationService.versionsDirectory);
const folderInInstallation = await getFoldersInFolder(await this.installLocationService.versionsDirectory());
for (const f of folderInInstallation) {
log.info("try get version from folder", f);
@@ -233,6 +237,8 @@ export class BSLocalVersionService {
this.setCustomVersions(versions.filter(v => !!v.color));
this._loadedVersions$.next(versions);
return versions;
}
@@ -310,4 +316,8 @@ export class BSLocalVersionService {
return (await linkedFolder).filter(folder => folder);
}
public get loadedVersions$(): Observable<BSVersion[]>{
return this._loadedVersions$.asObservable();
}
}
+1 -2
View File
@@ -1,6 +1,5 @@
import { Subject, Subscription, filter } from "rxjs";
import { DeepLinkService } from "./deep-link.service";
import { URL } from "url";
import { buildUrl, isValidUrl } from "../../shared/helpers/url.helpers";
export class BsmProtocolService {
@@ -30,7 +29,7 @@ export class BsmProtocolService {
}
private registerBsmProtocol(): boolean{
if(this.deepLink.isDeepLinkRegistred(this.BSM_PROTOCOL)){ return true; }
if(this.deepLink.isDeepLinkRegistered(this.BSM_PROTOCOL)){ return true; }
return this.deepLink.registerDeepLink(this.BSM_PROTOCOL);
}
+3 -3
View File
@@ -19,11 +19,11 @@ export class ConfigurationService {
this.locations = InstallationLocationService.getInstance();
this.initStore();
this.locations.onInstallLocationUpdate(() => this.initStore());
this.locations.onInstallLocationUpdate(() => { this.initStore() });
}
private initStore() {
const contentPath = this.locations.installationDirectory;
private async initStore() {
const contentPath = await this.locations.installationDirectory();
this.store = new ElectronStore({
cwd: contentPath,
name: "config",
+1 -1
View File
@@ -35,7 +35,7 @@ export class DeepLinkService {
return app.removeAsDefaultProtocolClient(protocol);
}
public isDeepLinkRegistred(protocol: string): boolean {
public isDeepLinkRegistered(protocol: string): boolean {
if (process.defaultApp && process.argv.length >= 2) {
return app.isDefaultProtocolClient(protocol, process.execPath, [path.resolve(process.argv[1])]);
}
+6 -6
View File
@@ -21,12 +21,12 @@ export class FolderLinkerService {
this.installLocationService = InstallationLocationService.getInstance();
}
private get sharedFolder(): string {
return this.installLocationService.sharedContentPath;
private async sharedFolder(): Promise<string> {
return this.installLocationService.sharedContentPath();
}
private getSharedFolder(folderPath: string, intermediateFolder?: string): string {
return path.join(this.sharedFolder, intermediateFolder ?? "", path.basename(folderPath));
private async getSharedFolder(folderPath: string, intermediateFolder?: string): Promise<string> {
return path.join(await this.sharedFolder(), intermediateFolder ?? "", path.basename(folderPath));
}
private getBackupFolder(folderPath: string): string {
@@ -50,7 +50,7 @@ export class FolderLinkerService {
}
public async linkFolder(folderPath: string, options?: LinkOptions): Promise<void> {
const sharedPath = this.getSharedFolder(folderPath, options?.intermediateFolder);
const sharedPath = await this.getSharedFolder(folderPath, options?.intermediateFolder);
if (await this.isFolderSymlink(folderPath)) {
const isTargetedToSharedPath = await readlink(folderPath)
@@ -86,7 +86,7 @@ export class FolderLinkerService {
}
await unlinkPath(folderPath);
const sharedPath = this.getSharedFolder(folderPath, options?.intermediateFolder);
const sharedPath = await this.getSharedFolder(folderPath, options?.intermediateFolder);
await ensureFolderExist(folderPath);
@@ -1,7 +1,7 @@
import path from "path";
import { app } from "electron";
import ElectronStore from "electron-store";
import { copyDirectoryWithJunctions, deleteFolder, ensureFolderExist } from "../helpers/fs.helpers";
import { copyDirectoryWithJunctions, deleteFolder, ensureFolderExist, pathExist } from "../helpers/fs.helpers";
export class InstallationLocationService {
private static instance: InstallationLocationService;
@@ -27,51 +27,61 @@ export class InstallationLocationService {
private constructor() {
this.installPathConfig = new ElectronStore({ watch: true });
this.initInstallationLocation();
this.installPathConfig.onDidChange(this.STORE_INSTALLATION_PATH_KEY, () => {
this.triggerListeners();
});
}
private initInstallationLocation(): void {
this._installationDirectory = (this.installPathConfig.get<string>(this.STORE_INSTALLATION_PATH_KEY) as string) || app.getPath("documents");
}
private triggerListeners(): void {
this.updateListeners.forEach(listener => listener());
}
public async setInstallationDirectory(newDir: string): Promise<string> {
const oldDir = this.installationDirectory;
const newDest = path.join(newDir, this.INSTALLATION_FOLDER);
newDir = path.basename(newDir) === this.INSTALLATION_FOLDER ? newDir : path.join(newDir, this.INSTALLATION_FOLDER);
const oldDir = await this.installationDirectory();
await ensureFolderExist(oldDir);
await copyDirectoryWithJunctions(oldDir, newDest, { overwrite: true });
await copyDirectoryWithJunctions(oldDir, newDir, { overwrite: true });
this._installationDirectory = newDir;
this.installPathConfig.set(this.STORE_INSTALLATION_PATH_KEY, newDir);
deleteFolder(oldDir);
return this.installationDirectory;
return this.installationDirectory();
}
public onInstallLocationUpdate(fn: Listener) {
this.updateListeners.add(fn);
}
public get installationDirectory(): string {
return path.join(this._installationDirectory, this.INSTALLATION_FOLDER);
public async installationDirectory(): Promise<string> {
if(this._installationDirectory) {
return this._installationDirectory;
}
if(this.installPathConfig.has(this.STORE_INSTALLATION_PATH_KEY)) {
this._installationDirectory = this.installPathConfig.get(this.STORE_INSTALLATION_PATH_KEY) as string;
return this._installationDirectory;
}
const oldPath = path.join(app.getPath("documents"), this.INSTALLATION_FOLDER);
if(await pathExist(oldPath)){
this._installationDirectory = oldPath;
return this._installationDirectory;
}
this._installationDirectory = path.join(app.getPath("home"), this.INSTALLATION_FOLDER);
return this._installationDirectory;
}
public get versionsDirectory(): string {
return path.join(this.installationDirectory, this.VERSIONS_FOLDER);
public async versionsDirectory(): Promise<string> {
return path.join(await this.installationDirectory(), this.VERSIONS_FOLDER);
}
public get sharedContentPath(): string {
return path.join(this.installationDirectory, this.SHARED_CONTENT_FOLDER);
public async sharedContentPath(): Promise<string> {
return path.join(await this.installationDirectory(), this.SHARED_CONTENT_FOLDER);
}
}
@@ -0,0 +1,97 @@
import { BSLauncherService } from "../bs-launcher.service";
import { LivEntry, LivService } from "./liv.service";
import { LaunchOption } from "shared/models/bs-launch";
import { app } from "electron";
import { BSLocalVersionService } from "../bs-local-version.service";
import { BSVersion } from "shared/bs-version.interface";
import { debounceTime, distinctUntilChanged, map } from "rxjs";
import equal from "fast-deep-equal";
import sanitize from "sanitize-filename";
import { tryit } from "../../../shared/helpers/error.helpers";
import log from "electron-log"
export class LivShortcut {
private static instance: LivShortcut;
public static getInstance(): LivShortcut {
if (!LivShortcut.instance) {
LivShortcut.instance = new LivShortcut();
}
return LivShortcut.instance;
}
private readonly LIV_ID_PREFIX = "BSManager";
private readonly liv: LivService;
private readonly launcher: BSLauncherService;
private readonly versionManager: BSLocalVersionService;
private constructor() {
this.liv = LivService.getInstance();
this.launcher = BSLauncherService.getInstance();
this.versionManager = BSLocalVersionService.getInstance();
this.liv.isLivInstalled().then(installed => {
if(!installed){ return; }
this.versionManager.loadedVersions$.pipe(debounceTime(1000), distinctUntilChanged((prev, curr) => equal(prev, curr)), map(versions => versions.filter(v => !v.steam))).subscribe(versions => {
(async () => {
const clearedLaunchOptions = (await this.clearLivShortcuts().catch(() => [] as LivEntry[]))?.map(entry => {
return tryit(() => this.launcher.shortcutLinkToLaunchOptions(entry.arguments)).result;
});
versions.forEach(version => this.createLivShortcut({
...(clearedLaunchOptions?.find(launchOpt => launchOpt.version.ino === version.ino) ?? {}),
version,
skipAlreadyRunning: true
}));
})().catch(err => log.error("Error while creating LIV shortcuts", err));
});
});
}
private buildShortcutId(version: BSVersion): string {
const name = (() => {
if(version.steam){ return "Steam"; }
if(version.oculus){ return "Oculus"; }
return version.name;
})();
return sanitize([this.LIV_ID_PREFIX, name, version.BSVersion].filter(Boolean).join("-").replaceAll(".", "-").replaceAll(" ", "-"));
}
private buildShortcutName(version: BSVersion): string {
const name = (() => {
if(version.steam){ return "Steam"; }
if(version.oculus){ return "Oculus"; }
return version.name;
})();
return ["Beat Saber", name, `v${version.BSVersion}`].filter(Boolean).join(" ");
}
private async buildLivEntry(launchOptions: LaunchOption): Promise<LivEntry> {
return {
id: this.buildShortcutId(launchOptions.version),
name: this.buildShortcutName(launchOptions.version),
installPath: await this.versionManager.getInstalledVersionPath(launchOptions.version),
executable: app.getPath("exe"),
arguments: this.launcher.createLaunchLink(launchOptions)
};
}
private createLivShortcut(launchOptions: LaunchOption): Promise<void>{
return this.buildLivEntry(launchOptions).then(entry => this.liv.createLivShortcut(entry));
}
private async clearLivShortcuts(): Promise<LivEntry[]>{
const bsmShortcuts = (await this.liv.getLivShortcuts()).reduce((acc, shortcut) => {
if(shortcut.id?.startsWith(this.LIV_ID_PREFIX)){
acc.push(shortcut);
}
return acc;
}, [] as LivEntry[]);
return this.liv.deleteLivShortcuts(bsmShortcuts.map(shortcut => shortcut.id)).then(() => bsmShortcuts);
}
}
+110
View File
@@ -0,0 +1,110 @@
import { execOnOs } from "../../helpers/env.helpers";
import path from "path";
import regedit from "regedit";
export class LivService {
private static instance: LivService;
public static getInstance(): LivService {
if (!LivService.instance) {
LivService.instance = new LivService();
}
return LivService.instance;
}
private readonly livRegeditKey: string = path.join("HKCU", "SOFTWARE", "LIV.App");
private readonly livExternalAppsRegeditKey: string = path.join(this.livRegeditKey, "ExternalApplications");
private constructor() {
}
public isLivInstalled(): Promise<boolean> {
return execOnOs({
win32: async () => {
const regRes = await regedit.promisified.list([this.livRegeditKey]).then(res => res[this.livRegeditKey]);
return regRes?.exists;
}
});
}
public async createLivShortcut(entry: LivEntry): Promise<void> {
return execOnOs({
win32: async () => {
const livExternalAppRegeditKey = path.join(this.livExternalAppsRegeditKey, entry.id);
await regedit.promisified.createKey([livExternalAppRegeditKey]);
await regedit.promisified.putValue({
[livExternalAppRegeditKey]: {
"InstallPath": {
value: entry.installPath,
type: "REG_SZ"
},
"Executable": {
value: entry.executable,
type: "REG_SZ"
},
"Arguments": {
value: entry.arguments,
type: "REG_SZ"
},
"Name": {
value: entry.name,
type: "REG_SZ"
}
}
});
}
});
}
public async deleteLivShortcuts(ids: string[]): Promise<void> {
return execOnOs({
win32: async () => {
const shotcutsKeys = ids.map(id => path.join(this.livExternalAppsRegeditKey, id));
return regedit.promisified.deleteKey(shotcutsKeys);
}
})
}
public getLivShortcuts(): Promise<LivEntry[]> {
return execOnOs({
win32: async () => {
const regRes = await regedit.promisified.list([this.livExternalAppsRegeditKey]).then(res => res[this.livExternalAppsRegeditKey]);
if(!regRes.exists){
return [];
}
const promises = regRes.keys.map(async key => {
const shortcutKey = path.join(this.livExternalAppsRegeditKey, key);
const entries = await regedit.promisified.list([shortcutKey]).then(res => res[shortcutKey]);
if(!entries.exists){
return undefined;
}
return {
id: key,
name: entries.values.Name.value,
installPath: entries.values.InstallPath.value,
executable: entries.values.Executable.value,
arguments: entries.values.Arguments.value
} as LivEntry;
});
return Promise.all(promises).then(entries => entries.filter(Boolean));
}
});
}
}
export interface LivEntry {
id: string,
name: string,
installPath: string,
executable: string,
arguments: string
}
@@ -38,6 +38,7 @@ export const LinkButton = motion(
!props.disabled && props.onClick?.();
}}
style={{ pointerEvents: props.disabled ? "none" : "auto" }}
tabIndex={-1}
>
<span className="absolute top-0 left-0 h-full w-full rounded-full brightness-50 opacity-75 dark:opacity-20 dark:filter-none" style={{ backgroundColor: linkedColor }} />
<BsmIcon className="p-1 absolute top-0 left-0 h-full w-full !bg-transparent -rotate-45 brightness-150" icon={props.linked ? "link" : "unlink"} style={{ color: linkedColor }} />
@@ -12,7 +12,6 @@ import { AudioPlayerService } from "renderer/services/audio-player.service";
import { useObservable } from "renderer/hooks/use-observable.hook";
import { map } from "rxjs/operators";
import equal from "fast-deep-equal/es6";
import { getMapZipUrlFromHash } from "renderer/helpers/maps-utils";
import { BsmBasicSpinner } from "../shared/bsm-basic-spinner/bsm-basic-spinner.component";
import defaultImage from "../../../../assets/images/default-version-img.jpg";
import { useTranslation } from "renderer/hooks/use-translation.hook";
@@ -73,8 +72,7 @@ export const MapItem = memo(({ hash, title, autor, songAutor, coverUrl, songUrl,
const songPlaying = useObservable(audioPlayer.playing$.pipe(map(playing => playing && audioPlayer.src === songUrl)));
const zipUrl = getMapZipUrlFromHash(hash);
const previewUrl = mapId ? `https://skystudioapps.com/bs-viewer/?url=${zipUrl}` : null;
const previewUrl = mapId ? `https://allpoland.github.io/ArcViewer/?id=${mapId}` : null;
const mapUrl = mapId ? `https://beatsaver.com/maps/${mapId}` : null;
const authorUrl = autorId ? `https://beatsaver.com/profile/${autorId}` : null;
const createdDate = createdAt ? dateFormat(createdAt, "d mmm yyyy") : null;
@@ -121,6 +121,7 @@ export function MapsPlaylistsPanel({ version, isActive }: Props) {
e.stopPropagation();
onClickAdd(index);
}}
tabIndex={-1}
>
<span className="absolute top-0 left-0 h-full w-full brightness-50 opacity-75 dark:opacity-20 dark:filter-none" style={{ backgroundColor: "currentcolor" }} />
<motion.div className="h-full p-0.5" variants={variants}>
@@ -11,21 +11,37 @@ import { useThemeColor } from "renderer/hooks/use-theme-color.hook";
import Tippy from "@tippyjs/react";
import { useTranslation } from "renderer/hooks/use-translation.hook";
import { useService } from "renderer/hooks/use-service.hook";
import { BsDownloaderService } from "renderer/services/bs-downloader.service";
import { distinctUntilChanged } from "rxjs";
import equal from "fast-deep-equal";
export function NavBar() {
const bsVersionServoce = useService(BSVersionManagerService);
const versionManager = useService(BSVersionManagerService);
const versionDownloader = useService(BsDownloaderService);
const downloadingVersion = useObservable(versionDownloader.currentBsVersionDownload$.pipe(distinctUntilChanged(equal)));
const installedVersions = useObservable(versionManager.installedVersions$);
const installedVersions = useObservable(bsVersionServoce.installedVersions$);
const color = useThemeColor("first-color");
const t = useTranslation();
function listVersions(){
const versions = Array.isArray(installedVersions) ? [...installedVersions] : [];
if (downloadingVersion){ versions.push(downloadingVersion); }
const sorted = versions.sort((a, b) => +b.ReleaseDate - +a.ReleaseDate);
return BSVersionManagerService.removeDuplicateVersions(sorted);
}
return (
<nav id="nav-bar" className="z-10 flex flex-col h-full max-h-full items-center p-1">
<BsManagerIcon className="relative aspect-square w-16 h-16 mb-3" />
<ol id="versions" className="w-fit max-w-[120px] relative left-[2px] grow overflow-y-hidden scrollbar-track-transparent scrollbar-thin scrollbar-thumb-rounded-full scrollbar-thumb-neutral-900 hover:overflow-y-scroll">
<SharedNavBarItem />
<NavBarSpliter />
{installedVersions?.map(version => (
{listVersions().map(version => (
<BsVersionItem key={JSON.stringify(version)} version={version} />
))}
</ol>
@@ -18,7 +18,7 @@ export function BsmIframeView() {
<div className="top-0 absolute w-screen h-screen flex content-center items-center justify-center z-[150]">
<motion.span className="absolute w-full h-full bg-black top-0 right-0" initial={{ opacity: 0 }} animate={{ opacity: 0.6 }} exit={{ opacity: 0 }} transition={{ duration: 0.2 }} />
<motion.div ref={ref} className="z-[1] w-[calc(100vw-250px)] h-[calc(100vh-250px)] shadow-black shadow-md rounded-md overflow-hidden bg-black" initial={{ y: "100vh" }} animate={{ y: 0 }} exit={{ y: "100vh" }}>
<iframe className="w-full h-full" src={iframeUrl} />
<iframe className="w-full h-full" src={iframeUrl} allowFullScreen/>
</motion.div>
</div>
)}
@@ -31,6 +31,11 @@ export function LaunchSlide({ version }: Props) {
configService.set("additionnal-args", additionalArgsString);
}, [additionalArgsString]);
useEffect(() => {
if(desktopMode){ return; }
bsLauncherService.restoreSteamVR();
}, [desktopMode]);
const setMode = (mode: LaunchMods, value: boolean) => {
if (mode === LaunchMods.DEBUG_MOD) {
setDebugMode(value);
-10
View File
@@ -1,10 +0,0 @@
import { BsvMapDetail } from "shared/models/maps";
export function getMapZipUrlFromMapDetails(map: BsvMapDetail) {
const { hash } = map.versions.at(0);
return getMapZipUrlFromHash(hash);
}
export function getMapZipUrlFromHash(hash: string) {
return `https://r2cdn.beatsaver.com/${hash}.zip`;
}
+2 -12
View File
@@ -1,6 +1,6 @@
import { DownloadInfo } from "main/services/bs-installer.service";
import { BehaviorSubject, Observable, ReplaySubject, Subscription, lastValueFrom, throwError } from "rxjs";
import { distinctUntilChanged, filter, map, share, take, tap, throttleTime } from "rxjs/operators";
import { filter, map, share, take, tap, throttleTime } from "rxjs/operators";
import { BSVersion } from "shared/bs-version.interface";
import { AuthUserService } from "./auth-user.service";
import { BSVersionManagerService } from "./bs-version-manager.service";
@@ -12,7 +12,6 @@ import { LoginModal } from "renderer/components/modal/modal-types/login-modal.co
import { GuardModal } from "renderer/components/modal/modal-types/guard-modal.component";
import { LinkOpenerService } from "./link-opener.service";
import { DepotDownloaderErrorEvent, DepotDownloaderEvent, DepotDownloaderEventType, DepotDownloaderInfoEvent, DepotDownloaderWarningEvent } from "../../shared/models/depot-downloader.model";
import equal from "fast-deep-equal";
import { SteamMobileApproveModal } from "renderer/components/modal/modal-types/steam-mobile-approve-modal.component";
export class BsDownloaderService {
@@ -45,15 +44,6 @@ export class BsDownloaderService {
this.progressBarService = ProgressBarService.getInstance();
this.notificationService = NotificationService.getInstance();
this.linkOpener = LinkOpenerService.getInstance();
this.currentBsVersionDownload$.pipe(distinctUntilChanged(equal)).subscribe(version => {
if(version) {
this.bsVersionManager.setInstalledVersions([...this.bsVersionManager.installedVersions$.value, version ]);
}
else {
this.bsVersionManager.askInstalledVersions();
}
});
}
public isDotNet6Installed(): Promise<boolean> {
@@ -281,7 +271,7 @@ export class BsDownloaderService {
this.currentBsVersionDownload$.next(null);
this.progressBarService.hide(true);
this.isVerification$.next(false);
this.bsVersionManager.askAvailableVersions();
this.bsVersionManager.askInstalledVersions();
});
}
+5 -2
View File
@@ -2,7 +2,7 @@ import { LaunchOption, BSLaunchEvent, BSLaunchWarning, BSLaunchEventData, BSLaun
import { BSVersion } from 'shared/bs-version.interface';
import { IpcService } from "./ipc.service";
import { NotificationService } from "./notification.service";
import { BehaviorSubject, Observable, filter } from "rxjs";
import { BehaviorSubject, Observable, filter, lastValueFrom } from "rxjs";
import { ConfigurationService } from "./configuration.service";
import { ThemeService } from "./theme.service";
@@ -37,7 +37,7 @@ export class BSLauncherService {
additionalArgs: (this.config.get<string>("additionnal-args") || "").split(";").map(arg => arg.trim()).filter(arg => arg.length > 0)
}
}
public doLaunch(launchOptions: LaunchOption): Observable<BSLaunchEventData>{
return this.ipcService.sendV2<BSLaunchEventData, LaunchOption>("bs-launch.launch", {args: launchOptions});
}
@@ -73,6 +73,9 @@ export class BSLauncherService {
return this.ipcService.sendV2<void, LaunchOption>("create-launch-shortcut", {args: options});
}
public restoreSteamVR(): Promise<void>{
return lastValueFrom(this.ipcService.sendV2<void, void>("bs-launch.restore-steamvr"));
}
}
export enum LaunchMods {
@@ -5,6 +5,7 @@ import { ModalExitCode, ModalService } from "./modale.service";
import { NotificationService } from "./notification.service";
import { ProgressBarService } from "./progress-bar.service";
import { EditVersionModal } from "renderer/components/modal/modal-types/edit-version-modal.component";
import { swapElements } from "shared/helpers/array.helpers";
export class BSVersionManagerService {
private static instance: BSVersionManagerService;
@@ -33,17 +34,19 @@ export class BSVersionManagerService {
}
public setInstalledVersions(versions: BSVersion[]) {
const sorted: BSVersion[] = [...versions].sort((a, b) => +b.ReleaseDate - +a.ReleaseDate);
const sorted: BSVersion[] = versions.sort((a, b) => +b.ReleaseDate - +a.ReleaseDate);
const steamIndex = sorted.findIndex(v => v.steam);
const oculusIndex = sorted.findIndex(v => v.oculus);
if (steamIndex > 0) {
[sorted[0], sorted[steamIndex]] = [sorted[steamIndex], sorted[0]];
swapElements(steamIndex, 0, sorted);
}
if (oculusIndex > 0) {
[sorted[steamIndex > 0 ? 1 : 0], sorted[steamIndex]] = [sorted[steamIndex], sorted[steamIndex > 0 ? 1 : 0]];
swapElements(oculusIndex, steamIndex >= 0 ? 1 : 0, sorted);
}
const cleanedSort = [...new Map(sorted.map(version => [`${version.BSVersion}-${version.name}-${version.steam}-${version.oculus}`, version])).values()];
this.installedVersions$.next(cleanedSort);
this.installedVersions$.next(BSVersionManagerService.removeDuplicateVersions(sorted));
}
public getInstalledVersions(): BSVersion[] {
@@ -119,4 +122,17 @@ export class BSVersionManagerService {
public getVersionPath(version: BSVersion): Observable<string> {
return this.ipcService.sendV2("get-version-full-path", { args: version });
}
public static removeDuplicateVersions(versions: BSVersion[]): BSVersion[] {
return Array.from(new Map(versions.map(version => ([
JSON.stringify([
version.BSVersion,
version.BSManifest,
version.name,
version.steam,
version.oculus
]),
version
]))).values());
}
}
+5
View File
@@ -5,3 +5,8 @@ export function splitIntoChunk<T = unknown>(arr: T[], chunkSize: number): T[][]
}
return resArr;
}
export function swapElements<T = unknown>(from: number, to: number, arr: T[]): T[] {
[arr[from], arr[to]] = [arr[to], arr[from]];
return arr;
}
+7
View File
@@ -0,0 +1,7 @@
export function tryit<Return>(func: () => Return): {error: Error, result: Return} {
try {
return { error: null, result: func() };
} catch (err) {
return { error: err instanceof Error ? err : new Error(`${err}`), result: null }
}
}