diff options
29 files changed, 690 insertions, 565 deletions
diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 19bb8c4c..3af6e5da 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,6 +2,14 @@ version: 2 updates: + # Root NPM package + - package-ecosystem: 'npm' + directory: '/' + schedule: + interval: "daily" + commit-message: + prefix: "chore: " + # NPM packages - package-ecosystem: 'npm' directory: '/src-vue' diff --git a/package-lock.json b/package-lock.json index d0c6aa49..4f9238c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,16 +6,16 @@ "": { "name": "flightcore", "dependencies": { - "@tauri-apps/api": "^1.4.0" + "@tauri-apps/api": "^1.5.0" }, "devDependencies": { - "@tauri-apps/cli": "^1.4.0" + "@tauri-apps/cli": "^1.5.2" } }, "node_modules/@tauri-apps/api": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.4.0.tgz", - "integrity": "sha512-Jd6HPoTM1PZSFIzq7FB8VmMu3qSSyo/3lSwLpoapW+lQ41CL5Dow2KryLg+gyazA/58DRWI9vu/XpEeHK4uMdw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.5.0.tgz", + "integrity": "sha512-yQY9wpVNuiYhLLuyDlu1nBpqJELT1fGp7OctN4rW9I2W1T2p7A3tqPxsEzQprEwneQRBAlPM9vC8NsnMbct+pg==", "engines": { "node": ">= 14.6.0", "npm": ">= 6.6.0", @@ -27,9 +27,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.4.0.tgz", - "integrity": "sha512-VXYr2i2iVFl98etQSQsqLzXgX96bnWiNZd1YADgatqwy/qecbd6Kl5ZAPB5R4ynsgE8A1gU7Fbzh7dCEQYFfmA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.2.tgz", + "integrity": "sha512-x4rPinrdyWLdTU5TbV7wrXudOyMilv0nmi1rngm/jwN3MmZdAj5J2xaS2rYtA8BU3oM/SE34qQwYxv1a2sM9ug==", "dev": true, "bin": { "tauri": "tauri.js" @@ -42,22 +42,22 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "1.4.0", - "@tauri-apps/cli-darwin-x64": "1.4.0", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.4.0", - "@tauri-apps/cli-linux-arm64-gnu": "1.4.0", - "@tauri-apps/cli-linux-arm64-musl": "1.4.0", - "@tauri-apps/cli-linux-x64-gnu": "1.4.0", - "@tauri-apps/cli-linux-x64-musl": "1.4.0", - "@tauri-apps/cli-win32-arm64-msvc": "1.4.0", - "@tauri-apps/cli-win32-ia32-msvc": "1.4.0", - "@tauri-apps/cli-win32-x64-msvc": "1.4.0" + "@tauri-apps/cli-darwin-arm64": "1.5.2", + "@tauri-apps/cli-darwin-x64": "1.5.2", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.2", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.2", + "@tauri-apps/cli-linux-arm64-musl": "1.5.2", + "@tauri-apps/cli-linux-x64-gnu": "1.5.2", + "@tauri-apps/cli-linux-x64-musl": "1.5.2", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.2", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.2", + "@tauri-apps/cli-win32-x64-msvc": "1.5.2" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.4.0.tgz", - "integrity": "sha512-nA/ml0SfUt6/CYLVbHmT500Y+ijqsuv5+s9EBnVXYSLVg9kbPUZJJHluEYK+xKuOj6xzyuT/+rZFMRapmJD3jQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.2.tgz", + "integrity": "sha512-3mYN15jpYjuuHRWii5Xk6JvB3ZLEgAZkeVgc5Hg7k3Yw1ZBrEGiUNe3Ku4DjbkYWL/QDd7oteIJnQk3j0mXwEg==", "cpu": [ "arm64" ], @@ -71,9 +71,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.4.0.tgz", - "integrity": "sha512-ov/F6Zr+dg9B0PtRu65stFo2G0ow2TUlneqYYrkj+vA3n+moWDHfVty0raDjMLQbQt3rv3uayFMXGPMgble9OA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.2.tgz", + "integrity": "sha512-8Jsl+EKBGdBoRUIR5ohjiTV6uG+pFpkNwHB4WaOzzR//v6p0lGULk2ohPIjJxhoQIFIN9oBd8bsSSNbZO/57/g==", "cpu": [ "x64" ], @@ -87,9 +87,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.4.0.tgz", - "integrity": "sha512-zwjbiMncycXDV7doovymyKD7sCg53ouAmfgpUqEBOTY3vgBi9TwijyPhJOqoG5vUVWhouNBC08akGmE4dja15g==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.2.tgz", + "integrity": "sha512-oWzcQtZogchdCSdQ+eEbDJHjJO9BGPO9EZNfvI2u3JzS/hJj4wCwnGHvZGI4jJ/6cnmcNvtt9ZftYYN4rpQW7A==", "cpu": [ "arm" ], @@ -103,9 +103,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.4.0.tgz", - "integrity": "sha512-5MCBcziqXC72mMXnkZU68mutXIR6zavDxopArE2gQtK841IlE06bIgtLi0kUUhlFJk2nhPRgiDgdLbrPlyt7fw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.2.tgz", + "integrity": "sha512-hfIUtys+SrrGEpLhQJwmL16g1FDhfObR4AGahCMqvMwA25uQKhtzRhxieO4X3k03vBeboTyJla5a2rX4TQ4lXA==", "cpu": [ "arm64" ], @@ -119,9 +119,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.4.0.tgz", - "integrity": "sha512-7J3pRB6n6uNYgIfCeKt2Oz8J7oSaz2s8GGFRRH2HPxuTHrBNCinzVYm68UhVpJrL3bnGkU0ziVZLsW/iaOGfUg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.2.tgz", + "integrity": "sha512-ZpFX4HyjkJHfF0geVVpq5fNjEXG8766LRg/BL4/wKy8MNbqcc/aW3sLEpVj0GvdulxOnd2trDb1FJdZ206Kp8g==", "cpu": [ "arm64" ], @@ -135,9 +135,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.4.0.tgz", - "integrity": "sha512-Zh5gfAJxOv5AVWxcwuueaQ2vIAhlg0d6nZui6nMyfIJ8dbf3aZQ5ZzP38sYow5h/fbvgL+3GSQxZRBIa3c2E1w==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.2.tgz", + "integrity": "sha512-/kEZrDVZv1+qYpZigtLntX4s+gx7WQqp8cmxKZL5GrzAjUNSTnfWK5VL7o0lYm09QBJAdTvjcJu2aPzNHLDS+Q==", "cpu": [ "x64" ], @@ -151,9 +151,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.4.0.tgz", - "integrity": "sha512-OLAYoICU3FaYiTdBsI+lQTKnDHeMmFMXIApN0M+xGiOkoIOQcV9CConMPjgmJQ867+NHRNgUGlvBEAh9CiJodQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.2.tgz", + "integrity": "sha512-vOrTqfW7NZLYmB1ZXjEq9JC8Z5knIHVGltN3jfyq9UY+tu7d6jNaSHuDdsVHLaKIRQajTHz+5cphDMoL+6/MUQ==", "cpu": [ "x64" ], @@ -167,9 +167,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.4.0.tgz", - "integrity": "sha512-gZ05GENFbI6CB5MlOUsLlU0kZ9UtHn9riYtSXKT6MYs8HSPRffPHaHSL0WxsJweWh9nR5Hgh/TUU8uW3sYCzCg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.2.tgz", + "integrity": "sha512-PCAIxH8TvIy1PlJK2qrdwpRCa7pZV648whRhmoLwj9lvn9PR4+vwuUWhSTXmp1ISHWZm/mEJpYuVq0ZxJDQKZQ==", "cpu": [ "arm64" ], @@ -183,9 +183,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.4.0.tgz", - "integrity": "sha512-JsetT/lTx/Zq98eo8T5CiRyF1nKeX04RO8JlJrI3ZOYsZpp/A5RJvMd/szQ17iOzwiHdge+tx7k2jHysR6oBlQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.2.tgz", + "integrity": "sha512-0rCXZC/9qyWZI2cgVnsT4JEjcxjQcZlrZjaSwhGynPUMkIUUBsWDimzkQeOP8abw5j/kLS2QPQRHAHqd0IF6Rg==", "cpu": [ "ia32" ], @@ -199,9 +199,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.4.0.tgz", - "integrity": "sha512-z8Olcnwp5aYhzqUAarFjqF+oELCjuYWnB2HAJHlfsYNfDCAORY5kct3Fklz8PSsubC3U2EugWn8n42DwnThurg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.2.tgz", + "integrity": "sha512-HrOwIujKTql8yUOvR+IEGW/SXwMwPrGWrcM35cDfCxpkLH6h3F5i4JtRqYTAiFdSfTk1J2rcFVQXfFJYIDntnA==", "cpu": [ "x64" ], diff --git a/package.json b/package.json index 27094072..7075ea4f 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,9 @@ "tauri": "tauri" }, "dependencies": { - "@tauri-apps/api": "^1.4.0" + "@tauri-apps/api": "^1.5.0" }, "devDependencies": { - "@tauri-apps/cli": "^1.4.0" + "@tauri-apps/cli": "^1.5.2" } } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 835cdef2..b619abf4 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -80,41 +80,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] -name = "app" -version = "2.10.3" -dependencies = [ - "anyhow", - "async-recursion", - "chrono", - "const_format", - "dirs", - "glob", - "json5", - "libthermite", - "log", - "open 5.0.0", - "pretty_env_logger", - "regex", - "reqwest", - "semver", - "sentry", - "sentry-log", - "serde", - "serde_json", - "steamlocate", - "sysinfo", - "tauri", - "tauri-build", - "tauri-plugin-store", - "tokio", - "ts-rs", - "winapi", - "winreg 0.51.0", - "zip", - "zip-extract", -] - -[[package]] name = "async-broadcast" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1101,6 +1066,41 @@ dependencies = [ ] [[package]] +name = "flightcore" +version = "2.13.0" +dependencies = [ + "anyhow", + "async-recursion", + "chrono", + "const_format", + "dirs", + "glob", + "json5", + "libthermite", + "log", + "open 5.0.0", + "pretty_env_logger", + "regex", + "reqwest", + "semver", + "sentry", + "sentry-log", + "serde", + "serde_json", + "steamlocate", + "sysinfo", + "tauri", + "tauri-build", + "tauri-plugin-store", + "tokio", + "ts-rs", + "winapi", + "winreg 0.51.0", + "zip", + "zip-extract", +] + +[[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1619,7 +1619,21 @@ checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" dependencies = [ "log", "mac", - "markup5ever", + "markup5ever 0.10.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "html5ever" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +dependencies = [ + "log", + "mac", + "markup5ever 0.11.0", "proc-macro2", "quote", "syn 1.0.109", @@ -2010,7 +2024,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358" dependencies = [ "cssparser", - "html5ever", + "html5ever 0.25.2", + "matches", + "selectors", +] + +[[package]] +name = "kuchikiki" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" +dependencies = [ + "cssparser", + "html5ever 0.26.0", + "indexmap 1.9.3", "matches", "selectors", ] @@ -2134,7 +2161,21 @@ checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" dependencies = [ "log", "phf 0.8.0", - "phf_codegen", + "phf_codegen 0.8.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", "string_cache", "string_cache_codegen", "tendril", @@ -2722,6 +2763,16 @@ dependencies = [ ] [[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] name = "phf_generator" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3086,14 +3137,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.6" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +checksum = "d119d7c7ca818f8a53c300863d4f87566aac09943aef5b355bb83969dae75d87" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.9", - "regex-syntax 0.7.5", + "regex-automata 0.4.1", + "regex-syntax 0.8.0", ] [[package]] @@ -3107,13 +3158,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "465c6fc0621e4abc4187a2bda0937bfd4f722c2730b29562e19689ea796c9a4b" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.5", + "regex-syntax 0.8.0", ] [[package]] @@ -3124,9 +3175,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "c3cbb081b9784b07cceb8824c8583f86db4814d172ab043f3c23f7dc600bf83d" [[package]] name = "reqwest" @@ -3375,7 +3426,7 @@ dependencies = [ "log", "matches", "phf 0.8.0", - "phf_codegen", + "phf_codegen 0.8.0", "precomputed-hash", "servo_arc", "smallvec", @@ -3384,9 +3435,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" dependencies = [ "serde", ] @@ -3511,18 +3562,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.188" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" dependencies = [ "proc-macro2", "quote", @@ -4029,9 +4080,9 @@ checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" [[package]] name = "tauri" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbe522898e35407a8e60dc3870f7579fea2fc262a6a6072eccdd37ae1e1d91e" +checksum = "9bfe673cf125ef364d6f56b15e8ce7537d9ca7e4dae1cf6fbbdeed2e024db3d9" dependencies = [ "anyhow", "base64 0.21.2", @@ -4088,12 +4139,13 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d2edd6a259b5591c8efdeb9d5702cb53515b82a6affebd55c7fd6d3a27b7d1b" +checksum = "defbfc551bd38ab997e5f8e458f87396d2559d05ce32095076ad6c30f7fc5f9c" dependencies = [ "anyhow", "cargo_toml", + "dirs-next", "heck 0.4.1", "json-patch", "semver", @@ -4101,13 +4153,14 @@ dependencies = [ "serde_json", "tauri-utils", "tauri-winres", + "walkdir", ] [[package]] name = "tauri-codegen" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ad2d49fdeab4a08717f5b49a163bdc72efc3b1950b6758245fcde79b645e1a" +checksum = "7b3475e55acec0b4a50fb96435f19631fb58cbcd31923e1a213de5c382536bbb" dependencies = [ "base64 0.21.2", "brotli", @@ -4131,9 +4184,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb12a2454e747896929338d93b0642144bb51e0dddbb36e579035731f0d76b7" +checksum = "613740228de92d9196b795ac455091d3a5fbdac2654abb8bb07d010b62ab43af" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -4157,9 +4210,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "108683199cb18f96d2d4134187bb789964143c845d2d154848dda209191fd769" +checksum = "07f8e9e53e00e9f41212c115749e87d5cd2a9eebccafca77a19722eeecd56d43" dependencies = [ "gtk", "http", @@ -4178,9 +4231,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7aa256a1407a3a091b5d843eccc1a5042289baf0a43d1179d9f0fcfea37c1b" +checksum = "8141d72b6b65f2008911e9ef5b98a68d1e3413b7a1464e8f85eb3673bb19a895" dependencies = [ "cocoa", "gtk", @@ -4198,19 +4251,20 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fc02bb6072bb397e1d473c6f76c953cda48b4a2d0cce605df284aa74a12e84" +checksum = "34d55e185904a84a419308d523c2c6891d5e2dbcee740c4997eb42e75a7b0f46" dependencies = [ "brotli", "ctor", "dunce", "glob", "heck 0.4.1", - "html5ever", + "html5ever 0.26.0", "infer", "json-patch", - "kuchiki", + "kuchikiki", + "log", "memchr", "phf 0.10.1", "proc-macro2", @@ -4359,9 +4413,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.32.0" +version = "1.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" dependencies = [ "backtrace", "bytes", @@ -5292,9 +5346,9 @@ dependencies = [ [[package]] name = "wry" -version = "0.24.3" +version = "0.24.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33748f35413c8a98d45f7a08832d848c0c5915501803d1faade5a4ebcd258cea" +checksum = "88ef04bdad49eba2e01f06e53688c8413bd6a87b0bc14b72284465cf96e3578e" dependencies = [ "base64 0.13.1", "block", @@ -5306,7 +5360,7 @@ dependencies = [ "gio", "glib", "gtk", - "html5ever", + "html5ever 0.25.2", "http", "kuchiki", "libc", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index f1d26cf8..5028a9e0 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "app" -version = "2.10.3" -description = "A Tauri App" -authors = ["you"] -license = "" -repository = "" -default-run = "app" +name = "flightcore" +version = "2.13.0" +description = "Mod-manager for Northstar" +authors = ["https://github.com/R2NorthstarTools/FlightCore/graphs/contributors"] +license = "MIT" +repository = "https://github.com/R2NorthstarTools/FlightCore" +default-run = "flightcore" edition = "2021" rust-version = "1.66" @@ -18,12 +18,12 @@ rust-version = "1.66" debug = 1 [build-dependencies] -tauri-build = { version = "1.4", features = [] } +tauri-build = { version = "1.5", features = [] } [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.4", features = ["api-all", "dialog", "updater"] } +tauri = { version = "1.5", features = ["api-all", "dialog", "updater"] } tokio = { version = "1", features = ["full"] } # Sentry (crash) logging sentry = "0.31" @@ -37,7 +37,7 @@ libthermite = { version = "0.7.0-beta", features = ["proton"] } # zip stuff zip = "0.6.2" # Regex -regex = "1.9" +regex = "1.10" # Read out running application process names sysinfo = "0.29.10" # HTTP requests diff --git a/src-tauri/src/constants.rs b/src-tauri/src/constants.rs index 33aefac8..7ee98f95 100644 --- a/src-tauri/src/constants.rs +++ b/src-tauri/src/constants.rs @@ -58,7 +58,3 @@ pub const NORTHSTAR_DLL: &str = "Northstar.dll"; /// Profile that Northstar defaults to and ships with pub const NORTHSTAR_DEFAULT_PROFILE: &str = "R2Northstar"; - -/// List of valid compatibility tools that Northstar can be launched with -pub const VALID_NORTHSTAR_PROTON_BUILDS: [&str; 3] = - ["NorthstarProton-8.1-1", "GE-Proton8-13", "GE-Proton8-11"]; diff --git a/src-tauri/src/github/mod.rs b/src-tauri/src/github/mod.rs index f35b64a1..0174084f 100644 --- a/src-tauri/src/github/mod.rs +++ b/src-tauri/src/github/mod.rs @@ -160,7 +160,7 @@ fn generate_flightcore_release_notes(commits: Vec<String>) -> String { "feat" => "**Features:**", "fix" => "**Bug Fixes:**", "docs" => "**Documentation:**", - "style" => "**Styles:**", + "style" => "**Code style changes:**", "refactor" => "**Code Refactoring:**", "build" => "**Build:**", "test" => "**Tests:**", diff --git a/src-tauri/src/github/pull_requests.rs b/src-tauri/src/github/pull_requests.rs index ccb45dff..91d8a5da 100644 --- a/src-tauri/src/github/pull_requests.rs +++ b/src-tauri/src/github/pull_requests.rs @@ -1,7 +1,7 @@ use crate::github::release_notes::fetch_github_releases_api; -use crate::check_is_valid_game_path; use crate::constants::{APP_USER_AGENT, PULLS_API_ENDPOINT_LAUNCHER, PULLS_API_ENDPOINT_MODS}; +use crate::repair_and_verify::check_is_valid_game_path; use crate::GameInstall; use anyhow::anyhow; use serde::{Deserialize, Serialize}; diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 66bb98d2..09242680 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -9,23 +9,22 @@ use std::{ time::Duration, }; -use crate::constants::REFRESH_DELAY; - +mod constants; mod development; mod github; mod mod_management; mod northstar; +mod platform_specific; mod repair_and_verify; mod thunderstore; mod util; -use semver::Version; use serde::{Deserialize, Serialize}; #[cfg(target_os = "windows")] use tauri::api::dialog::blocking::MessageDialogBuilder; #[cfg(target_os = "windows")] use tauri::api::dialog::{MessageDialogButtons, MessageDialogKind}; -use tauri::{Manager, Runtime}; +use tauri::Manager; use tokio::time::sleep; use ts_rs::TS; @@ -38,7 +37,7 @@ struct NorthstarThunderstoreRelease { #[derive(Serialize, Deserialize, Debug, Clone, TS)] #[ts(export)] -struct NorthstarThunderstoreReleaseWrapper { +pub struct NorthstarThunderstoreReleaseWrapper { label: String, value: NorthstarThunderstoreRelease, } @@ -103,7 +102,7 @@ fn main() { let app_handle = app.app_handle(); tauri::async_runtime::spawn(async move { loop { - sleep(REFRESH_DELAY).await; + sleep(constants::REFRESH_DELAY).await; app_handle .emit_all( "northstar-statistics", @@ -119,13 +118,13 @@ fn main() { .invoke_handler(tauri::generate_handler![ util::force_panic, northstar::install::find_game_install_location, - get_flightcore_version_number, + util::get_flightcore_version_number, northstar::get_northstar_version_number, - check_is_northstar_outdated, - verify_install_location, - get_host_os, - install_northstar_caller, - update_northstar, + northstar::check_is_northstar_outdated, + repair_and_verify::verify_install_location, + platform_specific::get_host_os, + northstar::install::install_northstar_wrapper, + northstar::install::update_northstar, northstar::launch_northstar, northstar::launch_northstar_steam, github::release_notes::check_is_flightcore_outdated, @@ -135,19 +134,19 @@ fn main() { repair_and_verify::disable_all_but_core, util::is_debug_mode, github::release_notes::get_northstar_release_notes, - linux_checks, + platform_specific::linux_checks, mod_management::get_installed_mods_and_properties, - install_mod_caller, - clean_up_download_folder_caller, + mod_management::install_mod_wrapper, + repair_and_verify::clean_up_download_folder_wrapper, github::release_notes::get_newest_flightcore_version, mod_management::delete_northstar_mod, util::get_server_player_count, util::kill_northstar, mod_management::delete_thunderstore_mod, - install_northstar_proton_wrapper, - uninstall_northstar_proton_wrapper, - get_local_northstar_proton_wrapper_version, - open_repair_window, + platform_specific::install_northstar_proton_wrapper, + platform_specific::uninstall_northstar_proton_wrapper, + platform_specific::get_local_northstar_proton_wrapper_version, + util::open_repair_window, thunderstore::query_thunderstore_packages_api, github::get_list_of_tags, github::compare_tags, @@ -155,11 +154,12 @@ fn main() { github::pull_requests::apply_launcher_pr, github::pull_requests::apply_mods_pr, github::pull_requests::get_launcher_download_link, - close_application, + util::close_application, development::install_git_main, - get_available_northstar_versions, + northstar::get_available_northstar_versions, northstar::profile::fetch_profiles, northstar::profile::validate_profile, + northstar::profile::delete_profile, ]) .run(tauri::generate_context!()) { @@ -193,272 +193,7 @@ fn main() { }; } -/// Returns true if linux compatible -#[tauri::command] -async fn linux_checks() -> Result<(), String> { - // Different behaviour depending on OS - // MacOS is missing as it is not a target - // in turn this means this application will not build on MacOS. - #[cfg(target_os = "windows")] - { - Err("Not available on Windows".to_string()) - } - - #[cfg(target_os = "linux")] - { - linux_checks_librs() - } -} - -/// Returns the current version number as a string -#[tauri::command] -async fn get_flightcore_version_number() -> String { - let version = env!("CARGO_PKG_VERSION"); - if cfg!(debug_assertions) { - // Debugging enabled - format!("v{} (debug mode)", version) - } else { - // Debugging disabled - format!("v{}", version) - } -} - -/// Helps with converting release candidate numbers which are different on Thunderstore -/// due to restrictions imposed by the platform -pub fn convert_release_candidate_number(version_number: String) -> String { - // This simply converts `-rc` to `0` - // Works as intended for RCs < 10, e.g. `v1.9.2-rc1` -> `v1.9.201` - // Doesn't work for larger numbers, e.g. `v1.9.2-rc11` -> `v1.9.2011` (should be `v1.9.211`) - version_number.replace("-rc", "0").replace("00", "") -} - -/// Checks if installed Northstar version is up-to-date -/// false -> Northstar install is up-to-date -/// true -> Northstar install is outdated -#[tauri::command] -async fn check_is_northstar_outdated( - game_install: GameInstall, - northstar_package_name: Option<String>, -) -> Result<bool, String> { - let northstar_package_name = match northstar_package_name { - Some(northstar_package_name) => { - if northstar_package_name.len() <= 1 { - "Northstar".to_string() - } else { - northstar_package_name - } - } - None => "Northstar".to_string(), - }; - - let index = match thermite::api::get_package_index() { - Ok(res) => res.to_vec(), - Err(err) => return Err(format!("Couldn't check if Northstar up-to-date: {err}")), - }; - let nmod = index - .iter() - .find(|f| f.name.to_lowercase() == northstar_package_name.to_lowercase()) - .expect("Couldn't find Northstar on thunderstore???"); - // .ok_or_else(|| anyhow!("Couldn't find Northstar on thunderstore???"))?; - - let version_number = match northstar::get_northstar_version_number(game_install) { - Ok(version_number) => version_number, - Err(err) => { - log::warn!("{}", err); - // If we fail to get new version just assume we are up-to-date - return Err(err); - } - }; - - // Release candidate version numbers are different between `mods.json` and Thunderstore - let version_number = convert_release_candidate_number(version_number); - - if version_number != nmod.latest { - log::info!("Installed Northstar version outdated"); - Ok(true) - } else { - log::info!("Installed Northstar version up-to-date"); - Ok(false) - } -} - -/// Checks if is valid Titanfall2 install based on certain conditions -#[tauri::command] -async fn verify_install_location(game_path: String) -> bool { - match check_is_valid_game_path(&game_path) { - Ok(()) => true, - Err(err) => { - log::warn!("{}", err); - false - } - } -} - -/// Installs Northstar to the given path -#[tauri::command] -async fn install_northstar_caller( - window: tauri::Window, - game_install: GameInstall, - northstar_package_name: Option<String>, - version_number: Option<String>, -) -> Result<bool, String> { - log::info!("Running Northstar install"); - - // Get Northstar package name (`Northstar` vs `NorthstarReleaseCandidate`) - let northstar_package_name = northstar_package_name - .map(|name| { - if name.len() <= 1 { - "Northstar".to_string() - } else { - name - } - }) - .unwrap_or("Northstar".to_string()); - - match northstar::install::install_northstar( - window, - game_install, - northstar_package_name, - version_number, - ) - .await - { - Ok(_) => Ok(true), - Err(err) => { - log::error!("{}", err); - Err(err) - } - } -} - -/// Update Northstar install in the given path -#[tauri::command] -async fn update_northstar( - window: tauri::Window, - game_install: GameInstall, - northstar_package_name: Option<String>, -) -> Result<bool, String> { - log::info!("Updating Northstar"); - - // Simply re-run install with up-to-date version for upate - install_northstar_caller(window, game_install, northstar_package_name, None).await -} - -/// Installs the specified mod -#[tauri::command] -async fn install_mod_caller( - game_install: GameInstall, - thunderstore_mod_string: String, -) -> Result<(), String> { - match mod_management::fc_download_mod_and_install(&game_install, &thunderstore_mod_string).await - { - Ok(()) => (), - Err(err) => { - log::warn!("{err}"); - return Err(err); - } - }; - match repair_and_verify::clean_up_download_folder(&game_install, false) { - Ok(()) => Ok(()), - Err(err) => { - log::info!("Failed to delete download folder due to {}", err); - // Failure to delete download folder is not an error in mod install - // As such ignore. User can still force delete if need be - Ok(()) - } - } -} - -/// Installs the specified mod -#[tauri::command] -async fn clean_up_download_folder_caller( - game_install: GameInstall, - force: bool, -) -> Result<(), String> { - match repair_and_verify::clean_up_download_folder(&game_install, force) { - Ok(()) => Ok(()), - Err(err) => Err(err.to_string()), - } -} - -/// Spawns repair window -#[tauri::command] -async fn open_repair_window(handle: tauri::AppHandle) -> Result<(), String> { - // Spawn new window - let repair_window = match tauri::WindowBuilder::new( - &handle, - "RepairWindow", - tauri::WindowUrl::App("/#/repair".into()), - ) - .build() - { - Ok(res) => res, - Err(err) => return Err(err.to_string()), - }; - - // Set window title - match repair_window.set_title("FlightCore Repair Window") { - Ok(()) => (), - Err(err) => return Err(err.to_string()), - }; - Ok(()) -} - -/// Closes all windows and exits application -#[tauri::command] -async fn close_application<R: Runtime>(app: tauri::AppHandle<R>) -> Result<(), String> { - app.exit(0); // Close application - Ok(()) -} - -/// Gets list of available Northstar versions from Thunderstore -#[tauri::command] -async fn get_available_northstar_versions() -> Result<Vec<NorthstarThunderstoreReleaseWrapper>, ()> -{ - let northstar_package_name = "Northstar"; - let index = thermite::api::get_package_index().unwrap().to_vec(); - let nsmod = index - .iter() - .find(|f| f.name.to_lowercase() == northstar_package_name.to_lowercase()) - .ok_or_else(|| panic!("Couldn't find Northstar on thunderstore???")) - .unwrap(); - - let mut releases: Vec<NorthstarThunderstoreReleaseWrapper> = vec![]; - for (_version_string, nsmod_version_obj) in nsmod.versions.iter() { - let current_elem = NorthstarThunderstoreRelease { - package: nsmod_version_obj.name.clone(), - version: nsmod_version_obj.version.clone(), - }; - let current_elem_wrapped = NorthstarThunderstoreReleaseWrapper { - label: format!( - "{} v{}", - nsmod_version_obj.name.clone(), - nsmod_version_obj.version.clone() - ), - value: current_elem, - }; - - releases.push(current_elem_wrapped); - } - - releases.sort_by(|a, b| { - // Parse version number - let a_ver = Version::parse(&a.value.version).unwrap(); - let b_ver = Version::parse(&b.value.version).unwrap(); - b_ver.partial_cmp(&a_ver).unwrap() // Sort newest first - }); - - Ok(releases) -} - -use anyhow::Result; - -pub mod constants; -mod platform_specific; - -#[cfg(target_os = "linux")] -use platform_specific::linux; - +/// Defines how Titanfall2 was installed (Steam, Origin, ...) #[derive(Serialize, Deserialize, Debug, Clone, TS)] #[ts(export)] pub enum InstallType { @@ -468,6 +203,10 @@ pub enum InstallType { UNKNOWN, } +/// Object holding information of the Titanfall2 install, including +/// - Install path +/// - Active profile +/// - Type of installation (Steam, Origin, ...) #[derive(Serialize, Deserialize, Debug, Clone)] pub struct GameInstall { pub game_path: String, @@ -475,6 +214,7 @@ pub struct GameInstall { pub install_type: InstallType, } +/// Object holding various information about a Northstar mod #[derive(Serialize, Deserialize, Debug, Clone, TS)] #[ts(export)] pub struct NorthstarMod { @@ -484,73 +224,3 @@ pub struct NorthstarMod { pub enabled: bool, pub directory: String, } - -// I intend to add more linux related stuff to check here, so making a func -// for now tho it only checks `ldd --version` -// - salmon -#[cfg(target_os = "linux")] -pub fn linux_checks_librs() -> Result<(), String> { - // Perform various checks in terms of Linux compatibility - // Return early with error message if a check fails - - // check `ldd --version` to see if glibc is up to date for northstar proton - let min_required_ldd_version = 2.33; - let lddv = linux::check_glibc_v(); - if lddv < min_required_ldd_version { - return Err(format!( - "GLIBC is not version {} or greater", - min_required_ldd_version - )); - }; - - // All checks passed - Ok(()) -} - -/// Checks whether the provided path is a valid Titanfall2 gamepath by checking against a certain set of criteria -pub fn check_is_valid_game_path(game_install_path: &str) -> Result<(), String> { - let path_to_titanfall2_exe = format!("{game_install_path}/Titanfall2.exe"); - let is_correct_game_path = std::path::Path::new(&path_to_titanfall2_exe).exists(); - log::info!("Titanfall2.exe exists in path? {}", is_correct_game_path); - - // Exit early if wrong game path - if !is_correct_game_path { - return Err(format!("Incorrect game path \"{game_install_path}\"")); // Return error cause wrong game path - } - Ok(()) -} - -/// Returns identifier of host OS FlightCore is running on -#[tauri::command] -fn get_host_os() -> String { - env::consts::OS.to_string() -} - -/// On Linux attempts to install NorthstarProton -/// On Windows simply returns an error message -#[tauri::command] -async fn install_northstar_proton_wrapper() -> Result<(), String> { - #[cfg(target_os = "linux")] - return linux::install_ns_proton().map_err(|err| err.to_string()); - - #[cfg(target_os = "windows")] - Err("Not supported on Windows".to_string()) -} - -#[tauri::command] -async fn uninstall_northstar_proton_wrapper() -> Result<(), String> { - #[cfg(target_os = "linux")] - return linux::uninstall_ns_proton(); - - #[cfg(target_os = "windows")] - Err("Not supported on Windows".to_string()) -} - -#[tauri::command] -async fn get_local_northstar_proton_wrapper_version() -> Result<String, String> { - #[cfg(target_os = "linux")] - return linux::get_local_ns_proton_version(); - - #[cfg(target_os = "windows")] - Err("Not supported on Windows".to_string()) -} diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index a9826522..ab639b11 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -89,6 +89,30 @@ impl std::ops::Deref for TempFile { } } +/// Installs the specified mod +#[tauri::command] +pub async fn install_mod_wrapper( + game_install: GameInstall, + thunderstore_mod_string: String, +) -> Result<(), String> { + match fc_download_mod_and_install(&game_install, &thunderstore_mod_string).await { + Ok(()) => (), + Err(err) => { + log::warn!("{err}"); + return Err(err); + } + }; + match crate::repair_and_verify::clean_up_download_folder(&game_install, false) { + Ok(()) => Ok(()), + Err(err) => { + log::info!("Failed to delete download folder due to {}", err); + // Failure to delete download folder is not an error in mod install + // As such ignore. User can still force delete if need be + Ok(()) + } + } +} + /// Returns a serde json object of the parsed `enabledmods.json` file pub fn get_enabled_mods(game_install: &GameInstall) -> Result<serde_json::value::Value, String> { let enabledmods_json_path = format!( diff --git a/src-tauri/src/northstar/install.rs b/src-tauri/src/northstar/install.rs index 757f6c68..693d7af2 100644 --- a/src-tauri/src/northstar/install.rs +++ b/src-tauri/src/northstar/install.rs @@ -29,6 +29,49 @@ struct InstallProgress { state: InstallState, } +/// Installs Northstar to the given path +#[tauri::command] +pub async fn install_northstar_wrapper( + window: tauri::Window, + game_install: GameInstall, + northstar_package_name: Option<String>, + version_number: Option<String>, +) -> Result<bool, String> { + log::info!("Running Northstar install"); + + // Get Northstar package name (`Northstar` vs `NorthstarReleaseCandidate`) + let northstar_package_name = northstar_package_name + .map(|name| { + if name.len() <= 1 { + "Northstar".to_string() + } else { + name + } + }) + .unwrap_or("Northstar".to_string()); + + match install_northstar(window, game_install, northstar_package_name, version_number).await { + Ok(_) => Ok(true), + Err(err) => { + log::error!("{}", err); + Err(err) + } + } +} + +/// Update Northstar install in the given path +#[tauri::command] +pub async fn update_northstar( + window: tauri::Window, + game_install: GameInstall, + northstar_package_name: Option<String>, +) -> Result<bool, String> { + log::info!("Updating Northstar"); + + // Simply re-run install with up-to-date version for upate + install_northstar_wrapper(window, game_install, northstar_package_name, None).await +} + /// Copied from `papa` source code and modified ///Install N* from the provided mod /// diff --git a/src-tauri/src/northstar/mod.rs b/src-tauri/src/northstar/mod.rs index 4ee9ba82..d6f6d712 100644 --- a/src-tauri/src/northstar/mod.rs +++ b/src-tauri/src/northstar/mod.rs @@ -5,11 +5,103 @@ pub mod profile; use crate::util::check_ea_app_or_origin_running; use crate::{ - constants::{CORE_MODS, TITANFALL2_STEAM_ID, VALID_NORTHSTAR_PROTON_BUILDS}, - get_host_os, GameInstall, InstallType, + constants::{CORE_MODS, TITANFALL2_STEAM_ID}, + platform_specific::get_host_os, + GameInstall, InstallType, }; +use crate::{NorthstarThunderstoreRelease, NorthstarThunderstoreReleaseWrapper}; use anyhow::anyhow; +/// Gets list of available Northstar versions from Thunderstore +#[tauri::command] +pub async fn get_available_northstar_versions( +) -> Result<Vec<NorthstarThunderstoreReleaseWrapper>, ()> { + let northstar_package_name = "Northstar"; + let index = thermite::api::get_package_index().unwrap().to_vec(); + let nsmod = index + .iter() + .find(|f| f.name.to_lowercase() == northstar_package_name.to_lowercase()) + .ok_or_else(|| panic!("Couldn't find Northstar on thunderstore???")) + .unwrap(); + + let mut releases: Vec<NorthstarThunderstoreReleaseWrapper> = vec![]; + for (_version_string, nsmod_version_obj) in nsmod.versions.iter() { + let current_elem = NorthstarThunderstoreRelease { + package: nsmod_version_obj.name.clone(), + version: nsmod_version_obj.version.clone(), + }; + let current_elem_wrapped = NorthstarThunderstoreReleaseWrapper { + label: format!( + "{} v{}", + nsmod_version_obj.name.clone(), + nsmod_version_obj.version.clone() + ), + value: current_elem, + }; + + releases.push(current_elem_wrapped); + } + + releases.sort_by(|a, b| { + // Parse version number + let a_ver = semver::Version::parse(&a.value.version).unwrap(); + let b_ver = semver::Version::parse(&b.value.version).unwrap(); + b_ver.partial_cmp(&a_ver).unwrap() // Sort newest first + }); + + Ok(releases) +} + +/// Checks if installed Northstar version is up-to-date +/// false -> Northstar install is up-to-date +/// true -> Northstar install is outdated +#[tauri::command] +pub async fn check_is_northstar_outdated( + game_install: GameInstall, + northstar_package_name: Option<String>, +) -> Result<bool, String> { + let northstar_package_name = match northstar_package_name { + Some(northstar_package_name) => { + if northstar_package_name.len() <= 1 { + "Northstar".to_string() + } else { + northstar_package_name + } + } + None => "Northstar".to_string(), + }; + + let index = match thermite::api::get_package_index() { + Ok(res) => res.to_vec(), + Err(err) => return Err(format!("Couldn't check if Northstar up-to-date: {err}")), + }; + let nmod = index + .iter() + .find(|f| f.name.to_lowercase() == northstar_package_name.to_lowercase()) + .expect("Couldn't find Northstar on thunderstore???"); + // .ok_or_else(|| anyhow!("Couldn't find Northstar on thunderstore???"))?; + + let version_number = match get_northstar_version_number(game_install) { + Ok(version_number) => version_number, + Err(err) => { + log::warn!("{}", err); + // If we fail to get new version just assume we are up-to-date + return Err(err); + } + }; + + // Release candidate version numbers are different between `mods.json` and Thunderstore + let version_number = crate::util::convert_release_candidate_number(version_number); + + if version_number != nmod.latest { + log::info!("Installed Northstar version outdated"); + Ok(true) + } else { + log::info!("Installed Northstar version up-to-date"); + Ok(false) + } +} + /// Check version number of a mod pub fn check_mod_version_number(path_to_mod_folder: &str) -> Result<String, anyhow::Error> { let data = std::fs::read_to_string(format!("{path_to_mod_folder}/mod.json"))?; @@ -158,15 +250,7 @@ pub fn launch_northstar_steam( if get_host_os() != "windows" { let titanfall2_steamid: u32 = TITANFALL2_STEAM_ID.parse().unwrap(); match steamdir.compat_tool(&titanfall2_steamid) { - Some(compat) => { - if !VALID_NORTHSTAR_PROTON_BUILDS - .contains(&compat.clone().name.unwrap().as_str()) - { - return Err( - "Titanfall2 was not configured to use a valid version of NorthstarProton or GE-Proton".to_string(), - ); - } - } + Some(_) => {} None => { return Err( "Titanfall2 was not configured to use a compatibility tool".to_string() diff --git a/src-tauri/src/northstar/profile.rs b/src-tauri/src/northstar/profile.rs index 78e734d0..b0c6c418 100644 --- a/src-tauri/src/northstar/profile.rs +++ b/src-tauri/src/northstar/profile.rs @@ -74,3 +74,20 @@ pub fn validate_profile(game_install: GameInstall, profile: String) -> bool { profile_dir.is_dir() } + +#[tauri::command] +pub fn delete_profile(game_install: GameInstall, profile: String) -> Result<(), String> { + // Check if the Profile actually exists + if !validate_profile(game_install.clone(), profile.clone()) { + return Err(format!("{} is not a valid Profile", profile)); + } + + log::info!("Deleting Profile {}", profile); + + let profile_path = format!("{}/{}", game_install.game_path, profile); + + match std::fs::remove_dir_all(profile_path) { + Ok(()) => Ok(()), + Err(err) => Err(format!("Failed to delete Profile: {}", err)), + } +} diff --git a/src-tauri/src/platform_specific/linux.rs b/src-tauri/src/platform_specific/linux.rs index 674f384b..706a4d22 100644 --- a/src-tauri/src/platform_specific/linux.rs +++ b/src-tauri/src/platform_specific/linux.rs @@ -3,6 +3,27 @@ use regex::Regex; use std::process::Command; +// I intend to add more linux related stuff to check here, so making a func +// for now tho it only checks `ldd --version` +// - salmon +pub fn linux_checks_librs() -> Result<(), String> { + // Perform various checks in terms of Linux compatibility + // Return early with error message if a check fails + + // check `ldd --version` to see if glibc is up to date for northstar proton + let min_required_ldd_version = 2.33; + let lddv = check_glibc_v(); + if lddv < min_required_ldd_version { + return Err(format!( + "GLIBC is not version {} or greater", + min_required_ldd_version + )); + }; + + // All checks passed + Ok(()) +} + fn get_proton_dir() -> Option<String> { let steam_dir = steamlocate::SteamDir::locate()?; let compat_dir = format!("{}/compatibilitytools.d/", steam_dir.path.display()); diff --git a/src-tauri/src/platform_specific/mod.rs b/src-tauri/src/platform_specific/mod.rs index 84bd478a..8dca9424 100644 --- a/src-tauri/src/platform_specific/mod.rs +++ b/src-tauri/src/platform_specific/mod.rs @@ -3,3 +3,55 @@ pub mod windows; #[cfg(target_os = "linux")] pub mod linux; + +/// Returns identifier of host OS FlightCore is running on +#[tauri::command] +pub fn get_host_os() -> String { + std::env::consts::OS.to_string() +} + +/// On Linux attempts to install NorthstarProton +/// On Windows simply returns an error message +#[tauri::command] +pub async fn install_northstar_proton_wrapper() -> Result<(), String> { + #[cfg(target_os = "linux")] + return linux::install_ns_proton().map_err(|err| err.to_string()); + + #[cfg(target_os = "windows")] + Err("Not supported on Windows".to_string()) +} + +#[tauri::command] +pub async fn uninstall_northstar_proton_wrapper() -> Result<(), String> { + #[cfg(target_os = "linux")] + return linux::uninstall_ns_proton(); + + #[cfg(target_os = "windows")] + Err("Not supported on Windows".to_string()) +} + +#[tauri::command] +pub async fn get_local_northstar_proton_wrapper_version() -> Result<String, String> { + #[cfg(target_os = "linux")] + return linux::get_local_ns_proton_version(); + + #[cfg(target_os = "windows")] + Err("Not supported on Windows".to_string()) +} + +/// Returns true if linux compatible +#[tauri::command] +pub async fn linux_checks() -> Result<(), String> { + // Different behaviour depending on OS + // MacOS is missing as it is not a target + // in turn this means this application will not build on MacOS. + #[cfg(target_os = "windows")] + { + Err("Not available on Windows".to_string()) + } + + #[cfg(target_os = "linux")] + { + linux::linux_checks_librs() + } +} diff --git a/src-tauri/src/platform_specific/windows.rs b/src-tauri/src/platform_specific/windows.rs index 899ab2cd..678e5be5 100644 --- a/src-tauri/src/platform_specific/windows.rs +++ b/src-tauri/src/platform_specific/windows.rs @@ -4,7 +4,7 @@ use anyhow::{anyhow, Result}; #[cfg(target_os = "windows")] use winreg::{enums::HKEY_LOCAL_MACHINE, RegKey}; -use crate::check_is_valid_game_path; +use crate::repair_and_verify::check_is_valid_game_path; /// Gets Titanfall2 install location on Origin pub fn origin_install_location_detection() -> Result<String, anyhow::Error> { diff --git a/src-tauri/src/repair_and_verify/mod.rs b/src-tauri/src/repair_and_verify/mod.rs index 70abc127..c752a3ab 100644 --- a/src-tauri/src/repair_and_verify/mod.rs +++ b/src-tauri/src/repair_and_verify/mod.rs @@ -2,6 +2,31 @@ use crate::mod_management::{get_enabled_mods, rebuild_enabled_mods_json, set_mod /// Contains various functions to repair common issues and verifying installation use crate::{constants::CORE_MODS, GameInstall}; +/// Checks if is valid Titanfall2 install based on certain conditions +#[tauri::command] +pub async fn verify_install_location(game_path: String) -> bool { + match check_is_valid_game_path(&game_path) { + Ok(()) => true, + Err(err) => { + log::warn!("{}", err); + false + } + } +} + +/// Checks whether the provided path is a valid Titanfall2 gamepath by checking against a certain set of criteria +pub fn check_is_valid_game_path(game_install_path: &str) -> Result<(), String> { + let path_to_titanfall2_exe = format!("{game_install_path}/Titanfall2.exe"); + let is_correct_game_path = std::path::Path::new(&path_to_titanfall2_exe).exists(); + log::info!("Titanfall2.exe exists in path? {}", is_correct_game_path); + + // Exit early if wrong game path + if !is_correct_game_path { + return Err(format!("Incorrect game path \"{game_install_path}\"")); // Return error cause wrong game path + } + Ok(()) +} + /// Verifies Titanfall2 game files #[tauri::command] pub fn verify_game_files(game_install: GameInstall) -> Result<String, String> { @@ -32,6 +57,18 @@ pub fn disable_all_but_core(game_install: GameInstall) -> Result<(), String> { Ok(()) } +/// Installs the specified mod +#[tauri::command] +pub async fn clean_up_download_folder_wrapper( + game_install: GameInstall, + force: bool, +) -> Result<(), String> { + match clean_up_download_folder(&game_install, force) { + Ok(()) => Ok(()), + Err(err) => Err(err.to_string()), + } +} + /// Deletes download folder /// If `force` is FALSE, bails on non-empty folder /// If `force` is TRUE, deletes folder even if non-empty diff --git a/src-tauri/src/util.rs b/src-tauri/src/util.rs index b21b2208..75555f3e 100644 --- a/src-tauri/src/util.rs +++ b/src-tauri/src/util.rs @@ -26,6 +26,49 @@ pub async fn is_debug_mode() -> bool { cfg!(debug_assertions) } +/// Returns the current version number as a string +#[tauri::command] +pub async fn get_flightcore_version_number() -> String { + let version = env!("CARGO_PKG_VERSION"); + if cfg!(debug_assertions) { + // Debugging enabled + format!("v{} (debug mode)", version) + } else { + // Debugging disabled + format!("v{}", version) + } +} + +/// Spawns repair window +#[tauri::command] +pub async fn open_repair_window(handle: tauri::AppHandle) -> Result<(), String> { + // Spawn new window + let repair_window = match tauri::WindowBuilder::new( + &handle, + "RepairWindow", + tauri::WindowUrl::App("/#/repair".into()), + ) + .build() + { + Ok(res) => res, + Err(err) => return Err(err.to_string()), + }; + + // Set window title + match repair_window.set_title("FlightCore Repair Window") { + Ok(()) => (), + Err(err) => return Err(err.to_string()), + }; + Ok(()) +} + +/// Closes all windows and exits application +#[tauri::command] +pub async fn close_application<R: tauri::Runtime>(app: tauri::AppHandle<R>) -> Result<(), String> { + app.exit(0); // Close application + Ok(()) +} + /// Fetches `/client/servers` endpoint from master server async fn fetch_server_list() -> Result<String, anyhow::Error> { let url = format!("{MASTER_SERVER_URL}{SERVER_BROWSER_ENDPOINT}"); @@ -182,3 +225,12 @@ pub fn move_dir_all( } Ok(()) } + +/// Helps with converting release candidate numbers which are different on Thunderstore +/// due to restrictions imposed by the platform +pub fn convert_release_candidate_number(version_number: String) -> String { + // This simply converts `-rc` to `0` + // Works as intended for RCs < 10, e.g. `v1.9.2-rc1` -> `v1.9.201` + // Doesn't work for larger numbers, e.g. `v1.9.2-rc11` -> `v1.9.2011` (should be `v1.9.211`) + version_number.replace("-rc", "0").replace("00", "") +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index dd638241..f9ab1583 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "FlightCore", - "version": "2.10.3" + "version": "2.13.0" }, "tauri": { "allowlist": { diff --git a/src-vue/package-lock.json b/src-vue/package-lock.json index ded2414b..efe0d2b0 100644 --- a/src-vue/package-lock.json +++ b/src-vue/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@element-plus/icons-vue": "^2.0.9", "element-plus": "^2.3.14", - "marked": "^9.1.0", + "marked": "^9.1.1", "tauri-plugin-store-api": "github:tauri-apps/tauri-plugin-store#9bd993aa67766596638bbfd91e79a1bf8f632014", "vue": "^3.2.37", "vue-i18n": "^9.5.0", @@ -22,7 +22,7 @@ "@vitejs/plugin-vue": "^3.1.0", "typescript": "^5.2.2", "vite": "^3.1.0", - "vue-tsc": "^1.8.15" + "vue-tsc": "^1.8.19" } }, "node_modules/@babel/parser": { @@ -218,30 +218,30 @@ } }, "node_modules/@volar/language-core": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.10.1.tgz", - "integrity": "sha512-JnsM1mIPdfGPxmoOcK1c7HYAsL6YOv0TCJ4aW3AXPZN/Jb4R77epDyMZIVudSGjWMbvv/JfUa+rQ+dGKTmgwBA==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.10.4.tgz", + "integrity": "sha512-Na69qA6uwVIdA0rHuOc2W3pHtVQQO8hCNim7FOaKNpRJh0oAFnu5r9i7Oopo5C4cnELZkPNjTrbmpcCTiW+CMQ==", "dev": true, "dependencies": { - "@volar/source-map": "1.10.1" + "@volar/source-map": "1.10.4" } }, "node_modules/@volar/source-map": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.10.1.tgz", - "integrity": "sha512-3/S6KQbqa7pGC8CxPrg69qHLpOvkiPHGJtWPkI/1AXCsktkJ6gIk/5z4hyuMp8Anvs6eS/Kvp/GZa3ut3votKA==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.10.4.tgz", + "integrity": "sha512-RxZdUEL+pV8p+SMqnhVjzy5zpb1QRZTlcwSk4bdcBO7yOu4rtEWqDGahVCEj4CcXour+0yJUMrMczfSCpP9Uxg==", "dev": true, "dependencies": { "muggle-string": "^0.3.1" } }, "node_modules/@volar/typescript": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.10.1.tgz", - "integrity": "sha512-+iiO9yUSRHIYjlteT+QcdRq8b44qH19/eiUZtjNtuh6D9ailYM7DVR0zO2sEgJlvCaunw/CF9Ov2KooQBpR4VQ==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.10.4.tgz", + "integrity": "sha512-BCCUEBASBEMCrz7qmNSi2hBEWYsXD0doaktRKpmmhvb6XntM2sAWYu6gbyK/MluLDgluGLFiFRpWgobgzUqolg==", "dev": true, "dependencies": { - "@volar/language-core": "1.10.1" + "@volar/language-core": "1.10.4" } }, "node_modules/@vue/compiler-core": { @@ -296,17 +296,17 @@ "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==" }, "node_modules/@vue/language-core": { - "version": "1.8.15", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.15.tgz", - "integrity": "sha512-zche5Aw8kkvp3YaghuLiOZyVIpoWHjSQ0EfjxGSsqHOPMamdCoa9x3HtbenpR38UMUoKJ88wiWuiOrV3B/Yq+A==", + "version": "1.8.19", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.19.tgz", + "integrity": "sha512-nt3dodGs97UM6fnxeQBazO50yYCKBK53waFWB3qMbLmR6eL3aUryZgQtZoBe1pye17Wl8fs9HysV3si6xMgndQ==", "dev": true, "dependencies": { - "@volar/language-core": "~1.10.0", - "@volar/source-map": "~1.10.0", + "@volar/language-core": "~1.10.4", + "@volar/source-map": "~1.10.4", "@vue/compiler-dom": "^3.3.0", "@vue/reactivity": "^3.3.0", "@vue/shared": "^3.3.0", - "minimatch": "^9.0.0", + "minimatch": "^9.0.3", "muggle-string": "^0.3.1", "vue-template-compiler": "^2.7.14" }, @@ -376,13 +376,13 @@ "integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==" }, "node_modules/@vue/typescript": { - "version": "1.8.15", - "resolved": "https://registry.npmjs.org/@vue/typescript/-/typescript-1.8.15.tgz", - "integrity": "sha512-qWyanQKXOsK84S8rP7QBrqsvUdQ0nZABZmTjXMpb3ox4Bp5IbkscREA3OPUrkgl64mAxwwCzIWcOc3BPTCPjQw==", + "version": "1.8.19", + "resolved": "https://registry.npmjs.org/@vue/typescript/-/typescript-1.8.19.tgz", + "integrity": "sha512-k/SHeeQROUgqsxyHQ8Cs3Zz5TnX57p7BcBDVYR2E0c61QL2DJ2G8CsaBremmNGuGE6o1R5D50IHIxFmroMz8iw==", "dev": true, "dependencies": { - "@volar/typescript": "~1.10.0", - "@vue/language-core": "1.8.15" + "@volar/typescript": "~1.10.4", + "@vue/language-core": "1.8.19" } }, "node_modules/@vueuse/core": { @@ -993,9 +993,9 @@ } }, "node_modules/marked": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.0.tgz", - "integrity": "sha512-VZjm0PM5DMv7WodqOUps3g6Q7dmxs9YGiFUZ7a2majzQTTCgX+6S6NAJHPvOhgFBzYz8s4QZKWWMfZKFmsfOgA==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.1.tgz", + "integrity": "sha512-ZmXkUGH54U4rEy3GL9vYj8+S1PHJx/zz5pc4Frn7UdGiNREKT12fWBJ5a5ffjFtghx9C9912vEg9Zra1Nf7CnA==", "bin": { "marked": "bin/marked.js" }, @@ -1289,14 +1289,14 @@ } }, "node_modules/vue-tsc": { - "version": "1.8.15", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.15.tgz", - "integrity": "sha512-4DoB3LUj7IToLmggoCxRiFG+QU5lem0nv03m1ocqugXA9rSVoTOEoYYaP8vu8b99Eh+/cCVdYOeIAQ+RsgUYUw==", + "version": "1.8.19", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.19.tgz", + "integrity": "sha512-tacMQLQ0CXAfbhRycCL5sWIy1qujXaIEtP1hIQpzHWOUuICbtTj9gJyFf91PvzG5KCNIkA5Eg7k2Fmgt28l5DQ==", "dev": true, "dependencies": { - "@vue/language-core": "1.8.15", - "@vue/typescript": "1.8.15", - "semver": "^7.3.8" + "@vue/language-core": "1.8.19", + "@vue/typescript": "1.8.19", + "semver": "^7.5.4" }, "bin": { "vue-tsc": "bin/vue-tsc.js" diff --git a/src-vue/package.json b/src-vue/package.json index e4c8c49f..5d7ede3c 100644 --- a/src-vue/package.json +++ b/src-vue/package.json @@ -11,7 +11,7 @@ "dependencies": { "@element-plus/icons-vue": "^2.0.9", "element-plus": "^2.3.14", - "marked": "^9.1.0", + "marked": "^9.1.1", "tauri-plugin-store-api": "github:tauri-apps/tauri-plugin-store#9bd993aa67766596638bbfd91e79a1bf8f632014", "vue": "^3.2.37", "vue-i18n": "^9.5.0", @@ -23,6 +23,6 @@ "@vitejs/plugin-vue": "^3.1.0", "typescript": "^5.2.2", "vite": "^3.1.0", - "vue-tsc": "^1.8.15" + "vue-tsc": "^1.8.19" } } diff --git a/src-vue/src/App.vue b/src-vue/src/App.vue index f80e000d..30e5e683 100644 --- a/src-vue/src/App.vue +++ b/src-vue/src/App.vue @@ -34,9 +34,6 @@ export default { this.$root!.$i18n.locale = lang; }, methods: { - async toggleMaximize() { - await appWindow.toggleMaximize(); - }, minimize() { appWindow.minimize() }, @@ -77,7 +74,6 @@ export default { <!-- Window controls --> <div id="fc_window__controls"> <el-button color="white" icon="SemiSelect" @click="minimize" circle /> - <el-button color="white" icon="FullScreen" @click="toggleMaximize" circle /> <el-button color="white" icon="CloseBold" @click="close" circle /> </div> </nav> diff --git a/src-vue/src/components/ThunderstoreModCard.vue b/src-vue/src/components/ThunderstoreModCard.vue index 54241e85..11be7545 100644 --- a/src-vue/src/components/ThunderstoreModCard.vue +++ b/src-vue/src/components/ThunderstoreModCard.vue @@ -243,7 +243,7 @@ export default defineComponent({ // Capture translation method in a context, so it can be used outside Vue component context. // (see https://github.com/R2NorthstarTools/FlightCore/issues/384) (async (translate: Function) => { - await invoke<string>("install_mod_caller", { gameInstall: this.$store.state.game_install, thunderstoreModString: this.latestVersion.full_name }).then((message) => { + await invoke<string>("install_mod_wrapper", { gameInstall: this.$store.state.game_install, thunderstoreModString: this.latestVersion.full_name }).then((message) => { showNotification(translate('mods.card.install_success', { modName: mod.name }), message); }) .catch((error) => { diff --git a/src-vue/src/i18n/lang/en.json b/src-vue/src/i18n/lang/en.json index 2b056655..2bf18c2e 100644 --- a/src-vue/src/i18n/lang/en.json +++ b/src-vue/src/i18n/lang/en.json @@ -11,6 +11,7 @@ "yes": "Yes", "no": "No", "error": "Error", + "confirm": "Confirm", "cancel": "Cancel", "informationShort": "Info", "downloading": "Downloading", @@ -115,7 +116,10 @@ "edit": "Edit Profiles", "dialog": { - "title": "Profiles" + "title": "Profiles", + "delete_confirm": "Are you sure to delete this profile?", + "delete": "Delete", + "clone": "Clone" } }, diff --git a/src-vue/src/plugins/store.ts b/src-vue/src/plugins/store.ts index b0eaaf65..2b9b03c8 100644 --- a/src-vue/src/plugins/store.ts +++ b/src-vue/src/plugins/store.ts @@ -62,7 +62,7 @@ export const store = createStore<FlightCoreStore>({ state(): FlightCoreStore { return { developer_mode: false, - game_install: {} as unknown as GameInstall, + game_install: {game_path: undefined, profile: undefined, install_type: "UNKNOWN"} as unknown as GameInstall, available_profiles: [], @@ -152,8 +152,15 @@ export const store = createStore<FlightCoreStore>({ await persistentStore.set('game-install', { value: state.game_install }); await persistentStore.save(); // explicit save to disk + // We can no longer be sure if our last profile is valid, lets reset to be sure + state.game_install.profile = "R2Northstar"; + // Check for Northstar install store.commit('checkNorthstarUpdates'); + + // Since we are in a new game directory, lets see if there are any profiles + store.commit('fetchProfiles'); + } else { // Not valid Titanfall2 install @@ -184,7 +191,7 @@ export const store = createStore<FlightCoreStore>({ switch (state.northstar_state) { // Install northstar if it wasn't detected. case NorthstarState.INSTALL: - let install_northstar_result = invoke("install_northstar_caller", { gameInstall: state.game_install, northstarPackageName: state.northstar_release_canal }); + let install_northstar_result = invoke("install_northstar_wrapper", { gameInstall: state.game_install, northstarPackageName: state.northstar_release_canal }); state.northstar_state = NorthstarState.INSTALLING; await install_northstar_result.then((message) => { @@ -201,7 +208,7 @@ export const store = createStore<FlightCoreStore>({ // Update northstar if it is outdated. case NorthstarState.MUST_UPDATE: // Updating is the same as installing, simply overwrites the existing files - let reinstall_northstar_result = invoke("install_northstar_caller", { gameInstall: state.game_install, northstarPackageName: state.northstar_release_canal }); + let reinstall_northstar_result = invoke("install_northstar_wrapper", { gameInstall: state.game_install, northstarPackageName: state.northstar_release_canal }); state.northstar_state = NorthstarState.UPDATING; await reinstall_northstar_result.then((message) => { @@ -324,6 +331,12 @@ export const store = createStore<FlightCoreStore>({ ); }, async fetchProfiles(state: FlightCoreStore) { + // To fetch profiles we need a valid game path + if (!state.game_install.game_path) { + return; + } + + await invoke("fetch_profiles", { gameInstall: state.game_install }) .then((message) => { state.available_profiles = message as string[]; @@ -435,8 +448,6 @@ async function _initializeApp(state: any) { await _get_northstar_version_number(state); } - store.commit('fetchProfiles'); - await invoke<[number, number]>("get_server_player_count") .then((message) => { state.player_count = message[0]; diff --git a/src-vue/src/style.css b/src-vue/src/style.css index c66a6248..dfe682bf 100644 --- a/src-vue/src/style.css +++ b/src-vue/src/style.css @@ -46,3 +46,11 @@ body { color: white; margin: 30px 15px; } + +.el-popper { + width: 200px !important; +} + +.el-popconfirm { + word-break: break-word; +} diff --git a/src-vue/src/views/DeveloperView.vue b/src-vue/src/views/DeveloperView.vue index 206d425b..1b455452 100644 --- a/src-vue/src/views/DeveloperView.vue +++ b/src-vue/src/views/DeveloperView.vue @@ -249,7 +249,7 @@ export default defineComponent({ }, async installMod() { let mod_to_install = this.mod_to_install_field_string; - await invoke<string>("install_mod_caller", { gameInstall: this.$store.state.game_install, thunderstoreModString: mod_to_install }).then((message) => { + await invoke<string>("install_mod_wrapper", { gameInstall: this.$store.state.game_install, thunderstoreModString: mod_to_install }).then((message) => { // Show user notification if mod install completed. showNotification(`Installed ${mod_to_install}`, message); }) @@ -317,7 +317,7 @@ export default defineComponent({ 0 ); - let install_northstar_result = invoke("install_northstar_caller", { gameInstall: this.$store.state.game_install, northstarPackageName: this.selected_ns_version.value.package, versionNumber: this.selected_ns_version.value.version }); + let install_northstar_result = invoke("install_northstar_wrapper", { gameInstall: this.$store.state.game_install, northstarPackageName: this.selected_ns_version.value.package, versionNumber: this.selected_ns_version.value.version }); await install_northstar_result .then((message) => { diff --git a/src-vue/src/views/RepairView.vue b/src-vue/src/views/RepairView.vue index ce7e154d..341dff2d 100644 --- a/src-vue/src/views/RepairView.vue +++ b/src-vue/src/views/RepairView.vue @@ -75,7 +75,7 @@ export default defineComponent({ 0 ); - let install_northstar_result = invoke("install_northstar_caller", { gameInstall: this.$store.state.game_install, northstarPackageName: ReleaseCanal.RELEASE }); + let install_northstar_result = invoke("install_northstar_wrapper", { gameInstall: this.$store.state.game_install, northstarPackageName: ReleaseCanal.RELEASE }); appWindow.listen<InstallProgress>( 'northstar-install-download-progress', @@ -102,7 +102,7 @@ export default defineComponent({ }); }, async cleanUpDownloadFolder() { - await invoke("clean_up_download_folder_caller", { gameInstall: this.$store.state.game_install, force: true }).then((message) => { + await invoke("clean_up_download_folder_wrapper", { gameInstall: this.$store.state.game_install, force: true }).then((message) => { // Show user notification if task completed. showNotification(this.$t('generic.done'), this.$t('generic.done')); }) diff --git a/src-vue/src/views/SettingsView.vue b/src-vue/src/views/SettingsView.vue index b1a62c56..70bffbc5 100644 --- a/src-vue/src/views/SettingsView.vue +++ b/src-vue/src/views/SettingsView.vue @@ -6,6 +6,23 @@ > <el-table :data="availableProfiles" > <el-table-column prop="name" label="Name" /> + <el-table-column align="right"> + <template #default="scope"> + <el-popconfirm + v-if="scope.row.name != 'R2Northstar'" + :title="$t('settings.profile.dialog.delete_confirm')" + :confirm-button-text="$t('generic.yes')" + :cancel-button-text="$t('generic.no')" + @confirm="deleteProfile(scope.row.name)" + > + <template #reference> + <el-button type="danger"> + {{ $t('settings.profile.dialog.delete') }} + </el-button> + </template> + </el-popconfirm> + </template> + </el-table-column> </el-table> </el-dialog> @@ -34,9 +51,9 @@ <!-- Northstar Active Profile --> <div class="fc_parameter__panel" v-if="$store.state.developer_mode"> <h3>{{ $t('settings.profile.active') }}</h3> - <el-dropdown trigger="click"> + <el-dropdown trigger="click" :disabled="!availableProfiles.length"> <el-button> - {{ $store.state.game_install.profile }} <el-icon class="el-icon--right"><arrow-down /></el-icon> + {{ activeProfile }} <el-icon class="el-icon--right" v-if="availableProfiles.length"><arrow-down /></el-icon> </el-button> <template #dropdown> <el-dropdown-menu> @@ -173,7 +190,10 @@ export default defineComponent({ await persistentStore.save(); // explicit save to disk } }, - availableProfiles(): Object { + activeProfile(): String { + return this.$store.state.game_install.profile || "None"; + }, + availableProfiles(): Object[] { let profiles = this.$store.state.available_profiles // convert string array to object array so we can fill a table @@ -209,6 +229,15 @@ export default defineComponent({ }); }, async openGameInstallFolder() { + // Verify the game path is actually set + if (!this.$store.state.game_install.game_path) { + showErrorNotification( + i18n.global.tc('notification.game_folder.not_found.text'), + i18n.global.tc('notification.game_folder.not_found.title') + ); + return; + } + // Opens the folder in default file explorer application await open(`${this.$store.state.game_install.game_path}`); }, @@ -244,10 +273,29 @@ export default defineComponent({ console.error(error); showErrorNotification(error); }); - } + }, + async deleteProfile(profile: string) { + let store = this.$store; + await invoke("delete_profile", { + gameInstall: store.state.game_install, + profile: profile, + }).then(async (message) => { + if (profile == store.state.game_install.profile) + { + // trying to delete the active profile, lets switch to the default profile + await this.switchProfile("R2Northstar"); + } + store.commit('fetchProfiles'); + showNotification('Success'); + }).catch((error) => { + console.error(error); + showErrorNotification(error); + }); + }, }, mounted() { document.querySelector('input')!.disabled = true; + this.$store.commit('fetchProfiles'); }, unmounted() { if (('' + this.modsPerPage) === '') { |