├── .editorconfig ├── .github ├── dependabot.yml └── workflows │ ├── merge-conflict-auto-label.yml │ ├── push-test.yml │ └── release.yml ├── .gitignore ├── .vscode ├── extensions.json └── tasks.json ├── LICENSE ├── README.md ├── docs ├── DEV-TOOLS.md ├── DEVELOPMENT.md ├── FAQ.md ├── TROUBLESHOOTING.md ├── assets │ ├── Square310x310Logo.png │ ├── dev-view-screenshot.png │ ├── downloadbutton.png │ ├── flightcore-webview2-windows-error-message.png │ ├── flightcore.svg │ ├── main-window-screenshot.png │ └── webview2-download-screenshot.png └── index.html ├── package-lock.json ├── package.json ├── scripts ├── check_version_numbers.py └── create-release-file.py ├── src-tauri ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── bindings │ ├── CommitHead.ts │ ├── FlightCoreVersion.ts │ ├── InstallProgress.ts │ ├── InstallState.ts │ ├── InstallType.ts │ ├── NorthstarLaunchOptions.ts │ ├── NorthstarMod.ts │ ├── NorthstarThunderstoreRelease.ts │ ├── NorthstarThunderstoreReleaseWrapper.ts │ ├── Project.ts │ ├── PullRequestType.ts │ ├── PullsApiResponseElement.ts │ ├── ReleaseInfo.ts │ ├── Repo.ts │ ├── Tag.ts │ ├── TagWrapper.ts │ ├── ThunderstoreMod.ts │ └── ThunderstoreModVersion.ts ├── build.rs ├── capabilities │ ├── default.json │ └── desktop.json ├── icons │ ├── 128x128.png │ ├── 128x128@2x.png │ ├── 32x32.png │ ├── Square107x107Logo.png │ ├── Square142x142Logo.png │ ├── Square150x150Logo.png │ ├── Square284x284Logo.png │ ├── Square30x30Logo.png │ ├── Square310x310Logo.png │ ├── Square44x44Logo.png │ ├── Square71x71Logo.png │ ├── Square89x89Logo.png │ ├── StoreLogo.png │ ├── icon.icns │ ├── icon.ico │ └── icon.png ├── src │ ├── constants.rs │ ├── development │ │ └── mod.rs │ ├── github │ │ ├── mod.rs │ │ ├── pull_requests.rs │ │ └── release_notes.rs │ ├── lib.rs │ ├── main.rs │ ├── mod_management │ │ ├── legacy.rs │ │ ├── mod.rs │ │ └── plugins.rs │ ├── northstar │ │ ├── install.rs │ │ ├── mod.rs │ │ └── profile.rs │ ├── platform_specific │ │ ├── linux.rs │ │ ├── mod.rs │ │ └── windows.rs │ ├── repair_and_verify │ │ └── mod.rs │ ├── thunderstore │ │ └── mod.rs │ └── util.rs └── tauri.conf.json └── src-vue ├── .gitignore ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── src ├── App.vue ├── assets │ ├── 1009235.jpg │ ├── mp_colony020033.jpg │ ├── thunderstore-icon.png │ └── wallpaperflare.com_wallpaper.jpg ├── components │ ├── InstallProgressBar.vue │ ├── LanguageSelector.vue │ ├── LocalModCard.vue │ ├── ModsMenu.vue │ ├── NotificationButton.vue │ ├── PlayButton.vue │ ├── PullRequestsSelector.vue │ └── ThunderstoreModCard.vue ├── i18n │ └── lang │ │ ├── da.json │ │ ├── de.json │ │ ├── en.json │ │ ├── es.json │ │ ├── fr.json │ │ ├── it.json │ │ ├── pl.json │ │ ├── ru.json │ │ └── zh_Hans.json ├── main.ts ├── plugins │ ├── modules │ │ ├── notifications.ts │ │ ├── pull_requests.ts │ │ └── search.ts │ └── store.ts ├── style.css ├── utils │ ├── GameInstall.ts │ ├── NorthstarState.ts │ ├── ReleaseCanal.ts │ ├── SortOptions.d.ts │ ├── Tabs.ts │ ├── filter.ts │ ├── thunderstore │ │ ├── ThunderstoreModStatus.ts │ │ └── version.ts │ └── ui.ts ├── views │ ├── ChangelogView.vue │ ├── DeveloperView.vue │ ├── ModsView.vue │ ├── PlayView.vue │ ├── RepairView.vue │ ├── SettingsView.vue │ └── mods │ │ ├── LocalModsView.vue │ │ └── ThunderstoreModsView.vue ├── vite-env.d.ts └── vuex-shim.d.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | # For more info on `.editorconfig` file see https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*.{rs,ts,vue,css}] 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | indent_style = space 11 | indent_size = 4 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Configures dependabot 2 | 3 | version: 2 4 | updates: 5 | # Root NPM package 6 | - package-ecosystem: 'npm' 7 | directory: '/' 8 | schedule: 9 | interval: "monthly" 10 | commit-message: 11 | prefix: "chore: " 12 | 13 | # NPM packages 14 | - package-ecosystem: 'npm' 15 | directory: '/src-vue' 16 | schedule: 17 | interval: "monthly" 18 | commit-message: 19 | prefix: "chore: " 20 | 21 | # Rust crates 22 | - package-ecosystem: 'cargo' 23 | directory: '/src-tauri' 24 | schedule: 25 | interval: "monthly" 26 | commit-message: 27 | prefix: "chore: " 28 | -------------------------------------------------------------------------------- /.github/workflows/merge-conflict-auto-label.yml: -------------------------------------------------------------------------------- 1 | name: Merge Conflict Auto Label 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | triage: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: mschilde/auto-label-merge-conflicts@master 12 | with: 13 | CONFLICT_LABEL_NAME: "merge conflicts" 14 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 15 | MAX_RETRIES: 5 16 | WAIT_MS: 5000 17 | -------------------------------------------------------------------------------- /.github/workflows/push-test.yml: -------------------------------------------------------------------------------- 1 | name: "test-on-push" 2 | on: 3 | push: 4 | pull_request: 5 | schedule: 6 | - cron: "0 0 * * 0" # Run weekly to cover rust toolchain updates 7 | 8 | jobs: 9 | # Ensure version numbers in various places match up 10 | ensure-same-version: 11 | runs-on: ubuntu-22.04 12 | steps: 13 | - uses: actions/checkout@v4 14 | - name: install dependencies 15 | run: | 16 | pip install toml 17 | - name: Run check 18 | run: | 19 | python3 scripts/check_version_numbers.py 20 | 21 | # Ensure correct Rust code formatting 22 | formatting: 23 | name: format-check 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: actions/checkout@v4 27 | - uses: dtolnay/rust-toolchain@stable 28 | with: 29 | toolchain: stable 30 | components: rustfmt 31 | - name: Format check 32 | run: cargo fmt --manifest-path src-tauri/Cargo.toml --all -- --check 33 | 34 | clippy: 35 | strategy: 36 | fail-fast: false 37 | matrix: 38 | platform: [ubuntu-22.04, windows-latest] 39 | 40 | name: clippy-check 41 | runs-on: ${{ matrix.platform }} 42 | steps: 43 | - uses: actions/checkout@v4 44 | - uses: dtolnay/rust-toolchain@stable 45 | with: 46 | toolchain: stable 47 | components: clippy 48 | - name: install dependencies (ubuntu only) 49 | if: matrix.platform == 'ubuntu-22.04' 50 | run: | 51 | sudo apt-get update 52 | sudo apt-get install -y libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev 53 | - name: Create dist folder (Ubuntu only) 54 | if: matrix.platform == 'ubuntu-22.04' 55 | run: mkdir --parent src-vue/dist 56 | - name: Create dist folder (Windows only) 57 | if: matrix.platform == 'windows-latest' 58 | run: New-Item -ItemType Directory -Force -Path "src-vue\dist" 59 | - name: Run clippy 60 | run: cargo clippy --manifest-path src-tauri/Cargo.toml -- --no-deps --deny warnings 61 | 62 | # Ensure committed bindings correct 63 | autogen-ts-bindings-check: 64 | runs-on: ubuntu-22.04 65 | steps: 66 | - uses: actions/checkout@v4 67 | - uses: dtolnay/rust-toolchain@stable 68 | with: 69 | toolchain: stable 70 | - name: install dependencies (ubuntu only) 71 | run: | 72 | sudo apt-get update 73 | sudo apt-get install -y libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev 74 | 75 | - name: Move original TypeScript bindings 76 | run: | 77 | cp -r src-tauri/bindings original-bindings 78 | rm -r src-tauri/bindings 79 | 80 | - name: Create empty dist folder # Otherwise tests fail 81 | run: mkdir src-vue/dist 82 | 83 | - name: Run Tests 84 | run: cargo test --manifest-path src-tauri/Cargo.toml 85 | 86 | - name: Compare TypeScript Bindings 87 | run: | 88 | diff -r src-tauri/bindings original-bindings 89 | if [[ $? -ne 0 ]]; then 90 | echo "Generated bindings are different from committed bindings" 91 | exit 1 92 | fi 93 | 94 | test-tauri: 95 | needs: ensure-same-version 96 | strategy: 97 | fail-fast: false 98 | matrix: 99 | platform: [ubuntu-22.04, windows-latest] 100 | 101 | runs-on: ${{ matrix.platform }} 102 | steps: 103 | - uses: actions/checkout@v4 104 | - name: setup node 105 | uses: actions/setup-node@v4 106 | with: 107 | node-version: 18 108 | - uses: dtolnay/rust-toolchain@stable 109 | with: 110 | toolchain: stable 111 | - name: install dependencies (ubuntu only) 112 | if: matrix.platform == 'ubuntu-22.04' 113 | run: | 114 | sudo apt-get update 115 | sudo apt-get install -y libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev 116 | - name: Disable self-updater 117 | shell: bash 118 | run: | 119 | jq 'del(.plugins.updater)' src-tauri/tauri.conf.json | jq 'del(.bundle.createUpdaterArtifacts)' > src-tauri/tauri.conf.json.new 120 | rm src-tauri/tauri.conf.json 121 | mv src-tauri/tauri.conf.json.new src-tauri/tauri.conf.json 122 | - uses: Swatinem/rust-cache@v2 # Cache Rust build artifacts 123 | with: 124 | workspaces: | 125 | src-tauri 126 | - name: install app dependencies and build it 127 | env: 128 | TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} 129 | run: | 130 | npm clean-install 131 | cd src-vue && npm clean-install && cd .. 132 | npm run tauri build 133 | - uses: tauri-apps/tauri-action@v0 134 | env: 135 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 136 | TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} 137 | - name: Upload Linux artifact 138 | if: matrix.platform == 'ubuntu-22.04' 139 | uses: actions/upload-artifact@v4 140 | with: 141 | name: linux-artifacts 142 | path: | 143 | src-tauri/target/release/bundle/appimage/* 144 | - name: Upload Linux AppImage 145 | if: matrix.platform == 'ubuntu-22.04' 146 | uses: actions/upload-artifact@v4 147 | with: 148 | name: linux-appimage 149 | path: | 150 | src-tauri/target/release/bundle/appimage/*.AppImage 151 | - name: Upload Windows artifact 152 | if: matrix.platform == 'windows-latest' 153 | uses: actions/upload-artifact@v4 154 | with: 155 | name: windows-artifacts 156 | path: | 157 | src-tauri/target/release/bundle/msi/* 158 | src-tauri/target/release/app.pdb 159 | - name: Additionally upload Windows installer separately 160 | if: matrix.platform == 'windows-latest' 161 | uses: actions/upload-artifact@v4 162 | with: 163 | name: windows-msi 164 | path: | 165 | src-tauri/target/release/bundle/msi/*.msi 166 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: "release" 2 | on: 3 | push: 4 | tags: 5 | - 'v*' 6 | 7 | permissions: 8 | contents: write # Needed to write to GitHub draft release 9 | 10 | jobs: 11 | # Ensure version numbers in various places match up 12 | ensure-same-version: 13 | runs-on: ubuntu-22.04 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: install dependencies 17 | run: | 18 | pip install toml 19 | - name: Run check 20 | run: | 21 | python3 scripts/check_version_numbers.py --release ${{github.ref_name}} 22 | 23 | build: 24 | needs: ensure-same-version 25 | strategy: 26 | fail-fast: false 27 | matrix: 28 | platform: [ubuntu-22.04, windows-latest] 29 | 30 | runs-on: ${{ matrix.platform }} 31 | steps: 32 | - uses: actions/checkout@v4 33 | - name: setup node 34 | uses: actions/setup-node@v4 35 | with: 36 | node-version: 18 37 | - name: install Rust stable 38 | uses: dtolnay/rust-toolchain@stable 39 | with: 40 | toolchain: stable 41 | - name: install dependencies (ubuntu only) 42 | if: matrix.platform == 'ubuntu-22.04' 43 | run: | 44 | sudo apt-get update 45 | sudo apt-get install -y libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev 46 | - uses: Swatinem/rust-cache@v2 # Cache Rust build artifacts 47 | with: 48 | workspaces: | 49 | src-tauri 50 | - name: install app dependencies and build it 51 | env: 52 | TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} 53 | run: | 54 | npm clean-install 55 | cd src-vue && npm clean-install && cd .. 56 | npm run tauri build 57 | - uses: tauri-apps/tauri-action@v0 58 | env: 59 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 60 | TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} 61 | - name: upload build artifact (windows) 62 | if: matrix.platform == 'windows-latest' 63 | uses: actions/upload-artifact@v4 64 | with: 65 | name: windows-artifacts 66 | path: | 67 | src-tauri/target/release/bundle/msi/*msi* 68 | src-tauri/target/release/flightcore.pdb 69 | - name: upload build artifact (linux) 70 | if: matrix.platform == 'ubuntu-22.04' 71 | uses: actions/upload-artifact@v4 72 | with: 73 | name: linux-artifacts 74 | path: | 75 | src-tauri/target/release/bundle/appimage/*AppImage* 76 | - name: Install sentry-cli (Windows only) 77 | if: matrix.platform == 'windows-latest' 78 | run: | 79 | curl --location --output sentry-cli.exe "https://release-registry.services.sentry.io/apps/sentry-cli/latest?response=download&arch=x86_64&platform=Windows&package=sentry-cli" 80 | - name: Run sentry-cli to upload pdb (Windows only) 81 | if: matrix.platform == 'windows-latest' 82 | env: 83 | SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} 84 | SENTRY_ORG: northstar-kv 85 | SENTRY_PROJECT: flightcore 86 | run: | 87 | ./sentry-cli.exe upload-dif --wait src-tauri/target/release/flightcore.pdb 88 | - name: Release 89 | uses: softprops/action-gh-release@v1 90 | with: 91 | draft: true 92 | files: | 93 | src-tauri/target/release/bundle/appimage/*AppImage* 94 | src-tauri/target/release/bundle/msi/*msi* 95 | 96 | create-release-file: 97 | needs: build 98 | runs-on: ubuntu-22.04 99 | steps: 100 | - uses: actions/checkout@v4 101 | - uses: actions/download-artifact@v4 102 | - name: Create release file 103 | run: | 104 | ls -al 105 | ls -al linux-artifacts/ 106 | ls -al windows-artifacts/ 107 | ls -al windows-artifacts/bundle/ 108 | ls -al windows-artifacts/bundle/msi/ 109 | python3 scripts/create-release-file.py --version ${{github.ref_name}} 110 | 111 | - name: upload release file 112 | uses: softprops/action-gh-release@v1 113 | with: 114 | draft: true 115 | files: | 116 | latest-release.json 117 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node modules 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "tauri-apps.tauri-vscode", 4 | "rust-lang.rust-analyzer", 5 | "vue.volar" 6 | ] 7 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "tauri dev", 8 | "type": "shell", 9 | "command": "npm", 10 | "args": [ 11 | "run", 12 | "tauri", 13 | "dev" 14 | ], 15 | "group": { 16 | "kind": "build", 17 | "isDefault": true 18 | } 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 R2NorthstarTools 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
4 |
5 | 6 |
7 |

