Compare commits

..

422 Commits

Author SHA1 Message Date
MathieuG-P ad4da530eb bumb to 1.5.0-alpha.4 2024-09-16 22:07:15 +02:00
MathieuG-P e4a894f75a [bugfix] Choose content folder was asked after each restart of BSM + add a log 2024-09-16 22:06:59 +02:00
MathieuG-P 1a62ae67c9 add patreon 2024-09-12 21:11:06 +02:00
MathieuG-P 78951f0de1 [chore] temporary add my name in readme for code signing certificate verification 2024-09-11 20:45:58 +02:00
MathieuG-P fd52fb8d78 Merge pull request #566 from silentrald/feat/560
[feat-560] ask user for installation folder/path
2024-09-11 12:45:37 +02:00
MathieuG-P e14ba2727b [feature-560] translations 2024-09-10 21:18:46 +02:00
MathieuG-P f6cd2fc316 Merge pull request #577 from silentrald/bugfix/linux-bs-version-readonly
[bugfix] use static config for version list in linux
2024-09-10 20:25:18 +02:00
silentrald 57f0679f57 [bugfix] use static config for version list in linux 2024-09-10 00:47:25 +08:00
Iluhadesu d407b396cf Add v1.37.5 to bs-versions.json 2024-09-07 01:35:36 +00:00
Iluhadesu 4bfc00d698 Add v1.37.4 to bs-versions.json 2024-09-05 16:02:25 +00:00
silentrald bd371b56e1 [bugfix-560] don't move old installation path if it doesn't exist 2024-09-05 09:37:32 +08:00
MathieuG-P 7ae097b990 [feature-560] some adjustments 2024-09-04 20:45:28 +02:00
silentrald 9734d714d7 [refactor] created installation-location.service.ts on client side 2024-09-04 08:57:19 +08:00
silentrald 9c86adf2d4 [feat-560] applied PR comments 2024-09-04 08:52:43 +08:00
silentrald 6258de5b06 [feat-560] added description text and default button tooltip
added tooltip support in BsmButton component
2024-09-04 08:52:43 +08:00
silentrald d3c797041f [feat-560] delay song details cache loading after user setup is done
added check if ElectronStore is null
2024-09-04 08:52:40 +08:00
silentrald 5e6837b8cd [feat-560] ask user for installation folder/path 2024-09-04 08:21:26 +08:00
MathieuG-P eba2b6fb03 Add patreon 2024-09-02 23:17:03 +02:00
MathieuG-P 1b2b8baa48 Merge pull request #572 from Zagrios/feature/add-advanced-settings
[feature] add advanced settings
2024-09-01 22:58:40 +02:00
MathieuG-P 846945b75a [feature] fix sonarlint issues 2024-09-01 22:55:21 +02:00
MathieuG-P f84758c42d [feature] translate + simplify code 2024-09-01 22:46:08 +02:00
MathieuG-P 55aeab896c [feature] disable hardware acceleration and use symlinks work, just still need to translate 2024-09-01 18:08:03 +02:00
MathieuG-P ac62926f8d [feature] create toogle gid for advanced settings 2024-08-29 22:30:29 +02:00
MathieuG-P 98bfbfa868 remove console log 2024-08-29 19:37:16 +02:00
MathieuG-P 150efb1a5c nothing 2024-08-29 19:34:56 +02:00
Iluhadesu b68c84dd6a Bump Beat Saber recommended version to 1.37.1 2024-08-26 17:05:22 +00:00
MathieuG-P 3145d2fdfa Merge pull request #568 from Zagrios/bugfix/improve-folder-linking-reliability
[bugfix] Improve folder linking reliability
2024-08-25 16:32:22 +02:00
MathieuG-P dac67ebe4e [bugfix] dont move the folder if all subitem in the folder already exist in the destination 2024-08-25 16:21:04 +02:00
MathieuG-P aea325a254 [bugfix] Improve folder linking reliability 2024-08-25 15:03:08 +02:00
MathieuG-P 462499fe81 Merge pull request #567 from silentrald/bugfix/bsipa-linux
[bugfix] wrap dotnet cmdlet's path argument with double quotes for installing bsipa
2024-08-24 15:57:56 +02:00
silentrald f6f69e2f13 [bugfix] wrap dotnet cmdlet's path argument with double quotes for installing bsipa 2024-08-24 21:41:10 +08:00
MathieuG-P c7ac3f2d9c Merge pull request #564 from Zagrios/bugfix/mods-using-manifests-sometimes-was-not-recognised-as-installed
[bugfix] Sometime mods using manifests were not recognised as installed + remove dead code
2024-08-20 21:16:11 +02:00
MathieuG-P cb95d5d88d [bugfix] Sometime mods using manifests were not recognised as installed + remove dead code 2024-08-20 21:06:37 +02:00
MathieuG-P 388ad76780 Merge pull request #563 from Zagrios/bugfix/translate-all-mods-already-notification
[bugfix] translate all mods already notification
2024-08-19 21:12:23 +02:00
MathieuG-P be4afb71e3 Merge pull request #562 from joriskleiber/window-restore-icon
Add window restore icon
2024-08-19 20:35:35 +02:00
MathieuG-P 11ddfc29b5 [bugfix] translate all mods already notification 2024-08-19 20:30:06 +02:00
joriskleiber b1eaad8df0 add window restore icon 2024-08-19 20:20:15 +02:00
Iluhadesu 36fc7cb9e2 Remove the . in the version name once again... 2024-08-19 10:28:48 +00:00
Iluhadesu 8df9516c11 Add v.1.37.3 to bs-versions.json 2024-08-19 10:27:39 +00:00
MathieuG-P 6bd8727067 Merge pull request #559 from kgabriel-dev/chore/improved-german-language/544
Improving the German language file
2024-08-17 21:51:56 +02:00
GabiKleebi02 b620b11eb5 improve German language file 2024-08-12 22:23:09 +02:00
MathieuG-P 3ff3ec7410 Merge pull request #558 from Zagrios/bugfix/466/bsmanager-does-not-handle-mods-with-missing-dependencies-on-beatmods
[bugfix-466] fix potential crashs when beatmods mod has invalid dependencies
2024-08-12 21:02:57 +02:00
MathieuG-P 8f9b3405bc Merge pull request #557 from Zagrios/bugfix/520/bug-unselect-item-when-you-switch-tab
[bugfix-520] clear selected items when switching BS version tab
2024-08-12 20:54:53 +02:00
MathieuG-P 698058710f [bugfix-466] fix potential crashs when beatmods mod has invalid dependencies 2024-08-12 20:53:51 +02:00
MathieuG-P 5fbc69e772 [bugfix-520] clear selected items when switching BS version tab + remove a console log 2024-08-12 20:22:33 +02:00
MathieuG-P daa2f864cc Merge pull request #555 from Insprill/fix/linux-admin
Fix Steam elevated check on Linux
2024-08-12 19:10:34 +02:00
Pierce Thompson f073f66533 Fix Steam elevated check on Linux 2024-08-10 18:00:07 -04:00
MathieuG-P ff9bede111 Merge pull request #554 from Zagrios/bugfix/542/exclude-tag-result-in-javascript-error
[bugfix-542] Fix crash when exclude map tag when browsing for new maps
2024-08-10 15:37:55 +02:00
MathieuG-P 650338d25b [bugfix-542] Fix crash when exclude map tag when browsing for new maps 2024-08-10 15:34:07 +02:00
MathieuG-P be32418b93 nothing 2024-08-10 15:19:02 +02:00
MathieuG-P 3bb9250269 Merge pull request #553 from Zagrios/feature/550/feat-show-any-number-stats-for-unranked-maps-difficulty
[feature-550] When its possible display the NPS ou NJS of the map instead of just the difficulty
2024-08-10 15:16:37 +02:00
MathieuG-P 13da659c0d [feature-550] When its possible display the NPS ou NJS of the map instead of just the difficulty 2024-08-10 15:10:49 +02:00
MathieuG-P 9f4a133b74 Update package-lock.json and release/app/package-lock.json to version 1.5.0-alpha.3 2024-08-07 10:53:24 +02:00
MathieuG-P 25b647630f [chore] add step to install correct Node version in the contributing guide 2024-08-07 10:53:12 +02:00
Iluhadesu 373c6b979d Correct version typo because they can't type 2024-08-06 12:56:57 +00:00
Iluhadesu ded5b58020 Add v.1.37.2 to bs-versions.json 2024-08-06 12:55:33 +00:00
Zagrios 763b3c65f5 fix depotdownload on linux again 2024-08-04 15:20:12 +02:00
Zagrios ef69e64ad7 all file in script is binary 2024-08-04 15:13:56 +02:00
Zagrios d82b7bab54 fix depotdownloader on linux 2024-08-04 14:59:11 +02:00
Zagrios 095ceccc19 should fix depotdownload on linux 2024-08-04 14:36:06 +02:00
MathieuG-P 32e5ee98ad Merge pull request #547 from silentrald/fix/issue-546
[bugfix] exclude regedit-rs on externals when webpack bundles it in linux
2024-08-04 11:19:34 +02:00
silentrald b2a57ea307 [bugfix] exclude regedit-rs on externals when webpack bundles it in linux 2024-08-03 12:00:03 +08:00
MathieuG-P eb30400b7c update to 1.5.0-alpha.3 2024-08-01 01:06:38 +02:00
MathieuG-P 0fd1e211ba Merge pull request #541 from Zagrios/chore/filter-sensitive-data-in-logs
[chore] filter sensitive data in logs
2024-08-01 00:55:39 +02:00
MathieuG-P 64484bfd4e Merge branch 'master' into chore/filter-sensitive-data-in-logs 2024-08-01 00:51:27 +02:00
MathieuG-P 499956d3b3 update to 1.4.8 2024-08-01 00:23:32 +02:00
MathieuG-P c313685f6f [chore] filter potential oculus token in logs 2024-08-01 00:20:02 +02:00
MathieuG-P 2e750f3d5a chore : use name instead of "_id" beacause BeatMods is broken 2024-07-30 22:29:58 +02:00
MathieuG-P e1c3115668 Merge pull request #540 from Zagrios/qol/dont-reinstall-all-mods-by-default
[qol] dont reinstall all mods by default
2024-07-29 21:32:57 +02:00
MathieuG-P a6462530bb [qol] reinstall all translations + fix buttons sizing 2024-07-29 21:11:14 +02:00
MathieuG-P 8316a9ef80 [qol] fix transform style not working 2024-07-29 20:31:06 +02:00
MathieuG-P 152313289c [qol] install only mods not already installed (not finished) 2024-07-28 21:40:09 +02:00
MathieuG-P c96ad6f7cd Merge branch 'master' into qol/dont-reinstall-all-mods-by-default 2024-07-28 19:46:43 +02:00
MathieuG-P b7cf3c5d20 Merge pull request #539 from Zagrios/chore/update-to-electron-31
[chore] update to electron 31 + update deps
2024-07-28 16:51:24 +02:00
MathieuG-P 97d3c2a3ae [chore] update to electron 31 + update deps 2024-07-28 16:41:16 +02:00
MathieuG-P a20ebe2075 Merge pull request #537 from Zagrios/bugfix/536/bug-no-maps-found-for-tag-dance
[bugfix-536] Fix dance-style filter
2024-07-27 16:12:00 +02:00
MathieuG-P 2f5a74b155 [bugfix-536] Fix dance-style filter 2024-07-27 16:06:07 +02:00
MathieuG-P a20c73d0e9 [qol] dont reinstall all mods by default (not finnished) 2024-07-27 15:51:06 +02:00
MathieuG-P aeca1c1e9e Merge pull request #535 from Zagrios/qol/dont-select-default-mods-when-mods-are-installed
[QOL] Do not reselect default mods when mods are already installed
2024-07-25 20:50:12 +02:00
MathieuG-P b9ce95968c Merge pull request #530 from Zagrios/feature/feature/small-addition-to-the-version-list
[bugfix] fix incorrect active state in shared nav bar item
2024-07-25 20:39:38 +02:00
MathieuG-P 490ccfdc1e [qol] Do not reselect default mods when mods are already installed 2024-07-24 15:45:35 +02:00
Shidorien 6d0c6b4f64 remove useless console.log 2024-07-23 21:13:22 +02:00
Shidorien 89c3b0906b fix little issue 2024-07-23 21:06:22 +02:00
Shidorien 8cd74c3b0b fix incorrect active state in shared nav bar item 2024-07-23 20:31:33 +02:00
MathieuG-P 769dab2896 Add changelog for 1.5.0-alpha.2 2024-07-22 18:26:13 +02:00
MathieuG-P 8f1f998c5a Update to 1.5.0-alpha.2 2024-07-22 17:59:22 +02:00
MathieuG-P 48d03cccbb Merge pull request #524 from Zagrios/bugfix/fix-timeout-when-downloading-maps-from-bsv
[bugfix] Downloading maps sometimes times out
2024-07-21 15:44:30 +02:00
MathieuG-P 7d54ae79f7 Merge pull request #523 from Zagrios/bugfix/unable-to-install-bsipa-when-its-path-contain-spaces
[bugfix] unable to install BSIPA if BSIPA path was containing spaces
2024-07-21 15:41:23 +02:00
MathieuG-P c46fdd56f6 Merge pull request #522 from Zagrios/bugfix/495/bug-custom-map-runtime-not-displaying-correctly-in-bsmanager
[bugfix] fix sometimes maps duration were wrong
2024-07-21 15:41:10 +02:00
MathieuG-P 22dc1ca511 [bugfix] fix timeout when downloading maps 2024-07-21 15:36:33 +02:00
MathieuG-P 709105b9f4 [bugfix] fixed : unable to install BSIPA if BSIPA path was containing spaces + wrong translation when bsipa was throwing errors 2024-07-21 14:53:49 +02:00
MathieuG-P 1c0cfb6b89 [bugfix] playlist duraction was always NaN 2024-07-21 14:10:30 +02:00
MathieuG-P 7ebc1bff16 [bugfix] fix sometimes maps duration were wrong 2024-07-21 14:09:14 +02:00
MathieuG-P 0e1cda5050 Merge pull request #517 from Zagrios/bugfix/playlist-maps-with-malformed-hash-doesnt-get-loaded
[bugfix] fix playlist maps with malformed hash doesnt get loaded + improve playlist maps reading reliability
2024-07-17 20:42:12 +02:00
MathieuG-P 331626bd1e Merge pull request #518 from Zagrios/bugfix/crash-when-changing-audio-volume
[bugfix] fix crash when changing audio volume
2024-07-17 20:41:31 +02:00
MathieuG-P ea62f2443f [bugfix-517] use regex.exec instead of .match 2024-07-17 20:35:31 +02:00
MathieuG-P 532ab08e46 [bugfix] fix crash when changing audio volume 2024-07-17 20:32:53 +02:00
MathieuG-P a6fa55719d [bugfix] fix playlist maps with malformed hash doesnt get loaded + improve playlist maps reading reliability 2024-07-17 20:26:54 +02:00
MathieuG-P 163857a14f Merge pull request #513 from Zagrios/bugfix/bsm-crashs-when-loading-playlists-with-an-invalid-playlist-file
[bugfix] Bsm crashs when loading playlists with an invalid playlist file
2024-07-15 21:54:53 +02:00
MathieuG-P 854e0e2761 Merge branch 'master' into bugfix/bsm-crashs-when-loading-playlists-with-an-invalid-playlist-file 2024-07-15 21:50:13 +02:00
MathieuG-P eba6f916a3 Merge pull request #514 from Zagrios/bugfix/read-playlists-in-sub-folders
[bugfix] Playlists in sub folders doesn't get loaded
2024-07-15 21:43:03 +02:00
MathieuG-P 9790f35749 [bugfix] Playlists in sub folders doesn't get loaded 2024-07-15 21:35:26 +02:00
MathieuG-P 93d3cbc8bf [bugfix] Bsm crashs when loading playlists with an invalid playlist file 2024-07-15 20:59:26 +02:00
MathieuG-P 51ea1b130b Merge pull request #512 from Zagrios/chore/update-changelog
Chore/update changelog
2024-07-15 15:58:10 +02:00
shidorien d020b72f20 Add web site button to ChangelogModal component 2024-07-15 15:51:19 +02:00
shidorien f2ac952cd9 Update changelogs.json with new features, fixes, and improvements 2024-07-15 15:23:38 +02:00
shidorien 189d2388fb add missing scrollbar 2024-07-15 15:16:42 +02:00
shidorien 1c989a2402 Update changelog for BSManager 1.5.0-alpha.1 release 2024-07-15 15:11:17 +02:00
shidorien 959e60127d Update changelog for BSManager 1.5.0-alpha.1 2024-07-15 15:08:22 +02:00
shidorien 0faa0f1288 Update changelog for BSManager 1.5.0-alpha.1 2024-07-15 15:00:53 +02:00
shidorien 5ad25f58d5 Update changelogs.json with BSManager 1.5.0-alpha.1 release 2024-07-15 14:57:39 +02:00
shidorien 8ace5e6a7a Add changelog fort 1.5.0-alpha.1 2024-07-15 14:46:14 +02:00
MathieuG-P 185d01e7b4 version to 1.5.0-alpha.1 2024-07-14 22:34:29 +02:00
MathieuG-P 755e407372 Merge pull request #511 from Zagrios/bugfix/bsipa-installation-never-throw-error-even-if-bsipa-process-errors
[bugfix] During the BSIPA installation, no errors are displayed, even if BSIPA generates errors
2024-07-14 21:27:01 +02:00
MathieuG-P 4f123b69ef [bugfix] bsipa installation never show error even if bsipa throw errors 2024-07-14 21:22:25 +02:00
MathieuG-P 7e2334f8fc Merge pull request #509 from Insprill/fix/linux-build
Fix Linux build & crash on startup
2024-07-14 17:46:13 +02:00
MathieuG-P 5be533ccfb chore: Update Linux publishing command in package.json 2024-07-14 17:32:45 +02:00
MathieuG-P b8eafd5f9b chore: Update Linux publishing command in package.json 2024-07-14 17:23:19 +02:00
MathieuG-P 3f3bb959c4 Merge branch 'github-action/build-linux' 2024-07-14 17:17:21 +02:00
MathieuG-P f30cad74d7 chore: Add GitHub Actions workflow for releasing Linux 2024-07-14 17:15:31 +02:00
MathieuG-P ede82393da chore: update category in package.json 2024-07-14 17:11:19 +02:00
MathieuG-P 9ee468af03 add icons for linux 2024-07-14 16:41:07 +02:00
MathieuG-P c4d5db809b build for linux 2024-07-14 15:52:51 +02:00
Pierce Thompson 8ecc9d30b3 Fix Linux build 2024-07-13 15:13:15 -04:00
MathieuG-P ca722b2a18 fix displaying "no playlist found" when playlists is loading 2024-07-13 18:50:12 +02:00
MathieuG-P c219e9655d update deps 2024-07-13 18:45:50 +02:00
MathieuG-P a6c1ba9fee Merge pull request #508 from Zagrios/qol/mods-load-faster
[QOL] Mods load faster
2024-07-13 17:31:03 +02:00
MathieuG-P 6e9ea1bd9a Merge branch 'master' into qol/mods-load-faster 2024-07-13 17:21:48 +02:00
MathieuG-P 84f27d571b nothing 2024-07-13 17:21:32 +02:00
MathieuG-P 51549161cd [qol] change use hash cache to load installed mods faster 2024-07-13 17:17:43 +02:00
MathieuG-P 198002238e change recommended version to 1.37.0 2024-07-13 15:58:03 +02:00
MathieuG-P ae0ad4d2f6 Merge pull request #507 from Zagrios/qol/display-bs-version-when-no-mods-are-available
[qol] Display version string when saying "No mods available for this …
2024-07-11 21:51:46 +02:00
MathieuG-P e470782bea [qol] Display version string when saying "No mods available for this version of Beat Saber" 2024-07-11 21:46:00 +02:00
MathieuG-P b440c1b9e9 Merge pull request #506 from Zagrios/bugfix/499/cannot-uninstall-versions
[bugfix-499] unable to uninstall a bs version
2024-07-11 21:37:26 +02:00
MathieuG-P 163b95ff26 [bugfix-499] unable to uninstall a bs version 2024-07-11 21:28:28 +02:00
MathieuG-P 6fa3b95f32 Merge pull request #505 from Zagrios/v1.5.0
v1.5.0
2024-07-11 21:11:03 +02:00
MathieuG-P 773432a407 [playlist] fix error when cloning a playlist and some songs are missing 2024-07-11 20:58:37 +02:00
MathieuG-P 45bab6ccce Fix some sonarcloud issues 2024-07-11 20:57:30 +02:00
Iluhadesu 748b75ef3b Add v1.37.1 to bs-versions.json 2024-07-11 15:27:02 +00:00
MathieuG-P 116e4d77fa Fix lint errors 2024-07-10 21:30:05 +02:00
MathieuG-P c1322c4ed7 fix npm run lint 2024-07-10 20:26:50 +02:00
MathieuG-P f2ecd34672 Not blur models when they are installed 2024-07-10 20:26:41 +02:00
MathieuG-P 657a683d13 Merge pull request #451 from Insprill/feature/linux-launch
Add support for launching Beat Saber on Linux
2024-07-10 19:38:39 +02:00
MathieuG-P 0f038ccdc2 Merge pull request #503 from Zagrios/feature/playlists/107
Feature/playlists/107
2024-07-05 20:28:03 +02:00
MathieuG-P 6d38985581 [feature-107] some fixes 2024-07-04 21:25:36 +02:00
MathieuG-P 0edee845d7 Add patreon 2024-07-03 11:39:29 +02:00
MathieuG-P 517db1d056 [feature] fix light theme issues 2024-07-01 20:54:10 +02:00
MathieuG-P 65bf528a11 [feature-107] translations 2024-06-30 16:03:06 +02:00
MathieuG-P 07e32df91a add japanese dateformat 2024-06-29 21:38:03 +02:00
MathieuG-P 05a4386479 [feature-107] remove useless things 2024-06-28 07:45:44 +02:00
MathieuG-P 8c242e607b add patreon 2024-06-27 22:06:24 +02:00
MathieuG-P a721c16c85 [feature-107] Add loading/empty state texts for lists in playlist creation + minor fixes 2024-06-24 21:03:21 +02:00
MathieuG-P 0957080e22 [feature-107] Change the color of highlighted difficulties + other minor fixes 2024-06-24 19:51:17 +02:00
MathieuG-P 3427cae437 [feature-107] add diffictulties hightlight for playlist maps 2024-06-22 19:40:49 +02:00
MathieuG-P 33be4de2ff [feature-107] add drag and drop to playlist maps 2024-06-21 21:08:41 +02:00
MathieuG-P d83507a865 Merge pull request #498 from Insprill/fix/linux-build
Fix Linux crash on startup
2024-06-21 17:46:26 +02:00
MathieuG-P 44c63a63c6 [feature-107] playlist creation and edition is finished 2024-06-19 22:25:00 +02:00
MathieuG-P d299553d1e [feature-107] Advancement on playlist creation 2024-06-18 21:03:13 +02:00
Pierce Thompson 415d47a9e5 Don't try to start the game as admin on linux
Isn't supported
2024-06-16 23:59:37 -04:00
Pierce Thompson 9b8f1a7c42 Launch Beat Saber with Proton on Linux 2024-06-16 23:41:10 -04:00
Pierce Thompson 12a8a49ccb Add Proton path setting 2024-06-16 23:37:27 -04:00
Pierce Thompson 3cfc59982b Add x64 Linux GNU version of resvg to package-lock.json 2024-06-16 23:28:01 -04:00
MathieuG-P 5e1a021c3a [feature-107] progress on the modal for creating and editing playlists 2024-06-16 21:13:54 +02:00
MathieuG-P d6ba587db0 Merge pull request #496 from Zagrios/bugfix/494/advanced-launch-args-not-being-used-when-input-is-closed
[bugfix-494] use advanced args even if the input is closed
2024-06-15 18:14:23 +02:00
MathieuG-P 4075b2fcde [bugfix-494] use advanced args even if the input is closed + add a glow effect to show if an advanced arg is present 2024-06-15 18:07:37 +02:00
MathieuG-P b1ee9f054d [feature-107] start modal to create and edit playlists 2024-06-13 21:54:22 +02:00
MathieuG-P 15ebe8e929 [feature-107] minor fixes + use virtual scroll in playlists details view 2024-06-10 16:22:52 +02:00
MathieuG-P 901137ada9 [feature-107] local playlist filtering & can select playlist to perform actions : export, delete, sync 2024-06-09 22:45:03 +02:00
MathieuG-P ab07334cb8 Merge branch 'v1.5.0' into feature/playlists/107 2024-06-08 16:38:13 +02:00
MathieuG-P 7407b7dc83 Merge branch 'master' into v1.5.0 2024-06-08 16:34:17 +02:00
MathieuG-P 46824eb3ed Merge pull request #493 from Zagrios/chore/blur-nsfw-models-received-from-modelsaber
[chore] blur nsfw models received from modelsaber
2024-06-08 16:15:11 +02:00
MathieuG-P 1c9289f989 [chore] remove brigtness filter 2024-06-08 16:12:04 +02:00
MathieuG-P 64d6aa25e3 [chore] blur nsfw models 2024-06-08 16:09:28 +02:00
MathieuG-P 126024b70b spaces to tabs 2024-06-08 16:08:59 +02:00
MathieuG-P cb08374cbb fix import 2024-06-08 16:08:36 +02:00
MathieuG-P 22a217528c Merge branch 'master' into v1.5.0 2024-06-05 20:31:21 +02:00
MathieuG-P e9f297f186 update patreon name 2024-06-05 20:30:09 +02:00
MathieuG-P 934f857f96 Merge pull request #491 from Zagrios/feature/fix-changelog-issues
Feature/fix changelog issues
2024-06-05 20:05:52 +02:00
Shidorien 56dbeea691 Merge branch 'feature/fix-changelog-issues' of https://github.com/Zagrios/bs-manager into feature/fix-changelog-issues 2024-06-05 19:51:44 +02:00
Shidorien bff5123373 Fix error handling and logging in SettingsPage and AutoUpdaterService 2024-06-05 19:51:40 +02:00
GaetanGrd a48db98001 Update auto-updater.service.ts 2024-06-05 14:29:21 +02:00
MathieuG-P 850f39339a Add patreon 2024-06-05 12:31:33 +02:00
MathieuG-P f0cbb066e4 Merge pull request #489 from Zagrios/chore/use-self-contained-depot-downloader
[chore] use self contained depot downloader
2024-06-04 21:09:45 +02:00
Shidorien 8fefefd5ac Update bs-versions.json with new version 2024-06-04 21:08:56 +02:00
Shidorien 365818266c update translations for changelog not found messages 2024-06-04 21:08:31 +02:00
MathieuG-P 764eeff57a [chore] remove functions and translations that or no longer needed 2024-06-04 20:59:58 +02:00
MathieuG-P e713782b9f nothing 2024-06-04 20:59:29 +02:00
Zagrios d8cfad32a6 [chore] self-contained depotdownload works on linux 2024-06-04 20:57:08 +02:00
MathieuG-P 86c73239c9 [chore] use self contained DepotDownloader on windows 2024-06-04 20:57:08 +02:00
MathieuG-P 9af6c9a94a add 1.37.0 2024-06-04 17:55:17 +02:00
shidorien 9ffa0db43e Fix error handling in AutoUpdaterService and add error logging in SettingsPage 2024-06-02 19:16:39 +02:00
shidorien 5cf80ec6f2 Update bs-versions.json and package-lock.json 2024-06-02 19:16:28 +02:00
MathieuG-P 0ea355d75c [feature-107] multiple lists now uses virtual scroll 2024-06-01 20:25:50 +02:00
MathieuG-P 044174c711 [feature-107] Fix issues with virtualScroll + add on scrollEnd on virtualScroll + Fix issue with submit playlists filter 2024-05-30 20:20:40 +02:00
MathieuG-P 7562b07832 [feature-107] create generic component for virtual scrolling 2024-05-28 22:10:02 +02:00
MathieuG-P 0196206ec1 [feature-107] open playlist details from download modal + use new proto format for maps details cache 2024-05-27 00:25:36 +02:00
MathieuG-P d54464401f [feature-107] advancements on playlist filter panel 2024-05-23 23:11:35 +02:00
MathieuG-P 969be1e816 Merge branch 'v1.5.0' into feature/playlists/107 2024-05-21 20:38:38 +02:00
MathieuG-P d91a95ec0b Merge branch 'v1.5.0' of https://github.com/Zagrios/bs-manager into v1.5.0 2024-05-21 20:37:08 +02:00
MathieuG-P 89066411b1 Merge branch 'master' into v1.5.0 2024-05-21 20:37:06 +02:00
MathieuG-P 604dec8540 Merge pull request #485 from Zagrios/bugfix/launch-shortcut-windows-not-closing
[bugfix] Fix the issue where the launch shortcut window never closes after launching BS
2024-05-20 21:52:05 +02:00
MathieuG-P 32f03eaaa2 [bugfix] Fix the issue where the launch shortcut window never closes after launching BS 2024-05-20 21:43:11 +02:00
MathieuG-P 22769da7c5 Merge pull request #483 from Zagrios/revert-464-chore/use-winhttp-dll-to-detect-bsipa-installation
Revert "[chore] use winhttp.dll to detect bsipa installation"
2024-05-19 20:11:14 +02:00
MathieuG-P 69e573a12c Revert "[chore] use winhttp.dll to detect bsipa installation" 2024-05-19 20:07:58 +02:00
MathieuG-P 7f726537ff [feature-107] sorting works for download playlist modal 2024-05-19 20:07:03 +02:00
MathieuG-P 40b12c6285 Merge pull request #482 from Zagrios/bugfix/450/crash-on-launch-when-developing-with-v150
Bugfix/450/crash-on-launch-when-developing-with-v150
2024-05-19 10:52:58 +02:00
Zagrios 28f0a4d8c6 [bugfix-450] fix crash due to wrong app version on Linux 2024-05-19 10:49:10 +02:00
MathieuG-P 6e9c6e6c9e Merge pull request #477 from eliasbenb/feature/github-actions-build-workflow
GitHub Actions Build Workflow
2024-05-18 20:29:50 +02:00
MathieuG-P 281ae0bbc6 Merge pull request #480 from Zagrios/chore/update-readme
Add website bouton 👀and update twitter logo
2024-05-18 20:24:36 +02:00
GaetanGrd aad4cb9a2e Add website bouton 👀and update twitter logo 2024-05-18 19:12:06 +02:00
MathieuG-P cc0ec76d83 Merge pull request #478 from Zagrios/chore/update-readme
Update README.md
2024-05-15 20:44:48 +02:00
GaetanGrd 7b7cdd5559 Update README.md 2024-05-15 20:21:15 +02:00
MathieuG-P 4a2f7697f9 Merge branch 'master' of https://github.com/Zagrios/bs-manager 2024-05-15 16:46:58 +02:00
MathieuG-P cbab039ca4 add patreon 2024-05-15 16:46:56 +02:00
Elias Benbourenane 576cd2dec5 Initial test of a GH Actions build workflow 2024-05-14 20:56:12 +00:00
MathieuG-P c02ac39184 [feature-107] we can now download playlist from beatsaver + other internal changes 2024-05-12 19:32:54 +02:00
MathieuG-P 5eda9463c4 Merge pull request #476 from Aeywoo/patch-1
Clearer English translation for Steam Credentials popup
2024-05-09 15:49:08 +02:00
Aeywoo 41ef0164fd Update en.json
Clearer sentence structure, outlying why their credentials are required more clearly, how they are used and ensuring users are aware that their Steam credentials are only being used through DepotDownloader.
2024-05-09 02:49:39 -04:00
MathieuG-P c833df9884 Merge branch 'v1.5.0' into feature/playlists/107 2024-05-08 16:57:29 +02:00
MathieuG-P ba3cca79b4 Merge branch 'master' into v1.5.0 2024-05-08 16:56:27 +02:00
MathieuG-P ad6d9b57f8 Add 1.36.2 2024-05-06 18:25:08 +02:00
MathieuG-P d21271693e Merge pull request #472 from Zagrios/bugfix/wrong-mods-for-a-bs-version-shown
[bugfix] Fix wrong mods shown for a BS version
2024-04-30 23:21:08 +02:00
MathieuG-P 589c191ac2 Fix wrong mods shown for a BS version 2024-04-30 23:16:53 +02:00
MathieuG-P 6a326fd584 add patreon 2024-04-26 19:57:17 +02:00
MathieuG-P 0f430293a5 Merge pull request #464 from Zagrios/chore/use-winhttp-dll-to-detect-bsipa-installation
[chore] use winhttp.dll to detect bsipa installation
2024-04-20 16:33:20 +02:00
MathieuG-P 61ad8ba75b [chore] use winhttp.dll to detect bsipa installation 2024-04-20 16:27:32 +02:00
MathieuG-P 0cea1cd89f [feature-107] use size optimized song details cache 2024-04-20 16:22:07 +02:00
MathieuG-P 6836f18e89 Merge branch 'v1.5.0' into feature/playlists/107 2024-04-18 15:25:21 +02:00
MathieuG-P 0093c3970c Merge branch 'master' into v1.5.0 2024-04-18 15:24:51 +02:00
MathieuG-P 644a0c4e43 1.34.2 is now the recommended version 2024-04-16 16:21:48 +02:00
MathieuG-P c71c7a96e3 Add patreon 2024-04-15 12:39:16 +02:00
MathieuG-P 0e02e2e2b9 Merge branch 'v1.5.0' into feature/playlists/107 2024-04-11 19:11:51 +02:00
MathieuG-P 4537cbd539 Merge branch 'v1.5.0' of https://github.com/Zagrios/bs-manager into v1.5.0 2024-04-11 19:10:01 +02:00
MathieuG-P 0c185066f6 Merge branch 'master' into v1.5.0 2024-04-11 19:09:55 +02:00
MathieuG-P 5d5985f305 Merge pull request #453 from Zagrios/chore/sharp-to-resvg-js
[CHORE] migrate from sharp to resvg-js
2024-04-11 19:03:18 +02:00
MathieuG-P 744c3f18c7 Update @resvg/resvg-js version to 2.6.2 2024-04-11 18:55:30 +02:00
MathieuG-P 2a52ae3644 Merge branch 'master' into chore/sharp-to-resvg-js 2024-04-11 18:52:42 +02:00
MathieuG-P e822738a3b oups 2024-04-09 18:50:59 +02:00
MathieuG-P d185614d3b add 1.36.0 2024-04-09 18:50:45 +02:00
MathieuG-P c1a6a43825 Merge pull request #449 from Insprill/fix/linux-admin
Fix Steam elevated check on Linux
2024-03-29 03:35:18 +01:00
MathieuG-P b98e1ccdfa [feature-107] Advancement on playlists feature 2024-03-27 21:33:19 +01:00
Pierce Thompson 4797aab0aa Fix Steam elevated check on Linux 2024-03-26 18:43:04 -04:00
MathieuG-P 0460a0dab3 [feature-107] advancement on playlists feature 2024-03-24 17:51:18 +01:00
MathieuG-P 9cd5c48831 remove patreons 2024-03-23 14:01:54 +01:00
MathieuG-P e0f597e252 add patreon 2024-03-23 13:38:33 +01:00
MathieuG-P ebbe2963b1 Merge branch 'v1.5.0' into feature/playlists/107 2024-03-22 15:12:26 +01:00
MathieuG-P 541a14d2a7 Merge pull request #445 from Zagrios/chore/improve-ipc-robustness-and-remove-dead-code
[chore] improve ipc robustness and remove dead code
2024-03-22 14:45:06 +01:00
MathieuG-P 169a6e99b0 [chore] add routes for IPCs + migrate all old ipc.send to sendV2 + remove some dead code 2024-03-20 19:00:35 +01:00
MathieuG-P 3da5af354e [feature-107] We can now download playlist's missing maps 2024-03-19 18:01:07 +01:00
MathieuG-P 031c9044a1 Merge pull request #438 from Liborsaf/feature/edit-modal-name-reset-button
[feature] Add reset button for name to version edit modal
2024-03-19 14:17:26 +01:00
MathieuG-P 6d271d8c48 Merge branch 'master' into v1.5.0 2024-03-19 14:15:12 +01:00
MathieuG-P 8bc37ef3f1 Merge pull request #439 from Insprill/fix/linux-mods
Fix BSIPA not running on Linux
2024-03-18 19:20:30 +01:00
Pierce Thompson d7f3936619 Fix BSIPA not running on Linux 2024-03-16 21:07:05 -04:00
Libor Šafář 49358b7006 Add reset button for name to version edit modal 2024-03-15 17:44:22 +01:00
MathieuG-P 067b967da1 add patreon 2024-03-15 11:55:16 +01:00
MathieuG-P 88a1691d4b bumb to 1.4.7 2024-03-13 15:04:45 +01:00
MathieuG-P cdd25b458c Merge pull request #436 from Zagrios/bugfix/downloading-models-with-bsm-no-longer-works
[bugfix] fix downloading models not working
2024-03-13 14:55:42 +01:00
MathieuG-P 30a53c013f [bugfix] fix downloading models not working
Add useragent to requests to not being rejected
2024-03-13 14:51:51 +01:00
MathieuG-P 31e1ae2273 [chore] use resvg-js@2.6.1-beta.0 instead of sharp; Waiting the release of v2.6.1 to merge into master 2024-03-12 07:35:23 +01:00
MathieuG-P 7237e49c7f [feature-107] progress on playlists (lot of things, i don't remember all things i've done in this commit) 2024-03-12 06:49:32 +01:00
MathieuG-P 501def3a94 [feature-107] Audio player can now take list of songs to play 2024-03-08 18:21:05 +01:00
MathieuG-P f2cd9a1174 Merge branch 'v1.5.0' into feature/playlists/107 2024-03-08 16:33:10 +01:00
MathieuG-P d0fee6aaca [chore] add script to build all rust scripts 2024-03-08 16:31:20 +01:00
MathieuG-P 7c034550fb Merge branch 'master' into v1.5.0 2024-03-08 16:03:32 +01:00
MathieuG-P 1db3db7bdd Merge branch 'master' of https://github.com/Zagrios/bs-manager 2024-03-07 18:09:18 +01:00
MathieuG-P e0e647b22a add version 1.35.0 2024-03-07 18:08:15 +01:00
MathieuG-P 69914e3063 Merge pull request #435 from fllppi/bugfix/fixed-typo-in-german-translation/434
fixed typo in german translation for map installation
2024-03-07 05:59:44 +01:00
Flippi 0c2624ed37 fixed typo in german translation for map installation 2024-03-06 21:58:06 +01:00
MathieuG-P cf11277541 bumb to 1.4.6 2024-03-06 12:30:26 +01:00
MathieuG-P d028e144fc [chore] Oculus backup is now automatically restored when Beat Saber closes 2024-03-06 10:06:27 +01:00
MathieuG-P 59c624d58d Merge pull request #432 from Zagrios/bugfix/oculus-versions-being-deleted-by-oculus-auto-updates
[bugfix] Added a Beat Saber ends watcher to delete created symlink to avoid Oculus version getting wiped by Oculus auto updates
2024-03-05 13:54:32 +01:00
MathieuG-P 2d67876ee1 [bugfix] Added a Beat Saber ends watcher to delete created symlink to avoid Oculus version getting wiped by Oculus auto updates 2024-03-05 13:33:04 +01:00
MathieuG-P 6b30d74628 Merge pull request #431 from Zagrios/bugfix/handle-unable-to-get-documents-path
[bugfix] handle unable to get documents path error
2024-03-04 13:35:26 +01:00
MathieuG-P eb76bb5df0 [bugfix] handle unable to get documents path error 2024-03-04 13:29:23 +01:00
MathieuG-P 1e6f051f59 [feature-107] can now list maps of playlist + lot of other things 2024-03-02 17:50:08 +01:00
MathieuG-P 08bdc03745 [feature-107] Make playlist discoverable in shared tab + quik fix miss handle params in html file url 2024-02-27 22:52:18 +01:00
MathieuG-P 590daf3be2 add patreon 2024-02-27 18:26:27 +01:00
MathieuG-P de0575aea4 Merge branch 'v1.5.0' into feature/playlists/107 2024-02-26 15:33:13 +01:00
MathieuG-P 487d0c1f8b [feature-107] Implement playlists linking + remove possibility to play a playlist for now + some refacto 2024-02-26 15:24:51 +01:00
MathieuG-P ecf18b9967 Update translations and disable "exclude installed" filters in list of installed maps 2024-02-26 13:44:04 +01:00
MathieuG-P bc26f329a5 Merge pull request #426 from Liborsaf/feature/exclude-installed
[feature] Implement exclude of installed maps as filter
2024-02-26 13:05:01 +01:00
Libor Šafář 030df21619 Implement exclude of installed maps as filter 2024-02-24 22:49:25 +01:00
MathieuG-P ac5a9b16e5 Merge branch 'master' into v1.5.0 2024-02-24 21:19:18 +01:00
MathieuG-P e7f5e98fcd Add volta for release package.json + Update package.json dependencies and version numbers 2024-02-24 21:17:56 +01:00
MathieuG-P a36ccb0c13 [feature-107] Fix various bugs and add new features for playlists 2024-02-23 21:49:29 +01:00
MathieuG-P 59b04ee33e nothing 2024-02-20 14:04:45 +01:00
MathieuG-P b42231b134 [feature-107] lot of changes but mainly, maps now use a cache and load almost instantly after first load 2024-02-18 22:24:57 +01:00
MathieuG-P d61588c09f add patreon 2024-02-18 22:22:41 +01:00
MathieuG-P 7ed2b5c820 add OculusBinaryId 2024-02-16 16:07:20 +01:00
Iluhadesu 239a68821e Add 1.34.6 2024-02-16 15:53:59 +01:00
MathieuG-P fc512091e4 add patreon 2024-02-14 10:27:42 +01:00
MathieuG-P f71c29da58 bumb to 1.4.5 2024-02-12 16:35:04 +01:00
Iluhadesu 60c656b45b Add 1.34.5 2024-02-12 16:04:28 +01:00
MathieuG-P bec8e1f571 Merge pull request #417 from slinkstr/bugfix/fpfc-restore/416
[bugfix-416] Wait for SteamVR folder rename before exit
2024-02-12 15:22:57 +01:00
MathieuG-P 11661cc1da Merge pull request #381 from Zagrios/feature/add-changelog-modal/178
Feature/add changelog modal/178
2024-02-12 15:22:39 +01:00
Shidorien d7c43a2ba9 Add query-process package 2024-02-12 14:54:19 +01:00
Shidorien 14a65f1d69 Update dompurify version to 3.0.8 2024-02-12 14:52:17 +01:00
Shidorien bc9ab121b9 Merge branch 'v1.5.0' of https://github.com/Zagrios/bs-manager into feature/add-changelog-modal/178 2024-02-12 14:50:44 +01:00
Shidorien 0f0f7c1abb Remove unnecessary line in handleVersionClick function 2024-02-12 14:38:29 +01:00
Shidorien 1d9a261bc5 Merge branch 'master' into feature/add-changelog-modal/178 2024-02-12 14:36:52 +01:00
MathieuG-P 20d0cd7ee6 Merge pull request #421 from Zagrios/bugfix/unable-to-launch-oculus-version-when-backup-already-exists
[bugfix] Fixed unable to launch downgraded oculus version when backup already exist
2024-02-12 14:30:55 +01:00
MathieuG-P 3f37c2ee34 [bugfix] Fixed unable to launch downgraded oculus version when backup already exists 2024-02-12 14:19:59 +01:00
slinky 0b24a5ceb2 [bugfix-416] Wait for SteamVR folder rename before exit 2024-02-08 11:55:57 -08:00
MathieuG-P 9a3ebf2971 [feature-107] moving files around and create Playlist panel component 2024-02-07 16:36:25 +01:00
Shidorien e51ef0992c Merge branch 'master' into feature/add-changelog-modal/178 2024-02-07 12:33:44 +01:00
MathieuG-P 318a6b5afa add patreon 2024-02-06 22:30:08 +01:00
shidorien d9f025e28b Update translation strings for "not-found" in multiple languages 2024-02-05 11:14:32 +01:00
shidorien b4efa9583e Merge branch 'master' into feature/add-changelog-modal/178 2024-02-05 11:14:24 +01:00
MathieuG-P 1b4b59fbf0 Merge branch 'v1.5.0' into feature/playlists/107 2024-02-03 23:34:07 +01:00
MathieuG-P 8394581544 Disable react/function-component-definition rule in ESLint configuration 2024-02-03 23:32:58 +01:00
MathieuG-P 159d478e94 Merge branch 'v1.5.0' into feature/playlists/107 2024-02-03 23:22:36 +01:00
MathieuG-P 90bb8f2c19 Fix eslint rule for no-shadow 2024-02-03 23:22:28 +01:00
MathieuG-P 097b18e72f Merge branch 'v1.5.0' into feature/playlists/107 2024-02-03 23:20:23 +01:00
MathieuG-P 9b744fb1e2 Add react/jsx-filename-extension rule to .eslintrc.js 2024-02-03 23:20:09 +01:00
MathieuG-P 31f1ee1549 Merge branch 'v1.5.0' into feature/playlists/107 2024-02-03 16:04:11 +01:00
MathieuG-P c540308c2c Update ESLint rules 2024-02-03 16:03:37 +01:00
MathieuG-P 778b4f6ee6 [feature-107] Can now open .bplist file with BSManager 2024-02-03 16:03:17 +01:00
MathieuG-P df057cf82e Merge branch 'v1.5.0' into feature/playlists/107 2024-02-03 13:39:46 +01:00
MathieuG-P 5f94190b68 Merge branch 'master' into v1.5.0 2024-02-02 20:24:16 +01:00
MathieuG-P c80685065e Merge pull request #415 from Zagrios/bugfix/cannot-launch-bs-steam-is-elevated-error
[bugfix] handle errors when cheking if steam is running as admin
2024-02-02 20:23:19 +01:00
MathieuG-P cdc589f602 [bugfix] handle error when cheking if steam is running as admin 2024-02-02 20:18:33 +01:00
MathieuG-P 7718d239b2 use volta 2024-02-01 18:47:53 +01:00
MathieuG-P b29c9515d3 Merge pull request #414 from Zagrios/chore/migrate-to-electron-v28
[chore] migrate to electron v28 + esm support + updated deps + remove decorators (incompatible)
2024-02-01 18:33:00 +01:00
MathieuG-P 535831c03a [chore] migrate to electron v28 + esm support + update deps + remove decorators 2024-02-01 18:29:20 +01:00
MathieuG-P ee6acb7980 bumb to 1.4.4 2024-02-01 10:48:28 +01:00
MathieuG-P b03b670d56 [feature-107] add file associations for .bplist (not completed) 2024-02-01 10:45:39 +01:00
MathieuG-P 515ef06589 add patreon 2024-01-27 20:12:10 +01:00
MathieuG-P 344cce9461 Merge pull request #412 from Zagrios/bugfix/regedit-rs-broke-linux-support/411
[bugfix-411] dynamically import regedit-rs depending on the os
2024-01-27 13:53:05 +01:00
MathieuG-P 536690dc55 [bugfix-411] dynamically import regedit-rs depending on the os 2024-01-27 13:46:44 +01:00
MathieuG-P 4fc5a87c13 [chore] add checks and args whitelist for launching BS as admin 2024-01-25 21:44:58 +01:00
MathieuG-P 263061e7ce bumb to 1.4.4-alpha.2 2024-01-25 00:39:31 +01:00
MathieuG-P 0b7cad82d5 Merge pull request #408 from Zagrios/feature/admin-confirm-modal
[feature] Added admin launch information modal
2024-01-24 23:16:17 +01:00
MathieuG-P 63d35f678d [feature] Added admin launch information modal 2024-01-24 23:07:49 +01:00
MathieuG-P 16b9ca79f2 bumb version to 1.4.4-alpha.1 2024-01-21 16:55:26 +01:00
MathieuG-P 792ad9d777 [chore] fix lint error 2024-01-21 16:54:53 +01:00
MathieuG-P b6ecaa3934 bumb version to 1.4.4 2024-01-21 16:15:50 +01:00
MathieuG-P bb4ce5505a [chore] add @Log decorator + add logs for LivShortcuts 2024-01-21 15:22:09 +01:00
MathieuG-P d6aad2690c Merge pull request #405 from Zagrios/bugfix/launch-oculus-to-avoid-bs-crashs
[bugfix] Launch Oculus when launching Oculus BS version to avoid crashs
2024-01-20 16:49:02 +01:00
MathieuG-P cfb2b35bf7 [bugfix] Fix reject error message in OculusService 2024-01-20 16:38:52 +01:00
MathieuG-P 40f6803b90 [bugfix] Launch Oculus when launching Oculus BS version to avoid crashs 2024-01-20 16:36:59 +01:00
MathieuG-P d2c1d815a1 Merge pull request #404 from Zagrios/bugfix/bs-crash-when-steam-run-as-admin
[bugfix] Start BS as Admin when Steam is running as admin but BSM is not
2024-01-20 15:55:18 +01:00
MathieuG-P 4c8617a419 [bugfix] Start BS as Admin when Steam is running as admin but BSM is not 2024-01-20 15:42:30 +01:00
MathieuG-P 444db56d90 indent_size to 4 2024-01-14 02:33:09 +01:00
MathieuG-P 4b94b11b53 add patreon 2024-01-14 02:31:58 +01:00
MathieuG-P 1a9ed04cc2 Merge pull request #400 from Zagrios/bugfix/update-regedit-rs-for-static-link-dll
[bugfix] update regedit-rs for static link dll
2024-01-13 14:57:22 +01:00
MathieuG-P f3d4c64118 [bugfix] update regedit-rs for static link dll 2024-01-13 14:55:26 +01:00
Shidorien 1fd185fe88 Complete Review change 2024-01-10 21:57:45 +01:00
Shidorien 05154f577f spam mails 👀 2024-01-08 15:32:01 +01:00
Shidorien c62896f078 fix timeout and indent on handleVersionClick 2024-01-08 15:05:42 +01:00
Shidorien 2403f02851 Remove unnecessary blank line in handleVersionClick function 2024-01-08 10:18:16 +01:00
Shidorien b8262a941d Fix timestamp field name in changelogs.json and ChangelogVersion interface 2024-01-08 10:17:19 +01:00
Shidorien 8e8d608120 Refactor handleVersionClick function in SettingsPage component 2024-01-08 10:15:21 +01:00
Shidorien c92ca87c4c Refactor date variable in ChangelogModal component 2024-01-08 10:01:25 +01:00
Shidorien b02cd7fc77 Merge branch 'master' into feature/add-changelog-modal/178 2024-01-08 09:43:59 +01:00
Shidorien 86c1f5aa7b Update path to get changelog 2024-01-05 17:56:41 +01:00
shidorien cd5237aff3 👀 2024-01-05 17:39:12 +01:00
shidorien 5449792294 Change checkisUpdated to fix a bug 2024-01-05 17:38:05 +01:00
shidorien 5c35eae53a Fix changelog loading issue and update version check 2024-01-05 17:29:48 +01:00
shidorien 61889c0b5b Refactor auto-updater service and App component 2024-01-05 17:16:35 +01:00
Shidorien 4cf242f683 Add autoUpdater check in useEffect 2024-01-05 16:43:08 +01:00
Shidorien 3217addaa6 Add checkIsUpdated method to AutoUpdaterService 2024-01-05 16:38:22 +01:00
Shidorien 76ed1b09a1 add modification after firt review part 1 2024-01-05 16:31:17 +01:00
Shidorien 9401f1cf4a Update configuration key for last app version 2024-01-05 13:44:34 +01:00
Shidorien 6b4d919afe Add version check before showing changelog 2024-01-05 13:27:08 +01:00
Shidorien e92efa0ada Merge branch 'master' into feature/add-changelog-modal/178 2024-01-05 12:21:13 +01:00
shidorien 99a9f5b1de Fix conditional return in BsmButton component 2023-12-28 15:32:50 +01:00
shidorien 98bdbba23c Add tooltips to social media buttons in ChangelogModal 2023-12-28 15:32:37 +01:00
shidorien ddde1f8b8a Update package version to 1.4.3 2023-12-28 15:32:30 +01:00
shidorien b951be9511 Merge branch 'master' into feature/add-changelog-modal/178 2023-12-28 15:07:48 +01:00
shidorien b91d74f3a3 Fix xlink namespace in PatreonIcon component 2023-12-23 22:38:38 +01:00
shidorien 002b11d54c Refactor handleVersionClick function in SettingsPage component 2023-12-23 22:33:46 +01:00
shidorien 4e15d1c1b6 Update Patreon and Twitter icons 2023-12-23 22:33:31 +01:00
shidorien 961e629de8 Refactor ChangelogModal component 2023-12-23 22:31:27 +01:00
shidorien 02ad4b9c68 change location of changelogs an dremove unused import 2023-12-22 13:51:43 +01:00
shidorien a981adede0 Delete changelog files for multiple languages 2023-12-22 13:49:38 +01:00
Shidorien 33bab3ea0e reset useless change 2023-12-22 02:00:05 +01:00
Shidorien 7dae25ce32 Fix formatting in bs-launcher-ipcs.ts 2023-12-22 01:55:32 +01:00
Shidorien 71f317dd37 Update translations for changelogs 2023-12-22 01:39:19 +01:00
Shidorien 8333e238a6 Add "none" as a BsmButtonType option 2023-12-22 01:31:21 +01:00
Shidorien 39f2a16c96 Optimise and refactor changelog loading 2023-12-22 01:30:59 +01:00
Shidorien 2c08f1e07c Add cache for changelog and refactor methods in AutoUpdaterService 2023-12-22 01:28:58 +01:00
Shidorien f4560b9190 Refactor autoUpdater logic in App component 2023-12-22 01:28:42 +01:00
Shidorien f0f83e2b3b Update indent size to 4 spaces in .editorconfig 2023-12-22 01:28:29 +01:00
Shidorien 0776de8d79 Remove unused imports and styling in ChangelogModal component 2023-12-22 01:24:37 +01:00
Shidorien 504462258a Refactor AutoUpdaterService methods to use LAST_VERSION instead of have-been-updated 2023-12-21 21:17:15 +01:00
Shidorien fdef870e83 remove unnecessary code 2023-12-21 21:17:00 +01:00
Shidorien 7d58fec63b Fix autoUpdater showChangelog condition 2023-12-21 21:16:40 +01:00
Shidorien c77f4a9448 Refactor changelog modal component layout and styling 2023-12-21 21:03:53 +01:00
Shidorien 37a3951f7b Update changelog formatting 2023-12-21 19:41:11 +01:00
Shidorien e5599b78d8 Update changelog formatting 2023-12-21 19:33:30 +01:00
Shidorien 2da329367f Update changelog for version 27.1.3 2023-12-21 19:27:16 +01:00
Shidorien 0b64722092 update AutoUpdaterService status 2023-12-21 04:09:38 +01:00
Shidorien fbec5a0e46 Add logic to show changelog if available 2023-12-21 04:08:57 +01:00
Shidorien e21b731e10 Remove unnecessary code in window-manager-ipcs.ts 2023-12-21 04:08:45 +01:00
Shidorien 19998facc7 Update Patreon icon viewBox 2023-12-21 04:08:34 +01:00
Shidorien c8017939da Remove unnecessary code in launcher-ipcs.ts 2023-12-21 04:08:03 +01:00
Shidorien 75100e6919 Add AutoUpdaterService and show changelog when available 2023-12-21 02:59:22 +01:00
Shidorien 834dad0cc0 Refactor AutoUpdaterService imports and add error handling for getChangelog() and isChangelogAvailable() 2023-12-21 02:59:13 +01:00
Shidorien f57926e41b Remove unnecessary imports and variables 2023-12-21 02:58:12 +01:00
Shidorien 57157b4553 Remove unnecessary blank lines 2023-12-21 01:27:57 +01:00
Shidorien b2c1338650 Refactor AutoUpdaterService and remove unused code 2023-12-21 01:27:29 +01:00
Shidorien 1dde1b8916 Remove unused import and commented code in AutoUpdaterService 2023-12-21 00:58:24 +01:00
Shidorien 7e9b8ec86d Add @types/dompurify package 2023-12-21 00:57:01 +01:00
Shidorien ec0d2fb8c6 Add Changelog Modal component and fix import path in AutoUpdaterService 2023-12-21 00:48:21 +01:00
Shidorien 214ffc243d Update package-lock.json version to 1.4.2 2023-12-21 00:48:08 +01:00
Shidorien d243475bf8 Add dompurify library to package.json and package-lock.json 2023-12-21 00:47:59 +01:00
Shidorien 9872fcb856 Update changelog to version 27.1.3 2023-12-21 00:09:32 +01:00
Shidorien 29f7754ba9 Merge branch 'master' into feature/add-changelog-modal/178 2023-12-21 00:00:00 +01:00
GaetanGrd 9c440a0430 Update changelog for version 27.0.0 2023-11-24 10:48:54 +01:00
Shidorien aaf75278d0 Add ChangelogModal component (WIP) 2023-11-24 06:59:55 +01:00
Shidorien ae2cf08c7d Add changelog functionality to AutoUpdaterService 2023-11-24 06:59:44 +01:00
Shidorien 4a0848fb41 Add AutoUpdaterService and show changelog 2023-11-24 06:59:35 +01:00
Shidorien 76c863608e Update version numbers in changelog 2023-11-24 06:46:08 +01:00
Shidorien 8963c08e64 Add data test 2023-11-24 06:04:17 +01:00
Shidorien ba51e76691 add getHaveBeenUpdated method 2023-11-24 04:23:39 +01:00
Shidorien cb0faad418 Fix reply type in bs-launcher-ipcs.ts 2023-11-24 04:22:57 +01:00
Shidorien 00bf26081b move Update "haveBeenUpdated" when update is available 2023-11-24 03:06:22 +01:00
Shidorien 385c403bee Update "havebeenupdated" when close index.html 2023-11-24 03:03:38 +01:00
Shidorien 6c3a241481 Update "haveBeenUpdated" when update is available 2023-11-24 02:59:08 +01:00
Shidorien 34c0ad03d3 Add ipc "have-been-updated" 2023-11-24 02:53:36 +01:00
Shidorien 8c9846d751 Add ConfigurationService and methods for getting
and setting haveBeenUpdated flag
2023-11-24 02:46:34 +01:00
Shidorien 0d7c160b24 Adding JSON changelog 2023-11-24 02:22:58 +01:00
318 changed files with 22852 additions and 26974 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ root = true
[*]
indent_style = space
indent_size = 2
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
+13 -1
View File
@@ -6,8 +6,20 @@ import webpack from "webpack";
import webpackPaths from "./webpack.paths";
import { dependencies as externals } from "../../release/app/package.json";
function createExternals(): string[] {
const webpackExternals: string[] = [...Object.keys(externals || {})];
const excludedExternals: string[] = [];
if (process.platform === "linux") {
// Linux only uses regedit-rs types
excludedExternals.push("regedit-rs");
}
return webpackExternals.filter(external => !excludedExternals.includes(external));
}
const configuration: webpack.Configuration = {
externals: [...Object.keys(externals || {})],
externals: createExternals(),
stats: "errors-only",
+64
View File
@@ -0,0 +1,64 @@
/**
* Webpack config for development electron main process
*/
import path from 'path';
import webpack from 'webpack';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import { merge } from 'webpack-merge';
import checkNodeEnv from '../scripts/check-node-env';
import baseConfig from './webpack.config.base';
import webpackPaths from './webpack.paths';
// When an ESLint server is running, we can't set the NODE_ENV so we'll check if it's
// at the dev webpack config is not accidentally run in a production environment
if (process.env.NODE_ENV === 'production') {
checkNodeEnv('development');
}
const configuration: webpack.Configuration = {
devtool: 'inline-source-map',
mode: 'development',
target: 'electron-main',
entry: {
main: path.join(webpackPaths.srcMainPath, 'main.ts'),
preload: path.join(webpackPaths.srcMainPath, 'preload.ts'),
},
output: {
path: webpackPaths.dllPath,
filename: '[name].bundle.dev.js',
library: {
type: 'umd',
},
},
plugins: [
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
new BundleAnalyzerPlugin({
analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled',
analyzerPort: 8888,
}),
new webpack.DefinePlugin({
'process.type': '"browser"',
}),
],
/**
* Disables webpack processing of __dirname and __filename.
* If you run the bundle in node.js it falls back to these values of node.js.
* https://github.com/webpack/webpack/issues/2010
*/
node: {
__dirname: false,
__filename: false,
},
};
export default merge(baseConfig, configuration);
+1
View File
@@ -40,6 +40,7 @@ const configuration: webpack.Configuration = {
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
@@ -1,3 +1,4 @@
/* eslint-disable import/no-import-module-exports */
import "webpack-dev-server";
import path from "path";
import fs from "fs";
+4
View File
@@ -2,6 +2,9 @@ const path = require("path");
const rootPath = path.join(__dirname, "../..");
const erbPath = path.join(__dirname, '..');
const erbNodeModulesPath = path.join(erbPath, 'node_modules');
const dllPath = path.join(__dirname, "../dll");
const srcPath = path.join(rootPath, "src");
@@ -22,6 +25,7 @@ const buildPath = path.join(releasePath, "build");
export default {
rootPath,
erbNodeModulesPath,
dllPath,
srcPath,
srcMainPath,
+33
View File
@@ -0,0 +1,33 @@
import path from 'path';
import { copyFileSync, existsSync, readdirSync } from 'fs-extra';
import { execSync } from 'child_process';
const eternalsFolder = path.join(__dirname, '..', '..', 'externals');
// Get rust project folders from externals
const rustProjects = readdirSync(eternalsFolder).filter(folder => existsSync(path.join(eternalsFolder, folder, 'Cargo.toml')));
// Build each rust project in release mode
rustProjects.forEach(project => {
console.log(`Building ${project}`);
execSync(`cargo build --release`, {
cwd: path.join(eternalsFolder, project),
stdio: 'inherit',
});
});
// Copy the built files exe to the assests/scripts folder
rustProjects.forEach(project => {
// read the project name from Cargo.toml using toml parser
const projectMetadata = execSync('cargo metadata --no-deps --format-version 1', {
cwd: path.join(eternalsFolder, project),
stdio: 'pipe',
});
const projectMetadataJson = JSON.parse(projectMetadata);
const projectName = projectMetadataJson.packages[0].name;
const source = path.join(eternalsFolder, project, 'target', 'release', `${projectName}.exe`);
const destination = path.join(__dirname, '..', '..', 'assets', 'scripts', `${projectName}.exe`);
console.log(`Copying ${source} to ${destination}`);
copyFileSync(source, destination);
});
+10 -14
View File
@@ -1,17 +1,13 @@
import rimraf from "rimraf";
import process from "process";
import webpackPaths from "../configs/webpack.paths";
import { rimrafSync } from 'rimraf';
import fs from 'fs';
import webpackPaths from '../configs/webpack.paths';
const args = process.argv.slice(2);
const commandMap = {
dist: webpackPaths.distPath,
release: webpackPaths.releasePath,
dll: webpackPaths.dllPath,
};
const foldersToRemove = [
webpackPaths.distPath,
webpackPaths.buildPath,
webpackPaths.dllPath,
];
args.forEach(x => {
const pathToRemove = commandMap[x];
if (pathToRemove !== undefined) {
rimraf.sync(pathToRemove);
}
foldersToRemove.forEach((folder) => {
if (fs.existsSync(folder)) rimrafSync(folder);
});
+12 -5
View File
@@ -1,8 +1,15 @@
import path from "path";
import rimraf from "rimraf";
import webpackPaths from "../configs/webpack.paths";
import fs from 'fs';
import path from 'path';
import { rimrafSync } from 'rimraf';
import webpackPaths from '../configs/webpack.paths';
export default function deleteSourceMaps() {
rimraf.sync(path.join(webpackPaths.distMainPath, "*.js.map"));
rimraf.sync(path.join(webpackPaths.distRendererPath, "*.js.map"));
if (fs.existsSync(webpackPaths.distMainPath))
rimrafSync(path.join(webpackPaths.distMainPath, '*.js.map'), {
glob: true,
});
if (fs.existsSync(webpackPaths.distRendererPath))
rimrafSync(path.join(webpackPaths.distRendererPath, '*.js.map'), {
glob: true,
});
}
+8 -5
View File
@@ -1,9 +1,12 @@
import fs from "fs";
import webpackPaths from "../configs/webpack.paths";
import fs from 'fs';
import webpackPaths from '../configs/webpack.paths';
const { srcNodeModulesPath } = webpackPaths;
const { appNodeModulesPath } = webpackPaths;
const { srcNodeModulesPath, appNodeModulesPath, erbNodeModulesPath } = webpackPaths;
if (!fs.existsSync(srcNodeModulesPath) && fs.existsSync(appNodeModulesPath)) {
fs.symlinkSync(appNodeModulesPath, srcNodeModulesPath, "junction");
fs.symlinkSync(appNodeModulesPath, srcNodeModulesPath, 'junction');
}
if (!fs.existsSync(erbNodeModulesPath) && fs.existsSync(appNodeModulesPath)) {
fs.symlinkSync(appNodeModulesPath, erbNodeModulesPath, 'junction');
}
+25 -21
View File
@@ -1,28 +1,32 @@
const { notarize } = require("electron-notarize");
const { build } = require("../../package.json");
const { notarize } = require('@electron/notarize');
const { build } = require('../../package.json');
exports.default = async function notarizeMacos(context) {
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== "darwin") {
return;
}
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== 'darwin') {
return;
}
if (process.env.CI !== "true") {
console.warn("Skipping notarizing step. Packaging is not running in CI");
return;
}
if (process.env.CI !== 'true') {
console.warn('Skipping notarizing step. Packaging is not running in CI');
return;
}
if (!("APPLE_ID" in process.env && "APPLE_ID_PASS" in process.env)) {
console.warn("Skipping notarizing step. APPLE_ID and APPLE_ID_PASS env variables must be set");
return;
}
if (
!('APPLE_ID' in process.env && 'APPLE_APP_SPECIFIC_PASSWORD' in process.env)
) {
console.warn(
'Skipping notarizing step. APPLE_ID and APPLE_APP_SPECIFIC_PASSWORD env variables must be set',
);
return;
}
const appName = context.packager.appInfo.productFilename;
const appName = context.packager.appInfo.productFilename;
await notarize({
appBundleId: build.appId,
appPath: `${appOutDir}/${appName}.app`,
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_ID_PASS,
});
await notarize({
appBundleId: build.appId,
appPath: `${appOutDir}/${appName}.app`,
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_APP_SPECIFIC_PASSWORD,
});
};
+18 -2
View File
@@ -46,15 +46,30 @@ module.exports = {
"react/prop-types": "off",
"import/no-cycle": "off",
"prefer-promise-reject-errors": "off",
"react/jsx-no-target-blank": "off"
"react/jsx-no-target-blank": "off",
"import/extensions": "off",
"lines-between-class-members": "off",
"no-throw-literal": "warn",
"no-use-before-define": "off",
"no-useless-constructor": "off",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error",
'react/jsx-filename-extension': [2, { 'extensions': ['.js', '.jsx', '.ts', '.tsx'] }],
"no-shadow": "off",
"react/function-component-definition": "off",
"jsx-a11y/control-has-associated-label": "off",
"react/button-has-type": "off",
},
parserOptions: {
ecmaVersion: 2020,
sourceType: "module",
project: "./tsconfig.json",
tsconfigRootDir: __dirname,
createDefaultProgram: true,
},
globals: {
JSX: true,
NodeJS: true
},
settings: {
"import/resolver": {
// See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below
@@ -68,4 +83,5 @@ module.exports = {
"@typescript-eslint/parser": [".ts", ".tsx"],
},
},
"plugins": ["@typescript-eslint"]
};
+1
View File
@@ -15,3 +15,4 @@
*.ttf binary
*.woff binary
*.woff2 binary
assets/scripts/* binary
+34
View File
@@ -0,0 +1,34 @@
# This workflow will...
name: Build
on:
push:
branches: ["master"]
workflow_dispatch:
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, ubuntu-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 18.x
cache: "npm"
- run: npm ci
- run: npm run package
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: release-${{ matrix.os }}
path: release
-48
View File
@@ -1,48 +0,0 @@
name : e2e-tests
on:
push:
branches: ["master"]
pull_request:
branches: ["master"]
workflow_dispatch:
jobs:
e2e-tests-windows:
runs-on: windows-latest
steps:
- name: Cleanup files
run: cmd /r dir
- name: Checkout
uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18.x
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Install Playwright deps
run: npx playwright install --with-deps
- name: Build
run: npm run build
- name: Package
run: npm exec -c 'electron-builder build --publish "never" --win --x64'
- name: Run e2e tests
run: npm run e2e-test-ci
- name: Upload test results
if: always()
uses: actions/upload-artifact@v3
with:
name: playwright-output
path: test-results/
+35
View File
@@ -0,0 +1,35 @@
# This workflow will...
name: Realease Linux
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
on:
workflow_dispatch:
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 18.x
cache: "npm"
- run: npm ci
- run: npm run publish:linux
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: release
path: release
+2 -1
View File
@@ -28,4 +28,5 @@ npm-debug.log.*
*.sass.d.ts
*.scss.d.ts
test-results
# externals
externals/**/target/*
+1
View File
@@ -0,0 +1 @@
20.11.0
+1
View File
@@ -18,6 +18,7 @@ We'd also love PRs. If you're thinking of a large PR, we advise opening up an is
## Submitting a pull request
1. [Fork][fork] and clone the repository.
1. Install the correct NodeJS version (highly recommend installing [Volta](https://volta.sh/) for that).
1. Configure and install the dependencies: `npm install`.
1. Create a new branch following naming convention: `git checkout -b (feature|bugfix|hotfix|chore)/(short-description)(/issue-id)`.
1. Make your change, test, and make sure BSManager work fine.
+7 -7
View File
@@ -57,10 +57,12 @@
<a href="https://discord.gg/uSqbHVpKdV"><img
src="https://img.shields.io/badge/-DISCORD-5865f2?style=for-the-badge&logo=discord&logoColor=ffffff"
alt="discord" /></a>
<a href="https://www.patreon.com/bsmanager"><img
src="https://img.shields.io/badge/-🥰%20Support%20BSM-EC4546?style=for-the-badge" alt="Donation" /></a>
<a href="https://twitter.com/BSManager_"><img
src="https://img.shields.io/badge/-Twitter-F5F8FA?style=for-the-badge&logo=Twitter" alt="Twitter" /></a>
src="https://img.shields.io/badge/-Twitter-black?style=for-the-badge&logo=X" alt="Twitter" /></a>
<a href="https://www.bsmanager.io">
<img src="https://img.shields.io/badge/-WebSite-00649c?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiPgogIDxnIGZpbGw9IiMzYjgyZmYiPgogICAgPHBhdGggZD0ibTYyNi43NSA0ODUuOTEgMjAuODIgMzUxLjk0YTM1LjIxIDM1LjIxIDAgMCAxLTE1LjQ5IDMxLjM2bC0xNDQuNzEgOTYuMTRoLS4wNmEzNS41NiAzNS41NiAwIDAgMS0xMS4zMSA0Ljc3IDM0Ljg1IDM0Ljg1IDAgMCAxLTIzLjUxLTIuODdMMTM2LjU4IDgwOS45YTExNS40NSAxMTUuNDUgMCAwIDEtNjMuNzUtOTYuNDlMNTIgMzYxLjQ2YTM1LjI2IDM1LjI2IDAgMCAxIDE1LjIzLTMxLjIxbDE0NS4wNS05Ni4zNmEzNS43MiAzNS43MiAwIDAgMSAxMS4yNy00LjcgMzQuODcgMzQuODcgMCAwIDEgMjMuNTEgMi44N0w1NjMgMzg5LjQyYTExNS40MSAxMTUuNDEgMCAwIDEgNjMuNzUgOTYuNDlaIi8+CiAgICA8cGF0aCBmaWx0ZXI9ImJyaWdodG5lc3MoMzAlKSIgZD0ibTYxMy43OCA0ODYuNjcgMjAuODIgMzUyYTIyLjM0IDIyLjM0IDAgMCAxLTMyLjI2IDIxLjMxTDI4Ni40IDcwMi41N0ExMDIuNDMgMTAyLjQzIDAgMCAxIDIyOS44MyA2MTdMMjA5IDI2NWEyMi4zNSAyMi4zNSAwIDAgMSAzMi4yNi0yMS4zMkw1NTcuMiA0MDEuMDVhMTAyLjQyIDEwMi40MiAwIDAgMSA1Ni41OCA4NS42MloiLz4KICA8L2c+CiAgPHBhdGggZD0iTTcxOC4yOSA3NzYuNDggNzAwIDgwNC4xOGMtNDAuNjMgMzkuNS04Ny4wNiA2Ny4yNS0xMzMuODEgOTAuNzUtODcuMzIgNDMuOS0yMDMuNjcgNzcuMTktMjQ5IDkwLjM0YTQ4IDQ4IDAgMCAxLTI2LjE3LjE2Yy02NC0xNy43Mi0xODguNjItNzItMjM2LjI4LTEyNS40OWE0LjIzIDQuMjMgMCAwIDEgNS4zLTYuNDVjMzUuNjQgMjAuODcgMTExLjIyIDU3LjY0IDE1Ni4zNyA3NC4yMiA0OS4xOCAxOC4wNiA4MS4yOSA4Ljc0IDkyLjI4LTMuMjZhNC43NyA0Ljc3IDAgMCAxIDcuMjQuMjFjMTkuNTEgMjQgMTA3LjI2IDQuNiAxNjYuNjQtMTMgNjQuMzQtMTkgMTg1Ljg1LTc2LjU2IDIzNS43Mi0xMzUuMThabS0xOTYuMiAxNTcuMzMtMTQ3LjQ1IDU1LjY4YTMuOTIgMy45MiAwIDAgMCAxLjQ0IDcuNThsNTQuNjItLjc3YTM1LjYzIDM1LjYzIDAgMCAwIDE5LTUuNzlsNzYtNDkuNTVhNCA0IDAgMCAwLTMuNjEtNy4xNVpNMjE4LjkyIDE5NS41NmMtMjEuMTQuMDctMzMuNTUgMzUuODYtMzMuMTYgODkuMDguMiAyOCAyLjU4IDkyLjc0IDQuNzkgMTQ3LjczLjIzIDUuNzEtOC4xOCA2LjQ4LTkgLjgxbC0zOC40Mi0yNzAuNzFhNC4zOCA0LjM4IDAgMCAxIDcuMTItNCA2My42MyA2My42MyAwIDAgMCAyMS45MyAxMS44NSA0LjYxIDQuNjEgMCAwIDAgNS45LTMuNzJjNC4yLTI3LjcgMTYuNjMtNTguNzQgMzcuMzUtODguNzRhNC4zNiA0LjM2IDAgMCAxIDcuNTYuNjljMTAuODYgMjMuODcgNDkgMTAzLjggOTMuMzQgMTUyLjc5YTQuNjUgNC42NSAwIDAgMS01LjYyIDcuMjJjLTM2LjU3LTE5LjM4LTgzLjAxLTQzLjAyLTkxLjc5LTQzWm0tMTUuNDcgMzg0LjhhNC41MSA0LjUxIDAgMCAxLTQuNDYtMy45MmwtMTMuODItMTA3LjI5YTQuNSA0LjUgMCAwIDEgOC45My0xLjE1bDEzLjgyIDEwNy4yOWE0LjUgNC41IDAgMCAxLTMuODkgNSAzLjg2IDMuODYgMCAwIDEtLjU4LjA3Wk01NzcuMDggNTQuNThjLTQ2Ljc5IDE1Ljg1LTExNS40NSA0MC41Ni0xNTguNzMgNjIuNzlhMzUuNSAzNS41IDAgMCAwLTE4LjU3IDI0LjUzYy0zLjk1IDE5LjQ5LTExIDU2LjA5LTE5IDEwNy4yNi0uNyA0LjQ4LTcuMzYgMy43OC03LjExLS43NWwxMC42Ni0xOTQuNzNhMy43OCAzLjc4IDAgMCAxIDcuNDYtLjY2bDMuNDkgMTQuODVhMi41NyAyLjU3IDAgMCAwIDQuNjkuNzdjNi4xOC0xMCAyMi4zNy0zMi43OSA1Ny4zMi02NWE0LjEzIDQuMTMgMCAwIDEgNi41NiA0LjcybC0zMi41NCA3Mi44OXM3OC43OC0xOS4zNyAxNDQtMzMuMDljNC4xMS0uODcgNS42OSA1LjA4IDEuNzcgNi40MloiIGZpbGw9IiNmZmYiIHN0cm9rZT0iYmxhY2siLz4KICA8ZyBmaWxsPSIjZjQ0Ij4KICAgIDxwYXRoIGZpbHRlcj0iYnJpZ2h0bmVzcyg2MCUpIHNhdHVyYXRlKDEyMCUpIiBkPSJtOTQ3LjA3IDQxMC4zNS01Ny43NSAzNDcuNzlhMzUuMTggMzUuMTggMCAwIDEtMjIuMDYgMjcuMTVsLTE2Mi40MyA2MS42NWgtLjA2YTM1LjUyIDM1LjUyIDAgMCAxLTEyLjA2IDIuMTEgMzQuODMgMzQuODMgMCAwIDEtMjIuMjktOGwtMjczLjE3LTIyMy41YTExNS40MyAxMTUuNDMgMCAwIDEtNDAuNzYtMTA4LjIybDU3Ljc1LTM0Ny44QTM1LjI1IDM1LjI1IDAgMCAxIDQzNiAxMzQuNDdsMTYyLjgzLTYxLjc5YTM1LjUxIDM1LjUxIDAgMCAxIDEyLTIuMDggMzQuODMgMzQuODMgMCAwIDEgMjIuMjkgOGwyNzMuMTkgMjIzLjUyYTExNS4zOCAxMTUuMzggMCAwIDEgNDAuNzYgMTA4LjIzWiIvPgogICAgPHBhdGggZD0iTTkzNC4yNSA0MDguMjIgODc2LjUgNzU2YTIyLjM0IDIyLjM0IDAgMCAxLTM2LjE4IDEzLjYzbC0yNzMuMTctMjIzLjVhMTAyLjQyIDEwMi40MiAwIDAgMS0zNi4xNy05Nmw1Ny43NS0zNDcuODNhMjIuMzQgMjIuMzQgMCAwIDEgMzYuMTgtMTMuNjNsMjczLjE3IDIyMy41MWExMDIuNDIgMTAyLjQyIDAgMCAxIDM2LjE3IDk2LjA0WiIvPgogIDwvZz4KICA8ZWxsaXBzZSBmaWxsPSIjZmZmIiBzdHJva2U9ImJsYWNrIiBjeD0iNzMyLjYxIiBjeT0iNDI5LjE2IiByeD0iNjIuODMiIHJ5PSIxMTAuNzMiIHRyYW5zZm9ybT0icm90YXRlKC0xNS40NSA3MzIuNzAzIDQyOS4xOTkpIi8+Cjwvc3ZnPg==" alt="Website" /></a>
<a href="https://www.patreon.com/bsmanager"><img
src="https://img.shields.io/badge/-🤍%20Support%20BSM-EC4546?style=for-the-badge" alt="Donation" /></a>
</div>
<!--
@@ -287,13 +289,11 @@
<div>
<ul>
<li><strong>via Oculus</strong>: For Oculus users, <a href="https://github.com/Zagrios/bs-manager">BSManager</a>
uses authentication directly via the <a href="https://about.meta.com/fr/">META</a> website
to retrieve the connection token, ensuring reliable and secure access to your account data.</li>
requires you to retrieve a connection token by following the instructions in this guide: <a href="https://github.com/Zagrios/bs-manager/wiki/How-to-obtain-your-Oculus-Token">How to obtain your Oculus Token</a>. Once obtained, please insert it into the form.</li>
</ul>
</div>
<div align="center">
<img height=450 src="https://github.com/Zagrios/bs-manager/assets/40648115/1e4a2f98-af16-45aa-821d-0c4e90e1e54b" />
<img height=450 src="https://github.com/Zagrios/bs-manager/assets/40648115/3674e629-542d-4de3-b8db-b248f25126d7" />
</div>
@@ -546,7 +546,7 @@
<div>
<h2>Credits</h2>
<ul>
<li><a href="https://github.com/Zagrios">Zagrios</a> - Lead Developer & Founder.</li>
<li><a href="https://github.com/Zagrios">Zagrios - Mathieu GRIES-PEROZ</a> - Lead Developer & Founder.</li>
<li><a href="https://github.com/Iluhadesu">Iluhadesu</a> - Co-Developer & Co-Founder, Discord Bot Developer.</li>
<li><a href="https://github.com/GaetanGrd">GaetanGrd</a> - Co-Developer & Co-Founder, Documentation Lead.</li>
<li><a href="https://github.com/cheddZy">cheddZy</a> - Icon Creator.</li>
Binary file not shown.

After

Width:  |  Height:  |  Size: 401 KiB

+99 -2
View File
@@ -598,8 +598,7 @@
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/6169409105101272202",
"ReleaseImg": "https://cdn.akamai.steamstatic.com/steamcommunity/public/images/clans/32055887/c328e407367e9914abaf92f609501877ee5abb63.png",
"ReleaseDate": "1680623885",
"year": "2023",
"recommended": true
"year": "2023"
},
{
"BSVersion": "1.29.4",
@@ -681,5 +680,103 @@
"ReleaseImg": "https://clan.akamai.steamstatic.com/images/32055887/ae11d195bbe41a0f244d7b4d055a0ab89f88e5bb.png",
"ReleaseDate": "1702309893",
"year": "2023"
},
{
"BSVersion": "1.34.5",
"BSManifest": "7413405154512822201",
"OculusBinaryId": "6639053626194360",
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/4036983137766828694",
"ReleaseImg": "https://clan.cloudflare.steamstatic.com/images/32055887/925e60f14c6815f7617fde11a894ed20f54a0846.png",
"ReleaseDate": "1707745958",
"year": "2024"
},
{
"BSVersion": "1.34.6",
"BSManifest": "4398761375819224126",
"OculusBinaryId": "6682206641879058",
"ReleaseURL": "https://store.steampowered.com/news/app/620980/view/7595953477644376720",
"ReleaseImg": "https://clan.cloudflare.steamstatic.com/images/32055887/e7c75bdfc76d00713adc3fbdf221c9ce8ab3620d.png",
"ReleaseDate": "1708091473",
"year": "2024"
},
{
"BSVersion": "1.35.0",
"BSManifest": "1490986193481243578",
"OculusBinaryId": "6720809361352119",
"ReleaseURL": "https://store.steampowered.com/news/app/620980/view/4142820264819707009",
"ReleaseImg": "https://clan.cloudflare.steamstatic.com/images//32055887/9a141be5c44ca6fc81551a2c7e7f28407df413ed.png",
"ReleaseDate": "1709831174",
"year": "2024"
},
{
"BSVersion": "1.36.0",
"BSManifest": "8533509040167838423",
"OculusBinaryId": "6863072637125790",
"ReleaseURL": "https://store.steampowered.com/news/app/620980/view/4205873192610459250",
"ReleaseImg": "https://clan.akamai.steamstatic.com/images//32055887/b8bd8a050e2bc3903cf18a277c5489ade01f7e75.png",
"ReleaseDate": "1712681263",
"year": "2024"
},
{
"BSVersion": "1.36.2",
"BSManifest": "4832237377879752064",
"OculusBinaryId": "6983660338400352",
"ReleaseURL": "https://store.steampowered.com/news/app/620980/view/4181105931135110118",
"ReleaseImg": "https://clan.cloudflare.steamstatic.com/images//32055887/74541417f14dee210bcfd89eefeabd7c0cc27c7d.png",
"ReleaseDate": "1715008020",
"year": "2024"
},
{
"BSVersion": "1.37.0",
"BSManifest": "7270690075584855288",
"OculusBinaryId": "7062062833893435",
"ReleaseURL": "https://store.steampowered.com/news/app/620980/view/4161968170153497460",
"ReleaseImg": "https://clan.akamai.steamstatic.com/images//32055887/f82d34c7582137a6748a28c5b02670ff4b235356.png",
"ReleaseDate": "1717513346",
"year": "2024"
},
{
"BSVersion": "1.37.1",
"BSManifest": "9129356330007601179",
"OculusBinaryId": "7313068492126200",
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/4253168598913260422",
"ReleaseImg": "https://clan.akamai.steamstatic.com/images/32055887/039be718c1494f948257cd5b09f0082986484a58.png",
"ReleaseDate": "1720710529",
"year": "2024",
"recommended": true
},
{
"BSVersion": "1.37.2",
"BSManifest": "6848299977215652352",
"OculusBinaryId": "7438773609555687",
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/4349999161850643744",
"ReleaseImg": "https://clan.akamai.steamstatic.com/images/32055887/7c03af6d12fad23f1d439666d4be86b492d40003.png",
"ReleaseDate": "1722945814",
"year": "2024"
},
{
"BSVersion": "1.37.3",
"BSManifest": "5834150512217183366",
"OculusBinaryId": "7553569971409383",
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/6808965920900622902",
"ReleaseImg": "https://clan.akamai.steamstatic.com/images/32055887/a1c9a6737cc5182fca8cddc7c8088eda6dd4d82d.png",
"ReleaseDate": "1724061712",
"year": "2024"
},
{
"BSVersion": "1.37.4",
"BSManifest": "7585106640515547731",
"OculusBinaryId": "7630971613669218",
"ReleaseURL": "https://steamcommunity.com/games/620980/announcements/detail/4601078012425941968",
"ReleaseImg": "https://clan.akamai.steamstatic.com/images/32055887/23e6e6f219a56d2f9ea4a27b560c54ac1214aec3.png",
"ReleaseDate": "1725548547",
"year": "2024"
},
{
"BSVersion": "1.37.5",
"BSManifest": "3122533396458693889",
"OculusBinaryId": "7685108391588873",
"ReleaseDate": "1725628356",
"year": "2024"
}
]
+14
View File
@@ -0,0 +1,14 @@
{
"1.5.0-alpha.1":{
"htmlBody" :"<strong>BSManager continues to get better, thanks to your continued support and contributions!</strong><center>🎈🎉🎈</center><p>Note: This is an alpha release, encountering bugs is expected. Please file new issues for any bugs you find.</p><h2>Features</h2><ul><li>Added playlist support</li><li>Added Linux support (Thanks to @Insprill)</li><li>Added reset button to reset values when editing a Beat Saber version (Thanks to @Liborsaf)</li><li>Added a changelog modal</li></ul><h2>Fixes</h2><ul><li>Fixed an issue where switching between Beat Saber versions too quickly displayed mods for the wrong version</li><li>Fixed an issue where the launch window from a shortcut would never close</li><li>Advanced launch arguments are used even when the input field is closed</li><li>Fixed an issue where having many maps caused some maps to not have their information loaded</li></ul><h2>Other changes</h2><ul><li>.NET Framework is no longer required</li><li>Clear English translations for the Steam credentials popup (Thanks to @Aeywoo)</li><li>NSFW models are now blurred when browsing for models</li><li>When no mods are available for a Beat Saber version, the version number is now shown</li><li>Mods load faster</li><li>After a first full maps loading, maps load almost instantly</li><li>Improved performance in lists with lot of contents</li></ul>",
"title" : "What's new ?",
"timestamp" : 1721048400,
"version" : "1.5.0-alpha.1"
},
"1.5.0-alpha.2":{
"htmlBody" :"<strong>BSManager continues to get better, thanks to your continued support and contributions!</strong><center>🎈🎉🎈</center><p>Note: This is an alpha release, encountering bugs is expected. Please file new issues for any bugs you find.</p><h4>Alpha changes</h4><ul><li>Fixed an issue where BSIPA could not be installed if the BS version&#39;s path contained spaces #523</li><li>Fixed a crash when changing audio volume #518</li><li>Fixed an issue where playlist maps with a malformed hash were not loaded #517</li><li>Improved reliability of reading maps from a playlist file #517</li><li>Playlists in sub-folders are now loaded #514</li><li>Fixed a crash when loading an invalid playlist file #513</li></ul><h2>Features</h2><ul> <li>Added playlist support</li> <li>Added Linux support (Thanks to @Insprill)</li> <li>Added reset button to reset values when editing a Beat Saber version (Thanks to @Liborsaf)</li> <li>Added a changelog modal</li></ul><h3>Fixes</h3><ul><li>Fixed an issue where switching between Beat Saber versions too quickly displayed mods for the wrong version #472</li><li>Fixed an issue where the launch window from a shortcut would never close #485</li><li>Advanced launch arguments are used even when the input field is closed #496</li><li>Fixed an issue where having many maps caused some maps to not have their information loaded #503</li><li>Fixed an issue where downloading maps sometimes resulted in a timeout error #524</li><li>Fixed an issue where the duration of maps could be wrong in some cases #522</li></ul><h2>Other changes</h2><ul> <li>.NET Framework is no longer required</li> <li>Clear English translations for the Steam credentials popup (Thanks to @Aeywoo)</li> <li>NSFW models are now blurred when browsing for models</li> <li>When no mods are available for a Beat Saber version, the version number is now shown</li> <li>Mods load faster</li> <li>After a first full maps loading, maps load almost instantly</li> <li>Improved performance in lists with lot of contents</li></ul>",
"title" : "What's new ?",
"timestamp" : 1721665382,
"version" : "1.5.0-alpha.2"
}
}
+57 -15
View File
@@ -18,9 +18,6 @@
{
"username": "Falmil"
},
{
"username": "K1Lc4m"
},
{
"username": "Anonymously42",
"type": "diamond",
@@ -30,9 +27,6 @@
"username": "Burt",
"type": "gold"
},
{
"username": "Ilnahro"
},
{
"username": "Phil",
"type": "gold"
@@ -41,18 +35,10 @@
"username": "Protocrush",
"type": "gold"
},
{
"username": "ServerMensch",
"type": "gold"
},
{
"username": "Karlito",
"type": "gold"
},
{
"username": "Cathery",
"type": "gold"
},
{
"username": ".sharkey"
},
@@ -67,5 +53,61 @@
"username": "Lumberjack462",
"type": "diamond",
"link": "https://www.youtube.com/@lumberjack462"
},
{
"username": "Xero"
},
{
"username": "Minescence"
},
{
"username": "mereknom"
},
{
"username": "Jascha"
},
{
"username": "Celldweller",
"type": "gold"
},
{
"username": "rhythmshade"
},
{
"username": "liborsaf"
},
{
"username": "aatame3",
"type": "gold"
},
{
"username": "Joshua"
},
{
"username": "Stuijvi",
"type": "gold"
},
{
"username": "_ monaka"
},
{
"username": "Better_Axel"
},
{
"username": "Riley",
"type": "gold"
},
{
"username": "Austin"
},
{
"username": "Fatalution",
"type": "diamond",
"link": "https://x.com/fatalution"
},
{
"username": "Taurus Arcade",
"type": "gold"
}
]
]
+350 -173
View File
@@ -1,23 +1,24 @@
{
"misc": {
"download": "Laden",
"download": "Herunterladen",
"add": "Hinzufügen",
"verify": "Prüfen",
"launch": "Starten",
"mods": "Mods",
"maps": "Maps",
"playlists": "Playlisten",
"playlists": "Playlists",
"models": "Modelle",
"cancel": "Abbruch",
"cancel": "Abbrechen",
"delete": "Löschen",
"accept": "Akzeptieren",
"refuse": "Ablehnen",
"apply": "Übernehmen",
"copy": "Kopieren",
"copied": "Kopiert!"
"copied": "Kopiert!",
"confirm": "Bestätigen"
},
"nav-bar": {
"add-version": "Version Hinzufügen",
"add-version": "Version hinzufügen",
"settings": "Einstellungen",
"shared": {
"text": "Geteilt",
@@ -28,14 +29,14 @@
"version-viewer": {
"launch-mods": {
"oculus": "Oculus Modus",
"oculus-description": "Wenn du Beat Saber über Steam benutzt, es ermöglicht dir Oculus's VR-Composer zu nutzen ohne SteamVR, um bessere Leistung zu erhalten. Dies wird nicht benötigt für Oculus Headsets",
"oculus-description": "Wenn du Beat Saber über Steam benutzt, ermöglicht dir diese Einstellung, Oculus's VR-Composer ohne SteamVR zu nutzen, um eine bessere Leistung zu erhalten. Dies wird nicht für Oculus Headsets benötigt.",
"desktop": "FPFC Modus",
"desktop-description": "Auf diese Weise kannst du WASD und die Maus verwenden, um im Spiel durch das Menü zu navigieren. Dies erleichtert das Testen erheblich, da Du dein Headset nicht aufsetzen musst!",
"desktop-description": "Auf diese Weise kannst du WASD und die Maus verwenden, um im Spiel durch das Menü zu navigieren. Dies erleichtert das Testen erheblich, da du dein Headset nicht aufsetzen musst!",
"debug": "Debug Modus",
"debug-description": "Aktiviert das Ausgabeprotokollfenster für IPA. Dies zeigt die Debug-Konsole, die Mods verwenden.",
"debug-description": "Aktiviert das Ausgabeprotokollfenster für IPA. Dies zeigt die Debug-Konsole, welche die Mods verwenden.",
"advanced-launch": {
"button": "Erweiterter Start",
"placeholder": "Weitere Argumente Bspw: --revert; --nowait"
"placeholder": "Weitere Argumente, bspw: --revert; --nowait"
}
},
"maps": {
@@ -43,8 +44,8 @@
"search-placeholder": "Suche eine Map",
"filters-btn": "Filter",
"dropdown": {
"export-maps": "Maps Exportieren",
"delete-maps": "Maps Löschen"
"export-maps": "Maps exportieren",
"delete-maps": "Maps löschen"
}
},
"tabs": {
@@ -55,14 +56,14 @@
},
"link-maps": {
"tooltips": {
"link": "Maps Verknüpfen",
"unlink": "Maps Verknüpfung aufheben"
"link": "Maps verknüpfen",
"unlink": "Maps-Verknüpfung aufheben"
}
}
},
"empty-maps": {
"text": "Keine Maps",
"button": "Maps Herunterladen"
"button": "Maps herunterladen"
}
}
}
@@ -70,10 +71,11 @@
"mods": {
"loading-mods": "Lade Mods...",
"no-internet": "Kein Internet",
"mods-not-available": "Für diese Version von Beat Saber sind noch keine Mods verfügbar",
"mods-not-available": "Für diese Version von Beat Saber sind noch keine Mods verfügbar.",
"buttons": {
"more-infos": "Mehr Infos",
"install-or-update": "Installieren oder aktualisieren"
"install-or-update": "Installieren oder aktualisieren",
"reinstall-all": "Alles neu installieren"
},
"mods-grid": {
"header-bar": {
@@ -85,55 +87,60 @@
"uninstall-all": "Alle deinstallieren"
}
}
},
"notifications": {
"all-mods-already-installed": {
"title": "Mods bereits installiert",
"description": "Alle ausgewählten Mods sind bereits installiert"
}
}
},
"dropdown": {
"open-folder": "Ordner Öffnen",
"verify-files": "Daten Prüfen",
"open-folder": "Ordner öffnen",
"verify-files": "Daten prüfen",
"clone": "Klonen",
"edit": "Bearbeiten",
"uninstall": "Entfernen",
"create-shortcut": "Verknüpfung erstellen",
"shared-folders": "Geteilte Ordner",
"restore-oculus-folder": "Ordner wiederherstellen"
"shared-folders": "Geteilte Ordner"
}
},
"available-versions": {
"title": "Wähle eine Version",
"steam-release": "Versions Seite",
"steam-release": "Versionsseite",
"dropdown": {
"refresh": "Aktualisieren Sie die Versionen",
"refresh": "Aktualisiere die Versionen",
"import-version": "Importiere eine Version"
},
"recommended": "empfohlen",
"recommended-tooltip": "Am modbarsten Version"
"recommended-tooltip": "Am modbarste Version"
},
"settings": {
"steam-and-oculus": {
"title": "Steam & Oculus",
"description": "Abmelden ermöglicht es dir, beim nächsten Beat Saber Download den Account zu wechseln.",
"description": "Das Abmelden ermöglicht es dir, beim nächsten Download von Beat Saber den Account zu wechseln.",
"logout": "Abmelden",
"download-platform": {
"title": "Standardplattform",
"desc": "Wähle die Standardplattform, die für das Herunterladen von Beat Saber-Versionen verwendet wird.",
"desc": "Wähle die Standardplattform, die für das Herunterladen von Beat Saber-Versionen verwendet werden soll.",
"always-ask": "Immer fragen"
}
},
"appearance": {
"title": "Aussehen",
"description": "Wähle Zwei von den Hauptfarben von BSManager",
"description": "Wähle die zwei Hauptfarben von BSManager.",
"reset": "Zurücksetzen",
"sub-title": "Design",
"themes": {
"dark": "Dunkel",
"light": "Hell",
"os": "Mit Computer Synchronisieren"
"os": "Mit Computer synchronisieren"
}
},
"installation-folder": {
"title": "Installations Ordner",
"description": "Ändern Sie den Standardordner für Beat Saber-Versionen und andere kommende Funktionen.",
"choose-folder": "Ordner Wählen"
"title": "Installations-Ordner",
"description": "Ändern Sie den Ordner, der alle von BSManager heruntergeladenen Inhalte enthalten wird.",
"choose-folder": "Ordner wählen"
},
"additional-content": {
"title": "Zusätzlicher Inhalt",
@@ -172,7 +179,7 @@
"title": "BSManager Unterstützen 💖",
"description": "Unterstütze das Projekt und helfe uns, BSManager kontinuierlich zu verbessern.",
"buttons": {
"support": "BSManager Unterstützen 🥰",
"support": "BSManager unterstützen 🥰",
"supporters": "Unterstützer 👀"
},
"view": {
@@ -182,15 +189,47 @@
}
},
"discord": {
"description": "Trete der BSManager-Community bei, indem Du uns in unseren sozialen Medien folgst!"
"description": "Trete der BSManager-Community bei, indem du uns in unseren sozialen Medien folgst!"
},
"contribution": {
"description": "Schlage neue Funktionen vor, oder melde einen Fehler und BSManager zu verbessern!",
"description": "Schlage neue Funktionen vor, oder melde einen Fehler, um BSManager zu verbessern!",
"buttons": {
"request-features": "Funktion Vorschlagen",
"request-features": "Funktion vorschlagen",
"report-bug": "Fehler melden",
"open-logs": "Protokolle öffnen"
}
},
"changelogs": {
"open" : "🚀 Neues im Changelog entdecken!",
"not-founds": "😕 Hoppla, kein Changelog zu sehen!"
},
"advanced": {
"title": "Erweiterte",
"description": "Erweiterte Einstellungen für BSManager.",
"hardware-acceleration": {
"title": "Hardware-Beschleunigung",
"description": "Aktivieren Sie die Hardware-Beschleunigung, um Ihre GPU zu nutzen und die Leistung von BSManager zu verbessern. Deaktivieren Sie diese Option, wenn Sie Frame-Drops erleben.",
"modal": {
"title": "Neustart erforderlich",
"body": "Das Ändern der Hardware-Beschleunigungseinstellung wird BSManager beenden und neu starten. Sind Sie sicher, dass Sie dies tun möchten?",
"confirm-btn": "Ja, ich bin sicher"
},
"error-notification": {
"message": "Ein Fehler ist aufgetreten, die Hardware-Beschleunigung kann nicht deaktiviert werden."
}
},
"use-symlinks": {
"title": "Symbolische Links verwenden",
"description": "Verwenden Sie symbolische Links anstelle von Verknüpfungen, um Ordner zu verknüpfen. Aktivieren Sie dies nur, wenn Sie es wirklich benötigen.",
"modal": {
"title": "Berechtigungen für symbolische Links",
"body": "Beim Erstellen symbolischer Links benötigt BSManager Administratorrechte oder den aktivierten Entwicklermodus auf Ihrem System. Sind Sie sicher, dass Sie fortfahren möchten?",
"confirm-btn": "Ja, ich bin sicher"
},
"error-notification": {
"message": "Ein Fehler ist aufgetreten, die Einstellungen für symbolische Links können nicht geändert werden."
}
}
}
}
},
@@ -202,7 +241,7 @@
},
"common": {
"msg": {
"error-occurred": "Ein Fehler ist aufgetreten"
"error-occurred": "Ein Fehler ist aufgetreten."
}
},
"shared": {
@@ -212,7 +251,7 @@
"no-internet": "Kein Internet"
},
"msg": {
"operation-running": "Warte auf das Ende des Aktuellen Vorgangs und versuche es erneut",
"operation-running": "Warte auf das Ende des aktuellen Vorgangs und versuche es erneut.",
"no-internet": "Überprüfe deine Verbindung und versuche es erneut."
}
}
@@ -220,14 +259,14 @@
"bs-download": {
"success": {
"titles": {
"download-success": "Erfolgreich Heruntergeladen",
"verification-finished": "Verifikation Erfolgreich"
"download-success": "Erfolgreich heruntergeladen",
"verification-finished": "Verifikation erfolgreich"
}
},
"steam-download": {
"warnings": {
"msg": {
"ManifestChecksum": "Die zuvor heruntergeladene Manifest stimmt nicht mit dem neuen überein 🤔",
"ManifestChecksum": "Das zuvor heruntergeladene Manifest stimmt nicht mit dem neuen überein 🤔",
"ConnectionTimeout": "Deine Internetverbindung scheint instabil zu sein 🥶",
"ConnectionLost": "Die Verbindung wurde unterbrochen, versuche es erneut...",
"ConnectionError": "Kann keine Verbindung zu Steam herstellen, versuche es erneut...",
@@ -235,51 +274,44 @@
}
},
"errors": {
"titles": {
"dotnet-required": ".NET 6 Benötigt"
},
"msg": {
"401": "Steam scheint uns BeatSaber nicht herunterladen zu lassen 😢",
"401": "Steam scheint uns Beat Saber nicht herunterladen zu lassen 😢",
"404": "Steam-Server können nicht kontaktiert werden.",
"Password": "Passwort ist ungültig.",
"InvalidCredentials": "Ungültige Anmeldedaten, nicht genehmigte Verbindung oder zu viele Anmeldeversuche.",
"NoManifest": "Es wurde keine Manifest gefunden",
"NoManifest": "Es wurde kein Manifest gefunden.",
"DirectoryCreate": "Die erforderlichen Ordner können nicht installiert werden.",
"NotAvailableApp": "Versuchst du, Beat Saber herunterzuladen, wenn Du es nicht hast? 🤣",
"DepotNotFound": "BeatSaber kann nicht heruntergeladen werden 😥 versuche es später noch einmal 😕",
"NotAvailableApp": "Versuchst du, Beat Saber herunterzuladen, obwohl du es nicht hast? 🤣",
"DepotNotFound": "Beat Saber kann nicht heruntergeladen werden 😥 Versuche es später noch einmal 😕",
"NotCompleted": "Der Download konnte nicht beendet werden ¯\\_(ツ)_/¯",
"InvalidManifest": "BeatSaber kann nicht heruntergeladen werden 😥 versuche es später noch einmal 😕",
"NoValidKey": "BeatSaber kann nicht heruntergeladen werden 😥 versuche es später noch einmal 😕",
"NoManifestCode": "BeatSaber kann nicht heruntergeladen werden 😥 versuche es später noch einmal 😕",
"Unknown": "Ein Unbekannter Fehler ist aufgetreten ¯\\_(ツ)_/¯",
"InvalidManifest": "Beat Saber kann nicht heruntergeladen werden 😥 Versuche es später noch einmal 😕",
"NoValidKey": "Beat Saber kann nicht heruntergeladen werden 😥 Versuche es später noch einmal 😕",
"NoManifestCode": "Beat Saber kann nicht heruntergeladen werden 😥 Versuche es später noch einmal 😕",
"Unknown": "Ein unbekannter Fehler ist aufgetreten ¯\\_(ツ)_/¯",
"NoServer": "Steam-Server können nicht kontaktiert werden.",
"NotAllowed": "Anscheinend darfst Du BeatSaber nicht herunterladen 🥱",
"NotAllowed": "Anscheinend darfst du Beat Saber nicht herunterladen 🥱",
"ConnectionTimeout": "Kann keine Verbindung zu Steam herstellen 😕",
"SteamLib": "Wenn dieser Fehler auftritt, melde den Fehler auf Github mit Protokollen, bitte.",
"SteamLib": "Wenn dieser Fehler auftritt, melde den Fehler bitte auf Github mit den Protokollen.",
"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": "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."
},
"actions": {
"download-dotnet": ".NET 6 Herunterladen"
"RateLimitExceeded": "Du hast es zu oft versucht. Warte eine Weile und versuche es später erneut.",
"TokenRejected": "Dein Anmeldetoken wurde abgelehnt 😕 Bitte versuche es erneut.",
"AccessDenied": "Der Zugang zu Steam wurde verweigert."
}
}
},
"oculus-download": {
"errors": {
"msg": {
"DOWNLOAD_MANIFEST_FAILED": "Es ist nicht möglich, das Manifest für diese Version herunterzuladen; Ihr Anmelde-Token ist möglicherweise ungültig.",
"DOWNLOAD_MANIFEST_FAILED": "Es ist nicht möglich, das Manifest für diese Version herunterzuladen. Dein Anmelde-Token ist möglicherweise ungültig.",
"MANIFEST_FILE_NOT_FOUND": "Unmöglich, das Manifest für diese Version zu finden.",
"PARSE_MANIFEST_FILE_FAILED": "Beim Lesen des Manifests ist ein Fehler aufgetreten.",
"ALREADY_DOWNLOADING": "Eine Version wird bereits heruntergeladen.",
"UNABLE_TO_GET_MANIFEST": "Unmöglich, das für den Download erforderliche Manifest zu erhalten.",
"VERIFY_INTEGRITY_FAILED": "Beim Überprüfen der Dateien ist ein Fehler aufgetreten.",
"SOME_FILES_FAILED_TO_DOWNLOAD": "Einige Dateien konnten nicht heruntergeladen werden.",
"OCULUS_LOGIN_TIMED_OUT": "Das Anmelde-Token hat zu lange gedauert, um abgerufen zu werden.",
"OCULUS_LOGIN_WINDOW_CLOSED_BY_USER": "Das Meta Anmeldefenster wurde geschlossen.",
"OCULUS_LOGIN_TIMED_OUT": "Es hat zu lange gedauert, das Anmelde-Token abzurufen.",
"OCULUS_LOGIN_WINDOW_CLOSED_BY_USER": "Das Meta-Anmeldefenster wurde geschlossen.",
"NO_META_AUTH_TOKEN": "Unmöglich, das für den Download erforderliche Meta-Anmelde-Token zu erhalten.",
"UNKNOWN_ERROR": "Ein unbekannter Fehler ist aufgetreten."
}
@@ -293,7 +325,7 @@
"desc": "Der Import kann je nach Konfiguration einige Minuten dauern."
},
"imported": {
"title": "Versionen Importiert 🎉"
"title": "Versionen importiert 🎉"
}
},
"errors": {
@@ -332,7 +364,7 @@
},
"additional-content": {
"deep-link": {
"select-all": "Alle Auswählen",
"select-all": "Alle auswählen",
"activation": {
"success": {
"title": "OneClick aktiviert!",
@@ -348,7 +380,7 @@
"description": "OneClick-Installationen wurden deaktiviert."
},
"error": {
"description": "Ein Unbekannter Fehler ist aufgetreten."
"description": "Ein unbekannter Fehler ist aufgetreten."
}
},
"check-all-enabled": {
@@ -356,7 +388,7 @@
"description": "Eine oder mehrere OneClick-Installationen sind deaktiviert. Gehe in die Einstellungen, um sie zu aktivieren.",
"actions": {
"settings": "Einstellungen",
"not-remind": "Erinnere mich nicht"
"not-remind": "Nicht mehr erinnern"
}
}
}
@@ -365,7 +397,7 @@
"bs-launch": {
"success": {
"titles": {
"BS_LAUNCHING": "Starte...🚀",
"BS_LAUNCHING": "Starte... 🚀",
"STEAM_LAUNCHING": "Steam startet!"
},
"msg": {
@@ -379,7 +411,7 @@
"STEAM_NOT_RUNNING": "Steam läuft nicht",
"OCULUS_NOT_RUNNING": "Oculus läuft nicht",
"BS_ALREADY_RUNNING": "Beat Saber läuft bereits",
"EXE_NOT_FINDED": "Dateien Fehlen",
"EXE_NOT_FINDED": "Dateien fehlen",
"EXIT": "Abrupter Stop",
"OCULUS_LIB_NOT_FOUND": "Oculus-Bibliothek nicht gefunden"
},
@@ -387,9 +419,9 @@
"UNKNOWN_ERROR": "Ein unbekannter Fehler ist aufgetreten.",
"STEAM_NOT_RUNNING": "Steam muss laufen, um Beat Saber zu starten.",
"OCULUS_NOT_RUNNING": "Oculus muss ausgeführt werden, um Beat Saber zu starten.",
"BS_ALREADY_RUNNING": "Schließe Beat Saber, bevor Du es erneut startest.",
"EXE_NOT_FINDED": "Einige Dateien scheinen zu fehlen, versuche die Dateien zu überprüfen.",
"EXIT": "Beat Saber stoppte abrupt, versuche die Dateien zu überprüfen.",
"BS_ALREADY_RUNNING": "Schließe Beat Saber, bevor du es erneut startest.",
"EXE_NOT_FINDED": "Einige Dateien scheinen zu fehlen. Versuche, die Dateien zu überprüfen.",
"EXIT": "Beat Saber stoppte abrupt. Versuche, die Dateien zu überprüfen.",
"OCULUS_LIB_NOT_FOUND": "Überprüfe, ob die Oculus-Anwendung korrekt installiert ist und dass die Bibliotheken in Oculus richtig definiert sind."
},
"actions": {
@@ -424,15 +456,15 @@
"mods": {
"install-mods": {
"titles": {
"success": "Mods Installiert 🎉",
"warning": "Mods Installiert 🤔"
"success": "Mods installiert 🎉",
"warning": "Mods installiert 🤔"
},
"msg": {
"success": "Alle Mods wurden installiert.",
"warning": "Eine oder mehr Mods konnten nicht installiert werden.",
"warning": "Eine oder mehrere Mods konnten nicht installiert werden.",
"errors": {
"no-mods": "Keine Mods zum installieren.",
"cannot-install-bsipa": "BSIPA installation fehlgeschlagen 😨"
"cannot-install-bsipa": "BSIPA-Installation fehlgeschlagen 😨"
}
}
},
@@ -460,27 +492,36 @@
},
"maps": {
"one-click-install": {
"success": "Map installation abegschlossen",
"error": "Ein Fehler ist aufgetreten während der installation der Map"
"success": "Map-Installation abgeschlossen",
"error": "Ein Fehler ist während der Installation der Map aufgetreten."
}
},
"playlists": {
"one-click-install": {
"success": "Playlist installation abgeschlossen",
"error": "Ein Fehler ist aufgetreten während der installation der Playlist"
"success": "Playlist-Installation abgeschlossen",
"error": "Ein Fehler ist während der Installation der Playlist aufgetreten."
}
},
"models": {
"one-click-install": {
"success": "Modell installation abgeschlossen",
"error": "Ein Fehler ist aufgetreten während der installation des Modells"
"success": "Modell-Installation abgeschlossen",
"error": "Ein Fehler ist während der Installation des Modells aufgetreten."
}
},
"shared-folder": {
"info": {
"userdata-backup-created": {
"title": "Sicherung erstellt",
"msg": "Das Freigeben des Ordners „UserData“ kann zu Fehlern führen. Bei Problemen trenne den Ordner, um die Sicherung wiederherzustellen"
"msg": "Das Freigeben des Ordners „UserData“ kann zu Fehlern führen. Bei Problemen trenne den Ordner, um die Sicherung wiederherzustellen."
}
},
"linking-error": {
"title": "Fehler beim Verknüpfen des Ordners",
"msg": {
"EPERM": "BSManager hat nicht die erforderlichen Berechtigungen, um den Ordner zu verknüpfen.",
"EACCES": "BSManager hat nicht die erforderlichen Berechtigungen, um den Ordner zu verknüpfen.",
"ENOSPC": "Die Festplatte ist voll, machen Sie Platz und versuchen Sie es erneut.",
"UNKNOWN_ERROR": "Ein unbekannter Fehler ist beim Verknüpfen des Ordners aufgetreten."
}
}
},
@@ -496,11 +537,11 @@
},
"modals": {
"misc": {
"remember-my-choice": "Merke meine Wahl"
"remember-my-choice": "Meine Wahl merken"
},
"choose-store": {
"title": "Welche Plattform?",
"body": "Wählen Sie die Plattform, von der Sie Beat Saber herunterladen möchten.",
"body": "Wähle die Plattform, von der du Beat Saber herunterladen möchtest.",
"set-in-settings": "Die Standardplattform in den Einstellungen festlegen"
},
"guard": {
@@ -520,19 +561,19 @@
"inputs": {
"username": {
"label": "Mit Accountnamen anmelden",
"placeholder": "Geben Sie Ihren Accountnamen ein"
"placeholder": "Gebe deinen Accountnamen ein"
},
"password": {
"label": "Passwort",
"placeholder": "Geben Sie Ihr Passwort ein",
"max-length-warning": "Das Passwort überschreitet 64 Zeichen! Wenn das Passwort ungültig ist, versuchen Sie nur seine ersten 64 Zeichen einzugeben."
"placeholder": "Gebe dein Passwort ein",
"max-length-warning": "Das Passwort überschreitet 64 Zeichen! Wenn das Passwort ungültig ist, versuche nur seine ersten 64 Zeichen einzugeben."
},
"qr": {
"label": "Oder mit einem QR-Code",
"note": {
"use-the": "Anmelden Sie sich über die ",
"use-the": "Melde dich über die ",
"steam-mobile-app": "Steam-Mobile-App",
"to-connect-with-qr": " per QR-Code an."
"to-connect-with-qr": "oder per QR-Code an."
}
},
"stay": "Angemeldet bleiben"
@@ -546,13 +587,13 @@
"steam-auth-approve": {
"title": "Warten auf Bestätigung",
"protected-by-mobile-auth": "Konto durch mobile Authentifizierung geschützt.",
"use-steam-app-to-approve": "Verwenden Sie die Steam Mobile-App, um die Verbindung zu bestätigen...",
"use-steam-app-to-approve": "Verwende die Steam Mobile-App, um die Verbindung zu bestätigen...",
"not-access-to-steam-app": "Ich habe keinen Zugang zur Steam Mobile-App"
},
"steam-credentials": {
"title": "Steam Anmeldeinformationen",
"p-1": "Die Anmeldeinformationen werden nur zum Herunterladen des Spiels verwendet, da Steam überprüfen muss, ob Du das Spiel bezahlt hast, um es herunterladen zu dürfen. Sie werden nicht gespeichert und direkt an DepotDownloader weitergegeben. Wenn Du deine Anmeldeinformationen nicht eingeben möchtest, kannst Du diesem Tutorial folgen:",
"p-2": "und klicke dann auf das Zahnradsymbol in der oberen rechten Ecke und wähle \"Version importieren\", wähle den Ordner aus, in den Beat Saber heruntergeladen wurde (Wenn Du dem obigen Tutorial folgst, solltest Du den richtigen Speicherort haben)"
"p-1": "Die Anmeldeinformationen werden nur zum Herunterladen des Spiels verwendet, da Steam überprüfen muss, ob du das Spiel bezahlt hast, um es herunterladen zu dürfen. Sie werden nicht gespeichert und direkt an den Depot-Downloader weitergegeben. Wenn du deine Anmeldeinformationen nicht eingeben möchtest, kannst du diesem Tutorial folgen:",
"p-2": "und klicke dann auf das Zahnradsymbol in der oberen rechten Ecke und wähle \"Version importieren\", wähle den Ordner aus, in den Beat Saber heruntergeladen wurde (Wenn du dem obigen Tutorial folgst, solltest du den richtigen Speicherort haben)."
},
"bs-import-version": {
"title": "Importiere eine Version",
@@ -571,10 +612,10 @@
}
},
"install-folder": {
"title": "Installation Ordner",
"title": "Installations-Ordner",
"description": "Das Ändern des Standardinstallationsordners führt dazu, dass alle installierten Daten in den neuen Ordner verschoben werden.",
"buttons": {
"submit": "Ordner Wählen"
"submit": "Ordner wählen"
}
},
"edit-version": {
@@ -584,12 +625,12 @@
}
},
"clone-version": {
"title": "Version Klonen",
"title": "Version klonen",
"description": "Durch das Klonen der Version kannst Du zusätzlichen Beat Saber-Inhalt zwischen zwei Versionen trennen.",
"inputs": {
"name": {
"label": "Name",
"placeholder": "Versions Name"
"placeholder": "Versionsname"
},
"color": {
"label": "Farbe"
@@ -601,50 +642,50 @@
},
"uninstall-mod": {
"title": "Entfernen",
"description": "Bist du sicher das du die Mod {mod} entfernen möchtest? Es könnte dafür sorgen, dass andere installationen nicht mehr richtig funktionieren.",
"description-bsipa": "Bist du sicher, dass du BSIPA entfernen möchtest? Dannach werden deine Mods nicht mehr funktionieren."
"description": "Bist du sicher, dass du die Mod {mod} entfernen möchtest? Es könnte dafür sorgen, dass andere Installationen nicht mehr richtig funktionieren.",
"description-bsipa": "Bist du sicher, dass du BSIPA entfernen möchtest? Danach werden deine Mods nicht mehr funktionieren."
},
"uninstall-all-mods": {
"title": "Entferne Alle Mods",
"description": "Bist du sicher das du alle Mods von der Version {version} entfernen möchtest? Diese Aktion kann nicht rückgängig gemacht werden."
"title": "Entferne alle Mods",
"description": "Bist du sicher, dass du alle Mods von der Version {version} entfernen möchtest? Diese Aktion kann nicht rückgängig gemacht werden."
},
"maps-actions": {
"delete-maps": {
"title": {
"single": "Map Entfernen?",
"multiple": "Maps Entfernen?"
"single": "Map entfernen?",
"multiple": "Maps entfernen?"
},
"desc": {
"single": "Bist du sicher das du die Map {name} entfernen willst?",
"multiple": "Bist du sicher das du alle {nb} maps entfernen willst?"
"single": "Bist du sicher, dass du die Map {name} entfernen willst?",
"multiple": "Bist du sicher, dass du alle {nb} Maps entfernen willst?"
},
"info": {
"desc": {
"single": "Diese Map ist teil der geteilten Maps",
"multiple": "Diese Maps sind teil der geteilten Maps"
"single": "Diese Map ist Teil der geteilten Maps.",
"multiple": "Diese Maps sind Teil der geteilten Maps."
},
"title": {
"single": "Diese Map wird auch aus Versionen entfernt, die geteilte Maps verwenden",
"multiple": "Diese Maps werden auch aus Versionen entfernt, die geteilte Maps verwenden"
"single": "Diese Map wird auch aus Versionen entfernt, die geteilte Maps verwenden.",
"multiple": "Diese Maps werden auch aus Versionen entfernt, die geteilte Maps verwenden."
}
}
},
"link-maps": {
"title": "Maps Verknüpfen",
"desc": "Das Verknüpfen von Maps ermöglicht es, Maps zwischen allen Versionen zu teilen. Nach der Verknüpfung profitiert diese Version von den geteilten Maps",
"info": "Das Hinzufügen und Löschen von Maps wird ebenfalls geteilt",
"title": "Maps verknüpfen",
"desc": "Das Verknüpfen von Maps ermöglicht es, Maps zwischen allen Versionen zu teilen. Nach der Verknüpfung profitiert diese Version von den geteilten Maps.",
"info": "Das Hinzufügen und Löschen von Maps wird ebenfalls geteilt.",
"keep-maps": {
"label": "Maps behalten",
"title": "Maps behalten verschiebt die Maps der aktuellen Version in den geteilten Maps. Andernfalls gehen sie verloren."
"title": "\"Maps behalten\" verschiebt die Maps der aktuellen Version in den geteilten Maps-Ordner. Andernfalls gehen sie verloren."
},
"valid-btn": "Maps Verknüpfen"
"valid-btn": "Maps verknüpfen"
},
"unlink-maps": {
"title": "Maps Verknüpfung aufheben",
"title": "Maps-Verknüpfung aufheben",
"desc": "Bitte beachte, dass das Aufheben der Verknüpfung von Maps die Verwendung von geteilten Maps für diese Version nicht zulässt.",
"keep-maps": {
"label": "Maps behalten",
"title": "Maps behalten verschiebt die Maps der aktuellen Version in den geteilten Maps. Andernfalls gehen sie verloren."
"title": "\"Maps behalten\" kopiert die Maps aus dem geteilten Maps-Ordner in den Ordner der ausgewählten Version. Andernfalls gehen sie verloren."
},
"valid-btn": "Verknüpfung aufheben"
}
@@ -657,7 +698,7 @@
},
"mods-disclaimer": {
"title": "Haftungsausschluss",
"p-1": "Indem Du dich für die Verwendung von Mods entscheiden, verstehst Du Folgendes:",
"p-1": "Indem du dich für die Verwendung von Mods entscheidest, verstehst du Folgendes:",
"li-1": "Möglicherweise treten Probleme auf, die im Vanilla-Spiel nicht vorhanden sind. 99.9% der Fehler, Abstürze und Verzögerungen sind auf Mods zurückzuführen.",
"li-2": "Mods können durch Updates beschädigt werden und das ist normal - sei geduldig und respektvoll, wenn dies passiert, da Modder Freiwillige mit echtem Leben sind.",
"li-3": "Beat Games versuchen nicht absichtlich, Mods kaputt zu machen. Sie möchten an der Codebasis arbeiten und manchmal macht dies Mods kaputt, aber sie sind nicht darauf aus, Mods zu verbieten.",
@@ -667,26 +708,26 @@
"title": "Geteilte Ordner",
"description": "Verknüpfe Beat Saber-Ordner, um ihre Inhalte mit freigegebenen Ordnern in anderen Versionen zu synchronisieren. Beachte, dass auch das Löschen von Inhalten geteilt wird.",
"buttons": {
"add-folder": "Ordner Hinzufügen",
"link-folder": "Ordner Verknüpfen",
"unlink-folder": "Ordner Verknüpfung Aufheben",
"add-folder": "Ordner hinzufügen",
"link-folder": "Ordner verknüpfen",
"unlink-folder": "Ordner-Verknüpfung aufheben",
"link-all": "Alle verlinken"
}
},
"create-launch-shortcut": {
"title": "Verknüpfung erstellen",
"desc": "Das Erstellen einer Verknüpfung ermöglicht es Ihnen, Beat Saber mit den ausgewählten Optionen zu starten, ohne durch BSManager zu gehen.",
"desc": "Das Erstellen einer Verknüpfung ermöglicht es dir, Beat Saber mit den ausgewählten Optionen zu starten, ohne durch BSManager zu gehen.",
"launch-options": "Startoptionen",
"advanced-launch": "Erweiterte Start",
"advanced-launch": "Erweiterter Start",
"valid-btn": "Verknüpfung erstellen"
},
"connect-to-meta": {
"title": "Mit Meta verbinden",
"body": {
"token-needed": "Dein Meta-Verbindungstoken wird benötigt, um Beat Saber herunterzuladen.",
"need-cookie-enabled": "Beim Einloggen in Meta wird ein Anmeldefenster geöffnet und du kannst dann den Anmeldevorgang beginnen. Bitte stelle sicher, dass Cookies akzeptiert werden, sonst könnten wir deinen Token zum Starten des Downloads nicht abrufen.",
"need-cookie-enabled": "Beim Einloggen in Meta wird ein Anmeldefenster geöffnet und du kannst dann den Anmeldevorgang beginnen. Bitte stelle sicher, dass Cookies akzeptiert werden, sonst können wir deinen Token zum Starten des Downloads nicht abrufen.",
"enter-token-manually": "Mein Anmelde-Token manuell eingeben",
"enter-token-manually-tooltip": "Dies ermöglicht es Ihnen, Ihren Anmelde-Token einzugeben, ohne sich über Meta anzumelden."
"enter-token-manually-tooltip": "Dies ermöglicht es dir, deinen Anmelde-Token einzugeben, ohne dich über Meta anzumelden."
},
"stay": "Angemeldet bleiben",
"connect-to-meta": "Mit Meta verbinden"
@@ -694,46 +735,63 @@
"original-version-backup-oculus": {
"title": "Achtung",
"body": {
"must-be-installed-once": "Sie müssen Beat Saber mindestens einmal aus dem Oculus Store installiert haben, sonst könnte sich Beat Saber nach dem Start automatisch schließen.",
"need-backup": "Um diese Version zu starten, wird der Installationsordner von Beat Saber in Ihrer Oculus-Bibliothek umbenannt.",
"can-restore-later": "Bei Bedarf können Sie ihn vom BSManager aus wiederherstellen, indem Sie zu den Optionen der originalen Oculus-Version gehen und auf 'Ordner wiederherstellen' klicken",
"tips-launch-oculus": "Tipp: Sie können diese Version direkt über Oculus starten, solange die Originalversion nicht wiederhergestellt ist."
"must-be-installed-once": "Du musst Beat Saber mindestens einmal aus dem Oculus Store installiert haben, sonst könnte sich Beat Saber nach dem Start automatisch schließen.",
"will-backup": "Um diese Version zu starten, wird der ursprüngliche Installationsordner von Beat Saber in deiner Oculus-Bibliothek umbenannt und beim Schließen von Beat Saber automatisch wiederhergestellt."
},
"not-remind-me": "Nicht mehr erinnern",
"understood": "Verstanden"
},
"enter-meta-token": {
"title": "Oculus Token",
"title": "Oculus-Token",
"body": {
"info-enter-token": "Um Beat Saber herunterzuladen, ist Ihr Oculus-Anmeldetoken erforderlich.",
"info-enter-token": "Um Beat Saber herunterzuladen, ist dein Oculus-Anmeldetoken erforderlich.",
"how-obtain-token": "Wie erhalte ich mein Oculus Token?",
"oculus-token": "Oculus Token",
"oculus-token": "Oculus-Token",
"token-is-invalid": "Das Token ist ungültig.",
"save-my-token": "Mein Token speichern",
"have-token-saved": "Ich habe bereits ein Token gespeichert",
"save-token-info": "Dies wird Ihr Token zur einfacheren Wiederverwendung speichern. Sie müssen ein Passwort erstellen, um Ihr Token zu verschlüsseln und zu speichern. Wenn Sie Ihr Passwort vergessen, müssen Sie nur Ihr Token erneut angeben.",
"save-my-token": "Meinen Token speichern",
"have-token-saved": "Ich habe bereits einen Token gespeichert",
"save-token-info": "Dies wird deinen Token zur einfacheren Wiederverwendung speichern. Du musst ein Passwort erstellen, um dein Token zu verschlüsseln und zu speichern. Wenn du dein Passwort vergisst, musst du nur deinen Token erneut angeben.",
"password": "Passwort",
"password-too-short": "Passwort zu kurz",
"info-enter-password": "Um Beat Saber herunterzuladen, ist Ihr Oculus-Anmeldetoken erforderlich. Geben Sie das Passwort ein, mit dem Ihr Oculus-Token gespeichert wurde.",
"info-disabled-btn-password": "Der mit dem angegebenen Passwort entschlüsselte Token ist ungültig. Stellen Sie sicher, dass das Passwort dasselbe ist wie das zum Speichern des Tokens verwendete.",
"info-enter-password": "Um Beat Saber herunterzuladen, ist dein Oculus-Anmeldetoken erforderlich. Gib das Passwort ein, mit dem dein Oculus-Token gespeichert wurde.",
"info-disabled-btn-password": "Der mit dem angegebenen Passwort entschlüsselte Token ist ungültig. Stelle sicher, dass das Passwort dasselbe ist, wie das zum Speichern des Tokens verwendete.",
"enter-oculus-token": "Ein Oculus-Token eingeben"
},
"valid-btn": "Validieren"
},
"launch-as-admin": {
"title": "Administratorberechtigungen",
"body": {
"info": "Es wurde festgestellt, dass Steam mit Administratorrechten ausgeführt wird. Um mit Steam zu kommunizieren, muss auch Beat Saber als Administrator gestartet werden. Andernfalls könnte Beat Saber Probleme haben und sich nach dem Starten schließen.",
"info-2": "Das Starten von Beat Saber im Administratormodus gibt auch den installierten Mods Administratorrechte. Daher wird empfohlen, Steam ohne Administratorrechte neu zu starten.",
"info-3": "Beachte, dass es nicht ratsam ist, Steam Administratorrechte zu geben, da dies auch die installierten Spiele und Mods betrifft und ein Sicherheitsrisiko darstellt."
},
"launch-as-admin": "Als Administrator starten",
"not-remind-me": "Nicht mehr erinnern"
},
"ask-install-path": {
"title": "Installations Ordner",
"choose-folder-description": "Wählen Sie den Ordner aus, der alle von BSManager heruntergeladenen Inhalte enthalten soll. (Versionen, Mods, Karten, Playlists, etc.)",
"choose-folder": "Ordner Wählen",
"default": "Standard",
"default-tooltip": "Standardmäßig in Ihrem persönlichen Ordner"
}
},
"maps": {
"map-filter-panel": {
"duration": "Länge",
"nps" : "Noten Pro Sekunde",
"tags": "Stichworte",
"nps" : "Noten pro Sekunde",
"njs": "Notensprunggeschwindigkeit",
"tags": "Stichwörter",
"specificities": "Allgemein",
"requirements": "Anforderungen"
"requirements": "Anforderungen",
"exclude": "Ausschließen"
},
"map-types": {
"accuracy": "Präzision",
"balanced": "Ausgeglichen",
"challenge": "Herausforderung",
"dancestyle": "Tanz",
"dance-style": "Tanz",
"fitness": "Fitness",
"speed": "Geschwindigkeit",
"tech": "Tech"
@@ -744,7 +802,7 @@
"nightcore": "Nightcore",
"folk": "Folk",
"family": "Familie",
"ambient": "umgebung",
"ambient": "Umgebung",
"funk": "Funk",
"jazz": "Jazz",
"soul": "Soul",
@@ -753,13 +811,13 @@
"rb": "R&B",
"holiday": "Urlaub",
"vocaloid": "Vokaloid",
"jrock": "J-Rock",
"j-rock": "J-Rock",
"trance": "Trance",
"drumbass": "Basstrommel",
"comedy": "Komödie",
"instrumental": "Instrumental",
"hardcore": "Hardcore",
"kpop": "K-Pop",
"k-pop": "K-Pop",
"indie": "Indie",
"techno": "Techno",
"house": "House",
@@ -770,25 +828,28 @@
"metal": "Metal",
"anime": "Anime",
"hiphop": "HipHop",
"jpop": "J-Pop",
"j-pop": "J-Pop",
"rock": "Rock",
"pop": "Pop",
"electronic": "Elektronisch",
"classical-orchestral": "Klassisch & Orchestra"
"classical-orchestral": "Klassisch & Orchester"
},
"map-specificities": {
"automapper": "KI",
"ranked": "ranked",
"curated": "curated",
"verified": "verifiziert",
"fullSpread": "full spread"
"ranked": "Ranked",
"curated": "Curated",
"verified": "Verifiziert",
"fullSpread": "Full Spread"
},
"map-excludes": {
"installed": "Installiert"
},
"difficulties": {
"Easy": "einfach",
"Normal": "normal",
"Hard": "hard",
"Expert": "expert",
"ExpertPlus": "expert+"
"Easy": "Einfach",
"Normal": "Normal",
"Hard": "Hard",
"Expert": "Expert",
"ExpertPlus": "Expert+"
},
"map-item": {
"by": "Von {songAutor}",
@@ -840,12 +901,12 @@
"modals": {
"delete-model": {
"title": "Das Modell löschen",
"desc": "Sind Sie sicher, dass Sie das Modell {modelName} löschen möchten?",
"desc": "Bist du dir sicher, dass du das Modell {modelName} löschen möchtest?",
"linked-annotation": "Dieses Modell wird aus allen verlinkten Versionen entfernt."
},
"delete-models": {
"title": "Modelle löschen",
"desc": "Sind Sie sicher, dass Sie die {nb} Modelle löschen möchten?",
"desc": "Bist du dir sicher, dass du die {nb} Modelle löschen möchtest?",
"linked-annotation": "Diese Modelle werden aus allen verlinkten Versionen entfernt."
},
"download-models": {
@@ -870,41 +931,41 @@
"link-models": {
"avatar": {
"title": "Avatare verbinden",
"desc": "Das Verbinden von Avataren ermöglicht das Teilen von Avataren zwischen allen Versionen. Sobald verbunden, wird diese Version von den geteilten Avataren profitieren",
"info": "Das Hinzufügen und Entfernen von Avataren wird ebenfalls geteilt",
"desc": "Das Verbinden von Avataren ermöglicht das Teilen von Avataren zwischen allen Versionen. Sobald verbunden, wird diese Version von den geteilten Avataren profitieren.",
"info": "Das Hinzufügen und Entfernen von Avataren wird ebenfalls geteilt.",
"keep-models": {
"label": "Avatare behalten",
"title": "Das Behalten der Avatare wird die Avatare der aktuellen Version in den Ordner der geteilten Avatare verschieben. Andernfalls gehen sie verloren"
"title": "Das Behalten der Avatare wird die Avatare der aktuellen Version in den Ordner der geteilten Avatare verschieben. Andernfalls gehen sie verloren."
},
"valid-btn": "Avatare verbinden"
},
"saber": {
"title": "Säbel verbinden",
"desc": "Das Verbinden von Säbeln ermöglicht das Teilen von Säbeln zwischen allen Versionen. Sobald verbunden, wird diese Version von den geteilten Säbeln profitieren",
"info": "Das Hinzufügen und Entfernen von Säbeln wird ebenfalls geteilt",
"desc": "Das Verbinden von Säbeln ermöglicht das Teilen von Säbeln zwischen allen Versionen. Sobald verbunden, wird diese Version von den geteilten Säbeln profitieren.",
"info": "Das Hinzufügen und Entfernen von Säbeln wird ebenfalls geteilt.",
"keep-models": {
"label": "Säbel behalten",
"title": "Das Behalten der Säbel wird die Säbel der aktuellen Version in den Ordner der geteilten Säbel verschieben. Andernfalls gehen sie verloren"
"title": "Das Behalten der Säbel wird die Säbel der aktuellen Version in den Ordner der geteilten Säbel verschieben. Andernfalls gehen sie verloren."
},
"valid-btn": "Säbel verbinden"
},
"platform": {
"title": "Plattformen verbinden",
"desc": "Das Verbinden von Plattformen ermöglicht das Teilen von Plattformen zwischen allen Versionen. Sobald verbunden, wird diese Version von den geteilten Plattformen profitieren",
"info": "Das Hinzufügen und Entfernen von Plattformen wird ebenfalls geteilt",
"desc": "Das Verbinden von Plattformen ermöglicht das Teilen von Plattformen zwischen allen Versionen. Sobald verbunden, wird diese Version von den geteilten Plattformen profitieren.",
"info": "Das Hinzufügen und Entfernen von Plattformen wird ebenfalls geteilt.",
"keep-models": {
"label": "Plattformen behalten",
"title": "Das Behalten der Plattformen wird die Plattformen der aktuellen Version in den Ordner der geteilten Plattformen verschieben. Andernfalls gehen sie verloren"
"title": "Das Behalten der Plattformen wird die Plattformen der aktuellen Version in den Ordner der geteilten Plattformen verschieben. Andernfalls gehen sie verloren."
},
"valid-btn": "Plattformen verbinden"
},
"bloq": {
"title": "Bloqs verbinden",
"desc": "Das Verbinden von Bloqs ermöglicht das Teilen von Bloqs zwischen allen Versionen. Sobald verbunden, wird diese Version von den geteilten Bloqs profitieren",
"info": "Das Hinzufügen und Entfernen von Bloqs wird ebenfalls geteilt",
"desc": "Das Verbinden von Bloqs ermöglicht das Teilen von Bloqs zwischen allen Versionen. Sobald verbunden, wird diese Version von den geteilten Bloqs profitieren.",
"info": "Das Hinzufügen und Entfernen von Bloqs wird ebenfalls geteilt.",
"keep-models": {
"label": "Bloqs behalten",
"title": "Das Behalten der Bloqs wird die Bloqs der aktuellen Version in den Ordner der geteilten Bloqs verschieben. Andernfalls gehen sie verloren"
"title": "Das Behalten der Bloqs wird die Bloqs der aktuellen Version in den Ordner der geteilten Bloqs verschieben. Andernfalls gehen sie verloren."
},
"valid-btn": "Bloqs verbinden"
}
@@ -951,9 +1012,9 @@
"notifications": {
"prevent-for-mods": {
"title": "Erforderliche Mods",
"desc": "Stellen Sie sicher, dass Sie die notwendigen Mods installiert haben, um Modelle in Beat Saber zu verwenden",
"go-to-mods": "Gehe zu Mods",
"not-remind": "Erinnere mich nicht"
"desc": "Stelle sicher, dass du die notwendigen Mods installiert hast, um Modelle in Beat Saber zu verwenden.",
"go-to-mods": "Zu den Mods",
"not-remind": "Nicht mehr erinnern"
},
"prevent-for-models-breaks": {
"title": "Gebrochene Modelle",
@@ -974,7 +1035,7 @@
},
"auto-update": {
"checking": "Prüfe auf Updates",
"downloading": "Lade Updates Herunter"
"downloading": "Lade Updates herunter"
},
"bs-shortcut-launch": {
"beat-saber-launching": "Start von Beat Saber",
@@ -983,13 +1044,129 @@
"status-text": {
"init": "Initialisierung...",
"success": {
"BS_LAUNCHING": "Start von Beat Saber...",
"STEAM_LAUNCHING": "Start von Steam...",
"BS_LAUNCHING": "Starte Beat Saber...",
"STEAM_LAUNCHING": "Starte Steam...",
"STEAM_LAUNCHED": "Steam erfolgreich gestartet!",
"UNABLE_TO_LAUNCH_STEAM": "Steam kann nicht gestartet werden, erzwungener Start von Beat Saber..."
}
}
},
"playlist": {
"error-playlist-creation-title": "Fehler beim Erstellen der Playlist",
"error-playlist-creation-desc": "Beim Erstellen der Playlist ist ein Fehler aufgetreten.",
"playlist-created-title": "Playlist erstellt",
"playlist-created-desc": "Die Playlist wurde erfolgreich erstellt. Du kannst jetzt ihre Karten synchronisieren!",
"download-playlist": "Playlist herunterladen",
"synchronize-playlist": "Playlist synchronisieren",
"synchronize-maps": "Karten synchronisieren",
"error-playlists-synchronization-title": "Fehler bei der Synchronisierung der Playlists",
"error-playlists-synchronization-desc": "Bei der Synchronisierung der Playlists ist ein Fehler aufgetreten.",
"playlists-synchronized-title": "Playlists synchronisiert!",
"playlists-synchronized-desc": "Playlists und ihre Karten wurden heruntergeladen.",
"playlists-export-error-title": "Fehler beim Exportieren der Playlists",
"playlists-export-error-desc": "Beim Exportieren der Playlists ist ein Fehler aufgetreten.",
"playlists-exported-title": "Playlists exportiert!",
"playlists-exported-desc": "Playlists wurden erfolgreich exportiert.",
"playlists-with-maps-exported-desc": "Playlists und ihre Karten wurden erfolgreich exportiert.",
"playlist-delete-error-title": "Fehler beim Löschen der Playlist",
"playlist-delete-error-desc": "Beim Löschen der Playlist ist ein Fehler aufgetreten.",
"playlists-deleted-title": "Playlists gelöscht!",
"playlists-deleted-desc": "Playlists wurden erfolgreich gelöscht.",
"edit-playlist": "Playlist bearbeiten",
"playlist-edit-error-title": "Fehler beim Bearbeiten der Playlist",
"playlist-edit-error-desc": "Beim Bearbeiten der Playlist ist ein Fehler aufgetreten.",
"playlist-edited-title": "Playlist bearbeitet!",
"playlist-edited-desc": "Die Playlist wurde erfolgreich geändert. Du kannst jetzt ihre Karten synchronisieren!",
"playlists-loading": "Playlists werden geladen...",
"no-playlists": "Keine Playlists",
"download-playlists": "Playlists herunterladen",
"created-by": "Erstellt von",
"stop-download": "Download stoppen",
"cancel-download": "Download abbrechen",
"open-file": "Datei öffnen",
"link-playlists": "Playlists verknüpfen",
"link-playlist-desc": "Das Verknüpfen von Playlists ermöglicht das Teilen von Playlists zwischen allen Versionen. Nach der Verknüpfung profitiert diese Version von geteilten Playlists.",
"link-playlist-info": "Das Hinzufügen und Löschen von Playlists wird ebenfalls geteilt.",
"keep-playlists": "Playlists behalten",
"keep-playlists-tip": "Wenn du Playlists behältst, werden die Playlists von der aktuellen Version in den Ordner für geteilte Playlists verschoben. Andernfalls gehen sie verloren.",
"unlink-playlists": "Playlists trennen",
"unlink-playlist-desc": "Achtung, das Trennen von Playlists verhindert die Nutzung geteilter Playlists für diese Version.",
"unlink-keep-playlists-tip": "Wenn du Playlists behältst, wird eine Kopie der geteilten Playlists für die aktuelle Version erstellt. Andernfalls werden keine Playlists für diese Version behalten.",
"delete-playlist-ask": "Playlist löschen?",
"delete-playlists-ask": "Playlists löschen?",
"delete-playlist-desc": "Bist du dir sicher, dass du die Playlist \"{playlistTitle}\" löschen möchtest?",
"delete-playlists-desc": "Bist du dir sicher, dass du {nb} Playlists löschen möchtest?",
"delete-maps": "Karten löschen",
"delete-playlist-maps-tip": "Wenn aktiviert, werden alle Karten in der Playlist gelöscht.",
"delete-playlists-maps-tip": "Wenn aktiviert, werden alle Karten in den Playlists gelöscht.",
"export-playlist-ask": "Playlist exportieren?",
"export-playlists-ask": "Playlists exportieren?",
"export-playlist-desc": "Bist du dir sicher, dass du die Playlist \"{playlistTitle}\" exportieren möchtest?",
"export-playlists-desc": "Bist du dir sicher, dass du {nb} Playlists exportieren möchtest?",
"export-maps": "Karten exportieren",
"export-playlist-maps-tip": "Wenn aktiviert, werden auch alle Karten in der Playlist exportiert.",
"export-playlists-maps-tip": "Wenn aktiviert, werden auch alle Karten in den Playlists exportiert.",
"export": "Exportieren",
"need-clone-title": "Warnung",
"need-clone-desc-1": "Diese Playlist wurde von einer externen Seite heruntergeladen und enthält einen Synchronisierungslink.",
"need-clone-desc-2": "Um deine Änderungen während der Synchronisierung nicht zu verlieren, wird die Playlist dupliziert und ihr Synchronisierungslink entfernt.",
"need-clone-desc-3": "Du kannst dann, wenn du möchtest, die ursprüngliche Playlist löschen.",
"understood": "Ich verstehe",
"synchronize-playlist-ask": "Playlist synchronisieren?",
"synchronize-playlists-ask": "Playlists synchronisieren?",
"synchronize-playlist-desc": "Bist du sicher, dass du die Playlist \"{playlistTitle}\" synchronisieren möchtest?",
"synchronize-playlists-desc": "Bist du sicher, dass du {nb} Playlists synchronisieren möchtest?",
"synchronize-playlist-tip": "Diese Aktion aktualisiert Playlists und lädt fehlende Karten herunter. Dies kann mehrere Minuten dauern.",
"synchronize": "Synchronisieren",
"curated": "Empfohlen",
"verified-mapper": "Verifizierter Mapper",
"empty-playlists": "Leere Playlists",
"search-playlist": "Nach einer Playlist suchen",
"no-playlists-found": "Keine Playlists gefunden.",
"error-occur-while-loading-playlists": "Beim Laden der Playlists ist ein Fehler aufgetreten.",
"error-occur-while-loading-playlist": "Beim Laden der Playlist ist ein Fehler aufgetreten.",
"loading-maps": "Karten werden geladen...",
"no-maps-found-for-playlist": "Keine Karten für diese Playlist gefunden.",
"playlist-contain-no-maps": "Die Playlist enthält keine Karten.",
"no-map-installed-for-playlist": "Keine Karten für diese Playlist installiert.",
"playlist-is-waiting-to-download": "Die Playlist wartet auf den Download.",
"download-maps": "Karten herunterladen",
"download-missing-maps": "Fehlende Karten herunterladen",
"playlist-is-downloading": "Die Playlist wird heruntergeladen.",
"some-playlist-maps-are-missing": "Einige Karten in dieser Playlist fehlen!",
"create-a-playlist": "Eine Playlist erstellen",
"synchronize-playlists": "Playlists synchronisieren",
"export-playlists": "Playlists exportieren",
"delete-playlists": "Playlists löschen",
"choose-image": "Bild auswählen",
"title": "Titel",
"playlist-title": "Playlist-Titel",
"description": "Beschreibung",
"playlist-description": "Playlist-Beschreibung",
"author": "Autor",
"playlist-author": "Playlist-Autor",
"save": "Speichern",
"loading": "Wird geladen...",
"installed": "Installiert",
"no-map-found": "Keine Karte gefunden!",
"edit-playlist-shortcuts": "Halte Shift oder Strg gedrückt, um mehrere Karten auszuwählen.",
"add-to-playlist": "Zur Playlist hinzufügen",
"remove-from-playlist": "Aus Playlist entfernen",
"playlist-is-empty": "Die Playlist ist leer.",
"continue": "Fortfahren",
"nb-maps": "Anzahl der Karten",
"nb-mappers": "Anzahl der Mapper",
"duration": "Dauer",
"nps": "Noten pro Sekunde",
"date-picker": {
"start-date-end-date": "Startdatum — Enddatum",
"all": "Alle",
"last-24h": "Letzte 24h",
"last-week": "Letzte Woche",
"last-month": "Letzter Monat",
"3-last-month": "Letzte 3 Monate"
}
},
"dateformat": {
"dayNames": ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa", "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
"monthNames": ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez", "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
+208 -24
View File
@@ -14,7 +14,8 @@
"refuse": "Refuse",
"apply": "Apply",
"copy": "Copy",
"copied": "Copied!"
"copied": "Copied!",
"confirm": "Confirm"
},
"nav-bar": {
"add-version": "Add a version",
@@ -73,7 +74,8 @@
"mods-not-available": "No mods are available yet for this version of Beat Saber",
"buttons": {
"more-infos": "More info",
"install-or-update": "Install or update"
"install-or-update": "Install or update",
"reinstall-all": "Reinstall all"
},
"mods-grid": {
"header-bar": {
@@ -85,6 +87,12 @@
"uninstall-all": "Uninstall all"
}
}
},
"notifications": {
"all-mods-already-installed": {
"title": "Mods already installed",
"description": "All selected mods are already installed"
}
}
},
"dropdown": {
@@ -94,8 +102,7 @@
"edit": "Edit",
"uninstall": "Uninstall",
"create-shortcut": "Create a shortcut",
"shared-folders": "Shared Folders",
"restore-oculus-folder": "Restore the folder"
"shared-folders": "Shared Folders"
}
},
"available-versions": {
@@ -132,9 +139,14 @@
},
"installation-folder": {
"title": "Installation folder",
"description": "Change the default folder for Beat Saber versions and other upcoming features.",
"description": "Change the folder that will contain all the content downloaded by BSManager.",
"choose-folder": "Choose folder"
},
"proton-path": {
"title": "Proton path",
"description": "Change the path to the Proton binary",
"choose-file": "Choose file"
},
"additional-content": {
"title": "Additional content",
"description": "Additional content that allows you to customize Beat Saber!",
@@ -191,6 +203,38 @@
"report-bug": "Report a bug",
"open-logs": "Open logs"
}
},
"changelogs": {
"open" : "🚀 Check Out the Changelog!",
"not-founds": "😕 Oops, No Changelog Here!"
},
"advanced": {
"title": "Advanced",
"description": "Advanced settings for BSManager.",
"hardware-acceleration": {
"title": "Hardware Acceleration",
"description": "Enable Hardware Acceleration to use your GPU and improve BSManager's performance. Turn this off if you're experiencing frame drops.",
"modal": {
"title": "Restart Needed",
"body": "Changing hardware acceleration setting will quit and re-launch BSManager. Are you sure you want to do this?",
"confirm-btn": "Yes I'm sure"
},
"error-notification": {
"message": "An error occur, unable to disable hardware acceleration."
}
},
"use-symlinks": {
"title": "Use Symlinks",
"description": "Use Symlinks instead of Junctions to link folders. Turn this on only if you really need it.",
"modal": {
"title": "Symlink Permissions",
"body": "When creating symlinks, BSManager will require administrator privileges or developer mode enabled on your system. Are you sure you want to continue?",
"confirm-btn": "Yes I'm sure"
},
"error-notification": {
"message": "An error occur, unable to change symlinks settings."
}
}
}
}
},
@@ -235,9 +279,6 @@
}
},
"errors": {
"titles": {
"dotnet-required": ".NET 6 Required"
},
"msg": {
"401": "Steam doesn't seem to want to let us download Beat Saber 😢",
"404": "Unable to contact Steam servers.",
@@ -260,11 +301,7 @@
"LicenceError": "Unable to get the list of licenses.",
"RateLimitExceeded": "You've tried too many times, wait a while and 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."
},
"actions": {
"download-dotnet": "Download .NET 6"
"AccessDenied": "Access to Steam has been denied."
}
}
},
@@ -380,6 +417,7 @@
"OCULUS_NOT_RUNNING": "Oculus is not running",
"BS_ALREADY_RUNNING": "Beat Saber already running",
"EXE_NOT_FINDED": "Missing files",
"PROTON_NOT_SET": "Proton path not set",
"EXIT": "Abrupt stop",
"OCULUS_LIB_NOT_FOUND": "Oculus library not found"
},
@@ -390,7 +428,8 @@
"BS_ALREADY_RUNNING": "Close BeatSaber before launching it again.",
"EXE_NOT_FINDED": "Some files seem to be missing, try to verify the files.",
"EXIT": "BeatSaber stopped abruptly, tries to check the files.",
"OCULUS_LIB_NOT_FOUND": "Check that the Oculus application is properly installed, and that the libraries are correctly defined in Oculus."
"OCULUS_LIB_NOT_FOUND": "Check that the Oculus application is properly installed, and that the libraries are correctly defined in Oculus.",
"PROTON_NOT_SET": "Set the Proton path in settings"
},
"actions": {
"STEAM_NOT_RUNNING": "Launch Steam"
@@ -482,6 +521,15 @@
"title": "Backup created",
"msg": "Sharing the 'UserData' folder can generate errors, in case of problems unlink the folder to restore the backup"
}
},
"linking-error": {
"title": "Error while linking folder",
"msg": {
"EPERM": "BSManager does not have the necessary permissions to link the folder.",
"EACCES": "BSManager does not have the necessary permissions to link the folder.",
"ENOSPC": "The disk is full, make some space and try again.",
"UNKNOWN_ERROR":"An unknown error has occurred while linking the folder."
}
}
},
"create-launch-shortcut": {
@@ -551,8 +599,8 @@
},
"steam-credentials": {
"title": "Steam Credentials",
"p-1": "The credentials are only used to download the game because steam need to verify that you paid the game in order to be allowed to download it. They aren't saved and directly passed to DepotDownloader. If you don't want to enter your credentials you can follow this tutorial :",
"p-2": "and then click on the gear icon in the top right corner and select \"Import a version\", select the folder where beat saber has been downloaded (If you follow the tutorial above you should have the correct location)"
"p-1": "Your Steam credentials are only required to download versions of Beat Saber, we use DepotDownloader to achieve this which requires your Steam credentials to verify that you own the game within your library before allowing you to retrieve the game files, your credentials are not stored or saved and are passed directly to DepotDownloader. However, if you don't want to do that, you can follow this tutorial instead: ",
"p-2": "Afterwards you can click on the gear icon in the top right corner and select \"Import a version\", then you can select the folder where Beat Saber was downloaded to. (If you followed the tutorial, you will have the right location)"
},
"bs-import-version": {
"title": "Import a version",
@@ -695,9 +743,7 @@
"title": "Warning",
"body": {
"must-be-installed-once": "You must have installed Beat Saber at least once from the Oculus Store, otherwise Beat Saber might automatically close after launching.",
"need-backup": "To launch this version, the Beat Saber installation folder located in your Oculus library will be renamed.",
"can-restore-later": "If needed, you can restore it from BSManager by going to the options of the original Oculus version and clicking on 'Restore the folder'",
"tips-launch-oculus": "Tip: You can launch this version directly from Oculus, as long as the original version is not restored."
"will-backup": "To launch this version, the original installation folder of Beat Saber located in your Oculus library will be renamed and will be automatically restored when Beat Saber is closed."
},
"not-remind-me": "Do not remind me",
"understood": "Understood"
@@ -719,21 +765,40 @@
"enter-oculus-token": "Enter an Oculus token"
},
"valid-btn": "Validate"
},
"launch-as-admin": {
"title": "Administrator Permissions",
"body": {
"info": "Steam has been detected as running with administrator permissions. To communicate with Steam, Beat Saber must also be launched as an administrator. Otherwise, Beat Saber might experience problems and close after launching.",
"info-2": "Launching Beat Saber in administrator mode will also give administrator rights to the installed mods. Therefore, it is recommended to restart Steam without administrator permissions.",
"info-3": "Note that it is advised against giving administrator rights to Steam, as this affects the installed games and mods, presenting a security risk."
},
"launch-as-admin": "Launch as Administrator",
"not-remind-me": "Do not remind me"
},
"ask-install-path": {
"title": "Installation folder",
"choose-folder-description": "Choose the folder that will contain all the content downloaded by BSManager. (versions, mods, maps, playlists, etc.)",
"choose-folder": "Choose folder",
"default": "Default",
"default-tooltip": "Defaults to your home folder"
}
},
"maps": {
"map-filter-panel": {
"duration": "Duration",
"nps" : "Notes Per Second",
"njs": "Note Jump Speed",
"tags": "tags",
"specificities": "general",
"requirements": "requirements"
"requirements": "requirements",
"exclude": "exclude"
},
"map-types": {
"accuracy": "accuracy",
"balanced": "balanced",
"challenge": "challenge",
"dancestyle": "dance",
"dance-style": "dance",
"fitness": "fitness",
"speed": "speed",
"tech": "tech"
@@ -753,13 +818,13 @@
"rb": "r&b",
"holiday": "holiday",
"vocaloid": "vocaloid",
"jrock": "j-rock",
"j-rock": "j-rock",
"trance": "trance",
"drumbass": "drum & bass",
"comedy": "comedy",
"instrumental": "instrumental",
"hardcore": "hardcore",
"kpop": "k-pop",
"k-pop": "k-pop",
"indie": "indie",
"techno": "techno",
"house": "house",
@@ -770,7 +835,7 @@
"metal": "metal",
"anime": "anime",
"hiphop": "hiphop",
"jpop": "j-pop",
"j-pop": "j-pop",
"rock": "rock",
"pop": "pop",
"electronic": "electronic",
@@ -783,6 +848,9 @@
"verified": "verified",
"fullSpread": "full spread"
},
"map-excludes": {
"installed": "installed"
},
"difficulties": {
"Easy": "easy",
"Normal": "normal",
@@ -990,6 +1058,122 @@
}
}
},
"playlist": {
"error-playlist-creation-title": "Error creating playlist",
"error-playlist-creation-desc": "An error occurred while creating the playlist.",
"playlist-created-title": "Playlist created",
"playlist-created-desc": "The playlist has been successfully created. You can now sync its maps!",
"download-playlist": "Download playlist",
"synchronize-playlist": "Synchronize playlist",
"synchronize-maps": "Synchronize maps",
"error-playlists-synchronization-title": "Error synchronizing playlists",
"error-playlists-synchronization-desc": "An error occurred while synchronizing playlists.",
"playlists-synchronized-title": "Playlists synchronized!",
"playlists-synchronized-desc": "Playlists and their maps have been downloaded.",
"playlists-export-error-title": "Error exporting playlists",
"playlists-export-error-desc": "An error occurred while exporting playlists.",
"playlists-exported-title": "Playlists exported!",
"playlists-exported-desc": "Playlists have been successfully exported.",
"playlists-with-maps-exported-desc": "Playlists and their maps have been successfully exported.",
"playlist-delete-error-title": "Error deleting playlist",
"playlist-delete-error-desc": "An error occurred while deleting the playlist.",
"playlists-deleted-title": "Playlists deleted!",
"playlists-deleted-desc": "Playlists have been successfully deleted.",
"edit-playlist": "Edit playlist",
"playlist-edit-error-title": "Error editing playlist",
"playlist-edit-error-desc": "An error occurred while editing the playlist.",
"playlist-edited-title": "Playlist edited!",
"playlist-edited-desc": "The playlist has been successfully modified. You can now sync its maps!",
"playlists-loading": "Loading playlists...",
"no-playlists": "No playlists",
"download-playlists": "Download playlists",
"created-by": "Created by",
"stop-download": "Stop download",
"cancel-download": "Cancel download",
"open-file": "Open file",
"link-playlists": "Link playlists",
"link-playlist-desc": "Linking playlists allows sharing playlists between all versions. Once linked, this version will benefit from shared playlists",
"link-playlist-info": "Adding and deleting playlists will also be shared",
"keep-playlists": "Keep playlists",
"keep-playlists-tip": "Keeping playlists will move the playlists from the current version to the shared playlists folder. Otherwise, they will be lost",
"unlink-playlists": "Unlink playlists",
"unlink-playlist-desc": "Warning, unlinking playlists will no longer allow the use of shared playlists for this version.",
"unlink-keep-playlists-tip": "Keeping playlists will create a copy of shared playlists for the current version. Otherwise, no playlists will be kept for this version.",
"delete-playlist-ask": "Delete playlist?",
"delete-playlists-ask": "Delete playlists?",
"delete-playlist-desc": "Are you sure you want to delete the playlist \"{playlistTitle}\"?",
"delete-playlists-desc": "Are you sure you want to delete {nb} playlists?",
"delete-maps": "Delete maps",
"delete-playlist-maps-tip": "If enabled, all maps in the playlist will be deleted",
"delete-playlists-maps-tip": "If enabled, all maps in the playlists will be deleted",
"export-playlist-ask": "Export playlist?",
"export-playlists-ask": "Export playlists?",
"export-playlist-desc": "Are you sure you want to export the playlist \"{playlistTitle}\"?",
"export-playlists-desc": "Are you sure you want to export {nb} playlists?",
"export-maps": "Export maps",
"export-playlist-maps-tip": "If enabled, all maps in the playlist will also be exported",
"export-playlists-maps-tip": "If enabled, all maps in the playlists will also be exported",
"export": "Export",
"need-clone-title": "Warning",
"need-clone-desc-1": "This playlist has been downloaded from an external site and contains a synchronization link.",
"need-clone-desc-2": "To avoid losing your changes during synchronization, the playlist will be duplicated and its synchronization link removed.",
"need-clone-desc-3": "You can then, if you wish, delete the original playlist.",
"understood": "I understand",
"synchronize-playlist-ask": "Synchronize playlist?",
"synchronize-playlists-ask": "Synchronize playlists?",
"synchronize-playlist-desc": "Are you sure you want to synchronize the playlist \"{playlistTitle}\"?",
"synchronize-playlists-desc": "Are you sure you want to synchronize {nb} playlists?",
"synchronize-playlist-tip": "This action updates playlists and downloads missing maps; it may take several minutes.",
"synchronize": "Synchronize",
"curated": "Recommended",
"verified-mapper": "Verified mapper",
"empty-playlists": "Empty playlists",
"search-playlist": "Search for a playlist",
"no-playlists-found": "No playlists found",
"error-occur-while-loading-playlists": "An error occurred while loading playlists",
"error-occur-while-loading-playlist": "An error occurred while loading the playlist",
"loading-maps": "Loading maps...",
"no-maps-found-for-playlist": "No maps found for this playlist",
"playlist-contain-no-maps": "The playlist contains no maps",
"no-map-installed-for-playlist": "No maps installed for this playlist",
"playlist-is-waiting-to-download": "The playlist is waiting to download",
"download-maps": "Download maps",
"download-missing-maps": "Download missing maps",
"playlist-is-downloading": "The playlist is downloading",
"some-playlist-maps-are-missing": "Some maps in this playlist are missing",
"create-a-playlist": "Create a playlist",
"synchronize-playlists": "Synchronize playlists",
"export-playlists": "Export playlists",
"delete-playlists": "Delete playlists",
"choose-image": "Choose an image",
"title": "Title",
"playlist-title": "Playlist title",
"description": "Description",
"playlist-description": "Playlist description",
"author": "Author",
"playlist-author": "Playlist author",
"save": "Save",
"loading": "Loading...",
"installed": "Installed",
"no-map-found": "No map found",
"edit-playlist-shortcuts": "Hold Shift or Ctrl to select multiple maps",
"add-to-playlist": "Add to playlist",
"remove-from-playlist": "Remove from playlist",
"playlist-is-empty": "The playlist is empty",
"continue": "Continue",
"nb-maps": "Number of maps",
"nb-mappers": "Number of mappers",
"duration": "Duration",
"nps": "Notes per second",
"date-picker": {
"start-date-end-date": "Start date — End date",
"all": "All",
"last-24h": "Last 24h",
"last-week": "Last week",
"last-month": "Last month",
"3-last-month": "Last 3 months"
}
},
"dateformat": {
"dayNames": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
"monthNames": ["Jan", "Feb", "Mar", "Apr", "May", "June", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+198 -21
View File
@@ -14,7 +14,8 @@
"refuse": "Rechazar",
"apply": "Aplicar",
"copy": "Copiar",
"copied": "¡Copiado!"
"copied": "¡Copiado!",
"confirm": "Confirmar"
},
"nav-bar": {
"add-version": "Agregar una versión",
@@ -73,7 +74,8 @@
"mods-not-available": "Aún no hay mods disponibles para esta versión de Beat Saber",
"buttons": {
"more-infos": "Más información",
"install-or-update": "Instalar o actualizar"
"install-or-update": "Instalar o actualizar",
"reinstall-all": "Reinstalar todo"
},
"mods-grid": {
"header-bar": {
@@ -85,6 +87,12 @@
"uninstall-all": "Desinstalar todos"
}
}
},
"notifications": {
"all-mods-already-installed": {
"title": "Mods ya instalados",
"description": "Todos los mods seleccionados ya están instalados"
}
}
},
"dropdown": {
@@ -94,8 +102,7 @@
"edit": "Editar",
"uninstall": "Desinstalar",
"create-shortcut": "Crear un atajo",
"shared-folders": "Carpetas Compartidas",
"restore-oculus-folder": "Restaurar la carpeta"
"shared-folders": "Carpetas Compartidas"
}
},
"available-versions": {
@@ -132,7 +139,7 @@
},
"installation-folder": {
"title": "Carpeta de instalación",
"description": "Cambia la carpeta por defecto para las versiones de Beat Saber y próximas funciones.",
"description": "Cambiar la carpeta que contendrá todo el contenido descargado por BSManager.",
"choose-folder": "Elige la carpeta"
},
"additional-content": {
@@ -191,6 +198,38 @@
"report-bug": "Informar de un error",
"open-logs": "Abrir los registros"
}
},
"changelogs": {
"open" : "🚀 ¡Descubre lo nuevo en el Changelog!",
"not-founds": "😕 Uy, ¡Changelog no encontrado!"
},
"advanced": {
"title": "Avanzados",
"description": "Configuraciones avanzadas para BSManager.",
"hardware-acceleration": {
"title": "Aceleración de hardware",
"description": "Habilite la aceleración de hardware para usar su GPU y mejorar el rendimiento de BSManager. Desactive esta opción si experimenta caídas de fotogramas.",
"modal": {
"title": "Reinicio necesario",
"body": "Cambiar la configuración de aceleración de hardware cerrará y reiniciará BSManager. ¿Estás seguro de que quieres hacer esto?",
"confirm-btn": "Sí, estoy seguro"
},
"error-notification": {
"message": "Ocurrió un error, no se puede desactivar la aceleración de hardware."
}
},
"use-symlinks": {
"title": "Usar enlaces simbólicos",
"description": "Utilice enlaces simbólicos en lugar de uniones para enlazar carpetas. Actívelo solo si realmente lo necesita.",
"modal": {
"title": "Permisos de enlace simbólico",
"body": "Al crear enlaces simbólicos, BSManager requerirá privilegios de administrador o el modo desarrollador activado en su sistema. ¿Estás seguro de que quieres continuar?",
"confirm-btn": "Sí, estoy seguro"
},
"error-notification": {
"message": "Ocurrió un error, no se pueden cambiar los ajustes de los enlaces simbólicos."
}
}
}
}
},
@@ -235,9 +274,6 @@
}
},
"errors": {
"titles": {
"dotnet-required": ".NET 6 Requerido"
},
"msg": {
"401": "Parece que Steam no quiere dejarnos descargar Beat Saber 😢",
"404": "No se puede contactar con los servidores de Steam",
@@ -260,11 +296,7 @@
"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": "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 Beat Saber. Descárgalo haciendo clic en el botón de abajo."
},
"actions": {
"download-dotnet": "Descargar .NET 6"
"AccessDenied": "El acceso a Steam ha sido denegado."
}
}
},
@@ -482,6 +514,15 @@
"title": "Backup creado",
"msg": "Compartir la carpeta 'UserData' puede generar errores, en caso de problemas desvincula la carpeta para restaurar la copia de seguridad"
}
},
"linking-error": {
"title": "Error al enlazar la carpeta",
"msg": {
"EPERM": "BSManager no tiene los permisos necesarios para enlazar la carpeta.",
"EACCES": "BSManager no tiene los permisos necesarios para enlazar la carpeta.",
"ENOSPC": "El disco está lleno, libera espacio e inténtalo de nuevo.",
"UNKNOWN_ERROR": "Se ha producido un error desconocido al enlazar la carpeta."
}
}
},
"create-launch-shortcut": {
@@ -695,9 +736,7 @@
"title": "Atención",
"body": {
"must-be-installed-once": "Debes haber instalado Beat Saber al menos una vez desde la Oculus Store, de lo contrario, Beat Saber podría cerrarse automáticamente después de iniciar.",
"need-backup": "Para iniciar esta versión, la carpeta de instalación de Beat Saber que se encuentra en tu biblioteca de Oculus será renombrada.",
"can-restore-later": "Si es necesario, podrás restaurarla desde el BSManager accediendo a las opciones de la versión original de Oculus y haciendo clic en 'Restaurar la carpeta'",
"tips-launch-oculus": "Consejo: Podrás iniciar esta versión directamente desde Oculus, siempre que la versión original no haya sido restaurada."
"will-backup": "Para lanzar esta versión, la carpeta de instalación original de Beat Saber ubicada en tu biblioteca de Oculus será renombrada y se restaurará automáticamente al cerrar Beat Saber."
},
"not-remind-me": "No volver a recordármelo",
"understood": "Entendido"
@@ -719,21 +758,40 @@
"enter-oculus-token": "Introducir un token de Oculus"
},
"valid-btn": "Validar"
},
"launch-as-admin": {
"title": "Permisos Administrador",
"body": {
"info": "Se ha detectado que Steam está funcionando con permisos de administrador. Para comunicarse con Steam, Beat Saber también debe iniciarse como administrador. De lo contrario, Beat Saber podría experimentar problemas y cerrarse después de iniciar.",
"info-2": "Iniciar Beat Saber en modo administrador también otorgará derechos de administrador a los mods instalados. Por lo tanto, se recomienda reiniciar Steam sin permisos de administrador.",
"info-3": "Tenga en cuenta que se desaconseja otorgar derechos de administrador a Steam, ya que esto afecta a los juegos y mods instalados, presentando un riesgo de seguridad."
},
"launch-as-admin": "Iniciar como Administrador",
"not-remind-me": "No volver a recordármelo"
},
"ask-install-path": {
"title": "Carpeta de instalación",
"choose-folder-description": "Elija la carpeta que contendrá todo el contenido descargado por BSManager. (versiones, mods, mapas, listas de reproducción, etc.)",
"choose-folder": "Elige la carpeta",
"default": "Predeterminado",
"default-tooltip": "Por defecto, en su carpeta personal"
}
},
"maps": {
"map-filter-panel": {
"duration": "Duración",
"nps" : "Notas Por Segundo",
"njs": "Velocidad de salto de nota",
"tags": "tags",
"specificities": "general",
"requirements": "requisitos"
"requirements": "requisitos",
"exclude": "excluir"
},
"map-types": {
"accuracy": "precisión",
"balanced": "equilibrado",
"challenge": "desafío",
"dancestyle": "baile",
"dance-style": "baile",
"fitness": "fitness",
"speed": "speed",
"tech": "tech"
@@ -753,13 +811,13 @@
"rb": "r&b",
"holiday": "vacaciones",
"vocaloid": "vocaloid",
"jrock": "j-rock",
"j-rock": "j-rock",
"trance": "trance",
"drumbass": "drum & bass",
"comedy": "comedia",
"instrumental": "instrumental",
"hardcore": "hardcore",
"kpop": "k-pop",
"k-pop": "k-pop",
"indie": "indie",
"techno": "tecno",
"house": "house",
@@ -770,7 +828,7 @@
"metal": "metal",
"anime": "anime",
"hiphop": "hiphop",
"jpop": "j-pop",
"j-pop": "j-pop",
"rock": "rock",
"pop": "pop",
"electronic": "electrónico",
@@ -783,6 +841,9 @@
"verified": "verificado",
"fullSpread": "panel completo"
},
"map-excludes": {
"installed": "instalado"
},
"difficulties": {
"Easy": "fácil",
"Normal": "normal",
@@ -990,6 +1051,122 @@
}
}
},
"playlist": {
"error-playlist-creation-title": "Error al crear la lista de reproducción",
"error-playlist-creation-desc": "Ocurrió un error al crear la lista de reproducción.",
"playlist-created-title": "Lista de reproducción creada",
"playlist-created-desc": "La lista de reproducción se ha creado con éxito. ¡Ahora puedes sincronizar sus mapas!",
"download-playlist": "Descargar lista de reproducción",
"synchronize-playlist": "Sincronizar lista de reproducción",
"synchronize-maps": "Sincronizar mapas",
"error-playlists-synchronization-title": "Error al sincronizar listas de reproducción",
"error-playlists-synchronization-desc": "Ocurrió un error al sincronizar las listas de reproducción.",
"playlists-synchronized-title": "¡Listas de reproducción sincronizadas!",
"playlists-synchronized-desc": "Las listas de reproducción y sus mapas han sido descargados.",
"playlists-export-error-title": "Error al exportar listas de reproducción",
"playlists-export-error-desc": "Ocurrió un error al exportar las listas de reproducción.",
"playlists-exported-title": "¡Listas de reproducción exportadas!",
"playlists-exported-desc": "Las listas de reproducción se han exportado con éxito.",
"playlists-with-maps-exported-desc": "Las listas de reproducción y sus mapas se han exportado con éxito.",
"playlist-delete-error-title": "Error al eliminar la lista de reproducción",
"playlist-delete-error-desc": "Ocurrió un error al eliminar la lista de reproducción.",
"playlists-deleted-title": "¡Listas de reproducción eliminadas!",
"playlists-deleted-desc": "Las listas de reproducción se han eliminado con éxito.",
"edit-playlist": "Editar lista de reproducción",
"playlist-edit-error-title": "Error al editar la lista de reproducción",
"playlist-edit-error-desc": "Ocurrió un error al editar la lista de reproducción.",
"playlist-edited-title": "¡Lista de reproducción editada!",
"playlist-edited-desc": "La lista de reproducción se ha modificado con éxito. ¡Ahora puedes sincronizar sus mapas!",
"playlists-loading": "Cargando listas de reproducción...",
"no-playlists": "No hay listas de reproducción",
"download-playlists": "Descargar listas de reproducción",
"created-by": "Creado por",
"stop-download": "Detener descarga",
"cancel-download": "Cancelar descarga",
"open-file": "Abrir archivo",
"link-playlists": "Vincular listas de reproducción",
"link-playlist-desc": "Vincular listas de reproducción permite compartirlas entre todas las versiones. Una vez vinculada, esta versión se beneficiará de las listas de reproducción compartidas",
"link-playlist-info": "Añadir y eliminar listas de reproducción también se compartirá",
"keep-playlists": "Mantener listas de reproducción",
"keep-playlists-tip": "Mantener las listas de reproducción moverá las listas de la versión actual a la carpeta de listas compartidas. De lo contrario, se perderán",
"unlink-playlists": "Desvincular listas de reproducción",
"unlink-playlist-desc": "Advertencia, desvincular las listas de reproducción ya no permitirá el uso de listas compartidas para esta versión.",
"unlink-keep-playlists-tip": "Mantener las listas de reproducción creará una copia de las listas compartidas para la versión actual. De lo contrario, no se mantendrán listas para esta versión.",
"delete-playlist-ask": "¿Eliminar lista de reproducción?",
"delete-playlists-ask": "¿Eliminar listas de reproducción?",
"delete-playlist-desc": "¿Estás seguro de que quieres eliminar la lista de reproducción \"{playlistTitle}\"?",
"delete-playlists-desc": "¿Estás seguro de que quieres eliminar {nb} listas de reproducción?",
"delete-maps": "Eliminar mapas",
"delete-playlist-maps-tip": "Si está activado, se eliminarán todos los mapas de la lista de reproducción",
"delete-playlists-maps-tip": "Si está activado, se eliminarán todos los mapas de las listas de reproducción",
"export-playlist-ask": "¿Exportar lista de reproducción?",
"export-playlists-ask": "¿Exportar listas de reproducción?",
"export-playlist-desc": "¿Estás seguro de que quieres exportar la lista de reproducción \"{playlistTitle}\"?",
"export-playlists-desc": "¿Estás seguro de que quieres exportar {nb} listas de reproducción?",
"export-maps": "Exportar mapas",
"export-playlist-maps-tip": "Si está activado, también se exportarán todos los mapas de la lista de reproducción",
"export-playlists-maps-tip": "Si está activado, también se exportarán todos los mapas de las listas de reproducción",
"export": "Exportar",
"need-clone-title": "Advertencia",
"need-clone-desc-1": "Esta lista de reproducción se ha descargado de un sitio externo y contiene un enlace de sincronización.",
"need-clone-desc-2": "Para evitar perder tus cambios durante la sincronización, la lista de reproducción se duplicará y se eliminará su enlace de sincronización.",
"need-clone-desc-3": "Luego puedes, si lo deseas, eliminar la lista de reproducción original.",
"understood": "Entendido",
"synchronize-playlist-ask": "¿Sincronizar lista de reproducción?",
"synchronize-playlists-ask": "¿Sincronizar listas de reproducción?",
"synchronize-playlist-desc": "¿Estás seguro de que quieres sincronizar la lista de reproducción \"{playlistTitle}\"?",
"synchronize-playlists-desc": "¿Estás seguro de que quieres sincronizar {nb} listas de reproducción?",
"synchronize-playlist-tip": "Esta acción actualiza las listas de reproducción y descarga los mapas faltantes; puede tardar varios minutos.",
"synchronize": "Sincronizar",
"curated": "Recomendado",
"verified-mapper": "Mapeador verificado",
"empty-playlists": "Listas de reproducción vacías",
"search-playlist": "Buscar una lista de reproducción",
"no-playlists-found": "No se encontraron listas de reproducción",
"error-occur-while-loading-playlists": "Ocurrió un error al cargar las listas de reproducción",
"error-occur-while-loading-playlist": "Ocurrió un error al cargar la lista de reproducción",
"loading-maps": "Cargando mapas...",
"no-maps-found-for-playlist": "No se encontraron mapas para esta lista de reproducción",
"playlist-contain-no-maps": "La lista de reproducción no contiene mapas",
"no-map-installed-for-playlist": "No hay mapas instalados para esta lista de reproducción",
"playlist-is-waiting-to-download": "La lista de reproducción está esperando para descargar",
"download-maps": "Descargar mapas",
"download-missing-maps": "Descargar mapas faltantes",
"playlist-is-downloading": "La lista de reproducción se está descargando",
"some-playlist-maps-are-missing": "Faltan algunos mapas en esta lista de reproducción",
"create-a-playlist": "Crear una lista de reproducción",
"synchronize-playlists": "Sincronizar listas de reproducción",
"export-playlists": "Exportar listas de reproducción",
"delete-playlists": "Eliminar listas de reproducción",
"choose-image": "Elegir una imagen",
"title": "Título",
"playlist-title": "Título de la lista de reproducción",
"description": "Descripción",
"playlist-description": "Descripción de la lista de reproducción",
"author": "Autor",
"playlist-author": "Autor de la lista de reproducción",
"save": "Guardar",
"loading": "Cargando...",
"installed": "Instalado",
"no-map-found": "No se encontró ningún mapa",
"edit-playlist-shortcuts": "Mantén presionado Shift o Ctrl para seleccionar múltiples mapas",
"add-to-playlist": "Añadir a la lista de reproducción",
"remove-from-playlist": "Quitar de la lista de reproducción",
"playlist-is-empty": "La lista de reproducción está vacía",
"continue": "Continuar",
"nb-maps": "Número de mapas",
"nb-mappers": "Número de mapeadores",
"duration": "Duración",
"nps": "Notas por segundo",
"date-picker": {
"start-date-end-date": "Fecha de inicio — Fecha de fin",
"all": "Todo",
"last-24h": "Últimas 24h",
"last-week": "Última semana",
"last-month": "Último mes",
"3-last-month": "Últimos 3 meses"
}
},
"dateformat": {
"dayNames": ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb", "Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"],
"monthNames": ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic", "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"],
+201 -22
View File
@@ -14,7 +14,8 @@
"refuse": "Refuser",
"apply": "Appliquer",
"copy": "Copier",
"copied": "Copié !"
"copied": "Copié !",
"confirm": "Confirmer"
},
"nav-bar": {
"add-version": "Ajouter une version",
@@ -73,7 +74,8 @@
"mods-not-available": "Aucun mod n'est encore disponible pour cette version de Beat Saber",
"buttons": {
"more-infos": "Plus d'infos",
"install-or-update": "Installer ou mettre à jour"
"install-or-update": "Installer ou mettre à jour",
"reinstall-all": "Tout réinstaller"
},
"mods-grid": {
"header-bar": {
@@ -85,6 +87,12 @@
"uninstall-all": "Tout désinstaller"
}
}
},
"notifications": {
"all-mods-already-installed": {
"title": "Mods déjà installées",
"description": "Tous les mods séléctionnées sont déjà installées"
}
}
},
"dropdown": {
@@ -94,8 +102,7 @@
"edit": "Modifier",
"uninstall": "Désinstaller",
"create-shortcut": "Créer un raccourci",
"shared-folders": "Dossiers partagés",
"restore-oculus-folder": "Restaurer le dossier"
"shared-folders": "Dossiers partagés"
}
},
"available-versions": {
@@ -132,7 +139,7 @@
},
"installation-folder": {
"title": "Dossier d'installation",
"description": "Change le dossier par défaut pour les versions de Beat Saber et d'autres fonctionnalités à venir.",
"description": "Changer le dossier qui contiendra tout le contenu téléchargé par BSManager.",
"choose-folder": "Choisir un dossier"
},
"additional-content": {
@@ -191,6 +198,38 @@
"report-bug": "Signaler un bug",
"open-logs": "Ouvrir les logs"
}
},
"changelogs": {
"open" : "🚀 Jetez un œil au Changelog !",
"not-founds": "😕 Oups, Changelog introuvable !"
},
"advanced": {
"title": "Avancés",
"description": "Paramètres avancés pour BSManager.",
"hardware-acceleration": {
"title": "Accélération matérielle",
"description": "Activez l'accélération matérielle pour utiliser votre GPU et améliorer les performances de BSManager. Désactivez cette option si vous rencontrez des chutes d'IPS.",
"modal": {
"title": "Redémarrage nécessaire",
"body": "Changer le paramètre d'accélération matérielle va quitter et relancer BSManager. Êtes-vous sûr de vouloir continuer ?",
"confirm-btn": "Oui, je suis sûr"
},
"error-notification": {
"message": "Une erreur s'est produite, impossible de désactiver l'accélération matérielle."
}
},
"use-symlinks": {
"title": "Utiliser des liens symboliques",
"description": "Utilisez des liens symboliques au lieu de jonctions pour lier des dossiers. Activez cette option uniquement si vous en avez besoin.",
"modal": {
"title": "Permissions des liens symboliques",
"body": "Lors de la création de liens symboliques, BSManager nécessitera des privilèges administrateur ou le mode développeur activé sur votre système. Êtes-vous sûr de vouloir continuer ?",
"confirm-btn": "Oui, je suis sûr"
},
"error-notification": {
"message": "Une erreur s'est produite, impossible de changer les paramètres des liens symboliques."
}
}
}
}
},
@@ -235,9 +274,6 @@
}
},
"errors": {
"titles": {
"dotnet-required": ".NET 6 Requis"
},
"msg": {
"401": "Steam ne semble pas vouloir nous laisser télécharger Beat Saber 😢",
"404": "Impossible de contacter les serveurs de Steam.",
@@ -260,11 +296,7 @@
"LicenceError": "Impossible d'obtenir la liste des licences.",
"RateLimitExceeded": "Tu as essayé trop de fois attends un peu et recommence 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."
},
"actions": {
"download-dotnet": "Télécharger .NET 6"
"AccessDenied": "L'accès à Steam a été refusé."
}
}
},
@@ -482,7 +514,17 @@
"title": "Sauvegarde créée",
"msg": "Le partage du dossier 'UserData' peut générer des erreurs, en cas de soucis déliez le dossier pour restaurer la sauvegarde"
}
},
"linking-error": {
"title": "Erreur lors de la liaison du dossier",
"msg": {
"EPERM": "BSManager n'a pas les autorisations nécessaires pour lier le dossier.",
"EACCES": "BSManager n'a pas les autorisations nécessaires pour lier le dossier.",
"ENOSPC": "Le disque est plein, faites de la place et réessayez.",
"UNKNOWN_ERROR": "Une erreur inconnue est survenue lors de la liaison du dossier."
}
}
},
"create-launch-shortcut": {
"success": {
@@ -695,9 +737,7 @@
"title": "Attention",
"body": {
"must-be-installed-once": "Vous devez avoir installé au moins une fois Beat Saber depuis l'Oculus Store, sinon Beat Saber pourrait se fermer automatiquement après son lancement.",
"need-backup": "Pour lancer cette version, le dossier d'installation de Beat Saber se trouvant dans votre librairie Oculus va être renommé.",
"can-restore-later": "Au besoin, vous pourrez le restaurer depuis BSManager en vous rendant dans les options de la version originale Oculus et en cliquant sur \"Restaurer le dossier\"",
"tips-launch-oculus": "Astuce : Vous pourrez lancer cette version directement depuis Oculus, tant que la version originale n'est pas restaurée."
"will-backup": "Afin de lancer cette version, le dossier d'installation original de Beat Saber se trouvant dans votre bibliothèque Oculus va être renommé et sera automatiquement restauré à l'arrêt de Beat Saber."
},
"not-remind-me": "Ne plus me rappeler",
"understood": "J'ai compris"
@@ -719,21 +759,40 @@
"enter-oculus-token": "Entrer un token Oculus"
},
"valid-btn": "Valider"
},
"launch-as-admin": {
"title": "Permissions Administrateur",
"body": {
"info": "Steam a été détecté comme fonctionnant avec des permissions administrateur. Afin communiquer avec Steam, Beat Saber doit également être lancé en tant qu'administrateur. Dans le cas contraire, Beat Saber pourrait rencontrer des problèmes et se fermer après son lancement.",
"info-2": "Lancer Beat Saber en mode administrateur donnera également les droits administrateur aux mods installés. Il est donc plutôt recommandé de redémarrer Steam sans permissions administrateur.",
"info-3": "Notez qu'il est déconseillé de donner des droits d'administrateur à Steam, car cela affecte également les jeux et mods installés, présentant un risque pour la sécurité."
},
"launch-as-admin": "Lancer en administateur",
"not-remind-me": "Ne plus me rappeler"
},
"ask-install-path": {
"title": "Dossier d'installation",
"choose-folder-description": "Choisissez le dossier qui contiendra tout le contenu téléchargé par BSManager. (versions, mods, cartes, playlists, etc.)",
"choose-folder": "Choisir un dossier",
"default": "Par défaut",
"default-tooltip": "Par défaut, dans votre dossier personnel"
}
},
"maps": {
"map-filter-panel": {
"duration": "Durée",
"nps" : "Notes Par Seconde",
"njs": "Vitesse de saut des notes",
"tags": "tags",
"specificities": "général",
"requirements": "requis"
"requirements": "requis",
"exclude": "exclure"
},
"map-types": {
"accuracy": "précision",
"balanced": "équilibrée",
"challenge": "challenge",
"dancestyle": "dance",
"dance-style": "dance",
"fitness": "fitness",
"speed": "vitesse",
"tech": "tech"
@@ -753,13 +812,13 @@
"rb": "r&b",
"holiday": "vacance",
"vocaloid": "vocaloid",
"jrock": "j-rock",
"j-rock": "j-rock",
"trance": "trance",
"drumbass": "drum & bass",
"comedy": "comédie",
"instrumental": "instrumental",
"hardcore": "hardcore",
"kpop": "k-pop",
"k-pop": "k-pop",
"indie": "indé",
"techno": "techno",
"house": "house",
@@ -770,7 +829,7 @@
"metal": "metal",
"anime": "anime",
"hiphop": "hiphop",
"jpop": "j-pop",
"j-pop": "j-pop",
"rock": "rock",
"pop": "pop",
"electronic": "électronique",
@@ -783,6 +842,9 @@
"verified": "vérifiée",
"fullSpread": "panel complet"
},
"map-excludes": {
"installed": "installé"
},
"difficulties": {
"Easy": "facile",
"Normal": "normal",
@@ -798,7 +860,8 @@
"bsr-code" : "Code BSR",
"download" : "Télécharger la carte",
"downloading" :"Téléchargement de la carte",
"cancel-download" : "Annuler le téléchargement"
"cancel-download" : "Annuler le téléchargement",
"hightlight-difficulty" : "Surligner la difficulté"
}
},
"models": {
@@ -990,6 +1053,122 @@
}
}
},
"playlist": {
"error-playlist-creation-title": "Erreur lors de la création de la playlist",
"error-playlist-creation-desc": "Une erreur est survenue lors de la création de la playlist.",
"playlist-created-title": "Playlist créée",
"playlist-created-desc": "La playlist a été créée avec succès. Tu peut maintenant synchroniser ses maps !",
"download-playlist": "Télécharger la playlist",
"synchronize-playlist": "Synchroniser la playlist",
"synchronize-maps": "Synchroniser les maps",
"error-playlists-synchronization-title": "Erreur lors de la synchronisation des playlists",
"error-playlists-synchronization-desc": "Une erreur est survenue lors de la synchronisation des playlists.",
"playlists-synchronized-title": "Playlists synchronisées !",
"playlists-synchronized-desc": "Les playlists et leurs maps ont été téléchargées.",
"playlists-export-error-title": "Erreur lors de l'exportation des playlists",
"playlists-export-error-desc": "Une erreur est survenue lors de l'exportation des playlists.",
"playlists-exported-title": "Playlists exportées !",
"playlists-exported-desc": "Les playlists ont été exportées avec succès.",
"playlists-with-maps-exported-desc": "Les playlists et leurs maps ont été exportées avec succès.",
"playlist-delete-error-title": "Erreur lors de la suppression de la playlist",
"playlist-delete-error-desc": "Une erreur est survenue lors de la suppression de la playlist.",
"playlists-deleted-title": "Playlists supprimées !",
"playlists-deleted-desc": "Les playlists ont été supprimées avec succès.",
"edit-playlist": "Éditer la playlist",
"playlist-edit-error-title": "Erreur lors de l'édition de la playlist",
"playlist-edit-error-desc": "Une erreur est survenue lors de l'édition de la playlist.",
"playlist-edited-title": "Playlist éditée !",
"playlist-edited-desc": "La playlist a été modifiée avec succès. Tu peut maintenant synchroniser ses maps !",
"playlists-loading": "Chargement des playlist...",
"no-playlists": "Aucune playlist",
"download-playlists": "Télécharger des playlists",
"created-by": "Créée par",
"stop-download": "Arrêter le téléchargement",
"cancel-download": "Annuler le téléchargement",
"open-file": "Ouvrir le fichier",
"link-playlists": "Lier les playlists",
"link-playlist-desc": "La liaison des playlists permet de partager les playlists entre toute les version. Une fois liée, cette version profitera des playlists partagées",
"link-playlist-info": "L'ajout et la suppression de playlists sera également partagé",
"keep-playlists": "Conserver les playlists",
"keep-playlists-tip": "Conserver les playlists déplacera les playlists de la version actuelle dans le dossier des playlists partagées. Dans le cas contraire elles seront perdues",
"unlink-playlists": "Délier les playlists",
"unlink-playlist-desc": "Attention, délier les playlists ne permettra plus l'utilisation des playlists paratagées pour cette version.",
"unlink-keep-playlists-tip": "Conserver les playlists créera une copie des playlists partagées pour la version actuelle. Dans le cas contraire, aucune playlist ne sera conservée pour cette version.",
"delete-playlist-ask": "Supprimer la playlist ?",
"delete-playlists-ask": "Supprimer les playlists ?",
"delete-playlist-desc": "Es-tu sur de vouloir supprimer la playlist \"{playlistTitle}\" ?",
"delete-playlists-desc": "Es-tu sur de vouloir supprimer {nb} playlists ?",
"delete-maps": "Supprimer les maps",
"delete-playlist-maps-tip": "Si activé, toutes les maps de la playlist seront supprimées",
"delete-playlists-maps-tip": "Si activé, toutes les maps des playlists seront supprimées",
"export-playlist-ask": "Exporter la playlist ?",
"export-playlists-ask": "Exporter les playlists ?",
"export-playlist-desc": "Es-tu sur de vouloir exporter la playlist \"{playlistTitle}\" ?",
"export-playlists-desc": "Es-tu sur de vouloir exporter les {nb} playlists ?",
"export-maps": "Exporter les maps",
"export-playlist-maps-tip": "Si activé, toutes les maps de la playlist seront également exportées",
"export-playlists-maps-tip": "Si activé, toutes les maps des playlists seront également exportées",
"export": "Exporter",
"need-clone-title": "Attention",
"need-clone-desc-1": "Cette playlist a été téléchargée depuis un site externe et contient un lien de synchronisation.",
"need-clone-desc-2": "Pour éviter de perdre vos modifications lors d'une synchronisation, la playlist va être dupliquée et son lien de synchronisation supprimé.",
"need-clone-desc-3": "Vous pourrez ensuite, si vous le souhaitez, supprimer la playlist originale.",
"understood": "J'ai compris",
"synchronize-playlist-ask": "Synchroniser la playlist ?",
"synchronize-playlists-ask": "Synchroniser les playlists ?",
"synchronize-playlist-desc": "Es-tu sur de vouloir synchroniser la playlist \"{playlistTitle}\" ?",
"synchronize-playlists-desc": "Es-tu sur de vouloir synchroniser les {nb} playlists ?",
"synchronize-playlist-tip": "Cette action met à jour les playlists et télécharge les maps manquantes; cela peut durer plusieurs minutes.",
"synchronize": "Synchroniser",
"curated": "Recommandée",
"verified-mapper": "Mapper vérifié",
"empty-playlists": "Playlists vides",
"search-playlist": "Rechercher une playlist",
"no-playlists-found": "Aucune playlists trouvées",
"error-occur-while-loading-playlists": "Une erreur est survenue lors du chargement des playlists",
"error-occur-while-loading-playlist": "Une erreur est survenue lors du chargement de la playlist",
"loading-maps":"Chargement des maps...",
"no-maps-found-for-playlist":"Aucune map trouvée pour cette playlist",
"playlist-contain-no-maps":"La playlist ne contient aucune map",
"no-map-installed-for-playlist":"Aucune map installée pour cette playlist",
"playlist-is-waiting-to-download":"La playlist est en attente de téléchargment",
"download-maps": "Télécharger les maps",
"download-missing-maps": "Télécharger les maps manquantes",
"playlist-is-downloading":"La playlist est en cours de téléchargement",
"some-playlist-maps-are-missing":"Certaines maps de cette playlist sont manquantes",
"create-a-playlist": "Créer une playlist",
"synchronize-playlists": "Synchroniser les playlists",
"export-playlists": "Exporter les playlists",
"delete-playlists": "Supprimer les playlists",
"choose-image": "Choisir une image",
"title": "Titre",
"playlist-title": "Titre de la playlist",
"description": "Description",
"playlist-description": "Description de la playlist",
"author": "Auteur",
"playlist-author": "Auteur de la playlist",
"save": "Enregistrer",
"loading": "Chargement...",
"installed": "Installée",
"no-map-found": "Aucune map trouvée",
"edit-playlist-shortcuts": "Maintenez Maj ou Ctrl pour sélectionner plusieurs maps",
"add-to-playlist": "Ajouter à la playlist",
"remove-from-playlist": "Retirer de la playlist",
"playlist-is-empty": "La playlist est vide",
"continue": "Continuer",
"nb-maps": "Nombre de maps",
"nb-mappers": "Nombre de mappers",
"duration": "Durée",
"nps": "Notes par secondes",
"date-picker": {
"start-date-end-date": "Date début — Date fin",
"all": "Tout",
"last-24h": "Dernières 24h",
"last-week": "Dernière semaine",
"last-month": "Dernier mois",
"3-last-month": "3 derniers mois"
}
},
"dateformat": {
"dayNames": ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"],
"monthNames": ["Jan", "Fév", "Mar", "Avr", "Mai", "Jun", "Juil", "Aou", "Sept", "Oct", "Nov", "Déc", "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"],
+201 -24
View File
@@ -14,7 +14,8 @@
"refuse": "拒否する",
"apply": "適用",
"copy": "コピー",
"copied": "コピー済み!"
"copied": "コピー済み!",
"confirm": "確認"
},
"nav-bar": {
"add-version": "バージョンを追加",
@@ -73,7 +74,8 @@
"mods-not-available": "このバージョンで使用できるMODはまだありません。",
"buttons": {
"more-infos": "詳細情報",
"install-or-update": "インストールとアップデート"
"install-or-update": "インストールとアップデート",
"reinstall-all": "すべて再インストール"
},
"mods-grid": {
"header-bar": {
@@ -85,6 +87,12 @@
"uninstall-all": "全てアンインストールする"
}
}
},
"notifications": {
"all-mods-already-installed": {
"title": "すでにインストール済みのMOD",
"description": "選択したすべてのMODはすでにインストールされています"
}
}
},
"dropdown": {
@@ -94,8 +102,7 @@
"edit": "編集",
"uninstall": "アンインストール",
"create-shortcut": "ショートカットを作成",
"shared-folders": "共有フォルダー",
"restore-oculus-folder": "フォルダーの復元"
"shared-folders": "共有フォルダー"
}
},
"available-versions": {
@@ -132,7 +139,7 @@
},
"installation-folder": {
"title": "インストールフォルダー",
"description": "BeatSaberのバージョンとその他の今後の機能を入れるフォルダを変更します。",
"description": "BSManager によってダウンロードされたすべてのコンテンツを含むフォルダを変更します。",
"choose-folder": "フォルダーを選択"
},
"additional-content": {
@@ -191,6 +198,38 @@
"report-bug": "バグを報告",
"open-logs": "ログを表示"
}
},
"changelogs": {
"open" : "🚀 チェンジログを覗いてみて!",
"not-founds": "😕 あれ、チェンジログが見当たらない!"
},
"advanced": {
"title": "高度な設定",
"description": "BSManagerの高度な設定。",
"hardware-acceleration": {
"title": "ハードウェアアクセラレーション",
"description": "ハードウェアアクセラレーションを有効にしてGPUを使用し、BSManagerのパフォーマンスを向上させます。フレームドロップが発生している場合は、これをオフにしてください。",
"modal": {
"title": "再起動が必要",
"body": "ハードウェアアクセラレーションの設定を変更すると、BSManagerが終了して再起動します。本当に続行しますか?",
"confirm-btn": "はい、確かです"
},
"error-notification": {
"message": "エラーが発生しました。ハードウェアアクセラレーションを無効にできません。"
}
},
"use-symlinks": {
"title": "シンボリックリンクを使用",
"description": "フォルダをリンクするためにジャンクションの代わりにシンボリックリンクを使用します。本当に必要な場合にのみこれをオンにしてください。",
"modal": {
"title": "シンボリックリンクの権限",
"body": "シンボリックリンクを作成する際、BSManagerは管理者権限またはシステムで有効になっている開発者モードを必要とします。本当に続行しますか?",
"confirm-btn": "はい、確かです"
},
"error-notification": {
"message": "エラーが発生しました。シンボリックリンク設定を変更できません。"
}
}
}
}
},
@@ -235,9 +274,6 @@
}
},
"errors": {
"titles": {
"dotnet-required": ".NET 6が必要です!"
},
"msg": {
"401": "SteamがBeat Saberのダウンロードを許可してくれないようだ。😢",
"404": "Steamサーバーに接続できません。",
@@ -260,11 +296,7 @@
"LicenceError": "ライセンスリストを取得できません。",
"RateLimitExceeded": "何度も試しているのでしばらくたって、もう一度お試しください。",
"TokenRejected": "ログイントークンが拒否されました 😕 もう一度お試しください。",
"AccessDenied": "Steamへのアクセスが拒否されました。",
"dotnet-required": "Beat Saberをダウンロードするには、.NET 6 Runtimeがインストールされている必要があります。下のボタンをクリックしてダウンロードしてください。"
},
"actions": {
"download-dotnet": ".NET 6をダウンロード"
"AccessDenied": "Steamへのアクセスが拒否されました。"
}
}
},
@@ -482,6 +514,15 @@
"title": "バックアップを作成しました",
"msg": "'UserData'フォルダを共有するとエラーが発生する可能性があります。問題が発生した場合は、フォルダをリンク解除してバックアップを復元してください。"
}
},
"linking-error": {
"title": "フォルダのリンク中にエラーが発生しました",
"msg": {
"EPERM": "BSManagerにはフォルダをリンクするための必要な権限がありません。",
"EACCES": "BSManagerにはフォルダをリンクするための必要な権限がありません。",
"ENOSPC": "ディスクがいっぱいです。空き容量を作ってもう一度試してください。",
"UNKNOWN_ERROR": "フォルダをリンク中に不明なエラーが発生しました。"
}
}
},
"create-launch-shortcut": {
@@ -695,9 +736,7 @@
"title": "注意",
"body": {
"must-be-installed-once": "少なくとも一度はOculus StoreからBeat Saberをインストールしている必要があります。そうしないとBeat Saberは起動後に自動的に終了する可能性があります。",
"need-backup": "このバージョンを起動するに、OculusライブラリにあるBeat Saberインストールフォルダ名前変更ます。",
"can-restore-later": "必要であれば、BSManagerから元のOculusバージョンのオプションに行き、'フォルダを復元'をクリックして復元することができます。",
"tips-launch-oculus": "ヒント: 元のバージョンが復元されない限り、Oculusから直接このバージョンを起動することができます。"
"will-backup": "このバージョンを起動するために、OculusライブラリにあるBeat Saberの元のインストールフォルダ名前変更され、Beat Saberの終了時に自動的に復元されます。"
},
"not-remind-me": "二度と表示しないでください",
"understood": "分かった"
@@ -719,21 +758,40 @@
"enter-oculus-token": "オキュラストークンを入力する"
},
"valid-btn": "確認"
},
"launch-as-admin": {
"title": "管理者権限",
"body": {
"info": "Steamが管理者権限で動作していることが検出されました。Steamと通信するためには、Beat Saberも管理者として起動する必要があります。そうでない場合、Beat Saberは問題が発生し、起動後に終了する可能性があります。",
"info-2": "管理者モードでBeat Saberを起動すると、インストールされたMODにも管理者権限が与えられます。そのため、管理者権限なしでSteamを再起動することをお勧めします。",
"info-3": "Steamに管理者権限を与えることはお勧めできません。これはインストールされたゲームやMODにも影響を与え、セキュリティリスクをもたらすからです。"
},
"launch-as-admin": "管理者として起動",
"not-remind-me": "Больше не напоминать"
},
"ask-install-path": {
"title": "インストールフォルダー",
"choose-folder-description": "BSManager によってダウンロードされたすべてのコンテンツ (バージョン、MOD、マップ、プレイリストなど) を含むフォルダを選択してください。",
"choose-folder": "フォルダーを選択",
"default": "デフォルト",
"default-tooltip": "デフォルトでは、ホームフォルダに設定されます"
}
},
"maps": {
"map-filter-panel": {
"duration": "尺",
"nps" : "秒間ノート数",
"njs": "ノートジャンプ速度",
"tags": "タグ",
"specificities": "一般",
"requirements": "要Mod"
"requirements": "要Mod",
"exclude": "除外する"
},
"map-types": {
"accuracy": "正確",
"balanced": "バランス",
"challenge": "挑戦",
"dancestyle": "ダンス",
"dance-style": "ダンス",
"fitness": "フットネス",
"speed": "スピード",
"tech": "技術的"
@@ -753,13 +811,13 @@
"rb": "r&b",
"holiday": "休日",
"vocaloid": "ボーカロイド",
"jrock": "j-rock",
"j-rock": "j-rock",
"trance": "トランス",
"drumbass": "ドラムンベース",
"comedy": "コメディ",
"instrumental": "器楽",
"hardcore": "ハードコア",
"kpop": "k-pop",
"k-pop": "k-pop",
"indie": "インディー",
"techno": "テクノ",
"house": "家",
@@ -770,7 +828,7 @@
"metal": "メタル",
"anime": "アニメ",
"hiphop": "ヒップポップ",
"jpop": "j-pop",
"j-pop": "j-pop",
"rock": "ロック",
"pop": "ポップ",
"electronic": "エレクトロニック",
@@ -783,6 +841,9 @@
"verified": "認証済み",
"fullSpread": "フルスプレッド"
},
"map-excludes": {
"installed": "インストール済み"
},
"difficulties": {
"Easy": "easy",
"Normal": "normal",
@@ -990,9 +1051,125 @@
}
}
},
"playlist": {
"error-playlist-creation-title": "プレイリストの作成エラー",
"error-playlist-creation-desc": "プレイリストの作成中にエラーが発生しました。",
"playlist-created-title": "プレイリストが作成されました",
"playlist-created-desc": "プレイリストが正常に作成されました。今すぐマップを同期できます!",
"download-playlist": "プレイリストをダウンロード",
"synchronize-playlist": "プレイリストを同期",
"synchronize-maps": "マップを同期",
"error-playlists-synchronization-title": "プレイリストの同期エラー",
"error-playlists-synchronization-desc": "プレイリストの同期中にエラーが発生しました。",
"playlists-synchronized-title": "プレイリストが同期されました!",
"playlists-synchronized-desc": "プレイリストとそのマップがダウンロードされました。",
"playlists-export-error-title": "プレイリストのエクスポートエラー",
"playlists-export-error-desc": "プレイリストのエクスポート中にエラーが発生しました。",
"playlists-exported-title": "プレイリストがエクスポートされました!",
"playlists-exported-desc": "プレイリストが正常にエクスポートされました。",
"playlists-with-maps-exported-desc": "プレイリストとそのマップが正常にエクスポートされました。",
"playlist-delete-error-title": "プレイリストの削除エラー",
"playlist-delete-error-desc": "プレイリストの削除中にエラーが発生しました。",
"playlists-deleted-title": "プレイリストが削除されました!",
"playlists-deleted-desc": "プレイリストが正常に削除されました。",
"edit-playlist": "プレイリストを編集",
"playlist-edit-error-title": "プレイリストの編集エラー",
"playlist-edit-error-desc": "プレイリストの編集中にエラーが発生しました。",
"playlist-edited-title": "プレイリストが編集されました!",
"playlist-edited-desc": "プレイリストが正常に変更されました。今すぐマップを同期できます!",
"playlists-loading": "プレイリストを読み込み中...",
"no-playlists": "プレイリストがありません",
"download-playlists": "プレイリストをダウンロード",
"created-by": "作成者",
"stop-download": "ダウンロードを停止",
"cancel-download": "ダウンロードをキャンセル",
"open-file": "ファイルを開く",
"link-playlists": "プレイリストをリンク",
"link-playlist-desc": "プレイリストをリンクすると、すべてのバージョン間でプレイリストを共有できます。リンクすると、このバージョンは共有プレイリストの恩恵を受けます",
"link-playlist-info": "プレイリストの追加と削除も共有されます",
"keep-playlists": "プレイリストを保持",
"keep-playlists-tip": "プレイリストを保持すると、現在のバージョンのプレイリストが共有プレイリストフォルダに移動されます。そうしない場合、それらは失われます",
"unlink-playlists": "プレイリストのリンクを解除",
"unlink-playlist-desc": "警告:プレイリストのリンクを解除すると、このバージョンでは共有プレイリストを使用できなくなります。",
"unlink-keep-playlists-tip": "プレイリストを保持すると、現在のバージョン用に共有プレイリストのコピーが作成されます。そうしない場合、このバージョンのプレイリストは保持されません。",
"delete-playlist-ask": "プレイリストを削除しますか?",
"delete-playlists-ask": "プレイリストを削除しますか?",
"delete-playlist-desc": "プレイリスト「{playlistTitle}」を削除してもよろしいですか?",
"delete-playlists-desc": "{nb}個のプレイリストを削除してもよろしいですか?",
"delete-maps": "マップを削除",
"delete-playlist-maps-tip": "有効にすると、プレイリスト内のすべてのマップが削除されます",
"delete-playlists-maps-tip": "有効にすると、プレイリスト内のすべてのマップが削除されます",
"export-playlist-ask": "プレイリストをエクスポートしますか?",
"export-playlists-ask": "プレイリストをエクスポートしますか?",
"export-playlist-desc": "プレイリスト「{playlistTitle}」をエクスポートしてもよろしいですか?",
"export-playlists-desc": "{nb}個のプレイリストをエクスポートしてもよろしいですか?",
"export-maps": "マップをエクスポート",
"export-playlist-maps-tip": "有効にすると、プレイリスト内のすべてのマップもエクスポートされます",
"export-playlists-maps-tip": "有効にすると、プレイリスト内のすべてのマップもエクスポートされます",
"export": "エクスポート",
"need-clone-title": "警告",
"need-clone-desc-1": "このプレイリストは外部サイトからダウンロードされ、同期リンクが含まれています。",
"need-clone-desc-2": "同期中に変更を失わないようにするため、プレイリストが複製され、同期リンクが削除されます。",
"need-clone-desc-3": "その後、必要に応じて元のプレイリストを削除できます。",
"understood": "理解しました",
"synchronize-playlist-ask": "プレイリストを同期しますか?",
"synchronize-playlists-ask": "プレイリストを同期しますか?",
"synchronize-playlist-desc": "プレイリスト「{playlistTitle}」を同期してもよろしいですか?",
"synchronize-playlists-desc": "{nb}個のプレイリストを同期してもよろしいですか?",
"synchronize-playlist-tip": "この操作はプレイリストを更新し、不足しているマップをダウンロードします。数分かかる場合があります。",
"synchronize": "同期",
"curated": "おすすめ",
"verified-mapper": "認証済みマッパー",
"empty-playlists": "空のプレイリスト",
"search-playlist": "プレイリストを検索",
"no-playlists-found": "プレイリストが見つかりません",
"error-occur-while-loading-playlists": "プレイリストの読み込み中にエラーが発生しました",
"error-occur-while-loading-playlist": "プレイリストの読み込み中にエラーが発生しました",
"loading-maps": "マップを読み込み中...",
"no-maps-found-for-playlist": "このプレイリストにマップが見つかりません",
"playlist-contain-no-maps": "プレイリストにマップが含まれていません",
"no-map-installed-for-playlist": "このプレイリストにインストールされたマップがありません",
"playlist-is-waiting-to-download": "プレイリストはダウンロード待ちです",
"download-maps": "マップをダウンロード",
"download-missing-maps": "不足しているマップをダウンロード",
"playlist-is-downloading": "プレイリストをダウンロード中です",
"some-playlist-maps-are-missing": "このプレイリストの一部のマップが不足しています",
"create-a-playlist": "プレイリストを作成",
"synchronize-playlists": "プレイリストを同期",
"export-playlists": "プレイリストをエクスポート",
"delete-playlists": "プレイリストを削除",
"choose-image": "画像を選択",
"title": "タイトル",
"playlist-title": "プレイリストのタイトル",
"description": "説明",
"playlist-description": "プレイリストの説明",
"author": "作者",
"playlist-author": "プレイリストの作者",
"save": "保存",
"loading": "読み込み中...",
"installed": "インストール済み",
"no-map-found": "マップが見つかりません",
"edit-playlist-shortcuts": "ShiftキーまたはCtrlキーを押しながら複数のマップを選択",
"add-to-playlist": "プレイリストに追加",
"remove-from-playlist": "プレイリストから削除",
"playlist-is-empty": "プレイリストが空です",
"continue": "続ける",
"nb-maps": "マップ数",
"nb-mappers": "マッパー数",
"duration": "継続時間",
"nps": "1秒あたりの音符数",
"date-picker": {
"start-date-end-date": "開始日 — 終了日",
"all": "すべて",
"last-24h": "過去24時間",
"last-week": "先週",
"last-month": "先月",
"3-last-month": "過去3ヶ月"
}
},
"dateformat": {
"dayNames": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
"monthNames": ["Jan", "Feb", "Mar", "Apr", "May", "June", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
"timeNames": ["a", "p", "am", "pm", "A", "P", "AM", "PM"]
"dayNames": ["", "", "", "", "", "", "", "日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"],
"monthNames": ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
"timeNames": ["午前", "午後", "午前", "午後", "午前", "午後", "午前", "午後"]
}
}
+197 -21
View File
@@ -14,7 +14,8 @@
"refuse": "Отказаться",
"apply": "Применить",
"copy": "Скопировать",
"copied": "Скопировано!"
"copied": "Скопировано!",
"confirm": "Подтвердить"
},
"nav-bar": {
"add-version": "Добавить версию игры",
@@ -73,7 +74,8 @@
"mods-not-available": "Не найдены моды для этой версии Beat Saber",
"buttons": {
"more-infos": "Подробнее",
"install-or-update": "Установить или обновить"
"install-or-update": "Установить или обновить",
"reinstall-all": "Переустановить все"
},
"mods-grid": {
"header-bar": {
@@ -85,6 +87,12 @@
"uninstall-all": "Удалить всё"
}
}
},
"notifications": {
"all-mods-already-installed": {
"title": "Моды уже установлены",
"description": "Все выбранные моды уже установлены"
}
}
},
"dropdown": {
@@ -94,8 +102,7 @@
"edit": "Редактировать",
"uninstall": "Удалить",
"create-shortcut": "Создать ярлык",
"shared-folders": "Общие папки",
"restore-oculus-folder": "Восстановить папку"
"shared-folders": "Общие папки"
}
},
"available-versions": {
@@ -132,7 +139,7 @@
},
"installation-folder": {
"title": "Папка установок",
"description": "Измените стандартную папку, где будут версии Beat Saber и прочее.",
"description": "Изменить папку, которая будет содержать весь контент, загруженный BSManager.",
"choose-folder": "Изменить папку"
},
"additional-content": {
@@ -191,6 +198,38 @@
"report-bug": "Сообщить о баге",
"open-logs": "Открыть логи"
}
},
"changelogs": {
"open" : "🚀 Изучаем Changelog!",
"not-founds": "😕 Ой, Changelog нигде не видно!"
},
"advanced": {
"title": "Дополнительные",
"description": "Дополнительные настройки для BSManager.",
"hardware-acceleration": {
"title": "Аппаратное ускорение",
"description": "Включите аппаратное ускорение, чтобы использовать ваш GPU и улучшить производительность BSManager. Отключите эту опцию, если у вас возникают пропуски кадров.",
"modal": {
"title": "Требуется перезагрузка",
"body": "Изменение настройки аппаратного ускорения приведет к завершению и перезапуску BSManager. Вы уверены, что хотите это сделать?",
"confirm-btn": "Да, я уверен"
},
"error-notification": {
"message": "Произошла ошибка, невозможно отключить аппаратное ускорение."
}
},
"use-symlinks": {
"title": "Использовать символические ссылки",
"description": "Используйте символические ссылки вместо соединений для связывания папок. Включайте эту опцию только если это действительно необходимо.",
"modal": {
"title": "Разрешения для символических ссылок",
"body": "При создании символических ссылок BSManager потребуется права администратора или включенный режим разработчика на вашем устройстве. Вы уверены, что хотите продолжить?",
"confirm-btn": "Да, я уверен"
},
"error-notification": {
"message": "Произошла ошибка, невозможно изменить настройки символических ссылок."
}
}
}
}
},
@@ -235,9 +274,6 @@
}
},
"errors": {
"titles": {
"dotnet-required": "Требуется .NET 6"
},
"msg": {
"401": "Похоже Steam не хочет, чтобы мы скачали Beat Saber 😢",
"404": "Нет связи с серверами Steam.",
@@ -260,11 +296,7 @@
"LicenceError": "Не удалось проверить наличие лицензии.",
"RateLimitExceeded": "Слишком много попыток, вернитесь позже и попробуйте снова.",
"TokenRejected": "Ваш токен для входа был отклонен 😕 Пожалуйста, попробуйте снова.",
"AccessDenied": "Доступ к Steam был отклонен.",
"dotnet-required": "Среда запуска .NET 6 должна быть установлена, чтобы скачать Beat Saber. Скачайте её с помощью кнопки ниже."
},
"actions": {
"download-dotnet": "Скачать .NET 6"
"AccessDenied": "Доступ к Steam был отклонен."
}
}
},
@@ -482,6 +514,15 @@
"title": "Бэкап создан",
"msg": "Общая папка 'UserData' может создавать ошибки. В случае проблем отвяжите папку, чтобы восстановить бэкап."
}
},
"linking-error": {
"title": "Ошибка при связывании папки",
"msg": {
"EPERM": "BSManager не имеет необходимых прав для связывания папки.",
"EACCES": "BSManager не имеет необходимых прав для связывания папки.",
"ENOSPC": "Диск заполнен, освободите место и попробуйте снова.",
"UNKNOWN_ERROR": "Произошла неизвестная ошибка при связывании папки."
}
}
},
"create-launch-shortcut": {
@@ -695,9 +736,7 @@
"title": "Внимание",
"body": {
"must-be-installed-once": "Вы должны были установить Beat Saber хотя бы один раз из Oculus Store, иначе Beat Saber может автоматически закрыться после запуска.",
"need-backup": "Для запуска этой версии папка установки Beat Saber в вашей библиотеке Oculus будет переименована.",
"can-restore-later": "При необходимости вы можете восстановить её через BSManager, перейдя в опции оригинальной версии Oculus и нажав на 'Восстановить папку'",
"tips-launch-oculus": "Совет: Вы можете запустить эту версию напрямую через Oculus, пока оригинальная версия не восстановлена."
"will-backup": "Для запуска этой версии исходная папка установки Beat Saber, находящаяся в вашей библиотеке Oculus, будет переименована и автоматически восстановлена при выходе из Beat Saber."
},
"not-remind-me": "Больше не напоминать",
"understood": "Понял"
@@ -719,21 +758,39 @@
"enter-oculus-token": "Введите токен Oculus"
},
"valid-btn": "Подтвердить"
},
"launch-as-admin": {
"title": "Права Администратора",
"body": {
"info": "Обнаружено, что Steam работает с правами администратора. Чтобы связаться со Steam, Beat Saber также должен быть запущен от имени администратора. В противном случае Beat Saber может столкнуться с проблемами и закрыться после запуска.",
"info-2": "Запуск Beat Saber в режиме администратора также даст права администратора установленным модам. Поэтому рекомендуется перезапустить Steam без прав администратора.",
"info-3": "Обратите внимание, что не рекомендуется предоставлять права администратора Steam, так как это также влияет на установленные игры и моды, представляя угрозу безопасности."
},
"launch-as-admin": "Запустить от имени администратора"
},
"ask-install-path": {
"title": "Папка установок",
"choose-folder-description": "Выберите папку, которая будет содержать весь контент, загруженный BSManager. (версии, моды, карты, плейлисты и т.д.)",
"choose-folder": "Изменить папку",
"default": "По умолчанию",
"default-tooltip": "По умолчанию в вашей домашней папке"
}
},
"maps": {
"map-filter-panel": {
"duration": "Длительность",
"nps" : "Нот в Секунду",
"njs": "Скорость прыжка нот",
"tags": "тэги",
"specificities": "основное",
"requirements": "требуемые моды"
"requirements": "требуемые моды",
"exclude": "исключить"
},
"map-types": {
"accuracy": "точность",
"balanced": "баланс",
"challenge": "испытание",
"dancestyle": "танец",
"dance-style": "танец",
"fitness": "фитнес",
"speed": "скорость",
"tech": "техника"
@@ -753,13 +810,13 @@
"rb": "ар-н-би",
"holiday": "праздник",
"vocaloid": "вокалоиды",
"jrock": "джей-рок",
"j-rock": "джей-рок",
"trance": "транс",
"drumbass": "драм-н-бейс",
"comedy": "комедия",
"instrumental": "инструментальные",
"hardcore": "хардкор",
"kpop": "кей-поп",
"k-pop": "кей-поп",
"indie": "инди",
"techno": "техно",
"house": "хаус",
@@ -770,7 +827,7 @@
"metal": "метал",
"anime": "аниме",
"hiphop": "хипхоп",
"jpop": "джей-поп",
"j-pop": "джей-поп",
"rock": "прк",
"pop": "поп",
"electronic": "электроника",
@@ -783,6 +840,9 @@
"verified": "проверенные авторы",
"fullSpread": "полный набор"
},
"map-excludes": {
"installed": "установленный"
},
"difficulties": {
"Easy": "легко",
"Normal": "нормально",
@@ -990,6 +1050,122 @@
}
}
},
"playlist": {
"error-playlist-creation-title": "Ошибка при создании плейлиста",
"error-playlist-creation-desc": "Произошла ошибка при создании плейлиста.",
"playlist-created-title": "Плейлист создан",
"playlist-created-desc": "Плейлист успешно создан. Теперь вы можете синхронизировать его карты!",
"download-playlist": "Скачать плейлист",
"synchronize-playlist": "Синхронизировать плейлист",
"synchronize-maps": "Синхронизировать карты",
"error-playlists-synchronization-title": "Ошибка синхронизации плейлистов",
"error-playlists-synchronization-desc": "Произошла ошибка при синхронизации плейлистов.",
"playlists-synchronized-title": "Плейлисты синхронизированы!",
"playlists-synchronized-desc": "Плейлисты и их карты были загружены.",
"playlists-export-error-title": "Ошибка экспорта плейлистов",
"playlists-export-error-desc": "Произошла ошибка при экспорте плейлистов.",
"playlists-exported-title": "Плейлисты экспортированы!",
"playlists-exported-desc": "Плейлисты успешно экспортированы.",
"playlists-with-maps-exported-desc": "Плейлисты и их карты успешно экспортированы.",
"playlist-delete-error-title": "Ошибка удаления плейлиста",
"playlist-delete-error-desc": "Произошла ошибка при удалении плейлиста.",
"playlists-deleted-title": "Плейлисты удалены!",
"playlists-deleted-desc": "Плейлисты успешно удалены.",
"edit-playlist": "Редактировать плейлист",
"playlist-edit-error-title": "Ошибка редактирования плейлиста",
"playlist-edit-error-desc": "Произошла ошибка при редактировании плейлиста.",
"playlist-edited-title": "Плейлист отредактирован!",
"playlist-edited-desc": "Плейлист успешно изменен. Теперь вы можете синхронизировать его карты!",
"playlists-loading": "Загрузка плейлистов...",
"no-playlists": "Нет плейлистов",
"download-playlists": "Скачать плейлисты",
"created-by": "Создано",
"stop-download": "Остановить загрузку",
"cancel-download": "Отменить загрузку",
"open-file": "Открыть файл",
"link-playlists": "Связать плейлисты",
"link-playlist-desc": "Связывание плейлистов позволяет делиться плейлистами между всеми версиями. После связывания эта версия будет иметь доступ к общим плейлистам",
"link-playlist-info": "Добавление и удаление плейлистов также будет общим",
"keep-playlists": "Сохранить плейлисты",
"keep-playlists-tip": "Сохранение плейлистов переместит плейлисты из текущей версии в папку общих плейлистов. В противном случае они будут потеряны",
"unlink-playlists": "Отвязать плейлисты",
"unlink-playlist-desc": "Внимание, отвязка плейлистов больше не позволит использовать общие плейлисты для этой версии.",
"unlink-keep-playlists-tip": "Сохранение плейлистов создаст копию общих плейлистов для текущей версии. В противном случае для этой версии не будут сохранены плейлисты.",
"delete-playlist-ask": "Удалить плейлист?",
"delete-playlists-ask": "Удалить плейлисты?",
"delete-playlist-desc": "Вы уверены, что хотите удалить плейлист \"{playlistTitle}\"?",
"delete-playlists-desc": "Вы уверены, что хотите удалить {nb} плейлистов?",
"delete-maps": "Удалить карты",
"delete-playlist-maps-tip": "Если включено, все карты в плейлисте будут удалены",
"delete-playlists-maps-tip": "Если включено, все карты в плейлистах будут удалены",
"export-playlist-ask": "Экспортировать плейлист?",
"export-playlists-ask": "Экспортировать плейлисты?",
"export-playlist-desc": "Вы уверены, что хотите экспортировать плейлист \"{playlistTitle}\"?",
"export-playlists-desc": "Вы уверены, что хотите экспортировать {nb} плейлистов?",
"export-maps": "Экспортировать карты",
"export-playlist-maps-tip": "Если включено, все карты в плейлисте также будут экспортированы",
"export-playlists-maps-tip": "Если включено, все карты в плейлистах также будут экспортированы",
"export": "Экспорт",
"need-clone-title": "Предупреждение",
"need-clone-desc-1": "Этот плейлист был загружен с внешнего сайта и содержит ссылку для синхронизации.",
"need-clone-desc-2": "Чтобы избежать потери ваших изменений во время синхронизации, плейлист будет дублирован, а его ссылка для синхронизации удалена.",
"need-clone-desc-3": "Затем вы можете, если хотите, удалить оригинальный плейлист.",
"understood": "Я понимаю",
"synchronize-playlist-ask": "Синхронизировать плейлист?",
"synchronize-playlists-ask": "Синхронизировать плейлисты?",
"synchronize-playlist-desc": "Вы уверены, что хотите синхронизировать плейлист \"{playlistTitle}\"?",
"synchronize-playlists-desc": "Вы уверены, что хотите синхронизировать {nb} плейлистов?",
"synchronize-playlist-tip": "Это действие обновляет плейлисты и загружает отсутствующие карты; это может занять несколько минут.",
"synchronize": "Синхронизировать",
"curated": "Рекомендованные",
"verified-mapper": "Проверенный маппер",
"empty-playlists": "Пустые плейлисты",
"search-playlist": "Поиск плейлиста",
"no-playlists-found": "Плейлисты не найдены",
"error-occur-while-loading-playlists": "Произошла ошибка при загрузке плейлистов",
"error-occur-while-loading-playlist": "Произошла ошибка при загрузке плейлиста",
"loading-maps": "Загрузка карт...",
"no-maps-found-for-playlist": "Для этого плейлиста не найдено карт",
"playlist-contain-no-maps": "Плейлист не содержит карт",
"no-map-installed-for-playlist": "Для этого плейлиста не установлено карт",
"playlist-is-waiting-to-download": "Плейлист ожидает загрузки",
"download-maps": "Скачать карты",
"download-missing-maps": "Скачать отсутствующие карты",
"playlist-is-downloading": "Плейлист загружается",
"some-playlist-maps-are-missing": "Некоторые карты в этом плейлисте отсутствуют",
"create-a-playlist": "Создать плейлист",
"synchronize-playlists": "Синхронизировать плейлисты",
"export-playlists": "Экспортировать плейлисты",
"delete-playlists": "Удалить плейлисты",
"choose-image": "Выбрать изображение",
"title": "Название",
"playlist-title": "Название плейлиста",
"description": "Описание",
"playlist-description": "Описание плейлиста",
"author": "Автор",
"playlist-author": "Автор плейлиста",
"save": "Сохранить",
"loading": "Загрузка...",
"installed": "Установлено",
"no-map-found": "Карта не найдена",
"edit-playlist-shortcuts": "Удерживайте Shift или Ctrl для выбора нескольких карт",
"add-to-playlist": "Добавить в плейлист",
"remove-from-playlist": "Удалить из плейлиста",
"playlist-is-empty": "Плейлист пуст",
"continue": "Продолжить",
"nb-maps": "Количество карт",
"nb-mappers": "Количество мапперов",
"duration": "Продолжительность",
"nps": "Нот в секунду",
"date-picker": {
"start-date-end-date": "Дата начала — Дата окончания",
"all": "Все",
"last-24h": "Последние 24 часа",
"last-week": "Последняя неделя",
"last-month": "Последний месяц",
"3-last-month": "Последние 3 месяца"
}
},
"dateformat": {
"dayNames": ["Вск", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Воскресение", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"],
"monthNames": ["Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авн", "Сен", "Окт", "Ноя", "Дек", "Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"],
+198 -21
View File
@@ -14,7 +14,8 @@
"refuse": "拒絕",
"apply": "應用",
"copy": "複製",
"copied": "已複製!"
"copied": "已複製!",
"confirm": "確認"
},
"nav-bar": {
"add-version": "新增版本",
@@ -73,7 +74,8 @@
"mods-not-available": "該版本 BeatSaber 暫無可用 Mod",
"buttons": {
"more-infos": "更多資訊",
"install-or-update": "安裝或更新"
"install-or-update": "安裝或更新",
"reinstall-all": "重新安裝全部"
},
"mods-grid": {
"header-bar": {
@@ -85,6 +87,12 @@
"uninstall-all": "全部移除"
}
}
},
"notifications": {
"all-mods-already-installed": {
"title": "模組已安裝",
"description": "所有選中的模組已經安裝"
}
}
},
"dropdown": {
@@ -94,8 +102,7 @@
"edit": "編輯",
"uninstall": "移除",
"create-shortcut": "創建捷徑",
"shared-folders": "Shared Folders",
"restore-oculus-folder": "Restore the folder"
"shared-folders": "Shared Folders"
}
},
"available-versions": {
@@ -132,7 +139,7 @@
},
"installation-folder": {
"title": "安裝文件夾",
"description": "為 BeatSaber 不同版本及未來其他特性修改預設文件夾",
"description": "更改將包含 BSManager 下載的所有內容的文件夾",
"choose-folder": "選擇文件夾"
},
"additional-content": {
@@ -191,6 +198,38 @@
"report-bug": "報告 bug",
"open-logs": "打開日誌"
}
},
"changelogs": {
"open" : "🚀 探索更新日誌!",
"not-founds": "😕 噢,找不到更新日誌!"
},
"advanced": {
"title": "高级设置",
"description": "BSManager的高级设置。",
"hardware-acceleration": {
"title": "硬體加速",
"description": "啟用硬體加速以使用您的GPU並提高BSManager的性能。如果您遇到幀丟失,請關閉此功能。",
"modal": {
"title": "需要重啟",
"body": "更改硬體加速設置將退出並重新啟動BSManager。您確定要這樣做嗎?",
"confirm-btn": "是的,我確定"
},
"error-notification": {
"message": "發生錯誤,無法禁用硬體加速。"
}
},
"use-symlinks": {
"title": "使用符號鏈接",
"description": "使用符號鏈接而不是連接來鏈接文件夾。僅在確實需要時才啟用此功能。",
"modal": {
"title": "符號鏈接權限",
"body": "創建符號鏈接時,BSManager將需要管理員權限或啟用開發者模式。您確定要繼續嗎?",
"confirm-btn": "是的,我確定"
},
"error-notification": {
"message": "發生錯誤,無法更改符號鏈接設置。"
}
}
}
}
},
@@ -235,9 +274,6 @@
}
},
"errors": {
"titles": {
"dotnet-required": "需要 .NET 6"
},
"msg": {
"401": "Steam 似乎不想讓我們下載 Beat Saber😢",
"404": "無法聯繫 Steam 伺服器。",
@@ -260,11 +296,7 @@
"LicenceError": "無法獲取許可證列表。",
"RateLimitExceeded": "你已經嘗試了太多次,請稍等片刻,稍後再試。",
"TokenRejected": "你的登錄令牌已被拒絕 😕 請重試。",
"AccessDenied": "訪問 Steam 被拒絕。",
"dotnet-required": "必須安裝 .NET 6 Runtime 才能下載 Beat Saber 版本。單擊下面的按鈕下載它。"
},
"actions": {
"download-dotnet": "下載 .NET 6"
"AccessDenied": "訪問 Steam 被拒絕。"
}
}
},
@@ -482,6 +514,15 @@
"title": "備份已創建",
"msg": "共享 “UserData” 文件夾可能會產生錯誤,如果出現問題,請取消關聯該文件夾以恢復備份"
}
},
"linking-error": {
"title": "連結文件夾時出錯",
"msg": {
"EPERM": "BSManager沒有必要的權限來連結文件夾。",
"EACCES": "BSManager沒有必要的權限來連結文件夾。",
"ENOSPC": "磁碟已滿,請騰出空間後再試。",
"UNKNOWN_ERROR": "連結文件夾時發生未知錯誤。"
}
}
},
"create-launch-shortcut": {
@@ -695,9 +736,7 @@
"title": "警告",
"body": {
"must-be-installed-once": "你必須至少從 Oculus 商店安裝過一次 BeatSaber,否則 BeatSaber 可能會在啟動後自動關閉。",
"need-backup": "要啟動該版本,位於你的 Oculus 庫中的 BeatSaber 安裝文件夾將被重命名。",
"can-restore-later": "如果需要,你可以通過前往 BSManager 的原始 Oculus 版本選項並點擊'恢復文件夾'來恢復它。",
"tips-launch-oculus": "提示:只要原始版本沒有被恢復,你就可以直接從 Oculus 啟動該版本。"
"will-backup": "為了啟動這個版本,位於您的Oculus庫中的Beat Saber的原始安裝文件夾將被重命名,並且在Beat Saber關閉時會自動恢復。"
},
"not-remind-me": "不再提醒我",
"understood": "明白了"
@@ -719,21 +758,40 @@
"enter-oculus-token": "輸入Oculus令牌"
},
"valid-btn": "驗證"
},
"launch-as-admin": {
"title": "管理員權限",
"body": {
"info": "檢測到Steam正在以管理員權限運行。為了與Steam通信,Beat Saber也必須以管理員身份啟動。否則,Beat Saber可能會遇到問題並在啟動後關閉。",
"info-2": "以管理員模式啟動Beat Saber還會將管理員權限賦予已安裝的模組。因此,建議重啟Steam,不使用管理員權限。",
"info-3": "請注意,不建議給Steam管理員權限,因為這也會影響已安裝的遊戲和模組,帶來安全風險。"
},
"launch-as-admin": "以管理員身份啟動",
"not-remind-me": "不再提醒我"
},
"ask-install-path": {
"title": "安裝文件夾",
"choose-folder-description": "選擇將包含 BSManager 下載的所有內容的文件夾。(版本、mod、地圖、播放列表等)",
"choose-folder": "選擇文件夾",
"default": "預設",
"default-tooltip": "預設為您的主資料夾"
}
},
"maps": {
"map-filter-panel": {
"duration": "時長",
"nps" : "每秒音符數",
"njs": "音符跳躍速度",
"tags": "標籤",
"specificities": "general",
"requirements": "要求"
"requirements": "要求",
"exclude": "排除"
},
"map-types": {
"accuracy": "精確度",
"balanced": "平衡",
"challenge": "挑戰",
"dancestyle": "舞蹈",
"dance-style": "舞蹈",
"fitness": "健身",
"speed": "速度",
"tech": "技術"
@@ -753,13 +811,13 @@
"rb": "R&B",
"holiday": "Holiday",
"vocaloid": "Vocaloid",
"jrock": "J-rock",
"j-rock": "J-rock",
"trance": "Trance",
"drumbass": "Drum & Bass",
"comedy": "Comedy",
"instrumental": "Instrumental",
"hardcore": "Hardcore",
"kpop": "K-pop",
"k-pop": "K-pop",
"indie": "Indie",
"techno": "Techno",
"house": "House",
@@ -770,7 +828,7 @@
"metal": "Metal",
"anime": "Anime",
"hiphop": "Hiphop",
"jpop": "J-pop",
"j-pop": "J-pop",
"rock": "Rock",
"pop": "Pop",
"electronic": "Electronic",
@@ -783,6 +841,9 @@
"verified": "Verified",
"fullSpread": "Full spread"
},
"map-excludes": {
"installed": "已安裝"
},
"difficulties": {
"Easy": "Easy",
"Normal": "Normal",
@@ -990,6 +1051,122 @@
}
}
},
"playlist": {
"error-playlist-creation-title": "建立播放清單時發生錯誤",
"error-playlist-creation-desc": "建立播放清單時發生錯誤。",
"playlist-created-title": "播放清單已建立",
"playlist-created-desc": "播放清單已成功建立。您現在可以同步其地圖了!",
"download-playlist": "下載播放清單",
"synchronize-playlist": "同步播放清單",
"synchronize-maps": "同步地圖",
"error-playlists-synchronization-title": "同步播放清單時發生錯誤",
"error-playlists-synchronization-desc": "同步播放清單時發生錯誤。",
"playlists-synchronized-title": "播放清單已同步!",
"playlists-synchronized-desc": "播放清單及其地圖已下載。",
"playlists-export-error-title": "匯出播放清單時發生錯誤",
"playlists-export-error-desc": "匯出播放清單時發生錯誤。",
"playlists-exported-title": "播放清單已匯出!",
"playlists-exported-desc": "播放清單已成功匯出。",
"playlists-with-maps-exported-desc": "播放清單及其地圖已成功匯出。",
"playlist-delete-error-title": "刪除播放清單時發生錯誤",
"playlist-delete-error-desc": "刪除播放清單時發生錯誤。",
"playlists-deleted-title": "播放清單已刪除!",
"playlists-deleted-desc": "播放清單已成功刪除。",
"edit-playlist": "編輯播放清單",
"playlist-edit-error-title": "編輯播放清單時發生錯誤",
"playlist-edit-error-desc": "編輯播放清單時發生錯誤。",
"playlist-edited-title": "播放清單已編輯!",
"playlist-edited-desc": "播放清單已成功修改。您現在可以同步其地圖了!",
"playlists-loading": "正在載入播放清單...",
"no-playlists": "沒有播放清單",
"download-playlists": "下載播放清單",
"created-by": "建立者",
"stop-download": "停止下載",
"cancel-download": "取消下載",
"open-file": "開啟檔案",
"link-playlists": "連結播放清單",
"link-playlist-desc": "連結播放清單允許在所有版本之間共享播放清單。一旦連結,此版本將受益於共享播放清單",
"link-playlist-info": "新增和刪除播放清單也將被共享",
"keep-playlists": "保留播放清單",
"keep-playlists-tip": "保留播放清單將把當前版本的播放清單移動到共享播放清單資料夾。否則,它們將遺失",
"unlink-playlists": "取消連結播放清單",
"unlink-playlist-desc": "警告,取消連結播放清單將不再允許此版本使用共享播放清單。",
"unlink-keep-playlists-tip": "保留播放清單將為當前版本建立共享播放清單的副本。否則,此版本將不保留任何播放清單。",
"delete-playlist-ask": "刪除播放清單?",
"delete-playlists-ask": "刪除播放清單?",
"delete-playlist-desc": "您確定要刪除播放清單 \"{playlistTitle}\" 嗎?",
"delete-playlists-desc": "您確定要刪除 {nb} 個播放清單嗎?",
"delete-maps": "刪除地圖",
"delete-playlist-maps-tip": "如果啟用,播放清單中的所有地圖都將被刪除",
"delete-playlists-maps-tip": "如果啟用,播放清單中的所有地圖都將被刪除",
"export-playlist-ask": "匯出播放清單?",
"export-playlists-ask": "匯出播放清單?",
"export-playlist-desc": "您確定要匯出播放清單 \"{playlistTitle}\" 嗎?",
"export-playlists-desc": "您確定要匯出 {nb} 個播放清單嗎?",
"export-maps": "匯出地圖",
"export-playlist-maps-tip": "如果啟用,播放清單中的所有地圖也將被匯出",
"export-playlists-maps-tip": "如果啟用,播放清單中的所有地圖也將被匯出",
"export": "匯出",
"need-clone-title": "警告",
"need-clone-desc-1": "此播放清單已從外部網站下載,並包含同步連結。",
"need-clone-desc-2": "為避免在同步過程中遺失更改,播放清單將被複製,並刪除其同步連結。",
"need-clone-desc-3": "然後,如果您願意,可以刪除原始播放清單。",
"understood": "我明白了",
"synchronize-playlist-ask": "同步播放清單?",
"synchronize-playlists-ask": "同步播放清單?",
"synchronize-playlist-desc": "您確定要同步播放清單 \"{playlistTitle}\" 嗎?",
"synchronize-playlists-desc": "您確定要同步 {nb} 個播放清單嗎?",
"synchronize-playlist-tip": "此操作更新播放清單並下載缺失的地圖;可能需要幾分鐘。",
"synchronize": "同步",
"curated": "精選",
"verified-mapper": "已驗證的製圖者",
"empty-playlists": "空播放清單",
"search-playlist": "搜尋播放清單",
"no-playlists-found": "未找到播放清單",
"error-occur-while-loading-playlists": "載入播放清單時發生錯誤",
"error-occur-while-loading-playlist": "載入播放清單時發生錯誤",
"loading-maps": "正在載入地圖...",
"no-maps-found-for-playlist": "未找到此播放清單的地圖",
"playlist-contain-no-maps": "播放清單不包含地圖",
"no-map-installed-for-playlist": "此播放清單沒有已安裝的地圖",
"playlist-is-waiting-to-download": "播放清單正在等待下載",
"download-maps": "下載地圖",
"download-missing-maps": "下載缺失的地圖",
"playlist-is-downloading": "播放清單正在下載",
"some-playlist-maps-are-missing": "此播放清單中的一些地圖缺失",
"create-a-playlist": "建立播放清單",
"synchronize-playlists": "同步播放清單",
"export-playlists": "匯出播放清單",
"delete-playlists": "刪除播放清單",
"choose-image": "選擇圖片",
"title": "標題",
"playlist-title": "播放清單標題",
"description": "描述",
"playlist-description": "播放清單描述",
"author": "作者",
"playlist-author": "播放清單作者",
"save": "儲存",
"loading": "載入中...",
"installed": "已安裝",
"no-map-found": "未找到地圖",
"edit-playlist-shortcuts": "按住 Shift 或 Ctrl 選擇多個地圖",
"add-to-playlist": "新增到播放清單",
"remove-from-playlist": "從播放清單中移除",
"playlist-is-empty": "播放清單為空",
"continue": "繼續",
"nb-maps": "地圖數量",
"nb-mappers": "製圖者數量",
"duration": "持續時間",
"nps": "每秒音符數",
"date-picker": {
"start-date-end-date": "開始日期 — 結束日期",
"all": "全部",
"last-24h": "最近24小時",
"last-week": "上週",
"last-month": "上個月",
"3-last-month": "最近3個月"
}
},
"dateformat": {
"dayNames": ["週日", "週一", "週二", "週三", "週四", "週五", "週六", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
"monthNames": ["1 月", "2 月", "3 月", "4 月", "5 月", "6 月", "7 月", "8 月", "9 月", "10 月", "11 月", "12 月", "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
+198 -21
View File
@@ -14,7 +14,8 @@
"refuse": "拒绝",
"apply": "应用",
"copy": "复制",
"copied": "已复制!"
"copied": "已复制!",
"confirm": "确认"
},
"nav-bar": {
"add-version": "添加版本",
@@ -73,7 +74,8 @@
"mods-not-available": "该版本 BeatSaber 暂无可用 Mod",
"buttons": {
"more-infos": "更多信息",
"install-or-update": "安装或更新"
"install-or-update": "安装或更新",
"reinstall-all": "重新安装全部"
},
"mods-grid": {
"header-bar": {
@@ -85,6 +87,12 @@
"uninstall-all": "全部卸载"
}
}
},
"notifications": {
"all-mods-already-installed": {
"title": "模组已安装",
"description": "所有选中的模组已经安装"
}
}
},
"dropdown": {
@@ -94,8 +102,7 @@
"edit": "编辑",
"uninstall": "卸载",
"create-shortcut": "创建快捷方式",
"shared-folders": "Shared Folders",
"restore-oculus-folder": "Restore the folder"
"shared-folders": "Shared Folders"
}
},
"available-versions": {
@@ -132,7 +139,7 @@
},
"installation-folder": {
"title": "安装文件夹",
"description": "为 BeatSaber 不同版本及未来其他特性修改默认文件夹",
"description": "更改将包含 BSManager 下载的所有内容的文件夹",
"choose-folder": "选择文件夹"
},
"additional-content": {
@@ -191,6 +198,38 @@
"report-bug": "报告 bug",
"open-logs": "打开日志"
}
},
"changelogs": {
"open" : "🚀 探索更新日志!",
"not-founds": "😕 哎呀,找不到更新日志!"
},
"advanced": {
"title": "高级设置",
"description": "BSManager的高级设置。",
"hardware-acceleration": {
"title": "硬件加速",
"description": "启用硬件加速以使用您的GPU并提高BSManager的性能。如果您遇到帧丢失,请关闭此功能。",
"modal": {
"title": "需要重启",
"body": "更改硬件加速设置将退出并重新启动BSManager。您确定要这样做吗?",
"confirm-btn": "是的,我确定"
},
"error-notification": {
"message": "发生错误,无法禁用硬件加速。"
}
},
"use-symlinks": {
"title": "使用符号链接",
"description": "使用符号链接而不是联接来链接文件夹。仅在确实需要时才启用此功能。",
"modal": {
"title": "符号链接权限",
"body": "创建符号链接时,BSManager将需要管理员权限或启用开发者模式。您确定要继续吗?",
"confirm-btn": "是的,我确定"
},
"error-notification": {
"message": "发生错误,无法更改符号链接设置。"
}
}
}
}
},
@@ -235,9 +274,6 @@
}
},
"errors": {
"titles": {
"dotnet-required": "需要 .NET 6"
},
"msg": {
"401": "Steam 似乎不想让我们下载 Beat Saber😢",
"404": "无法联系 Steam 服务器。",
@@ -260,11 +296,7 @@
"LicenceError": "无法获取许可证列表。",
"RateLimitExceeded": "你已经尝试了太多次,请稍等片刻,稍后再试。",
"TokenRejected": "你的登录令牌已被拒绝 😕 请重试。",
"AccessDenied": "访问 Steam 被拒绝。",
"dotnet-required": "必须安装 .NET 6 Runtime 才能下载 Beat Saber 版本。单击下面的按钮下载它。"
},
"actions": {
"download-dotnet": "下载 .NET 6"
"AccessDenied": "访问 Steam 被拒绝。"
}
}
},
@@ -482,6 +514,15 @@
"title": "备份已创建",
"msg": "共享 “UserData” 文件夹可能会产生错误,如果出现问题,请取消关联该文件夹以恢复备份"
}
},
"linking-error": {
"title": "链接文件夹时出错",
"msg": {
"EPERM": "BSManager没有必要的权限来链接文件夹。",
"EACCES": "BSManager没有必要的权限来链接文件夹。",
"ENOSPC": "磁盘已满,请腾出空间后再试。",
"UNKNOWN_ERROR": "链接文件夹时发生未知错误。"
}
}
},
"create-launch-shortcut": {
@@ -695,9 +736,7 @@
"title": "警告",
"body": {
"must-be-installed-once": "你必须至少从 Oculus 商店安装过一次 BeatSaber,否则 BeatSaber 可能会在启动后自动关闭。",
"need-backup": "要启动该版本,位于你的 Oculus 库中的 BeatSaber 安装文件夹将被重命名。",
"can-restore-later": "如果需要,你可以通过前往 BSManager 的原始 Oculus 版本选项并点击'恢复文件夹'来恢复它。",
"tips-launch-oculus": "提示:只要原始版本没有被恢复,你就可以直接从 Oculus 启动该版本。"
"will-backup": "为了启动这个版本,位于您的Oculus库中的Beat Saber的原始安装文件夹将被重命名,并且在Beat Saber关闭时会自动恢复。"
},
"not-remind-me": "不再提醒我",
"understood": "明白了"
@@ -719,21 +758,40 @@
"enter-oculus-token": "输入Oculus令牌"
},
"valid-btn": "验证"
},
"launch-as-admin": {
"title": "管理员权限",
"body": {
"info": "检测到Steam正在以管理员权限运行。为了与Steam通信,Beat Saber也必须以管理员身份启动。否则,Beat Saber可能会遇到问题并在启动后关闭。",
"info-2": "以管理员模式启动Beat Saber还会将管理员权限赋予已安装的模组。因此,建议重启Steam,不使用管理员权限。",
"info-3": "请注意,不建议给Steam管理员权限,因为这也会影响已安装的游戏和模组,带来安全风险。"
},
"launch-as-admin": "以管理员身份启动",
"not-remind-me": "不再提醒我"
},
"ask-install-path": {
"title": "安装文件夹",
"choose-folder-description": "选择将包含 BSManager 下载的所有内容的文件夹。(版本、mod、地图、播放列表等)",
"choose-folder": "选择文件夹",
"default": "默认",
"default-tooltip": "默认为您的主文件夹"
}
},
"maps": {
"map-filter-panel": {
"duration": "时长",
"nps" : "每秒音符数",
"njs": "音符跳跃速度",
"tags": "标签",
"specificities": "general",
"requirements": "要求"
"requirements": "要求",
"exclude": "排除"
},
"map-types": {
"accuracy": "精确度",
"balanced": "平衡",
"challenge": "挑战",
"dancestyle": "舞蹈",
"dance-style": "舞蹈",
"fitness": "健身",
"speed": "速度",
"tech": "技术"
@@ -753,13 +811,13 @@
"rb": "r&b",
"holiday": "holiday",
"vocaloid": "vocaloid",
"jrock": "j-rock",
"j-rock": "j-rock",
"trance": "trance",
"drumbass": "drum & bass",
"comedy": "comedy",
"instrumental": "instrumental",
"hardcore": "hardcore",
"kpop": "k-pop",
"k-pop": "k-pop",
"indie": "indie",
"techno": "techno",
"house": "house",
@@ -770,7 +828,7 @@
"metal": "metal",
"anime": "anime",
"hiphop": "hiphop",
"jpop": "j-pop",
"j-pop": "j-pop",
"rock": "rock",
"pop": "pop",
"electronic": "electronic",
@@ -783,6 +841,9 @@
"verified": "verified",
"fullSpread": "full spread"
},
"map-excludes": {
"installed": "已安装"
},
"difficulties": {
"Easy": "easy",
"Normal": "normal",
@@ -990,6 +1051,122 @@
}
}
},
"playlist": {
"error-playlist-creation-title": "创建播放列表时出错",
"error-playlist-creation-desc": "创建播放列表时发生错误。",
"playlist-created-title": "播放列表已创建",
"playlist-created-desc": "播放列表已成功创建。您现在可以同步其地图了!",
"download-playlist": "下载播放列表",
"synchronize-playlist": "同步播放列表",
"synchronize-maps": "同步地图",
"error-playlists-synchronization-title": "同步播放列表时出错",
"error-playlists-synchronization-desc": "同步播放列表时发生错误。",
"playlists-synchronized-title": "播放列表已同步!",
"playlists-synchronized-desc": "播放列表及其地图已下载。",
"playlists-export-error-title": "导出播放列表时出错",
"playlists-export-error-desc": "导出播放列表时发生错误。",
"playlists-exported-title": "播放列表已导出!",
"playlists-exported-desc": "播放列表已成功导出。",
"playlists-with-maps-exported-desc": "播放列表及其地图已成功导出。",
"playlist-delete-error-title": "删除播放列表时出错",
"playlist-delete-error-desc": "删除播放列表时发生错误。",
"playlists-deleted-title": "播放列表已删除!",
"playlists-deleted-desc": "播放列表已成功删除。",
"edit-playlist": "编辑播放列表",
"playlist-edit-error-title": "编辑播放列表时出错",
"playlist-edit-error-desc": "编辑播放列表时发生错误。",
"playlist-edited-title": "播放列表已编辑!",
"playlist-edited-desc": "播放列表已成功修改。您现在可以同步其地图了!",
"playlists-loading": "正在加载播放列表...",
"no-playlists": "没有播放列表",
"download-playlists": "下载播放列表",
"created-by": "创建者",
"stop-download": "停止下载",
"cancel-download": "取消下载",
"open-file": "打开文件",
"link-playlists": "链接播放列表",
"link-playlist-desc": "链接播放列表允许在所有版本之间共享播放列表。一旦链接,此版本将受益于共享播放列表",
"link-playlist-info": "添加和删除播放列表也将被共享",
"keep-playlists": "保留播放列表",
"keep-playlists-tip": "保留播放列表将把当前版本的播放列表移动到共享播放列表文件夹。否则,它们将丢失",
"unlink-playlists": "取消链接播放列表",
"unlink-playlist-desc": "警告,取消链接播放列表将不再允许此版本使用共享播放列表。",
"unlink-keep-playlists-tip": "保留播放列表将为当前版本创建共享播放列表的副本。否则,此版本将不保留任何播放列表。",
"delete-playlist-ask": "删除播放列表?",
"delete-playlists-ask": "删除播放列表?",
"delete-playlist-desc": "您确定要删除播放列表 \"{playlistTitle}\" 吗?",
"delete-playlists-desc": "您确定要删除 {nb} 个播放列表吗?",
"delete-maps": "删除地图",
"delete-playlist-maps-tip": "如果启用,播放列表中的所有地图都将被删除",
"delete-playlists-maps-tip": "如果启用,播放列表中的所有地图都将被删除",
"export-playlist-ask": "导出播放列表?",
"export-playlists-ask": "导出播放列表?",
"export-playlist-desc": "您确定要导出播放列表 \"{playlistTitle}\" 吗?",
"export-playlists-desc": "您确定要导出 {nb} 个播放列表吗?",
"export-maps": "导出地图",
"export-playlist-maps-tip": "如果启用,播放列表中的所有地图也将被导出",
"export-playlists-maps-tip": "如果启用,播放列表中的所有地图也将被导出",
"export": "导出",
"need-clone-title": "警告",
"need-clone-desc-1": "此播放列表已从外部站点下载,并包含同步链接。",
"need-clone-desc-2": "为避免在同步过程中丢失更改,播放列表将被复制,并删除其同步链接。",
"need-clone-desc-3": "然后,如果您愿意,可以删除原始播放列表。",
"understood": "我明白了",
"synchronize-playlist-ask": "同步播放列表?",
"synchronize-playlists-ask": "同步播放列表?",
"synchronize-playlist-desc": "您确定要同步播放列表 \"{playlistTitle}\" 吗?",
"synchronize-playlists-desc": "您确定要同步 {nb} 个播放列表吗?",
"synchronize-playlist-tip": "此操作更新播放列表并下载缺失的地图;可能需要几分钟。",
"synchronize": "同步",
"curated": "推荐",
"verified-mapper": "已验证的制图者",
"empty-playlists": "空播放列表",
"search-playlist": "搜索播放列表",
"no-playlists-found": "未找到播放列表",
"error-occur-while-loading-playlists": "加载播放列表时发生错误",
"error-occur-while-loading-playlist": "加载播放列表时发生错误",
"loading-maps": "正在加载地图...",
"no-maps-found-for-playlist": "未找到此播放列表的地图",
"playlist-contain-no-maps": "播放列表不包含地图",
"no-map-installed-for-playlist": "此播放列表没有已安装的地图",
"playlist-is-waiting-to-download": "播放列表正在等待下载",
"download-maps": "下载地图",
"download-missing-maps": "下载缺失的地图",
"playlist-is-downloading": "播放列表正在下载",
"some-playlist-maps-are-missing": "此播放列表中的一些地图缺失",
"create-a-playlist": "创建播放列表",
"synchronize-playlists": "同步播放列表",
"export-playlists": "导出播放列表",
"delete-playlists": "删除播放列表",
"choose-image": "选择图片",
"title": "标题",
"playlist-title": "播放列表标题",
"description": "描述",
"playlist-description": "播放列表描述",
"author": "作者",
"playlist-author": "播放列表作者",
"save": "保存",
"loading": "加载中...",
"installed": "已安装",
"no-map-found": "未找到地图",
"edit-playlist-shortcuts": "按住 Shift 或 Ctrl 选择多个地图",
"add-to-playlist": "添加到播放列表",
"remove-from-playlist": "从播放列表中移除",
"playlist-is-empty": "播放列表为空",
"continue": "继续",
"nb-maps": "地图数量",
"nb-mappers": "制图者数量",
"duration": "持续时间",
"nps": "每秒音符数",
"date-picker": {
"start-date-end-date": "开始日期 — 结束日期",
"all": "全部",
"last-24h": "最近24小时",
"last-week": "上周",
"last-month": "上个月",
"3-last-month": "最近3个月"
}
},
"dateformat": {
"dayNames": ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
"monthNames": ["1 月", "2 月", "3 月", "4 月", "5 月", "6 月", "7 月", "8 月", "9 月", "10 月", "11 月", "12 月", "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
+127
View File
@@ -0,0 +1,127 @@
syntax = "proto3";
package song_details_cache_v1;
message SongDetailsCache {
repeated SongDetails songs = 1;
uint32 lastUpdated = 2;
uint32 total = 3;
UploadersList uploaders = 4;
repeated string difficultyLabels = 5;
}
message UploadersList {
repeated string names = 1;
repeated uint32 ids = 2;
}
message SongDetails {
uint32 idInt = 1;
repeated uint32 hashIndices = 2;
string name = 3;
uint32 duration = 4;
UploaderRef uploaderRef = 5;
uint32 uploadedAt = 6;
repeated MapTag tags = 7;
bool ranked = 8;
bool qualified = 9;
bool curated = 10;
bool blRanked = 11;
bool blQualified = 12;
uint32 upVotes = 13;
uint32 downVotes = 14;
uint32 downloads = 15;
bool automapper = 16;
repeated Difficulty difficulties = 17;
}
message Difficulty {
DifficultyLabel difficulty = 1;
DifficultyCharacteristic characteristic = 2;
uint32 labelIndex = 3;
uint32 starsT100 = 4;
uint32 starsBlT100 = 5;
uint32 njsT100 = 6;
uint32 npsT100 = 7;
int32 offsetT100 = 8;
bool chroma = 9;
bool cinema = 10;
bool me = 11;
bool ne = 12;
uint32 bombs = 13;
uint32 notes = 14;
uint32 obstacles = 15;
}
message UploaderRef {
uint32 uploader_ref_index = 1;
bool verified = 2;
}
enum DifficultyLabel {
UNKNOWN_LABEL = 0; // Default value for undefined/unknown labels
EASY = 1;
NORMAL = 2;
HARD = 3;
EXPERT = 4;
EXPERT_PLUS = 5;
}
enum DifficultyCharacteristic {
UNKNOWN_CHARACTERISTIC = 0; // Default value for undefined/unknown characteristics
STANDARD = 1;
ONE_SABER = 2;
NO_ARROWS = 3;
LAWLESS = 4;
LIGHTSHOW = 5;
LEGACY = 6;
NINETY_DEGREE = 7;
THREESIXTY_DEGREE = 8;
}
enum MapTag {
UNKNOWN_TAG = 0; // Default value for undefined/unknown tags
DANCE = 1;
SWING = 2;
NIGHTCORE = 3;
FOLK = 4;
FAMILY = 5;
AMBIENT = 6;
FUNK = 7;
JAZZ = 8;
SOUL = 9;
SPEEDCORE = 10;
PUNK = 11;
RB = 12;
HOLIDAY = 13;
VOCALOID = 14;
J_ROCK = 15;
TRANCE = 16;
DRUMBASS = 17;
COMEDY = 18;
INSTRUMENTAL = 19;
HARDCORE = 20;
K_POP = 21;
INDIE = 22;
TECHNO = 23;
HOUSE = 24;
GAME = 25;
FILM = 26;
ALT = 27;
DUBSTEP = 28;
METAL = 29;
ANIME = 30;
HIPHOP = 31;
J_POP = 32;
ROCK = 33;
POP = 34;
ELECTRONIC = 35;
CLASSICAL_ORCHESTRAL = 36;
ACCURACY = 37;
BALANCED = 38;
CHALLENGE = 39;
DANCESTYLE = 40;
FITNESS = 41;
SPEED = 42;
TECH = 43;
}
BIN
View File
Binary file not shown.
Binary file not shown.
@@ -1,166 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v6.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v6.0": {
"DepotDownloader/2.5.0": {
"dependencies": {
"QRCoder": "1.4.3",
"SteamKit2": "2.5.0-Beta.1",
"protobuf-net": "3.2.16"
},
"runtime": {
"DepotDownloader.dll": {}
}
},
"Microsoft.NETCore.Platforms/5.0.0": {},
"Microsoft.Win32.Registry/5.0.0": {
"dependencies": {
"System.Security.AccessControl": "5.0.0",
"System.Security.Principal.Windows": "5.0.0"
}
},
"protobuf-net/3.2.16": {
"dependencies": {
"protobuf-net.Core": "3.2.16"
},
"runtime": {
"lib/net6.0/protobuf-net.dll": {
"assemblyVersion": "3.0.0.0",
"fileVersion": "3.2.16.54102"
}
}
},
"protobuf-net.Core/3.2.16": {
"dependencies": {
"System.Collections.Immutable": "7.0.0"
},
"runtime": {
"lib/net6.0/protobuf-net.Core.dll": {
"assemblyVersion": "3.0.0.0",
"fileVersion": "3.2.16.54102"
}
}
},
"QRCoder/1.4.3": {
"runtime": {
"lib/net6.0/QRCoder.dll": {
"assemblyVersion": "1.4.3.0",
"fileVersion": "1.4.3.0"
}
}
},
"SteamKit2/2.5.0-Beta.1": {
"dependencies": {
"Microsoft.Win32.Registry": "5.0.0",
"protobuf-net": "3.2.16"
},
"runtime": {
"lib/net6.0/SteamKit2.dll": {
"assemblyVersion": "2.5.0.0",
"fileVersion": "2.5.0.0"
}
}
},
"System.Collections.Immutable/7.0.0": {
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
},
"runtime": {
"lib/net6.0/System.Collections.Immutable.dll": {
"assemblyVersion": "7.0.0.0",
"fileVersion": "7.0.22.51805"
}
}
},
"System.Runtime.CompilerServices.Unsafe/6.0.0": {},
"System.Security.AccessControl/5.0.0": {
"dependencies": {
"Microsoft.NETCore.Platforms": "5.0.0",
"System.Security.Principal.Windows": "5.0.0"
}
},
"System.Security.Principal.Windows/5.0.0": {}
}
},
"libraries": {
"DepotDownloader/2.5.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Microsoft.NETCore.Platforms/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==",
"path": "microsoft.netcore.platforms/5.0.0",
"hashPath": "microsoft.netcore.platforms.5.0.0.nupkg.sha512"
},
"Microsoft.Win32.Registry/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
"path": "microsoft.win32.registry/5.0.0",
"hashPath": "microsoft.win32.registry.5.0.0.nupkg.sha512"
},
"protobuf-net/3.2.16": {
"type": "package",
"serviceable": true,
"sha512": "sha512-W6RM2B2f5O7SigBGfkXFYzI/a7Mks+rCHtuGlE/b5O3NMupDon7I0akjCLhrfcnqIfdWDkDafseav/MnIzUSHA==",
"path": "protobuf-net/3.2.16",
"hashPath": "protobuf-net.3.2.16.nupkg.sha512"
},
"protobuf-net.Core/3.2.16": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ZFoY0lfMUWGJ4RoyI0oNj2o2l8t08n3k27YyDD0kYWQ+vXj0hTbWEwYWOpGAfCWvyUPkq9Jcc/4uR74GICZL2g==",
"path": "protobuf-net.core/3.2.16",
"hashPath": "protobuf-net.core.3.2.16.nupkg.sha512"
},
"QRCoder/1.4.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-fWuFqjm8GTlEb2GqBl3Hi8HZZeZQwBSHxvRPtPjyNbT82H0ff0JwavKRBmMaXCno1Av6McPC8aJzri0Mj2w9Jw==",
"path": "qrcoder/1.4.3",
"hashPath": "qrcoder.1.4.3.nupkg.sha512"
},
"SteamKit2/2.5.0-Beta.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-fwwdF0cZZEIdNpcUc1+B9zbP5Q48A3DFOAclPhBh2dMTU03aROaIDktFW+Ww/NN1Z/Emp/LwVqHB+hCM8uxS4Q==",
"path": "steamkit2/2.5.0-beta.1",
"hashPath": "steamkit2.2.5.0-beta.1.nupkg.sha512"
},
"System.Collections.Immutable/7.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==",
"path": "system.collections.immutable/7.0.0",
"hashPath": "system.collections.immutable.7.0.0.nupkg.sha512"
},
"System.Runtime.CompilerServices.Unsafe/6.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
"path": "system.runtime.compilerservices.unsafe/6.0.0",
"hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512"
},
"System.Security.AccessControl/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
"path": "system.security.accesscontrol/5.0.0",
"hashPath": "system.security.accesscontrol.5.0.0.nupkg.sha512"
},
"System.Security.Principal.Windows/5.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==",
"path": "system.security.principal.windows/5.0.0",
"hashPath": "system.security.principal.windows.5.0.0.nupkg.sha512"
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,13 +0,0 @@
{
"runtimeOptions": {
"tfm": "net6.0",
"rollForward": "LatestMajor",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "6.0.0"
},
"configProperties": {
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Before

Width:  |  Height:  |  Size: 442 KiB

After

Width:  |  Height:  |  Size: 442 KiB

-243
View File
@@ -1,243 +0,0 @@
/**
* Code taken from https://github.com/kubeshop/monokle/blob/main/tests/electronHelpers.ts
* don't tunch unless you know what you're doing
*/
import { Page } from "@playwright/test";
import path from "path";
import {ElectronApplication, _electron as electron} from 'playwright-core';
import { pause } from "shared/helpers/promise.helpers";
import log from "electron-log";
import * as fs from 'fs';
import * as ASAR from 'asar';
export const TEST_OUTPUT_DIR = 'test-results';
export async function startApp(): Promise<StartAppResponse> {
const latestBuild = findLatestBuild();
const appInfo = parseElectronApp(latestBuild);
const electronApp = await electron.launch({
args: [appInfo.main],
env: {
...process.env,
E2E_BUILD: "true",
},
executablePath: appInfo.executable,
recordVideo: {
dir: getRecordingPath(appInfo.platform),
size: {
width: 1200,
height: 800,
},
},
});
const appWindow = await electronApp.firstWindow();
if (!appWindow) {
throw new Error('Unable to get main window');
}
await pause(3000);
appWindow.on('console', log.info);
appWindow.screenshot({path: path.join(TEST_OUTPUT_DIR, "initial-screen.png")});
return {appWindow, appInfo, electronApp};
}
export function findLatestBuild(): string {
const rootDir = path.resolve('./');
const outDir = path.join(rootDir, 'release', 'build');
const builds = fs.readdirSync(outDir);
const platforms = ['win32', 'win', 'windows', 'darwin', 'mac', 'macos', 'osx', 'linux', 'ubuntu'];
const latestBuild = builds
.map(fileName => {
// make sure it's a directory with "-" delimited platform in its name
const stats = fs.statSync(path.join(outDir, fileName));
const isBuild = fileName.toLocaleLowerCase().split('-').some(part => platforms.includes(part));
if(!stats.isDirectory() || !isBuild){ return undefined; }
return {
name: fileName,
time: fs.statSync(path.join(outDir, fileName)).mtimeMs,
};
})
.sort((a, b) => b.time - a.time)
.map(file => file?.name)[0];
if (!latestBuild) {
throw new Error('No build found in out directory');
}
return path.join(outDir, latestBuild);
}
/**
* Given a directory containing an Electron app build,
* return the path to the app's executable and the path to the app's main file.
*/
export function parseElectronApp(buildDir: string): ElectronAppInfo {
log.info(`Parsing Electron app in ${buildDir}`);
let platform: string | undefined;
if (buildDir.endsWith('.app')) {
buildDir = path.dirname(buildDir);
platform = 'darwin';
}
else if (buildDir.endsWith('.exe')) {
buildDir = path.dirname(buildDir);
platform = 'win32';
}
const baseName = path.basename(buildDir).toLowerCase();
if (!platform) {
// parse the directory name to figure out the platform
if (baseName.includes('win')) {
platform = 'win32';
}
if (baseName.includes('linux') || baseName.includes('ubuntu') || baseName.includes('debian')) {
platform = 'linux';
}
if (baseName.includes('darwin') || baseName.includes('mac') || baseName.includes('osx')) {
platform = 'darwin';
}
}
if (!platform) {
throw new Error(`Platform not found in directory name: ${baseName}`);
}
let arch: Architecture;
if (baseName.includes('x32') || baseName.includes('i386')) {
arch = 'x32';
}
if (baseName.includes('x64')) {
arch = 'x64';
}
if (baseName.includes('arm64')) {
arch = 'arm64';
}
let executable: string;
let main: string;
let name: string;
let asar: boolean;
let resourcesDir: string;
if (platform === 'darwin') {
// MacOS Structure
// <buildDir>/
// <appName>.app/
// Contents/
// MacOS/
// <appName> (executable)
// Info.plist
// PkgInfo
// Resources/
// electron.icns
// file.icns
// app.asar (asar bundle) - or -
// app
// package.json
// (your app structure)
const list = fs.readdirSync(buildDir);
const appBundle = list.find(fileName => {
return fileName.endsWith('.app');
});
const appDir = path.join(buildDir, appBundle, 'Contents', 'MacOS');
const appName = fs.readdirSync(appDir)[0];
executable = path.join(appDir, appName);
resourcesDir = path.join(buildDir, appBundle, 'Contents', 'Resources');
const resourcesList = fs.readdirSync(resourcesDir);
asar = resourcesList.includes('app.asar');
let packageJson: {main: string; name: string};
if (asar) {
const asarPath = path.join(resourcesDir, 'app.asar');
packageJson = JSON.parse(ASAR.extractFile(asarPath, 'package.json').toString('utf8'));
main = path.join(asarPath, packageJson.main);
} else {
packageJson = JSON.parse(fs.readFileSync(path.join(resourcesDir, 'app', 'package.json'), 'utf8'));
main = path.join(resourcesDir, 'app', packageJson.main);
}
name = packageJson.name;
}
else if (platform === 'win32') {
// Windows Structure
// <buildDir>/
// <appName>.exe (executable)
// resources/
// app.asar (asar bundle) - or -
// app
// package.json
// (your app structure)
const list = fs.readdirSync(buildDir);
const exe = list.find(fileName => {
return fileName.endsWith('.exe');
});
executable = path.join(buildDir, exe);
resourcesDir = path.join(buildDir, 'resources');
const resourcesList = fs.readdirSync(resourcesDir);
asar = resourcesList.includes('app.asar');
let packageJson: {main: string; name: string};
if (asar) {
const asarPath = path.join(resourcesDir, 'app.asar');
packageJson = JSON.parse(ASAR.extractFile(asarPath, 'package.json').toString('utf8'));
main = path.join(asarPath, packageJson.main);
} else {
packageJson = JSON.parse(fs.readFileSync(path.join(resourcesDir, 'app', 'package.json'), 'utf8'));
main = path.join(resourcesDir, 'app', packageJson.main);
}
name = packageJson.name;
}
else {
/** @todo add support for linux */
throw new Error(`Platform not supported: ${platform}`);
}
return { executable, main, asar, name, platform, resourcesDir, arch };
}
export function getRecordingPath(...paths: string[]): string {
return path.join(TEST_OUTPUT_DIR, ...paths);
}
export function getMainWindow(windows: Page[]): Page {
const mainWindow = windows.find(w => w.url().includes('index.html'));
return mainWindow;
}
type Architecture = 'x64' | 'x32' | 'arm64';
export interface ElectronAppInfo {
/** Path to the app's executable file */
executable: string;
/** Path to the app's main (JS) file */
main: string;
/** Name of the app */
name: string;
/** Resources directory */
resourcesDir: string;
/** True if the app is using asar */
asar: boolean;
/** OS platform */
platform: 'darwin' | 'win32' | 'linux';
arch: Architecture;
}
interface StartAppResponse {
electronApp: ElectronApplication;
appWindow: Page;
appInfo: ElectronAppInfo;
}
-55
View File
@@ -1,55 +0,0 @@
import {Page} from 'playwright';
import { test, expect } from '@playwright/test';
import { getRecordingPath, startApp } from './helpers/electron.helpers';
import { pause } from 'shared/helpers/promise.helpers';
import { MainWindow } from './models/main-window.class';
import { AddVersionPanel } from './models/add-version-panel.class';
let appWindow: Page;
let mainWindow: MainWindow;
let addVersionPanel: AddVersionPanel;
test.beforeAll(async () => {
const startAppResponse = await startApp();
appWindow = startAppResponse.appWindow;
mainWindow = new MainWindow(appWindow);
addVersionPanel = new AddVersionPanel(appWindow);
});
test.beforeEach(async () => {
await pause(1000);
await mainWindow.clickAddVersionButton();
});
test.afterEach(async () => {
await pause(1000);
});
test('should be able to select then unselect a bs version', async () => {
const versionManifest = "8948172000430595334";
await addVersionPanel.selectYear("2021");
await pause(1000);
await addVersionPanel.clickVersion(versionManifest); // select version 0.12.2
await pause(1000);
expect(await addVersionPanel.downloadVersionButton.isVisible()).toBeTruthy();
await addVersionPanel.clickVersion(versionManifest); // deselect version 0.12.2
await pause(3000);
expect(await addVersionPanel.downloadVersionButton.isVisible()).toBeFalsy();
// sadly we can't test if the download works or not :( (Steam ids, dot-net, etc)
});
test('should be able to download a map then delete it', async () => {
// TODO: implement this test
});
test.afterAll(async () => {
await pause(3000);
await appWindow.screenshot({path: getRecordingPath("final-screen.png")});
await appWindow.close();
});
@@ -1,26 +0,0 @@
import { Page, Locator } from "playwright";
import { MainWindow } from "./main-window.class";
export class AddVersionPanel extends MainWindow {
private readonly _yearsTabBar: Locator;
private readonly _downloadVersionButton: Locator;
constructor(page: Page) {
super(page);
this._yearsTabBar = page.locator("#version-years-tab-bar");
this._downloadVersionButton = page.locator("#download-version-btn");
}
selectYear(year: string): Promise<void>{
return this._yearsTabBar.getByText(year).click();
}
clickVersion(manifest: string): Promise<void>{
return this._page.locator(`#version-item-${manifest}`).click();
}
get downloadVersionButton(): Locator { return this._downloadVersionButton; }
}
-36
View File
@@ -1,36 +0,0 @@
import { Page, Locator } from "playwright"
export class MainWindow {
protected readonly _page: Page;
private readonly _bsmLogo: Locator;
private readonly _addVersionButton: Locator;
private readonly _settingsButton: Locator;
private readonly _sharedContentButton: Locator;
constructor(page: Page) {
this._page = page;
this._bsmLogo = page.locator("#bsm-logo");
this._addVersionButton = page.locator("#add-version-btn");
this._settingsButton = page.locator("#settings-btn");
this._sharedContentButton = page.locator("#shared-contents-btn");
}
public async clickBsmLogo(): Promise<void> {
return this._bsmLogo.click();
}
public async clickAddVersionButton(): Promise<void> {
return this._addVersionButton.click();
}
public async clickSettingsButton(): Promise<void> {
return this._settingsButton.click();
}
public async clickSharedContentButton(): Promise<void> {
return this._sharedContentButton.click();
}
}
+2
View File
@@ -0,0 +1,2 @@
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]
+83
View File
@@ -0,0 +1,83 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "proc-macro2"
version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "serde"
version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "start_beat_saber_admin"
version = "0.1.0"
dependencies = [
"winres",
]
[[package]]
name = "syn"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "toml"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
dependencies = [
"serde",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "winres"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c"
dependencies = [
"toml",
]
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "start_beat_saber_admin"
version = "0.1.0"
edition = "2021"
build = "build.rs"
[build-dependencies]
winres = "0.1.12"
[profile.release]
codegen-units = 1
lto = true
opt-level = "z"
[package.metadata.winres]
FileDescription = "Start Beat Saber as Admin"
LegalCopyright = "Copyright © 2024 Zagrios"
CompanyName = "Zagrios"
+20
View File
@@ -0,0 +1,20 @@
extern crate winres;
fn main() {
if cfg!(target_os = "windows") {
let mut res = winres::WindowsResource::new();
res.set_manifest(r#"
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
"#);
res.set_icon("./icon.ico");
res.compile().unwrap();
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

+47
View File
@@ -0,0 +1,47 @@
use std::{process::Command, path::Path};
const EXECUTABLE_NAME: &str = "Beat Saber.exe";
const AUTORIZED_ARGS: [&str; 8] = [
"fpfc",
"-vrmode",
"oculus",
"--verbose",
"--no-yeet",
"--disable-autoupdate",
"--combine-logs",
"editor"
];
fn main() {
let args: Vec<String> = std::env::args().collect();
let executable_path = Path::new(&args[1]);
if executable_path.file_name().unwrap() != EXECUTABLE_NAME {
eprintln!("Executable path is not Beat Saber.exe.");
return;
}
if !executable_path.exists() || !executable_path.is_file() {
eprintln!("Executable path is not valid.");
return;
}
let mut command = Command::new(executable_path);
if let Some(parent_dir) = executable_path.parent() {
command.current_dir(parent_dir);
}
for arg in args.iter().skip(2) {
if !AUTORIZED_ARGS.contains(&arg.as_str()) {
continue;
}
command.arg(arg);
}
command.env("SteamAppId", "620980");
let _ = command.spawn();
}
+2
View File
@@ -0,0 +1,2 @@
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]
+281
View File
@@ -0,0 +1,281 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "core-foundation-sys"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]]
name = "either"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "ntapi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
dependencies = [
"winapi",
]
[[package]]
name = "oculus_symlink_cleaner"
version = "0.1.0"
dependencies = [
"sysinfo",
"winres",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "serde"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "2.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "sysinfo"
version = "0.30.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6746919caf9f2a85bff759535664c060109f21975c5ac2e8652e60102bd4d196"
dependencies = [
"cfg-if",
"core-foundation-sys",
"libc",
"ntapi",
"once_cell",
"rayon",
"windows",
]
[[package]]
name = "toml"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
dependencies = [
"serde",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [
"windows-core",
"windows-targets",
]
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
[[package]]
name = "windows_i686_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
[[package]]
name = "winres"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c"
dependencies = [
"toml",
]
+22
View File
@@ -0,0 +1,22 @@
[package]
name = "oculus_symlink_cleaner"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
winres = "0.1.12"
[dependencies]
sysinfo = "0.30.6"
[profile.release]
codegen-units = 1
lto = true
opt-level = "z"
[package.metadata.winres]
FileDescription = "Clean Oculus Symlink after Beat Saber ends"
LegalCopyright = "Copyright © 2024 Zagrios"
CompanyName = "Zagrios"
+9
View File
@@ -0,0 +1,9 @@
extern crate winres;
fn main() {
if cfg!(target_os = "windows") {
let mut res = winres::WindowsResource::new();
res.set_icon("./icon.ico");
res.compile().unwrap();
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

+78
View File
@@ -0,0 +1,78 @@
use sysinfo::{Pid, ProcessRefreshKind, System};
use std::{env, thread, time::Duration, fs};
use std::ffi::OsStr;
use std::path::Path;
use std::str::FromStr;
const BEAT_SABER_OCULUS_FOLDER_NAME: &str = "hyperbolic-magnetism-beat-saber";
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
eprintln!("Usage: {} <pid> <path_to_directory>", args[0]);
std::process::exit(1);
}
let pid: Pid = Pid::from_str(&args[1]).expect("Invalid pid");
let directory_path = Path::new(&args[2]);
if directory_path.file_name() != Some(OsStr::new(BEAT_SABER_OCULUS_FOLDER_NAME)) {
eprintln!("Directory name is not {}", BEAT_SABER_OCULUS_FOLDER_NAME);
std::process::exit(1);
}
// we want to monitor only processes
let mut system = System::new_with_specifics(sysinfo::RefreshKind::new().with_processes(ProcessRefreshKind::everything()));
loop {
system.refresh_processes();
let process = system.process(pid);
match process {
Some(_) => {
println!("Process {} is still running.", pid);
thread::sleep(Duration::from_secs(2));
},
None => {
println!("Process {} has stopped, deleting directory {:?}", pid, directory_path);
match delete_dir_if_is_symlink(directory_path) {
Ok(_) => {
println!("Directory {:?} deleted successfully.", directory_path);
if let Err(e) = rename_specific_backup_directory(directory_path.parent().unwrap()) {
eprintln!("Failed to rename backup directory: {}", e);
}
},
Err(e) => eprintln!("Failed to delete directory {:?}: {}", directory_path, e),
}
break;
}
}
}
}
fn delete_dir_if_is_symlink(path: &Path) -> Result<(), Box<dyn std::error::Error>>{
match path.symlink_metadata()?.file_type().is_symlink() {
true => {
fs::remove_dir_all(path)?;
Ok(())
},
false => {
eprintln!("Path {:?} is not a symlink.", path);
Err("Path is not a symlink.".into())
}
}
}
fn rename_specific_backup_directory(parent_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
let backup_dir_name = format!("{}.bsmbak", BEAT_SABER_OCULUS_FOLDER_NAME);
let backup_path = parent_path.join(&backup_dir_name);
if backup_path.exists() && backup_path.is_dir() {
let new_path = parent_path.join(BEAT_SABER_OCULUS_FOLDER_NAME);
fs::rename(&backup_path, &new_path)?;
println!("Renamed {:?} to {:?}", backup_path, new_path);
Ok(())
} else {
Err(format!("Backup directory {:?} does not exist or is not a directory.", backup_path).into())
}
}
+10562 -21733
View File
File diff suppressed because it is too large Load Diff
+121 -123
View File
@@ -1,22 +1,26 @@
{
"name": "bs-manager",
"description": "Manage maps, mods and more for Beat Saber",
"main": "./.erb/dll/main.bundle.dev.js",
"version": "1.5.0-alpha.4",
"scripts": {
"build-rust-scripts": "ts-node ./.erb/scripts/build-rust-scripts.js",
"build": "concurrently \"npm run build:main\" \"npm run build:renderer\"",
"build:main": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.main.prod.ts",
"build:renderer": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.prod.ts",
"build:dll": "cross-env NODE_ENV=development webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.ts",
"build:main": "cross-env NODE_ENV=production webpack --config ./.erb/configs/webpack.config.main.prod.ts",
"build:renderer": "cross-env NODE_ENV=production webpack --config ./.erb/configs/webpack.config.renderer.prod.ts",
"postinstall": "ts-node .erb/scripts/check-native-dep.js && electron-builder install-app-deps && npm run build:dll",
"rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir release/app",
"prestart": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.main.dev.ts",
"lint": "cross-env NODE_ENV=development eslint . --ext .js,.jsx,.ts,.tsx",
"package": "ts-node ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never",
"postinstall": "ts-node .erb/scripts/check-native-dep.js && electron-builder install-app-deps && cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.ts && opencollective-postinstall",
"start": "ts-node ./.erb/scripts/check-port-in-use.js && npm run start:renderer",
"start:main": "cross-env NODE_ENV=development electronmon -r ts-node/register/transpile-only ./src/main/main.ts",
"package": "ts-node ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never && npm run build:dll",
"start": "ts-node ./.erb/scripts/check-port-in-use.js && npm run prestart && npm run start:renderer",
"start:main": "concurrently -k \"cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --watch --config ./.erb/configs/webpack.config.main.dev.ts\" \"electronmon .\"",
"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 -c.win.certificateSha1=842a817a51e2a1d360fcd62f54bf5f9193e919e1 --publish always --win --x64",
"e2e-test": "npm run package && xvfb-maybe npx playwright test --workers=1",
"e2e-test-ci": "xvfb-maybe npx playwright test --workers=1"
"publish:linux": "npm run build && electron-builder --publish always --linux --x64"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
@@ -34,10 +38,9 @@
},
"build": {
"extraResources": [
"./assets/favicon.ico",
"./assets/jsons/bs-versions.json",
"./assets/jsons/patreons.json",
"./assets/scripts/**"
"./assets/proto/song_details_cache_v1.proto"
],
"productName": "BSManager",
"appId": "org.erb.BSManager",
@@ -49,46 +52,27 @@
],
"afterSign": ".erb/scripts/notarize.js",
"afterPack": ".erb/scripts/after-pack.js",
"mac": {
"target": {
"target": "default",
"arch": [
"arm64",
"x64"
]
},
"type": "distribution",
"hardenedRuntime": true,
"entitlements": "assets/entitlements.mac.plist",
"entitlementsInherit": "assets/entitlements.mac.plist",
"gatekeeperAssess": false
},
"dmg": {
"contents": [
{
"x": 130,
"y": 220
},
{
"x": 410,
"y": 220,
"type": "link",
"path": "/Applications"
}
]
},
"win": {
"target": [
"nsis",
"nsis-web"
],
"icon": "assets/favicon.ico"
"icon": "./build/icons/win/favicon.ico",
"extraResources": [
"./build/icons/win",
"./assets/scripts/*.exe"
]
},
"linux": {
"target": [
"AppImage"
],
"category": "Development"
"icon": "./build/icons/png",
"category": "Utility;Game;",
"extraResources": [
"./build/icons/png",
"./assets/scripts/DepotDownloader"
]
},
"directories": {
"app": "release/app",
@@ -98,7 +82,15 @@
"publish": {
"provider": "github",
"owner": "Zagrios"
}
},
"fileAssociations": [
{
"ext": "bplist",
"description": "Beat Saber Playlist (BSManager)",
"icon": "./assets/bsm_file.ico",
"role": "Viewer"
}
]
},
"repository": {
"type": "git",
@@ -150,145 +142,148 @@
]
},
"devDependencies": {
"@electron/rebuild": "^3.2.13",
"@playwright/test": "^1.38.1",
"@electron/fuses": "^1.7.0",
"@electron/notarize": "^2.3.0",
"@electron/rebuild": "^3.6.0",
"@pmmmwh/react-refresh-webpack-plugin": "0.5.5",
"@teamsupercell/typings-for-css-modules-loader": "^2.5.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.3.0",
"@types/archiver": "^5.3.1",
"@teamsupercell/typings-for-css-modules-loader": "^2.5.2",
"@testing-library/jest-dom": "^6.4.1",
"@testing-library/react": "^14.2.0",
"@types/archiver": "^6.0.2",
"@types/color": "^3.0.3",
"@types/crypto-js": "^4.2.1",
"@types/dateformat": "^5.0.0",
"@types/jest": "^27.5.2",
"@types/node": "17.0.23",
"@types/dompurify": "^3.0.5",
"@types/got": "^9.6.12",
"@types/jest": "^29.5.11",
"@types/node": "20.11.15",
"@types/node-fetch": "^2.6.3",
"@types/pako": "^2.0.1",
"@types/react": "^18.0.33",
"@types/react-beautiful-dnd": "^13.1.8",
"@types/react-dom": "^18.0.11",
"@types/react-outside-click-handler": "^1.3.1",
"@types/react-test-renderer": "^17.0.2",
"@types/react-test-renderer": "^18.0.7",
"@types/react-virtualized-auto-sizer": "^1.0.1",
"@types/react-window": "^1.8.5",
"@types/recursive-readdir": "^2.2.1",
"@types/terser-webpack-plugin": "^5.0.4",
"@types/to-ico": "^1.1.1",
"@types/use-double-click": "^1.0.1",
"@types/use-double-click": "^1.0.4",
"@types/webpack-bundle-analyzer": "^4.4.2",
"@types/webpack-env": "^1.18.0",
"@typescript-eslint/eslint-plugin": "^5.34.0",
"@typescript-eslint/parser": "^5.34.0",
"asar": "^3.2.0",
"autoprefixer": "^10.4.8",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.20.0",
"autoprefixer": "^10.4.17",
"browserslist-config-erb": "^0.0.3",
"chalk": "^4.1.2",
"concurrently": "^7.2.2",
"core-js": "^3.24.1",
"concurrently": "^8.2.2",
"core-js": "^3.36.0",
"cross-env": "^7.0.3",
"css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^4.1.0",
"detect-port": "^1.3.0",
"electron": "^27.1.3",
"electron-builder": "^24.9.1",
"css-loader": "^6.10.0",
"css-minimizer-webpack-plugin": "^6.0.0",
"detect-port": "^1.5.1",
"electron": "^31.3.0",
"electron-builder": "^24.13.3",
"electron-devtools-installer": "^3.2.0",
"electron-notarize": "^1.2.1",
"electronmon": "^2.0.2",
"eslint": "^8.22.0",
"eslint": "^8.56.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-erb": "^4.0.3",
"eslint-import-resolver-typescript": "^2.7.1",
"eslint-import-resolver-webpack": "^0.13.2",
"eslint-plugin-compat": "^4.0.2",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.8.7",
"eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.30.0",
"eslint-config-erb": "^4.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-import-resolver-webpack": "^0.13.8",
"eslint-plugin-compat": "^4.2.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jest": "^27.6.3",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.5.0",
"html-webpack-plugin": "^5.6.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^27.5.1",
"lint-staged": "^12.5.0",
"mini-css-extract-plugin": "^2.6.1",
"jest": "^29.7.0",
"lint-staged": "^15.2.1",
"mini-css-extract-plugin": "^2.7.7",
"opencollective-postinstall": "^2.0.3",
"playwright": "^1.38.1",
"playwright-core": "^1.38.1",
"postcss": "^8.4.16",
"postcss-loader": "^6.2.1",
"prettier": "^2.7.1",
"ps-scrollbar-tailwind": "0.0.1",
"react-refresh": "^0.12.0",
"react-refresh-typescript": "^2.0.7",
"postcss": "^8.4.33",
"postcss-loader": "^8.1.0",
"prettier": "^3.2.4",
"react-refresh": "^0.14.0",
"react-test-renderer": "^18.2.0",
"rimraf": "^3.0.2",
"sass": "^1.54.5",
"sass-loader": "^12.6.0",
"style-loader": "^3.3.1",
"tailwind-scrollbar": "^2.0.1",
"tailwindcss": "^3.3.1",
"terser-webpack-plugin": "^5.3.5",
"ts-jest": "^27.1.5",
"ts-loader": "^9.3.0",
"ts-node": "^10.8.2",
"typescript": "^4.7.4",
"rimraf": "^5.0.5",
"sass": "^1.70.0",
"sass-loader": "^14.1.0",
"style-loader": "^3.3.4",
"tailwindcss": "^3.4.7",
"terser-webpack-plugin": "^5.3.10",
"ts-jest": "^29.1.2",
"ts-loader": "^9.5.1",
"typescript": "^5.3.3",
"url-loader": "^4.1.1",
"webpack": "^5.74.0",
"webpack-bundle-analyzer": "^4.6.1",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.10.0",
"webpack-merge": "^5.8.0",
"xvfb-maybe": "^0.2.1"
"webpack": "^5.90.3",
"webpack-bundle-analyzer": "^4.10.1",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"webpack-merge": "^5.10.0"
},
"dependencies": {
"@electron/fuses": "^1.6.2",
"@internationalized/date": "^3.5.4",
"@nextui-org/date-picker": "^2.0.7",
"@nextui-org/react": "^2.3.6",
"@node-steam/vdf": "^2.2.0",
"@tippyjs/react": "^4.2.6",
"archiver": "^6.0.1",
"archiver": "^7.0.1",
"clsx": "^2.1.1",
"color": "^4.2.3",
"crypto-js": "^4.2.0",
"dateformat": "^5.0.3",
"dompurify": "^3.0.9",
"dot-prop": "^8.0.2",
"electron-debug": "^3.2.0",
"electron-log": "^4.4.8",
"electron-store": "^8.1.0",
"electron-updater": "^6.1.7",
"electron-updater": "^6.2.1",
"fast-deep-equal": "^3.1.3",
"framer-motion": "^10.16.16",
"format-duration": "^3.0.2",
"framer-motion": "^11.2.6",
"fs-extra": "^11.2.0",
"got": "^14.4.2",
"history": "^5.3.0",
"is-elevated": "^4.0.0",
"jszip": "^3.10.1",
"md5-file": "^5.0.0",
"node-abi": "^3.47.0",
"node-fetch": "^2.6.7",
"node-abi": "^3.65.0",
"node-fetch": "^3.3.2",
"node-stream-zip": "^1.15.0",
"pako": "^2.1.0",
"ps-list": "^7.2.0",
"protobufjs": "^7.3.2",
"qrcode.react": "^3.1.0",
"query-process": "^0.0.3",
"react": "^18.2.0",
"react-beautiful-dnd": "^13.1.1",
"react-colorful": "^5.6.1",
"react-dom": "^18.2.0",
"react-range": "^1.8.14",
"react-router-dom": "^6.3.0",
"react-virtualized-auto-sizer": "^1.0.12",
"react-window": "^1.8.8",
"react-router-dom": "^6.24.1",
"react-virtualized-auto-sizer": "^1.0.24",
"react-window": "^1.8.10",
"recursive-readdir": "^2.2.3",
"rfdc": "^1.3.0",
"rxjs": "^7.8.0",
"rfdc": "^1.4.1",
"rxjs": "^7.8.1",
"sanitize-filename": "^1.6.3",
"semver": "^7.5.4",
"serialize-error": "^8.1.0",
"semver": "^7.6.3",
"serialize-error": "^11.0.3",
"striptags": "^4.0.0-alpha.4",
"tailwind-scrollbar-hide": "^1.1.7",
"tailwind-merge": "^2.4.0",
"tailwindcss-scoped-groups": "^2.0.0",
"tippy.js": "^6.3.7",
"to-ico": "^1.1.5",
"use-double-click": "^1.0.5",
"use-fit-text": "^2.4.0"
},
"devEngines": {
"node": ">=14.x",
"npm": ">=7.x"
"engines": {
"node": ">=20.0.0"
},
"collective": {
"url": "https://www.patreon.com/bsmanager"
@@ -318,10 +313,13 @@
},
"electronmon": {
"patterns": [
"!src/__tests__/**",
"!release/**",
"!assets/**"
"!**/**",
"src/main/**",
".erb/dll/**"
],
"logLevel": "quiet"
},
"volta": {
"node": "20.11.0"
}
}
-18
View File
@@ -1,18 +0,0 @@
import { defineConfig, devices } from '@playwright/test';
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./e2e-tests",
testMatch: "**/*.test.ts",
timeout: 200000,
fullyParallel: true,
retries: 1,
});
+88 -967
View File
File diff suppressed because it is too large Load Diff
+10 -6
View File
@@ -1,6 +1,6 @@
{
"name": "bs-manager",
"version": "1.4.3",
"version": "1.5.0-alpha.4",
"description": "BSManager",
"main": "./dist/main/main.js",
"author": {
@@ -9,14 +9,18 @@
"url": "https://github.com/Zagrios/bs-manager"
},
"scripts": {
"electron-rebuild": "node -r ts-node/register ../../.erb/scripts/electron-rebuild.js",
"rebuild": "node -r ts-node/register ../../.erb/scripts/electron-rebuild.js",
"link-modules": "node -r ts-node/register ../../.erb/scripts/link-modules.ts",
"postinstall": "npm run electron-rebuild && npm run link-modules"
"postinstall": "npm run rebuild && npm run link-modules"
},
"dependencies": {
"@resvg/resvg-js": "2.6.2",
"ps-list": "^7.2.0",
"regedit-rs": "^1.0.1",
"sharp": "^0.32.6"
"query-process": "^0.0.3",
"regedit-rs": "^1.0.2"
},
"license": "MIT"
"license": "MIT",
"volta": {
"node": "20.11.0"
}
}
+6 -2
View File
@@ -1,4 +1,5 @@
import { app } from "electron";
import { constants } from "http2";
import path from "path";
export const BS_EXECUTABLE = "Beat Saber.exe";
@@ -10,5 +11,8 @@ export const APP_NAME = "BSManager";
export const STEAMVR_APP_ID = "250820";
export const IMAGE_CACHE_FOLDER = "imagescache";
export const IMAGE_CACHE_PATH = path.join(app.getPath("userData"), IMAGE_CACHE_FOLDER);
export const CACHE_PATH = path.join(app.getPath("userData"), "CachedData");
export const IMAGE_CACHE_PATH = path.join(CACHE_PATH, "imagescache");
export const HTTP_STATUS_CODES = constants;
+67
View File
@@ -0,0 +1,67 @@
import log from "electron-log";
import { isPromise } from "../../shared/helpers/promise.helpers";
import { tryit } from "../../shared/helpers/error.helpers";
type LogOptions = {
logInput?: boolean;
logOutput?: boolean;
logArgs?: boolean;
};
const stringifyArgs = (args: unknown[]) => {
return args?.map(a => JSON.stringify(a)).join(', ');
};
const logInfo = (message: string, propertyKey: string, args: unknown[], logArgs: boolean, result: unknown) => {
log.info(`[${message}] ${propertyKey}(${logArgs ? stringifyArgs(args) : ''})`, result);
};
const logError = (propertyKey: string, args: unknown[], logArgs: boolean, error: unknown) => {
log.error(`[ERROR] ${propertyKey}(${logArgs ? stringifyArgs(args) : ''})`, error);
throw error;
};
export function Log(options?: LogOptions){
const logInput = options?.logInput ?? false;
const logOutput = options?.logOutput ?? true;
const logArgs = options?.logArgs ?? true;
return (target: unknown, propertyKey: string, descriptor: PropertyDescriptor) => {
const originalMethod = descriptor.value;
descriptor.value = function(...args: unknown[]) {
if (logInput) {
logInfo('INPUT', propertyKey, args, logArgs, null);
}
const outcome = tryit(() => originalMethod.apply(this, args));
if (isPromise(outcome)) {
return outcome.then(({ result, error }) => {
if (error) {
logError(propertyKey, args, logArgs, error);
}
if (logOutput) {
logInfo('OUTPUT', propertyKey, args, logArgs, result);
}
return result;
});
}
const { result, error } = outcome;
if (error) {
logError(propertyKey, args, logArgs, error);
}
if (logOutput) {
logInfo('OUTPUT', propertyKey, args, logArgs, result);
}
return result;
};
};
}
+48 -18
View File
@@ -1,4 +1,4 @@
import { CopyOptions, copy, createReadStream, ensureDir, move, realpath, stat, symlink } from "fs-extra";
import { CopyOptions, MoveOptions, copy, createReadStream, ensureDir, move, pathExists, pathExistsSync, realpath, stat, symlink } from "fs-extra";
import { access, mkdir, rm, readdir, unlink, lstat, readlink } from "fs/promises";
import path from "path";
import { Observable, concatMap, from } from "rxjs";
@@ -7,6 +7,7 @@ import { BsmException } from "shared/models/bsm-exception.model";
import crypto from "crypto";
import { execSync } from "child_process";
import { tryit } from "../../shared/helpers/error.helpers";
import { CustomError } from "shared/models/exceptions/custom-error.class";
export async function pathExist(path: string): Promise<boolean> {
try {
@@ -78,36 +79,37 @@ export async function getFilesInFolder(folderPath: string): Promise<string[]> {
return dirEntries.filter(entry => entry.isFile()).map(file => path.join(folderPath, file.name));
}
export function moveFolderContent(src: string, dest: string): Observable<Progression> {
export function moveFolderContent(src: string, dest: string, option?: MoveOptions): Observable<Progression> {
const progress: Progression = { current: 0, total: 0 };
return new Observable<Progression>(subscriber => {
subscriber.next(progress);
(async () => {
const srcExist = await pathExist(src);
const srcExist = await pathExists(src);
if (!srcExist) {
return subscriber.complete();
}
ensureFolderExist(dest);
await ensureFolderExist(dest);
const files = await readdir(src, { encoding: "utf-8" });
progress.total = files.length;
const promises = files.map(async file => {
for(const file of files){
const srcFullPath = path.join(src, file);
const destFullPath = path.join(dest, file);
if (await pathExist(destFullPath)) {
progress.current++;
return subscriber.next(progress);
const srcChilds = await readdir(srcFullPath, { encoding: "utf-8", recursive: true });
const allChildsAlreadyExist = srcChilds.every(child => pathExistsSync(path.join(destFullPath, child)));
if(!allChildsAlreadyExist){
await move(srcFullPath, destFullPath, option);
}
await move(srcFullPath, destFullPath);
progress.current++;
subscriber.next(progress);
});
Promise.allSettled(promises).then(() => subscriber.complete());
})();
}
})().catch(err => subscriber.error(CustomError.fromError(err, err?.code))).finally(() => subscriber.complete());
});
}
@@ -151,7 +153,7 @@ export async function copyDirectoryWithJunctions(src: string, dest: string, opti
const symlinkTarget = await readlink(sourcePath);
const relativePath = path.relative(src, symlinkTarget);
const newTarget = path.join(dest, relativePath);
await symlink(newTarget, destinationPath, "junction");
await symlink(newTarget, destinationPath, "junction"); // Only junction to avoid right issues while copying content of BSManager folder
}
}
}
@@ -175,7 +177,7 @@ export async function dirSize(dirPath: string): Promise<number>{
const realPath = await realpath(fullPath);
const stat = await lstat(realPath);
if (stat.isDirectory()) {
if (stat.isDirectory()) {
return dirSize(fullPath);
}
@@ -217,13 +219,27 @@ export function rxCopy(src: string, dest: string, option?: CopyOptions): Observa
export async function ensurePathNotAlreadyExist(path: string): Promise<string> {
let destPath = path;
let folderExist = await pathExist(destPath);
let folderExist = await pathExists(destPath);
let i = 0;
while (folderExist) {
i++;
destPath = `${path} (${i})`;
folderExist = await pathExist(destPath);
folderExist = await pathExists(destPath);
}
return destPath;
}
export function ensurePathNotAlreadyExistSync(path: string): string {
let destPath = path;
let folderExist = pathExistsSync(destPath);
let i = 0;
while (folderExist) {
i++;
destPath = `${path} (${i})`;
folderExist = pathExistsSync(destPath);
}
return destPath;
@@ -244,9 +260,23 @@ export function resolveGUIDPath(guidPath: string): string {
return path.join(driveLetter, path.relative(guidVolume, guidPath));
}
export interface Progression<T = unknown> {
export function getUniqueFileNamePath(filePath: string): string {
const { dir, name, ext } = path.parse(filePath);
let i = 0;
let newFileName = `${name}${ext}`;
while (pathExistsSync(path.join(dir, newFileName))) {
i++;
newFileName = `${name} (${i})${ext}`;
}
return path.join(dir, newFileName);
}
export interface Progression<T = unknown, D = unknown> {
total: number;
current: number;
diff?: number;
data?: T;
extra?: D;
}
+13 -1
View File
@@ -10,4 +10,16 @@ export async function taskRunning(task: string): Promise<boolean> {
log.error(error);
return false;
}
}
}
export async function getProcessPid(task: string): Promise<number> {
try {
const processes = await psList();
const process = processes.find(process => process.name?.includes(task) || process.cmd?.includes(task));
return process?.pid;
}
catch(error){
log.error(error);
return null;
}
}
+17 -50
View File
@@ -1,63 +1,30 @@
import { ipcMain } from "electron";
import { UtilsService } from "../services/utils.service";
import { IpcRequest } from "shared/models/ipc";
import { SearchParams } from "shared/models/maps/beat-saver.model";
import { BeatSaverService } from "../services/thrid-party/beat-saver/beat-saver.service";
import log from "electron-log";
import { IpcService } from "../services/ipc.service";
import { from } from "rxjs";
ipcMain.on("bsv-search-map", async (event, request: IpcRequest<SearchParams>) => {
const utlis = UtilsService.getInstance();
const ipc = IpcService.getInstance();
ipc.on("bsv-search-map", (args, reply) => {
const bsvService = BeatSaverService.getInstance();
bsvService
.searchMaps(request.args)
.then(maps => {
utlis.ipcSend(request.responceChannel, { success: true, data: maps });
})
.catch(e => {
utlis.ipcSend(request.responceChannel, { success: false, error: e });
});
reply(from(bsvService.searchMaps(args)));
});
ipcMain.on("bsv-get-map-details-from-hashs", async (event, request: IpcRequest<string[]>) => {
const utlis = UtilsService.getInstance();
ipc.on("bsv-get-map-details-from-hashs", (args, reply) => {
const bsvService = BeatSaverService.getInstance();
bsvService
.getMapDetailsFromHashs(request.args)
.then(maps => {
utlis.ipcSend(request.responceChannel, { success: true, data: maps });
})
.catch(e => {
log.error(e);
utlis.ipcSend(request.responceChannel, { success: false, error: e });
});
reply(from(bsvService.getMapDetailsFromHashs(args)));
});
ipcMain.on("bsv-get-map-details-by-id", async (event, request: IpcRequest<string>) => {
const utlis = UtilsService.getInstance();
ipc.on("bsv-get-map-details-by-id", (args, reply) => {
const bsvService = BeatSaverService.getInstance();
bsvService
.getMapDetailsById(request.args)
.then(maps => {
utlis.ipcSend(request.responceChannel, { success: true, data: maps });
})
.catch(e => {
utlis.ipcSend(request.responceChannel, { success: false, error: e });
});
reply(from(bsvService.getMapDetailsById(args)));
});
ipcMain.on("bsv-get-playlist-details-by-id", async (event, request: IpcRequest<string>) => {
const utlis = UtilsService.getInstance();
ipc.on("bsv-search-playlist", (args, reply) => {
const bsvService = BeatSaverService.getInstance();
bsvService
.getPlaylistPage(request.args)
.then(maps => {
utlis.ipcSend(request.responceChannel, { success: true, data: maps });
})
.catch(e => {
utlis.ipcSend(request.responceChannel, { success: false, error: e });
});
reply(from(bsvService.searchPlaylists(args)));
});
ipc.on("bsv-get-playlist-details-by-id", (args, reply) => {
const bsvService = BeatSaverService.getInstance();
reply(from(bsvService.getPlaylistDetailsById(args.id, args.page)));
});
+27
View File
@@ -0,0 +1,27 @@
import { pathExistsSync } from "fs-extra";
import { from, of } from "rxjs";
import { InstallationLocationService } from "main/services/installation-location.service";
import { IpcService } from "main/services/ipc.service";
const ipc = IpcService.getInstance();
ipc.on("bs-installer.folder-exists", (_, reply) => {
const service = InstallationLocationService.getInstance();
reply(of(pathExistsSync(service.installationDirectory())));
});
ipc.on("bs-installer.default-install-path", (_, reply) => {
const service = InstallationLocationService.getInstance();
reply(of(service.defaultInstallationDirectory()));
});
ipc.on("bs-installer.install-path", (_, reply) => {
const service = InstallationLocationService.getInstance();
reply(of(service.installationDirectory()));
});
ipc.on("bs-installer.set-install-path", (args, reply) => {
const service = InstallationLocationService.getInstance();
reply(from(service.setInstallationDirectory(args.path, args.move)));
});
+19 -15
View File
@@ -1,32 +1,36 @@
import { LaunchOption } from "shared/models/bs-launch";
import { BSLauncherService } from "../services/bs-launcher/bs-launcher.service"
import { IpcService } from '../services/ipc.service';
import { from } from "rxjs";
import { SteamLauncherService } from "../services/bs-launcher/steam-launcher.service";
import { OculusLauncherService } from "../services/bs-launcher/oculus-launcher.service";
import { SteamService } from "../services/steam.service";
import log from "electron-log";
import isElevated from "is-elevated";
const ipc = IpcService.getInstance();
ipc.on<LaunchOption>('bs-launch.launch', (req, reply) => {
ipc.on('bs-launch.launch', (args, reply) => {
const bsLauncher = BSLauncherService.getInstance();
reply(bsLauncher.launch(req.args));
reply(bsLauncher.launch(args));
});
ipc.on<LaunchOption>("create-launch-shortcut", (req, reply) => {
const bsLauncher = BSLauncherService.getInstance();
reply(from(bsLauncher.createLaunchShortcut(req.args)));
ipc.on("bs-launch.need-start-as-admin", (_, reply) => {
const steam = SteamService.getInstance();
reply(from(isElevated().then(elevated => {
if(elevated){ return false; }
return steam.isElevated().catch(e => {
log.error("Error while checking if Steam is running as admin", e);
return false;
});
})));
});
ipc.on("create-launch-shortcut", (args, reply) => {
const bsLauncher = BSLauncherService.getInstance();
reply(from(bsLauncher.createLaunchShortcut(args)));
});
ipc.on<void>("bs-launch.restore-steamvr", (_, reply) => {
ipc.on("bs-launch.restore-steamvr", (_, reply) => {
const steamLauncher = SteamLauncherService.getInstance();
reply(from(steamLauncher.restoreSteamVR()));
});
ipc.on<void>("restore-original-oculus-folder", (_, reply) => {
const oculusLauncher = OculusLauncherService.getInstance();
reply(from(
oculusLauncher.deleteBsSymlinks().then(() => oculusLauncher.restoreOriginalBeatSaber())
));
})
+49 -85
View File
@@ -1,119 +1,83 @@
import { LocalMapsManagerService } from "../services/additional-content/local-maps-manager.service";
import { UtilsService } from "../services/utils.service";
import { BSVersion } from "shared/bs-version.interface";
import { IpcRequest } from "shared/models/ipc";
import { BsmLocalMap } from "shared/models/maps/bsm-local-map.interface";
import { BsvMapDetail } from "shared/models/maps";
import { LocalMapsManagerService } from "../services/additional-content/maps/local-maps-manager.service";
import { IpcService } from "../services/ipc.service";
import { from } from "rxjs";
import log from "electron-log"
import { from, of, throwError } from "rxjs";
import { tryit } from "shared/helpers/error.helpers";
import { SongDetailsCacheService } from "main/services/additional-content/maps/song-details-cache.service";
import { SongDetails } from "shared/models/maps";
const ipc = IpcService.getInstance();
ipc.on("load-version-maps", async (request: IpcRequest<BSVersion>, reply) => {
ipc.on("load-version-maps", (args, reply) => {
const localMaps = LocalMapsManagerService.getInstance();
reply(localMaps.getMaps(request.args));
reply(localMaps.getMaps(args));
});
ipc.on("verion-have-maps-linked", async (request: IpcRequest<BSVersion>) => {
const utils = UtilsService.getInstance();
ipc.on("delete-maps", (args, reply) => {
const maps = LocalMapsManagerService.getInstance();
utils.ipcSend<boolean>(request.responceChannel, { success: true, data: await maps.versionIsLinked(request.args) });
reply(maps.deleteMaps(args));
});
ipc.on("link-version-maps", async (request: IpcRequest<{ version: BSVersion; keepMaps: boolean }>) => {
const utils = UtilsService.getInstance();
ipc.on("export-maps", async (args, reply) => {
const maps = LocalMapsManagerService.getInstance();
maps.linkVersionMaps(request.args.version, request.args.keepMaps)
.then(() => {
utils.ipcSend<void>(request.responceChannel, { success: true });
})
.catch(err => {
utils.ipcSend<void>(request.responceChannel, { success: true, error: err });
});
reply(await maps.exportMaps(args.version, args.maps, args.outPath));
});
ipc.on("unlink-version-maps", async (request: IpcRequest<{ version: BSVersion; keepMaps: boolean }>) => {
const utils = UtilsService.getInstance();
ipc.on("download-map", async (args, reply) => {
const maps = LocalMapsManagerService.getInstance();
maps.unlinkVersionMaps(request.args.version, request.args.keepMaps)
.then(() => {
utils.ipcSend<void>(request.responceChannel, { success: true });
})
.catch(err => {
utils.ipcSend<void>(request.responceChannel, { success: true, error: err });
});
reply(from(maps.downloadMap(args.map, args.version)));
});
ipc.on("delete-maps", async (request: IpcRequest<BsmLocalMap[]>, reply) => {
ipc.on("one-click-install-map", (args, reply) => {
const maps = LocalMapsManagerService.getInstance();
reply(maps.deleteMaps(request.args));
reply(from(maps.oneClickDownloadMap(args)))
});
ipc.on("export-maps", async (request: IpcRequest<{ version: BSVersion; maps: BsmLocalMap[]; outPath: string }>, reply) => {
ipc.on("register-maps-deep-link", (_, reply) => {
const maps = LocalMapsManagerService.getInstance();
reply(await maps.exportMaps(request.args.version, request.args.maps, request.args.outPath));
});
const { error, result } = tryit(() => maps.enableDeepLinks());
ipc.on("download-map", async (request: IpcRequest<{ map: BsvMapDetail; version: BSVersion }>, reply) => {
const maps = LocalMapsManagerService.getInstance();
reply(from(maps.downloadMap(request.args.map, request.args.version)));
});
ipc.on("one-click-install-map", async (request: IpcRequest<BsvMapDetail>) => {
const utils = UtilsService.getInstance();
const maps = LocalMapsManagerService.getInstance();
maps.oneClickDownloadMap(request.args)
.then(() => {
utils.ipcSend(request.responceChannel, { success: true });
})
.catch(err => {
log.error(err);
utils.ipcSend(request.responceChannel, { success: false, error: err });
});
});
ipc.on("register-maps-deep-link", async (request: IpcRequest<void>) => {
const maps = LocalMapsManagerService.getInstance();
const utils = UtilsService.getInstance();
try {
const res = maps.enableDeepLinks();
utils.ipcSend(request.responceChannel, { success: true, data: res });
} catch (e) {
utils.ipcSend(request.responceChannel, { success: false });
if(error) {
return reply(throwError(() => error));
}
reply(of(result));
});
ipc.on("unregister-maps-deep-link", async (request: IpcRequest<void>) => {
ipc.on("unregister-maps-deep-link", (_, reply) => {
const maps = LocalMapsManagerService.getInstance();
const utils = UtilsService.getInstance();
const { error, result } = tryit(() => maps.disableDeepLinks());
try {
const res = maps.disableDeepLinks();
utils.ipcSend(request.responceChannel, { success: true, data: res });
} catch (e) {
utils.ipcSend(request.responceChannel, { success: false });
if(error) {
return reply(throwError(() => error));
}
reply(of(result));
});
ipc.on("is-map-deep-links-enabled", async (request: IpcRequest<void>) => {
ipc.on("is-map-deep-links-enabled", (_, reply) => {
const maps = LocalMapsManagerService.getInstance();
const utils = UtilsService.getInstance();
const { error, result } = tryit(() => maps.isDeepLinksEnabled());
try {
const res = maps.isDeepLinksEnabled();
utils.ipcSend(request.responceChannel, { success: true, data: res });
} catch (e) {
utils.ipcSend(request.responceChannel, { success: false });
if(error) {
return reply(throwError(() => error));
}
reply(of(result));
});
ipc.on("get-version-maps-path", async (req: IpcRequest<BSVersion>, reply) => {
const maps = LocalMapsManagerService.getInstance();
reply(from(maps.getMapsFolderPath(req.args)));
});
ipc.on("get-maps-info-from-cache", (args, reply) => {
const songsCache = SongDetailsCacheService.getInstance();
const res = (args ?? []).reduce((acc, hash) => {
const songDetails = songsCache.getSongDetails(hash);
if(songDetails){
acc.push(songDetails);
}
return acc;
}, [] as SongDetails[]);
reply(of(res));
})
+23 -60
View File
@@ -1,82 +1,45 @@
import { ipcMain } from "electron";
import { UtilsService } from "../services/utils.service";
import { IpcRequest } from "shared/models/ipc";
import { MSModel, MSModelType } from "shared/models/models/model-saber.model";
import { LocalModelsManagerService } from "../services/additional-content/local-models-manager.service";
import { IpcService } from "../services/ipc.service";
import { BSVersion } from "shared/bs-version.interface";
import { BsmLocalModel } from "shared/models/models/bsm-local-model.interface";
import { ModelDownload } from "renderer/services/models-management/models-downloader.service";
import { from, of } from "rxjs";
const ipc = IpcService.getInstance();
ipcMain.on("one-click-install-model", async (event, request: IpcRequest<MSModel>) => {
const utils = UtilsService.getInstance();
ipc.on("one-click-install-model", (args, reply) => {
const models = LocalModelsManagerService.getInstance();
models
.oneClickDownloadModel(request.args)
.then(() => {
utils.ipcSend(request.responceChannel, { success: true });
})
.catch(e => {
utils.ipcSend(request.responceChannel, { success: false, error: e });
});
reply(from(models.oneClickDownloadModel(args)));
});
ipcMain.on("register-models-deep-link", async (event, request: IpcRequest<void>) => {
ipc.on("register-models-deep-link", (_, reply) => {
const models = LocalModelsManagerService.getInstance();
reply(of(models.enableDeepLinks()));
});
ipc.on("unregister-models-deep-link", (_, reply) => {
const models = LocalModelsManagerService.getInstance();
reply(of(models.disableDeepLinks()));
});
ipc.on("is-models-deep-links-enabled", (_, reply) => {
const maps = LocalModelsManagerService.getInstance();
const utils = UtilsService.getInstance();
try {
const res = maps.enableDeepLinks();
utils.ipcSend(request.responceChannel, { success: true, data: res });
} catch (e) {
utils.ipcSend(request.responceChannel, { success: false });
}
reply(of(maps.isDeepLinksEnabled()));
});
ipcMain.on("unregister-models-deep-link", async (event, request: IpcRequest<void>) => {
const maps = LocalModelsManagerService.getInstance();
const utils = UtilsService.getInstance();
try {
const res = maps.disableDeepLinks();
utils.ipcSend(request.responceChannel, { success: true, data: res });
} catch (e) {
utils.ipcSend(request.responceChannel, { success: false });
}
});
ipcMain.on("is-models-deep-links-enabled", async (event, request: IpcRequest<void>) => {
const maps = LocalModelsManagerService.getInstance();
const utils = UtilsService.getInstance();
try {
const res = maps.isDeepLinksEnabled();
utils.ipcSend(request.responceChannel, { success: true, data: res });
} catch (e) {
utils.ipcSend(request.responceChannel, { success: false });
}
});
ipc.on<ModelDownload>("download-model", async (req, reply) => {
ipc.on("download-model", (args, reply) => {
const models = LocalModelsManagerService.getInstance();
reply(models.downloadModel(req.args.model, req.args.version));
reply(models.downloadModel(args.model, args.version));
});
ipc.on<{ version: BSVersion; type: MSModelType }>("get-version-models", async (req, reply) => {
ipc.on("get-version-models", (args, reply) => {
const models = LocalModelsManagerService.getInstance();
const res = await models.getModels(req.args.type, req.args.version);
reply(res);
reply(from(models.getModels(args.type, args.version)));
});
ipc.on<{ version: BSVersion; models: BsmLocalModel[]; outPath: string }>("export-models", async (req, reply) => {
ipc.on("export-models", (args, reply) => {
const models = LocalModelsManagerService.getInstance();
reply(models.exportModels(req.args.outPath, req.args.version, req.args.models));
reply(models.exportModels(args.outPath, args.version, args.models));
});
ipc.on<BsmLocalModel[]>("delete-models", async (req, reply) => {
ipc.on("delete-models", (args, reply) => {
const models = LocalModelsManagerService.getInstance();
reply(models.deleteModels(req.args));
reply(models.deleteModels(args));
});
+10 -47
View File
@@ -1,67 +1,30 @@
import { ipcMain } from "electron";
import { BsModsManagerService } from "../services/mods/bs-mods-manager.service";
import { UtilsService } from "../services/utils.service";
import { BSVersion } from "shared/bs-version.interface";
import { IpcRequest } from "shared/models/ipc";
import { Mod } from "shared/models/mods/mod.interface";
import { InstallModsResult } from "shared/models/mods";
import log from "electron-log";
import { IpcService } from "../services/ipc.service";
import { from } from "rxjs";
const ipc = IpcService.getInstance();
ipc.on<BSVersion>("get-available-mods", (req, reply) => {
ipc.on("get-available-mods", (args, reply) => {
const modsManager = BsModsManagerService.getInstance();
reply(from(modsManager.getAvailableMods(req.args)));
reply(from(modsManager.getAvailableMods(args)));
});
ipc.on<BSVersion>("get-installed-mods", (req, reply) => {
ipc.on("get-installed-mods", (args, reply) => {
const modsManager = BsModsManagerService.getInstance();
reply(from(modsManager.getInstalledMods(req.args)));
reply(from(modsManager.getInstalledMods(args)));
});
ipcMain.on("install-mods", (event, request: IpcRequest<{ mods: Mod[]; version: BSVersion }>) => {
const utils = UtilsService.getInstance();
ipc.on("install-mods", (args, reply) => {
const modsManager = BsModsManagerService.getInstance();
modsManager
.installMods(request.args.mods, request.args.version)
.then(nbInstalled => {
utils.ipcSend<InstallModsResult>(request.responceChannel, { success: true, data: nbInstalled });
})
.catch(err => {
utils.ipcSend(request.responceChannel, { success: false, error: err });
log.error("ipc", "install-mods", err, request);
});
reply(from(modsManager.installMods(args.mods, args.version)));
});
ipcMain.on("uninstall-mods", (event, request: IpcRequest<{ mods: Mod[]; version: BSVersion }>) => {
const utils = UtilsService.getInstance();
ipc.on("uninstall-mods", (args, reply) => {
const modsManager = BsModsManagerService.getInstance();
modsManager
.uninstallMods(request.args.mods, request.args.version)
.then(nbInstalled => {
utils.ipcSend(request.responceChannel, { success: true, data: nbInstalled });
})
.catch(err => {
utils.ipcSend(request.responceChannel, { success: false, error: err });
log.error("ipc", "uninstall-mods", err, request);
});
reply(from(modsManager.uninstallMods(args.mods, args.version)));
});
ipcMain.on("uninstall-all-mods", (event, request: IpcRequest<BSVersion>) => {
const utils = UtilsService.getInstance();
ipc.on("uninstall-all-mods", (args, reply) => {
const modsManager = BsModsManagerService.getInstance();
modsManager
.uninstallAllMods(request.args)
.then(nbInstalled => {
utils.ipcSend(request.responceChannel, { success: true, data: nbInstalled });
})
.catch(err => {
utils.ipcSend(request.responceChannel, { success: false, error: err });
log.error("ipc", "uninstall-all-mods", err, request);
});
reply(from(modsManager.uninstallAllMods(args)));
});
+59 -32
View File
@@ -1,48 +1,75 @@
import { ipcMain } from "electron";
import { IpcRequest } from "shared/models/ipc";
import { LocalPlaylistsManagerService } from "../services/additional-content/local-playlists-manager.service";
import { UtilsService } from "../services/utils.service";
import { IpcService } from "../services/ipc.service";
import { from, lastValueFrom, mergeMap, of } from "rxjs";
import { LocalMapsManagerService } from "../services/additional-content/maps/local-maps-manager.service";
import { Progression } from "main/helpers/fs.helpers";
import { isValidUrl } from "shared/helpers/url.helpers";
import { pathToFileURL } from "url";
const ipc = IpcService.getInstance();
ipc.on<string>("one-click-install-playlist", (req, reply) => {
ipc.on("one-click-install-playlist", (args, reply) => {
const mapsManager = LocalPlaylistsManagerService.getInstance();
reply(mapsManager.oneClickInstallPlaylist(req.args));
reply(mapsManager.oneClickInstallPlaylist(args));
});
ipcMain.on("register-playlists-deep-link", async (event, request: IpcRequest<void>) => {
ipc.on("register-playlists-deep-link", (args, reply) => {
const maps = LocalPlaylistsManagerService.getInstance();
const utils = UtilsService.getInstance();
try {
const res = maps.enableDeepLinks();
utils.ipcSend(request.responceChannel, { success: true, data: res });
} catch (e) {
utils.ipcSend(request.responceChannel, { success: false });
}
reply(of(maps.enableDeepLinks()));
});
ipcMain.on("unregister-playlists-deep-link", async (event, request: IpcRequest<void>) => {
ipc.on("unregister-playlists-deep-link", (args, reply) => {
const maps = LocalPlaylistsManagerService.getInstance();
const utils = UtilsService.getInstance();
try {
const res = maps.disableDeepLinks();
utils.ipcSend(request.responceChannel, { success: true, data: res });
} catch (e) {
utils.ipcSend(request.responceChannel, { success: false });
}
reply(of(maps.disableDeepLinks()));
});
ipcMain.on("is-playlists-deep-links-enabled", async (event, request: IpcRequest<void>) => {
ipc.on("is-playlists-deep-links-enabled", (args, reply) => {
const maps = LocalPlaylistsManagerService.getInstance();
const utils = UtilsService.getInstance();
try {
const res = maps.isDeepLinksEnabled();
utils.ipcSend(request.responceChannel, { success: true, data: res });
} catch (e) {
utils.ipcSend(request.responceChannel, { success: false });
}
reply(of(maps.isDeepLinksEnabled()));
});
ipc.on("download-playlist", (args, reply) => {
const playlists = LocalPlaylistsManagerService.getInstance();
const downloadUrl = isValidUrl(args.downloadSource) ? args.downloadSource : pathToFileURL(args.downloadSource).href;
return reply(playlists.downloadPlaylist({
bpListUrl: downloadUrl,
version: args.version,
ignoreSongsHashs: args.ignoreSongsHashs,
dest: args.dest
}));
});
ipc.on("get-version-playlists-details", (args, reply) => {
const playlists = LocalPlaylistsManagerService.getInstance();
reply(playlists.getVersionPlaylistsDetails(args));
});
ipc.on("delete-playlist", (args, reply) => {
const playlists = LocalPlaylistsManagerService.getInstance();
const maps = LocalMapsManagerService.getInstance();
reply(playlists.deletePlaylistFile(args.bpList).pipe(mergeMap(() => {
if(args.deleteMaps){
return maps.deleteMapsFromHashs(args.version, args.bpList.songs.map(s => s.hash));
}
return of({ current: 0, total: 0 } as Progression);
})));
});
ipc.on("export-playlists", (args, reply) => {
const playlists = LocalPlaylistsManagerService.getInstance();
reply(playlists.exportPlaylists(args));
});
ipc.on("install-playlist-file", (args, reply) => {
const playlists = LocalPlaylistsManagerService.getInstance();
const promise = async () => {
const playlist = await lastValueFrom(playlists.writeBPListFile({ bpList: args.bplist, version: args.version, dest: args.dest}));
return playlists.getLocalBPListDetails(playlist);
}
reply(from(promise()));
})
+2 -4
View File
@@ -1,12 +1,10 @@
import { BSVersion } from "shared/bs-version.interface";
import { BSLocalVersionService } from "../services/bs-local-version.service";
import { IpcService } from "../services/ipc.service";
import { from } from "rxjs";
const ipc = IpcService.getInstance();
ipc.on<BSVersion>("bs.uninstall", (req, reply) => {
ipc.on("bs.uninstall", (args, reply) => {
const bsLocalVersionService = BSLocalVersionService.getInstance();
reply(from(bsLocalVersionService.deleteVersion(req.args)));
reply(from(bsLocalVersionService.deleteVersion(args)));
});
@@ -1,47 +1,31 @@
import { BsOculusDownloaderService } from "../../services/bs-version-download/bs-oculus-downloader.service";
import { BsSteamDownloaderService, DownloadInfo, DownloadSteamInfo } from "../../services/bs-version-download/bs-steam-downloader.service";
import { InstallationLocationService } from "../../services/installation-location.service";
import { BsSteamDownloaderService } from "../../services/bs-version-download/bs-steam-downloader.service";
import { IpcService } from "../../services/ipc.service";
import { from, of } from "rxjs";
import { BSLocalVersionService, ImportVersionOptions } from "../../services/bs-local-version.service";
import { of } from "rxjs";
import { BSLocalVersionService } from "../../services/bs-local-version.service";
const ipc = IpcService.getInstance();
ipc.on<ImportVersionOptions>("import-version", (req, reply) => {
ipc.on("import-version", (args, reply) => {
const versionManager = BSLocalVersionService.getInstance();
reply(versionManager.importVersion(req.args));
reply(versionManager.importVersion(args));
});
// #region Steam
// #region Steam
ipc.on("is-dotnet-6-installed", (_, reply) => {
const installer = BsSteamDownloaderService.getInstance();
reply(from(installer.isDotNet6Installed()));
});
ipc.on("bs-download.installation-folder", (_, reply) => {
const installLocation = InstallationLocationService.getInstance();
reply(from(installLocation.installationDirectory()));
});
ipc.on<string>("bs-download.set-installation-folder", (req, reply) => {
const installerService = InstallationLocationService.getInstance();
reply(from(installerService.setInstallationDirectory(req.args)));
});
ipc.on<DownloadSteamInfo>("auto-download-bs-version", (req, reply) => {
ipc.on("auto-download-bs-version", (args, reply) => {
const bsInstaller = BsSteamDownloaderService.getInstance();
reply(bsInstaller.autoDownloadBsVersion(req.args));
reply(bsInstaller.autoDownloadBsVersion(args));
});
ipc.on<DownloadSteamInfo>("download-bs-version", (req, reply) => {
ipc.on("download-bs-version", (args, reply) => {
const bsInstaller = BsSteamDownloaderService.getInstance();
reply(bsInstaller.downloadBsVersion(req.args))
reply(bsInstaller.downloadBsVersion(args))
});
ipc.on<DownloadSteamInfo>("download-bs-version-qr", (req, reply) => {
ipc.on("download-bs-version-qr", (args, reply) => {
const bsInstaller = BsSteamDownloaderService.getInstance();
reply(bsInstaller.downloadBsVersionWithQRCode(req.args))
reply(bsInstaller.downloadBsVersionWithQRCode(args))
});
ipc.on("stop-download-bs-version", (_, reply) => {
@@ -49,23 +33,18 @@ ipc.on("stop-download-bs-version", (_, reply) => {
reply(of(bsInstaller.stopDownload()));
});
ipc.on<string>("send-input-bs-download", (req, reply) => {
ipc.on("send-input-bs-download", (args, reply) => {
const bsInstaller = BsSteamDownloaderService.getInstance();
reply(of(bsInstaller.sendInput(req.args)));
reply(of(bsInstaller.sendInput(args)));
});
// #endregion
// #region Oculus
ipc.on<DownloadInfo>("bs-oculus-download", async (req, reply) => {
ipc.on("bs-oculus-download", async (args, reply) => {
const oculusDownloader = BsOculusDownloaderService.getInstance();
reply(oculusDownloader.downloadVersion(req.args));
});
ipc.on<DownloadInfo>("bs-oculus-auto-download", async (req, reply) => {
const oculusDownloader = BsOculusDownloaderService.getInstance();
reply(oculusDownloader.autoDownloadVersion(req.args));
reply(oculusDownloader.downloadVersion(args));
});
ipc.on("bs-oculus-stop-download", async (_, reply) => {
@@ -73,14 +52,4 @@ ipc.on("bs-oculus-stop-download", async (_, reply) => {
reply(of(oculusDownloader.stopDownload()));
});
ipc.on("bs-oculus-has-auth-token", async (_, reply) => {
const oculusDownloader = BsOculusDownloaderService.getInstance();
reply(from(oculusDownloader.getAuthToken().then(token => !!token)));
});
ipc.on("bs-oculus-clear-auth-token", async (_, reply) => {
const oculusDownloader = BsOculusDownloaderService.getInstance();
reply(from(oculusDownloader.clearAuthToken()));
});
// #endregion
// #endregion
+38 -142
View File
@@ -1,173 +1,69 @@
import { ipcMain, shell } from "electron";
import { UtilsService } from "../services/utils.service";
import { shell } from "electron";
import { BSVersionLibService } from "../services/bs-version-lib.service";
import { BSVersion } from "shared/bs-version.interface";
import { IpcRequest } from "shared/models/ipc";
import { BSLocalVersionService } from "../services/bs-local-version.service";
import { BsmException } from "shared/models/bsm-exception.model";
import { IpcService } from "../services/ipc.service";
import { from } from "rxjs";
import path from "path";
import { pathExist } from "../helpers/fs.helpers";
import { FolderLinkerService, LinkOptions } from "../services/folder-linker.service";
import { LocalMapsManagerService } from "../services/additional-content/local-maps-manager.service";
import { readJSON, writeJSON } from "fs-extra";
import log from "electron-log";
import { VersionLinkerAction } from "renderer/services/version-folder-linker.service";
import { pathExists } from "fs-extra";
import { VersionFolderLinkerService } from "../services/version-folder-linker.service";
const ipc = IpcService.getInstance();
ipcMain.on("bs-version.get-version-dict", (_event, req: IpcRequest<void>) => {
BSVersionLibService.getInstance()
.getAvailableVersions()
.then(versions => {
UtilsService.getInstance().ipcSend(req.responceChannel, { success: true, data: versions });
})
.catch(() => {
UtilsService.getInstance().ipcSend(req.responceChannel, { success: false });
});
ipc.on("bs-version.get-version-dict", (_, reply) => {
const versionsLib = BSVersionLibService.getInstance();
reply(from(versionsLib.getAvailableVersions()));
});
ipcMain.on("bs-version.installed-versions", async (_event, req: IpcRequest<void>) => {
BSLocalVersionService.getInstance()
.getInstalledVersions()
.then(versions => {
UtilsService.getInstance().ipcSend(req.responceChannel, { success: true, data: versions });
})
.catch(() => {
UtilsService.getInstance().ipcSend(req.responceChannel, { success: false });
});
ipc.on("bs-version.installed-versions", (_, reply) => {
const versions = BSLocalVersionService.getInstance();
reply(from(versions.getInstalledVersions()));
});
ipcMain.on("bs-version.open-folder", async (_event, req: IpcRequest<BSVersion>) => {
const localVersionService = BSLocalVersionService.getInstance();
const versionFolder = await localVersionService.getVersionPath(req.args);
if (!(await pathExist(versionFolder))) return;
shell.openPath(versionFolder);
});
ipcMain.on("bs-version.edit", async (__event, req: IpcRequest<{ version: BSVersion; name: string; color: string }>) => {
BSLocalVersionService.getInstance()
.editVersion(req.args.version, req.args.name, req.args.color)
.then(res => {
UtilsService.getInstance().ipcSend(req.responceChannel, { success: !!res, data: res });
})
.catch((error: BsmException) => {
UtilsService.getInstance().ipcSend(req.responceChannel, { success: false, error });
});
});
ipcMain.on("bs-version.clone", async (_event, req: IpcRequest<{ version: BSVersion; name: string; color: string }>) => {
BSLocalVersionService.getInstance()
.cloneVersion(req.args.version, req.args.name, req.args.color)
.then(res => {
UtilsService.getInstance().ipcSend(req.responceChannel, { success: !!res, data: res });
})
.catch((error: BsmException) => {
UtilsService.getInstance().ipcSend(req.responceChannel, { success: false, error });
});
});
ipc.on("get-version-full-path", async (req: IpcRequest<BSVersion>, reply) => {
const localVersions = BSLocalVersionService.getInstance();
reply(from(localVersions.getVersionPath(req.args)));
});
ipc.on("relative-version-path-to-full", async (req: IpcRequest<{ version: BSVersion; relative: string }>, reply) => {
path.isAbsolute(req.args.relative) && reply(from(Promise.resolve(req.args.relative)));
const localVersions = BSLocalVersionService.getInstance();
const promise = localVersions
.getVersionPath(req.args.version)
.catch(() => null)
.then(versionPath => {
return path.join(versionPath, req.args.relative);
});
ipc.on("bs-version.open-folder", (args, reply) => {
const versions = BSLocalVersionService.getInstance();
const promise = versions.getVersionPath(args).then(versionFolder => {
if(!versionFolder || !pathExists(versionFolder)) return;
shell.openPath(versionFolder);
})
reply(from(promise));
});
ipc.on("full-version-path-to-relative", async (req: IpcRequest<{ version: BSVersion; fullPath: string }>, reply) => {
ipc.on("bs-version.edit", (args, reply) => {
const versions = BSLocalVersionService.getInstance();
reply(from(versions.editVersion(args.version, args.name, args.color)));
});
ipc.on("bs-version.clone", (args, reply) => {
const versions = BSLocalVersionService.getInstance();
reply(from(versions.cloneVersion(args.version, args.name, args.color)));
});
ipc.on("get-version-full-path", (args, reply) => {
const localVersions = BSLocalVersionService.getInstance();
const promise = localVersions
.getVersionPath(req.args.version)
.catch(() => null)
.then(versionPath => {
return path.relative(versionPath, req.args.fullPath);
});
reply(from(promise));
reply(from(localVersions.getVersionPath(args)));
});
ipc.on("get-linked-folders", async (req: IpcRequest<{ version: BSVersion; options?: { relative?: boolean } }>, reply) => {
ipc.on("full-version-path-to-relative", (args, reply) => {
const localVersions = BSLocalVersionService.getInstance();
reply(from(localVersions.getVersionPath(args.version).then(versionPath => path.relative(versionPath, args.fullPath))));
});
ipc.on("get-linked-folders", (args, reply) => {
const versionLinker = VersionFolderLinkerService.getInstance();
reply(from(versionLinker.getLinkedFolders(req.args.version, req.args.options)));
reply(from(versionLinker.getLinkedFolders(args.version, args.options)));
});
ipc.on("link-folder", async (req: IpcRequest<{ folder: string; options?: LinkOptions }>, reply) => {
req.args.options ??= {};
const linker = FolderLinkerService.getInstance();
const relativeMapsFolder = path.join(LocalMapsManagerService.LEVELS_ROOT_FOLDER, LocalMapsManagerService.CUSTOM_LEVELS_FOLDER);
if (req.args.folder.includes(relativeMapsFolder)) {
return reply(from(linker.linkFolder(req.args.folder, { keepContents: req.args.options?.keepContents, intermediateFolder: LocalMapsManagerService.SHARED_MAPS_FOLDER })));
}
if (req.args.folder.includes("UserData")) {
req.args.options = { ...req.args.options, backup: true };
}
const res = from(linker.linkFolder(req.args.folder, req.args.options));
const jsonIPAPath = path.join(req.args.folder, "Beat Saber IPA.json");
if (!(await pathExist(jsonIPAPath))) {
return reply(res);
}
await res.toPromise();
try {
const ipaData = (await readJSON(jsonIPAPath)) ?? ({} as any);
ipaData.YeetMods = false;
await writeJSON(jsonIPAPath, ipaData, { spaces: 4 });
} catch (e) {
log.error("Disable YeetMods", e);
}
reply(res);
});
ipc.on("link-version-folder-action", async (req: IpcRequest<VersionLinkerAction>, reply) => {
ipc.on("link-version-folder-action", (args, reply) => {
const versionLinker = VersionFolderLinkerService.getInstance();
reply(from(versionLinker.doAction(req.args)));
reply(from(versionLinker.doAction(args)));
});
ipc.on("is-version-folder-linked", async (req: IpcRequest<{ version: BSVersion; relativeFolder: string }>, reply) => {
ipc.on("is-version-folder-linked", (args, reply) => {
const versionLinker = VersionFolderLinkerService.getInstance();
reply(from(versionLinker.isFolderLinked(req.args.version, req.args.relativeFolder)));
reply(from(versionLinker.isFolderLinked(args.version, args.relativeFolder)));
});
ipc.on("unlink-folder", async (req: IpcRequest<{ folder: string; options?: LinkOptions }>, reply) => {
req.args.options ??= {};
const linker = FolderLinkerService.getInstance();
const relativeMapsFolder = path.join(LocalMapsManagerService.LEVELS_ROOT_FOLDER, LocalMapsManagerService.CUSTOM_LEVELS_FOLDER);
if (req.args.folder.includes(relativeMapsFolder)) {
return reply(from(linker.unlinkFolder(req.args.folder, { ...req.args.options, intermediateFolder: LocalMapsManagerService.SHARED_MAPS_FOLDER })));
}
if (req.args.folder.includes("UserData")) {
req.args.options = { ...req.args.options, backup: true };
}
reply(from(linker.unlinkFolder(req.args.folder, req.args.options)));
});
ipc.on("relink-all-versions-folders", async (req: IpcRequest<void>, reply) => {
ipc.on("relink-all-versions-folders", (_, reply) => {
const versionLinker = VersionFolderLinkerService.getInstance();
reply(from(versionLinker.relinkAllVersionsFolders()));
});
+2
View File
@@ -1,4 +1,5 @@
import "./os-controls-ipcs";
import "./bs-installer-ipcs.ts";
import "./bs-launcher-ipcs";
import "./bs-version-ipcs";
import "./bs-uninstall-ipcs";
@@ -12,3 +13,4 @@ import "./bs-playlist-ipcs";
import "./model-saber.ipcs";
import "./bs-model-ipcs";
import "./bs-version-download/bs-download-ipcs";
import "./static-configuration.ipcs";
+5 -13
View File
@@ -1,20 +1,12 @@
import { ipcMain } from "electron";
import { AutoUpdaterService } from "../services/auto-updater.service";
import { IpcRequest } from "shared/models/ipc";
import { UtilsService } from "../services/utils.service";
import { IpcService } from "../services/ipc.service";
import { from } from "rxjs";
import { from, of } from "rxjs";
const ipc = IpcService.getInstance();
ipcMain.on("download-update", async (event, request: IpcRequest<void>) => {
ipc.on("download-update", (_, reply) => {
const updaterService = AutoUpdaterService.getInstance();
const utilsService = UtilsService.getInstance();
updaterService
.downloadUpdate()
.then(res => utilsService.ipcSend(request.responceChannel, { success: res }))
.catch(() => utilsService.ipcSend(request.responceChannel, { success: false }));
reply(from(updaterService.downloadUpdate()));
});
ipc.on("check-update", (_, reply) => {
@@ -22,7 +14,7 @@ ipc.on("check-update", (_, reply) => {
reply(from(updaterService.isUpdateAvailable()));
});
ipcMain.on("install-update", async (event, request: IpcRequest<void>) => {
ipc.on("install-update", (_, reply) => {
const updaterService = AutoUpdaterService.getInstance();
updaterService.quitAndInstall();
reply(of(updaterService.quitAndInstall()));
});
+5 -16
View File
@@ -1,26 +1,15 @@
import { ipcMain } from "electron";
import { IpcRequest } from "shared/models/ipc";
import { ModelSaberService } from "../services/thrid-party/model-saber/model-saber.service";
import { UtilsService } from "../services/utils.service";
import { IpcService } from "../services/ipc.service";
import { MSGetQuery } from "shared/models/models/model-saber.model";
import { from } from "rxjs";
const ipc = IpcService.getInstance();
ipcMain.on("ms-get-model-by-id", async (event, request: IpcRequest<string | number>) => {
const utils = UtilsService.getInstance();
ipc.on("ms-get-model-by-id", (args, reply) => {
const ms = ModelSaberService.getInstance();
ms.getModelById(request.args)
.then(model => {
utils.ipcSend(request.responceChannel, { success: true, data: model });
})
.catch(e => {
utils.ipcSend(request.responceChannel, { success: false, error: e });
});
reply(from(ms.getModelById(args)));
});
ipc.on<MSGetQuery>("search-models", async (req, reply) => {
ipc.on("search-models", async (args, reply) => {
const ms = ModelSaberService.getInstance();
reply(ms.searchModels(req.args));
reply(ms.searchModels(args));
});
+47 -32
View File
@@ -1,59 +1,74 @@
import { ipcMain, shell, dialog, app, BrowserWindow } from "electron";
import { UtilsService } from "../services/utils.service";
import { IpcRequest } from "shared/models/ipc";
import { SystemNotificationOptions } from "shared/models/notification/system-notification.model";
import { shell, dialog, app, BrowserWindow } from "electron";
import { NotificationService } from "../services/notification.service";
import { SteamService } from "../services/steam.service";
import { IpcService } from "../services/ipc.service";
import { from, of } from "rxjs";
import { readFileSync } from "fs-extra";
import log from "electron-log";
// TODO IMPROVE WINDOW CONTROL BY USING WINDOW SERVICE
const ipc = IpcService.getInstance();
ipcMain.on("new-window", async (event, request: IpcRequest<string>) => {
shell.openExternal(request.args);
ipc.on("new-window", (args, reply) => {
reply(from(shell.openExternal(args)));
});
ipc.on<string>("choose-folder", async (req, reply) => {
reply(from(dialog.showOpenDialog({ properties: ["openDirectory"], defaultPath: req.args ?? "" })));
ipc.on("choose-folder", (args, reply) => {
reply(from(dialog.showOpenDialog({ properties: ["openDirectory"], defaultPath: args ?? "" })));
});
ipcMain.on("window.progression", async (event, request: IpcRequest<number>) => {
BrowserWindow.fromWebContents(event.sender)?.setProgressBar(request.args / 100);
ipc.on("choose-file", async (args, reply) => {
reply(from(dialog.showOpenDialog({ properties: ["openFile"], defaultPath: args ?? "" })));
});
ipcMain.on("save-file", async (event, request: IpcRequest<{ filename?: string; filters?: Electron.FileFilter[] }>) => {
dialog.showSaveDialog({ properties: ["showOverwriteConfirmation"], defaultPath: request.args.filename, filters: request.args.filters }).then(res => {
const utils = UtilsService.getInstance();
ipc.on("window.progression",(args, reply, sender) => {
BrowserWindow.fromWebContents(sender)?.setProgressBar(args / 100);
reply(of(undefined));
});
ipc.on("save-file", (args, reply) => {
reply(from(dialog.showSaveDialog({ properties: ["showOverwriteConfirmation"], defaultPath: args.filename, filters: args.filters }).then(res => {
if (res.canceled || !res.filePath) {
utils.ipcSend(request.responceChannel, { success: false });
throw new Error("No file path selected");
}
UtilsService.getInstance().ipcSend(request.responceChannel, { success: true, data: res.filePath });
});
return res.filePath;
})));
});
ipc.on("current-version", (_, reply) => {
reply(of(app.getVersion()));
});
ipcMain.on("open-logs", async (event, request: IpcRequest<void>) => {
shell.openPath(app.getPath("logs"));
ipc.on("open-logs", (_, reply) => {
reply(from(shell.openPath(app.getPath("logs"))));
});
ipcMain.on("notify-system", async (event, request: IpcRequest<SystemNotificationOptions>) => {
NotificationService.getInstance().notify(request.args);
ipc.on("notify-system", (args, reply) => {
const systemNotification = NotificationService.getInstance();
reply(of(systemNotification.notify(args)));
});
ipcMain.on("open-steam", async (event, request: IpcRequest<void>) => {
const steam = SteamService.getInstance();
const utils = UtilsService.getInstance();
steam
.openSteam()
.then(res => {
utils.ipcSend(request.responceChannel, { success: true, data: res });
})
.catch(e => {
utils.ipcSend(request.responceChannel, { success: false, error: e });
});
ipc.on("view-path-in-explorer", (args, reply) => {
reply(of(shell.showItemInFolder(args)));
});
ipc.on("choose-image", (args, reply) => {
reply(from(dialog.showOpenDialog({ properties: ["openFile", "multiSelections"], filters: [{ name: "Images", extensions: ["jpg", "png", "jpeg"] }] }).then(res => {
if (res.canceled || !res.filePaths) {
return [];
}
if(args.base64){
return res.filePaths.map(path => Buffer.from(readFileSync(path)).toString("base64"));
}
return res.filePaths;
})));
});
ipc.on("restart-app", (_, reply) => {
log.info("App was requested to restart");
reply(of()); // Reply before restarting to avoid any issue
app.relaunch();
app.quit();
});
@@ -0,0 +1,14 @@
import { of } from "rxjs";
import { IpcService } from "../services/ipc.service";
import { StaticConfigurationService } from "../services/static-configuration.service";
const ipc = IpcService.getInstance();
const staticConfig = StaticConfigurationService.getInstance();
ipc.on("static-configuration.get", (args, reply) => {
reply(of(staticConfig.get(args)));
});
ipc.on("static-configuration.set", (args, reply) => {
reply(of(staticConfig.set(args.key, args.value)));
});
+6 -14
View File
@@ -1,18 +1,10 @@
import { ipcMain } from "electron";
import { SupportersService } from "../services/supporters.service";
import { IpcRequest } from "shared/models/ipc";
import { UtilsService } from "../services/utils.service";
import { IpcService } from "../services/ipc.service";
import { from } from "rxjs";
ipcMain.on("get-supporters", (event, request: IpcRequest<void>) => {
const utils = UtilsService.getInstance();
const ipc = IpcService.getInstance();
ipc.on("get-supporters", (_, reply) => {
const supportersService = SupportersService.getInstance();
supportersService
.getSupporters()
.then(supporters => {
utils.ipcSend(request.responceChannel, { success: true, data: supporters });
})
.catch(() => {
utils.ipcSend(request.responceChannel, { success: false });
});
reply(from(supportersService.getSupporters()));
});
+15 -16
View File
@@ -1,40 +1,39 @@
import { WindowManagerService } from "../services/window-manager.service";
import { AppWindow } from "shared/models/window-manager/app-window.model";
import { IpcService } from "../services/ipc.service";
import { from } from "rxjs";
import { BrowserWindow, ipcMain } from "electron";
import { from, of } from "rxjs";
import { BrowserWindow } from "electron";
const ipc = IpcService.getInstance();
// Native windows control, do not pass through IPC service
ipcMain.on("close-window", async (event) => {
BrowserWindow.fromWebContents(event.sender)?.close();
ipc.on("close-window", (_, reply, sender) => {
reply(of(BrowserWindow.fromWebContents(sender)?.close()));
});
ipcMain.on("maximise-window", async (event) => {
BrowserWindow.fromWebContents(event.sender)?.maximize();
ipc.on("maximise-window", (_, reply, sender) => {
reply(of(BrowserWindow.fromWebContents(sender)?.maximize()));
});
ipcMain.on("minimise-window", async (event) => {
BrowserWindow.fromWebContents(event.sender)?.minimize();
ipc.on("minimise-window", (_, reply, sender) => {
reply(of(BrowserWindow.fromWebContents(sender)?.minimize()));
});
ipcMain.on("unmaximise-window", async (event) => {
BrowserWindow.fromWebContents(event.sender)?.unmaximize();
ipc.on("unmaximise-window", (_, reply, sender) => {
reply(of(BrowserWindow.fromWebContents(sender)?.unmaximize()));
});
ipc.on<AppWindow>("open-window-then-close-all", (req, reply) => {
ipc.on("open-window-then-close-all", (args, reply) => {
const windowManager = WindowManagerService.getInstance();
const res = windowManager.openWindow(req.args).then(() => {
windowManager.closeAllWindows(req.args);
const res = windowManager.openWindow(args).then(() => {
windowManager.closeAllWindows(args);
});
reply(from(res));
});
ipc.on<AppWindow>("open-window-or-focus", (req, reply) => {
ipc.on("open-window-or-focus", (args, reply) => {
const windowManager = WindowManagerService.getInstance();
reply(from(windowManager.openWindowOrFocus(req.args)));
reply(from(windowManager.openWindowOrFocus(args)));
});
+171 -22
View File
@@ -13,7 +13,7 @@ import "./ipcs";
import { WindowManagerService } from "./services/window-manager.service";
import { DeepLinkService } from "./services/deep-link.service";
import { AppWindow } from "shared/models/window-manager/app-window.model";
import { LocalMapsManagerService } from "./services/additional-content/local-maps-manager.service";
import { LocalMapsManagerService } from "./services/additional-content/maps/local-maps-manager.service";
import { LocalPlaylistsManagerService } from "./services/additional-content/local-playlists-manager.service";
import { LocalModelsManagerService } from "./services/additional-content/local-models-manager.service";
import { APP_NAME } from "./constants";
@@ -21,17 +21,31 @@ import { BSLauncherService } from "./services/bs-launcher/bs-launcher.service";
import { IpcRequest } from "shared/models/ipc";
import { LivShortcut } from "./services/liv/liv-shortcut.service";
import { SteamLauncherService } from "./services/bs-launcher/steam-launcher.service";
import { FileAssociationService } from "./services/file-association.service";
import { SongDetailsCacheService } from "./services/additional-content/maps/song-details-cache.service";
import { readdirSync, statSync, unlinkSync } from "fs-extra";
import { StaticConfigurationService } from "./services/static-configuration.service";
const isDebug = process.env.NODE_ENV === "development" || process.env.DEBUG_PROD === "true";
const isE2E = process.env.E2E_BUILD === "true";
const staticConfig = StaticConfigurationService.getInstance();
log.transports.file.level = "info";
log.transports.file.resolvePath = () => {
const now = new Date();
return path.join(app.getPath("logs"), `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}-v${app.getVersion()}.log`);
};
export const filterStrings = new Set<string>();
export const filterPatterns = new Set<RegExp>();
// Filter all occulus tokens
filterPatterns.add(/FRL\S{10,}/g);
initLogger();
deleteOlestLogs();
deleteOldLogs();
staticConfig.take("disable-hadware-acceleration", disabled => {
if(disabled === true){ // strictly check for true
log.info("Disabling hardware acceleration");
app.disableHardwareAcceleration();
}
});
log.catchErrors();
if (process.env.NODE_ENV === "production") {
const sourceMapSupport = require("source-map-support");
@@ -55,7 +69,7 @@ const installExtensions = async () => {
.catch(log.error);
};
const createWindow = async (window: AppWindow) => {
const createWindow = async (window: AppWindow = "launcher.html") => {
if (isDebug) {
await installExtensions();
}
@@ -68,6 +82,15 @@ const initServicesMustBeInitialized = () => {
LocalModelsManagerService.getInstance();
LivShortcut.getInstance();
BSLauncherService.getInstance();
SongDetailsCacheService.getInstance();
}
const findDeepLinkInArgs = (args: string[]): string => {
return args.find(arg => DeepLinkService.getInstance().isDeepLink(arg));
}
const findAssociatedFileInArgs = (args: string[]): string => {
return args.find(arg => FileAssociationService.getInstance().isFileAssociated(arg));
}
const gotTheLock = app.requestSingleInstanceLock();
@@ -76,13 +99,15 @@ if (!gotTheLock) {
app.quit();
} else {
app.on("second-instance", (_, argv) => {
const deepLink = argv.find(arg => DeepLinkService.getInstance().isDeepLink(arg));
const deepLink = findDeepLinkInArgs(argv);
const associatedFile = findAssociatedFileInArgs(argv);
if (!deepLink) {
return;
if (deepLink) {
DeepLinkService.getInstance().dispatchLinkOpened(deepLink);
} else if (associatedFile) {
FileAssociationService.getInstance().handleFileAssociation(associatedFile);
}
DeepLinkService.getInstance().dispatchLinkOpened(deepLink);
});
app.on("window-all-closed", () => {
@@ -91,25 +116,149 @@ if (!gotTheLock) {
})
app.whenReady().then(() => {
app.setAppUserModelId(APP_NAME);
initServicesMustBeInitialized();
const deepLink = process.argv.find(arg => DeepLinkService.getInstance().isDeepLink(arg));
if (!deepLink) {
createWindow(!isE2E ? "launcher.html" : "index.html");
} else {
const deepLink = findDeepLinkInArgs(process.argv);
const associatedFile = findAssociatedFileInArgs(process.argv);
if (deepLink) {
DeepLinkService.getInstance().dispatchLinkOpened(deepLink);
} else if (associatedFile) {
FileAssociationService.getInstance().handleFileAssociation(associatedFile);
} else {
createWindow();
}
SteamLauncherService.getInstance().restoreSteamVR();
// Log renderer errors
ipcMain.on("log-error", (_, args: IpcRequest<unknown>) => {
log.error(args?.args);
});
ipcMain.on("add-filter-string", (_, args: IpcRequest<string>) => {
filterStrings.add(args?.args);
});
ipcMain.on("add-filter-pattern", (_, args: IpcRequest<string>) => {
filterPatterns.add(new RegExp(args?.args));
});
}).catch(log.error);
}
function initLogger(){
log.transports.file.level = "info";
log.transports.file.resolvePath = () => {
const now = new Date();
return path.join(app.getPath("logs"), `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}-v${app.getVersion()}.log`);
};
log.hooks.push((message) => {
const filterMessage = (filter: string|RegExp, ...param: unknown[]): unknown[] => {
return param.map(data => {
if(typeof data === "string"){
return data.replaceAll(filter, "****");
}
if(data instanceof Error){
data.message = data.message?.replaceAll(filter, "****");
data.stack = data.stack?.replaceAll(filter, "****");
}
if(data instanceof Array){
return filterMessage(filter, ...data);
}
return data;
});
}
filterStrings.forEach(filter => {
if(filter && message.data.length){
message.data = filterMessage(filter, ...message.data);
}
});
filterPatterns.forEach(filter => {
if(filter && message.data.length){
message.data = filterMessage(filter, ...message.data);
}
});
return message;
});
log.catchErrors();
}
function getLogFilesEntries() {
try {
const logsFolder = app.getPath("logs");
let logs = readdirSync(logsFolder, { withFileTypes: true });
logs = logs.filter(file => file.isFile() && path.extname(file.name) === ".log");
logs.sort((a, b) => {
const aStat = statSync(path.join(logsFolder, a.name));
const bStat = statSync(path.join(logsFolder, b.name));
return bStat.mtime.getTime() - aStat.mtime.getTime();
});
return logs.map(file => {
const filePath = path.join(logsFolder, file.name);
const stat = statSync(filePath);
return {
path: filePath,
name: file.name,
stats: stat
};
});
} catch (err) {
log.error('Error while retrieving log files entries:', err);
return [];
}
}
// keep only the last 5 logs
function deleteOldLogs(): void{
try {
let logs = getLogFilesEntries();
logs = logs.slice(5);
logs.forEach(file => {
try {
unlinkSync(file.path);
log.info(`Deleted log file: ${file.path}`);
} catch (err) {
log.error(`Error deleting file ${file.path}:`, err);
}
});
} catch (err) {
log.error("Error while deleting old logs:", err);
}
}
// Temporary function to delete logs before 2024-07-31
function deleteOlestLogs(): void{
// delete all logs before 2024-07-31
const date = new Date(2024, 6, 31); // month is 0-based
const logs = getLogFilesEntries().filter(file => file.stats.mtime.getTime() < date.getTime());
logs.forEach(file => {
try {
unlinkSync(file.path);
log.info(`Deleted log file: ${file.path}`);
} catch (err) {
log.error(`Error deleting file ${file.path}:`, err);
}
});
}
+5 -5
View File
@@ -36,8 +36,7 @@ export class Archive {
public addDirectory(path: string, destPath?: string | false): void {
this.directories.push(path);
destPath = destPath === false ? false : _path.basename(path);
this.archive.directory(path, destPath);
this.archive.directory(path, destPath ?? _path.basename(path));
}
public addFile(path: string, destPath?: string): void {
@@ -46,13 +45,14 @@ export class Archive {
this.archive.file(path, { name: destPath });
}
public finalize(): Observable<Progression> {
const progress: Progression = {
public finalize(): Observable<Progression<string>> {
const progress: Progression<string> = {
total: 0,
current: 0,
data: this.output,
};
return new Observable<Progression>(observer => {
return new Observable<Progression<string>>(observer => {
(async () => {
progress.total = await this.loadTotalFiles();

Some files were not shown because too many files have changed in this diff Show More