8 | 9 | # FlightCore 10 | 11 | A [Northstar](https://northstar.tf/) installer, updater, and mod-manager 12 | 13 | ![FlightCore screenshot](docs/assets/main-window-screenshot.png) 14 | 15 | ## Install 16 | 17 | Downloads are available on the [releases page](https://github.com/R2NorthstarTools/FlightCore/releases). 18 | 19 | **Windows:** Download `FlightCore_X.Y.Z_x64_en-US.msi` and then run the installer by double-clicking the file. 20 | 21 | **Linux:** Download `flight-core_X.Y.Z_amd64.AppImage`, put it in a preferred location and make it executable. A Flatpak version is planned for the future. 22 | 23 | All versions of FlightCore feature an auto-updater that will ask to self-update on new releases. 24 | 25 | GitHub release (latest by date) 26 | GitHub release downloads (latest by date) 27 | 28 | Translation status 29 | 30 | 31 | ## Frequently Asked Questions (FAQ) 32 | 33 | Answers to frequently asked questions can be found in [docs/FAQ.md](docs/FAQ.md) 34 | 35 | ## Development 36 | 37 | If you'd like to contribute to FlightCore, see [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) 38 | 39 | If you are a Northstar developer/contributor, you might want to look at [docs/DEV-TOOLS.md](docs/DEV-TOOLS.md) 40 | 41 | ### Translating 42 | 43 | Translations can be submitted via [weblate](https://translate.harmony.tf/projects/northstar/flightcore/). \ 44 | If you want to add translations for a new language that does not exist in FlightCore yet, please [reach out via GitHub issues](https://github.com/R2NorthstarTools/FlightCore/issues/new) so that we can add support for it. 45 | 46 | 47 | Translation status 48 | 49 | 50 | ## Roadmap 51 | 52 | --> See https://github.com/R2NorthstarTools/FlightCore/issues/1 53 | -------------------------------------------------------------------------------- /docs/DEV-TOOLS.md: -------------------------------------------------------------------------------- 1 | # Dev tools 2 | 3 | ![dev view screenshot](assets/dev-view-screenshot.png) 4 | 5 | FlightCore features a hidden view that contains development features. 6 | 7 | It's targetted at both Northstar and FlightCore contributors. Among other things it contains buttons for unreleased features in FlightCore and tools to help with Northstar development. 8 | 9 | To activate it, spam click the FlightCore version number in the settings view at least 6 times. After that a new entry named _DEV_ should appear in the menubar. 10 | 11 | ## Northstar 12 | 13 | ### Pull request install 14 | 15 | The dev view offers a way to install pull request from the [NorthstarLauncher](https://github.com/R2Northstar/NorthstarLauncher) and [NorthstarMods](https://github.com/R2Northstar/NorthstarMods) repositories. 16 | 17 | Launcher pull requests overwrite `NorthstarLauncher.exe` and `Northstar.dll`. 18 | 19 | Mod pull requests install into a separate profile called `R2Northstar-PR-test-managed-folder`. \ 20 | When installing a mods PR, FlightCore will place `r2ns-launch-mod-pr-version.bat` into your Titanfall2 directory that can be used to run that PR profile directly. \ 21 | The batch file simply runs `NorthstarLauncher.exe -profile=R2Northstar-PR-test-managed-folder` 22 | 23 | 24 | ## FlightCore 25 | 26 | The dev view contains various buttons that call functions that might not be fully implemented or tested yet. 27 | 28 | Additionally it has some buttons for testing like the _Panic button_ which force crashes the application to test automatic log uploading on crash among other things. 29 | -------------------------------------------------------------------------------- /docs/FAQ.md: -------------------------------------------------------------------------------- 1 | # FAQ 2 | 3 | ## What is FlightCore? 4 | 5 | FlightCore is a Northstar installer, updater, and mod-manager for Northstar? 6 | 7 | You can use it to easily install and update Northstar as well as for installing, updating, and managing mods for Northstar. 8 | 9 | ## What is Northstar? 10 | 11 | Northstar is a modding and custom server framework for Titanfall2. 12 | 13 | You use it to do stuff like 14 | 15 | - [this](https://www.youtube.com/watch?v=en06Y6CPMQg) 16 | - [or this](https://www.youtube.com/watch?v=suhBGqzDbNA) 17 | - [or this](https://www.youtube.com/watch?v=vyUxAwobY60) 18 | 19 | ## I have an issue with FlightCore, where do I go? 20 | 21 | Check [TROUBLESHOOTING.md](TROUBLESHOOTING.md). 22 | 23 | ## Why yet another Northstar intaller/updater/mod-manager instead of contributing to an existing one? 24 | 25 | The 3 main GUI tools for handling such tasks with Norhtstar are 26 | 27 | - [r2modman](https://github.com/ebkr/r2modmanPlus) 28 | - [Viper](https://github.com/0neGal/viper) 29 | - [VTOL](https://github.com/BigSpice/VTOL) 30 | 31 | while they get most of the work done, each of them has their own problem. 32 | 33 | - **r2modman** has not too great UX and given that it also has to support other games there's not a(n easy) way to quickly add new features specific to Northstar 34 | - **Viper** probably has the best UX but is missing features such as Origin process runtime detection (to avoid LSX errors) and lacks the ability to install Northstar from Thunderstore. 35 | - **VTOL** has recently undergone a rewrite that removes a lot of older issues (such as requiring to be run as admin), however it is Windows exclusive and requires installing an additional library not shipped directly with the application, confusing some users. It also has a lot of edge case handling that while giving a smoother user experience blows up code base complexity. 36 | 37 | With that said, FlightCore is not written from scratch. For handling Northstar specific logic, functions are re-used from the CLI-only Northstar installer called [papa](https://github.com/AnActualEmerald/papa) by making use of the underlying library [libthermite](https://crates.io/crates/libthermite). 38 | 39 | The plan is to upstream any changes to `libthermite` so that it can be re-used by any other Rust-based Northstar installer. 40 | 41 | ## I'd like to contribute to FlightCore, where do I start? 42 | 43 | Check [DEVELOPMENT.md](DEVELOPMENT.md) 44 | -------------------------------------------------------------------------------- /docs/TROUBLESHOOTING.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | 3 | Got an issue with FlightCore? Hopefully one of the steps below will help you resolve it. If not open an [issue on GitHub](https://github.com/R2NorthstarTools/FlightCore/issues/new) or ping `@geckoeidechse` on the Northstar Discord. 4 | 5 | ## FlightCore won't launch 6 | 7 | If you are on Windows and FlightCore won't start but instead shows an error message like this 8 | 9 | ![webview2 error message windows](assets/flightcore-webview2-windows-error-message.png) 10 | 11 | that means that WebView2 is not installed. WebView2 is an embedded browser framework used by FlightCore to display its GUI. 12 | 13 | To install it, you can grab the latest version from the Microsoft website: \ 14 | https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section 15 | 16 | ![webview2 download screenshot](assets/webview2-download-screenshot.png) 17 | 18 | (make sure to select _Evergreen Bootstrapper_ -> _Download_). 19 | 20 | 21 | ## Linux 22 | 23 | ### FlightCore launches, but the main window is blank 24 | This may be caused by tauri-apps/tauri#5143 25 | 26 | Try setting this environment variable when starting FlightCore: 27 | `WEBKIT_DISABLE_COMPOSITING_MODE=1` 28 | 29 | ```bash 30 | WEBKIT_DISABLE_COMPOSITING_MODE=1 ./flight-core.AppImage 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/assets/Square310x310Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/docs/assets/Square310x310Logo.png -------------------------------------------------------------------------------- /docs/assets/dev-view-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/docs/assets/dev-view-screenshot.png -------------------------------------------------------------------------------- /docs/assets/downloadbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/docs/assets/downloadbutton.png -------------------------------------------------------------------------------- /docs/assets/flightcore-webview2-windows-error-message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/docs/assets/flightcore-webview2-windows-error-message.png -------------------------------------------------------------------------------- /docs/assets/main-window-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/docs/assets/main-window-screenshot.png -------------------------------------------------------------------------------- /docs/assets/webview2-download-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/docs/assets/webview2-download-screenshot.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 65 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flightcore", 3 | "scripts": { 4 | "tauri": "tauri" 5 | }, 6 | "dependencies": { 7 | "@tauri-apps/api": "^2", 8 | "@tauri-apps/plugin-opener": "^2" 9 | }, 10 | "devDependencies": { 11 | "@tauri-apps/cli": "^2" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /scripts/check_version_numbers.py: -------------------------------------------------------------------------------- 1 | # %% 2 | """"Ensure that version numbers between `tauri.conf.json`, `cargo.toml`, and GitHub release are the same""" 3 | import json 4 | import toml 5 | import sys 6 | 7 | with open("src-tauri/tauri.conf.json", "rt") as f: 8 | tauri_conf_json = json.load(f) 9 | 10 | with open("src-tauri/Cargo.toml", "rt") as f: 11 | Cargo_toml = toml.load(f) 12 | 13 | tauri_conf_json_version = tauri_conf_json["version"] 14 | Cargo_toml_version = Cargo_toml["package"]["version"] 15 | 16 | # Ensure same 17 | assert(tauri_conf_json_version == Cargo_toml_version) 18 | 19 | # Check release tag additionally if release 20 | if "--release" in sys.argv: 21 | print("TODO") 22 | release_tag = sys.argv[2] 23 | print(release_tag) 24 | assert(release_tag == f"v{tauri_conf_json_version}") 25 | -------------------------------------------------------------------------------- /scripts/create-release-file.py: -------------------------------------------------------------------------------- 1 | # %% 2 | import json 3 | import datetime 4 | import sys 5 | 6 | assert("--version" in sys.argv) 7 | 8 | version_number = sys.argv[2] 9 | version_number_stripped_v = version_number.replace("v", "") 10 | 11 | PATH_TO_LINUX_SIG = f"./linux-artifacts/FlightCore_{version_number_stripped_v}_amd64.AppImage.tar.gz.sig" 12 | PATH_TO_WINDOWS_SIG = f"./windows-artifacts/bundle/msi/FlightCore_{version_number_stripped_v}_x64_en-US.msi.zip.sig" 13 | 14 | # Text to show in update notification 15 | RELEASE_TEXT = "See the following link for release notes: https://github.com/R2NorthstarTools/FlightCore/releases" 16 | 17 | # Read signatures 18 | with open(PATH_TO_LINUX_SIG, "rt") as f: 19 | linux_sig = f.read() 20 | with open(PATH_TO_WINDOWS_SIG, "rt") as f: 21 | windows_sig = f.read() 22 | 23 | 24 | current_datetime_string = str(datetime.datetime.utcnow().replace(microsecond=0).isoformat() + "Z") 25 | 26 | release_dict = { 27 | "version": f"{version_number}", 28 | "notes": f"{RELEASE_TEXT}", 29 | "pub_date": current_datetime_string, 30 | "platforms": { 31 | "linux-x86_64": { 32 | "signature": linux_sig, 33 | "url": f"https://github.com/R2NorthstarTools/FlightCore/releases/download/{version_number}/flight-core_{version_number_stripped_v}_amd64.AppImage.tar.gz" 34 | }, 35 | "windows-x86_64": { 36 | "signature": windows_sig, 37 | "url": f"https://github.com/R2NorthstarTools/FlightCore/releases/download/{version_number}/FlightCore_{version_number_stripped_v}_x64_en-US.msi.zip" 38 | } 39 | } 40 | } 41 | json_string = json.dumps(release_dict, indent=4) 42 | print(json_string) 43 | # %% 44 | RESULT_JSON_FILENAME = "latest-release.json" 45 | with open(RESULT_JSON_FILENAME, "wt") as f: 46 | f.write(json_string) 47 | # %% 48 | -------------------------------------------------------------------------------- /src-tauri/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Generated by Tauri 6 | # will have schema files for capabilities auto-completion 7 | /gen/schemas 8 | -------------------------------------------------------------------------------- /src-tauri/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "flightcore" 3 | version = "3.0.6" 4 | description = "Mod-manager for Northstar" 5 | authors = ["https://github.com/R2NorthstarTools/FlightCore/graphs/contributors"] 6 | license = "MIT" 7 | repository = "https://github.com/R2NorthstarTools/FlightCore" 8 | edition = "2021" 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [profile.release] 13 | # Keeps line tables in built binary 14 | # c.f.: https://doc.rust-lang.org/cargo/reference/profiles.html#debug 15 | # This is done to see line numbers in stack trace on sentry.io 16 | debug = 1 17 | 18 | [lib] 19 | # The `_lib` suffix may seem redundant but it is necessary 20 | # to make the lib name unique and wouldn't conflict with the bin name. 21 | # This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519 22 | name = "tauri_app_lib" 23 | crate-type = ["staticlib", "cdylib", "rlib"] 24 | 25 | [build-dependencies] 26 | tauri-build = { version = "2", features = [] } 27 | 28 | [dependencies] 29 | serde_json = "1.0" 30 | serde = { version = "1.0", features = ["derive"] } 31 | tauri = { version = "2", features = [] } 32 | tauri-plugin-dialog = "2" 33 | tauri-plugin-opener = "2" 34 | tauri-plugin-store = "2" 35 | tokio = { version = "1", features = ["full"] } 36 | # Sentry (crash) logging 37 | sentry = "0.32" 38 | sentry-log = "0.34" 39 | # Find steam games 40 | steamlocate = "2.0.0-beta.2" 41 | # Error messages 42 | anyhow = "1.0" 43 | # libthermite for Northstar/mod install handling 44 | libthermite = { version = "0.8.1", features = ["proton"] } 45 | # zip stuff 46 | zip = "0.6.2" 47 | # Regex 48 | regex = "1.10" 49 | # Read out running application process names 50 | sysinfo = "0.30.13" 51 | # HTTP requests 52 | reqwest = { version = "0.11", features = ["blocking", "json"] } 53 | # JSON5 parsing support (allows comments in JSON) 54 | json5 = "0.4.1" 55 | # Async recursion for recursive mod install 56 | async-recursion = "1.1.1" 57 | # For parsing timestamps 58 | chrono = "0.4.38" 59 | # TypeScript bindings 60 | ts-rs = "10.0" 61 | # const formatting 62 | const_format = "0.2.33" 63 | # Logging libraries 64 | pretty_env_logger = "0.5.0" 65 | log = "0.4" 66 | # Extracting zip files easily 67 | zip-extract = "0.1.3" 68 | # open urls 69 | open = "5.3.0" 70 | semver = "1.0" 71 | # simplified filesystem access 72 | glob = "0.3.1" 73 | dirs = "5" 74 | # Random number stuff 75 | rand = "0.8.5" 76 | 77 | # Interacting with GitHub 78 | octocrab = "0.38.0" 79 | # Library for removing markdown links 80 | remove-markdown-links = "1.0.0" 81 | 82 | 83 | [target.'cfg(windows)'.dependencies] 84 | # Windows API stuff 85 | winapi = "0.3.9" 86 | winreg = "0.52.0" 87 | 88 | [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] 89 | tauri-plugin-updater = "2" 90 | -------------------------------------------------------------------------------- /src-tauri/bindings/CommitHead.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | import type { Repo } from "./Repo"; 3 | 4 | export type CommitHead = { sha: string, ref: string, repo: Repo, }; 5 | -------------------------------------------------------------------------------- /src-tauri/bindings/FlightCoreVersion.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | 3 | export type FlightCoreVersion = { tag_name: string, published_at: string, }; 4 | -------------------------------------------------------------------------------- /src-tauri/bindings/InstallProgress.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | import type { InstallState } from "./InstallState"; 3 | 4 | export type InstallProgress = { current_downloaded: bigint, total_size: bigint, state: InstallState, }; 5 | -------------------------------------------------------------------------------- /src-tauri/bindings/InstallState.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | 3 | export type InstallState = "Downloading" | "Extracting" | "Done"; 4 | -------------------------------------------------------------------------------- /src-tauri/bindings/InstallType.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | 3 | /** 4 | * Defines how Titanfall2 was installed (Steam, Origin, ...) 5 | */ 6 | export type InstallType = "STEAM" | "ORIGIN" | "EAPLAY" | "UNKNOWN"; 7 | -------------------------------------------------------------------------------- /src-tauri/bindings/NorthstarLaunchOptions.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | 3 | export type NorthstarLaunchOptions = { launch_via_steam: boolean, bypass_checks: boolean, }; 4 | -------------------------------------------------------------------------------- /src-tauri/bindings/NorthstarMod.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | 3 | /** 4 | * Object holding various information about a Northstar mod 5 | */ 6 | export type NorthstarMod = { name: string, version: string | null, thunderstore_mod_string: string | null, enabled: boolean, directory: string, }; 7 | -------------------------------------------------------------------------------- /src-tauri/bindings/NorthstarThunderstoreRelease.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | 3 | export type NorthstarThunderstoreRelease = { package: string, version: string, }; 4 | -------------------------------------------------------------------------------- /src-tauri/bindings/NorthstarThunderstoreReleaseWrapper.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | import type { NorthstarThunderstoreRelease } from "./NorthstarThunderstoreRelease"; 3 | 4 | export type NorthstarThunderstoreReleaseWrapper = { label: string, value: NorthstarThunderstoreRelease, }; 5 | -------------------------------------------------------------------------------- /src-tauri/bindings/Project.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | 3 | export type Project = "FlightCore" | "Northstar"; 4 | -------------------------------------------------------------------------------- /src-tauri/bindings/PullRequestType.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | 3 | export type PullRequestType = "Mods" | "Launcher"; 4 | -------------------------------------------------------------------------------- /src-tauri/bindings/PullsApiResponseElement.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | import type { CommitHead } from "./CommitHead"; 3 | 4 | export type PullsApiResponseElement = { number: bigint, title: string, url: string, head: CommitHead, html_url: string, labels: Array, }; 5 | -------------------------------------------------------------------------------- /src-tauri/bindings/ReleaseInfo.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | 3 | export type ReleaseInfo = { name: string, published_at: string, body: string, }; 4 | -------------------------------------------------------------------------------- /src-tauri/bindings/Repo.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | 3 | export type Repo = { full_name: string, }; 4 | -------------------------------------------------------------------------------- /src-tauri/bindings/Tag.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | 3 | export type Tag = { name: string, }; 4 | -------------------------------------------------------------------------------- /src-tauri/bindings/TagWrapper.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | import type { Tag } from "./Tag"; 3 | 4 | /** 5 | * Wrapper type needed for frontend 6 | */ 7 | export type TagWrapper = { label: string, value: Tag, }; 8 | -------------------------------------------------------------------------------- /src-tauri/bindings/ThunderstoreMod.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | import type { ThunderstoreModVersion } from "./ThunderstoreModVersion"; 3 | 4 | export type ThunderstoreMod = { name: string, full_name: string, owner: string, package_url: string, date_created: string, date_updated: string, uuid4: string, rating_score: number, is_pinned: boolean, is_deprecated: boolean, has_nsfw_content: boolean, categories: Array, versions: Array, }; 5 | -------------------------------------------------------------------------------- /src-tauri/bindings/ThunderstoreModVersion.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. 2 | 3 | export type ThunderstoreModVersion = { name: string, full_name: string, description: string, icon: string, version_number: string, dependencies: Array, download_url: string, downloads: number, date_created: string, website_url: string, is_active: boolean, uuid4: string, file_size: bigint, }; 4 | -------------------------------------------------------------------------------- /src-tauri/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | tauri_build::build() 3 | } 4 | -------------------------------------------------------------------------------- /src-tauri/capabilities/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../gen/schemas/desktop-schema.json", 3 | "identifier": "default", 4 | "description": "Capability for the main window", 5 | "windows": [ 6 | "main", 7 | "RepairWindow" 8 | ], 9 | "permissions": [ 10 | "core:window:allow-minimize", 11 | "core:window:allow-request-user-attention", 12 | "core:window:allow-start-dragging", 13 | "core:default", 14 | "opener:default", 15 | "store:default", 16 | "updater:default" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src-tauri/capabilities/desktop.json: -------------------------------------------------------------------------------- 1 | { 2 | "identifier": "desktop-capability", 3 | "platforms": [ 4 | "macOS", 5 | "windows", 6 | "linux" 7 | ], 8 | "windows": [ 9 | "main" 10 | ], 11 | "permissions": [ 12 | "updater:default" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src-tauri/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/128x128.png -------------------------------------------------------------------------------- /src-tauri/icons/128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/128x128@2x.png -------------------------------------------------------------------------------- /src-tauri/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/32x32.png -------------------------------------------------------------------------------- /src-tauri/icons/Square107x107Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/Square107x107Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square142x142Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/Square142x142Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square150x150Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/Square150x150Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square284x284Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/Square284x284Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square30x30Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/Square30x30Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square310x310Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/Square310x310Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square44x44Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/Square44x44Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square71x71Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/Square71x71Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square89x89Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/Square89x89Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/StoreLogo.png -------------------------------------------------------------------------------- /src-tauri/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/icon.icns -------------------------------------------------------------------------------- /src-tauri/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/icon.ico -------------------------------------------------------------------------------- /src-tauri/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-tauri/icons/icon.png -------------------------------------------------------------------------------- /src-tauri/src/constants.rs: -------------------------------------------------------------------------------- 1 | // This file stores various global constants values 2 | use const_format::concatcp; 3 | use std::time::Duration; 4 | 5 | /// FlightCore user agent for web requests 6 | pub const APP_USER_AGENT: &str = concatcp!("FlightCore/", env!("CARGO_PKG_VERSION")); 7 | 8 | /// URL of the Northstar masterserver 9 | pub const MASTER_SERVER_URL: &str = "https://northstar.tf"; 10 | 11 | /// server list endpoint 12 | pub const SERVER_BROWSER_ENDPOINT: &str = "/client/servers"; 13 | 14 | /// List of core Northstar mods 15 | pub const CORE_MODS: [&str; 3] = [ 16 | "Northstar.Client", 17 | "Northstar.Custom", 18 | "Northstar.CustomServers", 19 | ]; 20 | 21 | /// List of Thunderstoremods that shouldn't be installable 22 | /// as they behave different than common Squirrel mods 23 | pub const BLACKLISTED_MODS: [&str; 3] = [ 24 | "northstar-Northstar", 25 | "northstar-NorthstarReleaseCandidate", 26 | "ebkr-r2modman", 27 | ]; 28 | 29 | /// List of Thunderstoremods that have some specific install requirements that makes them different from standard mods 30 | pub const MODS_WITH_SPECIAL_REQUIREMENTS: [&str; 2] = 31 | ["NanohmProtogen-VanillaPlus", "NachosChipeados-VanillaPlus"]; 32 | 33 | /// Order in which the sections for release notes should be displayed 34 | pub const SECTION_ORDER: [&str; 11] = [ 35 | "feat", "fix", "docs", "style", "refactor", "build", "test", "i18n", "ci", "chore", "other", 36 | ]; 37 | 38 | /// Statistics (players and servers counts) refresh delay 39 | pub const REFRESH_DELAY: Duration = Duration::from_secs(5 * 60); 40 | 41 | /// Flightcore repo name and org name on GitHub 42 | pub const FLIGHTCORE_REPO_NAME: &str = "R2NorthstarTools/FlightCore"; 43 | 44 | /// Northstar release repo name and org name on GitHub 45 | pub const NORTHSTAR_RELEASE_REPO_NAME: &str = "R2Northstar/Northstar"; 46 | 47 | /// NorthstarLauncher repo name on GitHub 48 | pub const NORTHSTAR_LAUNCHER_REPO_NAME: &str = "NorthstarLauncher"; 49 | 50 | /// NorthstarMods repo name on GitHub 51 | pub const NORTHSTAR_MODS_REPO_NAME: &str = "NorthstarMods"; 52 | 53 | /// URL to launcher commits API URL 54 | pub const NS_LAUNCHER_COMMITS_API_URL: &str = 55 | "https://api.github.com/repos/R2Northstar/NorthstarLauncher/commits"; 56 | 57 | /// Filename of DLL that Northstar uses 58 | pub const NORTHSTAR_DLL: &str = "Northstar.dll"; 59 | 60 | /// Profile that Northstar defaults to and ships with 61 | pub const NORTHSTAR_DEFAULT_PROFILE: &str = "R2Northstar"; 62 | -------------------------------------------------------------------------------- /src-tauri/src/development/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::constants::NS_LAUNCHER_COMMITS_API_URL; 2 | use crate::github::{ 3 | pull_requests::{check_github_api, download_zip_into_memory, get_launcher_download_link}, 4 | CommitInfo, 5 | }; 6 | 7 | #[tauri::command] 8 | pub async fn install_git_main(game_install_path: &str) -> Result { 9 | // Get list of commits 10 | let commits: Vec = serde_json::from_value( 11 | check_github_api(NS_LAUNCHER_COMMITS_API_URL) 12 | .await 13 | .expect("Failed request"), 14 | ) 15 | .unwrap(); 16 | 17 | // Get latest commit... 18 | let latest_commit_sha = commits[0].sha.clone(); 19 | // ...and according artifact download URL 20 | let download_url = get_launcher_download_link(latest_commit_sha.clone()).await?; 21 | 22 | let archive = match download_zip_into_memory(download_url).await { 23 | Ok(archive) => archive, 24 | Err(err) => return Err(err.to_string()), 25 | }; 26 | 27 | let extract_directory = format!( 28 | "{}/___flightcore-temp/download-dir/launcher-pr-{}", 29 | game_install_path, latest_commit_sha 30 | ); 31 | match std::fs::create_dir_all(extract_directory.clone()) { 32 | Ok(_) => (), 33 | Err(err) => { 34 | return Err(format!( 35 | "Failed creating temporary download directory: {}", 36 | err 37 | )) 38 | } 39 | }; 40 | 41 | let target_dir = std::path::PathBuf::from(extract_directory.clone()); // Doesn't need to exist 42 | match zip_extract::extract(std::io::Cursor::new(archive), &target_dir, true) { 43 | Ok(()) => (), 44 | Err(err) => { 45 | return Err(format!("Failed unzip: {}", err)); 46 | } 47 | }; 48 | 49 | // Copy only necessary files from temp dir 50 | // Copy: 51 | // - NorthstarLauncher.exe 52 | // - Northstar.dll 53 | let files_to_copy = vec!["NorthstarLauncher.exe", "Northstar.dll"]; 54 | for file_name in files_to_copy { 55 | let source_file_path = format!("{}/{}", extract_directory, file_name); 56 | let destination_file_path = format!("{}/{}", game_install_path, file_name); 57 | match std::fs::copy(source_file_path, destination_file_path) { 58 | Ok(_result) => (), 59 | Err(err) => { 60 | return Err(format!( 61 | "Failed to copy necessary file {} from temp dir: {}", 62 | file_name, err 63 | )) 64 | } 65 | }; 66 | } 67 | 68 | // delete extract directory 69 | match std::fs::remove_dir_all(&extract_directory) { 70 | Ok(()) => (), 71 | Err(err) => { 72 | return Err(format!( 73 | "Failed to delete temporary download directory: {}", 74 | err 75 | )) 76 | } 77 | } 78 | 79 | log::info!( 80 | "All done with installing launcher from {}", 81 | latest_commit_sha 82 | ); 83 | Ok(latest_commit_sha) 84 | } 85 | -------------------------------------------------------------------------------- /src-tauri/src/github/release_notes.rs: -------------------------------------------------------------------------------- 1 | use rand::prelude::SliceRandom; 2 | use serde::{Deserialize, Serialize}; 3 | use std::vec::Vec; 4 | use ts_rs::TS; 5 | 6 | #[derive(Serialize, Deserialize, Debug, Clone, TS)] 7 | #[ts(export)] 8 | pub struct ReleaseInfo { 9 | pub name: String, 10 | pub published_at: String, 11 | pub body: String, 12 | } 13 | 14 | #[derive(Serialize, Deserialize, Debug, Clone, TS)] 15 | #[ts(export)] 16 | pub struct FlightCoreVersion { 17 | tag_name: String, 18 | published_at: String, 19 | } 20 | 21 | /// Gets newest FlighCore version from GitHub 22 | #[tauri::command] 23 | pub async fn get_newest_flightcore_version() -> Result { 24 | // Get newest version number from GitHub API 25 | log::info!("Checking GitHub API"); 26 | let octocrab = octocrab::instance(); 27 | let page = octocrab 28 | .repos("R2NorthstarTools", "FlightCore") 29 | .releases() 30 | .list() 31 | // Optional Parameters 32 | .per_page(1) 33 | .page(1u32) 34 | // Send the request 35 | .send() 36 | .await 37 | .map_err(|err| err.to_string())?; 38 | 39 | // Get newest element 40 | let latest_release_item = &page.items[0]; 41 | 42 | let flightcore_version = FlightCoreVersion { 43 | tag_name: latest_release_item.tag_name.clone(), 44 | published_at: latest_release_item.published_at.unwrap().to_rfc3339(), 45 | }; 46 | log::info!("Done checking GitHub API"); 47 | 48 | Ok(flightcore_version) 49 | } 50 | 51 | /// Checks if installed FlightCore version is up-to-date 52 | /// false -> FlightCore install is up-to-date 53 | /// true -> FlightCore install is outdated 54 | #[tauri::command] 55 | pub async fn check_is_flightcore_outdated() -> Result { 56 | let newest_flightcore_release = get_newest_flightcore_version().await?; 57 | // Parse version number excluding leading `v` 58 | let newest_version = semver::Version::parse(&newest_flightcore_release.tag_name[1..]).unwrap(); 59 | 60 | // Get version of installed FlightCore 61 | let current_version = env!("CARGO_PKG_VERSION"); 62 | let current_version = semver::Version::parse(current_version).unwrap(); 63 | 64 | #[cfg(debug_assertions)] 65 | let is_outdated = current_version < newest_version; 66 | #[cfg(not(debug_assertions))] 67 | let is_outdated = current_version != newest_version; 68 | 69 | // If outdated, check how new the update is 70 | if is_outdated { 71 | // Time to wait (2h) h * m * s 72 | let threshold_seconds = 2 * 60 * 60; 73 | 74 | // Get current time 75 | let current_time = chrono::Utc::now(); 76 | 77 | // Get latest release time from GitHub API response 78 | let result = chrono::DateTime::parse_from_rfc3339(&newest_flightcore_release.published_at) 79 | .unwrap() 80 | .with_timezone(&chrono::Utc); 81 | 82 | // Check if current time is outside of threshold 83 | let diff = current_time - result; 84 | if diff.num_seconds() < threshold_seconds { 85 | // User would be outdated but the newest release is recent 86 | // therefore we do not wanna show outdated warning. 87 | return Ok(false); 88 | } 89 | return Ok(true); 90 | } 91 | 92 | Ok(is_outdated) 93 | } 94 | 95 | #[tauri::command] 96 | pub async fn get_northstar_release_notes() -> Result, String> { 97 | let octocrab = octocrab::instance(); 98 | let page = octocrab 99 | .repos("R2Northstar", "Northstar") 100 | .releases() 101 | .list() 102 | // Optional Parameters 103 | .per_page(25) 104 | .page(1u32) 105 | // Send the request 106 | .send() 107 | .await 108 | .map_err(|err| err.to_string())?; 109 | 110 | // TODO there's probably a way to automatically serialize into the struct but I don't know yet how to 111 | let mut release_info_vector: Vec = vec![]; 112 | for item in page.items { 113 | let release_info = ReleaseInfo { 114 | name: item.name.ok_or(String::from("Release name not found"))?, 115 | published_at: item 116 | .published_at 117 | .ok_or(String::from("Release date not found"))? 118 | .to_rfc3339(), 119 | body: item.body.ok_or(String::from("Release body not found"))?, 120 | }; 121 | release_info_vector.push(release_info); 122 | } 123 | 124 | log::info!("Done checking GitHub API"); 125 | 126 | Ok(release_info_vector) 127 | } 128 | 129 | /// Checks latest GitHub release and generates a announcement message for Discord based on it 130 | #[tauri::command] 131 | pub async fn generate_release_note_announcement() -> Result { 132 | let octocrab = octocrab::instance(); 133 | let page = octocrab 134 | .repos("R2Northstar", "Northstar") 135 | .releases() 136 | .list() 137 | // Optional Parameters 138 | .per_page(1) 139 | .page(1u32) 140 | // Send the request 141 | .send() 142 | .await 143 | .unwrap(); 144 | 145 | // Get newest element 146 | let latest_release_item = &page.items[0]; 147 | 148 | // Extract the URL to the GitHub release note 149 | let github_release_link = latest_release_item.html_url.clone(); 150 | 151 | // Extract release version number 152 | let current_ns_version = &latest_release_item.tag_name; 153 | 154 | // Extract changelog and format it 155 | let changelog = remove_markdown_links::remove_markdown_links( 156 | latest_release_item 157 | .body 158 | .as_ref() 159 | .unwrap() 160 | .split("**Contributors:**") 161 | .next() 162 | .unwrap() 163 | .trim(), 164 | ); 165 | 166 | // Strings to insert for different sections 167 | // Hardcoded for now 168 | let general_info = "REPLACE ME"; 169 | let modders_info = "Mod compatibility should not be impacted"; 170 | let server_hosters_info = "REPLACE ME"; 171 | 172 | let mut rng = rand::thread_rng(); 173 | let attributes = vec![ 174 | "adorable", 175 | "amazing", 176 | "beautiful", 177 | "blithsome", 178 | "brilliant", 179 | "compassionate", 180 | "dazzling", 181 | "delightful", 182 | "distinguished", 183 | "elegant", 184 | "enigmatic", 185 | "enthusiastic", 186 | "fashionable", 187 | "fortuitous", 188 | "friendly", 189 | "generous", 190 | "gleeful", 191 | "gorgeous", 192 | "handsome", 193 | "lively", 194 | "lovely", 195 | "lucky", 196 | "lustrous", 197 | "marvelous", 198 | "merry", 199 | "mirthful", 200 | "phantasmagorical", 201 | "pretty", 202 | "propitious", 203 | "ravishing", 204 | "sincere", 205 | "sophisticated fellow", 206 | "stupendous", 207 | "vivacious", 208 | "wonderful", 209 | "zestful", 210 | ]; 211 | 212 | let selected_attribute = attributes.choose(&mut rng).unwrap(); 213 | 214 | // Build announcement string 215 | let return_string = format!( 216 | r"Hello {selected_attribute} people <3 217 | **Northstar `{current_ns_version}` is out!** 218 | 219 | {general_info} 220 | 221 | __**Modders:**__ 222 | 223 | {modders_info} 224 | 225 | __**Server hosters:**__ 226 | 227 | {server_hosters_info} 228 | 229 | __**Changelog:**__ 230 | ``` 231 | {changelog} 232 | ``` 233 | {github_release_link} 234 | 235 | Checkout #installation on how to install/update Northstar 236 | (the process is the same for both, using a Northstar installer like FlightCore, Viper, or VTOL is recommended over manual installation) 237 | 238 | If you do notice any bugs, please open an issue on Github or drop a message in the thread below 239 | " 240 | ); 241 | 242 | // Return built announcement message 243 | Ok(return_string.to_string()) 244 | } 245 | -------------------------------------------------------------------------------- /src-tauri/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::{env, time::Duration}; 2 | 3 | mod constants; 4 | mod development; 5 | mod github; 6 | mod mod_management; 7 | mod northstar; 8 | mod platform_specific; 9 | mod repair_and_verify; 10 | mod thunderstore; 11 | mod util; 12 | 13 | use serde::{Deserialize, Serialize}; 14 | use tauri::Emitter; 15 | use tokio::time::sleep; 16 | use ts_rs::TS; 17 | 18 | #[derive(Serialize, Deserialize, Debug, Clone, TS)] 19 | #[ts(export)] 20 | struct NorthstarThunderstoreRelease { 21 | package: String, 22 | version: String, 23 | } 24 | 25 | #[derive(Serialize, Deserialize, Debug, Clone, TS)] 26 | #[ts(export)] 27 | pub struct NorthstarThunderstoreReleaseWrapper { 28 | label: String, 29 | value: NorthstarThunderstoreRelease, 30 | } 31 | 32 | #[cfg_attr(mobile, tauri::mobile_entry_point)] 33 | pub fn run() { 34 | // Setup logger 35 | let mut log_builder = pretty_env_logger::formatted_builder(); 36 | log_builder.parse_filters("info"); 37 | let logger = sentry_log::SentryLogger::with_dest(log_builder.build()); 38 | 39 | log::set_boxed_logger(Box::new(logger)).unwrap(); 40 | log::set_max_level(log::LevelFilter::Info); 41 | 42 | // Only enable Sentry crash logs on release 43 | #[cfg(not(debug_assertions))] 44 | let _guard = sentry::init(( 45 | "https://f833732deb2240b0b2dc4abce97d0f1d@o1374052.ingest.sentry.io/6692177", 46 | sentry::ClientOptions { 47 | release: sentry::release_name!(), 48 | attach_stacktrace: true, 49 | ..Default::default() 50 | }, 51 | )); 52 | 53 | let tauri_builder_res = tauri::Builder::default() 54 | .plugin(tauri_plugin_dialog::init()) 55 | .plugin(tauri_plugin_updater::Builder::new().build()) 56 | .plugin(tauri_plugin_store::Builder::new().build()) 57 | .plugin(tauri_plugin_opener::init()) 58 | .setup(|app| { 59 | let app_handle = app.handle().clone(); 60 | tauri::async_runtime::spawn(async move { 61 | loop { 62 | sleep(Duration::from_millis(2000)).await; 63 | // println!("sending backend ping"); 64 | app_handle.emit("backend-ping", "ping").unwrap(); 65 | } 66 | }); 67 | let app_handle = app.handle().clone(); 68 | tauri::async_runtime::spawn(async move { 69 | loop { 70 | sleep(Duration::from_millis(2000)).await; 71 | app_handle 72 | .emit( 73 | "ea-app-running-ping", 74 | util::check_ea_app_or_origin_running(), 75 | ) 76 | .unwrap(); 77 | } 78 | }); 79 | let app_handle = app.handle().clone(); 80 | tauri::async_runtime::spawn(async move { 81 | loop { 82 | sleep(Duration::from_millis(2000)).await; 83 | app_handle 84 | .emit("northstar-running-ping", util::check_northstar_running()) 85 | .unwrap(); 86 | } 87 | }); 88 | 89 | // Emit updated player and server count to GUI 90 | let app_handle = app.handle().clone(); 91 | tauri::async_runtime::spawn(async move { 92 | loop { 93 | sleep(constants::REFRESH_DELAY).await; 94 | app_handle 95 | .emit( 96 | "northstar-statistics", 97 | util::get_server_player_count().await, 98 | ) 99 | .unwrap(); 100 | } 101 | }); 102 | 103 | Ok(()) 104 | }) 105 | .manage(()) 106 | .invoke_handler(tauri::generate_handler![ 107 | development::install_git_main, 108 | github::compare_tags, 109 | github::get_list_of_tags, 110 | github::pull_requests::apply_launcher_pr, 111 | github::pull_requests::apply_mods_pr, 112 | github::pull_requests::get_launcher_download_link, 113 | github::pull_requests::get_pull_requests_wrapper, 114 | github::release_notes::check_is_flightcore_outdated, 115 | github::release_notes::generate_release_note_announcement, 116 | github::release_notes::get_newest_flightcore_version, 117 | github::release_notes::get_northstar_release_notes, 118 | mod_management::delete_northstar_mod, 119 | mod_management::delete_thunderstore_mod, 120 | mod_management::get_installed_mods_and_properties, 121 | mod_management::install_mod_wrapper, 122 | mod_management::set_mod_enabled_status, 123 | northstar::check_is_northstar_outdated, 124 | northstar::get_available_northstar_versions, 125 | northstar::get_northstar_version_number, 126 | northstar::install::find_game_install_location, 127 | northstar::install::install_northstar_wrapper, 128 | northstar::install::update_northstar, 129 | northstar::launch_northstar, 130 | northstar::profile::clone_profile, 131 | northstar::profile::delete_profile, 132 | northstar::profile::fetch_profiles, 133 | northstar::profile::validate_profile, 134 | platform_specific::check_cgnat, 135 | platform_specific::get_host_os, 136 | platform_specific::get_local_northstar_proton_wrapper_version, 137 | platform_specific::install_northstar_proton_wrapper, 138 | platform_specific::uninstall_northstar_proton_wrapper, 139 | repair_and_verify::clean_up_download_folder_wrapper, 140 | repair_and_verify::disable_all_but_core, 141 | repair_and_verify::get_log_list, 142 | repair_and_verify::verify_game_files, 143 | repair_and_verify::verify_install_location, 144 | thunderstore::query_thunderstore_packages_api, 145 | util::close_application, 146 | util::force_panic, 147 | util::get_flightcore_version_number, 148 | util::get_server_player_count, 149 | util::is_debug_mode, 150 | util::kill_northstar, 151 | util::open_repair_window, 152 | ]) 153 | .run(tauri::generate_context!()); 154 | 155 | match tauri_builder_res { 156 | Ok(()) => (), 157 | Err(err) => { 158 | // Failed to launch system native web view 159 | 160 | // Log error on Linux 161 | #[cfg(not(target_os = "windows"))] 162 | { 163 | log::error!("{err}"); 164 | } 165 | 166 | // Log error on Windows 167 | // TODO show error dialog instead 168 | #[cfg(target_os = "windows")] 169 | { 170 | log::error!("{err}"); 171 | } 172 | } 173 | }; 174 | } 175 | 176 | /// Defines how Titanfall2 was installed (Steam, Origin, ...) 177 | #[derive(Serialize, Deserialize, Debug, Clone, TS)] 178 | #[ts(export)] 179 | pub enum InstallType { 180 | STEAM, 181 | ORIGIN, 182 | EAPLAY, 183 | UNKNOWN, 184 | } 185 | 186 | /// Object holding information of the Titanfall2 install, including 187 | /// - Install path 188 | /// - Active profile 189 | /// - Type of installation (Steam, Origin, ...) 190 | #[derive(Serialize, Deserialize, Debug, Clone)] 191 | pub struct GameInstall { 192 | pub game_path: String, 193 | pub profile: String, 194 | pub install_type: InstallType, 195 | } 196 | 197 | /// Object holding various information about a Northstar mod 198 | #[derive(Serialize, Deserialize, Debug, Clone, TS)] 199 | #[ts(export)] 200 | pub struct NorthstarMod { 201 | pub name: String, 202 | pub version: Option, 203 | pub thunderstore_mod_string: Option, 204 | pub enabled: bool, 205 | pub directory: String, 206 | } 207 | -------------------------------------------------------------------------------- /src-tauri/src/main.rs: -------------------------------------------------------------------------------- 1 | // Prevents additional console window on Windows in release, DO NOT REMOVE!! 2 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] 3 | 4 | fn main() { 5 | tauri_app_lib::run() 6 | } 7 | -------------------------------------------------------------------------------- /src-tauri/src/mod_management/plugins.rs: -------------------------------------------------------------------------------- 1 | /// Prompt on plugin 2 | /// Returns: 3 | /// - true: user accepted plugin install 4 | /// - false: user denied plugin install 5 | pub fn plugin_prompt() -> bool { 6 | log::error!("Plugin install cancelled"); 7 | // TODO handle plugin installation again 8 | false 9 | } 10 | -------------------------------------------------------------------------------- /src-tauri/src/northstar/profile.rs: -------------------------------------------------------------------------------- 1 | use crate::util::copy_dir_all; 2 | use crate::GameInstall; 3 | 4 | // These folders are part of Titanfall 2 and 5 | // should NEVER be used as a Profile 6 | const SKIP_PATHS: [&str; 8] = [ 7 | "___flightcore-temp", 8 | "__overlay", 9 | "bin", 10 | "Core", 11 | "r2", 12 | "vpk", 13 | "platform", 14 | "Support", 15 | ]; 16 | 17 | // A profile may have one of these to be detected 18 | const MAY_CONTAIN: [&str; 10] = [ 19 | "mods/", 20 | "plugins/", 21 | "packages/", 22 | "logs/", 23 | "runtime/", 24 | "save_data/", 25 | "Northstar.dll", 26 | "enabledmods.json", 27 | "placeholder.playerdata.pdata", 28 | "LEGAL.txt", 29 | ]; 30 | 31 | /// Returns a list of Profile names 32 | /// All the returned Profiles can be found relative to the game path 33 | #[tauri::command] 34 | pub fn fetch_profiles(game_install: GameInstall) -> Result, String> { 35 | let mut profiles: Vec = Vec::new(); 36 | 37 | for content in MAY_CONTAIN { 38 | let pattern = format!("{}/*/{}", game_install.game_path, content); 39 | for e in glob::glob(&pattern).expect("Failed to read glob pattern") { 40 | let path = e.unwrap(); 41 | let mut ancestors = path.ancestors(); 42 | 43 | ancestors.next(); 44 | 45 | let profile_path = std::path::Path::new(ancestors.next().unwrap()); 46 | let profile_name = profile_path 47 | .file_name() 48 | .unwrap() 49 | .to_os_string() 50 | .into_string() 51 | .unwrap(); 52 | 53 | if !profiles.contains(&profile_name) { 54 | profiles.push(profile_name); 55 | } 56 | } 57 | } 58 | 59 | Ok(profiles) 60 | } 61 | 62 | /// Validates if a given profile is actually a valid profile 63 | #[tauri::command] 64 | pub fn validate_profile(game_install: GameInstall, profile: String) -> bool { 65 | // Game files are never a valid profile 66 | // Prevent users with messed up installs from making it even worse 67 | if SKIP_PATHS.contains(&profile.as_str()) { 68 | return false; 69 | } 70 | 71 | log::info!("Validating Profile {}", profile); 72 | 73 | let profile_path = format!("{}/{}", game_install.game_path, profile); 74 | let profile_dir = std::path::Path::new(profile_path.as_str()); 75 | 76 | profile_dir.is_dir() 77 | } 78 | 79 | #[tauri::command] 80 | pub fn delete_profile(game_install: GameInstall, profile: String) -> Result<(), String> { 81 | // Check if the Profile actually exists 82 | if !validate_profile(game_install.clone(), profile.clone()) { 83 | return Err(format!("{} is not a valid Profile", profile)); 84 | } 85 | 86 | log::info!("Deleting Profile {}", profile); 87 | 88 | let profile_path = format!("{}/{}", game_install.game_path, profile); 89 | 90 | match std::fs::remove_dir_all(profile_path) { 91 | Ok(()) => Ok(()), 92 | Err(err) => Err(format!("Failed to delete Profile: {}", err)), 93 | } 94 | } 95 | 96 | /// Clones a profile by simply duplicating the folder under a new name 97 | #[tauri::command] 98 | pub fn clone_profile( 99 | game_install: GameInstall, 100 | old_profile: String, 101 | new_profile: String, 102 | ) -> Result<(), String> { 103 | // Check if the old Profile already exists 104 | if !validate_profile(game_install.clone(), old_profile.clone()) { 105 | return Err(format!("{} is not a valid Profile", old_profile)); 106 | } 107 | 108 | // Check that new Profile does not already exist 109 | if validate_profile(game_install.clone(), new_profile.clone()) { 110 | return Err(format!("{} already exists", new_profile)); 111 | } 112 | 113 | log::info!("Cloning Profile {} to {}", old_profile, new_profile); 114 | 115 | let old_profile_path = format!("{}/{}", game_install.game_path, old_profile); 116 | let new_profile_path = format!("{}/{}", game_install.game_path, new_profile); 117 | 118 | copy_dir_all(old_profile_path, new_profile_path).unwrap(); 119 | 120 | Ok(()) 121 | } 122 | -------------------------------------------------------------------------------- /src-tauri/src/platform_specific/linux.rs: -------------------------------------------------------------------------------- 1 | // Linux specific code 2 | 3 | fn get_proton_dir() -> Result { 4 | let steam_dir = match steamlocate::SteamDir::locate() { 5 | Ok(result) => result, 6 | Err(_) => return Err("Unable to find Steam directory".to_string()), 7 | }; 8 | let compat_dir = format!("{}/compatibilitytools.d", steam_dir.path().display()); 9 | 10 | Ok(compat_dir) 11 | } 12 | 13 | /// Downloads and installs NS proton 14 | /// Assumes Steam install 15 | pub fn install_ns_proton() -> Result<(), String> { 16 | // Get latest NorthstarProton release 17 | let latest = match thermite::core::latest_release() { 18 | Ok(result) => result, 19 | Err(_) => return Err("Failed to fetch latest NorthstarProton release".to_string()), 20 | }; 21 | 22 | let temp_dir = std::env::temp_dir(); 23 | let path = format!("{}/nsproton-{}.tar.gz", temp_dir.display(), latest); 24 | let archive = match std::fs::File::create(path.clone()) { 25 | Ok(result) => result, 26 | Err(_) => return Err("Failed to allocate NorthstarProton archive on disk".to_string()), 27 | }; 28 | 29 | // Download the latest Proton release 30 | log::info!("Downloading NorthstarProton to {}", path); 31 | match thermite::core::download_ns_proton(latest, archive) { 32 | Ok(_) => {} 33 | Err(_) => return Err("Failed to download NorthstarProton".to_string()), 34 | } 35 | 36 | log::info!("Finished Download"); 37 | 38 | let compat_dir = get_proton_dir()?; 39 | 40 | match std::fs::create_dir_all(compat_dir.clone()) { 41 | Ok(_) => {} 42 | Err(_) => return Err("Failed to create compatibilitytools directory".to_string()), 43 | } 44 | 45 | let finished = match std::fs::File::open(path.clone()) { 46 | Ok(result) => result, 47 | Err(_) => return Err("Failed to open NorthstarProton archive".to_string()), 48 | }; 49 | 50 | // Extract to Proton dir 51 | log::info!("Installing NorthstarProton to {}", compat_dir); 52 | match thermite::core::install_ns_proton(&finished, compat_dir) { 53 | Ok(_) => {} 54 | Err(_) => return Err("Failed to create install NorthstarProton".to_string()), 55 | } 56 | log::info!("Finished Installation"); 57 | drop(finished); 58 | 59 | // We installed NSProton, lets ignore this if it fails 60 | let _ = std::fs::remove_file(path); 61 | 62 | Ok(()) 63 | } 64 | 65 | /// Remove NS Proton 66 | pub fn uninstall_ns_proton() -> Result<(), String> { 67 | let compat_dir = get_proton_dir()?; 68 | let pattern = format!("{}/NorthstarProton*", compat_dir); 69 | for e in glob::glob(&pattern).expect("Failed to read glob pattern") { 70 | match e { 71 | Ok(path) => match std::fs::remove_dir_all(path.clone()) { 72 | Ok(_) => {} 73 | Err(_) => return Err(format!("Failed to remove {}", path.display())), 74 | }, 75 | Err(e) => return Err(format!("Found unprocessable entry {}", e)), 76 | } 77 | } 78 | 79 | Ok(()) 80 | } 81 | 82 | /// Get the latest installed NS Proton version 83 | pub fn get_local_ns_proton_version() -> Result { 84 | let compat_dir = get_proton_dir().unwrap(); 85 | let pattern = format!("{}/NorthstarProton*/version", compat_dir); 86 | 87 | if let Some(e) = glob::glob(&pattern) 88 | .expect("Failed to read glob pattern") 89 | .next() 90 | { 91 | let version_content = std::fs::read_to_string(e.unwrap()).unwrap(); 92 | let version = version_content.split(' ').nth(1).unwrap().to_string(); 93 | 94 | return Ok(version); 95 | } 96 | 97 | Err("Northstar Proton is not installed".to_string()) 98 | } 99 | -------------------------------------------------------------------------------- /src-tauri/src/platform_specific/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(target_os = "windows")] 2 | pub mod windows; 3 | 4 | #[cfg(target_os = "linux")] 5 | pub mod linux; 6 | 7 | /// Returns identifier of host OS FlightCore is running on 8 | #[tauri::command] 9 | pub fn get_host_os() -> String { 10 | std::env::consts::OS.to_string() 11 | } 12 | 13 | /// On Linux attempts to install NorthstarProton 14 | /// On Windows simply returns an error message 15 | #[tauri::command] 16 | pub async fn install_northstar_proton_wrapper() -> Result<(), String> { 17 | #[cfg(target_os = "linux")] 18 | return linux::install_ns_proton().map_err(|err| err.to_string()); 19 | 20 | #[cfg(target_os = "windows")] 21 | Err("Not supported on Windows".to_string()) 22 | } 23 | 24 | #[tauri::command] 25 | pub async fn uninstall_northstar_proton_wrapper() -> Result<(), String> { 26 | #[cfg(target_os = "linux")] 27 | return linux::uninstall_ns_proton(); 28 | 29 | #[cfg(target_os = "windows")] 30 | Err("Not supported on Windows".to_string()) 31 | } 32 | 33 | #[tauri::command] 34 | pub async fn get_local_northstar_proton_wrapper_version() -> Result { 35 | #[cfg(target_os = "linux")] 36 | return linux::get_local_ns_proton_version(); 37 | 38 | #[cfg(target_os = "windows")] 39 | Err("Not supported on Windows".to_string()) 40 | } 41 | 42 | /// Check whether the current device might be behind a CGNAT 43 | #[tauri::command] 44 | pub async fn check_cgnat() -> Result { 45 | #[cfg(target_os = "linux")] 46 | return Err("Not supported on Linux".to_string()); 47 | 48 | #[cfg(target_os = "windows")] 49 | windows::check_cgnat().await 50 | } 51 | -------------------------------------------------------------------------------- /src-tauri/src/platform_specific/windows.rs: -------------------------------------------------------------------------------- 1 | /// Windows specific code 2 | use anyhow::{anyhow, Result}; 3 | use std::net::Ipv4Addr; 4 | 5 | #[cfg(target_os = "windows")] 6 | use winreg::{enums::HKEY_LOCAL_MACHINE, RegKey}; 7 | 8 | use crate::repair_and_verify::check_is_valid_game_path; 9 | 10 | /// Gets Titanfall2 install location on Origin 11 | pub fn origin_install_location_detection() -> Result { 12 | #[cfg(target_os = "windows")] 13 | { 14 | let hklm = RegKey::predef(HKEY_LOCAL_MACHINE); 15 | match hklm.open_subkey("SOFTWARE\\Respawn\\Titanfall2") { 16 | Ok(tf) => { 17 | let game_path_str: String = tf.get_value("Install Dir")?; 18 | 19 | match check_is_valid_game_path(&game_path_str) { 20 | Ok(()) => { 21 | return Ok(game_path_str.to_string()); 22 | } 23 | Err(err) => { 24 | log::warn!("{err}"); 25 | } 26 | } 27 | } 28 | Err(err) => { 29 | log::warn!("{err}"); 30 | } 31 | } 32 | } 33 | 34 | Err(anyhow!("No Origin / EA App install path found")) 35 | } 36 | 37 | /// Check whether the current device might be behind a CGNAT 38 | pub async fn check_cgnat() -> Result { 39 | // Use external service to grap IP 40 | let url = "https://api.ipify.org"; 41 | let response = reqwest::get(url).await.unwrap().text().await.unwrap(); 42 | 43 | // Check if valid IPv4 address and return early if not 44 | if response.parse::().is_err() { 45 | return Err(format!("Not valid IPv4 address: {}", response)); 46 | } 47 | 48 | let hops_count = run_tracert(&response)?; 49 | Ok(format!("Counted {} hops to {}", hops_count, response)) 50 | } 51 | 52 | /// Count number of hops in tracert output 53 | fn count_hops(output: &str) -> usize { 54 | // Split the output into lines 55 | let lines: Vec<&str> = output.lines().collect(); 56 | 57 | // Filter lines that appear to represent hops 58 | let hop_lines: Vec<&str> = lines 59 | .iter() 60 | .filter(|&line| line.contains("ms") || line.contains("*")) // TODO check if it contains just the `ms` surrounded by whitespace, otherwise it might falsely pick up some domain names as well 61 | .cloned() 62 | .collect(); 63 | 64 | // Return the number of hops 65 | hop_lines.len() 66 | } 67 | 68 | /// Run `tracert` 69 | fn run_tracert(target_ip: &str) -> Result { 70 | // Ensure valid IPv4 address to avoid prevent command injection 71 | assert!(target_ip.parse::().is_ok()); 72 | 73 | // Execute the `tracert` command 74 | let output = match std::process::Command::new("tracert") 75 | .arg("-4") // Force IPv4 76 | .arg("-d") // Prevent resolving intermediate IP addresses 77 | .arg("-w") // Set timeout to 1 second 78 | .arg("1000") 79 | .arg("-h") // Set max hop count 80 | .arg("5") 81 | .arg(target_ip) 82 | .output() 83 | { 84 | Ok(res) => res, 85 | Err(err) => return Err(format!("Failed running tracert: {}", err)), 86 | }; 87 | 88 | // Check if the command was successful 89 | if output.status.success() { 90 | // Convert the output to a string 91 | let stdout = 92 | std::str::from_utf8(&output.stdout).expect("Invalid UTF-8 sequence in command output"); 93 | println!("{}", stdout); 94 | 95 | // Count the number of hops 96 | let hop_count = count_hops(stdout); 97 | Ok(hop_count) 98 | } else { 99 | let stderr = std::str::from_utf8(&output.stderr) 100 | .expect("Invalid UTF-8 sequence in command error output"); 101 | println!("{}", stderr); 102 | Err(format!("Failed collecting tracert output: {}", stderr)) 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src-tauri/src/repair_and_verify/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::mod_management::{get_enabled_mods, rebuild_enabled_mods_json, set_mod_enabled_status}; 2 | /// Contains various functions to repair common issues and verifying installation 3 | use crate::{constants::CORE_MODS, GameInstall}; 4 | 5 | /// Checks if is valid Titanfall2 install based on certain conditions 6 | #[tauri::command] 7 | pub async fn verify_install_location(game_path: String) -> bool { 8 | match check_is_valid_game_path(&game_path) { 9 | Ok(()) => true, 10 | Err(err) => { 11 | log::warn!("{}", err); 12 | false 13 | } 14 | } 15 | } 16 | 17 | /// Checks whether the provided path is a valid Titanfall2 gamepath by checking against a certain set of criteria 18 | pub fn check_is_valid_game_path(game_install_path: &str) -> Result<(), String> { 19 | let path_to_titanfall2_exe = format!("{game_install_path}/Titanfall2.exe"); 20 | let is_correct_game_path = std::path::Path::new(&path_to_titanfall2_exe).exists(); 21 | log::info!("Titanfall2.exe exists in path? {}", is_correct_game_path); 22 | 23 | // Exit early if wrong game path 24 | if !is_correct_game_path { 25 | return Err(format!("Incorrect game path \"{game_install_path}\"")); // Return error cause wrong game path 26 | } 27 | Ok(()) 28 | } 29 | 30 | /// Verifies Titanfall2 game files 31 | #[tauri::command] 32 | pub fn verify_game_files(game_install: GameInstall) -> Result { 33 | dbg!(game_install); 34 | Err("TODO, not yet implemented".to_string()) 35 | } 36 | 37 | /// Disables all mods except core ones 38 | /// Enables core mods if disabled 39 | #[tauri::command] 40 | pub fn disable_all_but_core(game_install: GameInstall) -> Result<(), String> { 41 | // Rebuild `enabledmods.json` first to ensure all mods are added 42 | rebuild_enabled_mods_json(&game_install)?; 43 | 44 | let current_mods = get_enabled_mods(&game_install)?; 45 | 46 | // Disable all mods, set core mods to enabled 47 | for (key, _value) in current_mods.as_object().unwrap() { 48 | if CORE_MODS.contains(&key.as_str()) { 49 | // This is a core mod, we do not want to disable it 50 | set_mod_enabled_status(game_install.clone(), key.to_string(), true)?; 51 | } else { 52 | // Not a core mod 53 | set_mod_enabled_status(game_install.clone(), key.to_string(), false)?; 54 | } 55 | } 56 | 57 | Ok(()) 58 | } 59 | 60 | /// Installs the specified mod 61 | #[tauri::command] 62 | pub async fn clean_up_download_folder_wrapper( 63 | game_install: GameInstall, 64 | force: bool, 65 | ) -> Result<(), String> { 66 | match clean_up_download_folder(&game_install, force) { 67 | Ok(()) => Ok(()), 68 | Err(err) => Err(err.to_string()), 69 | } 70 | } 71 | 72 | /// Deletes download folder 73 | /// If `force` is FALSE, bails on non-empty folder 74 | /// If `force` is TRUE, deletes folder even if non-empty 75 | pub fn clean_up_download_folder( 76 | game_install: &GameInstall, 77 | force: bool, 78 | ) -> Result<(), anyhow::Error> { 79 | const TEMPORARY_DIRECTORIES: [&str; 4] = [ 80 | "___flightcore-temp-download-dir", 81 | "___flightcore-temp/download-dir", 82 | "___flightcore-temp/extract-dir", 83 | "___flightcore-temp", 84 | ]; 85 | 86 | for directory in TEMPORARY_DIRECTORIES { 87 | // Get download directory 88 | let download_directory = format!("{}/{}/", game_install.game_path, directory); 89 | 90 | // Check if files in folder 91 | let download_dir_contents = match std::fs::read_dir(download_directory.clone()) { 92 | Ok(contents) => contents, 93 | Err(_) => continue, 94 | }; 95 | 96 | let mut count = 0; 97 | download_dir_contents.for_each(|_| count += 1); 98 | 99 | if count > 0 && !force { 100 | // Skip folder if not empty 101 | log::warn!("Folder not empty, not deleting: {directory}"); 102 | continue; 103 | } 104 | 105 | // Delete folder 106 | std::fs::remove_dir_all(download_directory)?; 107 | } 108 | Ok(()) 109 | } 110 | 111 | /// Get list of Northstar logs 112 | #[tauri::command] 113 | pub fn get_log_list(game_install: GameInstall) -> Result, String> { 114 | let ns_log_folder = format!("{}/{}/logs", game_install.game_path, game_install.profile); 115 | 116 | // List files in logs folder 117 | let paths = match std::fs::read_dir(ns_log_folder) { 118 | Ok(paths) => paths, 119 | Err(_err) => return Err("No logs folder found".to_string()), 120 | }; 121 | 122 | // Stores paths of log files 123 | let mut log_files: Vec = Vec::new(); 124 | 125 | for path in paths { 126 | let path = path.unwrap().path(); 127 | if path.display().to_string().contains("nslog") { 128 | log_files.push(path); 129 | } 130 | } 131 | 132 | if !log_files.is_empty() { 133 | Ok(log_files) 134 | } else { 135 | Err("No logs found".to_string()) 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src-tauri/src/thunderstore/mod.rs: -------------------------------------------------------------------------------- 1 | //! For interacting with Thunderstore API 2 | use crate::constants::{APP_USER_AGENT, BLACKLISTED_MODS}; 3 | use serde::{Deserialize, Serialize}; 4 | use std::collections::HashSet; 5 | use ts_rs::TS; 6 | 7 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, TS)] 8 | #[ts(export)] 9 | pub struct ThunderstoreMod { 10 | pub name: String, 11 | pub full_name: String, 12 | pub owner: String, 13 | pub package_url: String, 14 | pub date_created: String, 15 | pub date_updated: String, 16 | pub uuid4: String, 17 | pub rating_score: i32, 18 | pub is_pinned: bool, 19 | pub is_deprecated: bool, 20 | pub has_nsfw_content: bool, 21 | pub categories: Vec, 22 | pub versions: Vec, 23 | } 24 | 25 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, TS)] 26 | #[ts(export)] 27 | pub struct ThunderstoreModVersion { 28 | pub name: String, 29 | pub full_name: String, 30 | pub description: String, 31 | pub icon: String, 32 | pub version_number: String, 33 | pub dependencies: Vec, 34 | pub download_url: String, 35 | pub downloads: i32, 36 | pub date_created: String, 37 | pub website_url: String, 38 | pub is_active: bool, 39 | pub uuid4: String, 40 | pub file_size: i64, 41 | } 42 | 43 | /// Performs actual fetch from Thunderstore and returns response 44 | async fn fetch_thunderstore_packages() -> Result { 45 | log::info!("Fetching Thunderstore API"); 46 | 47 | // Fetches 48 | let url = "https://northstar.thunderstore.io/api/v1/package/"; 49 | 50 | let client = reqwest::Client::new(); 51 | client 52 | .get(url) 53 | .header(reqwest::header::USER_AGENT, APP_USER_AGENT) 54 | .send() 55 | .await? 56 | .text() 57 | .await 58 | } 59 | 60 | /// Queries Thunderstore packages API 61 | #[tauri::command] 62 | pub async fn query_thunderstore_packages_api() -> Result, String> { 63 | let res = match fetch_thunderstore_packages().await { 64 | Ok(res) => res, 65 | Err(err) => { 66 | let warn_response = format!("Couldn't fetch from Thunderstore: {err}"); 67 | log::warn!("{warn_response}"); 68 | return Err(warn_response); 69 | } 70 | }; 71 | 72 | // Parse response 73 | let parsed_json: Vec = match serde_json::from_str(&res) { 74 | Ok(res) => res, 75 | Err(err) => return Err(err.to_string()), 76 | }; 77 | 78 | // Remove some mods from listing 79 | let to_remove_set: HashSet<&str> = BLACKLISTED_MODS.iter().copied().collect(); 80 | let filtered_packages = parsed_json 81 | .into_iter() 82 | .filter(|package| !to_remove_set.contains(&package.full_name.as_ref())) 83 | .collect::>(); 84 | 85 | Ok(filtered_packages) 86 | } 87 | -------------------------------------------------------------------------------- /src-tauri/tauri.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.tauri.app/config/2", 3 | "build": { 4 | "beforeBuildCommand": "cd src-vue && npm run build", 5 | "beforeDevCommand": "cd src-vue && npm run dev", 6 | "devUrl": "http://localhost:1420/", 7 | "frontendDist": "../src-vue/dist" 8 | }, 9 | "productName": "FlightCore", 10 | "version": "3.0.6", 11 | "identifier": "com.github.r2northstartools.flightcore", 12 | "app": { 13 | "windows": [ 14 | { 15 | "title": "FlightCore", 16 | "decorations": false, 17 | "width": 1010, 18 | "height": 600 19 | } 20 | ], 21 | "security": { 22 | "csp": null 23 | } 24 | }, 25 | "bundle": { 26 | "active": true, 27 | "createUpdaterArtifacts": "v1Compatible", 28 | "targets": "all", 29 | "icon": [ 30 | "icons/32x32.png", 31 | "icons/128x128.png", 32 | "icons/128x128@2x.png", 33 | "icons/icon.icns", 34 | "icons/icon.ico" 35 | ] 36 | }, 37 | "plugins": { 38 | "updater": { 39 | "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEVBNjM3NzJGRDgxMTU4NUUKUldSZVdCSFlMM2RqNmdhK3pIZjhEYWg2WnZGSFJqdkhLSHNOSjNhaW5VQVFLaHV3YWFDTnFKWWQK", 40 | "endpoints": [ 41 | "https://github.com/R2NorthstarTools/FlightCore/releases/latest/download/latest-release.json" 42 | ] 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src-vue/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src-vue/README.md: -------------------------------------------------------------------------------- 1 | # FlightCore UI 2 | 3 | This folder holds FlightCore's interface repository. 4 | 5 | This is a [Vue (v4)](https://vuejs.org/) project, using [Element Plus](https://element-plus.org/en-US/) component library. 6 | 7 | ## Development 8 | 9 | ```shell 10 | # Install dependencies 11 | npm install 12 | 13 | # Run in development mode 14 | npm run dev 15 | 16 | # Build for production 17 | npm run build 18 | ``` 19 | -------------------------------------------------------------------------------- /src-vue/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + Vue + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src-vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "src-vue", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vue-tsc --noEmit && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@element-plus/icons-vue": "^2.0.9", 13 | "element-plus": "^2.7.8", 14 | "marked": "^14.1.3", 15 | "@tauri-apps/plugin-dialog": "^2.0.0", 16 | "@tauri-apps/plugin-shell": "^2.0.0", 17 | "@tauri-apps/plugin-store": "^2.2.0", 18 | "@tauri-apps/plugin-updater": "^2.5.1", 19 | "vue": "^3.4.35", 20 | "vue-i18n": "^9.13.1", 21 | "vue-router": "^4.4.3", 22 | "vuex": "^4.0.2" 23 | }, 24 | "devDependencies": { 25 | "@vitejs/plugin-vue": "^3.1.0", 26 | "typescript": "^5.6.3", 27 | "vite": "^3.1.0", 28 | "vue-tsc": "^2.1.10" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src-vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 87 | 88 | 216 | -------------------------------------------------------------------------------- /src-vue/src/assets/1009235.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-vue/src/assets/1009235.jpg -------------------------------------------------------------------------------- /src-vue/src/assets/mp_colony020033.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-vue/src/assets/mp_colony020033.jpg -------------------------------------------------------------------------------- /src-vue/src/assets/thunderstore-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-vue/src/assets/thunderstore-icon.png -------------------------------------------------------------------------------- /src-vue/src/assets/wallpaperflare.com_wallpaper.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/R2NorthstarTools/FlightCore/f0e46c4dd790ed9bed4e032e46e710f52e75618d/src-vue/src/assets/wallpaperflare.com_wallpaper.jpg -------------------------------------------------------------------------------- /src-vue/src/components/InstallProgressBar.vue: -------------------------------------------------------------------------------- 1 | 72 | 73 | 84 | 85 | 104 | -------------------------------------------------------------------------------- /src-vue/src/components/LanguageSelector.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 76 | -------------------------------------------------------------------------------- /src-vue/src/components/LocalModCard.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 95 | 96 | 121 | -------------------------------------------------------------------------------- /src-vue/src/components/ModsMenu.vue: -------------------------------------------------------------------------------- 1 | 57 | 58 | 90 | 91 | 142 | -------------------------------------------------------------------------------- /src-vue/src/components/NotificationButton.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 63 | 64 | 82 | -------------------------------------------------------------------------------- /src-vue/src/components/PlayButton.vue: -------------------------------------------------------------------------------- 1 | 95 | 96 | 120 | 121 | 158 | -------------------------------------------------------------------------------- /src-vue/src/components/PullRequestsSelector.vue: -------------------------------------------------------------------------------- 1 | 80 | 81 | 156 | 157 | 182 | -------------------------------------------------------------------------------- /src-vue/src/i18n/lang/da.json: -------------------------------------------------------------------------------- 1 | { 2 | "menu": { 3 | "changelog": "Ændringslog", 4 | "mods": "Mods", 5 | "settings": "Indstillinger", 6 | "dev": "Dev", 7 | "play": "Spil" 8 | }, 9 | "generic": { 10 | "yes": "Ja", 11 | "no": "Nej", 12 | "error": "Fejl", 13 | "cancel": "afbryd", 14 | "informationShort": "Info", 15 | "downloading": "Henter", 16 | "success": "Succes", 17 | "extracting": "Udpakker", 18 | "done": "Færdig" 19 | }, 20 | "play": { 21 | "button": { 22 | "select_game_dir": "Vælg Titanfall2 spil mappe", 23 | "install": "Installere", 24 | "installing": "Installer...", 25 | "update": "Opdater", 26 | "updating": "Opdatere...", 27 | "ready_to_play": "Start spil", 28 | "northstar_is_running": "Spillet køre" 29 | }, 30 | "unknown_version": "Ukendt version", 31 | "see_patch_notes": "Se patch noter", 32 | "players": "Spillere", 33 | "servers": "Servere", 34 | "northstar_running": "Northstar køre", 35 | "ea_app_running": "EA appen køre", 36 | "unable_to_load_playercount": "Kan ikke hente antallet af spillere" 37 | }, 38 | "mods": { 39 | "local": { 40 | "no_mods": "Ingen mods blev fundet.", 41 | "delete_confirm": "Er du sikker på at du vil slette dette mod?", 42 | "delete": "Slet", 43 | "success_deleting": "Sletningen af {modName} lykkedes", 44 | "part_of_ts_mod": "Dette Northstar mod er en del af et Thunderstore mod" 45 | }, 46 | "online": { 47 | "no_match": "Der er ikke fundet nogen matchende mod.", 48 | "try_another_search": "Prøv en anden søgning!" 49 | }, 50 | "menu": { 51 | "local": "Lokal", 52 | "online": "Online", 53 | "filter": "Filter", 54 | "search": "Søg", 55 | "sort_mods": "Sorter mods", 56 | "select_categories": "Vælg kategorier", 57 | "sort": { 58 | "name_asc": "navn (A til Z)", 59 | "name_desc": "navn (Z til A)", 60 | "date_asc": "Dato (fra ældste)", 61 | "most_downloaded": "Mest hentet", 62 | "top_rated": "bedst bedømt", 63 | "date_desc": "Dato (fra nyeste)" 64 | } 65 | }, 66 | "card": { 67 | "button": { 68 | "being_installed": "Installerer...", 69 | "being_updated": "Opdaterer...", 70 | "installed": "Installeret", 71 | "install": "Installere", 72 | "outdated": "Opdater" 73 | }, 74 | "by": "af", 75 | "more_info": "Mere info", 76 | "remove": "Fjern mod", 77 | "remove_dialog_title": "Advarsel", 78 | "remove_success": "Fjernet {modName}", 79 | "install_success": "Installeret {modName}", 80 | "remove_dialog_text": "Fjern Thunderstore mod?" 81 | } 82 | }, 83 | "settings": { 84 | "manage_install": "Administrer installation", 85 | "choose_folder": "Vælg installationsmappe", 86 | "open_game_folder": "Åben mappe", 87 | "nb_ts_mods_per_page": "Antal Thunderstore-mods pr. side", 88 | "nb_ts_mods_reset": "Nulstil til standard", 89 | "language": "Sprog", 90 | "language_select": "Vælg dit yndlingssprog", 91 | "about": "Om:", 92 | "flightcore_version": "FlightCore version:", 93 | "testing": "Tester:", 94 | "enable_test_channels": "Aktiver testudgivelseskanaler", 95 | "dev_mode_enabled_title": "Pas på!", 96 | "dev_mode_enabled_text": "Udviklertilstand aktiveret.", 97 | "show_deprecated_mods": "Vis forældede Thunderstore-mods", 98 | "show_deprecated_mods_desc2": "Pas på, sådanne mods er normalt forældet af en god grund.", 99 | "profile": { 100 | "active": "Aktiv profil", 101 | "edit": "Rediger profiler", 102 | "dialog": { 103 | "title": "Profiler" 104 | } 105 | }, 106 | "repair": { 107 | "title": "Reparere", 108 | "open_window": "Åbn reparationsvinduet", 109 | "window": { 110 | "title": "FlightCore reparationsvinduet", 111 | "disable_all_but_core": "Deaktiver alle undtagen kernemods", 112 | "disable_all_but_core_success": "Deaktiverede alle mods undtagen kernemods", 113 | "disable_modsettings": "Deaktiver ModSettings mod", 114 | "disable_modsettings_success": "Deaktiver ModSettings mod", 115 | "force_reinstall_ns": "Tving geninstallation Northstar", 116 | "force_delete_temp_dl": "Tving sletning af midlertidig download-mappe", 117 | "delete_persistent_store": "Slet FlightCore persistent indhold", 118 | "reinstall_title": "Tving geninstallation af Northstar", 119 | "reinstall_text": "Vent lidt", 120 | "reinstall_success": "Northstar blev geninstalleret", 121 | "warning": "Dette vindue indeholder forskellige funktioner til at reparere almindelige problemer med Northstar og FlightCore.", 122 | "kill_northstar_process": "Dræb, der kører Northstar/Titanfall2-processen" 123 | } 124 | }, 125 | "nb_ts_mods_per_page_desc1": "Dette har en indvirkning på skærmydelsen, når du gennemser Thunderstore-mods.", 126 | "nb_ts_mods_per_page_desc2": "Indstil denne værdi til 0 for at deaktivere paginering.", 127 | "show_deprecated_mods_desc1": "Dette giver dig mulighed for at se forældede mods i online-mods-samlingen." 128 | }, 129 | "notification": { 130 | "game_folder": { 131 | "new": { 132 | "title": "Ny spil mappe", 133 | "text": "Spilmappen blev opdateret." 134 | }, 135 | "wrong": { 136 | "title": "Forkert mappe", 137 | "text": "Den valgte mappe er ikke en gyldig Titanfall2 Installation." 138 | }, 139 | "not_found": { 140 | "title": "Titanfall2 ikke fundet!", 141 | "text": "Vælg venligst installationsstedet manuelt" 142 | } 143 | }, 144 | "profile": { 145 | "invalid": { 146 | "title": "Ugyldig profil", 147 | "text": "Den profil, du forsøgte at skifte til, er ikke længere gyldig." 148 | } 149 | }, 150 | "flightcore_outdated": { 151 | "title": "FlightCore forældet!", 152 | "text": "Opdater venligst FlightCore.\nKører forældet version {oldVersion}.\nNyeste er {newVersion}!" 153 | } 154 | }, 155 | "channels": { 156 | "release": { 157 | "switch": { 158 | "text": "Skiftet udgivelseskanal til \"{canal}\"." 159 | } 160 | }, 161 | "names": { 162 | "Northstar": "Northstar", 163 | "NorthstarReleaseCandidate": "Northstar udgivelseskandidat" 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src-vue/src/i18n/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "menu": { 3 | "play": "Play", 4 | "changelog": "Changelog", 5 | "mods": "Mods", 6 | "settings": "Settings", 7 | "dev": "Dev" 8 | }, 9 | 10 | "generic": { 11 | "yes": "Yes", 12 | "no": "No", 13 | "error": "Error", 14 | "confirm": "Confirm", 15 | "cancel": "Cancel", 16 | "informationShort": "Info", 17 | "downloading": "Downloading", 18 | "extracting": "Extracting", 19 | "done": "Done", 20 | "success": "Success" 21 | }, 22 | 23 | "play": { 24 | "button": { 25 | "northstar_is_running": "Game is running", 26 | "select_game_dir": "Select Titanfall2 game folder", 27 | "install": "Install", 28 | "installing": "Installing...", 29 | "update": "Update", 30 | "updating": "Updating...", 31 | "ready_to_play": "Launch game" 32 | }, 33 | 34 | "unknown_version": "Unknown version", 35 | "see_patch_notes": "see patch notes", 36 | "players": "players", 37 | "servers": "servers", 38 | "unable_to_load_playercount": "Unable to load playercount", 39 | "northstar_running": "Northstar is running:", 40 | "ea_app_running": "EA App is running:" 41 | }, 42 | 43 | "mods": { 44 | "local": { 45 | "no_mods": "No mods were found.", 46 | "delete_confirm": "Are you sure to delete this mod?", 47 | "delete": "Delete", 48 | "part_of_ts_mod": "This Northstar mod is part of a Thunderstore mod", 49 | "success_deleting": "Success deleting {modName}" 50 | }, 51 | 52 | "online": { 53 | "no_match": "No matching mod has been found.", 54 | "try_another_search": "Try another search!" 55 | }, 56 | 57 | "menu": { 58 | "local": "Local", 59 | "online": "Online", 60 | "filter": "Filter", 61 | "search": "Search", 62 | "sort_mods": "Sort mods", 63 | "select_categories": "Select categories", 64 | 65 | "sort": { 66 | "name_asc": "By name (A to Z)", 67 | "name_desc": "By name (Z to A)", 68 | "date_asc": "By date (from oldest)", 69 | "date_desc": "By date (from newest)", 70 | "most_downloaded": "Most downloaded", 71 | "top_rated": "Top rated" 72 | } 73 | }, 74 | 75 | "card": { 76 | "button": { 77 | "being_installed": "Installing...", 78 | "being_updated": "Updating...", 79 | "installed": "Installed", 80 | "install": "Install", 81 | "outdated": "Update" 82 | }, 83 | 84 | "by": "by", 85 | "more_info": "More info", 86 | "remove": "Remove mod", 87 | "remove_dialog_title": "Warning", 88 | "remove_dialog_text": "Delete Thunderstore mod?", 89 | "remove_success": "Removed {modName}", 90 | "install_success": "Installed {modName}" 91 | } 92 | }, 93 | 94 | "settings": { 95 | "manage_install": "Manage installation", 96 | "choose_folder": "Choose installation folder", 97 | "open_game_folder": "Open Folder", 98 | "nb_ts_mods_per_page": "Number of Thunderstore mods per page", 99 | "nb_ts_mods_per_page_desc1": "This has an impact on display performances when browsing Thunderstore mods.", 100 | "nb_ts_mods_per_page_desc2": "Set this value to 0 to disable pagination.", 101 | "nb_ts_mods_reset": "Reset to default", 102 | "language": "Language", 103 | "language_select": "Select your favorite language", 104 | "about": "About:", 105 | "flightcore_version": "FlightCore version:", 106 | "testing": "Testing:", 107 | "enable_test_channels": "Enable testing release channels", 108 | "dev_mode_enabled_title": "Watch out!", 109 | "dev_mode_enabled_text": "Developer mode enabled.", 110 | "show_deprecated_mods": "Show deprecated Thunderstore mods", 111 | "show_deprecated_mods_desc1": "This allows you to see deprecated mods in the online mods collection.", 112 | "show_deprecated_mods_desc2": "Watch out, such mods are usually deprecated for a good reason.", 113 | "show_nsfw_mods": "Show NSFW Thunderstore mods", 114 | 115 | "profile": { 116 | "active": "Active Profile", 117 | "edit": "Edit Profiles", 118 | 119 | "dialog": { 120 | "title": "Profiles", 121 | "delete_confirm": "Are you sure to delete this profile?", 122 | "delete": "Delete", 123 | "clone": "Clone", 124 | "new_profile_name": "Enter the new Profile name", 125 | "create_empty": "New Profile" 126 | } 127 | }, 128 | 129 | "repair": { 130 | "title": "Repair", 131 | "open_window": "Open repair window", 132 | 133 | "window": { 134 | "title": "FlightCore repair window", 135 | "warning": "This window contains various functionality to repair common issues with Northstar and FlightCore.", 136 | "disable_all_but_core": "Disable all but core mods", 137 | "disable_all_but_core_success": "Disabled all mods but core", 138 | "disable_modsettings": "Disable ModSettings mod", 139 | "disable_modsettings_success": "Disabled ModSettings mod", 140 | "force_reinstall_ns": "Force reinstall Northstar", 141 | "force_delete_temp_dl": "Force delete temp download folder", 142 | "delete_persistent_store": "Delete FlightCore persistent store", 143 | "kill_northstar_process": "Kill running Northstar/Titanfall2 process", 144 | "reinstall_title": "Force reinstalling Northstar", 145 | "reinstall_text": "Please wait", 146 | "reinstall_success": "Successfully reinstalled Northstar" 147 | } 148 | } 149 | }, 150 | 151 | "notification": { 152 | "date_prefix": "at", 153 | "no_new": { 154 | "title": "Up-to-date", 155 | "text": "Nothing to see here!" 156 | }, 157 | 158 | "game_folder": { 159 | "new": { 160 | "title": "New game folder", 161 | "text": "Game folder was successfully updated." 162 | }, 163 | 164 | "wrong": { 165 | "title": "Wrong folder", 166 | "text": "Selected folder is not a valid Titanfall2 install." 167 | }, 168 | 169 | "not_found": { 170 | "title": "Titanfall2 not found!", 171 | "text": "Please manually select install location" 172 | } 173 | }, 174 | 175 | "profile": { 176 | "invalid": { 177 | "title": "Invalid Profile", 178 | "text": "The profile you tried to switch to is no longer valid." 179 | } 180 | }, 181 | 182 | "flightcore_outdated": { 183 | "title": "FlightCore outdated!", 184 | "text": "Please update FlightCore.\nRunning outdated version {oldVersion}.\nNewest is {newVersion}!" 185 | } 186 | }, 187 | 188 | "channels": { 189 | "release": { 190 | "switch": { 191 | "text": "Switched release channel to \"{canal}\"." 192 | } 193 | }, 194 | 195 | "names": { 196 | "Northstar": "Northstar", 197 | "NorthstarReleaseCandidate": "Northstar release candidate" 198 | } 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /src-vue/src/i18n/lang/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "menu": { 3 | "mods": "Modificaciones", 4 | "settings": "Opciones", 5 | "dev": "Desarrollador", 6 | "play": "Jugar", 7 | "changelog": "Cambios" 8 | }, 9 | "generic": { 10 | "yes": "Sí", 11 | "no": "No", 12 | "error": "Error", 13 | "cancel": "Cancelar", 14 | "informationShort": "Información", 15 | "extracting": "Extrayendo", 16 | "done": "Listo", 17 | "success": "Éxito", 18 | "downloading": "Descargando", 19 | "confirm": "Confirmar" 20 | }, 21 | "play": { 22 | "button": { 23 | "northstar_is_running": "El juego ya se está ejecutando", 24 | "install": "Instalar", 25 | "update": "Actualizar", 26 | "select_game_dir": "Seleccione carpeta base de Titanfall 2", 27 | "ready_to_play": "Jugar ahora", 28 | "installing": "Instalando...", 29 | "updating": "Actualizando..." 30 | }, 31 | "ea_app_running": "La aplicación de EA ya se está ejecutando:", 32 | "unknown_version": "Versión Desconocida", 33 | "see_patch_notes": "Ver las notas del parche", 34 | "players": "jugadores", 35 | "servers": "servidores", 36 | "northstar_running": "Northstar ya se está ejecutando:", 37 | "unable_to_load_playercount": "Cantidad de jugadores no disponible" 38 | }, 39 | "mods": { 40 | "local": { 41 | "no_mods": "No hay mods encontrados.", 42 | "delete_confirm": "¿Estás segur@ que quieres eliminar este mod?", 43 | "delete": "Eliminar", 44 | "success_deleting": "{modName} Ha sido eliminado correctamente", 45 | "part_of_ts_mod": "Este mod de Northstar es parte de un mod de la ThunderStore" 46 | }, 47 | "online": { 48 | "no_match": "No hay mods coincidentes.", 49 | "try_another_search": "Intente otra busqueda!" 50 | }, 51 | "menu": { 52 | "local": "Local", 53 | "online": "En línea", 54 | "filter": "FIltro", 55 | "search": "Búsqueda", 56 | "sort_mods": "Ordenar mods", 57 | "select_categories": "Seleccionar categorías", 58 | "sort": { 59 | "name_asc": "Por nombre (de la A a la Z)", 60 | "date_asc": "Por fecha (desde la más antigua)", 61 | "date_desc": "Por fecha (desde la más reciente)", 62 | "most_downloaded": "Los más descargados", 63 | "top_rated": "Mejor valorados", 64 | "name_desc": "Por nombre (de la Z a la A)" 65 | } 66 | }, 67 | "card": { 68 | "button": { 69 | "being_installed": "Instalando...", 70 | "being_updated": "Actualizando...", 71 | "installed": "Instalado", 72 | "outdated": "Actualizar", 73 | "install": "Instalar" 74 | }, 75 | "by": "por", 76 | "remove": "Quitar mod", 77 | "remove_dialog_title": "Advertencia", 78 | "remove_dialog_text": "Eliminar mod de la ThunderStore?", 79 | "install_success": "{modName} Instalado", 80 | "more_info": "Mas información", 81 | "remove_success": "{modName} Ha sido eliminado" 82 | } 83 | }, 84 | "settings": { 85 | "manage_install": "Administrar instalación", 86 | "choose_folder": "Elegir carpeta de instalación", 87 | "open_game_folder": "Abrir carpeta", 88 | "nb_ts_mods_per_page": "Numero de mods por página de ThunderStore", 89 | "nb_ts_mods_per_page_desc2": "Poner valor en 0 para desactivar la paginación.", 90 | "nb_ts_mods_reset": "Reestablecer por defecto", 91 | "language": "Idioma", 92 | "language_select": "Seleccionar idioma favorito", 93 | "about": "Acerca de:", 94 | "flightcore_version": "Versión de FlightCore:", 95 | "testing": "Probando:", 96 | "enable_test_channels": "Activar liberación de canales", 97 | "dev_mode_enabled_title": "¡Cuidado!", 98 | "dev_mode_enabled_text": "Modo de desarrollador activado.", 99 | "show_deprecated_mods_desc1": "Esto permite ver mods obsoletos de la colección online de ThunderStore.", 100 | "show_deprecated_mods_desc2": "Cuidado, estos mods suelen estar obsoletos por una buena razón.", 101 | "profile": { 102 | "active": "Perfil activo", 103 | "edit": "Editar perfiles", 104 | "dialog": { 105 | "title": "Perfiles", 106 | "delete_confirm": "Eliminar Perfil?", 107 | "delete": "Eliminar", 108 | "clone": "Duplicar" 109 | } 110 | }, 111 | "repair": { 112 | "title": "Reparar", 113 | "window": { 114 | "title": "Ventana de reparación de FlightCore", 115 | "disable_all_but_core": "Desactivar todos los mods excepto los principales", 116 | "disable_all_but_core_success": "Desactivados todos los mods excepto el núcleo", 117 | "disable_modsettings": "Desactivar ModSettings", 118 | "disable_modsettings_success": "ModSettings desactivado", 119 | "force_reinstall_ns": "Forzar reinstalación de Northstar", 120 | "force_delete_temp_dl": "Forzar la eliminación de la carpeta temporal de descargas", 121 | "delete_persistent_store": "Borrar el almacén persistente de FlightCore", 122 | "reinstall_title": "Forzar la reinstalación de Northstar", 123 | "reinstall_text": "Espere, por favor", 124 | "reinstall_success": "Northstar reinstalado con éxito", 125 | "warning": "Esta ventana tiene varias funciones para reparar problemas comunes con Northstar y FlightCore.", 126 | "kill_northstar_process": "Finalizar proceso de Northstar/Titanfall 2" 127 | }, 128 | "open_window": "Abrir la ventana de reparación" 129 | }, 130 | "nb_ts_mods_per_page_desc1": "Esto puede tener impactos en fluidez al buscar mods en la ThunderStore.", 131 | "show_deprecated_mods": "Mostrar mods the ThunderStore obsoletos" 132 | }, 133 | "notification": { 134 | "game_folder": { 135 | "new": { 136 | "title": "Nueva carpeta de juego", 137 | "text": "La carpeta de juego fue actualizada exitosamente." 138 | }, 139 | "wrong": { 140 | "title": "Carpeta equivocada", 141 | "text": "La carpeta seleccionada no es una carpeta de Titanfall2 válida." 142 | }, 143 | "not_found": { 144 | "title": "Titanfall 2 no encontrado!", 145 | "text": "Por favor seleccione manualmente el lugar de instalación" 146 | } 147 | }, 148 | "profile": { 149 | "invalid": { 150 | "title": "Perfil inválido", 151 | "text": "El perfil de cambio anterior ya no es válido." 152 | } 153 | }, 154 | "flightcore_outdated": { 155 | "title": "FlightCore desactualizado!", 156 | "text": "Por favor actualize FlightCore.\nEsta versión esta desactualizada {oldVersion}\nLa versión mas nueva es {newVersion}!" 157 | }, 158 | "no_new": { 159 | "title": "Al día", 160 | "text": "Nada que ver aquí!" 161 | }, 162 | "date_prefix": "en" 163 | }, 164 | "channels": { 165 | "release": { 166 | "switch": { 167 | "text": "El canal seleccionado se cambió a \"{canal}\"." 168 | } 169 | }, 170 | "names": { 171 | "Northstar": "Northstar", 172 | "NorthstarReleaseCandidate": "Candidato de nueva versión de Northstar" 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src-vue/src/i18n/lang/it.json: -------------------------------------------------------------------------------- 1 | { 2 | "generic": { 3 | "yes": "Si", 4 | "no": "No", 5 | "error": "Errore", 6 | "cancel": "Cancella", 7 | "downloading": "Scaricando", 8 | "extracting": "Estraendo", 9 | "done": "Fatto", 10 | "success": "Successo", 11 | "informationShort": "Info", 12 | "confirm": "Conferma" 13 | }, 14 | "play": { 15 | "unknown_version": "Versione sconosciuta", 16 | "unable_to_load_playercount": "Impossibile caricare numero giocatori", 17 | "northstar_running": "Northstar sta andando:", 18 | "origin_running": "Origin sta andando:", 19 | "see_patch_notes": "guarda le note della patch", 20 | "players": "Giocatori", 21 | "servers": "Server", 22 | "button": { 23 | "northstar_is_running": "Il Gioco sta andando", 24 | "install": "Installa", 25 | "installing": "Installazione...", 26 | "update": "Aggiorna", 27 | "updating": "Aggiornamento...", 28 | "ready_to_play": "Gioca", 29 | "select_game_dir": "Seleziona la cartella di Titanfall 2" 30 | }, 31 | "ea_app_running": "EA App sta andando:" 32 | }, 33 | "mods": { 34 | "local": { 35 | "no_mods": "Nessuna mod è stata trovata.", 36 | "delete_confirm": "Sei sicuro di voler eliminare questa mod?", 37 | "part_of_ts_mod": "Questa Northstar mod è parte di una Thunderstore mod", 38 | "success_deleting": "{modName} Eliminata con successo", 39 | "delete": "Elimina" 40 | }, 41 | "online": { 42 | "no_match": "Nessuna mod corrispondente trovata.", 43 | "try_another_search": "Prova un'altra ricerca!" 44 | }, 45 | "menu": { 46 | "local": "Locale", 47 | "filter": "Filtra", 48 | "online": "Online", 49 | "search": "Cerca", 50 | "sort_mods": "Sorteggia mods", 51 | "select_categories": "Seleziona categorie", 52 | "sort": { 53 | "name_asc": "Per nome (da A alla Z)", 54 | "name_desc": "Per nome (da Z alla A)", 55 | "date_asc": "Per data (dal più vecchio)", 56 | "date_desc": "Per data (dal più recente)", 57 | "most_downloaded": "Più scaricate", 58 | "top_rated": "Più votate" 59 | } 60 | }, 61 | "card": { 62 | "button": { 63 | "being_updated": "Aggiornando...", 64 | "installed": "Installato", 65 | "being_installed": "Installando...", 66 | "install": "Installa", 67 | "outdated": "Aggiorna" 68 | }, 69 | "by": "per", 70 | "more_info": "Più informazioni", 71 | "remove": "Rimuovi mod", 72 | "remove_dialog_title": "Attenzione", 73 | "remove_dialog_text": "Eliminare Thunderstore mod?", 74 | "remove_success": "{modName} Rimossa", 75 | "install_success": "{modName} Installata" 76 | } 77 | }, 78 | "menu": { 79 | "mods": "Mods", 80 | "settings": "Impostazioni", 81 | "dev": "Dev", 82 | "play": "Gioca", 83 | "changelog": "Note" 84 | }, 85 | "notification": { 86 | "game_folder": { 87 | "wrong": { 88 | "title": "Cartella errata", 89 | "text": "La cartella selezionata non ha un'installazione di Titanfall2 valida." 90 | }, 91 | "new": { 92 | "title": "Nuova cartella di gioco", 93 | "text": "Cartella di gioco aggiornata con successo." 94 | }, 95 | "not_found": { 96 | "title": "Titanfall2 non trovato!", 97 | "text": "Per favore selezionare manualmente la posizione dell'installazione" 98 | } 99 | }, 100 | "flightcore_outdated": { 101 | "title": "FlightCore fuori data!", 102 | "text": "Per favore aggiorna FlightCore.\nVersione in uso {oldVersion} fuori data.\nLa più recente è {newVersion}!" 103 | }, 104 | "no_new": { 105 | "text": "Niente da vedere qui!", 106 | "title": "Aggiornato" 107 | }, 108 | "profile": { 109 | "invalid": { 110 | "text": "Il profilo a cui hai provato ad accedere non è più valido.", 111 | "title": "Profilo non valido" 112 | } 113 | } 114 | }, 115 | "settings": { 116 | "manage_install": "Gestisci l'installazione", 117 | "choose_folder": "Scegli la cartella dell'installazione", 118 | "open_game_folder": "Apri Cartella", 119 | "nb_ts_mods_per_page": "Numero di Thunderstore mods per pagina", 120 | "nb_ts_mods_per_page_desc1": "Questo ha un impatto sulle performazioni schermo mentre si navigano le Thunderstore mods.", 121 | "nb_ts_mods_per_page_desc2": "Cambiare questo valore a 0 per disattivare la paginazione.", 122 | "nb_ts_mods_reset": "Resetta a default", 123 | "language": "Lingua", 124 | "language_select": "Seleziona la tua lingua preferito", 125 | "about": "Al riguardo:", 126 | "flightcore_version": "Versione FlighCore:", 127 | "testing": "Testando:", 128 | "enable_test_channels": "Abilita i canali del test di rilascio", 129 | "dev_mode_enabled_title": "Attenzione!", 130 | "dev_mode_enabled_text": "Modalità Sviluppatore attivata.", 131 | "repair": { 132 | "title": "Ripara", 133 | "open_window": "Apri finestra di riparazione", 134 | "window": { 135 | "title": "Finestra riparazione di FlightCore", 136 | "warning": "Questa finestra contiene varie funzionalità per riparare problemi comuni con Northstar e FlightCore.", 137 | "disable_all_but_core": "Disattiva tutte le mods (eccetto quelle di Northstar)", 138 | "disable_all_but_core_success": "Disattivate tutte le mods (eccetto quelle di Northstar)", 139 | "force_reinstall_ns": "Forza reinstallazione di Northstar", 140 | "force_delete_temp_dl": "Forza l'eliminazione della cartella dei download temporanei", 141 | "delete_persistent_store": "Elimina lo spazio d'archiviazione persistente di FlightCore", 142 | "reinstall_title": "Reinstallando Northstar forzatamente", 143 | "reinstall_text": "Attendere per favore", 144 | "reinstall_success": "Northstar reinstallato con successo", 145 | "kill_northstar_process": "Ferma il processo Northstar/Titanfall2 in esecuzione", 146 | "disable_modsettings_success": "ModSettings disabilitata", 147 | "disable_modsettings": "Disabilita la mod ModSettings" 148 | } 149 | }, 150 | "profile": { 151 | "active": "Profilo attivo", 152 | "dialog": { 153 | "clone": "Clona", 154 | "delete": "Elimina", 155 | "delete_confirm": "Sei sicuro di voler eliminare questo profilo?", 156 | "title": "Profili" 157 | }, 158 | "edit": "Modifica profilo" 159 | }, 160 | "show_deprecated_mods": "Mostra mod di Thunderstore deprecate", 161 | "show_deprecated_mods_desc2": "Fai attenzione, alcune mod di solito sono deprecate per un buon motivo.", 162 | "show_deprecated_mods_desc1": "Permette di vedere le mod deprecate nella collezione online." 163 | }, 164 | "channels": { 165 | "release": { 166 | "switch": { 167 | "text": "Cambiato il canale di rilascio a \"{canal}\"." 168 | } 169 | }, 170 | "names": { 171 | "Northstar": "Northstar", 172 | "NorthstarReleaseCandidate": "Northstar versione pre-rilascio" 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src-vue/src/i18n/lang/pl.json: -------------------------------------------------------------------------------- 1 | { 2 | "menu": { 3 | "changelog": "Dziennik zmian", 4 | "mods": "Mody", 5 | "settings": "Ustawienia", 6 | "dev": "Dev", 7 | "play": "Graj" 8 | }, 9 | "generic": { 10 | "yes": "Tak", 11 | "no": "Nie", 12 | "error": "Błąd", 13 | "cancel": "Anuluj", 14 | "downloading": "Pobieranie", 15 | "extracting": "Wypakowywanie", 16 | "done": "Gotowe", 17 | "success": "Sukces", 18 | "informationShort": "Informacja", 19 | "confirm": "Potwierdź" 20 | }, 21 | "play": { 22 | "button": { 23 | "northstar_is_running": "Gra jest uruchomiona", 24 | "select_game_dir": "Wybierz folder gry Titanfall2", 25 | "install": "Zainstaluj", 26 | "update": "Aktualizuj", 27 | "updating": "Aktualizowanie...", 28 | "ready_to_play": "Uruchom grę", 29 | "installing": "Instalowanie..." 30 | }, 31 | "unknown_version": "Nieznana wersja", 32 | "see_patch_notes": "zobacz listę zmian", 33 | "players": "gracze", 34 | "servers": "serwery", 35 | "northstar_running": "Northstar jest uruchomiony:", 36 | "ea_app_running": "EA App jest uruchomiony:", 37 | "unable_to_load_playercount": "Nie można załadować liczby graczy" 38 | }, 39 | "mods": { 40 | "local": { 41 | "no_mods": "Nie znaleziono żadnych modów.", 42 | "delete_confirm": "Czy na pewno chcesz usunąć ten mod?", 43 | "delete": "Usuń", 44 | "success_deleting": "Sukces usuwania {modName}", 45 | "part_of_ts_mod": "Ten mod Northstar jest częścią moda Thunderstore" 46 | }, 47 | "online": { 48 | "no_match": "Nie znaleziono pasującego moda.", 49 | "try_another_search": "Spróbuj innego wyszukiwania!" 50 | }, 51 | "menu": { 52 | "local": "Lokalne", 53 | "online": "Online", 54 | "filter": "Filtry", 55 | "search": "Szukaj", 56 | "sort_mods": "Sortowanie modów", 57 | "select_categories": "Wybierz kategorie", 58 | "sort": { 59 | "name_asc": "Według nazwy (od A do Z)", 60 | "name_desc": "Według nazwy (od Z do A)", 61 | "date_desc": "Według daty (od najnowszej)", 62 | "most_downloaded": "Najczęściej pobierane", 63 | "top_rated": "Najwyżej ocenione", 64 | "date_asc": "Według daty (od najstarszej)" 65 | } 66 | }, 67 | "card": { 68 | "button": { 69 | "being_installed": "Instalowanie...", 70 | "being_updated": "Aktualizowanie...", 71 | "installed": "Zainstalowano", 72 | "install": "Zainstaluj", 73 | "outdated": "Aktualizuj" 74 | }, 75 | "by": "od", 76 | "more_info": "Więcej informacji", 77 | "remove": "Usuń moda", 78 | "remove_dialog_title": "Ostrzeżenie", 79 | "remove_dialog_text": "Usunąć mod Thunderstore?", 80 | "remove_success": "Usunięto {modName}", 81 | "install_success": "Zainstalowano {modName}" 82 | } 83 | }, 84 | "settings": { 85 | "manage_install": "Zarządzaj instalacją", 86 | "choose_folder": "Wybierz folder instalacyjny", 87 | "nb_ts_mods_per_page": "Liczba modów Thunderstore na stronie", 88 | "nb_ts_mods_per_page_desc2": "Ustaw tę wartość na 0, aby wyłączyć paginację.", 89 | "nb_ts_mods_reset": "Przywrócenie ustawień domyślnych", 90 | "language": "Język", 91 | "language_select": "Wybierz swój ulubiony język", 92 | "about": "O:", 93 | "flightcore_version": "Wersja FlightCore:", 94 | "testing": "Testy:", 95 | "enable_test_channels": "Włączenie kanałów wydań testowych", 96 | "dev_mode_enabled_title": "Uważaj!", 97 | "dev_mode_enabled_text": "Tryb deweloperski włączony.", 98 | "repair": { 99 | "title": "Naprawa", 100 | "open_window": "Otwórz okno naprawy", 101 | "window": { 102 | "disable_all_but_core": "Wyłączenie wszystkich modów poza podstawowymi", 103 | "disable_all_but_core_success": "Wyłączone wszystkie mody oprócz podstawowych", 104 | "force_reinstall_ns": "Wymuś reinstalację Northstara", 105 | "force_delete_temp_dl": "Wymuś usunięcie folderu tymczasowego pobierania", 106 | "delete_persistent_store": "Usuń stały magazyn FlightCore", 107 | "reinstall_title": "Wymuszona reinstalacja Northstara", 108 | "reinstall_text": "Proszę czekać", 109 | "reinstall_success": "Pomyślnie przeinstalowano Northstar", 110 | "title": "Okno naprawy FlightCore", 111 | "warning": "To okno zawiera różne funkcje do naprawy typowych problemów z Northstar i FlightCore.", 112 | "disable_modsettings": "Wyłącz moda ModSettings", 113 | "disable_modsettings_success": "Wyłączono moda ModSettings", 114 | "kill_northstar_process": "Zamknij uruchomiony proces Northstar/Titanfall2" 115 | } 116 | }, 117 | "nb_ts_mods_per_page_desc1": "Ma to wpływ na wydajność wyświetlania podczas przeglądania modów Thunderstore.", 118 | "open_game_folder": "Otwórz folder", 119 | "show_deprecated_mods_desc2": "Ostrożnie, mody są zazwyczaj oznaczone jako przestarzałe nie bez powodu.", 120 | "show_deprecated_mods": "Pokaż przestarzałe mody Thunderstore", 121 | "show_deprecated_mods_desc1": "Pozwala to zobaczyć przestarzałe mody w kolekcji modów online.", 122 | "profile": { 123 | "active": "Aktywny profil", 124 | "dialog": { 125 | "title": "Profile", 126 | "delete": "Usuń", 127 | "clone": "Klonuj", 128 | "new_profile_name": "Wprowadź nową nazwę profilu", 129 | "create_empty": "Nowy profil", 130 | "delete_confirm": "Czy na pewno chcesz usunąć ten profil?" 131 | }, 132 | "edit": "Edytuj profile" 133 | } 134 | }, 135 | "notification": { 136 | "game_folder": { 137 | "new": { 138 | "title": "Nowy folder z grą", 139 | "text": "Folder gry został pomyślnie zaktualizowany." 140 | }, 141 | "wrong": { 142 | "title": "Niewłaściwy folder", 143 | "text": "Wybrany folder nie jest poprawną instalacją Titanfall2." 144 | }, 145 | "not_found": { 146 | "title": "Nie znaleziono Titanfall2!", 147 | "text": "Proszę ręcznie wybrać lokalizację instalacji" 148 | } 149 | }, 150 | "flightcore_outdated": { 151 | "title": "FlightCore nieaktualny!", 152 | "text": "Proszę zaktualizować FlightCore.\nUruchomiono przestarzałą wersję {oldVersion}.\nNajnowsza to {newVersion}!" 153 | }, 154 | "profile": { 155 | "invalid": { 156 | "title": "Nieprawidłowy profil", 157 | "text": "Profil, na który próbowano się przełączyć, nie jest już prawidłowy." 158 | } 159 | }, 160 | "no_new": { 161 | "title": "Aktualny", 162 | "text": "Nie ma tu nic do obejrzenia!" 163 | }, 164 | "date_prefix": "na" 165 | }, 166 | "channels": { 167 | "release": { 168 | "switch": { 169 | "text": "Przełączono kanał wydań na \"{canal}\"." 170 | } 171 | }, 172 | "names": { 173 | "Northstar": "Northstar", 174 | "NorthstarReleaseCandidate": "Kandydat do wydania Northstar" 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src-vue/src/i18n/lang/ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "generic": { 3 | "yes": "Да", 4 | "no": "Нет", 5 | "extracting": "Распаковывание", 6 | "done": "Готово", 7 | "success": "Успешно", 8 | "error": "Ошибка", 9 | "cancel": "Отмена", 10 | "informationShort": "Информация", 11 | "downloading": "Скачивание", 12 | "confirm": "Подтвердить" 13 | }, 14 | "menu": { 15 | "mods": "Моды", 16 | "play": "Играть", 17 | "settings": "Настройки", 18 | "dev": "Разработчик", 19 | "changelog": "Обновления" 20 | }, 21 | "play": { 22 | "button": { 23 | "northstar_is_running": "Игра запущена", 24 | "install": "Установить", 25 | "installing": "Установка...", 26 | "updating": "Обновление...", 27 | "ready_to_play": "Запустить игру", 28 | "update": "Обновить", 29 | "select_game_dir": "Выберите папку с Titanfall 2" 30 | }, 31 | "unknown_version": "Неизвестная версия", 32 | "players": "игроков", 33 | "servers": "серверов", 34 | "unable_to_load_playercount": "Не можем загрузить количество игроков", 35 | "northstar_running": "Northstar запущен:", 36 | "ea_app_running": "EA App запущен:", 37 | "see_patch_notes": "просмотреть список изменений" 38 | }, 39 | "mods": { 40 | "local": { 41 | "delete_confirm": "Вы уверены, что хотите удалить этот мод?", 42 | "delete": "Удалить", 43 | "success_deleting": "{modName} Успешно удален", 44 | "no_mods": "Моды не найдены.", 45 | "part_of_ts_mod": "Этот мод Northstar является частью мода на Thunderstore" 46 | }, 47 | "online": { 48 | "no_match": "Не найдено совпадающих модов.", 49 | "try_another_search": "Попробуйте другой запрос!" 50 | }, 51 | "menu": { 52 | "online": "Онлайн", 53 | "filter": "Фильтр", 54 | "search": "Поиск", 55 | "sort_mods": "Сортировать моды", 56 | "sort": { 57 | "name_asc": "По имени (от A до Z)", 58 | "name_desc": "По имени (от Z до A)", 59 | "date_asc": "По дате (со старейшего)", 60 | "date_desc": "По дате (с новейшего)", 61 | "top_rated": "Самый популярный", 62 | "most_downloaded": "Самый загружаемый" 63 | }, 64 | "local": "Установленные", 65 | "select_categories": "Выбрать категории" 66 | }, 67 | "card": { 68 | "button": { 69 | "being_installed": "Установка...", 70 | "being_updated": "Обновление...", 71 | "installed": "Установлен", 72 | "install": "Установить", 73 | "outdated": "Обновить" 74 | }, 75 | "by": "от", 76 | "remove": "Удалить мод", 77 | "remove_dialog_title": "Внимание", 78 | "remove_dialog_text": "Удалить мод Thunderstore?", 79 | "remove_success": "{modName} Удален", 80 | "more_info": "Подробнее", 81 | "install_success": "{modName} Установлен" 82 | } 83 | }, 84 | "settings": { 85 | "manage_install": "Управлять установкой", 86 | "choose_folder": "Выберите папку установки", 87 | "open_game_folder": "Открыть папку", 88 | "nb_ts_mods_reset": "Вернуть по умолчанию", 89 | "language": "Язык", 90 | "language_select": "Выберите свой любимый язык", 91 | "testing": "Тестирование:", 92 | "enable_test_channels": "Включить каналы с тестовыми релизами", 93 | "dev_mode_enabled_title": "Осторожно!", 94 | "repair": { 95 | "open_window": "Открыть окно фиксов", 96 | "window": { 97 | "title": "Окно фиксов FlightCore", 98 | "force_reinstall_ns": "Принудительно переустановить Northstar", 99 | "delete_persistent_store": "Удалить постоянное хранилище FlightCore", 100 | "reinstall_title": "Принудительно переустанавливаем Northstar", 101 | "reinstall_text": "Пожалуйста, подождите", 102 | "disable_all_but_core_success": "Выключены все моды кроме главных", 103 | "disable_all_but_core": "Выключить все моды, кроме главных", 104 | "warning": "Это окно содержит различные функции для устранения часто возникающих проблем с Northstar и FlightCore.", 105 | "force_delete_temp_dl": "Принудительно удалить папку с временными загрузками", 106 | "reinstall_success": "Northstar успешно переустановлен", 107 | "disable_modsettings": "Выключить мод ModSettings", 108 | "disable_modsettings_success": "Выключен мод ModSettings", 109 | "kill_northstar_process": "Закрыть запущенный Northstar/Titanfall 2" 110 | }, 111 | "title": "Фиксы" 112 | }, 113 | "nb_ts_mods_per_page_desc1": "Это влияет на производительность при просмотре модов с Thunderstore.", 114 | "about": "Информация:", 115 | "nb_ts_mods_per_page": "Количество модов Thunderstore на каждую страницу", 116 | "nb_ts_mods_per_page_desc2": "Установите это значение на 0, чтобы отключить страницы.", 117 | "flightcore_version": "Версия FlightCore:", 118 | "dev_mode_enabled_text": "Включен режим разработчика.", 119 | "show_deprecated_mods": "Показать устаревшие моды Thunderstore", 120 | "show_deprecated_mods_desc1": "Это позволяет вам видеть устаревшие моды в меню онлайн модов.", 121 | "show_deprecated_mods_desc2": "Внимание, такие моды обычно устаревшие по хорошей причине.", 122 | "profile": { 123 | "active": "Активный Профиль", 124 | "edit": "Редактировать Профили", 125 | "dialog": { 126 | "title": "Профили", 127 | "clone": "Копировать", 128 | "delete": "Удалить", 129 | "delete_confirm": "Вы уверены, что хотите удалить этот профиль?", 130 | "new_profile_name": "Введите новое имя профиля", 131 | "create_empty": "Новый профиль" 132 | } 133 | }, 134 | "show_nsfw_mods": "Показывать NSFW-моды с Thunderstore" 135 | }, 136 | "notification": { 137 | "game_folder": { 138 | "new": { 139 | "title": "Новая папка игры", 140 | "text": "Папка игры успешно обновлена." 141 | }, 142 | "wrong": { 143 | "title": "Неправильная папка", 144 | "text": "Выбранная папка не является папкой с Titanfall 2." 145 | }, 146 | "not_found": { 147 | "title": "Titanfall 2 не найден!", 148 | "text": "Пожалуйста, вручную выберите место установки" 149 | } 150 | }, 151 | "flightcore_outdated": { 152 | "title": "FlightCore устарел!", 153 | "text": "Пожалуйста, обновите FlightCore\nСейчас запущена старая версия - {oldVersion}.\nНовейшая версия - {newVersion}!" 154 | }, 155 | "profile": { 156 | "invalid": { 157 | "title": "Некорректный Профиль", 158 | "text": "Профиль, на который вы пытаетесь переключиться, больше не является корректным." 159 | } 160 | }, 161 | "no_new": { 162 | "text": "Смотреть здесь нечего!", 163 | "title": "Нет уведомлений" 164 | }, 165 | "date_prefix": "в" 166 | }, 167 | "channels": { 168 | "release": { 169 | "switch": { 170 | "text": "Релизный канал переключен на \"{canal}\"." 171 | } 172 | }, 173 | "names": { 174 | "Northstar": "Northstar", 175 | "NorthstarReleaseCandidate": "Пре-релизная версия Northstar" 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src-vue/src/i18n/lang/zh_Hans.json: -------------------------------------------------------------------------------- 1 | { 2 | "menu": { 3 | "mods": "模组", 4 | "settings": "设置", 5 | "dev": "开发者模式", 6 | "play": "开始游玩", 7 | "changelog": "更新日志" 8 | }, 9 | "generic": { 10 | "error": "错误", 11 | "cancel": "取消", 12 | "yes": "是", 13 | "no": "否", 14 | "informationShort": "信息", 15 | "downloading": "下载中", 16 | "extracting": "解压中", 17 | "done": "完成", 18 | "success": "成功", 19 | "confirm": "确认" 20 | }, 21 | "play": { 22 | "button": { 23 | "northstar_is_running": "游戏正在运行", 24 | "select_game_dir": "选择Titanfall 2游戏目录", 25 | "install": "安装", 26 | "installing": "安装中...", 27 | "update": "升级", 28 | "ready_to_play": "启动游戏", 29 | "updating": "升级中..." 30 | }, 31 | "unknown_version": "未知版本", 32 | "see_patch_notes": "参阅相关补丁说明", 33 | "servers": "服务器", 34 | "players": "玩家", 35 | "unable_to_load_playercount": "加载玩家数量失败", 36 | "ea_app_running": "EA App运行状态:", 37 | "northstar_running": "Northstar运行状态:" 38 | }, 39 | "mods": { 40 | "local": { 41 | "no_mods": "未找到模组。", 42 | "delete_confirm": "你确定要删除该模组吗?", 43 | "delete": "删除", 44 | "part_of_ts_mod": "该Northstar模组来源于Thunderstore", 45 | "success_deleting": "成功删除 {modName}" 46 | }, 47 | "online": { 48 | "try_another_search": "尝试其他搜索方式!", 49 | "no_match": "未找到相匹配的模组。" 50 | }, 51 | "menu": { 52 | "local": "本地", 53 | "search": "搜索", 54 | "sort_mods": "模组排序", 55 | "select_categories": "标签选择", 56 | "sort": { 57 | "date_desc": "日期降序", 58 | "date_asc": "日期升序", 59 | "name_desc": "按名称(Z到A)", 60 | "most_downloaded": "最多下载", 61 | "top_rated": "最高评分", 62 | "name_asc": "按名称(A到Z)" 63 | }, 64 | "online": "线上", 65 | "filter": "筛选" 66 | }, 67 | "card": { 68 | "button": { 69 | "being_installed": "安装中...", 70 | "being_updated": "升级中...", 71 | "installed": "已安装", 72 | "install": "安装", 73 | "outdated": "升级" 74 | }, 75 | "by": "作者:", 76 | "remove": "移除模组", 77 | "remove_dialog_title": "警告", 78 | "remove_success": "已移除{modName}", 79 | "install_success": "已安装 {modName}", 80 | "more_info": "更多信息", 81 | "remove_dialog_text": "删除该来自Thunderstore的模组?" 82 | } 83 | }, 84 | "settings": { 85 | "manage_install": "安装管理", 86 | "choose_folder": "选择安装目录", 87 | "open_game_folder": "打开文件夹", 88 | "nb_ts_mods_per_page": "Thunderstore每页显示多少个模组", 89 | "nb_ts_mods_per_page_desc2": "该值设为0时将不再显示页码。", 90 | "nb_ts_mods_reset": "重置为默认值", 91 | "language": "语言", 92 | "language_select": "请选择你需要的语言", 93 | "about": "关于:", 94 | "flightcore_version": "FlightCore 版本:", 95 | "testing": "测试选项:", 96 | "enable_test_channels": "开启测试版本选项", 97 | "nb_ts_mods_per_page_desc1": "该数值对加载Thunderstore页面时的速度有影响。", 98 | "dev_mode_enabled_title": "看上面!", 99 | "dev_mode_enabled_text": "开发者模式已启用。", 100 | "show_deprecated_mods": "显示已弃用的Thunderstore模组", 101 | "show_deprecated_mods_desc1": "该选项会使您可以在线上模组合集中看到已弃用的模组。", 102 | "show_deprecated_mods_desc2": "请注意,这类模组被弃用一般是有原因的。", 103 | "repair": { 104 | "title": "修复", 105 | "window": { 106 | "title": "FlightCore 修复工具", 107 | "warning": "此工具包含修复Northstar和FlightCore各种常见问题的功能。", 108 | "disable_all_but_core": "除了核心模组以外禁用其他模组", 109 | "disable_all_but_core_success": "已禁用除核心模组以外的所有模组", 110 | "disable_modsettings": "禁用ModSettings模组", 111 | "disable_modsettings_success": "已禁用ModSettings模组", 112 | "force_delete_temp_dl": "强制删除临时下载目录", 113 | "delete_persistent_store": "删除FlightCore永久存储文件", 114 | "reinstall_text": "请耐心等待", 115 | "reinstall_success": "成功重装Northstar", 116 | "force_reinstall_ns": "强制重装Northstar", 117 | "reinstall_title": "正在强制重装Northstar", 118 | "kill_northstar_process": "终止正在运行的 Northstar/Titanfall2 进程" 119 | }, 120 | "open_window": "打开修复工具" 121 | }, 122 | "profile": { 123 | "active": "当前用户配置", 124 | "edit": "编辑用户配置", 125 | "dialog": { 126 | "title": "用户配置", 127 | "delete_confirm": "你确定要删除此配置文件吗?", 128 | "delete": "删除" 129 | } 130 | } 131 | }, 132 | "notification": { 133 | "game_folder": { 134 | "new": { 135 | "title": "新的游戏目录", 136 | "text": "已成功更新游戏目录。" 137 | }, 138 | "wrong": { 139 | "title": "错误的文件夹", 140 | "text": "所选文件夹不是有效的Titanfall2安装目录。" 141 | }, 142 | "not_found": { 143 | "title": "未找到Titanfall2!", 144 | "text": "请手动选择安装目录" 145 | } 146 | }, 147 | "flightcore_outdated": { 148 | "title": "FlightCore需要更新!", 149 | "text": "请更新FlightCore.\n正在运行旧版本 {oldVersion}.\n最新版本为 {newVersion}!" 150 | }, 151 | "profile": { 152 | "invalid": { 153 | "title": "无效用户配置", 154 | "text": "您尝试切换到的用户配置已失效。" 155 | } 156 | } 157 | }, 158 | "channels": { 159 | "release": { 160 | "switch": { 161 | "text": "将资源版本切换至 \"{canal}\"." 162 | } 163 | }, 164 | "names": { 165 | "NorthstarReleaseCandidate": "Northstar测试版本", 166 | "Northstar": "Northstar" 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src-vue/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import { createI18n } from "vue-i18n"; 3 | import App from './App.vue' 4 | import ElementPlus from "element-plus"; 5 | import * as ElementPlusIconsVue from '@element-plus/icons-vue' 6 | import { store } from './plugins/store'; 7 | import PlayView from "./views/PlayView.vue"; 8 | import ChangelogView from "./views/ChangelogView.vue"; 9 | import ModsView from "./views/ModsView.vue"; 10 | import SettingsView from "./views/SettingsView.vue"; 11 | import DeveloperView from "./views/DeveloperView.vue"; 12 | import RepairView from "./views/RepairView.vue"; 13 | import {createRouter, createWebHashHistory} from "vue-router"; 14 | import en from "./i18n/lang/en.json"; 15 | import fr from "./i18n/lang/fr.json"; 16 | import da from "./i18n/lang/da.json"; 17 | import de from "./i18n/lang/de.json"; 18 | import es from "./i18n/lang/es.json"; 19 | import pl from "./i18n/lang/pl.json"; 20 | import ru from "./i18n/lang/ru.json"; 21 | import it from "./i18n/lang/it.json"; 22 | import zh_Hans from "./i18n/lang/zh_Hans.json"; 23 | 24 | 25 | const app = createApp(App); 26 | 27 | // internationalization 28 | export const i18n = createI18n({ 29 | locale: 'en', 30 | fallbackLocale: 'en', 31 | messages: { 32 | en, fr, da, de, es, pl, ru, it, zh_Hans 33 | } 34 | }); 35 | app.use(i18n); 36 | 37 | // styles 38 | import 'element-plus/theme-chalk/index.css'; 39 | import './style.css' 40 | 41 | app.use(ElementPlus); 42 | 43 | // icons 44 | for (const [key, component] of Object.entries(ElementPlusIconsVue)) { 45 | app.component(key, component); 46 | } 47 | 48 | // style 49 | app.use( store, '$store' ); 50 | 51 | 52 | // routes 53 | const routes = [ 54 | { path: '/', name: 'Main', component: async () => PlayView}, 55 | { path: '/changelog', name: 'Changelog', component: async () => ChangelogView}, 56 | { path: '/mods', name: 'Mods', component: async () => ModsView}, 57 | { path: '/settings', name: 'Settings', component: async () => SettingsView}, 58 | { path: '/dev', name: 'Dev', component: async () => DeveloperView}, 59 | { path: '/repair', name: 'Repair', component: async () => RepairView}, 60 | ]; 61 | export const router = createRouter({ 62 | history: createWebHashHistory(), 63 | routes, // short for `routes: routes` 64 | }); 65 | app.use(router); 66 | 67 | 68 | app.mount('#app') 69 | -------------------------------------------------------------------------------- /src-vue/src/plugins/modules/notifications.ts: -------------------------------------------------------------------------------- 1 | type NotificationType = 'success' | 'warning' | 'info' | 'error'; 2 | 3 | export interface Notification { 4 | title: string; 5 | text: string; 6 | type: NotificationType; 7 | } 8 | 9 | interface NotificationsStoreState { 10 | notifications: Notification[]; 11 | } 12 | 13 | 14 | /** 15 | * This notification module is meant to host the list of notifications that have been fired while the application was 16 | * not focused. 17 | * This list is then used by the [NotificationButton] component to display notifications to user. 18 | **/ 19 | export const notificationsModule = { 20 | state: () => ({ 21 | notifications: [] 22 | }) as NotificationsStoreState, 23 | mutations: { 24 | addNotification(state: NotificationsStoreState, payload: Notification) { 25 | state.notifications.push(payload); 26 | }, 27 | removeNotification(state: NotificationsStoreState, index: number): void { 28 | state.notifications.splice(index, 1); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src-vue/src/plugins/modules/pull_requests.ts: -------------------------------------------------------------------------------- 1 | import { invoke } from "@tauri-apps/api/core"; 2 | import { open } from '@tauri-apps/plugin-shell'; 3 | import { PullsApiResponseElement } from "../../../../src-tauri/bindings/PullsApiResponseElement"; 4 | import { PullRequestType } from '../../../../src-tauri/bindings/PullRequestType'; 5 | import { store } from "../store"; 6 | import { showErrorNotification, showNotification } from "../../utils/ui"; 7 | 8 | interface PullRequestStoreState { 9 | searchValue: string, 10 | pull_requests_launcher: PullsApiResponseElement[], 11 | pull_requests_mods: PullsApiResponseElement[], 12 | } 13 | 14 | export const pullRequestModule = { 15 | state: () => ({ 16 | pull_requests_launcher: [], 17 | pull_requests_mods: [], 18 | }), 19 | mutations: { 20 | async getPullRequests(state: PullRequestStoreState, pull_request_type: PullRequestType) { 21 | await invoke("get_pull_requests_wrapper", { installType: pull_request_type }) 22 | .then((message) => { 23 | switch (pull_request_type) { 24 | case "Mods": 25 | state.pull_requests_mods = message; 26 | break; 27 | 28 | case "Launcher": 29 | state.pull_requests_launcher = message; 30 | break; 31 | 32 | default: 33 | console.error("We should never end up here"); 34 | } 35 | }) 36 | .catch((error) => { 37 | showErrorNotification(error); 38 | }); 39 | }, 40 | async downloadLauncherPR(_state: PullRequestStoreState, pull_request: PullsApiResponseElement) { 41 | await invoke("get_launcher_download_link", { commitSha: pull_request.head.sha }) 42 | .then((url) => { 43 | // Open URL in default HTTPS handler (i.e. default browser) 44 | open(url); 45 | }) 46 | .catch((error) => { 47 | showErrorNotification(error); 48 | }); 49 | }, 50 | async downloadModsPR(_state: PullRequestStoreState, pull_request: PullsApiResponseElement) { 51 | let url = `https://github.com/${pull_request.head.repo.full_name}/archive/refs/heads/${pull_request.head.ref}.zip` 52 | open(url); 53 | }, 54 | async installLauncherPR(_state: PullRequestStoreState, pull_request: PullsApiResponseElement) { 55 | // Send notification telling the user to wait for the process to finish 56 | const notification = showNotification(`Installing launcher PR ${pull_request.number}`, 'Please wait', 'info', 0); 57 | 58 | await invoke("apply_launcher_pr", { pullRequest: pull_request, gameInstall: store.state.game_install }) 59 | .then((message) => { 60 | console.log(message); 61 | // Show user notification if mod install completed. 62 | showNotification(`Done`, `Installed ${pull_request.number}: "${pull_request.title}"`); 63 | }) 64 | .catch((error) => { 65 | showErrorNotification(error); 66 | }) 67 | .finally(() => { 68 | // Clear old notification 69 | notification.close(); 70 | }); 71 | }, 72 | async installModsPR(_state: PullRequestStoreState, pull_request: PullsApiResponseElement) { 73 | // Send notification telling the user to wait for the process to finish 74 | const notification = showNotification(`Installing mods PR ${pull_request.number}`, 'Please wait', 'info', 0); 75 | 76 | await invoke("apply_mods_pr", { pullRequest: pull_request, gameInstall: store.state.game_install }) 77 | .then((_message) => { 78 | // Show user notification if mod install completed. 79 | showNotification( 80 | `Done`, 81 | `Installed ${pull_request.number}: "${pull_request.title}"\nMake sure to launch via batch file or by specifying correct profile!`, 82 | 'success', 83 | 7000 84 | ); 85 | }) 86 | .catch((error) => { 87 | showErrorNotification(error); 88 | }) 89 | .finally(() => { 90 | // Clear old notification 91 | notification.close(); 92 | }); 93 | }, 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src-vue/src/plugins/modules/search.ts: -------------------------------------------------------------------------------- 1 | interface SearchStoreState { 2 | searchValue: string 3 | } 4 | 5 | export const searchModule = { 6 | state: () => ({ 7 | // This is the treated value of search input 8 | searchValue: '', 9 | // Selected mod categories 10 | selectedCategories: [], 11 | showDeprecatedMods: false, 12 | showNsfwMods: false, 13 | sortValue: {label: '', value: ''} 14 | }), 15 | getters: { 16 | searchWords(state: SearchStoreState): string { 17 | return state.searchValue.toLowerCase(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src-vue/src/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | html, body { 6 | height: 100%; 7 | width: 100%; 8 | } 9 | 10 | body { 11 | margin: 0; 12 | font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif; 13 | --fc-menu_height: 50px; 14 | user-select: none; 15 | } 16 | 17 | #app { 18 | position: relative; 19 | height: 100%; 20 | width: 100%; 21 | } 22 | 23 | #fc_bg__container { 24 | background: url(/src/assets/1009235.jpg) center no-repeat; 25 | background-size: cover; 26 | height: 100%; 27 | width: 100%; 28 | position: fixed; 29 | filter: brightness(0.8); 30 | scale: 1.03; 31 | } 32 | 33 | .el-scrollbar { 34 | --el-scrollbar-opacity: 0.5; 35 | --el-scrollbar-hover-opacity: 0.7; 36 | } 37 | 38 | .fc-container { 39 | position: relative; 40 | padding-top: var(--fc-menu_height); 41 | height: 100%; 42 | color: white; 43 | } 44 | 45 | .noModMessage { 46 | color: white; 47 | margin: 30px 15px; 48 | } 49 | 50 | .fc_popper { 51 | width: auto !important; 52 | } 53 | 54 | .el-popconfirm { 55 | word-break: break-word; 56 | } 57 | -------------------------------------------------------------------------------- /src-vue/src/utils/GameInstall.ts: -------------------------------------------------------------------------------- 1 | export interface GameInstall { 2 | game_path: string; 3 | profile: string, 4 | install_type: string; 5 | } 6 | -------------------------------------------------------------------------------- /src-vue/src/utils/NorthstarState.ts: -------------------------------------------------------------------------------- 1 | export enum NorthstarState { 2 | GAME_NOT_FOUND = "GAME_NOT_FOUND", 3 | INSTALL = "INSTALL", 4 | INSTALLING = "INSTALLING", 5 | MUST_UPDATE = "MUST_UPDATE", 6 | UPDATING = "UPDATING", 7 | READY_TO_PLAY = "READY_TO_PLAY" 8 | } -------------------------------------------------------------------------------- /src-vue/src/utils/ReleaseCanal.ts: -------------------------------------------------------------------------------- 1 | export enum ReleaseCanal { 2 | RELEASE = 'Northstar', 3 | RELEASE_CANDIDATE = 'NorthstarReleaseCandidate' 4 | } 5 | -------------------------------------------------------------------------------- /src-vue/src/utils/SortOptions.d.ts: -------------------------------------------------------------------------------- 1 | export enum SortOptions { 2 | NAME_ASC = 'name_asc', 3 | NAME_DESC = 'name_desc', 4 | DATE_ASC = 'date_asc', 5 | DATE_DESC = 'date_desc', 6 | MOST_DOWNLOADED = 'most_downloaded', 7 | TOP_RATED = 'top_rated' 8 | } 9 | -------------------------------------------------------------------------------- /src-vue/src/utils/Tabs.ts: -------------------------------------------------------------------------------- 1 | export enum Tabs { 2 | PLAY = '/', 3 | CHANGELOG = '/changelog', 4 | SETTINGS = '/settings', 5 | DEV = '/dev', 6 | MODS = '/mods', 7 | REPAIR = '/repair', 8 | } 9 | -------------------------------------------------------------------------------- /src-vue/src/utils/filter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Implements a fuzzy filter 3 | * Iterates through chars of `search_term` and checks if each char exists in consecutive order in `text`. 4 | * For example, this means that `text="Gecko"` and `search_term="geo"` will return `true` 5 | * but using `text="Gecko"` and `search_term="goe"` will return `false` 6 | * 7 | * Implements a subset of "fuzzy string searching" 8 | * https://en.wikipedia.org/wiki/Approximate_string_matching 9 | */ 10 | function fuzzy_filter(text: string, search_term: string): boolean { 11 | const lowercase_text = text.toLowerCase(); 12 | const lowercase_search_term = search_term.toLowerCase(); 13 | 14 | let previousIndex = -1; 15 | for (let i = 0; i < lowercase_search_term.length; i++) { 16 | const char = lowercase_search_term[i]; 17 | const currentIndex = lowercase_text.indexOf(char, previousIndex + 1); 18 | if (currentIndex === -1) { 19 | return false; 20 | } 21 | previousIndex = currentIndex; 22 | } 23 | 24 | return true; 25 | } 26 | export { fuzzy_filter }; 27 | -------------------------------------------------------------------------------- /src-vue/src/utils/thunderstore/ThunderstoreModStatus.ts: -------------------------------------------------------------------------------- 1 | export enum ThunderstoreModStatus { 2 | INSTALLED, 3 | BEING_INSTALLED, 4 | BEING_UPDATED, 5 | NOT_INSTALLED, 6 | OUTDATED 7 | } 8 | -------------------------------------------------------------------------------- /src-vue/src/utils/thunderstore/version.ts: -------------------------------------------------------------------------------- 1 | import {ThunderstoreMod} from "../../../../src-tauri/bindings/ThunderstoreMod"; 2 | import {NorthstarMod} from "../../../../src-tauri/bindings/NorthstarMod"; 3 | import {store} from "../../plugins/store"; 4 | 5 | /** 6 | * Strips off a Thunderstore dependency string from its version 7 | * (e.g. "taskinoz-WallrunningTitans-1.0.0" to 8 | * "taskinoz-WallrunningTitans"). 9 | **/ 10 | function getThunderstoreDependencyStringPrefix(dependency: string): string { 11 | const dependencyStringMembers = dependency.split('-'); 12 | return `${dependencyStringMembers[0]}-${dependencyStringMembers[1]}`; 13 | } 14 | 15 | function isThunderstoreModOutdated(mod: ThunderstoreMod): boolean { 16 | // Ensure mod is up-to-date. 17 | const tsModPrefix = getThunderstoreDependencyStringPrefix(mod.versions[0].full_name); 18 | const matchingMods: NorthstarMod[] = store.state.installed_mods.filter((mod: NorthstarMod) => { 19 | if (!mod.thunderstore_mod_string) return false; 20 | return getThunderstoreDependencyStringPrefix(mod.thunderstore_mod_string!) === tsModPrefix; 21 | }); 22 | if (matchingMods.length !== 0) { 23 | // There shouldn't be several mods with same dependency string, but we never know... 24 | const matchingMod = matchingMods[0]; 25 | // A mod is outdated if its dependency strings differs from Thunderstore dependency string 26 | // (no need for semver check here). 27 | // This assumes mod versions list is sorted from newest to oldest version. 28 | return matchingMod.thunderstore_mod_string !== mod.versions[0].full_name; 29 | } 30 | return false; 31 | } 32 | 33 | export { isThunderstoreModOutdated }; 34 | -------------------------------------------------------------------------------- /src-vue/src/utils/ui.ts: -------------------------------------------------------------------------------- 1 | import { ElNotification, NotificationHandle } from "element-plus"; 2 | import { getCurrentWindow, UserAttentionType } from '@tauri-apps/api/window'; 3 | import { i18n } from "../main"; 4 | import { store } from "../plugins/store"; 5 | 6 | /** 7 | * Displays content to the user in the form of a notification appearing on screen bottom right. 8 | * If the app is not focused when this is invoked, a notification is added to the notifications menu. 9 | **/ 10 | function showNotification( 11 | title: string, 12 | message: string = '', 13 | type: 'success' | 'warning' | 'error' | 'info' = 'success', 14 | duration: number = 4500 15 | ): NotificationHandle { 16 | if (!document.hasFocus()) { 17 | const date = new Date(); 18 | const titleWithDate = `${title} (${i18n.global.tc('notification.date_prefix')} ${('0' + date.getHours()).slice(-2)}:${('0' + date.getMinutes()).slice(-2)})`; 19 | store.commit('addNotification', {title: titleWithDate, text: message, type}); 20 | getCurrentWindow().requestUserAttention(UserAttentionType.Informational); 21 | } 22 | 23 | return ElNotification({ 24 | title, message, type, duration, 25 | position: 'bottom-right', 26 | }); 27 | } 28 | 29 | /** 30 | * Helper method displaying an error message to the user. 31 | **/ 32 | function showErrorNotification( 33 | error: string, 34 | title: string = i18n.global.tc('generic.error') 35 | ): NotificationHandle { 36 | return showNotification(title, error, 'error'); 37 | } 38 | 39 | export {showNotification, showErrorNotification}; 40 | -------------------------------------------------------------------------------- /src-vue/src/views/ChangelogView.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 60 | 61 | 83 | -------------------------------------------------------------------------------- /src-vue/src/views/ModsView.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 47 | 48 | 55 | -------------------------------------------------------------------------------- /src-vue/src/views/PlayView.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 68 | 69 | 125 | -------------------------------------------------------------------------------- /src-vue/src/views/RepairView.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 140 | 141 | 146 | -------------------------------------------------------------------------------- /src-vue/src/views/mods/LocalModsView.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 65 | 66 | 73 | -------------------------------------------------------------------------------- /src-vue/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module "*.vue" { 4 | import type { DefineComponent } from "vue"; 5 | const component: DefineComponent<{}, {}, any>; 6 | export default component; 7 | } 8 | -------------------------------------------------------------------------------- /src-vue/src/vuex-shim.d.ts: -------------------------------------------------------------------------------- 1 | import { ComponentCustomProperties } from 'vue' 2 | import { Store } from 'vuex' 3 | 4 | declare module '@vue/runtime-core' { 5 | interface ComponentCustomProperties { 6 | $i18n: I18n; 7 | $route: Route; 8 | $store: Store; 9 | $t: (key: string, ...params: any[]) => string; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src-vue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "sourceMap": true, 10 | "allowImportingTsExtensions": true, 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "esModuleInterop": true, 14 | "noEmit": true, 15 | "noUnusedLocals": true, 16 | "noUnusedParameters": true, 17 | "noFallthroughCasesInSwitch": true, 18 | "lib": ["ESNext", "DOM", "ES2018"], 19 | "skipLibCheck": true 20 | }, 21 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 22 | "references": [{ "path": "./tsconfig.node.json" }] 23 | } 24 | -------------------------------------------------------------------------------- /src-vue/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "bundler", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /src-vue/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import vue from "@vitejs/plugin-vue"; 3 | 4 | // @ts-expect-error process is a nodejs global 5 | const host = process.env.TAURI_DEV_HOST; 6 | 7 | // https://vitejs.dev/config/ 8 | export default defineConfig(async () => ({ 9 | // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` 10 | // 11 | // 1. prevent vite from obscuring rust errors 12 | clearScreen: false, 13 | // 2. tauri expects a fixed port, fail if that port is not available 14 | server: { 15 | port: 1420, 16 | strictPort: true, 17 | host: host || false, 18 | hmr: host 19 | ? { 20 | protocol: "ws", 21 | host, 22 | port: 1421, 23 | } 24 | : undefined, 25 | watch: { 26 | // 3. tell vite to ignore watching `src-tauri` 27 | ignored: ["**/src-tauri/**"], 28 | }, 29 | }, 30 | 31 | build: { 32 | // Tauri supports es2022 33 | target: ['es2022'], 34 | }, 35 | plugins: [vue()] 36 | })); 37 | --------------------------------------------------------------------------------