diff --git a/.editorconfig b/.editorconfig
index b4b1641f..5cf88b9b 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -3,16 +3,23 @@ root = true
[*]
charset = utf-8
-indent_style = space
-indent_size = 2
+indent_style = tab
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = 100
[*.md]
+indent_size = 2
max_line_length = off
-trim_trailing_whitespace = false
-[*.{rs,java,kts}]
-indent_size = 4
+[*.toml]
+indent_size = 2
+
+[*.json]
+indent_size = 2
+
+# YAML requires space indentation by spec
+[*.{yml,yaml}]
+indent_size = 2
+indent_style = space
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 73f69e09..00000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
-# Editor-based HTTP Client requests
-/httpRequests/
diff --git a/.idea/code.iml b/.idea/code.iml
deleted file mode 100644
index aeca7f8c..00000000
--- a/.idea/code.iml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.idea/discord.xml b/.idea/discord.xml
deleted file mode 100644
index d8e95616..00000000
--- a/.idea/discord.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/KotlinJavaRuntime.xml b/.idea/libraries/KotlinJavaRuntime.xml
deleted file mode 100644
index 78d18789..00000000
--- a/.idea/libraries/KotlinJavaRuntime.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 23968dc6..00000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 7ddfc9ed..00000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 00000000..65f06574
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,3 @@
+Cargo.lock
+pnpm-lock.yaml
+.github/**/*.png
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 9caec96a..81e9bb92 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,9 +1,15 @@
{
- "prettier.endOfLine": "lf",
- "editor.formatOnSave": true,
- "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
- "editor.detectIndentation": true,
- "editor.codeActionsOnSave": {
- "source.fixAll.eslint": "explicit"
- }
+ "prettier.endOfLine": "lf",
+ "editor.formatOnSave": true,
+ "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
+ "editor.detectIndentation": false,
+ "editor.insertSpaces": false,
+ "files.eol": "\n",
+ "files.trimTrailingWhitespace": true,
+ "files.insertFinalNewline": true,
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": "explicit",
+ "source.organizeImports": "always"
+ },
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
}
diff --git a/COPYING.md b/COPYING.md
index 37aed2dd..1b18b36c 100644
--- a/COPYING.md
+++ b/COPYING.md
@@ -2,7 +2,7 @@
All packages in this repository are licensed under their respective licenses. For more information, refer to the LICENSE file in each package.
-For detailed information, consult each package's COPYING.md file, if available.
+For detailed information, consult each package's COPYING.md, LICENSE.txt, or LICENSE file, if available.
## Modrinth Branding
diff --git a/Cargo.lock b/Cargo.lock
index 61ac18bf..8e8d060b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -8,7 +8,7 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"bytes",
"futures-core",
"futures-sink",
@@ -44,7 +44,7 @@ dependencies = [
"actix-service",
"actix-utils",
"actix-web",
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"bytes",
"derive_more 0.99.20",
"futures-core",
@@ -68,7 +68,7 @@ dependencies = [
"actix-service",
"actix-utils",
"base64 0.22.1",
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"brotli",
"bytes",
"bytestring",
@@ -87,7 +87,7 @@ dependencies = [
"mime",
"percent-encoding",
"pin-project-lite",
- "rand 0.9.1",
+ "rand 0.9.2",
"sha1",
"smallvec",
"tokio",
@@ -103,7 +103,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
dependencies = [
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -137,11 +137,11 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e11eb847f49a700678ea2fa73daeb3208061afa2b9d1a8527c03390f4c4a1c6b"
dependencies = [
- "darling",
+ "darling 0.20.11",
"parse-size",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -182,7 +182,7 @@ dependencies = [
"futures-core",
"futures-util",
"mio",
- "socket2",
+ "socket2 0.5.10",
"tokio",
"tracing",
]
@@ -244,7 +244,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"smallvec",
- "socket2",
+ "socket2 0.5.10",
"time",
"tracing",
"url",
@@ -259,7 +259,7 @@ dependencies = [
"actix-router",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -386,9 +386,9 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.6.19"
+version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
+checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -416,35 +416,35 @@ dependencies = [
[[package]]
name = "anstyle-query"
-version = "1.1.3"
+version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
+checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
dependencies = [
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
name = "anstyle-wincon"
-version = "3.0.9"
+version = "3.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
+checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
dependencies = [
"anstyle",
"once_cell_polyfill",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
name = "anyhow"
-version = "1.0.98"
+version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
+checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
[[package]]
name = "arbitrary"
-version = "1.4.1"
+version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223"
+checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
dependencies = [
"derive_arbitrary",
]
@@ -457,7 +457,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -483,8 +483,8 @@ dependencies = [
"serde_bytes",
"serde_cbor",
"serde_json",
- "thiserror 2.0.12",
- "uuid 1.17.0",
+ "thiserror 2.0.14",
+ "uuid 1.18.0",
]
[[package]]
@@ -508,7 +508,7 @@ dependencies = [
"enumflags2",
"futures-channel",
"futures-util",
- "rand 0.9.1",
+ "rand 0.9.2",
"raw-window-handle",
"serde",
"serde_repr",
@@ -526,7 +526,7 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
dependencies = [
- "event-listener 5.4.0",
+ "event-listener 5.4.1",
"event-listener-strategy",
"futures-core",
"pin-project-lite",
@@ -583,57 +583,56 @@ dependencies = [
"async-task",
"concurrent-queue",
"fastrand 2.3.0",
- "futures-lite 2.6.0",
+ "futures-lite 2.6.1",
"pin-project-lite",
"slab",
]
[[package]]
name = "async-fs"
-version = "2.1.2"
+version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a"
+checksum = "09f7e37c0ed80b2a977691c47dae8625cfb21e205827106c64f7c588766b2e50"
dependencies = [
"async-lock",
"blocking",
- "futures-lite 2.6.0",
+ "futures-lite 2.6.1",
]
[[package]]
name = "async-io"
-version = "2.4.1"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3"
+checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca"
dependencies = [
"async-lock",
"cfg-if",
"concurrent-queue",
"futures-io",
- "futures-lite 2.6.0",
+ "futures-lite 2.6.1",
"parking",
"polling",
"rustix 1.0.8",
"slab",
- "tracing",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
name = "async-lock"
-version = "3.4.0"
+version = "3.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
+checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc"
dependencies = [
- "event-listener 5.4.0",
+ "event-listener 5.4.1",
"event-listener-strategy",
"pin-project-lite",
]
[[package]]
name = "async-process"
-version = "2.3.1"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc"
+checksum = "65daa13722ad51e6ab1a1b9c01299142bc75135b337923cfa10e79bbbd669f00"
dependencies = [
"async-channel 2.5.0",
"async-io",
@@ -642,10 +641,9 @@ dependencies = [
"async-task",
"blocking",
"cfg-if",
- "event-listener 5.4.0",
- "futures-lite 2.6.0",
+ "event-listener 5.4.1",
+ "futures-lite 2.6.1",
"rustix 1.0.8",
- "tracing",
]
[[package]]
@@ -656,14 +654,14 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
name = "async-signal"
-version = "0.2.11"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7605a4e50d4b06df3898d5a70bf5fde51ed9059b0434b73105193bc27acce0d"
+checksum = "f567af260ef69e1d52c2b560ce0ea230763e6fbb9214a85d768760a920e3e3c1"
dependencies = [
"async-io",
"async-lock",
@@ -674,7 +672,7 @@ dependencies = [
"rustix 1.0.8",
"signal-hook-registry",
"slab",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -696,7 +694,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -731,20 +729,20 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
[[package]]
name = "async-trait"
-version = "0.1.88"
+version = "0.1.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
+checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
name = "async-tungstenite"
-version = "0.29.1"
+version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef0f7efedeac57d9b26170f72965ecfd31473ca52ca7a64e925b0b6f5f079886"
+checksum = "e308e9866b891743e3fdf9dfd6b57f85c5062ca01ce4fed6f393e76eb5accea4"
dependencies = [
"atomic-waker",
"futures-core",
@@ -757,7 +755,7 @@ dependencies = [
"tokio",
"tokio-rustls 0.26.2",
"tungstenite",
- "webpki-roots 0.26.11",
+ "webpki-roots 1.0.2",
]
[[package]]
@@ -767,8 +765,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37672978ae0febce7516ae0a85b53e6185159a9a28787391eb63fc44ec36037d"
dependencies = [
"async-fs",
- "futures-lite 2.6.0",
- "thiserror 2.0.12",
+ "futures-lite 2.6.1",
+ "thiserror 2.0.14",
]
[[package]]
@@ -780,7 +778,7 @@ dependencies = [
"async-compression",
"chrono",
"crc32fast",
- "futures-lite 2.6.0",
+ "futures-lite 2.6.1",
"pin-project",
"thiserror 1.0.69",
"tokio",
@@ -833,7 +831,7 @@ checksum = "07a9b245ba0739fc90935094c29adbaee3f977218b5fb95e822e261cda7f56a3"
dependencies = [
"http 1.3.1",
"log",
- "rustls 0.23.29",
+ "rustls 0.23.31",
"serde",
"serde_json",
"url",
@@ -862,9 +860,9 @@ dependencies = [
[[package]]
name = "avif-serialize"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ea8ef51aced2b9191c08197f55450d830876d9933f8f48a429b354f1d496b42"
+checksum = "47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f"
dependencies = [
"arrayvec",
]
@@ -1022,9 +1020,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.9.1"
+version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29"
dependencies = [
"serde",
]
@@ -1080,7 +1078,7 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2"
dependencies = [
- "objc2 0.6.1",
+ "objc2 0.6.2",
]
[[package]]
@@ -1092,7 +1090,7 @@ dependencies = [
"async-channel 2.5.0",
"async-task",
"futures-io",
- "futures-lite 2.6.0",
+ "futures-lite 2.6.1",
"piper",
]
@@ -1116,14 +1114,14 @@ dependencies = [
"proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
name = "brotli"
-version = "8.0.1"
+version = "8.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d"
+checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
@@ -1185,9 +1183,9 @@ dependencies = [
[[package]]
name = "bytemuck"
-version = "1.23.1"
+version = "1.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422"
+checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677"
[[package]]
name = "byteorder"
@@ -1234,7 +1232,7 @@ version = "0.18.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"cairo-sys-rs",
"glib",
"libc",
@@ -1255,9 +1253,9 @@ dependencies = [
[[package]]
name = "camino"
-version = "1.1.10"
+version = "1.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab"
+checksum = "5d07aa9a93b00c76f71bc35d598bed923f6d4f3a9ca5c24b7737ae1a292841c0"
dependencies = [
"serde",
]
@@ -1282,24 +1280,24 @@ dependencies = [
"semver",
"serde",
"serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
]
[[package]]
name = "cargo_toml"
-version = "0.22.1"
+version = "0.22.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02260d489095346e5cafd04dea8e8cb54d1d74fcd759022a9b72986ebe9a1257"
+checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77"
dependencies = [
"serde",
- "toml 0.8.23",
+ "toml 0.9.5",
]
[[package]]
name = "cc"
-version = "1.2.29"
+version = "1.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362"
+checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f"
dependencies = [
"jobserver",
"libc",
@@ -1329,7 +1327,7 @@ checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f"
dependencies = [
"byteorder",
"fnv",
- "uuid 1.17.0",
+ "uuid 1.18.0",
]
[[package]]
@@ -1398,9 +1396,9 @@ checksum = "93a719913643003b84bd13022b4b7e703c09342cd03b679c4641c7d2e50dc34d"
[[package]]
name = "clap"
-version = "4.5.41"
+version = "4.5.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
+checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318"
dependencies = [
"clap_builder",
"clap_derive",
@@ -1408,9 +1406,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.41"
+version = "4.5.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
+checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8"
dependencies = [
"anstream",
"anstyle",
@@ -1420,14 +1418,14 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "4.5.41"
+version = "4.5.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
+checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -1460,7 +1458,7 @@ dependencies = [
"time",
"tokio",
"url",
- "uuid 1.17.0",
+ "uuid 1.18.0",
]
[[package]]
@@ -1472,7 +1470,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -1521,15 +1519,15 @@ dependencies = [
[[package]]
name = "console"
-version = "0.15.11"
+version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8"
+checksum = "2e09ced7ebbccb63b4c65413d821f2e00ce54c5ca4514ddc6b3c892fdbcbc69d"
dependencies = [
"encode_unicode",
"libc",
"once_cell",
"unicode-width 0.2.1",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -1611,9 +1609,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
name = "convert_case"
-version = "0.6.0"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
+checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f"
dependencies = [
"unicode-segmentation",
]
@@ -1690,7 +1688,7 @@ version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"core-foundation 0.10.1",
"core-graphics-types",
"foreign-types",
@@ -1703,7 +1701,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"core-foundation 0.10.1",
"libc",
]
@@ -1842,7 +1840,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
dependencies = [
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -1873,7 +1871,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501"
dependencies = [
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -1883,7 +1881,7 @@ dependencies = [
"chrono",
"serde",
"serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
]
[[package]]
@@ -1905,7 +1903,7 @@ dependencies = [
"serde-xml-rs",
"serde_json",
"sha1_smol",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tokio",
"tracing",
"tracing-error",
@@ -1918,8 +1916,18 @@ version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
dependencies = [
- "darling_core",
- "darling_macro",
+ "darling_core 0.20.11",
+ "darling_macro 0.20.11",
+]
+
+[[package]]
+name = "darling"
+version = "0.21.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08440b3dd222c3d0433e63e097463969485f112baff337dfdaca043a0d760570"
+dependencies = [
+ "darling_core 0.21.2",
+ "darling_macro 0.21.2",
]
[[package]]
@@ -1933,7 +1941,20 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
- "syn 2.0.104",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.21.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d25b7912bc28a04ab1b7715a68ea03aaa15662b43a1a4b2c480531fd19f8bf7e"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
]
[[package]]
@@ -1942,9 +1963,20 @@ version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
- "darling_core",
+ "darling_core 0.20.11",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.21.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce154b9bea7fb0c8e8326e62d00354000c36e79770ff21b8c84e3aa267d9d531"
+dependencies = [
+ "darling_core 0.21.2",
+ "quote",
+ "syn 2.0.106",
]
[[package]]
@@ -1987,9 +2019,9 @@ dependencies = [
[[package]]
name = "deadpool-redis"
-version = "0.21.1"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "667d186d69c8b4dd7f8cf1ac71bec88b312e1752f2d1a63028aa9ea124c3f191"
+checksum = "c0965b977f1244bc3783bb27cd79cfcff335a8341da18f79232d00504b18eb1a"
dependencies = [
"deadpool",
"redis",
@@ -2011,7 +2043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d"
dependencies = [
"serde",
- "uuid 1.17.0",
+ "uuid 1.18.0",
]
[[package]]
@@ -2043,13 +2075,13 @@ dependencies = [
[[package]]
name = "derive_arbitrary"
-version = "1.4.1"
+version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800"
+checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2067,10 +2099,10 @@ version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
dependencies = [
- "darling",
+ "darling 0.20.11",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2080,7 +2112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
dependencies = [
"derive_builder_core",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2093,7 +2125,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustc_version",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2113,7 +2145,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"unicode-xid",
]
@@ -2156,7 +2188,7 @@ checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
dependencies = [
"libc",
"option-ext",
- "redox_users 0.5.0",
+ "redox_users 0.5.2",
"windows-sys 0.60.2",
]
@@ -2196,10 +2228,10 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"block2 0.6.1",
"libc",
- "objc2 0.6.1",
+ "objc2 0.6.2",
]
[[package]]
@@ -2210,7 +2242,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2242,7 +2274,7 @@ checksum = "788160fb30de9cdd857af31c6a2675904b16ece8fc2737b2c7127ba368c9d0f4"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2313,9 +2345,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "dyn-clone"
-version = "1.0.19"
+version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005"
+checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
[[package]]
name = "ecdsa"
@@ -2385,7 +2417,7 @@ dependencies = [
"cc",
"memchr",
"rustc_version",
- "toml 0.9.2",
+ "toml 0.9.5",
"vswhom",
"winreg 0.55.0",
]
@@ -2426,7 +2458,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2447,14 +2479,14 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
name = "enumset"
-version = "1.1.7"
+version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6ee17054f550fd7400e1906e2f9356c7672643ed34008a9e8abe147ccd2d821"
+checksum = "41326c68a68a5d2235daf392dc0da9f342a6579284b1a12ce1e6fed6c95fe19e"
dependencies = [
"enumset_derive",
"serde",
@@ -2462,14 +2494,14 @@ dependencies = [
[[package]]
name = "enumset_derive"
-version = "0.12.0"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76d07902c93376f1e96c34abc4d507c0911df3816cef50b01f5a2ff3ad8c370d"
+checksum = "86b0b3dd7a4444d18c9331b659b5f309577448a2e47f0c125fed64407bc0a82c"
dependencies = [
- "darling",
+ "darling 0.21.2",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2514,7 +2546,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2562,9 +2594,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "event-listener"
-version = "5.4.0"
+version = "5.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae"
+checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
dependencies = [
"concurrent-queue",
"parking",
@@ -2577,7 +2609,7 @@ version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
dependencies = [
- "event-listener 5.4.0",
+ "event-listener 5.4.1",
"pin-project-lite",
]
@@ -2727,7 +2759,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -2863,9 +2895,9 @@ dependencies = [
[[package]]
name = "futures-lite"
-version = "2.6.0"
+version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532"
+checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
dependencies = [
"fastrand 2.3.0",
"futures-core",
@@ -2882,7 +2914,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -3150,7 +3182,7 @@ version = "0.18.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"futures-channel",
"futures-core",
"futures-executor",
@@ -3178,7 +3210,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -3193,9 +3225,9 @@ dependencies = [
[[package]]
name = "glob"
-version = "0.3.2"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
+checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
[[package]]
name = "gobject-sys"
@@ -3268,7 +3300,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -3292,9 +3324,9 @@ dependencies = [
[[package]]
name = "h2"
-version = "0.4.11"
+version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785"
+checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386"
dependencies = [
"atomic-waker",
"bytes",
@@ -3346,9 +3378,9 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.15.4"
+version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2",
"equivalent",
@@ -3361,7 +3393,7 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
dependencies = [
- "hashbrown 0.15.4",
+ "hashbrown 0.15.5",
]
[[package]]
@@ -3417,9 +3449,9 @@ dependencies = [
"idna",
"ipnet",
"once_cell",
- "rand 0.9.1",
+ "rand 0.9.2",
"ring",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tinyvec",
"tokio",
"tracing",
@@ -3439,10 +3471,10 @@ dependencies = [
"moka",
"once_cell",
"parking_lot",
- "rand 0.9.1",
+ "rand 0.9.2",
"resolv-conf",
"smallvec",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tokio",
"tracing",
]
@@ -3615,7 +3647,7 @@ dependencies = [
"httpdate",
"itoa",
"pin-project-lite",
- "socket2",
+ "socket2 0.5.10",
"tokio",
"tower-service",
"tracing",
@@ -3631,7 +3663,7 @@ dependencies = [
"bytes",
"futures-channel",
"futures-util",
- "h2 0.4.11",
+ "h2 0.4.12",
"http 1.3.1",
"http-body 1.0.1",
"httparse",
@@ -3668,13 +3700,13 @@ dependencies = [
"http 1.3.1",
"hyper 1.6.0",
"hyper-util",
- "rustls 0.23.29",
+ "rustls 0.23.31",
"rustls-native-certs 0.8.1",
"rustls-pki-types",
"tokio",
"tokio-rustls 0.26.2",
"tower-service",
- "webpki-roots 1.0.1",
+ "webpki-roots 1.0.2",
]
[[package]]
@@ -3692,9 +3724,9 @@ dependencies = [
[[package]]
name = "hyper-util"
-version = "0.1.15"
+version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df"
+checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e"
dependencies = [
"base64 0.22.1",
"bytes",
@@ -3708,7 +3740,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
- "socket2",
+ "socket2 0.6.0",
"system-configuration",
"tokio",
"tower-service",
@@ -3926,20 +3958,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
dependencies = [
"equivalent",
- "hashbrown 0.15.4",
+ "hashbrown 0.15.5",
"serde",
]
[[package]]
name = "indicatif"
-version = "0.17.11"
+version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235"
+checksum = "70a646d946d06bedbbc4cac4c218acf4bbf2d87757a784857025f4d447e4e1cd"
dependencies = [
"console",
- "number_prefix",
"portable-atomic",
"unicode-width 0.2.1",
+ "unit-prefix",
"web-time",
]
@@ -3986,7 +4018,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"inotify-sys",
"libc",
]
@@ -4017,16 +4049,16 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
name = "io-uring"
-version = "0.7.8"
+version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
+checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"cfg-if",
"libc",
]
@@ -4037,7 +4069,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f"
dependencies = [
- "socket2",
+ "socket2 0.5.10",
"widestring",
"windows-sys 0.48.0",
"winreg 0.50.0",
@@ -4168,9 +4200,9 @@ dependencies = [
[[package]]
name = "jemalloc_pprof"
-version = "0.7.0"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5622af6d21ff86ed7797ef98e11b8f302da25ec69a7db9f6cde8e2e1c8df9992"
+checksum = "74ff642505c7ce8d31c0d43ec0e235c6fd4585d9b8172d8f9dd04d36590200b5"
dependencies = [
"anyhow",
"libc",
@@ -4294,7 +4326,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"serde",
"unicode-segmentation",
]
@@ -4348,7 +4380,7 @@ dependencies = [
"async-stripe",
"async-trait",
"base64 0.22.1",
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"bytes",
"censor",
"chrono",
@@ -4398,7 +4430,7 @@ dependencies = [
"spdx",
"sqlx",
"tar",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tikv-jemalloc-ctl",
"tikv-jemallocator",
"tokio",
@@ -4408,7 +4440,7 @@ dependencies = [
"tracing-actix-web",
"url",
"urlencoding",
- "uuid 1.17.0",
+ "uuid 1.18.0",
"validator",
"webp",
"woothee",
@@ -4440,9 +4472,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]]
name = "lettre"
-version = "0.11.17"
+version = "0.11.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb2a0354e9ece2fcdcf9fa53417f6de587230c0c248068eb058fa26c4a753179"
+checksum = "5cb54db6ff7a89efac87dba5baeac57bb9ccd726b49a9b6f21fb92b3966aaf56"
dependencies = [
"base64 0.22.1",
"chumsky",
@@ -4457,9 +4489,9 @@ dependencies = [
"nom 8.0.0",
"percent-encoding",
"quoted_printable",
- "rustls 0.23.29",
+ "rustls 0.23.31",
"rustls-native-certs 0.8.1",
- "socket2",
+ "socket2 0.6.0",
"tokio",
"url",
]
@@ -4490,15 +4522,15 @@ dependencies = [
[[package]]
name = "libbz2-rs-sys"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "775bf80d5878ab7c2b1080b5351a48b2f737d9f6f8b383574eebcc22be0dfccb"
+checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7"
[[package]]
name = "libc"
-version = "0.2.174"
+version = "0.2.175"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
+checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
[[package]]
name = "libfuzzer-sys"
@@ -4527,7 +4559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
dependencies = [
"cfg-if",
- "windows-targets 0.53.2",
+ "windows-targets 0.53.3",
]
[[package]]
@@ -4538,11 +4570,11 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "libredox"
-version = "0.1.4"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638"
+checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"libc",
"redox_syscall",
]
@@ -4597,9 +4629,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
[[package]]
name = "litrs"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
+checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed"
[[package]]
name = "local-channel"
@@ -4676,9 +4708,9 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
[[package]]
name = "mappings"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e434981a332777c2b3062652d16a55f8e74fa78e6b1882633f0d77399c84fc2a"
+checksum = "db4d277bb50d4508057e7bddd7fcd19ef4a4cc38051b6a5a36868d75ae2cbeb9"
dependencies = [
"anyhow",
"libc",
@@ -4709,7 +4741,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -4743,7 +4775,7 @@ dependencies = [
"log",
"memchr",
"serde",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
]
[[package]]
@@ -4754,7 +4786,7 @@ checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -4785,22 +4817,22 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
[[package]]
name = "meilisearch-index-setting-macro"
-version = "0.28.0"
+version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "420f67f5943a0236eea7f199720cc465e806c48978d9b0fdc1fb62eceaee7556"
+checksum = "14a9c03a7c7c9c2b6396bf824b7e9181feb242aafaddf43dede6ccff0ab8b229"
dependencies = [
- "convert_case 0.6.0",
+ "convert_case 0.8.0",
"proc-macro2",
"quote",
"structmeta",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
name = "meilisearch-sdk"
-version = "0.28.0"
+version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2325355c73c96667178c09675389cfa7afc2382d5aa0e0d34d0cf29793d89090"
+checksum = "b4bde2e2d304697ec15ec6475d2f299e73bb24347ab1d356de8709a83e3bf6f3"
dependencies = [
"async-trait",
"bytes",
@@ -4815,9 +4847,9 @@ dependencies = [
"reqwest",
"serde",
"serde_json",
- "thiserror 1.0.69",
+ "thiserror 2.0.14",
"time",
- "uuid 1.17.0",
+ "uuid 1.18.0",
"wasm-bindgen-futures",
"web-sys",
"yaup",
@@ -4913,28 +4945,28 @@ dependencies = [
"smallvec",
"tagptr",
"thiserror 1.0.69",
- "uuid 1.17.0",
+ "uuid 1.18.0",
]
[[package]]
name = "muda"
-version = "0.17.0"
+version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58b89bf91c19bf036347f1ab85a81c560f08c0667c8601bece664d860a600988"
+checksum = "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a"
dependencies = [
"crossbeam-channel",
"dpi",
"gtk",
"keyboard-types",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-foundation 0.3.1",
"once_cell",
"png",
"serde",
- "thiserror 2.0.12",
- "windows-sys 0.59.0",
+ "thiserror 2.0.14",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -4960,13 +4992,13 @@ dependencies = [
"dirs",
"dispatch2",
"formatx",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-foundation 0.3.1",
"raw-window-handle",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"versions",
"wfd",
"which",
@@ -4979,7 +5011,7 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"jni-sys",
"log",
"ndk-sys",
@@ -5015,7 +5047,7 @@ version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"cfg-if",
"cfg_aliases",
"libc",
@@ -5055,11 +5087,11 @@ checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
[[package]]
name = "notify"
-version = "8.1.0"
+version = "8.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3163f59cd3fa0e9ef8c32f242966a7b9994fd7378366099593e0e73077cd8c97"
+checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"fsevent-sys",
"inotify",
"kqueue",
@@ -5073,9 +5105,9 @@ dependencies = [
[[package]]
name = "notify-debouncer-mini"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a689eb4262184d9a1727f9087cd03883ea716682ab03ed24efec57d7716dccb8"
+checksum = "17849edfaabd9a5fef1c606d99cfc615a8e99f7ac4366406d86c7942a3184cf2"
dependencies = [
"log",
"notify",
@@ -5172,7 +5204,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -5255,15 +5287,9 @@ dependencies = [
"proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
-[[package]]
-name = "number_prefix"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
-
[[package]]
name = "objc-sys"
version = "0.3.5"
@@ -5282,9 +5308,9 @@ dependencies = [
[[package]]
name = "objc2"
-version = "0.6.1"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551"
+checksum = "561f357ba7f3a2a61563a186a163d0a3a5247e1089524a3981d49adb775078bc"
dependencies = [
"objc2-encode",
"objc2-exception-helper",
@@ -5296,10 +5322,10 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"block2 0.6.1",
"libc",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-cloud-kit",
"objc2-core-data",
"objc2-core-foundation",
@@ -5315,8 +5341,8 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17614fdcd9b411e6ff1117dfb1d0150f908ba83a7df81b1f118005fe0a8ea15d"
dependencies = [
- "bitflags 2.9.1",
- "objc2 0.6.1",
+ "bitflags 2.9.2",
+ "objc2 0.6.2",
"objc2-foundation 0.3.1",
]
@@ -5326,8 +5352,8 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291fbbf7d29287518e8686417cf7239c74700fd4b607623140a7d4a3c834329d"
dependencies = [
- "bitflags 2.9.1",
- "objc2 0.6.1",
+ "bitflags 2.9.2",
+ "objc2 0.6.2",
"objc2-foundation 0.3.1",
]
@@ -5337,11 +5363,11 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"block2 0.6.1",
"dispatch2",
"libc",
- "objc2 0.6.1",
+ "objc2 0.6.2",
]
[[package]]
@@ -5350,11 +5376,11 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"block2 0.6.1",
"dispatch2",
"libc",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-core-foundation",
"objc2-io-surface",
"objc2-metal 0.3.1",
@@ -5366,7 +5392,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79b3dc0cc4386b6ccf21c157591b34a7f44c8e75b064f85502901ab2188c007e"
dependencies = [
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-foundation 0.3.1",
]
@@ -5391,7 +5417,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"block2 0.5.1",
"libc",
"objc2 0.5.2",
@@ -5403,10 +5429,10 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"block2 0.6.1",
"libc",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-core-foundation",
]
@@ -5426,8 +5452,8 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c"
dependencies = [
- "bitflags 2.9.1",
- "objc2 0.6.1",
+ "bitflags 2.9.2",
+ "objc2 0.6.2",
"objc2-core-foundation",
]
@@ -5437,7 +5463,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
@@ -5449,8 +5475,8 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f246c183239540aab1782457b35ab2040d4259175bd1d0c58e46ada7b47a874"
dependencies = [
- "bitflags 2.9.1",
- "objc2 0.6.1",
+ "bitflags 2.9.2",
+ "objc2 0.6.2",
"objc2-foundation 0.3.1",
]
@@ -5460,8 +5486,8 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26bb88504b5a050dbba515d2414607bf5e57dd56b107bc5f0351197a3e7bdc5d"
dependencies = [
- "bitflags 2.9.1",
- "objc2 0.6.1",
+ "bitflags 2.9.2",
+ "objc2 0.6.2",
"objc2-app-kit",
"objc2-foundation 0.3.1",
]
@@ -5472,7 +5498,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
@@ -5485,8 +5511,8 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5"
dependencies = [
- "bitflags 2.9.1",
- "objc2 0.6.1",
+ "bitflags 2.9.2",
+ "objc2 0.6.2",
"objc2-foundation 0.3.1",
]
@@ -5496,8 +5522,8 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed"
dependencies = [
- "bitflags 2.9.1",
- "objc2 0.6.1",
+ "bitflags 2.9.2",
+ "objc2 0.6.2",
"objc2-core-foundation",
"objc2-foundation 0.3.1",
]
@@ -5508,9 +5534,9 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91672909de8b1ce1c2252e95bbee8c1649c9ad9d14b9248b3d7b4c47903c47ad"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"block2 0.6.1",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-foundation 0.3.1",
@@ -5603,12 +5629,12 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "732c71caeaa72c065bb69d7ea08717bd3f4863a4f451402fc9513e29dbd5261b"
dependencies = [
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-foundation 0.3.1",
"objc2-osa-kit",
"serde",
"serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
]
[[package]]
@@ -5757,6 +5783,17 @@ dependencies = [
"phf_shared 0.11.3",
]
+[[package]]
+name = "phf"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
+dependencies = [
+ "phf_macros 0.12.1",
+ "phf_shared 0.12.1",
+ "serde",
+]
+
[[package]]
name = "phf_codegen"
version = "0.8.0"
@@ -5807,6 +5844,16 @@ dependencies = [
"rand 0.8.5",
]
+[[package]]
+name = "phf_generator"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2cbb1126afed61dd6368748dae63b1ee7dc480191c6262a3b4ff1e29d86a6c5b"
+dependencies = [
+ "fastrand 2.3.0",
+ "phf_shared 0.12.1",
+]
+
[[package]]
name = "phf_macros"
version = "0.10.0"
@@ -5831,7 +5878,20 @@ dependencies = [
"phf_shared 0.11.3",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "phf_macros"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d713258393a82f091ead52047ca779d37e5766226d009de21696c4e667044368"
+dependencies = [
+ "phf_generator 0.12.1",
+ "phf_shared 0.12.1",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
]
[[package]]
@@ -5861,6 +5921,15 @@ dependencies = [
"siphasher 1.0.1",
]
+[[package]]
+name = "phf_shared"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
+dependencies = [
+ "siphasher 1.0.1",
+]
+
[[package]]
name = "pin-project"
version = "1.1.10"
@@ -5878,7 +5947,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -5939,7 +6008,7 @@ checksum = "3af6b589e163c5a788fab00ce0c0366f6efbb9959c2f9874b224936af7fce7e1"
dependencies = [
"base64 0.22.1",
"indexmap 2.10.0",
- "quick-xml 0.38.0",
+ "quick-xml 0.38.1",
"serde",
"time",
]
@@ -5959,17 +6028,16 @@ dependencies = [
[[package]]
name = "polling"
-version = "3.8.0"
+version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50"
+checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829"
dependencies = [
"cfg-if",
"concurrent-queue",
"hermit-abi",
"pin-project-lite",
"rustix 1.0.8",
- "tracing",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -5995,9 +6063,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "pprof_util"
-version = "0.7.0"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa015c78eed2130951e22c58d2095849391e73817ab2e74f71b0b9f63dd8416"
+checksum = "f9aba4251d95ac86f14c33e688d57a9344bfcff29e9b0c5a063fc66b5facc8a1"
dependencies = [
"anyhow",
"backtrace",
@@ -6117,7 +6185,7 @@ dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -6128,9 +6196,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
-version = "1.0.95"
+version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+checksum = "e7442a916bc70e3bf71a5305a899d53301649d2838345fa309420318b5ffafe8"
dependencies = [
"unicode-ident",
]
@@ -6141,7 +6209,7 @@ version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc5b72d8145275d844d4b5f6d4e1eef00c8cd889edb6035c21675d1bb1f45c9f"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"hex",
"procfs-core",
"rustix 0.38.44",
@@ -6153,7 +6221,7 @@ version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239df02d8349b06fc07398a3a1697b06418223b1c7725085e801e7c0fc6a12ec"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"hex",
]
@@ -6173,7 +6241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b"
dependencies = [
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -6190,7 +6258,7 @@ dependencies = [
"parking_lot",
"procfs",
"protobuf",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
]
[[package]]
@@ -6213,7 +6281,7 @@ dependencies = [
"itertools 0.14.0",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -6347,16 +6415,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
dependencies = [
"memchr",
- "tokio",
]
[[package]]
name = "quick-xml"
-version = "0.38.0"
+version = "0.38.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8927b0664f5c5a98265138b7e3f90aa19a6b21353182469ace36d4ac527b7b1b"
+checksum = "9845d9dccf565065824e69f9f235fafba1587031eda353c1f1561cd6a6be78f4"
dependencies = [
"memchr",
+ "tokio",
]
[[package]]
@@ -6371,9 +6439,9 @@ dependencies = [
"quinn-proto",
"quinn-udp",
"rustc-hash",
- "rustls 0.23.29",
- "socket2",
- "thiserror 2.0.12",
+ "rustls 0.23.31",
+ "socket2 0.5.10",
+ "thiserror 2.0.14",
"tokio",
"tracing",
"web-time",
@@ -6388,13 +6456,13 @@ dependencies = [
"bytes",
"getrandom 0.3.3",
"lru-slab",
- "rand 0.9.1",
+ "rand 0.9.2",
"ring",
"rustc-hash",
- "rustls 0.23.29",
+ "rustls 0.23.31",
"rustls-pki-types",
"slab",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tinyvec",
"tracing",
"web-time",
@@ -6409,7 +6477,7 @@ dependencies = [
"cfg_aliases",
"libc",
"once_cell",
- "socket2",
+ "socket2 0.5.10",
"tracing",
"windows-sys 0.59.0",
]
@@ -6479,9 +6547,9 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.9.1"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
+checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.3",
@@ -6620,9 +6688,9 @@ checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
[[package]]
name = "rayon"
-version = "1.10.0"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
+checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
dependencies = [
"either",
"rayon-core",
@@ -6630,9 +6698,9 @@ dependencies = [
[[package]]
name = "rayon-core"
-version = "1.12.1"
+version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
+checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
@@ -6640,9 +6708,9 @@ dependencies = [
[[package]]
name = "redis"
-version = "0.31.0"
+version = "0.32.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bc1ea653e0b2e097db3ebb5b7f678be339620b8041f66b30a308c1d45d36a7f"
+checksum = "7cd3650deebc68526b304898b192fa4102a4ef0b9ada24da096559cb60e0eef8"
dependencies = [
"ahash 0.8.12",
"bytes",
@@ -6656,7 +6724,7 @@ dependencies = [
"r2d2",
"ryu",
"sha1_smol",
- "socket2",
+ "socket2 0.6.0",
"tokio",
"tokio-util",
"url",
@@ -6664,11 +6732,11 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.5.13"
+version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
+checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
]
[[package]]
@@ -6684,13 +6752,13 @@ dependencies = [
[[package]]
name = "redox_users"
-version = "0.5.0"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
+checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
dependencies = [
"getrandom 0.2.16",
"libredox",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
]
[[package]]
@@ -6710,7 +6778,7 @@ checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -6780,9 +6848,9 @@ checksum = "51743d3e274e2b18df81c4dc6caf8a5b8e15dbe799e0dca05c7617380094e884"
[[package]]
name = "reqwest"
-version = "0.12.22"
+version = "0.12.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531"
+checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb"
dependencies = [
"async-compression",
"base64 0.22.1",
@@ -6793,7 +6861,7 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-util",
- "h2 0.4.11",
+ "h2 0.4.12",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
@@ -6807,7 +6875,7 @@ dependencies = [
"percent-encoding",
"pin-project-lite",
"quinn",
- "rustls 0.23.29",
+ "rustls 0.23.31",
"rustls-native-certs 0.8.1",
"rustls-pki-types",
"serde",
@@ -6825,7 +6893,7 @@ dependencies = [
"wasm-bindgen-futures",
"wasm-streams",
"web-sys",
- "webpki-roots 1.0.1",
+ "webpki-roots 1.0.2",
]
[[package]]
@@ -6864,7 +6932,7 @@ dependencies = [
"gtk-sys",
"js-sys",
"log",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-foundation 0.3.1",
@@ -6913,7 +6981,7 @@ dependencies = [
"rkyv_derive",
"seahash",
"tinyvec",
- "uuid 1.17.0",
+ "uuid 1.18.0",
]
[[package]]
@@ -7018,7 +7086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6268b74858287e1a062271b988a0c534bf85bbeb567fe09331bf40ed78113d5"
dependencies = [
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -7035,9 +7103,9 @@ dependencies = [
[[package]]
name = "rustc-demangle"
-version = "0.1.25"
+version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
+checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
[[package]]
name = "rustc-hash"
@@ -7060,7 +7128,7 @@ version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"errno",
"libc",
"linux-raw-sys 0.4.15",
@@ -7073,7 +7141,7 @@ version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"errno",
"libc",
"linux-raw-sys 0.9.4",
@@ -7094,9 +7162,9 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.23.29"
+version = "0.23.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1"
+checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc"
dependencies = [
"log",
"once_cell",
@@ -7128,7 +7196,7 @@ dependencies = [
"openssl-probe",
"rustls-pki-types",
"schannel",
- "security-framework 3.2.0",
+ "security-framework 3.3.0",
]
[[package]]
@@ -7182,9 +7250,9 @@ dependencies = [
[[package]]
name = "rustversion"
-version = "1.0.21"
+version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "rusty-money"
@@ -7258,7 +7326,7 @@ dependencies = [
"serde",
"serde_json",
"url",
- "uuid 1.17.0",
+ "uuid 1.18.0",
]
[[package]]
@@ -7294,7 +7362,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -7333,7 +7401,7 @@ checksum = "22f968c5ea23d555e670b449c1c5e7b2fc399fdaec1d304a17cd48e288abc107"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -7356,7 +7424,7 @@ version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"core-foundation 0.9.4",
"core-foundation-sys",
"libc",
@@ -7365,11 +7433,11 @@ dependencies = [
[[package]]
name = "security-framework"
-version = "3.2.0"
+version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316"
+checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"core-foundation 0.10.1",
"core-foundation-sys",
"libc",
@@ -7415,13 +7483,13 @@ dependencies = [
[[package]]
name = "sentry"
-version = "0.41.0"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "507ac2be9bf2da56c831da57faf1dadd81f434bd282935cdb06193d0c94e8811"
+checksum = "989425268ab5c011e06400187eed6c298272f8ef913e49fcadc3fda788b45030"
dependencies = [
"httpdate",
"reqwest",
- "rustls 0.23.29",
+ "rustls 0.23.31",
"sentry-backtrace",
"sentry-contexts",
"sentry-core",
@@ -7434,9 +7502,9 @@ dependencies = [
[[package]]
name = "sentry-actix"
-version = "0.41.0"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8402c142005ee560ae361c73ebece13a299ec3e9cce5b8654479ea9aac8dc8df"
+checksum = "a5c675bdf6118764a8e265c3395c311b4d905d12866c92df52870c0223d2ffc1"
dependencies = [
"actix-http",
"actix-web",
@@ -7447,9 +7515,9 @@ dependencies = [
[[package]]
name = "sentry-backtrace"
-version = "0.41.0"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb4416302fa5325181a120e0fe7d4afd83cd95e52a9b86afa34a8161383fe0dc"
+checksum = "68e299dd3f7bcf676875eee852c9941e1d08278a743c32ca528e2debf846a653"
dependencies = [
"backtrace",
"regex",
@@ -7458,9 +7526,9 @@ dependencies = [
[[package]]
name = "sentry-contexts"
-version = "0.41.0"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "936752f42b6f651dcb257da0bfa235ecc79e82011c49ed3383c212cc582263ff"
+checksum = "fac0c5d6892cd4c414492fc957477b620026fb3411fca9fa12774831da561c88"
dependencies = [
"hostname",
"libc",
@@ -7472,21 +7540,22 @@ dependencies = [
[[package]]
name = "sentry-core"
-version = "0.41.0"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00e9bd2cadaeda3af41e9fa5d14645127d6f6a4aec73da3ae38e477ecafd3682"
+checksum = "deaa38b94e70820ff3f1f9db3c8b0aef053b667be130f618e615e0ff2492cbcc"
dependencies = [
- "rand 0.9.1",
+ "rand 0.9.2",
"sentry-types",
"serde",
"serde_json",
+ "url",
]
[[package]]
name = "sentry-debug-images"
-version = "0.41.0"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1e074fe9a0970c91999b23ed3195e6e30990d589fba3a68f20a1686af0f5cda"
+checksum = "00950648aa0d371c7f57057434ad5671bd4c106390df7e7284739330786a01b6"
dependencies = [
"findshlibs",
"sentry-core",
@@ -7494,9 +7563,9 @@ dependencies = [
[[package]]
name = "sentry-panic"
-version = "0.41.0"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4651d34f3ba649d9e6dc1268443cae6728b8f741c2f0264004f8ecf5b247330d"
+checksum = "2b7a23b13c004873de3ce7db86eb0f59fe4adfc655a31f7bbc17fd10bacc9bfe"
dependencies = [
"sentry-backtrace",
"sentry-core",
@@ -7504,11 +7573,11 @@ dependencies = [
[[package]]
name = "sentry-tracing"
-version = "0.41.0"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c25c47d36bc80c74d26d568ffe970c37b337c061b7234ad6f2d159439c16f000"
+checksum = "fac841c7050aa73fc2bec8f7d8e9cb1159af0b3095757b99820823f3e54e5080"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"sentry-backtrace",
"sentry-core",
"tracing-core",
@@ -7517,19 +7586,19 @@ dependencies = [
[[package]]
name = "sentry-types"
-version = "0.41.0"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a08e7154abe2cd557f26fd70038452810748aefdf39bc973f674421224b147c1"
+checksum = "e477f4d4db08ddb4ab553717a8d3a511bc9e81dde0c808c680feacbb8105c412"
dependencies = [
"debugid",
"hex",
- "rand 0.9.1",
+ "rand 0.9.2",
"serde",
"serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"time",
"url",
- "uuid 1.17.0",
+ "uuid 1.18.0",
]
[[package]]
@@ -7543,9 +7612,9 @@ dependencies = [
[[package]]
name = "serde-untagged"
-version = "0.1.7"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "299d9c19d7d466db4ab10addd5703e4c615dec2a5a16dbbafe191045e87ee66e"
+checksum = "34836a629bcbc6f1afdf0907a744870039b1e14c0561cb26094fa683b158eff3"
dependencies = [
"erased-serde",
"serde",
@@ -7591,7 +7660,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -7602,7 +7671,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -7618,9 +7687,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.140"
+version = "1.0.142"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
+checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
dependencies = [
"itoa",
"memchr",
@@ -7677,7 +7746,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -7707,7 +7776,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -7748,10 +7817,10 @@ version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f"
dependencies = [
- "darling",
+ "darling 0.20.11",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -7831,9 +7900,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
-version = "1.4.5"
+version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
+checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
dependencies = [
"libc",
]
@@ -7883,9 +7952,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]]
name = "slab"
-version = "0.4.10"
+version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
+checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
[[package]]
name = "smallvec"
@@ -7937,6 +8006,16 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "socket2"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
+dependencies = [
+ "libc",
+ "windows-sys 0.59.0",
+]
+
[[package]]
name = "softbuffer"
version = "0.4.6"
@@ -8038,12 +8117,12 @@ dependencies = [
"crc",
"crossbeam-queue",
"either",
- "event-listener 5.4.0",
+ "event-listener 5.4.1",
"futures-core",
"futures-intrusive",
"futures-io",
"futures-util",
- "hashbrown 0.15.4",
+ "hashbrown 0.15.5",
"hashlink",
"indexmap 2.10.0",
"log",
@@ -8051,17 +8130,17 @@ dependencies = [
"once_cell",
"percent-encoding",
"rust_decimal",
- "rustls 0.23.29",
+ "rustls 0.23.31",
"serde",
"serde_json",
"sha2",
"smallvec",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tokio",
"tokio-stream",
"tracing",
"url",
- "uuid 1.17.0",
+ "uuid 1.18.0",
"webpki-roots 0.26.11",
]
@@ -8075,7 +8154,7 @@ dependencies = [
"quote",
"sqlx-core",
"sqlx-macros-core",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -8098,7 +8177,7 @@ dependencies = [
"sqlx-mysql",
"sqlx-postgres",
"sqlx-sqlite",
- "syn 2.0.104",
+ "syn 2.0.106",
"tokio",
"url",
]
@@ -8111,7 +8190,7 @@ checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526"
dependencies = [
"atoi",
"base64 0.22.1",
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"byteorder",
"bytes",
"chrono",
@@ -8142,9 +8221,9 @@ dependencies = [
"smallvec",
"sqlx-core",
"stringprep",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tracing",
- "uuid 1.17.0",
+ "uuid 1.18.0",
"whoami",
]
@@ -8156,7 +8235,7 @@ checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46"
dependencies = [
"atoi",
"base64 0.22.1",
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"byteorder",
"chrono",
"crc",
@@ -8182,9 +8261,9 @@ dependencies = [
"smallvec",
"sqlx-core",
"stringprep",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tracing",
- "uuid 1.17.0",
+ "uuid 1.18.0",
"whoami",
]
@@ -8208,10 +8287,10 @@ dependencies = [
"serde",
"serde_urlencoded",
"sqlx-core",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tracing",
"url",
- "uuid 1.17.0",
+ "uuid 1.18.0",
]
[[package]]
@@ -8247,9 +8326,9 @@ checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb"
[[package]]
name = "strfmt"
-version = "0.2.4"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a8348af2d9fc3258c8733b8d9d8db2e56f54b2363a4b5b81585c7875ed65e65"
+checksum = "29fdc163db75f7b5ffa3daf0c5a7136fb0d4b2f35523cd1769da05e034159feb"
[[package]]
name = "string_cache"
@@ -8302,7 +8381,7 @@ dependencies = [
"proc-macro2",
"quote",
"structmeta-derive",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -8313,7 +8392,7 @@ checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -8346,9 +8425,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.104"
+version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
@@ -8372,7 +8451,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -8386,9 +8465,9 @@ dependencies = [
[[package]]
name = "sysinfo"
-version = "0.35.2"
+version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c3ffa3e4ff2b324a57f7aeb3c349656c7b127c3c189520251a648102a92496e"
+checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d"
dependencies = [
"libc",
"memchr",
@@ -8404,7 +8483,7 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"core-foundation 0.9.4",
"system-configuration-sys",
]
@@ -8444,7 +8523,7 @@ version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49c380ca75a231b87b6c9dd86948f035012e7171d1a7c40a9c2890489a7ffd8a"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"core-foundation 0.10.1",
"core-graphics",
"crossbeam-channel",
@@ -8461,7 +8540,7 @@ dependencies = [
"ndk",
"ndk-context",
"ndk-sys",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-app-kit",
"objc2-foundation 0.3.1",
"once_cell",
@@ -8485,7 +8564,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -8513,9 +8592,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "tauri"
-version = "2.6.2"
+version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "124e129c9c0faa6bec792c5948c89e86c90094133b0b9044df0ce5f0a8efaa0d"
+checksum = "352a4bc7bf6c25f5624227e3641adf475a6535707451b09bb83271df8b7a6ac7"
dependencies = [
"anyhow",
"bytes",
@@ -8533,7 +8612,7 @@ dependencies = [
"log",
"mime",
"muda",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-app-kit",
"objc2-foundation 0.3.1",
"objc2-ui-kit",
@@ -8551,7 +8630,7 @@ dependencies = [
"tauri-runtime",
"tauri-runtime-wry",
"tauri-utils",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tokio",
"tray-icon",
"url",
@@ -8564,9 +8643,9 @@ dependencies = [
[[package]]
name = "tauri-build"
-version = "2.3.0"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12f025c389d3adb83114bec704da973142e82fc6ec799c7c750c5e21cefaec83"
+checksum = "182d688496c06bf08ea896459bf483eb29cdff35c1c4c115fb14053514303064"
dependencies = [
"anyhow",
"cargo_toml",
@@ -8588,9 +8667,9 @@ dependencies = [
[[package]]
name = "tauri-codegen"
-version = "2.3.0"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5df493a1075a241065bc865ed5ef8d0fbc1e76c7afdc0bf0eccfaa7d4f0e406"
+checksum = "b54a99a6cd8e01abcfa61508177e6096a4fe2681efecee9214e962f2f073ae4a"
dependencies = [
"base64 0.22.1",
"brotli",
@@ -8604,34 +8683,34 @@ dependencies = [
"serde",
"serde_json",
"sha2",
- "syn 2.0.104",
+ "syn 2.0.106",
"tauri-utils",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"time",
"url",
- "uuid 1.17.0",
+ "uuid 1.18.0",
"walkdir",
]
[[package]]
name = "tauri-macros"
-version = "2.3.1"
+version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f237fbea5866fa5f2a60a21bea807a2d6e0379db070d89c3a10ac0f2d4649bbc"
+checksum = "7945b14dc45e23532f2ded6e120170bbdd4af5ceaa45784a6b33d250fbce3f9e"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"tauri-codegen",
"tauri-utils",
]
[[package]]
name = "tauri-plugin"
-version = "2.3.0"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d9a0bd00bf1930ad1a604d08b0eb6b2a9c1822686d65d7f4731a7723b8901d3"
+checksum = "5bd5c1e56990c70a906ef67a9851bbdba9136d26075ee9a2b19c8b46986b3e02"
dependencies = [
"anyhow",
"glob",
@@ -8646,9 +8725,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-deep-link"
-version = "2.4.0"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab261eb006db10ab478e3fbb5a4e2692df3f7eb3e28300ee2b64428979167ed0"
+checksum = "1fec67f32d7a06d80bd3dc009fdb678c35a66116d9cb8cd2bb32e406c2b5bbd2"
dependencies = [
"dunce",
"rust-ini",
@@ -8657,7 +8736,7 @@ dependencies = [
"tauri",
"tauri-plugin",
"tauri-utils",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tracing",
"url",
"windows-registry",
@@ -8666,9 +8745,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-dialog"
-version = "2.3.0"
+version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1aefb14219b492afb30b12647b5b1247cadd2c0603467310c36e0f7ae1698c28"
+checksum = "37e5858cc7b455a73ab4ea2ebc08b5be33682c00ff1bf4cad5537d4fb62499d9"
dependencies = [
"log",
"raw-window-handle",
@@ -8678,15 +8757,15 @@ dependencies = [
"tauri",
"tauri-plugin",
"tauri-plugin-fs",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"url",
]
[[package]]
name = "tauri-plugin-fs"
-version = "2.4.0"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c341290d31991dbca38b31d412c73dfbdb070bb11536784f19dd2211d13b778f"
+checksum = "8c6ef84ee2f2094ce093e55106d90d763ba343fad57566992962e8f76d113f99"
dependencies = [
"anyhow",
"dunce",
@@ -8699,16 +8778,16 @@ dependencies = [
"tauri",
"tauri-plugin",
"tauri-utils",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"toml 0.8.23",
"url",
]
[[package]]
name = "tauri-plugin-http"
-version = "2.5.0"
+version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0c1a38da944b357ffa23bafd563b1579f18e6fbd118fcd84769406d35dcc5c7"
+checksum = "fcde333d97e565a7765aad82f32d8672458f7bd77b6ee653830d5dded9d7b5c2"
dependencies = [
"bytes",
"cookie_store",
@@ -8722,7 +8801,7 @@ dependencies = [
"tauri",
"tauri-plugin",
"tauri-plugin-fs",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tokio",
"url",
"urlpattern",
@@ -8744,7 +8823,7 @@ dependencies = [
"serde_json",
"tauri",
"tauri-plugin",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"url",
"windows",
"zbus",
@@ -8765,19 +8844,19 @@ dependencies = [
"sys-locale",
"tauri",
"tauri-plugin",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
]
[[package]]
name = "tauri-plugin-single-instance"
-version = "2.3.0"
+version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b441b6d5d1a194e9fee0b358fe0d602ded845d0f580e1f8c8ef78ebc3c8b225d"
+checksum = "50a0e5a4ce43cb3a733c3aef85e8478bc769dac743c615e26639cbf5d953faf7"
dependencies = [
"serde",
"serde_json",
"tauri",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tracing",
"windows-sys 0.60.2",
"zbus",
@@ -8807,7 +8886,7 @@ dependencies = [
"tauri",
"tauri-plugin",
"tempfile",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"time",
"tokio",
"url",
@@ -8817,52 +8896,52 @@ dependencies = [
[[package]]
name = "tauri-plugin-window-state"
-version = "2.3.0"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3d22b21b9cec73601b512a868f7c74f93c044d44fd6ca1c84e9d6afb6b1559"
+checksum = "2d5f6fe3291bfa609c7e0b0ee3bedac294d94c7018934086ce782c1d0f2a468e"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"log",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
]
[[package]]
name = "tauri-runtime"
-version = "2.7.0"
+version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e7bb73d1bceac06c20b3f755b2c8a2cb13b20b50083084a8cf3700daf397ba4"
+checksum = "2b1cc885be806ea15ff7b0eb47098a7b16323d9228876afda329e34e2d6c4676"
dependencies = [
"cookie 0.18.1",
"dpi",
"gtk",
"http 1.3.1",
"jni",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-ui-kit",
"raw-window-handle",
"serde",
"serde_json",
"tauri-utils",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"url",
"windows",
]
[[package]]
name = "tauri-runtime-wry"
-version = "2.7.1"
+version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "902b5aa9035e16f342eb64f8bf06ccdc2808e411a2525ed1d07672fa4e780bad"
+checksum = "fe653a2fbbef19fe898efc774bc52c8742576342a33d3d028c189b57eb1d2439"
dependencies = [
"gtk",
"http 1.3.1",
"jni",
"log",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-app-kit",
"objc2-foundation 0.3.1",
"once_cell",
@@ -8881,9 +8960,9 @@ dependencies = [
[[package]]
name = "tauri-utils"
-version = "2.5.0"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41743bbbeb96c3a100d234e5a0b60a46d5aa068f266160862c7afdbf828ca02e"
+checksum = "9330c15cabfe1d9f213478c9e8ec2b0c76dab26bb6f314b8ad1c8a568c1d186e"
dependencies = [
"anyhow",
"brotli",
@@ -8909,23 +8988,22 @@ dependencies = [
"serde_json",
"serde_with",
"swift-rs",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"toml 0.8.23",
"url",
"urlpattern",
- "uuid 1.17.0",
+ "uuid 1.18.0",
"walkdir",
]
[[package]]
name = "tauri-winres"
-version = "0.3.1"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8d321dbc6f998d825ab3f0d62673e810c861aac2d0de2cc2c395328f1d113b4"
+checksum = "fd21509dd1fa9bd355dc29894a6ff10635880732396aa38c0066c1e6c1ab8074"
dependencies = [
"embed-resource",
- "indexmap 2.10.0",
- "toml 0.8.23",
+ "toml 0.9.5",
]
[[package]]
@@ -8999,9 +9077,10 @@ dependencies = [
"notify-debouncer-mini",
"p256",
"paste",
+ "phf 0.12.1",
"png",
"quartz_nbt",
- "quick-xml 0.37.5",
+ "quick-xml 0.38.1",
"rand 0.8.5",
"regex",
"reqwest",
@@ -9016,14 +9095,14 @@ dependencies = [
"sysinfo",
"tauri",
"tempfile",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tokio",
"tokio-util",
"tracing",
"tracing-error",
"tracing-subscriber",
"url",
- "uuid 1.17.0",
+ "uuid 1.18.0",
"whoami",
"winreg 0.55.0",
"zip",
@@ -9056,13 +9135,13 @@ dependencies = [
"tauri-plugin-updater",
"tauri-plugin-window-state",
"theseus",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"tokio",
"tracing",
"tracing-error",
"url",
"urlencoding",
- "uuid 1.17.0",
+ "uuid 1.18.0",
]
[[package]]
@@ -9085,11 +9164,11 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "2.0.12"
+version = "2.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
+checksum = "0b0949c3a6c842cbde3f1686d6eea5a010516deb7085f79db747562d4102f41e"
dependencies = [
- "thiserror-impl 2.0.12",
+ "thiserror-impl 2.0.14",
]
[[package]]
@@ -9100,18 +9179,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
name = "thiserror-impl"
-version = "2.0.12"
+version = "2.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
+checksum = "cc5b44b4ab9c2fdd0e0512e6bece8388e214c0749f5862b114cc5b7a25daf227"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -9232,9 +9311,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.46.1"
+version = "1.47.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
+checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
dependencies = [
"backtrace",
"bytes",
@@ -9245,10 +9324,10 @@ dependencies = [
"pin-project-lite",
"signal-hook-registry",
"slab",
- "socket2",
+ "socket2 0.6.0",
"tokio-macros",
"tracing",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -9259,7 +9338,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -9278,7 +9357,7 @@ version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
dependencies = [
- "rustls 0.23.29",
+ "rustls 0.23.31",
"tokio",
]
@@ -9295,9 +9374,9 @@ dependencies = [
[[package]]
name = "tokio-util"
-version = "0.7.15"
+version = "0.7.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
+checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5"
dependencies = [
"bytes",
"futures-core",
@@ -9321,9 +9400,9 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.9.2"
+version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed0aee96c12fa71097902e0bb061a5e1ebd766a6636bb605ba401c45c1650eac"
+checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8"
dependencies = [
"indexmap 2.10.0",
"serde",
@@ -9390,9 +9469,9 @@ dependencies = [
[[package]]
name = "toml_parser"
-version = "1.0.1"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30"
+checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10"
dependencies = [
"winnow 0.7.12",
]
@@ -9420,7 +9499,7 @@ dependencies = [
"axum",
"base64 0.22.1",
"bytes",
- "h2 0.4.11",
+ "h2 0.4.12",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
@@ -9430,7 +9509,7 @@ dependencies = [
"percent-encoding",
"pin-project",
"prost",
- "socket2",
+ "socket2 0.5.10",
"tokio",
"tokio-stream",
"tower 0.4.13",
@@ -9448,7 +9527,7 @@ dependencies = [
"base32",
"constant_time_eq",
"hmac",
- "rand 0.9.1",
+ "rand 0.9.2",
"sha1",
"sha2",
]
@@ -9494,7 +9573,7 @@ version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"bytes",
"futures-util",
"http 1.3.1",
@@ -9540,7 +9619,7 @@ dependencies = [
"mutually_exclusive_features",
"pin-project",
"tracing",
- "uuid 1.17.0",
+ "uuid 1.18.0",
]
[[package]]
@@ -9551,7 +9630,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -9606,15 +9685,15 @@ dependencies = [
[[package]]
name = "tray-icon"
-version = "0.21.0"
+version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2da75ec677957aa21f6e0b361df0daab972f13a5bee3606de0638fd4ee1c666a"
+checksum = "a0d92153331e7d02ec09137538996a7786fe679c629c279e82a6be762b7e6fe2"
dependencies = [
"crossbeam-channel",
"dirs",
"libappindicator",
"muda",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-core-graphics",
@@ -9622,7 +9701,7 @@ dependencies = [
"once_cell",
"png",
"serde",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"windows-sys 0.59.0",
]
@@ -9634,20 +9713,20 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "tungstenite"
-version = "0.26.2"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13"
+checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d"
dependencies = [
"bytes",
"data-encoding",
"http 1.3.1",
"httparse",
"log",
- "rand 0.9.1",
- "rustls 0.23.29",
+ "rand 0.9.2",
+ "rustls 0.23.31",
"rustls-pki-types",
"sha1",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"utf-8",
]
@@ -9781,6 +9860,12 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+[[package]]
+name = "unit-prefix"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "323402cff2dd658f39ca17c789b502021b3f18707c91cdf22e3838e1b4023817"
+
[[package]]
name = "untrusted"
version = "0.9.0"
@@ -9796,7 +9881,7 @@ dependencies = [
"base64 0.22.1",
"log",
"percent-encoding",
- "rustls 0.23.29",
+ "rustls 0.23.31",
"rustls-pemfile 2.2.0",
"rustls-pki-types",
"ureq-proto",
@@ -9875,13 +9960,13 @@ dependencies = [
[[package]]
name = "uuid"
-version = "1.17.0"
+version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
+checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
dependencies = [
"getrandom 0.3.3",
"js-sys",
- "rand 0.9.1",
+ "rand 0.9.2",
"serde",
"wasm-bindgen",
]
@@ -9925,12 +10010,12 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7df16e474ef958526d1205f6dda359fdfab79d9aa6d54bafcb92dcd07673dca"
dependencies = [
- "darling",
+ "darling 0.20.11",
"once_cell",
"proc-macro-error2",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -10067,7 +10152,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"wasm-bindgen-shared",
]
@@ -10102,7 +10187,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -10131,13 +10216,13 @@ dependencies = [
[[package]]
name = "wayland-backend"
-version = "0.3.10"
+version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121"
+checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35"
dependencies = [
"cc",
"downcast-rs",
- "rustix 0.38.44",
+ "rustix 1.0.8",
"scoped-tls",
"smallvec",
"wayland-sys",
@@ -10145,23 +10230,23 @@ dependencies = [
[[package]]
name = "wayland-client"
-version = "0.31.10"
+version = "0.31.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61"
+checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d"
dependencies = [
- "bitflags 2.9.1",
- "rustix 0.38.44",
+ "bitflags 2.9.2",
+ "rustix 1.0.8",
"wayland-backend",
"wayland-scanner",
]
[[package]]
name = "wayland-protocols"
-version = "0.32.8"
+version = "0.32.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "779075454e1e9a521794fed15886323ea0feda3f8b0fc1390f5398141310422a"
+checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
"wayland-backend",
"wayland-client",
"wayland-scanner",
@@ -10169,9 +10254,9 @@ dependencies = [
[[package]]
name = "wayland-scanner"
-version = "0.31.6"
+version = "0.31.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484"
+checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3"
dependencies = [
"proc-macro2",
"quick-xml 0.37.5",
@@ -10180,9 +10265,9 @@ dependencies = [
[[package]]
name = "wayland-sys"
-version = "0.31.6"
+version = "0.31.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615"
+checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142"
dependencies = [
"dlib",
"log",
@@ -10268,14 +10353,14 @@ version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
dependencies = [
- "webpki-roots 1.0.1",
+ "webpki-roots 1.0.2",
]
[[package]]
name = "webpki-roots"
-version = "1.0.1"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502"
+checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2"
dependencies = [
"rustls-pki-types",
]
@@ -10302,7 +10387,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -10311,7 +10396,7 @@ version = "0.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c"
dependencies = [
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"windows",
"windows-core",
]
@@ -10346,11 +10431,11 @@ dependencies = [
[[package]]
name = "whoami"
-version = "1.6.0"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7"
+checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d"
dependencies = [
- "redox_syscall",
+ "libredox",
"wasite",
"web-sys",
]
@@ -10398,7 +10483,7 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c"
dependencies = [
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-foundation 0.3.1",
@@ -10461,7 +10546,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -10472,7 +10557,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -10562,7 +10647,7 @@ version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
- "windows-targets 0.53.2",
+ "windows-targets 0.53.3",
]
[[package]]
@@ -10613,10 +10698,11 @@ dependencies = [
[[package]]
name = "windows-targets"
-version = "0.53.2"
+version = "0.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
+checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
dependencies = [
+ "windows-link",
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
@@ -10875,7 +10961,7 @@ version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.2",
]
[[package]]
@@ -10897,7 +10983,7 @@ checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
[[package]]
name = "wry"
version = "0.52.1"
-source = "git+https://github.com/modrinth/wry?rev=21db186#21db1866d53e7be8b513c7272887c6993e7f09b3"
+source = "git+https://github.com/modrinth/wry?rev=f2ce0b0#f2ce0b0105d9d94f482c4f8ecffb4f3c3c325b40"
dependencies = [
"base64 0.22.1",
"block2 0.6.1",
@@ -10914,7 +11000,7 @@ dependencies = [
"kuchikiki",
"libc",
"ndk",
- "objc2 0.6.1",
+ "objc2 0.6.2",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-foundation 0.3.1",
@@ -10926,7 +11012,7 @@ dependencies = [
"sha2",
"soup3",
"tao-macros",
- "thiserror 2.0.12",
+ "thiserror 2.0.14",
"url",
"webkit2gtk",
"webkit2gtk-sys",
@@ -11006,7 +11092,7 @@ dependencies = [
"quote",
"serde",
"serde_tokenstream",
- "syn 2.0.104",
+ "syn 2.0.106",
"xml-rs",
]
@@ -11041,15 +11127,15 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"synstructure",
]
[[package]]
name = "zbus"
-version = "5.8.0"
+version = "5.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597f45e98bc7e6f0988276012797855613cd8269e23b5be62cc4e5d28b7e515d"
+checksum = "4bb4f9a464286d42851d18a605f7193b8febaf5b0919d71c6399b7b26e5b0aad"
dependencies = [
"async-broadcast",
"async-executor",
@@ -11061,9 +11147,9 @@ dependencies = [
"async-trait",
"blocking",
"enumflags2",
- "event-listener 5.4.0",
+ "event-listener 5.4.1",
"futures-core",
- "futures-lite 2.6.0",
+ "futures-lite 2.6.1",
"hex",
"nix",
"ordered-stream",
@@ -11081,14 +11167,14 @@ dependencies = [
[[package]]
name = "zbus_macros"
-version = "5.8.0"
+version = "5.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5c8e4e14dcdd9d97a98b189cd1220f30e8394ad271e8c987da84f73693862c2"
+checksum = "ef9859f68ee0c4ee2e8cde84737c78e3f4c54f946f2a38645d0d4c7a95327659"
dependencies = [
"proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"zbus_names",
"zvariant",
"zvariant_utils",
@@ -11123,7 +11209,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -11143,7 +11229,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"synstructure",
]
@@ -11166,9 +11252,9 @@ dependencies = [
[[package]]
name = "zerovec"
-version = "0.11.2"
+version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
+checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
dependencies = [
"yoke",
"zerofrom",
@@ -11183,7 +11269,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
]
[[package]]
@@ -11266,9 +11352,9 @@ dependencies = [
[[package]]
name = "zune-jpeg"
-version = "0.4.19"
+version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c9e525af0a6a658e031e95f14b7f889976b74a11ba0eca5a5fc9ac8a1c43a6a"
+checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089"
dependencies = [
"zune-core",
]
@@ -11297,7 +11383,7 @@ dependencies = [
"proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
- "syn 2.0.104",
+ "syn 2.0.106",
"zvariant_utils",
]
@@ -11311,7 +11397,7 @@ dependencies = [
"quote",
"serde",
"static_assertions",
- "syn 2.0.104",
+ "syn 2.0.106",
"winnow 0.7.12",
]
diff --git a/Cargo.toml b/Cargo.toml
index 341c8838..5c73777c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,13 +1,13 @@
[workspace]
resolver = "2"
members = [
- "apps/app",
- "apps/app-playground",
- "apps/daedalus_client",
- "apps/labrinth",
- "packages/app-lib",
- "packages/ariadne",
- "packages/daedalus",
+ "apps/app",
+ "apps/app-playground",
+ "apps/daedalus_client",
+ "apps/labrinth",
+ "packages/app-lib",
+ "packages/ariadne",
+ "packages/daedalus",
]
[workspace.package]
@@ -25,31 +25,29 @@ actix-ws = "0.3.0"
argon2 = { version = "0.5.3", features = ["std"] }
ariadne = { path = "packages/ariadne" }
async_zip = "0.0.17"
-async-compression = { version = "0.4.25", default-features = false }
+async-compression = { version = "0.4.27", default-features = false }
async-recursion = "1.1.1"
async-stripe = { version = "0.41.0", default-features = false, features = [
- "runtime-tokio-hyper-rustls",
+ "runtime-tokio-hyper-rustls",
] }
async-trait = "0.1.88"
-async-tungstenite = { version = "0.29.1", default-features = false, features = [
- "futures-03-sink",
-] }
+async-tungstenite = { version = "0.30.0", default-features = false, features = ["futures-03-sink"] }
async-walkdir = "2.1.0"
base64 = "0.22.1"
bitflags = "2.9.1"
-bytemuck = "1.23.0"
+bytemuck = "1.23.1"
bytes = "1.10.1"
censor = "0.3.0"
chardetng = "0.1.17"
chrono = "0.4.41"
-clap = "4.5.40"
+clap = "4.5.43"
clickhouse = "0.13.3"
color-thief = "0.2.2"
console-subscriber = "0.4.1"
daedalus = { path = "packages/daedalus" }
dashmap = "6.1.0"
data-url = "0.3.1"
-deadpool-redis = "0.21.1"
+deadpool-redis = "0.22.0"
dirs = "6.0.0"
discord-rich-presence = "0.2.5"
dotenv-build = "0.1.1"
@@ -57,7 +55,7 @@ dotenvy = "0.15.7"
dunce = "1.0.5"
either = "1.15.0"
encoding_rs = "0.8.35"
-enumset = "1.1.6"
+enumset = "1.1.7"
flate2 = "1.1.2"
fs4 = { version = "0.13.1", default-features = false }
futures = { version = "0.3.31", default-features = false }
@@ -69,104 +67,102 @@ hickory-resolver = "0.25.2"
hmac = "0.12.1"
hyper = "1.6.0"
hyper-rustls = { version = "0.27.7", default-features = false, features = [
- "http1",
- "native-tokio",
- "ring",
- "tls12",
+ "http1",
+ "native-tokio",
+ "ring",
+ "tls12",
] }
-hyper-util = "0.1.14"
+hyper-util = "0.1.16"
iana-time-zone = "0.1.63"
image = { version = "0.25.6", default-features = false, features = ["rayon"] }
-indexmap = "2.9.0"
-indicatif = "0.17.11"
+indexmap = "2.10.0"
+indicatif = "0.18.0"
itertools = "0.14.0"
-jemalloc_pprof = "0.7.0"
+jemalloc_pprof = "0.8.1"
json-patch = { version = "4.0.0", default-features = false }
-lettre = { version = "0.11.17", default-features = false, features = [
- "builder",
- "hostname",
- "pool",
- "ring",
- "rustls",
- "rustls-native-certs",
- "smtp-transport",
+lettre = { version = "0.11.18", default-features = false, features = [
+ "builder",
+ "hostname",
+ "pool",
+ "ring",
+ "rustls",
+ "rustls-native-certs",
+ "smtp-transport",
] }
maxminddb = "0.26.0"
-meilisearch-sdk = { version = "0.28.0", default-features = false }
+meilisearch-sdk = { version = "0.29.1", default-features = false }
murmur2 = "0.1.0"
native-dialog = "0.9.0"
-notify = { version = "8.0.0", default-features = false }
-notify-debouncer-mini = { version = "0.6.0", default-features = false }
+notify = { version = "8.2.0", default-features = false }
+notify-debouncer-mini = { version = "0.7.0", default-features = false }
p256 = "0.13.2"
paste = "1.0.15"
+phf = { version = "0.12.1", features = ["macros"] }
png = "0.17.16"
prometheus = "0.14.0"
quartz_nbt = "0.2.9"
-quick-xml = "0.37.5"
-rand = "=0.8.5" # Locked on 0.8 until argon2 and p256 update to 0.9
-rand_chacha = "=0.3.1" # Locked on 0.3 until we can update rand to 0.9
-redis = "=0.31.0" # Locked on 0.31 until deadpool-redis updates to 0.32
+quick-xml = "0.38.1"
+rand = "=0.8.5" # Locked on 0.8 until argon2 and p256 update to 0.9
+rand_chacha = "=0.3.1" # Locked on 0.3 until we can update rand to 0.9
+redis = "0.32.4"
regex = "1.11.1"
-reqwest = { version = "0.12.20", default-features = false }
-rgb = "0.8.50"
-rust_decimal = { version = "1.37.2", features = [
- "serde-with-float",
- "serde-with-str",
-] }
+reqwest = { version = "0.12.22", default-features = false }
+rgb = "0.8.52"
+rust_decimal = { version = "1.37.2", features = ["serde-with-float", "serde-with-str"] }
rust_iso3166 = "0.1.14"
rust-s3 = { version = "0.35.1", default-features = false, features = [
- "fail-on-err",
- "tags",
- "tokio-rustls-tls",
+ "fail-on-err",
+ "tags",
+ "tokio-rustls-tls",
] }
rusty-money = "0.4.1"
-sentry = { version = "0.41.0", default-features = false, features = [
- "backtrace",
- "contexts",
- "debug-images",
- "panic",
- "reqwest",
- "rustls",
+sentry = { version = "0.42.0", default-features = false, features = [
+ "backtrace",
+ "contexts",
+ "debug-images",
+ "panic",
+ "reqwest",
+ "rustls",
] }
-sentry-actix = "0.41.0"
+sentry-actix = "0.42.0"
serde = "1.0.219"
serde_bytes = "0.11.17"
serde_cbor = "0.11.2"
serde_ini = "0.2.0"
-serde_json = "1.0.140"
-serde_with = "3.13.0"
-serde-xml-rs = "0.8.1" # Also an XML (de)serializer, consider dropping yaserde in favor of this
+serde_json = "1.0.142"
+serde_with = "3.14.0"
+serde-xml-rs = "0.8.1" # Also an XML (de)serializer, consider dropping yaserde in favor of this
sha1 = "0.10.6"
sha1_smol = { version = "1.0.1", features = ["std"] }
sha2 = "0.10.9"
-spdx = "0.10.8"
+spdx = "0.10.9"
sqlx = { version = "0.8.6", default-features = false }
-sysinfo = { version = "0.35.2", default-features = false }
+sysinfo = { version = "0.36.1", default-features = false }
tar = "0.4.44"
-tauri = "2.6.1"
-tauri-build = "2.3.0"
-tauri-plugin-deep-link = "2.4.0"
-tauri-plugin-dialog = "2.3.0"
-tauri-plugin-http = "2.5.0"
+tauri = "2.7.0"
+tauri-build = "2.3.1"
+tauri-plugin-deep-link = "2.4.1"
+tauri-plugin-dialog = "2.3.2"
+tauri-plugin-http = "2.5.1"
tauri-plugin-opener = "2.4.0"
tauri-plugin-os = "2.3.0"
-tauri-plugin-single-instance = "2.3.0"
+tauri-plugin-single-instance = "2.3.2"
tauri-plugin-updater = { version = "2.9.0", default-features = false, features = [
- "rustls-tls",
- "zip",
+ "rustls-tls",
+ "zip",
] }
-tauri-plugin-window-state = "2.3.0"
+tauri-plugin-window-state = "2.4.0"
tempfile = "3.20.0"
theseus = { path = "packages/app-lib" }
thiserror = "2.0.12"
tikv-jemalloc-ctl = "0.6.0"
tikv-jemallocator = "0.6.0"
-tokio = "1.45.1"
+tokio = "1.47.1"
tokio-stream = "0.1.17"
-tokio-util = "0.7.15"
+tokio-util = "0.7.16"
totp-rs = "5.7.0"
tracing = "0.1.41"
-tracing-actix-web = "0.7.18"
+tracing-actix-web = "0.7.19"
tracing-error = "0.2.1"
tracing-subscriber = "0.3.19"
url = "2.5.4"
@@ -178,11 +174,11 @@ whoami = "1.6.0"
winreg = "0.55.0"
woothee = "0.13.0"
yaserde = "0.12.0"
-zip = { version = "4.2.0", default-features = false, features = [
- "bzip2",
- "deflate",
- "deflate64",
- "zstd",
+zip = { version = "4.3.0", default-features = false, features = [
+ "bzip2",
+ "deflate",
+ "deflate64",
+ "zstd",
] }
zxcvbn = "3.1.0"
@@ -225,15 +221,15 @@ wildcard_dependencies = "warn"
warnings = "deny"
[patch.crates-io]
-wry = { git = "https://github.com/modrinth/wry", rev = "21db186" }
+wry = { git = "https://github.com/modrinth/wry", rev = "f2ce0b0" }
# Optimize for speed and reduce size on release builds
[profile.release]
-opt-level = "s" # Optimize for binary size
-strip = true # Remove debug symbols
-lto = true # Enables link to optimizations
-panic = "abort" # Strip expensive panic clean-up logic
-codegen-units = 1 # Compile crates one after another so the compiler can optimize better
+opt-level = "s" # Optimize for binary size
+strip = true # Remove debug symbols
+lto = true # Enables link to optimizations
+panic = "abort" # Strip expensive panic clean-up logic
+codegen-units = 1 # Compile crates one after another so the compiler can optimize better
[profile.dev.package.sqlx-macros]
opt-level = 3
diff --git a/apps/app-frontend/.prettierignore b/apps/app-frontend/.prettierignore
index 0cb3e84e..7ea3c138 100644
--- a/apps/app-frontend/.prettierignore
+++ b/apps/app-frontend/.prettierignore
@@ -1,2 +1,4 @@
**/dist
*.gltf
+src/locales/
+src/assets/**/*.svg
diff --git a/apps/app-frontend/eslint.config.mjs b/apps/app-frontend/eslint.config.mjs
index 05f55942..3d6da7fb 100644
--- a/apps/app-frontend/eslint.config.mjs
+++ b/apps/app-frontend/eslint.config.mjs
@@ -1,22 +1,2 @@
-import { createConfigForNuxt } from '@nuxt/eslint-config/flat'
-import { fixupPluginRules } from '@eslint/compat'
-import turboPlugin from 'eslint-plugin-turbo'
-
-export default createConfigForNuxt().append([
- {
- name: 'turbo',
- plugins: {
- turbo: fixupPluginRules(turboPlugin),
- },
- rules: {
- 'turbo/no-undeclared-env-vars': 'error',
- },
- },
- {
- name: 'modrinth',
- rules: {
- 'vue/html-self-closing': 'off',
- 'vue/multi-word-component-names': 'off',
- },
- },
-])
+import config from '@modrinth/tooling-config/eslint/nuxt.mjs'
+export default config
diff --git a/apps/app-frontend/index.html b/apps/app-frontend/index.html
index d577b736..876739c3 100644
--- a/apps/app-frontend/index.html
+++ b/apps/app-frontend/index.html
@@ -1,16 +1,17 @@
-
-
-
-
- AstralRinth App
+
+
+
+
+ AstralRinth App
-
-
+
+
-
-
-
-
+
+
+
+
+
diff --git a/apps/app-frontend/package.json b/apps/app-frontend/package.json
index b58e6355..4cc577cd 100644
--- a/apps/app-frontend/package.json
+++ b/apps/app-frontend/package.json
@@ -1,64 +1,63 @@
{
- "name": "@modrinth/app-frontend",
- "private": true,
- "version": "1.0.0-local",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "vue-tsc --noEmit && vite build",
- "tsc:check": "vue-tsc --noEmit",
- "lint": "eslint . && prettier --check .",
- "fix": "eslint . --fix && prettier --write .",
- "intl:extract": "formatjs extract \"{,src/components,src/composables,src/helpers,src/pages,src/store}/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" --ignore '**/*.d.ts' --ignore 'node_modules' --out-file src/locales/en-US/index.json --format crowdin --preserve-whitespace",
- "test": "vue-tsc --noEmit"
- },
- "dependencies": {
- "@geometrically/minecraft-motd-parser": "^1.1.4",
- "@modrinth/assets": "workspace:*",
- "@modrinth/ui": "workspace:*",
- "@modrinth/utils": "workspace:*",
- "@sentry/vue": "^8.27.0",
- "@tauri-apps/api": "^2.5.0",
- "@tauri-apps/plugin-dialog": "^2.2.1",
- "@tauri-apps/plugin-http": "^2.5.0",
- "@tauri-apps/plugin-opener": "^2.2.6",
- "@tauri-apps/plugin-os": "^2.2.1",
- "@tauri-apps/plugin-updater": "^2.7.1",
- "@tauri-apps/plugin-window-state": "^2.2.2",
- "@types/three": "^0.172.0",
- "@vintl/vintl": "^4.4.1",
- "@vueuse/core": "^11.1.0",
- "dayjs": "^1.11.10",
- "floating-vue": "^5.2.2",
- "ofetch": "^1.3.4",
- "pinia": "^2.1.7",
- "posthog-js": "^1.158.2",
- "three": "^0.172.0",
- "vite-svg-loader": "^5.1.0",
- "vue": "^3.5.13",
- "vue-multiselect": "3.0.0",
- "vue-router": "4.3.0",
- "vue-virtual-scroller": "v2.0.0-beta.8"
- },
- "devDependencies": {
- "@eslint/compat": "^1.1.1",
- "@formatjs/cli": "^6.2.12",
- "@nuxt/eslint-config": "^0.5.6",
- "@taijased/vue-render-tracker": "^1.0.7",
- "@vitejs/plugin-vue": "^5.0.4",
- "autoprefixer": "^10.4.19",
- "eslint": "^9.9.1",
- "eslint-config-custom": "workspace:*",
- "eslint-plugin-turbo": "^2.5.4",
- "postcss": "^8.4.39",
- "prettier": "^3.2.5",
- "sass": "^1.74.1",
- "tailwindcss": "^3.4.4",
- "tsconfig": "workspace:*",
- "typescript": "^5.5.4",
- "vite": "^5.4.6",
- "vue-tsc": "^2.1.6"
- },
- "packageManager": "pnpm@9.4.0",
- "web-types": "../../web-types.json"
+ "name": "@modrinth/app-frontend",
+ "private": true,
+ "version": "1.0.0-local",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vue-tsc --noEmit && vite build",
+ "tsc:check": "vue-tsc --noEmit",
+ "lint": "eslint . && prettier --check .",
+ "fix": "eslint . --fix && prettier --write .",
+ "intl:extract": "formatjs extract \"src/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" --ignore \"**/*.d.ts\" --ignore node_modules --out-file src/locales/en-US/index.json --format crowdin --preserve-whitespace",
+ "test": "vue-tsc --noEmit"
+ },
+ "dependencies": {
+ "@geometrically/minecraft-motd-parser": "^1.1.4",
+ "@modrinth/assets": "workspace:*",
+ "@modrinth/ui": "workspace:*",
+ "@modrinth/utils": "workspace:*",
+ "@sentry/vue": "^8.27.0",
+ "@tauri-apps/api": "^2.5.0",
+ "@tauri-apps/plugin-dialog": "^2.2.1",
+ "@tauri-apps/plugin-http": "^2.5.0",
+ "@tauri-apps/plugin-opener": "^2.2.6",
+ "@tauri-apps/plugin-os": "^2.2.1",
+ "@tauri-apps/plugin-updater": "^2.7.1",
+ "@tauri-apps/plugin-window-state": "^2.2.2",
+ "@types/three": "^0.172.0",
+ "@vintl/vintl": "^4.4.1",
+ "@vueuse/core": "^11.1.0",
+ "dayjs": "^1.11.10",
+ "floating-vue": "^5.2.2",
+ "ofetch": "^1.3.4",
+ "pinia": "^2.1.7",
+ "posthog-js": "^1.158.2",
+ "three": "^0.172.0",
+ "vite-svg-loader": "^5.1.0",
+ "vue": "^3.5.13",
+ "vue-multiselect": "3.0.0",
+ "vue-router": "4.3.0",
+ "vue-virtual-scroller": "v2.0.0-beta.8"
+ },
+ "devDependencies": {
+ "@modrinth/tooling-config": "workspace:*",
+ "@eslint/compat": "^1.1.1",
+ "@formatjs/cli": "^6.2.12",
+ "@nuxt/eslint-config": "^0.5.6",
+ "@taijased/vue-render-tracker": "^1.0.7",
+ "@vitejs/plugin-vue": "^5.0.4",
+ "autoprefixer": "^10.4.19",
+ "eslint": "^9.9.1",
+ "eslint-plugin-turbo": "^2.5.4",
+ "postcss": "^8.4.39",
+ "prettier": "^3.2.5",
+ "sass": "^1.74.1",
+ "tailwindcss": "^3.4.4",
+ "typescript": "^5.5.4",
+ "vite": "^5.4.6",
+ "vue-tsc": "^2.1.6"
+ },
+ "packageManager": "pnpm@9.4.0",
+ "web-types": "../../web-types.json"
}
diff --git a/apps/app-frontend/postcss.config.js b/apps/app-frontend/postcss.config.js
index 2e7af2b7..1a526247 100644
--- a/apps/app-frontend/postcss.config.js
+++ b/apps/app-frontend/postcss.config.js
@@ -1,6 +1,6 @@
export default {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
}
diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue
index e554210f..ffadb314 100644
--- a/apps/app-frontend/src/App.vue
+++ b/apps/app-frontend/src/App.vue
@@ -1,33 +1,33 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Sign out
-
-
-
-
- Sign in
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- getCurrentWindow().minimize()">
-
-
- getCurrentWindow().toggleMaximize()"
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ route.fullPath }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sign out
+
+
+
+
+ Sign in
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getCurrentWindow().minimize()">
+
+
+ getCurrentWindow().toggleMaximize()"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Would you mind answering a few questions about your experience with Modrinth App?
+
+
+ This feedback will go directly to the Modrinth team and help guide future updates!
+
+
+
+ Take survey
+
+
+ No thanks
+
+
+
+
+
+
+
+
+ {{ route.fullPath }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/assets/external/index.js b/apps/app-frontend/src/assets/external/index.js
index c20eb57c..479cf4fd 100644
--- a/apps/app-frontend/src/assets/external/index.js
+++ b/apps/app-frontend/src/assets/external/index.js
@@ -1,18 +1,18 @@
+export { default as ATLauncherIcon } from './atlauncher.svg'
export { default as BuyMeACoffeeIcon } from './bmac.svg'
export { default as DiscordIcon } from './discord.svg'
+export { default as GDLauncherIcon } from './gdlauncher.png'
+export { default as GithubIcon } from './github.svg'
+export { default as GitLabIcon } from './gitlab.svg'
+export { default as GoogleIcon } from './google.svg'
export { default as KoFiIcon } from './kofi.svg'
+export { default as MastodonIcon } from './mastodon.svg'
+export { default as MicrosoftIcon } from './microsoft.svg'
+export { default as MultiMCIcon } from './multimc.webp'
+export { default as OpenCollectiveIcon } from './opencollective.svg'
export { default as PatreonIcon } from './patreon.svg'
export { default as PaypalIcon } from './paypal.svg'
-export { default as OpenCollectiveIcon } from './opencollective.svg'
-export { default as TwitterIcon } from './twitter.svg'
-export { default as GithubIcon } from './github.svg'
-export { default as MastodonIcon } from './mastodon.svg'
-export { default as RedditIcon } from './reddit.svg'
-export { default as GoogleIcon } from './google.svg'
-export { default as MicrosoftIcon } from './microsoft.svg'
-export { default as SteamIcon } from './steam.svg'
-export { default as GitLabIcon } from './gitlab.svg'
-export { default as ATLauncherIcon } from './atlauncher.svg'
-export { default as GDLauncherIcon } from './gdlauncher.png'
-export { default as MultiMCIcon } from './multimc.webp'
export { default as PrismIcon } from './prism.svg'
+export { default as RedditIcon } from './reddit.svg'
+export { default as SteamIcon } from './steam.svg'
+export { default as TwitterIcon } from './twitter.svg'
diff --git a/apps/app-frontend/src/assets/icons/index.js b/apps/app-frontend/src/assets/icons/index.js
index 72f3b005..8694e3be 100644
--- a/apps/app-frontend/src/assets/icons/index.js
+++ b/apps/app-frontend/src/assets/icons/index.js
@@ -1,12 +1,12 @@
-export { default as SwapIcon } from './arrow-left-right.svg'
-export { default as ToggleIcon } from './toggle.svg'
-export { default as PackageIcon } from './package.svg'
-export { default as VersionIcon } from './milestone.svg'
-export { default as TextInputIcon } from './text-cursor-input.svg'
export { default as AddProjectImage } from './add-project.svg'
-export { default as NewInstanceImage } from './new-instance.svg'
+export { default as SwapIcon } from './arrow-left-right.svg'
export { default as MenuIcon } from './menu.svg'
export { default as ChatIcon } from './messages-square.svg'
export { default as Pirate } from './pirate.svg'
export { default as Microsoft } from './microsoft.svg'
export { default as PirateShip } from './pirate-ship.svg'
+export { default as VersionIcon } from './milestone.svg'
+export { default as NewInstanceImage } from './new-instance.svg'
+export { default as PackageIcon } from './package.svg'
+export { default as TextInputIcon } from './text-cursor-input.svg'
+export { default as ToggleIcon } from './toggle.svg'
diff --git a/apps/app-frontend/src/assets/stylesheets/global.scss b/apps/app-frontend/src/assets/stylesheets/global.scss
index 7ab08fd5..2969d3cb 100644
--- a/apps/app-frontend/src/assets/stylesheets/global.scss
+++ b/apps/app-frontend/src/assets/stylesheets/global.scss
@@ -3,158 +3,158 @@
@tailwind utilities;
@font-face {
- font-family: 'bundled-minecraft-font-mrapp';
- font-style: normal;
- font-display: swap;
- font-weight: 400;
- src: url('https://cdn-raw.modrinth.com/fonts/minecraft/regular.otf') format('opentype');
+ font-family: 'bundled-minecraft-font-mrapp';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 400;
+ src: url('https://cdn-raw.modrinth.com/fonts/minecraft/regular.otf') format('opentype');
}
@font-face {
- font-family: 'bundled-minecraft-font-mrapp';
- font-style: italic;
- font-display: swap;
- font-weight: 400;
- src: url('https://cdn-raw.modrinth.com/fonts/minecraft/italic.otf') format('opentype');
+ font-family: 'bundled-minecraft-font-mrapp';
+ font-style: italic;
+ font-display: swap;
+ font-weight: 400;
+ src: url('https://cdn-raw.modrinth.com/fonts/minecraft/italic.otf') format('opentype');
}
@font-face {
- font-family: 'bundled-minecraft-font-mrapp';
- font-style: normal;
- font-display: swap;
- font-weight: 600;
- src: url('https://cdn-raw.modrinth.com/fonts/minecraft/bold.otf') format('opentype');
+ font-family: 'bundled-minecraft-font-mrapp';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 600;
+ src: url('https://cdn-raw.modrinth.com/fonts/minecraft/bold.otf') format('opentype');
}
@font-face {
- font-family: 'bundled-minecraft-font-mrapp';
- font-style: italic;
- font-display: swap;
- font-weight: 600;
- src: url('https://cdn-raw.modrinth.com/fonts/minecraft/bold-italic.otf') format('opentype');
+ font-family: 'bundled-minecraft-font-mrapp';
+ font-style: italic;
+ font-display: swap;
+ font-weight: 600;
+ src: url('https://cdn-raw.modrinth.com/fonts/minecraft/bold-italic.otf') format('opentype');
}
.font-minecraft {
- font-family: 'bundled-minecraft-font-mrapp', monospace;
+ font-family: 'bundled-minecraft-font-mrapp', monospace;
}
:root {
- font-family: var(--font-standard, sans-serif), sans-serif;
- color-scheme: dark;
- --view-width: calc(100% - 5rem);
- --expanded-view-width: calc(100% - 13rem);
+ font-family: var(--font-standard, sans-serif), sans-serif;
+ color-scheme: dark;
+ --view-width: calc(100% - 5rem);
+ --expanded-view-width: calc(100% - 13rem);
}
body {
- position: fixed;
- width: 100%;
- height: 100%;
- overflow: hidden;
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
}
* {
- box-sizing: border-box;
+ box-sizing: border-box;
}
.card-divider {
- background-color: var(--color-button-bg);
- border: none;
- color: var(--color-button-bg);
- height: 1px;
- margin: var(--gap-sm) 0;
+ background-color: var(--color-button-bg);
+ border: none;
+ color: var(--color-button-bg);
+ height: 1px;
+ margin: var(--gap-sm) 0;
}
.no-wrap {
- white-space: nowrap;
+ white-space: nowrap;
}
.no-select {
- -webkit-user-select: none;
- -ms-user-select: none;
- user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
}
a {
- color: var(--color-link);
- text-decoration: none;
+ color: var(--color-link);
+ text-decoration: none;
- &:hover {
- text-decoration: none;
- }
+ &:hover {
+ text-decoration: none;
+ }
}
input {
- border: none !important;
+ border: none !important;
}
.badge {
- display: flex;
- border-radius: var(--radius-md);
- white-space: nowrap;
- align-items: center;
- background-color: var(--color-bg);
- padding-block: var(--gap-sm);
- padding-inline: var(--gap-lg);
- width: min-content;
+ display: flex;
+ border-radius: var(--radius-md);
+ white-space: nowrap;
+ align-items: center;
+ background-color: var(--color-bg);
+ padding-block: var(--gap-sm);
+ padding-inline: var(--gap-lg);
+ width: min-content;
- svg {
- width: 1.1rem;
- height: 1.1rem;
- margin-right: 0.5rem;
- }
+ svg {
+ width: 1.1rem;
+ height: 1.1rem;
+ margin-right: 0.5rem;
+ }
- &.featured {
- background-color: var(--color-brand-highlight);
- color: var(--color-contrast);
- }
+ &.featured {
+ background-color: var(--color-brand-highlight);
+ color: var(--color-contrast);
+ }
}
* {
- scrollbar-width: auto;
- scrollbar-color: var(--color-scrollbar) var(--color-bg);
+ scrollbar-width: auto;
+ scrollbar-color: var(--color-scrollbar) var(--color-bg);
}
/* Chrome, Edge, and Safari */
*::-webkit-scrollbar {
- width: 16px;
- border: 3px solid transparent;
- opacity: 0.5;
- transition: opacity 0.2s ease-in-out;
+ width: 16px;
+ border: 3px solid transparent;
+ opacity: 0.5;
+ transition: opacity 0.2s ease-in-out;
}
*::-webkit-scrollbar:hover {
- opacity: 1;
+ opacity: 1;
}
*::-webkit-scrollbar-track {
- background: transparent;
+ background: transparent;
}
*::-webkit-scrollbar-thumb {
- background-color: var(--color-scrollbar);
- border-radius: var(--radius-lg);
- border: 5px solid transparent;
- background-clip: content-box;
+ background-color: var(--color-scrollbar);
+ border-radius: var(--radius-lg);
+ border: 5px solid transparent;
+ background-clip: content-box;
}
.highlighted {
- box-shadow: 0 0 1rem var(--color-brand) !important;
+ box-shadow: 0 0 1rem var(--color-brand) !important;
}
.gecko {
- background-color: var(--color-raised-bg);
- box-shadow: none !important;
+ background-color: var(--color-raised-bg);
+ box-shadow: none !important;
}
img {
- user-select: none;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
+ user-select: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
}
.card-shadow {
- box-shadow: var(--shadow-card);
+ box-shadow: var(--shadow-card);
}
@import '@modrinth/assets/omorphia.scss';
diff --git a/apps/app-frontend/src/assets/stylesheets/macFix.css b/apps/app-frontend/src/assets/stylesheets/macFix.css
index b56737a9..901ce864 100644
--- a/apps/app-frontend/src/assets/stylesheets/macFix.css
+++ b/apps/app-frontend/src/assets/stylesheets/macFix.css
@@ -1,3 +1,3 @@
img {
- pointer-events: none !important;
+ pointer-events: none !important;
}
diff --git a/apps/app-frontend/src/components/GridDisplay.vue b/apps/app-frontend/src/components/GridDisplay.vue
index 2ced2956..046244f6 100644
--- a/apps/app-frontend/src/components/GridDisplay.vue
+++ b/apps/app-frontend/src/components/GridDisplay.vue
@@ -1,36 +1,38 @@
-
-
-
-
- (search = '')">
-
-
-
-
- Sort by:
- {{ selected }}
-
-
- Group by:
- {{ selected }}
-
-
-
-
-
{{ instanceSection.key }}
-
-
-
- handleRightClick(event, instance.path)"
- />
-
-
-
-
- Play
- Stop
- Add content
- View instance
- Duplicate instance
- Delete
- Open folder
- Copy path
-
+
+
+
+
+ (search = '')">
+
+
+
+
+ Sort by:
+ {{ selected }}
+
+
+ Group by:
+ {{ selected }}
+
+
+
+
+
{{ instanceSection.key }}
+
+
+
+ handleRightClick(event, instance.path)"
+ />
+
+
+
+
+ Play
+ Stop
+ Add content
+ View instance
+ Duplicate instance
+ Delete
+ Open folder
+ Copy path
+
diff --git a/apps/app-frontend/src/components/LoadingIndicatorBar.vue b/apps/app-frontend/src/components/LoadingIndicatorBar.vue
index 3c1dd088..7cbee496 100644
--- a/apps/app-frontend/src/components/LoadingIndicatorBar.vue
+++ b/apps/app-frontend/src/components/LoadingIndicatorBar.vue
@@ -1,29 +1,30 @@
-
-
-
+
+
+
diff --git a/apps/app-frontend/src/components/RowDisplay.vue b/apps/app-frontend/src/components/RowDisplay.vue
index d4054648..363f0744 100644
--- a/apps/app-frontend/src/components/RowDisplay.vue
+++ b/apps/app-frontend/src/components/RowDisplay.vue
@@ -1,52 +1,54 @@
-
-
-
-
- {{ row.label }}
-
-
- handleInstanceRightClick(event, instance)"
- />
-
-
- handleProjectClick(event, project)"
- />
-
-
-
-
- Play
- Stop
- Add content
- View instance
- Delete
- Open folder
- Duplicate instance
- Copy path
- Install
- Open in Modrinth
- Copy link
-
+
+
+
+
+ {{ row.label }}
+
+
+ handleInstanceRightClick(event, instance)"
+ />
+
+
+ handleProjectClick(event, project)"
+ />
+
+
+
+
+ Play
+ Stop
+ Add content
+ View instance
+ Delete
+ Open folder
+ Duplicate instance
+ Copy path
+ Install
+ Open in Modrinth
+ Copy link
+
diff --git a/apps/app-frontend/src/components/ui/AccountsCard.vue b/apps/app-frontend/src/components/ui/AccountsCard.vue
index e41b4f4d..50ca61bb 100644
--- a/apps/app-frontend/src/components/ui/AccountsCard.vue
+++ b/apps/app-frontend/src/components/ui/AccountsCard.vue
@@ -1,212 +1,212 @@
-
-
-
-
-
-
-
- {{ selectedAccount.profile.name }}
-
-
Selected
-
-
-
-
-
-
-
Not signed in
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ account.profile.name }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Enter your 2FA code
-
-
-
- Continue
-
-
-
-
-
-
Enter your player name or email (preferred)
-
-
Enter your password
-
-
-
- Login
-
-
-
-
-
-
-
Enter your player name
-
-
-
- Login
-
-
-
-
-
-
-
- An error occurred while logging in.
-
+
+
+
+
+
+
+
+ {{
+ selectedAccount.profile.name }}
+
+
Selected
+
+
+
+
+
+
+
Not signed in
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ account.profile.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Enter your 2FA code
+
+
+
+ Continue
+
+
+
+
+
+
Enter your player name or email (preferred)
+
+
Enter your password
+
+
+
+ Login
+
+
+
+
+
+
+
Enter your player name
+
+
+
+ Login
+
+
+
+
+
+
+
+ An error occurred while logging in.
+
-
-
- Try again
-
-
-
-
-
-
-
- An error occurred while adding the Ely.by account. Please follow the instructions below.
-
+
+
+ Try again
+
+
+
+
+
+
+
+ An error occurred while adding the Ely.by account. Please follow the instructions below.
+
-
- Check that you have entered the correct player name or email.
- Check that you have entered the correct password.
-
+
+ Check that you have entered the correct player name or email.
+ Check that you have entered the correct password.
+
-
-
- Try again
-
-
-
-
-
-
-
- An error occurred while adding the offline account. Please follow the instructions below.
-
+
+
+ Try again
+
+
+
+
+
+
+
+ An error occurred while adding the offline account. Please follow the instructions below.
+
-
- Check that you have entered the correct player name.
-
- Player name must be at least {{ minOfflinePlayerNameLength }} characters long and no more than
- {{ maxOfflinePlayerNameLength }} characters.
-
-
+
+ Check that you have entered the correct player name.
+
+ Player name must be at least {{ minOfflinePlayerNameLength }} characters long and no more than
+ {{ maxOfflinePlayerNameLength }} characters.
+
+
-
-
- Try again
-
-
-
-
-
-
- An unexpected error has occurred. Please try again later.
-
-
+
+
+ Try again
+
+
+
+
+
+
+ An unexpected error has occurred. Please try again later.
+
+
diff --git a/apps/app-frontend/src/components/ui/AddContentButton.vue b/apps/app-frontend/src/components/ui/AddContentButton.vue
index 414634c9..193b6e80 100644
--- a/apps/app-frontend/src/components/ui/AddContentButton.vue
+++ b/apps/app-frontend/src/components/ui/AddContentButton.vue
@@ -1,60 +1,62 @@
-
+
diff --git a/apps/app-frontend/src/components/ui/Breadcrumbs.vue b/apps/app-frontend/src/components/ui/Breadcrumbs.vue
index d87c502f..ee12e17e 100644
--- a/apps/app-frontend/src/components/ui/Breadcrumbs.vue
+++ b/apps/app-frontend/src/components/ui/Breadcrumbs.vue
@@ -1,63 +1,64 @@
-
-
-
-
-
-
-
- {{ breadcrumbData.resetToNames(breadcrumbs) }}
-
- {{
- breadcrumb.name.charAt(0) === '?'
- ? breadcrumbData.getName(breadcrumb.name.slice(1))
- : breadcrumb.name
- }}
-
- {{
- breadcrumb.name.charAt(0) === '?'
- ? breadcrumbData.getName(breadcrumb.name.slice(1))
- : breadcrumb.name
- }}
-
-
-
+
+
+
+
+
+
+
+ {{ breadcrumbData.resetToNames(breadcrumbs) }}
+
+ {{
+ breadcrumb.name.charAt(0) === '?'
+ ? breadcrumbData.getName(breadcrumb.name.slice(1))
+ : breadcrumb.name
+ }}
+
+ {{
+ breadcrumb.name.charAt(0) === '?'
+ ? breadcrumbData.getName(breadcrumb.name.slice(1))
+ : breadcrumb.name
+ }}
+
+
+
diff --git a/apps/app-frontend/src/components/ui/ContextMenu.vue b/apps/app-frontend/src/components/ui/ContextMenu.vue
index b3370fa0..bddcbfb8 100644
--- a/apps/app-frontend/src/components/ui/ContextMenu.vue
+++ b/apps/app-frontend/src/components/ui/ContextMenu.vue
@@ -1,18 +1,26 @@
-
-
-
+
+
+
diff --git a/apps/app-frontend/src/components/ui/CurseForgeProfileImportModal.vue b/apps/app-frontend/src/components/ui/CurseForgeProfileImportModal.vue
index 008d2d04..c608c547 100644
--- a/apps/app-frontend/src/components/ui/CurseForgeProfileImportModal.vue
+++ b/apps/app-frontend/src/components/ui/CurseForgeProfileImportModal.vue
@@ -1,75 +1,55 @@
-
-
-
-
-
-
Profile Information
-
Name: {{ metadata.name }}
-
-
-
-
-
-
- {{ importProgress.message }}
- {{ Math.floor(importProgress.percentage) }}%
-
-
-
-
-
-
-
- Cancel
-
-
-
- {{ fetching ? 'Checking...' : 'Check Profile' }}
-
-
-
- {{ importing ? 'Importing...' : 'Import Profile' }}
-
-
-
-
+
+
+
+
+
+
Profile Information
+
Name: {{ metadata.name }}
+
+
+
+
+
+
+ {{ importProgress.message }}
+ {{ Math.floor(importProgress.percentage) }}%
+
+
+
+
+
+
+
+ Cancel
+
+
+
+ {{ fetching ? 'Checking...' : 'Check Profile' }}
+
+
+
+ {{ importing ? 'Importing...' : 'Import Profile' }}
+
+
+
+
@@ -487,44 +480,44 @@ async function onApplyMigrationFix(eol) {
@import '../../../../../packages/assets/styles/neon-text.scss';
.cta-button {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 0.5rem;
- gap: 0.5rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0.5rem;
+ gap: 0.5rem;
}
.warning-banner {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
- padding: var(--gap-lg);
- background-color: var(--color-orange-bg);
- border: 2px solid var(--color-orange);
- border-radius: var(--radius-md);
- margin-bottom: 1rem;
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ padding: var(--gap-lg);
+ background-color: var(--color-orange-bg);
+ border: 2px solid var(--color-orange);
+ border-radius: var(--radius-md);
+ margin-bottom: 1rem;
}
.warning-banner__title {
- display: flex;
- align-items: center;
- gap: 0.5rem;
- font-weight: 700;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ font-weight: 700;
- svg {
- color: var(--color-orange);
- height: 1.5rem;
- width: 1.5rem;
- }
+ svg {
+ color: var(--color-orange);
+ height: 1.5rem;
+ width: 1.5rem;
+ }
}
.modal-body {
- display: flex;
- flex-direction: column;
- gap: var(--gap-md);
+ display: flex;
+ flex-direction: column;
+ gap: var(--gap-md);
}
.markdown-body {
- overflow: auto;
+ overflow: auto;
}
diff --git a/apps/app-frontend/src/components/ui/ExportModal.vue b/apps/app-frontend/src/components/ui/ExportModal.vue
index 0b96afb1..d29633af 100644
--- a/apps/app-frontend/src/components/ui/ExportModal.vue
+++ b/apps/app-frontend/src/components/ui/ExportModal.vue
@@ -1,25 +1,27 @@
-
-
-
-
-
-
+
+
+
+ Select files and folders to include in pack
+
(showingFiles = !showingFiles)"
+ >
+
+
+
+
+
+
+
+
+
+ children.forEach((child) => (child.selected = newValue))
+ "
+ />
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/Instance.vue b/apps/app-frontend/src/components/ui/Instance.vue
index 3f9176f6..73940147 100644
--- a/apps/app-frontend/src/components/ui/Instance.vue
+++ b/apps/app-frontend/src/components/ui/Instance.vue
@@ -1,51 +1,52 @@
-
-
-
-
- {{ instance.name }}
-
-
-
- stop(e, 'InstanceCard')">
-
-
-
-
-
-
-
-
-
- play(e, 'InstanceCard')"
- @mousehover="checkProcess"
- >
-
-
-
-
-
-
-
-
-
- Played {{ formatRelativeTime(dayjs(instance.last_played).toISOString()) }}
-
- Never played
-
-
-
-
-
+
+
+
+
+ {{ instance.name }}
+
+
+
+ stop(e, 'InstanceCard')">
+
+
+
+
+
+
+
+
+
+ play(e, 'InstanceCard')"
+ @mousehover="checkProcess"
+ >
+
+
+
+
+
+
+
+
+
+ Played {{ formatRelativeTime(dayjs(instance.last_played).toISOString()) }}
+
+ Never played
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/InstanceCreationModal.vue b/apps/app-frontend/src/components/ui/InstanceCreationModal.vue
index c086afaf..b8451e86 100644
--- a/apps/app-frontend/src/components/ui/InstanceCreationModal.vue
+++ b/apps/app-frontend/src/components/ui/InstanceCreationModal.vue
@@ -1,241 +1,244 @@
-
-
-
-
-
-
-
-
-
- Select icon
-
-
-
- Remove icon
-
-
-
-
-
-
-
-
-
-
-
-
Import from file
-
Or drag and drop your .mrpack file
-
-
-
-
-
{{ selectedProfileType.name }} path
-
-
-
-
-
-
- profiles
- .get(selectedProfileType.name)
- ?.forEach((child) => (child.selected = newValue))
- "
- />
-
-
Profile name
-
-
-
-
-
-
-
- {{ profile.name }}
-
-
-
-
No profiles found
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ Select icon
+
+
+
+ Remove icon
+
+
+
+
+
+
+
+
+
+
+
+
Import from file
+
Or drag and drop your .mrpack file
+
+
+
+
+
{{ selectedProfileType.name }} path
+
+
+
+
+
+
+ profiles
+ .get(selectedProfileType.name)
+ ?.forEach((child) => (child.selected = newValue))
+ "
+ />
+
+
Profile name
+
+
+
+
+
+
+
+ {{ profile.name }}
+
+
+
+
No profiles found
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/InstanceIndicator.vue b/apps/app-frontend/src/components/ui/InstanceIndicator.vue
index 61adcfa2..a00263bd 100644
--- a/apps/app-frontend/src/components/ui/InstanceIndicator.vue
+++ b/apps/app-frontend/src/components/ui/InstanceIndicator.vue
@@ -1,53 +1,53 @@
-
-
-
-
-
-
-
-
- {{ formatCategory(instance.loader) }} {{ instance.game_version }}
-
-
-
-
-
-
- Back to instance
-
-
-
+
+
+
+
+
+
+
+
+ {{ formatCategory(instance.loader) }} {{ instance.game_version }}
+
+
+
+
+
+
+ Back to instance
+
+
+
diff --git a/apps/app-frontend/src/components/ui/JavaDetectionModal.vue b/apps/app-frontend/src/components/ui/JavaDetectionModal.vue
index bbb2a86c..472d000f 100644
--- a/apps/app-frontend/src/components/ui/JavaDetectionModal.vue
+++ b/apps/app-frontend/src/components/ui/JavaDetectionModal.vue
@@ -1,95 +1,97 @@
-
-
-
-
-
Version
-
Path
-
Actions
-
-
-
- {{ javaInstall.version }}
-
-
- {{ javaInstall.path }}
-
-
-
-
-
No java installations found!
-
-
-
-
-
- Cancel
-
-
-
-
+
+
+
+
+
Version
+
Path
+
Actions
+
+
+
+ {{ javaInstall.version }}
+
+
+ {{ javaInstall.path }}
+
+
+
+
+
No java installations found!
+
+
+
+
+
+ Cancel
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/JavaSelector.vue b/apps/app-frontend/src/components/ui/JavaSelector.vue
index ebbeed89..17361f22 100644
--- a/apps/app-frontend/src/components/ui/JavaSelector.vue
+++ b/apps/app-frontend/src/components/ui/JavaSelector.vue
@@ -1,100 +1,102 @@
- emit('update:modelValue', val)" />
-
-
{
- emit('update:modelValue', {
- ...props.modelValue,
- path: val.target.value,
- })
- }
- "
- />
-
-
-
- {{ installingJava ? 'Installing...' : 'Install recommended' }}
-
-
-
- Detect
-
-
-
- Browse
-
- Testing...
-
-
- Success
-
-
-
- Failed
-
-
-
- Test
-
-
-
+ emit('update:modelValue', val)" />
+
+
{
+ emit('update:modelValue', {
+ ...props.modelValue,
+ path: val.target.value,
+ })
+ }
+ "
+ />
+
+
+
+ {{ installingJava ? 'Installing...' : 'Install recommended' }}
+
+
+
+ Detect
+
+
+
+ Browse
+
+ Testing...
+
+
+ Success
+
+
+
+ Failed
+
+
+
+ Test
+
+
+
diff --git a/apps/app-frontend/src/components/ui/ModpackVersionModal.vue b/apps/app-frontend/src/components/ui/ModpackVersionModal.vue
index a8141a4a..f804be58 100644
--- a/apps/app-frontend/src/components/ui/ModpackVersionModal.vue
+++ b/apps/app-frontend/src/components/ui/ModpackVersionModal.vue
@@ -1,33 +1,34 @@
-
-
-
+
+
+
diff --git a/apps/app-frontend/src/components/ui/NavButton.vue b/apps/app-frontend/src/components/ui/NavButton.vue
index b723f2d7..70731a40 100644
--- a/apps/app-frontend/src/components/ui/NavButton.vue
+++ b/apps/app-frontend/src/components/ui/NavButton.vue
@@ -1,24 +1,24 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/NavTabs.vue b/apps/app-frontend/src/components/ui/NavTabs.vue
index 72e77253..0203950d 100644
--- a/apps/app-frontend/src/components/ui/NavTabs.vue
+++ b/apps/app-frontend/src/components/ui/NavTabs.vue
@@ -1,50 +1,50 @@
-
-
-
- {{ link.label }}
-
-
-
+
+
+
+ {{ link.label }}
+
+
+
diff --git a/apps/app-frontend/src/components/ui/ProgressBar.vue b/apps/app-frontend/src/components/ui/ProgressBar.vue
index 1d254748..2be23807 100644
--- a/apps/app-frontend/src/components/ui/ProgressBar.vue
+++ b/apps/app-frontend/src/components/ui/ProgressBar.vue
@@ -1,33 +1,33 @@
-
+
diff --git a/apps/app-frontend/src/components/ui/ProjectCard.vue b/apps/app-frontend/src/components/ui/ProjectCard.vue
index e78f3fb2..2d23f3ae 100644
--- a/apps/app-frontend/src/components/ui/ProjectCard.vue
+++ b/apps/app-frontend/src/components/ui/ProjectCard.vue
@@ -1,10 +1,10 @@
-
-
-
-
-
-
- {{ project.title }}
-
-
-
- {{ project.description }}
-
-
-
-
- {{ formatNumber(project.downloads) }}
-
-
-
- {{ formatNumber(project.follows) }}
-
-
-
-
- {{ formatCategory(featuredCategory) }}
-
-
-
-
-
+
+
+
+
+
+
+ {{ project.title }}
+
+
+
+ {{ project.description }}
+
+
+
+
+ {{ formatNumber(project.downloads) }}
+
+
+
+ {{ formatNumber(project.follows) }}
+
+
+
+
+ {{ formatCategory(featuredCategory) }}
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue b/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue
index 77099feb..64e5bd26 100644
--- a/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue
+++ b/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue
@@ -1,73 +1,75 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/RunningAppBar.vue b/apps/app-frontend/src/components/ui/RunningAppBar.vue
index f3a766b1..573be649 100644
--- a/apps/app-frontend/src/components/ui/RunningAppBar.vue
+++ b/apps/app-frontend/src/components/ui/RunningAppBar.vue
@@ -1,89 +1,119 @@
-
-
-
-
-
-
-
-
-
-
-
- {{ selectedProcess.profile.name }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- No instances running
-
-
-
-
-
-
- {{ loadingBar.title }}
-
-
-
- {{ Math.floor((100 * loadingBar.current) / loadingBar.total) }}% {{ loadingBar.message }}
-
-
-
-
-
-
-
- {{ process.profile.name }}
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ {{ selectedProcess.profile.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No instances running
+
+
+
+
+
+
+ {{ loadingBar.title }}
+
+
+
+ {{ Math.floor((100 * loadingBar.current) / loadingBar.total) }}%
+ {{ loadingBar.message }}
+
+
+
+
+
+
+
+ {{ process.profile.name }}
+
+
+
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/SearchCard.vue b/apps/app-frontend/src/components/ui/SearchCard.vue
index 80edc736..7f7b6c44 100644
--- a/apps/app-frontend/src/components/ui/SearchCard.vue
+++ b/apps/app-frontend/src/components/ui/SearchCard.vue
@@ -1,159 +1,162 @@
- {
- emit('open')
- $router.push({
- path: `/project/${project.project_id ?? project.id}`,
- query: { i: props.instance ? props.instance.path : undefined },
- })
- }
- "
- >
-
-
-
-
- by {{ project.author }}
-
-
- {{ project.description }}
-
-
-
-
-
- Client or server
-
-
- Client
-
-
- Server
-
-
- Unsupported
-
-
- Client and server
-
-
-
- {{ formatCategory(tag.name) }}
-
-
-
-
-
-
-
- {{ formatNumber(project.downloads) }}
- downloads
-
-
-
-
-
- {{ formatNumber(project.follows ?? project.followers) }}
- followers
-
-
-
-
-
-
-
-
-
-
-
- {{
- installing
- ? 'Installing'
- : installed
- ? 'Installed'
- : modpack || instance
- ? 'Install'
- : 'Add to an instance'
- }}
-
-
-
-
-
-
+ {
+ emit('open')
+ $router.push({
+ path: `/project/${project.project_id ?? project.id}`,
+ query: { i: props.instance ? props.instance.path : undefined },
+ })
+ }
+ "
+ >
+
+
+
+
+ by {{ project.author }}
+
+
+ {{ project.description }}
+
+
+
+
+
+ Client or server
+
+
+ Client
+
+
+ Server
+
+
+ Unsupported
+
+
+ Client and server
+
+
+
+ {{ formatCategory(tag.name) }}
+
+
+
+
+
+
+
+ {{ formatNumber(project.downloads) }}
+ downloads
+
+
+
+
+
+ {{ formatNumber(project.follows ?? project.followers) }}
+ followers
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ installing
+ ? 'Installing'
+ : installed
+ ? 'Installed'
+ : modpack || instance
+ ? 'Install'
+ : 'Add to an instance'
+ }}
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/URLConfirmModal.vue b/apps/app-frontend/src/components/ui/URLConfirmModal.vue
index 91014edc..a2595061 100644
--- a/apps/app-frontend/src/components/ui/URLConfirmModal.vue
+++ b/apps/app-frontend/src/components/ui/URLConfirmModal.vue
@@ -1,12 +1,14 @@
-
-
-
+
+
+
diff --git a/apps/app-frontend/src/components/ui/friends/FriendsList.vue b/apps/app-frontend/src/components/ui/friends/FriendsList.vue
index 095e4d1e..a23f911c 100644
--- a/apps/app-frontend/src/components/ui/friends/FriendsList.vue
+++ b/apps/app-frontend/src/components/ui/friends/FriendsList.vue
@@ -1,28 +1,35 @@
-
- Add friends to share what you're playing!
-
-
-
-
-
{{ friend.username }}
-
-
-
-
- Remove
-
-
-
-
-
-
-
- You have no pending friend requests :C
-
-
-
-
-
-
-
- {{ friend.username }} sent you a friend request
-
-
- You sent {{ friend.username }} a friend request
-
-
-
- {{ formatRelativeTime(friend.created.toISOString()) }}
-
-
-
-
-
-
-
- Accept
-
-
-
-
-
- Ignore
-
-
-
-
-
-
-
- Cancel
-
-
-
-
-
-
-
-
-
-
-
-
You can add friends with their Modrinth username.
-
-
-
-
-
- Add friend
-
-
-
-
-
Friends
-
-
-
-
-
- Add friend
-
-
-
- Manage friends
-
- {{ acceptedFriends.length }}
-
-
-
-
- View friend requests
-
- {{ pendingFriends.length }}
-
-
-
-
-
-
-
-
-
-
-
-
- Sign in to add friends!
-
-
- Add friends
- to share what you're playing!
-
-
-
-
-
- Remove friend
-
-
- friendOptions.showMenu(event, friend, [
- {
- name: 'remove-friend',
- color: 'danger',
- },
- ])
- "
- >
-
-
-
- {{ friend.username }}
-
- {{ friend.status }}
-
-
-
-
+
+ Add friends to share what you're playing!
+
+
+
+
+
{{ friend.username }}
+
+
+
+
+ Remove
+
+
+
+
+
+
+
+ You have no pending friend requests :C
+
+
+
+
+
+
+
+ {{ friend.username }} sent you a friend request
+
+
+ You sent {{ friend.username }} a friend request
+
+
+
+ {{ formatRelativeTime(friend.created.toISOString()) }}
+
+
+
+
+
+
+
+ Accept
+
+
+
+
+
+ Ignore
+
+
+
+
+
+
+
+ Cancel
+
+
+
+
+
+
+
+
+
+
+
+
You can add friends with their Modrinth username.
+
+
+
+
+
+ Add friend
+
+
+
+
+
Friends
+
+
+
+
+
+ Add friend
+
+
+
+ Manage friends
+
+ {{ acceptedFriends.length }}
+
+
+
+
+ View friend requests
+
+ {{ pendingFriends.length }}
+
+
+
+
+
+
+
+
+
+
+
+
+ Sign in to add friends!
+
+
+ Add friends
+ to share what you're playing!
+
+
+
+
+
+ Remove friend
+
+
+ friendOptions.showMenu(event, friend, [
+ {
+ name: 'remove-friend',
+ color: 'danger',
+ },
+ ])
+ "
+ >
+
+
+
+ {{ friend.username }}
+
+ {{ friend.status }}
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/install_flow/IncompatibilityWarningModal.vue b/apps/app-frontend/src/components/ui/install_flow/IncompatibilityWarningModal.vue
index 31029e1e..c77f4469 100644
--- a/apps/app-frontend/src/components/ui/install_flow/IncompatibilityWarningModal.vue
+++ b/apps/app-frontend/src/components/ui/install_flow/IncompatibilityWarningModal.vue
@@ -1,71 +1,73 @@
-
-
-
- This {{ versions?.length > 0 ? 'project' : 'version' }} is not compatible with the instance
- you're trying to install it on. Are you sure you want to continue? Dependencies will not be
- installed.
-
-
-
-
-
-
-
- {{ instance?.loader }} {{ instance?.game_version }}
-
-
-
-
- {{ selectedVersion?.name }} ({{
- selectedVersion?.loaders.map((name) => formatCategory(name)).join(', ')
- }}
- - {{ selectedVersion?.game_versions.join(', ') }})
-
-
-
-
-
-
-
- incompatibleModal.hide()"> Cancel
-
- {{ installing ? 'Installing' : 'Install' }}
-
-
-
-
+
+
+
+ This {{ versions?.length > 0 ? 'project' : 'version' }} is not compatible with the instance
+ you're trying to install it on. Are you sure you want to continue? Dependencies will not be
+ installed.
+
+
+
+
+
+
+
+ {{ instance?.loader }} {{ instance?.game_version }}
+
+
+
+
+ {{ selectedVersion?.name }} ({{
+ selectedVersion?.loaders.map((name) => formatCategory(name)).join(', ')
+ }}
+ - {{ selectedVersion?.game_versions.join(', ') }})
+
+
+
+
+
+
+
+ incompatibleModal.hide()"> Cancel
+
+ {{ installing ? 'Installing' : 'Install' }}
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/install_flow/InstallConfirmModal.vue b/apps/app-frontend/src/components/ui/install_flow/InstallConfirmModal.vue
index 6803c350..fe2749f7 100644
--- a/apps/app-frontend/src/components/ui/install_flow/InstallConfirmModal.vue
+++ b/apps/app-frontend/src/components/ui/install_flow/InstallConfirmModal.vue
@@ -1,11 +1,13 @@
-
-
-
You already have this modpack installed. Are you sure you want to install it again?
-
- $refs.confirmModal.hide()"> Cancel
- {{ installing ? 'Installing' : 'Install' }}
-
-
-
+
+
+
You already have this modpack installed. Are you sure you want to install it again?
+
+ $refs.confirmModal.hide()"> Cancel
+ {{ installing ? 'Installing' : 'Install' }}
+
+
+
diff --git a/apps/app-frontend/src/components/ui/install_flow/ModInstallModal.vue b/apps/app-frontend/src/components/ui/install_flow/ModInstallModal.vue
index f89df8bc..ccf6586e 100644
--- a/apps/app-frontend/src/components/ui/install_flow/ModInstallModal.vue
+++ b/apps/app-frontend/src/components/ui/install_flow/ModInstallModal.vue
@@ -1,29 +1,30 @@
-
-
-
-
-
-
-
- {{ profile.name }}
-
-
-
-
-
- {{
- profile.installing
- ? 'Installing...'
- : profile.installedMod
- ? 'Installed'
- : 'Install'
- }}
-
-
-
-
-
-
-
-
-
-
-
- Select icon
-
-
-
- Remove icon
-
-
-
-
-
-
-
- {{ creatingInstance ? 'Creating...' : 'Create' }}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {{ profile.name }}
+
+
+
+
+
+ {{
+ profile.installing
+ ? 'Installing...'
+ : profile.installedMod
+ ? 'Installed'
+ : 'Install'
+ }}
+
+
+
+
+
+
+
+
+
+
+
+ Select icon
+
+
+
+ Remove icon
+
+
+
+
+
+
+
+ {{ creatingInstance ? 'Creating...' : 'Create' }}
+
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/instance_settings/GeneralSettings.vue b/apps/app-frontend/src/components/ui/instance_settings/GeneralSettings.vue
index 6d035dce..b98d00cf 100644
--- a/apps/app-frontend/src/components/ui/instance_settings/GeneralSettings.vue
+++ b/apps/app-frontend/src/components/ui/instance_settings/GeneralSettings.vue
@@ -1,17 +1,25 @@
-
-
-
-
-
-
-
-
- {{ icon ? formatMessage(messages.replaceIcon) : formatMessage(messages.selectIcon) }}
-
- {{ formatMessage(messages.removeIcon) }}
-
-
-
-
-
-
-
-
-
-
- {{ formatMessage(messages.duplicateInstanceDescription) }}
-
-
-
-
- {{ formatMessage(messages.duplicateButton) }}
-
-
-
-
-
- {{ formatMessage(messages.libraryGroupsDescription) }}
-
-
-
-
-
addCategory"
- />
-
- addCategory()">
- {{ formatMessage(messages.libraryGroupsCreate) }}
-
-
-
-
-
-
- {{ formatMessage(messages.deleteInstanceDescription) }}
-
-
-
-
-
- {{
- removing
- ? formatMessage(messages.deletingInstanceButton)
- : formatMessage(messages.deleteInstanceButton)
- }}
-
-
-
+
+
+
+
+
+
+
+
+ {{ icon ? formatMessage(messages.replaceIcon) : formatMessage(messages.selectIcon) }}
+
+ {{ formatMessage(messages.removeIcon) }}
+
+
+
+
+
+
+
+
+
+
+ {{ formatMessage(messages.duplicateInstanceDescription) }}
+
+
+
+
+ {{ formatMessage(messages.duplicateButton) }}
+
+
+
+
+
+ {{ formatMessage(messages.libraryGroupsDescription) }}
+
+
+
+
+
addCategory"
+ />
+
+ addCategory()">
+ {{ formatMessage(messages.libraryGroupsCreate) }}
+
+
+
+
+
+
+ {{ formatMessage(messages.deleteInstanceDescription) }}
+
+
+
+
+
+ {{
+ removing
+ ? formatMessage(messages.deletingInstanceButton)
+ : formatMessage(messages.deleteInstanceButton)
+ }}
+
+
+
diff --git a/apps/app-frontend/src/components/ui/instance_settings/HooksSettings.vue b/apps/app-frontend/src/components/ui/instance_settings/HooksSettings.vue
index c7de8bec..9f1d589b 100644
--- a/apps/app-frontend/src/components/ui/instance_settings/HooksSettings.vue
+++ b/apps/app-frontend/src/components/ui/instance_settings/HooksSettings.vue
@@ -1,12 +1,14 @@
-
-
-
- {{ formatMessage(messages.hooksDescription) }}
-
-
+
+
+
+ {{ formatMessage(messages.hooksDescription) }}
+
+
-
-
- {{ formatMessage(messages.preLaunchDescription) }}
-
-
+
+
+ {{ formatMessage(messages.preLaunchDescription) }}
+
+
-
-
- {{ formatMessage(messages.wrapperDescription) }}
-
-
+
+
+ {{ formatMessage(messages.wrapperDescription) }}
+
+
-
-
- {{ formatMessage(messages.postExitDescription) }}
-
-
-
+
+
+ {{ formatMessage(messages.postExitDescription) }}
+
+
+
diff --git a/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue b/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue
index ff16faad..ec6806fc 100644
--- a/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue
+++ b/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue
@@ -1,39 +1,47 @@
-
-
-
-
-
- AuthLib installation completed successfully! Now you can log in and play!
-
-
- Failed to install AuthLib. It's possible that no compatible AuthLib version was found for the selected game and/or mod loader version.
- There may also be a problem with accessing resources behind CloudFlare.
-
-
-
-
-
- repairProfile(true)"
- />
- {
- changingVersion = false
- modpackVersion =
- modpackVersions?.find(
- (version: Version) => version.id === props.instance.linked_data?.version_id,
- ) ?? null
- }
- "
- />
- unpairProfile()"
- />
- repairModpack()"
- />
-
-
-
- {{ formatMessage(messages.noConnection) }}
-
-
-
- {{ formatMessage(messages.noModpackFound) }}
-
-
{{ formatMessage(messages.debugInformation) }}
-
- {{ instance.linked_data }}
-
-
-
-
-
- {{ formatMessage(messages.fetchingModpackDetails) }}
-
-
-
-
-
-
-
- {{
- modpackProject
- ? modpackProject.title
- : formatMessage(messages.minecraftVersion, { version: instance.game_version })
- }}
-
-
- {{
- modpackProject
- ? modpackVersion
- ? modpackVersion?.version_number
- : 'Unknown version'
- : formatCategory(instance.loader)
- }}
-
- {{ instance.loader_version || formatMessage(messages.unknownVersion) }}
-
-
-
-
-
-
-
-
-
- {{
- repairing
- ? formatMessage(messages.repairingButton)
- : formatMessage(messages.repairButton)
- }}
-
-
-
- {
- changingVersion = true
- modpackVersionModal.show()
- }
- "
- >
-
-
- {{
- changingVersion
- ? formatMessage(messages.installingButton)
- : formatMessage(messages.changeVersionButton)
- }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- (loaderVersionIndex = value.index)"
- />
-
-
- {{ formatMessage(messages.noLoaderVersions, { loader: loader, version: gameVersion }) }}
-
-
-
-
-
-
-
- {{
- editing
- ? formatMessage(messages.installingButton)
- : formatMessage(messages.installButton)
- }}
-
-
-
- {
- loader = instance.loader
- gameVersion = instance.game_version
- resetLoaderVersionIndex()
- }
- "
- >
-
- {{ formatMessage(messages.resetSelections) }}
-
-
-
-
-
-
-
- Install Microsoft
-
-
-
-
- Install Ely.By
-
-
-
-
-
-
-
-
- {{ formatMessage(messages.unlinkInstanceDescription) }}
-
-
-
- {{ formatMessage(messages.unlinkInstanceButton) }}
-
-
-
-
-
-
- {{ formatMessage(messages.reinstallModpackDescription) }}
-
-
-
-
-
-
- {{
- reinstalling
- ? formatMessage(messages.reinstallingModpackButton)
- : formatMessage(messages.reinstallModpackButton)
- }}
-
-
-
-
-
-
+
+
+
+
+
+ AuthLib installation completed successfully! Now you can log in and play!
+
+
+ Failed to install AuthLib. It's possible that no compatible AuthLib version was found for the selected game and/or mod loader version.
+ There may also be a problem with accessing resources behind CloudFlare.
+
+
+
+
+
+ repairProfile(true)"
+ />
+ {
+ changingVersion = false
+ modpackVersion =
+ modpackVersions?.find(
+ (version: Version) => version.id === props.instance.linked_data?.version_id,
+ ) ?? null
+ }
+ "
+ />
+ unpairProfile()"
+ />
+ repairModpack()"
+ />
+
+
+
+ {{ formatMessage(messages.noConnection) }}
+
+
+
+
+ {{ formatMessage(messages.noModpackFound) }}
+
+
{{ formatMessage(messages.debugInformation) }}
+
+ {{ instance.linked_data }}
+
+
+
+
+
+ {{ formatMessage(messages.fetchingModpackDetails) }}
+
+
+
+
+
+
+
+ {{
+ modpackProject
+ ? modpackProject.title
+ : formatMessage(messages.minecraftVersion, {
+ version: instance.game_version,
+ })
+ }}
+
+
+ {{
+ modpackProject
+ ? modpackVersion
+ ? modpackVersion?.version_number
+ : 'Unknown version'
+ : formatCategory(instance.loader)
+ }}
+
+ {{ instance.loader_version || formatMessage(messages.unknownVersion) }}
+
+
+
+
+
+
+
+
+
+ {{
+ repairing
+ ? formatMessage(messages.repairingButton)
+ : formatMessage(messages.repairButton)
+ }}
+
+
+
+ {
+ changingVersion = true
+ modpackVersionModal.show()
+ }
+ "
+ >
+
+
+ {{
+ changingVersion
+ ? formatMessage(messages.installingButton)
+ : formatMessage(messages.changeVersionButton)
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (loaderVersionIndex = value.index)"
+ />
+
+
+ {{
+ formatMessage(messages.noLoaderVersions, {
+ loader: loader,
+ version: gameVersion,
+ })
+ }}
+
+
+
+
+
+
+
+ {{
+ editing
+ ? formatMessage(messages.installingButton)
+ : formatMessage(messages.installButton)
+ }}
+
+
+
+ {
+ loader = instance.loader
+ gameVersion = instance.game_version
+ resetLoaderVersionIndex()
+ }
+ "
+ >
+
+ {{ formatMessage(messages.resetSelections) }}
+
+
+
+
+
+
+
+ Install Microsoft
+
+
+
+
+ Install Ely.By
+
+
+
+
+
+
+
+
+ {{ formatMessage(messages.unlinkInstanceDescription) }}
+
+
+
+ {{ formatMessage(messages.unlinkInstanceButton) }}
+
+
+
+
+
+
+ {{ formatMessage(messages.reinstallModpackDescription) }}
+
+
+
+
+
+
+ {{
+ reinstalling
+ ? formatMessage(messages.reinstallingModpackButton)
+ : formatMessage(messages.reinstallModpackButton)
+ }}
+
+
+
+
+
+
\ No newline at end of file
+
diff --git a/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue b/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue
index cd1b58d3..fbc110f8 100644
--- a/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue
+++ b/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue
@@ -1,20 +1,22 @@
-
-
-
-
-
-
-
- Using default Java {{ optimalJava.major_version }} installation:
-
-
-
- Could not find a default Java {{ optimalJava.major_version }} installation. Please set
- one below:
-
-
-
- Could not automatically determine a Java installation to use. Please set one
- below:
-
-
-
- {{ javaInstall.path }}
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ Using default Java {{ optimalJava.major_version }} installation:
+
+
+
+ Could not find a default Java {{ optimalJava.major_version }} installation. Please set
+ one below:
+
+
+
+ Could not automatically determine a Java installation to use. Please set one
+ below:
+
+
+
+ {{ javaInstall.path }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/instance_settings/WindowSettings.vue b/apps/app-frontend/src/components/ui/instance_settings/WindowSettings.vue
index 3f2f8827..c0b93796 100644
--- a/apps/app-frontend/src/components/ui/instance_settings/WindowSettings.vue
+++ b/apps/app-frontend/src/components/ui/instance_settings/WindowSettings.vue
@@ -1,12 +1,14 @@
-
-
{
- if (!value) {
- resolution = globalSettings.game_resolution
- fullscreenSetting = globalSettings.force_fullscreen
- }
- }
- "
- />
-
-
-
-
- {{ formatMessage(messages.fullscreenDescription) }}
-
-
-
{
- fullscreenSetting = e
- }
- "
- />
-
+
+
{
+ if (!value) {
+ resolution = globalSettings.game_resolution
+ fullscreenSetting = globalSettings.force_fullscreen
+ }
+ }
+ "
+ />
+
+
+
+
+ {{ formatMessage(messages.fullscreenDescription) }}
+
+
+
{
+ fullscreenSetting = e
+ }
+ "
+ />
+
-
-
-
-
- {{ formatMessage(messages.widthDescription) }}
-
-
-
-
+
+
+
+
+ {{ formatMessage(messages.widthDescription) }}
+
+
+
+
-
-
-
-
- {{ formatMessage(messages.heightDescription) }}
-
-
-
-
-
+
+
+
+
+ {{ formatMessage(messages.heightDescription) }}
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue b/apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue
index 0ce1e6c6..0a098cb5 100644
--- a/apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue
+++ b/apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue
@@ -1,29 +1,29 @@
-
-
-
-
+
+
+
+
-
-
-
-
- {{ formatMessage(developerModeEnabled) }}
-
-
-
-
-
-
-
AstralRinth App {{ version }}
-
- MacOS
- {{ osPlatform }}
- {{ osVersion }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
The new version of the AstralRinth launcher is available.
-
Your version is outdated. We recommend that you update to the latest version.
-
⚠️ Warning ⚠️
-
- Before updating, make sure that you have saved all running instances and made a backup copy of the instances
- that are valuable to you. Remember that the authors of the product are not responsible for the breakdown of
- your files, so you should always make copies of them and keep them in a safe place.
-
-
-
-
Source: Git Astralium
-
- Version on remote server:
-
-
-
- Version on local device:
- v{{ version }}
-
-
+
+
+
+
+ {{ formatMessage(developerModeEnabled) }}
+
+
+
+
+
+
+
AstralRinth App {{ version }}
+
+ MacOS
+ {{ osPlatform }}
+ {{ osVersion }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The new version of the AstralRinth launcher is available.
+
Your version is outdated. We recommend that you update to the latest version.
+
⚠️ Warning ⚠️
+
+ Before updating, make sure that you have saved all running instances and made a backup copy of the instances
+ that are valuable to you. Remember that the authors of the product are not responsible for the breakdown of
+ your files, so you should always make copies of them and keep them in a safe place.
+
+
+
+
Source: Git Astralium
+
+ Version on remote server:
+
+
+
+ Version on local device:
+ v{{ version }}
+
+
-
- Cancel
- Download file
-
-
-
-
-
-
-
Error occurred
-
Unfortunately, the program was unable to download the file from our servers.
-
- Please try downloading it yourself from
- Git
- Astralium
- if there are any updates available.
-
-
+
+ Cancel
+ Download file
+
+
+
+
+
+
+
Error occurred
+
Unfortunately, the program was unable to download the file from our servers.
+
+ Please try downloading it yourself from
+ Git
+ Astralium
+ if there are any updates available.
+
+
-
-
- Local AstralRinth:
- v{{ version }}
-
-
+
+
+ Local AstralRinth:
+ v{{ version }}
+
+
-
- Close
-
-
-
-
+
+ Close
+
+
+
+
\ No newline at end of file
+
diff --git a/apps/app-frontend/src/components/ui/modal/AuthGrantFlowWaitModal.vue b/apps/app-frontend/src/components/ui/modal/AuthGrantFlowWaitModal.vue
index 3f169faf..03f3036f 100644
--- a/apps/app-frontend/src/components/ui/modal/AuthGrantFlowWaitModal.vue
+++ b/apps/app-frontend/src/components/ui/modal/AuthGrantFlowWaitModal.vue
@@ -1,42 +1,43 @@
-
-
-
-
+
+
+
+
-
-
-
-
- Please sign in at the browser window that just opened to continue.
-
-
+
+
+
+
+ Please sign in at the browser window that just opened to continue.
+
+
diff --git a/apps/app-frontend/src/components/ui/modal/ConfirmModalWrapper.vue b/apps/app-frontend/src/components/ui/modal/ConfirmModalWrapper.vue
index 99c8c70c..fbae0e7d 100644
--- a/apps/app-frontend/src/components/ui/modal/ConfirmModalWrapper.vue
+++ b/apps/app-frontend/src/components/ui/modal/ConfirmModalWrapper.vue
@@ -1,89 +1,91 @@
-
+
diff --git a/apps/app-frontend/src/components/ui/modal/InstanceModalTitlePrefix.vue b/apps/app-frontend/src/components/ui/modal/InstanceModalTitlePrefix.vue
index c28213ca..a1ce6f0f 100644
--- a/apps/app-frontend/src/components/ui/modal/InstanceModalTitlePrefix.vue
+++ b/apps/app-frontend/src/components/ui/modal/InstanceModalTitlePrefix.vue
@@ -2,19 +2,20 @@
import { ChevronRightIcon } from '@modrinth/assets'
import { Avatar } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
+
import type { GameInstance } from '@/helpers/types'
defineProps<{
- instance: GameInstance
+ instance: GameInstance
}>()
-
-
- {{ instance.name }}
-
+
+
+ {{ instance.name }}
+
diff --git a/apps/app-frontend/src/components/ui/modal/InstanceSettingsModal.vue b/apps/app-frontend/src/components/ui/modal/InstanceSettingsModal.vue
index 8cdb3821..102d0978 100644
--- a/apps/app-frontend/src/components/ui/modal/InstanceSettingsModal.vue
+++ b/apps/app-frontend/src/components/ui/modal/InstanceSettingsModal.vue
@@ -1,22 +1,24 @@
-
-
-
-
- {{ instance.name }}
-
-
-
+
+
+
+
+ {{ instance.name }}
+
+
+
-
-
+
+
diff --git a/apps/app-frontend/src/components/ui/modal/ModalWrapper.vue b/apps/app-frontend/src/components/ui/modal/ModalWrapper.vue
index fb0ddf3d..c26a85d5 100644
--- a/apps/app-frontend/src/components/ui/modal/ModalWrapper.vue
+++ b/apps/app-frontend/src/components/ui/modal/ModalWrapper.vue
@@ -1,57 +1,58 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/modal/ShareModalWrapper.vue b/apps/app-frontend/src/components/ui/modal/ShareModalWrapper.vue
index 65fd776e..aefea372 100644
--- a/apps/app-frontend/src/components/ui/modal/ShareModalWrapper.vue
+++ b/apps/app-frontend/src/components/ui/modal/ShareModalWrapper.vue
@@ -1,48 +1,62 @@
-
+
diff --git a/apps/app-frontend/src/components/ui/settings/AppearanceSettings.vue b/apps/app-frontend/src/components/ui/settings/AppearanceSettings.vue
index 30f8ff7e..04473bb8 100644
--- a/apps/app-frontend/src/components/ui/settings/AppearanceSettings.vue
+++ b/apps/app-frontend/src/components/ui/settings/AppearanceSettings.vue
@@ -1,9 +1,10 @@
-
- Select your preferred color theme for Modrinth App.
+
+ Select your preferred color theme for Modrinth App.
-
+
-
-
-
-
- Enables advanced rendering such as blur effects that may cause performance issues without
- hardware-accelerated rendering.
-
-
+
+
+
+
+ Enables advanced rendering such as blur effects that may cause performance issues without
+ hardware-accelerated rendering.
+
+
-
{
- themeStore.advancedRendering = e
- settings.advanced_rendering = themeStore.advancedRendering
- }
- "
- />
-
+
{
+ themeStore.advancedRendering = e
+ settings.advanced_rendering = themeStore.advancedRendering
+ }
+ "
+ />
+
-
-
-
-
Disables the nametag above your player on the skins page.
-
-
-
+
+
+
+
Disables the nametag above your player on the skins page.
+
+
+
-
-
-
-
Use system window frame (app restart required).
-
-
-
+
+
+
+
Use system window frame (app restart required).
+
+
+
-
-
-
-
Minimize the launcher when a Minecraft process starts.
-
-
-
+
+
+
+
Minimize the launcher when a Minecraft process starts.
+
+
+
-
-
-
-
Change the page to which the launcher opens on.
-
-
-
+
+
+
+
Change the page to which the launcher opens on.
+
+
+
-
-
-
-
Includes recent worlds in the "Jump back in" section on the Home page.
-
-
{
- const newValue = !themeStore.getFeatureFlag('worlds_in_home')
- themeStore.featureFlags['worlds_in_home'] = newValue
- settings.feature_flags['worlds_in_home'] = newValue
- }
- "
- />
-
+
+
+
+
Includes recent worlds in the "Jump back in" section on the Home page.
+
+
{
+ const newValue = !themeStore.getFeatureFlag('worlds_in_home')
+ themeStore.featureFlags['worlds_in_home'] = newValue
+ settings.feature_flags['worlds_in_home'] = newValue
+ }
+ "
+ />
+
-
-
-
-
Enables the ability to toggle the sidebar.
-
-
+
+
+
+
Enables the ability to toggle the sidebar.
+
+
diff --git a/apps/app-frontend/src/components/ui/settings/DefaultInstanceSettings.vue b/apps/app-frontend/src/components/ui/settings/DefaultInstanceSettings.vue
index 4b6a91bf..f9ffd696 100644
--- a/apps/app-frontend/src/components/ui/settings/DefaultInstanceSettings.vue
+++ b/apps/app-frontend/src/components/ui/settings/DefaultInstanceSettings.vue
@@ -1,8 +1,11 @@
-
-
+
+
-
-
-
-
- Overwrites the options.txt file to start in full screen when launched.
-
-
+
+
+
+
+ Overwrites the options.txt file to start in full screen when launched.
+
+
-
-
+
+
-
-
-
-
- The width of the game window when launched.
-
-
+
+
+
+
+ The width of the game window when launched.
+
+
-
-
+
+
-
-
-
-
- The height of the game window when launched.
-
-
+
+
+
+
+ The height of the game window when launched.
+
+
-
-
+
+
-
+
-
-
The memory allocated to each instance when it is ran.
-
+
+
The memory allocated to each instance when it is ran.
+
-
-
+
+
-
-
+
+
-
+
-
+
-
-
Ran before the instance is launched.
-
+
+
Ran before the instance is launched.
+
-
-
- Wrapper command for launching Minecraft.
-
-
+
+
+ Wrapper command for launching Minecraft.
+
+
-
-
Ran after the game closes.
-
-
+
+
Ran after the game closes.
+
+
diff --git a/apps/app-frontend/src/components/ui/settings/FeatureFlagSettings.vue b/apps/app-frontend/src/components/ui/settings/FeatureFlagSettings.vue
index 45034c24..679dfc48 100644
--- a/apps/app-frontend/src/components/ui/settings/FeatureFlagSettings.vue
+++ b/apps/app-frontend/src/components/ui/settings/FeatureFlagSettings.vue
@@ -1,8 +1,9 @@
-
-
-
-
+
+
+
+
-
setFeatureFlag(option, !themeStore.getFeatureFlag(option))"
- />
-
+
setFeatureFlag(option, !themeStore.getFeatureFlag(option))"
+ />
+
diff --git a/apps/app-frontend/src/components/ui/settings/JavaSettings.vue b/apps/app-frontend/src/components/ui/settings/JavaSettings.vue
index 226c809d..02169651 100644
--- a/apps/app-frontend/src/components/ui/settings/JavaSettings.vue
+++ b/apps/app-frontend/src/components/ui/settings/JavaSettings.vue
@@ -1,32 +1,35 @@
-
-
-
-
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/settings/PrivacySettings.vue b/apps/app-frontend/src/components/ui/settings/PrivacySettings.vue
index 13f5991c..c69f23e5 100644
--- a/apps/app-frontend/src/components/ui/settings/PrivacySettings.vue
+++ b/apps/app-frontend/src/components/ui/settings/PrivacySettings.vue
@@ -1,64 +1,65 @@
-
-
-
-
- (Hard disabled by AR) • Modrinth's ad provider, Aditude, shows ads based on your preferences. By disabling this
- option, you opt out and ads will no longer be shown based on your interests.
-
-
+
+
+
+
+ Modrinth's ad provider, Aditude, shows ads based on your preferences. By disabling this
+ option, you opt out and ads will no longer be shown based on your interests.
+
+
-
-
+
+
-
-
-
-
- (Hard disabled by AR) • Modrinth collects anonymized analytics and usage data to improve our user experience and
- customize your experience. By disabling this option, you opt out and your data will no
- longer be collected.
-
-
+
+
+
+
+ Modrinth collects anonymized analytics and usage data to improve our user experience and
+ customize your experience. By disabling this option, you opt out and your data will no
+ longer be collected.
+
+
-
-
+
+
-
-
-
-
- Manages the Discord Rich Presence integration. Disabling this will cause 'Modrinth' to no
- longer show up as a game or app you are using on your Discord profile.
-
-
- Note: This will not prevent any instance-specific Discord Rich Presence integrations, such
- as those added by mods. (app restart required to take effect)
-
-
-
-
+
+
+
+
+ Manages the Discord Rich Presence integration. Disabling this will cause 'Modrinth' to no
+ longer show up as a game or app you are using on your Discord profile.
+
+
+ Note: This will not prevent any instance-specific Discord Rich Presence integrations, such
+ as those added by mods. (app restart required to take effect)
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/settings/ResourceManagementSettings.vue b/apps/app-frontend/src/components/ui/settings/ResourceManagementSettings.vue
index 328e329c..f48f3f52 100644
--- a/apps/app-frontend/src/components/ui/settings/ResourceManagementSettings.vue
+++ b/apps/app-frontend/src/components/ui/settings/ResourceManagementSettings.vue
@@ -1,117 +1,118 @@
-
-
- The directory where the launcher stores all of its files. Changes will be applied after
- restarting the launcher.
-
+
+
+ The directory where the launcher stores all of its files. Changes will be applied after
+ restarting the launcher.
+
-
+
-
-
+
+
-
-
- The Modrinth app stores a cache of data to speed up loading. This can be purged to force the
- app to reload data. This may slow down the app temporarily.
-
-
-
-
- Purge cache
-
+
+
+ The Modrinth app stores a cache of data to speed up loading. This can be purged to force the
+ app to reload data. This may slow down the app temporarily.
+
+
+
+
+ Purge cache
+
-
-
- The maximum amount of files the launcher can download at the same time. Set this to a lower
- value if you have a poor internet connection. (app restart required to take effect)
-
-
+
+
+ The maximum amount of files the launcher can download at the same time. Set this to a lower
+ value if you have a poor internet connection. (app restart required to take effect)
+
+
-
-
- The maximum amount of files the launcher can write to the disk at once. Set this to a lower
- value if you are frequently getting I/O errors. (app restart required to take effect)
-
-
+
+
+ The maximum amount of files the launcher can write to the disk at once. Set this to a lower
+ value if you are frequently getting I/O errors. (app restart required to take effect)
+
+
diff --git a/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue b/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue
index 06b45fd1..1ac359d7 100644
--- a/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue
+++ b/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue
@@ -1,136 +1,139 @@
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
-
- Texture
- Replace texture
-
+
+
+ Texture
+ Replace texture
+
-
- Arm style
-
-
- {{ item === 'CLASSIC' ? 'Wide' : 'Slim' }}
-
-
-
+
+ Arm style
+
+
+ {{ item === 'CLASSIC' ? 'Wide' : 'Slim' }}
+
+
+
-
- Cape
-
-
- Use default cape
-
-
- Use default cape
-
+
+ Cape
+
+
+ Use default cape
+
+
+ Use default cape
+
-
+
-
-
- More
-
-
-
-
-
+
+
+ More
+
+
+
+
+
-
-
-
-
-
-
- {{ mode === 'new' ? 'Add skin' : 'Save skin' }}
-
-
- Cancel
-
-
+
+
+
+
+
+
+ {{ mode === 'new' ? 'Add skin' : 'Save skin' }}
+
+
+ Cancel
+
+
-
+
diff --git a/apps/app-frontend/src/components/ui/skin/SelectCapeModal.vue b/apps/app-frontend/src/components/ui/skin/SelectCapeModal.vue
index 3bb559d6..57358229 100644
--- a/apps/app-frontend/src/components/ui/skin/SelectCapeModal.vue
+++ b/apps/app-frontend/src/components/ui/skin/SelectCapeModal.vue
@@ -1,33 +1,34 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
- None
-
-
-
-
-
-
-
-
-
-
- Select
-
-
-
-
-
- Cancel
-
-
-
-
+
+
+
+
+
+
+
+ None
+
+
+
+
+
+
+
+
+
+
+ Select
+
+
+
+
+
+ Cancel
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/skin/UploadSkinModal.vue b/apps/app-frontend/src/components/ui/skin/UploadSkinModal.vue
index 818922ef..7a35e63e 100644
--- a/apps/app-frontend/src/components/ui/skin/UploadSkinModal.vue
+++ b/apps/app-frontend/src/components/ui/skin/UploadSkinModal.vue
@@ -1,40 +1,41 @@
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
- {{ instance.name }}
-
-
-
-
-
- {{
- formatMessage(commonMessages.playedLabel, {
- time: formatRelativeTime(last_played.toISOString?.()),
- })
- }}
-
- Not played yet
-
- •
-
-
-
- {{ modpack.title }}
-
- ({{ loader }} {{ instance.game_version }})
-
-
-
- Loading modpack...
-
-
- {{ loader }}
- {{ instance.game_version }}
-
-
-
-
-
-
-
- {{ formatMessage(commonMessages.stopButton) }}
-
-
-
-
-
-
- {{ formatMessage(commonMessages.playButton) }}
-
-
-
-
-
-
-
- View instance
-
-
-
- {{ formatMessage(commonMessages.openFolderButton) }}
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ {{ instance.name }}
+
+
+
+
+
+ {{
+ formatMessage(commonMessages.playedLabel, {
+ time: formatRelativeTime(last_played.toISOString?.()),
+ })
+ }}
+
+ Not played yet
+
+ •
+
+
+
+ {{ modpack.title }}
+
+ ({{ loader }} {{ instance.game_version }})
+
+
+
+ Loading modpack...
+
+
+ {{ loader }}
+ {{ instance.game_version }}
+
+
+
+
+
+
+
+ {{ formatMessage(commonMessages.stopButton) }}
+
+
+
+
+
+
+ {{ formatMessage(commonMessages.playButton) }}
+
+
+
+
+
+
+
+ View instance
+
+
+
+ {{ formatMessage(commonMessages.openFolderButton) }}
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/world/RecentWorldsList.vue b/apps/app-frontend/src/components/ui/world/RecentWorldsList.vue
index a960f805..6bac73f9 100644
--- a/apps/app-frontend/src/components/ui/world/RecentWorldsList.vue
+++ b/apps/app-frontend/src/components/ui/world/RecentWorldsList.vue
@@ -1,56 +1,59 @@
-
-
- Jump back in
-
-
- Jump back in
-
-
-
-
- item.world.type === 'server'
- ? refreshServer(item.world.address, item.instance.path)
- : {}
- "
- @update="() => populateJumpBackIn()"
- @play="
- () => {
- currentProfile = item.instance.path
- currentWorld = getWorldIdentifier(item.world)
- joinWorld(item.world)
- }
- "
- @play-instance="
- () => {
- currentProfile = item.instance.path
- playInstance(item.instance)
- }
- "
- @stop="() => stopInstance(item.instance.path)"
- />
-
-
-
-
+
+
+ Jump back in
+
+
+ Jump back in
+
+
+
+
+ item.world.type === 'server'
+ ? refreshServer(item.world.address, item.instance.path)
+ : {}
+ "
+ @update="() => populateJumpBackIn()"
+ @play="
+ () => {
+ currentProfile = item.instance.path
+ currentWorld = getWorldIdentifier(item.world)
+ joinWorld(item.world)
+ }
+ "
+ @play-instance="
+ () => {
+ currentProfile = item.instance.path
+ playInstance(item.instance)
+ }
+ "
+ @stop="() => stopInstance(item.instance.path)"
+ />
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/world/WorldItem.vue b/apps/app-frontend/src/components/ui/world/WorldItem.vue
index c8c1893f..7c61ac05 100644
--- a/apps/app-frontend/src/components/ui/world/WorldItem.vue
+++ b/apps/app-frontend/src/components/ui/world/WorldItem.vue
@@ -1,42 +1,49 @@
-
-
-
-
-
-
-
-
-
- {{ world.name }}
-
-
-
- {{ formatMessage(commonMessages.singleplayerLabel) }}
-
-
-
-
- Loading...
-
-
-
-
-
- Incompatible version {{ serverStatus.version?.name }}
-
-
-
-
-
-
- {{ formatNumber(serverStatus.players?.online, false) }} online
-
-
-
-
- {{ player.name }}
-
-
-
-
-
-
-
- Offline
-
-
-
-
-
-
- {{
- formatMessage(commonMessages.playedLabel, {
- time: formatRelativeTime(dayjs(world.last_played).toISOString()),
- })
- }}
-
- Not played yet
-
-
- •
-
-
- {{ instanceName }}
-
-
-
-
-
-
-
-
- {{ formatMessage(commonMessages.loadingLabel) }}
-
-
-
- {{ formatMessage(messages.cantConnect) }}
-
-
- {{ formatMessage(messages.aMinecraftServer) }}
-
-
-
-
-
- {{ formatMessage(messages.hardcore) }}
-
-
-
- {{ formatMessage(gameMode.message) }}
-
-
-
-
-
-
-
- {{ formatMessage(commonMessages.stopButton) }}
-
-
-
-
-
-
- {{ formatMessage(commonMessages.playButton) }}
-
-
-
-
-
-
-
- {{ formatMessage(messages.playInstance) }}
-
-
-
- {{ formatMessage(messages.playAnyway) }}
-
-
-
- {{ formatMessage(messages.viewInstance) }}
-
-
- {{ formatMessage(commonMessages.editButton) }}
-
-
-
- {{ formatMessage(commonMessages.openFolderButton) }}
-
-
- {{ formatMessage(messages.copyAddress) }}
-
-
- {{ formatMessage(commonMessages.refreshButton) }}
-
-
-
- {{ formatMessage(messages.dontShowOnHome) }}
-
-
-
- {{
- formatMessage(
- world.type === 'server'
- ? commonMessages.removeButton
- : commonMessages.deleteLabel,
- )
- }}
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ {{ world.name }}
+
+
+
+ {{ formatMessage(commonMessages.singleplayerLabel) }}
+
+
+
+
+ Loading...
+
+
+
+
+
+ Incompatible version {{ serverStatus.version?.name }}
+
+
+
+
+
+
+ {{ formatNumber(serverStatus.players?.online, false) }}
+ online
+
+
+
+
+ {{ player.name }}
+
+
+
+
+
+
+
+
+ Offline
+
+
+
+
+
+
+ {{
+ formatMessage(commonMessages.playedLabel, {
+ time: formatRelativeTime(dayjs(world.last_played).toISOString()),
+ })
+ }}
+
+ Not played yet
+
+
+ •
+
+
+ {{ instanceName }}
+
+
+
+
+
+
+
+
+ {{ formatMessage(commonMessages.loadingLabel) }}
+
+
+
+ {{ formatMessage(messages.cantConnect) }}
+
+
+ {{ formatMessage(messages.aMinecraftServer) }}
+
+
+
+
+
+ {{ formatMessage(messages.hardcore) }}
+
+
+
+ {{ formatMessage(gameMode.message) }}
+
+
+
+
+
+
+
+ {{ formatMessage(commonMessages.stopButton) }}
+
+
+
+
+
+
+ {{ formatMessage(commonMessages.playButton) }}
+
+
+
+
+
+
+
+ {{ formatMessage(messages.playInstance) }}
+
+
+
+ {{ formatMessage(messages.viewInstance) }}
+
+
+
+ {{ formatMessage(commonMessages.editButton) }}
+
+
+
+ {{ formatMessage(commonMessages.openFolderButton) }}
+
+
+
+ {{ formatMessage(messages.copyAddress) }}
+
+
+
+ {{ formatMessage(commonMessages.refreshButton) }}
+
+
+
+ {{ formatMessage(messages.dontShowOnHome) }}
+
+
+
+ {{
+ formatMessage(
+ world.type === 'server'
+ ? commonMessages.removeButton
+ : commonMessages.deleteLabel,
+ )
+ }}
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/world/modal/AddServerModal.vue b/apps/app-frontend/src/components/ui/world/modal/AddServerModal.vue
index 00fab96e..139d82b9 100644
--- a/apps/app-frontend/src/components/ui/world/modal/AddServerModal.vue
+++ b/apps/app-frontend/src/components/ui/world/modal/AddServerModal.vue
@@ -1,23 +1,24 @@
-
-
-
-
-
-
-
-
-
-
-
-
- {{ formatMessage(messages.addAndPlay) }}
-
-
-
-
-
- {{ formatMessage(messages.addServer) }}
-
-
-
-
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatMessage(messages.addAndPlay) }}
+
+
+
+
+
+ {{ formatMessage(messages.addServer) }}
+
+
+
+
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/world/modal/EditServerModal.vue b/apps/app-frontend/src/components/ui/world/modal/EditServerModal.vue
index 5e03bbb8..0670b1e5 100644
--- a/apps/app-frontend/src/components/ui/world/modal/EditServerModal.vue
+++ b/apps/app-frontend/src/components/ui/world/modal/EditServerModal.vue
@@ -1,29 +1,30 @@
-
-
-
-
-
-
-
-
-
-
- {{ formatMessage(commonMessages.saveChangesButton) }}
-
-
-
-
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ {{ formatMessage(commonMessages.saveChangesButton) }}
+
+
+
+
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/world/modal/EditSingleplayerWorldModal.vue b/apps/app-frontend/src/components/ui/world/modal/EditSingleplayerWorldModal.vue
index 5a01d93e..f0cabd43 100644
--- a/apps/app-frontend/src/components/ui/world/modal/EditSingleplayerWorldModal.vue
+++ b/apps/app-frontend/src/components/ui/world/modal/EditSingleplayerWorldModal.vue
@@ -1,23 +1,24 @@
-
-
-
- {{ instance.name }}
-
-
-
-
-
-
-
-
-
-
-
- {{ formatMessage(commonMessages.saveChangesButton) }}
-
-
-
-
-
- {{ formatMessage(messages.resetIcon) }}
-
-
-
-
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
-
-
+
+
+
+ {{ instance.name }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatMessage(commonMessages.saveChangesButton) }}
+
+
+
+
+
+ {{ formatMessage(messages.resetIcon) }}
+
+
+
+
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/world/modal/HideFromHomeOption.vue b/apps/app-frontend/src/components/ui/world/modal/HideFromHomeOption.vue
index 024072b5..78d026a9 100644
--- a/apps/app-frontend/src/components/ui/world/modal/HideFromHomeOption.vue
+++ b/apps/app-frontend/src/components/ui/world/modal/HideFromHomeOption.vue
@@ -1,18 +1,18 @@
-
+
diff --git a/apps/app-frontend/src/components/ui/world/modal/ServerModalBody.vue b/apps/app-frontend/src/components/ui/world/modal/ServerModalBody.vue
index 64c82b27..48b69050 100644
--- a/apps/app-frontend/src/components/ui/world/modal/ServerModalBody.vue
+++ b/apps/app-frontend/src/components/ui/world/modal/ServerModalBody.vue
@@ -1,7 +1,8 @@
-
+
diff --git a/apps/app-frontend/src/composables/macCssFix.js b/apps/app-frontend/src/composables/macCssFix.js
index c4ce417a..51b58e76 100644
--- a/apps/app-frontend/src/composables/macCssFix.js
+++ b/apps/app-frontend/src/composables/macCssFix.js
@@ -1,20 +1,21 @@
import { invoke } from '@tauri-apps/api/core'
+
import cssContent from '@/assets/stylesheets/macFix.css?inline'
export async function useCheckDisableMouseover() {
- try {
- // Fetch the CSS content from the Rust backend
- let should_disable_mouseover = await invoke('plugin:utils|should_disable_mouseover')
+ try {
+ // Fetch the CSS content from the Rust backend
+ let should_disable_mouseover = await invoke('plugin:utils|should_disable_mouseover')
- if (should_disable_mouseover) {
- // Create a style element and set its content
- const styleElement = document.createElement('style')
- styleElement.innerHTML = cssContent
+ if (should_disable_mouseover) {
+ // Create a style element and set its content
+ const styleElement = document.createElement('style')
+ styleElement.innerHTML = cssContent
- // Append the style element to the document's head
- document.head.appendChild(styleElement)
- }
- } catch (error) {
- console.error('Error checking OS version from Rust backend', error)
- }
+ // Append the style element to the document's head
+ document.head.appendChild(styleElement)
+ }
+ } catch (error) {
+ console.error('Error checking OS version from Rust backend', error)
+ }
}
diff --git a/apps/app-frontend/src/composables/useMemorySlider.js b/apps/app-frontend/src/composables/useMemorySlider.js
index c52f457e..cd466006 100644
--- a/apps/app-frontend/src/composables/useMemorySlider.js
+++ b/apps/app-frontend/src/composables/useMemorySlider.js
@@ -1,21 +1,21 @@
-import { ref, computed } from 'vue'
+import { computed, ref } from 'vue'
+
import { get_max_memory } from '@/helpers/jre.js'
-import { handleError } from '@/store/notifications.js'
export default async function () {
- const maxMemory = ref(Math.floor((await get_max_memory().catch(handleError)) / 1024))
+ const maxMemory = ref(Math.floor((await get_max_memory()) / 1024))
- const snapPoints = computed(() => {
- let points = []
- let memory = 2048
+ const snapPoints = computed(() => {
+ let points = []
+ let memory = 2048
- while (memory <= maxMemory.value) {
- points.push(memory)
- memory *= 2
- }
+ while (memory <= maxMemory.value) {
+ points.push(memory)
+ memory *= 2
+ }
- return points
- })
+ return points
+ })
- return { maxMemory, snapPoints }
+ return { maxMemory, snapPoints }
}
diff --git a/apps/app-frontend/src/helpers/analytics.js b/apps/app-frontend/src/helpers/analytics.js
index 6fa5ea3a..61b9de23 100644
--- a/apps/app-frontend/src/helpers/analytics.js
+++ b/apps/app-frontend/src/helpers/analytics.js
@@ -1,24 +1,24 @@
import { posthog } from 'posthog-js'
export const initAnalytics = () => {
- posthog.init('phc_9Iqi6lFs9sr5BSqh9RRNRSJ0mATS9PSgirDiX3iOYJ', {
- persistence: 'localStorage',
- api_host: 'https://posthog.modrinth.com',
- })
+ posthog.init('phc_9Iqi6lFs9sr5BSqh9RRNRSJ0mATS9PSgirDiX3iOYJ', {
+ persistence: 'localStorage',
+ api_host: 'https://posthog.modrinth.com',
+ })
}
export const debugAnalytics = () => {
- posthog.debug()
+ posthog.debug()
}
export const optOutAnalytics = () => {
- posthog.opt_out_capturing()
+ posthog.opt_out_capturing()
}
export const optInAnalytics = () => {
- posthog.opt_in_capturing()
+ posthog.opt_in_capturing()
}
export const trackEvent = (eventName, properties) => {
- posthog.capture(eventName, properties)
+ posthog.capture(eventName, properties)
}
diff --git a/apps/app-frontend/src/helpers/auth.js b/apps/app-frontend/src/helpers/auth.js
index abd1b765..61461f06 100644
--- a/apps/app-frontend/src/helpers/auth.js
+++ b/apps/app-frontend/src/helpers/auth.js
@@ -44,7 +44,7 @@ export async function elyby_auth_authenticate(login, password, clientToken) {
* @property {string} user_code - The code to enter on the verification_uri page.
*/
export async function login() {
- return await invoke('plugin:auth|login')
+ return await invoke('plugin:auth|login')
}
/**
@@ -52,7 +52,7 @@ export async function login() {
* @return {Promise}
*/
export async function get_default_user() {
- return await invoke('plugin:auth|get_default_user')
+ return await invoke('plugin:auth|get_default_user')
}
/**
@@ -60,7 +60,7 @@ export async function get_default_user() {
* @param {UUID} user
*/
export async function set_default_user(user) {
- return await invoke('plugin:auth|set_default_user', { user })
+ return await invoke('plugin:auth|set_default_user', { user })
}
/**
@@ -68,7 +68,7 @@ export async function set_default_user(user) {
* @param {UUID} user
*/
export async function remove_user(user) {
- return await invoke('plugin:auth|remove_user', { user })
+ return await invoke('plugin:auth|remove_user', { user })
}
/**
@@ -76,5 +76,5 @@ export async function remove_user(user) {
* @returns {Promise}
*/
export async function users() {
- return await invoke('plugin:auth|get_users')
+ return await invoke('plugin:auth|get_users')
}
diff --git a/apps/app-frontend/src/helpers/cache.js b/apps/app-frontend/src/helpers/cache.js
index 45b3b438..6c631266 100644
--- a/apps/app-frontend/src/helpers/cache.js
+++ b/apps/app-frontend/src/helpers/cache.js
@@ -1,53 +1,53 @@
import { invoke } from '@tauri-apps/api/core'
export async function get_project(id, cacheBehaviour) {
- return await invoke('plugin:cache|get_project', { id, cacheBehaviour })
+ return await invoke('plugin:cache|get_project', { id, cacheBehaviour })
}
export async function get_project_many(ids, cacheBehaviour) {
- return await invoke('plugin:cache|get_project_many', { ids, cacheBehaviour })
+ return await invoke('plugin:cache|get_project_many', { ids, cacheBehaviour })
}
export async function get_version(id, cacheBehaviour) {
- return await invoke('plugin:cache|get_version', { id, cacheBehaviour })
+ return await invoke('plugin:cache|get_version', { id, cacheBehaviour })
}
export async function get_version_many(ids, cacheBehaviour) {
- return await invoke('plugin:cache|get_version_many', { ids, cacheBehaviour })
+ return await invoke('plugin:cache|get_version_many', { ids, cacheBehaviour })
}
export async function get_user(id, cacheBehaviour) {
- return await invoke('plugin:cache|get_user', { id, cacheBehaviour })
+ return await invoke('plugin:cache|get_user', { id, cacheBehaviour })
}
export async function get_user_many(ids, cacheBehaviour) {
- return await invoke('plugin:cache|get_user_many', { ids, cacheBehaviour })
+ return await invoke('plugin:cache|get_user_many', { ids, cacheBehaviour })
}
export async function get_team(id, cacheBehaviour) {
- return await invoke('plugin:cache|get_team', { id, cacheBehaviour })
+ return await invoke('plugin:cache|get_team', { id, cacheBehaviour })
}
export async function get_team_many(ids, cacheBehaviour) {
- return await invoke('plugin:cache|get_team_many', { ids, cacheBehaviour })
+ return await invoke('plugin:cache|get_team_many', { ids, cacheBehaviour })
}
export async function get_organization(id, cacheBehaviour) {
- return await invoke('plugin:cache|get_organization', { id, cacheBehaviour })
+ return await invoke('plugin:cache|get_organization', { id, cacheBehaviour })
}
export async function get_organization_many(ids, cacheBehaviour) {
- return await invoke('plugin:cache|get_organization_many', { ids, cacheBehaviour })
+ return await invoke('plugin:cache|get_organization_many', { ids, cacheBehaviour })
}
export async function get_search_results(id, cacheBehaviour) {
- return await invoke('plugin:cache|get_search_results', { id, cacheBehaviour })
+ return await invoke('plugin:cache|get_search_results', { id, cacheBehaviour })
}
export async function get_search_results_many(ids, cacheBehaviour) {
- return await invoke('plugin:cache|get_search_results_many', { ids, cacheBehaviour })
+ return await invoke('plugin:cache|get_search_results_many', { ids, cacheBehaviour })
}
export async function purge_cache_types(cacheTypes) {
- return await invoke('plugin:cache|purge_cache_types', { cacheTypes })
+ return await invoke('plugin:cache|purge_cache_types', { cacheTypes })
}
diff --git a/apps/app-frontend/src/helpers/events.js b/apps/app-frontend/src/helpers/events.js
index 81a849b9..5c10eaeb 100644
--- a/apps/app-frontend/src/helpers/events.js
+++ b/apps/app-frontend/src/helpers/events.js
@@ -41,7 +41,7 @@ import { listen } from '@tauri-apps/api/event'
}
*/
export async function loading_listener(callback) {
- return await listen('loading', (event) => callback(event.payload))
+ return await listen('loading', (event) => callback(event.payload))
}
/// Payload for the 'process' event
@@ -54,7 +54,7 @@ export async function loading_listener(callback) {
}
*/
export async function process_listener(callback) {
- return await listen('process', (event) => callback(event.payload))
+ return await listen('process', (event) => callback(event.payload))
}
/// Payload for the 'profile' event
@@ -68,7 +68,7 @@ export async function process_listener(callback) {
}
*/
export async function profile_listener(callback) {
- return await listen('profile', (event) => callback(event.payload))
+ return await listen('profile', (event) => callback(event.payload))
}
/// Payload for the 'command' event
@@ -79,9 +79,9 @@ export async function profile_listener(callback) {
}
*/
export async function command_listener(callback) {
- return await listen('command', (event) => {
- callback(event.payload)
- })
+ return await listen('command', (event) => {
+ callback(event.payload)
+ })
}
/// Payload for the 'warning' event
@@ -91,9 +91,9 @@ export async function command_listener(callback) {
}
*/
export async function warning_listener(callback) {
- return await listen('warning', (event) => callback(event.payload))
+ return await listen('warning', (event) => callback(event.payload))
}
export async function friend_listener(callback) {
- return await listen('friend', (event) => callback(event.payload))
+ return await listen('friend', (event) => callback(event.payload))
}
diff --git a/apps/app-frontend/src/helpers/fetch.js b/apps/app-frontend/src/helpers/fetch.js
index 5c5cf39c..3e29387f 100644
--- a/apps/app-frontend/src/helpers/fetch.js
+++ b/apps/app-frontend/src/helpers/fetch.js
@@ -1,18 +1,18 @@
-import { fetch } from '@tauri-apps/plugin-http'
-import { handleError } from '@/store/state.js'
import { getVersion } from '@tauri-apps/api/app'
+import { fetch } from '@tauri-apps/plugin-http'
export const useFetch = async (url, item, isSilent) => {
- try {
- const version = await getVersion()
- return await fetch(url, {
- method: 'GET',
- headers: { 'User-Agent': `modrinth/theseus/${version} (support@modrinth.com)` },
- })
- } catch (err) {
- if (!isSilent) {
- handleError({ message: `Error fetching ${item}` })
- }
- console.error(err)
- }
+ try {
+ const version = await getVersion()
+ return await fetch(url, {
+ method: 'GET',
+ headers: { 'User-Agent': `modrinth/theseus/${version} (support@modrinth.com)` },
+ })
+ } catch (err) {
+ if (!isSilent) {
+ throw err
+ } else {
+ console.error(err)
+ }
+ }
}
diff --git a/apps/app-frontend/src/helpers/friends.js b/apps/app-frontend/src/helpers/friends.js
index 168c9383..16d64f11 100644
--- a/apps/app-frontend/src/helpers/friends.js
+++ b/apps/app-frontend/src/helpers/friends.js
@@ -1,17 +1,17 @@
import { invoke } from '@tauri-apps/api/core'
export async function friends() {
- return await invoke('plugin:friends|friends')
+ return await invoke('plugin:friends|friends')
}
export async function friend_statuses() {
- return await invoke('plugin:friends|friend_statuses')
+ return await invoke('plugin:friends|friend_statuses')
}
export async function add_friend(userId) {
- return await invoke('plugin:friends|add_friend', { userId })
+ return await invoke('plugin:friends|add_friend', { userId })
}
export async function remove_friend(userId) {
- return await invoke('plugin:friends|remove_friend', { userId })
+ return await invoke('plugin:friends|remove_friend', { userId })
}
diff --git a/apps/app-frontend/src/helpers/import.js b/apps/app-frontend/src/helpers/import.js
index d6bc9d38..602d7259 100644
--- a/apps/app-frontend/src/helpers/import.js
+++ b/apps/app-frontend/src/helpers/import.js
@@ -4,6 +4,7 @@
* and deserialized into a usable JS object.
*/
import { invoke } from '@tauri-apps/api/core'
+
import { create } from './profile'
/*
@@ -27,39 +28,39 @@ import { create } from './profile'
/// eg: get_importable_instances("MultiMC", "C:/MultiMC")
/// returns ["Instance 1", "Instance 2"]
export async function get_importable_instances(launcherType, basePath) {
- return await invoke('plugin:import|get_importable_instances', { launcherType, basePath })
+ return await invoke('plugin:import|get_importable_instances', { launcherType, basePath })
}
/// Import an instance from a launcher type and base path
/// eg: import_instance("profile-name-to-go-to", "MultiMC", "C:/MultiMC", "Instance 1")
export async function import_instance(launcherType, basePath, instanceFolder) {
- // create a basic, empty instance (most properties will be filled in by the import process)
- // We do NOT watch the fs for changes to avoid duplicate events during installation
- // fs watching will be enabled once the instance is imported
- const profilePath = await create(instanceFolder, '1.19.4', 'vanilla', 'latest', null, true)
+ // create a basic, empty instance (most properties will be filled in by the import process)
+ // We do NOT watch the fs for changes to avoid duplicate events during installation
+ // fs watching will be enabled once the instance is imported
+ const profilePath = await create(instanceFolder, '1.19.4', 'vanilla', 'latest', null, true)
- return await invoke('plugin:import|import_instance', {
- profilePath,
- launcherType,
- basePath,
- instanceFolder,
- })
+ return await invoke('plugin:import|import_instance', {
+ profilePath,
+ launcherType,
+ basePath,
+ instanceFolder,
+ })
}
/// Checks if this instance is valid for importing, given a certain launcher type
/// eg: is_valid_importable_instance("C:/MultiMC/Instance 1", "MultiMC")
export async function is_valid_importable_instance(instanceFolder, launcherType) {
- return await invoke('plugin:import|is_valid_importable_instance', {
- instanceFolder,
- launcherType,
- })
+ return await invoke('plugin:import|is_valid_importable_instance', {
+ instanceFolder,
+ launcherType,
+ })
}
/// Gets the default path for the given launcher type
/// null if it can't be found or doesn't exist
/// eg: get_default_launcher_path("MultiMC")
export async function get_default_launcher_path(launcherType) {
- return await invoke('plugin:import|get_default_launcher_path', { launcherType })
+ return await invoke('plugin:import|get_default_launcher_path', { launcherType })
}
/// Fetch CurseForge profile metadata from profile code
diff --git a/apps/app-frontend/src/helpers/jre.js b/apps/app-frontend/src/helpers/jre.js
index 207c0258..4be5ff02 100644
--- a/apps/app-frontend/src/helpers/jre.js
+++ b/apps/app-frontend/src/helpers/jre.js
@@ -15,37 +15,37 @@ JavaVersion {
*/
export async function get_java_versions() {
- return await invoke('plugin:jre|get_java_versions')
+ return await invoke('plugin:jre|get_java_versions')
}
export async function set_java_version(javaVersion) {
- return await invoke('plugin:jre|set_java_version', { javaVersion })
+ return await invoke('plugin:jre|set_java_version', { javaVersion })
}
// Finds all the installation of Java 7, if it exists
// Returns [JavaVersion]
export async function find_filtered_jres(version) {
- return await invoke('plugin:jre|jre_find_filtered_jres', { version })
+ return await invoke('plugin:jre|jre_find_filtered_jres', { version })
}
// Gets java version from a specific path by trying to run 'java -version' on it.
// This also validates it, as it returns null if no valid java version is found at the path
export async function get_jre(path) {
- return await invoke('plugin:jre|jre_get_jre', { path })
+ return await invoke('plugin:jre|jre_get_jre', { path })
}
// Tests JRE version by running 'java -version' on it.
// Returns true if the version is valid, and matches given (after extraction)
export async function test_jre(path, majorVersion) {
- return await invoke('plugin:jre|jre_test_jre', { path, majorVersion })
+ return await invoke('plugin:jre|jre_test_jre', { path, majorVersion })
}
// Automatically installs specified java version
export async function auto_install_java(javaVersion) {
- return await invoke('plugin:jre|jre_auto_install_java', { javaVersion })
+ return await invoke('plugin:jre|jre_auto_install_java', { javaVersion })
}
// Get max memory in KiB
export async function get_max_memory() {
- return await invoke('plugin:jre|jre_get_max_memory')
+ return await invoke('plugin:jre|jre_get_max_memory')
}
diff --git a/apps/app-frontend/src/helpers/logs.js b/apps/app-frontend/src/helpers/logs.js
index 963bae88..bb243f2a 100644
--- a/apps/app-frontend/src/helpers/logs.js
+++ b/apps/app-frontend/src/helpers/logs.js
@@ -18,31 +18,35 @@ pub struct Logs {
/// Get all logs that exist for a given profile
/// This is returned as an array of Log objects, sorted by filename (the folder name, when the log was created)
export async function get_logs(profilePath, clearContents) {
- return await invoke('plugin:logs|logs_get_logs', { profilePath, clearContents })
+ return await invoke('plugin:logs|logs_get_logs', { profilePath, clearContents })
}
/// Get a profile's log by filename
export async function get_logs_by_filename(profilePath, logType, filename) {
- return await invoke('plugin:logs|logs_get_logs_by_filename', { profilePath, logType, filename })
+ return await invoke('plugin:logs|logs_get_logs_by_filename', { profilePath, logType, filename })
}
/// Get a profile's log text only by filename
export async function get_output_by_filename(profilePath, logType, filename) {
- return await invoke('plugin:logs|logs_get_output_by_filename', { profilePath, logType, filename })
+ return await invoke('plugin:logs|logs_get_output_by_filename', {
+ profilePath,
+ logType,
+ filename,
+ })
}
/// Delete a profile's log by filename
export async function delete_logs_by_filename(profilePath, logType, filename) {
- return await invoke('plugin:logs|logs_delete_logs_by_filename', {
- profilePath,
- logType,
- filename,
- })
+ return await invoke('plugin:logs|logs_delete_logs_by_filename', {
+ profilePath,
+ logType,
+ filename,
+ })
}
/// Delete all logs for a given profile
export async function delete_logs(profilePath) {
- return await invoke('plugin:logs|logs_delete_logs', { profilePath })
+ return await invoke('plugin:logs|logs_delete_logs', { profilePath })
}
/// Get the latest log for a given profile and cursor (startpoint to read withi nthe file)
@@ -57,5 +61,5 @@ export async function delete_logs(profilePath) {
// From latest.log directly
export async function get_latest_log_cursor(profilePath, cursor) {
- return await invoke('plugin:logs|logs_get_latest_log_cursor', { profilePath, cursor })
+ return await invoke('plugin:logs|logs_get_latest_log_cursor', { profilePath, cursor })
}
diff --git a/apps/app-frontend/src/helpers/metadata.js b/apps/app-frontend/src/helpers/metadata.js
index 2959834f..51898dd5 100644
--- a/apps/app-frontend/src/helpers/metadata.js
+++ b/apps/app-frontend/src/helpers/metadata.js
@@ -3,11 +3,11 @@ import { invoke } from '@tauri-apps/api/core'
/// Gets the game versions from daedalus
// Returns a VersionManifest
export async function get_game_versions() {
- return await invoke('plugin:metadata|metadata_get_game_versions')
+ return await invoke('plugin:metadata|metadata_get_game_versions')
}
// Gets the given loader versions from daedalus
// Returns Manifest
export async function get_loader_versions(loader) {
- return await invoke('plugin:metadata|metadata_get_loader_versions', { loader })
+ return await invoke('plugin:metadata|metadata_get_loader_versions', { loader })
}
diff --git a/apps/app-frontend/src/helpers/mr_auth.js b/apps/app-frontend/src/helpers/mr_auth.js
index 6be54bd2..2690957e 100644
--- a/apps/app-frontend/src/helpers/mr_auth.js
+++ b/apps/app-frontend/src/helpers/mr_auth.js
@@ -6,17 +6,17 @@
import { invoke } from '@tauri-apps/api/core'
export async function login() {
- return await invoke('plugin:mr-auth|modrinth_login')
+ return await invoke('plugin:mr-auth|modrinth_login')
}
export async function logout() {
- return await invoke('plugin:mr-auth|logout')
+ return await invoke('plugin:mr-auth|logout')
}
export async function get() {
- return await invoke('plugin:mr-auth|get')
+ return await invoke('plugin:mr-auth|get')
}
export async function cancelLogin() {
- return await invoke('plugin:mr-auth|cancel_modrinth_login')
+ return await invoke('plugin:mr-auth|cancel_modrinth_login')
}
diff --git a/apps/app-frontend/src/helpers/pack.js b/apps/app-frontend/src/helpers/pack.js
index 2026ec12..312dfc62 100644
--- a/apps/app-frontend/src/helpers/pack.js
+++ b/apps/app-frontend/src/helpers/pack.js
@@ -4,61 +4,62 @@
* and deserialized into a usable JS object.
*/
import { invoke } from '@tauri-apps/api/core'
+
import { create } from './profile'
// Installs pack from a version ID
export async function create_profile_and_install(
- projectId,
- versionId,
- packTitle,
- iconUrl,
- createInstanceCallback = () => {},
+ projectId,
+ versionId,
+ packTitle,
+ iconUrl,
+ createInstanceCallback = () => {},
) {
- const location = {
- type: 'fromVersionId',
- project_id: projectId,
- version_id: versionId,
- title: packTitle,
- icon_url: iconUrl,
- }
- const profile_creator = await invoke('plugin:pack|pack_get_profile_from_pack', { location })
- const profile = await create(
- profile_creator.name,
- profile_creator.gameVersion,
- profile_creator.modloader,
- profile_creator.loaderVersion,
- null,
- true,
- )
- createInstanceCallback(profile)
+ const location = {
+ type: 'fromVersionId',
+ project_id: projectId,
+ version_id: versionId,
+ title: packTitle,
+ icon_url: iconUrl,
+ }
+ const profile_creator = await invoke('plugin:pack|pack_get_profile_from_pack', { location })
+ const profile = await create(
+ profile_creator.name,
+ profile_creator.gameVersion,
+ profile_creator.modloader,
+ profile_creator.loaderVersion,
+ null,
+ true,
+ )
+ createInstanceCallback(profile)
- return await invoke('plugin:pack|pack_install', { location, profile })
+ return await invoke('plugin:pack|pack_install', { location, profile })
}
export async function install_to_existing_profile(projectId, versionId, title, profilePath) {
- const location = {
- type: 'fromVersionId',
- project_id: projectId,
- version_id: versionId,
- title,
- }
- return await invoke('plugin:pack|pack_install', { location, profile: profilePath })
+ const location = {
+ type: 'fromVersionId',
+ project_id: projectId,
+ version_id: versionId,
+ title,
+ }
+ return await invoke('plugin:pack|pack_install', { location, profile: profilePath })
}
// Installs pack from a path
export async function create_profile_and_install_from_file(path) {
- const location = {
- type: 'fromFile',
- path: path,
- }
- const profile_creator = await invoke('plugin:pack|pack_get_profile_from_pack', { location })
- const profile = await create(
- profile_creator.name,
- profile_creator.gameVersion,
- profile_creator.modloader,
- profile_creator.loaderVersion,
- null,
- true,
- )
- return await invoke('plugin:pack|pack_install', { location, profile })
+ const location = {
+ type: 'fromFile',
+ path: path,
+ }
+ const profile_creator = await invoke('plugin:pack|pack_get_profile_from_pack', { location })
+ const profile = await create(
+ profile_creator.name,
+ profile_creator.gameVersion,
+ profile_creator.modloader,
+ profile_creator.loaderVersion,
+ null,
+ true,
+ )
+ return await invoke('plugin:pack|pack_install', { location, profile })
}
diff --git a/apps/app-frontend/src/helpers/process.js b/apps/app-frontend/src/helpers/process.js
index 140ba6a9..a9f4dcc3 100644
--- a/apps/app-frontend/src/helpers/process.js
+++ b/apps/app-frontend/src/helpers/process.js
@@ -8,16 +8,16 @@ import { invoke } from '@tauri-apps/api/core'
/// Gets all running process IDs with a given profile path
/// Returns [u32]
export async function get_by_profile_path(path) {
- return await invoke('plugin:process|process_get_by_profile_path', { path })
+ return await invoke('plugin:process|process_get_by_profile_path', { path })
}
/// Gets all running process IDs with a given profile path
/// Returns [u32]
export async function get_all() {
- return await invoke('plugin:process|process_get_all')
+ return await invoke('plugin:process|process_get_all')
}
/// Kills a process by UUID
export async function kill(uuid) {
- return await invoke('plugin:process|process_kill', { uuid })
+ return await invoke('plugin:process|process_kill', { uuid })
}
diff --git a/apps/app-frontend/src/helpers/profile.js b/apps/app-frontend/src/helpers/profile.js
index ed9741bd..e3c844d2 100644
--- a/apps/app-frontend/src/helpers/profile.js
+++ b/apps/app-frontend/src/helpers/profile.js
@@ -4,8 +4,8 @@
* and deserialized into a usable JS object.
*/
import { invoke } from '@tauri-apps/api/core'
+
import { install_to_existing_profile } from '@/helpers/pack.js'
-import { handleError } from '@/store/notifications.js'
/// Add instance
/*
@@ -19,142 +19,145 @@ import { handleError } from '@/store/notifications.js'
*/
export async function create(name, gameVersion, modloader, loaderVersion, iconPath, skipInstall) {
- //Trim string name to avoid "Unable to find directory"
- name = name.trim()
- return await invoke('plugin:profile-create|profile_create', {
- name,
- gameVersion,
- modloader,
- loaderVersion,
- iconPath,
- skipInstall,
- })
+ //Trim string name to avoid "Unable to find directory"
+ name = name.trim()
+ return await invoke('plugin:profile-create|profile_create', {
+ name,
+ gameVersion,
+ modloader,
+ loaderVersion,
+ iconPath,
+ skipInstall,
+ })
}
// duplicate a profile
export async function duplicate(path) {
- return await invoke('plugin:profile-create|profile_duplicate', { path })
+ return await invoke('plugin:profile-create|profile_duplicate', { path })
}
// Remove a profile
export async function remove(path) {
- return await invoke('plugin:profile|profile_remove', { path })
+ return await invoke('plugin:profile|profile_remove', { path })
}
// Get a profile by path
// Returns a Profile
export async function get(path) {
- return await invoke('plugin:profile|profile_get', { path })
+ return await invoke('plugin:profile|profile_get', { path })
}
export async function get_many(paths) {
- return await invoke('plugin:profile|profile_get_many', { paths })
+ return await invoke('plugin:profile|profile_get_many', { paths })
}
// Get a profile's projects
// Returns a map of a path to profile file
export async function get_projects(path, cacheBehaviour) {
- return await invoke('plugin:profile|profile_get_projects', { path, cacheBehaviour })
+ return await invoke('plugin:profile|profile_get_projects', { path, cacheBehaviour })
}
// Get a profile's full fs path
// Returns a path
export async function get_full_path(path) {
- return await invoke('plugin:profile|profile_get_full_path', { path })
+ return await invoke('plugin:profile|profile_get_full_path', { path })
}
// Get's a mod's full fs path
// Returns a path
export async function get_mod_full_path(path, projectPath) {
- return await invoke('plugin:profile|profile_get_mod_full_path', { path, projectPath })
+ return await invoke('plugin:profile|profile_get_mod_full_path', { path, projectPath })
}
// Get optimal java version from profile
// Returns a java version
export async function get_optimal_jre_key(path) {
- return await invoke('plugin:profile|profile_get_optimal_jre_key', { path })
+ return await invoke('plugin:profile|profile_get_optimal_jre_key', { path })
}
// Get a copy of the profile set
// Returns hashmap of path -> Profile
export async function list() {
- return await invoke('plugin:profile|profile_list')
+ return await invoke('plugin:profile|profile_list')
}
export async function check_installed(path, projectId) {
- return await invoke('plugin:profile|profile_check_installed', { path, projectId })
+ return await invoke('plugin:profile|profile_check_installed', { path, projectId })
}
// Installs/Repairs a profile
export async function install(path, force) {
- return await invoke('plugin:profile|profile_install', { path, force })
+ return await invoke('plugin:profile|profile_install', { path, force })
}
// Updates all of a profile's projects
export async function update_all(path) {
- return await invoke('plugin:profile|profile_update_all', { path })
+ return await invoke('plugin:profile|profile_update_all', { path })
}
// Updates a specified project
export async function update_project(path, projectPath) {
- return await invoke('plugin:profile|profile_update_project', { path, projectPath })
+ return await invoke('plugin:profile|profile_update_project', { path, projectPath })
}
// Add a project to a profile from a version
// Returns a path to the new project file
export async function add_project_from_version(path, versionId) {
- return await invoke('plugin:profile|profile_add_project_from_version', { path, versionId })
+ return await invoke('plugin:profile|profile_add_project_from_version', { path, versionId })
}
// Add a project to a profile from a path + project_type
// Returns a path to the new project file
export async function add_project_from_path(path, projectPath, projectType) {
- return await invoke('plugin:profile|profile_add_project_from_path', {
- path,
- projectPath,
- projectType,
- })
+ return await invoke('plugin:profile|profile_add_project_from_path', {
+ path,
+ projectPath,
+ projectType,
+ })
}
// Toggle disabling a project
export async function toggle_disable_project(path, projectPath) {
- return await invoke('plugin:profile|profile_toggle_disable_project', { path, projectPath })
+ return await invoke('plugin:profile|profile_toggle_disable_project', { path, projectPath })
}
// Remove a project
export async function remove_project(path, projectPath) {
- return await invoke('plugin:profile|profile_remove_project', { path, projectPath })
+ return await invoke('plugin:profile|profile_remove_project', { path, projectPath })
}
// Update a managed Modrinth profile to a specific version
export async function update_managed_modrinth_version(path, versionId) {
- return await invoke('plugin:profile|profile_update_managed_modrinth_version', { path, versionId })
+ return await invoke('plugin:profile|profile_update_managed_modrinth_version', {
+ path,
+ versionId,
+ })
}
// Repair a managed Modrinth profile
export async function update_repair_modrinth(path) {
- return await invoke('plugin:profile|profile_repair_managed_modrinth', { path })
+ return await invoke('plugin:profile|profile_repair_managed_modrinth', { path })
}
// Export a profile to .mrpack
/// included_overrides is an array of paths to override folders to include (ie: 'mods', 'resource_packs')
// Version id is optional (ie: 1.1.5)
export async function export_profile_mrpack(
- path,
- exportLocation,
- includedOverrides,
- versionId,
- description,
- name,
+ path,
+ exportLocation,
+ includedOverrides,
+ versionId,
+ description,
+ name,
) {
- return await invoke('plugin:profile|profile_export_mrpack', {
- path,
- exportLocation,
- includedOverrides,
- versionId,
- description,
- name,
- })
+ return await invoke('plugin:profile|profile_export_mrpack', {
+ path,
+ exportLocation,
+ includedOverrides,
+ versionId,
+ description,
+ name,
+ })
}
// Given a folder path, populate an array of all the subfolders
@@ -166,39 +169,39 @@ export async function export_profile_mrpack(
// => [mods, resourcepacks]
// allows selection for 'included_overrides' in export_profile_mrpack
export async function get_pack_export_candidates(profilePath) {
- return await invoke('plugin:profile|profile_get_pack_export_candidates', { profilePath })
+ return await invoke('plugin:profile|profile_get_pack_export_candidates', { profilePath })
}
// Run Minecraft using a pathed profile
// Returns PID of child
export async function run(path) {
- return await invoke('plugin:profile|profile_run', { path })
+ return await invoke('plugin:profile|profile_run', { path })
}
export async function kill(path) {
- return await invoke('plugin:profile|profile_kill', { path })
+ return await invoke('plugin:profile|profile_kill', { path })
}
// Edits a profile
export async function edit(path, editProfile) {
- return await invoke('plugin:profile|profile_edit', { path, editProfile })
+ return await invoke('plugin:profile|profile_edit', { path, editProfile })
}
// Edits a profile's icon
export async function edit_icon(path, iconPath) {
- return await invoke('plugin:profile|profile_edit_icon', { path, iconPath })
+ return await invoke('plugin:profile|profile_edit_icon', { path, iconPath })
}
export async function finish_install(instance) {
- if (instance.install_stage !== 'pack_installed') {
- let linkedData = instance.linked_data
- await install_to_existing_profile(
- linkedData.project_id,
- linkedData.version_id,
- instance.name,
- instance.path,
- ).catch(handleError)
- } else {
- await install(instance.path, false).catch(handleError)
- }
+ if (instance.install_stage !== 'pack_installed') {
+ let linkedData = instance.linked_data
+ await install_to_existing_profile(
+ linkedData.project_id,
+ linkedData.version_id,
+ instance.name,
+ instance.path,
+ )
+ } else {
+ await install(instance.path, false)
+ }
}
diff --git a/apps/app-frontend/src/helpers/rendering/batch-skin-renderer.ts b/apps/app-frontend/src/helpers/rendering/batch-skin-renderer.ts
index 4e66e649..bd7d43fc 100644
--- a/apps/app-frontend/src/helpers/rendering/batch-skin-renderer.ts
+++ b/apps/app-frontend/src/helpers/rendering/batch-skin-renderer.ts
@@ -1,191 +1,192 @@
-import * as THREE from 'three'
-import type { Skin, Cape } from '../skins'
-import { get_normalized_skin_texture, determineModelType } from '../skins'
-import { reactive } from 'vue'
-import {
- setupSkinModel,
- disposeCaches,
- loadTexture,
- applyCapeTexture,
- createTransparentTexture,
-} from '@modrinth/utils'
-import { skinPreviewStorage } from '../storage/skin-preview-storage'
-import { headStorage } from '../storage/head-storage'
import { ClassicPlayerModel, SlimPlayerModel } from '@modrinth/assets'
+import {
+ applyCapeTexture,
+ createTransparentTexture,
+ disposeCaches,
+ loadTexture,
+ setupSkinModel,
+} from '@modrinth/utils'
+import * as THREE from 'three'
+import { reactive } from 'vue'
+
+import type { Cape, Skin } from '../skins'
+import { determineModelType, get_normalized_skin_texture } from '../skins'
+import { headStorage } from '../storage/head-storage'
+import { skinPreviewStorage } from '../storage/skin-preview-storage'
export interface RenderResult {
- forwards: string
- backwards: string
+ forwards: string
+ backwards: string
}
export interface RawRenderResult {
- forwards: Blob
- backwards: Blob
+ forwards: Blob
+ backwards: Blob
}
class BatchSkinRenderer {
- private renderer: THREE.WebGLRenderer | null = null
- private scene: THREE.Scene | null = null
- private camera: THREE.PerspectiveCamera | null = null
- private currentModel: THREE.Group | null = null
- private readonly width: number
- private readonly height: number
+ private renderer: THREE.WebGLRenderer | null = null
+ private scene: THREE.Scene | null = null
+ private camera: THREE.PerspectiveCamera | null = null
+ private currentModel: THREE.Group | null = null
+ private readonly width: number
+ private readonly height: number
- constructor(width: number = 360, height: number = 504) {
- this.width = width
- this.height = height
- }
+ constructor(width: number = 360, height: number = 504) {
+ this.width = width
+ this.height = height
+ }
- private initializeRenderer(): void {
- if (this.renderer) return
+ private initializeRenderer(): void {
+ if (this.renderer) return
- const canvas = document.createElement('canvas')
- canvas.width = this.width
- canvas.height = this.height
+ const canvas = document.createElement('canvas')
+ canvas.width = this.width
+ canvas.height = this.height
- this.renderer = new THREE.WebGLRenderer({
- canvas: canvas,
- antialias: true,
- alpha: true,
- preserveDrawingBuffer: true,
- })
+ this.renderer = new THREE.WebGLRenderer({
+ canvas: canvas,
+ antialias: true,
+ alpha: true,
+ preserveDrawingBuffer: true,
+ })
- this.renderer.outputColorSpace = THREE.SRGBColorSpace
- this.renderer.toneMapping = THREE.NoToneMapping
- this.renderer.toneMappingExposure = 10.0
- this.renderer.setClearColor(0x000000, 0)
- this.renderer.setSize(this.width, this.height)
+ this.renderer.outputColorSpace = THREE.SRGBColorSpace
+ this.renderer.toneMapping = THREE.NoToneMapping
+ this.renderer.toneMappingExposure = 10.0
+ this.renderer.setClearColor(0x000000, 0)
+ this.renderer.setSize(this.width, this.height)
- this.scene = new THREE.Scene()
- this.camera = new THREE.PerspectiveCamera(20, this.width / this.height, 0.4, 1000)
+ this.scene = new THREE.Scene()
+ this.camera = new THREE.PerspectiveCamera(20, this.width / this.height, 0.4, 1000)
- const ambientLight = new THREE.AmbientLight(0xffffff, 2)
- const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2)
- directionalLight.castShadow = true
- directionalLight.position.set(2, 4, 3)
- this.scene.add(ambientLight)
- this.scene.add(directionalLight)
- }
+ const ambientLight = new THREE.AmbientLight(0xffffff, 2)
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2)
+ directionalLight.castShadow = true
+ directionalLight.position.set(2, 4, 3)
+ this.scene.add(ambientLight)
+ this.scene.add(directionalLight)
+ }
- public async renderSkin(
- textureUrl: string,
- modelUrl: string,
- capeUrl?: string,
- ): Promise {
- this.initializeRenderer()
+ public async renderSkin(
+ textureUrl: string,
+ modelUrl: string,
+ capeUrl?: string,
+ ): Promise {
+ this.initializeRenderer()
- this.clearScene()
+ this.clearScene()
- await this.setupModel(modelUrl, textureUrl, capeUrl)
+ await this.setupModel(modelUrl, textureUrl, capeUrl)
- const headPart = this.currentModel!.getObjectByName('Head')
- let lookAtTarget: [number, number, number]
+ const headPart = this.currentModel!.getObjectByName('Head')
+ let lookAtTarget: [number, number, number]
- if (headPart) {
- const headPosition = new THREE.Vector3()
- headPart.getWorldPosition(headPosition)
- lookAtTarget = [headPosition.x, headPosition.y - 0.3, headPosition.z]
- } else {
- throw new Error("Failed to find 'Head' object in model.")
- }
+ if (headPart) {
+ const headPosition = new THREE.Vector3()
+ headPart.getWorldPosition(headPosition)
+ lookAtTarget = [headPosition.x, headPosition.y - 0.3, headPosition.z]
+ } else {
+ throw new Error("Failed to find 'Head' object in model.")
+ }
- const frontCameraPos: [number, number, number] = [-1.3, 1, 6.3]
- const backCameraPos: [number, number, number] = [-1.3, 1, -2.5]
+ const frontCameraPos: [number, number, number] = [-1.3, 1, 6.3]
+ const backCameraPos: [number, number, number] = [-1.3, 1, -2.5]
- const forwards = await this.renderView(frontCameraPos, lookAtTarget)
- const backwards = await this.renderView(backCameraPos, lookAtTarget)
+ const forwards = await this.renderView(frontCameraPos, lookAtTarget)
+ const backwards = await this.renderView(backCameraPos, lookAtTarget)
- return { forwards, backwards }
- }
+ return { forwards, backwards }
+ }
- private async renderView(
- cameraPosition: [number, number, number],
- lookAtPosition: [number, number, number],
- ): Promise {
- if (!this.camera || !this.renderer || !this.scene) {
- throw new Error('Renderer not initialized')
- }
+ private async renderView(
+ cameraPosition: [number, number, number],
+ lookAtPosition: [number, number, number],
+ ): Promise {
+ if (!this.camera || !this.renderer || !this.scene) {
+ throw new Error('Renderer not initialized')
+ }
- this.camera.position.set(...cameraPosition)
- this.camera.lookAt(...lookAtPosition)
+ this.camera.position.set(...cameraPosition)
+ this.camera.lookAt(...lookAtPosition)
- this.renderer.render(this.scene, this.camera)
+ this.renderer.render(this.scene, this.camera)
- const dataUrl = this.renderer.domElement.toDataURL('image/webp', 0.9)
- const response = await fetch(dataUrl)
- return await response.blob()
- }
+ const dataUrl = this.renderer.domElement.toDataURL('image/webp', 0.9)
+ const response = await fetch(dataUrl)
+ return await response.blob()
+ }
- private async setupModel(modelUrl: string, textureUrl: string, capeUrl?: string): Promise {
- if (!this.scene) {
- throw new Error('Renderer not initialized')
- }
+ private async setupModel(modelUrl: string, textureUrl: string, capeUrl?: string): Promise {
+ if (!this.scene) {
+ throw new Error('Renderer not initialized')
+ }
- const { model } = await setupSkinModel(modelUrl, textureUrl)
+ const { model } = await setupSkinModel(modelUrl, textureUrl)
- if (capeUrl) {
- const capeTexture = await loadTexture(capeUrl)
- applyCapeTexture(model, capeTexture)
- } else {
- const transparentTexture = createTransparentTexture()
- applyCapeTexture(model, null, transparentTexture)
- }
+ if (capeUrl) {
+ const capeTexture = await loadTexture(capeUrl)
+ applyCapeTexture(model, capeTexture)
+ } else {
+ const transparentTexture = createTransparentTexture()
+ applyCapeTexture(model, null, transparentTexture)
+ }
- const group = new THREE.Group()
- group.add(model)
- group.position.set(0, 0.3, 1.95)
- group.scale.set(0.8, 0.8, 0.8)
+ const group = new THREE.Group()
+ group.add(model)
+ group.position.set(0, 0.3, 1.95)
+ group.scale.set(0.8, 0.8, 0.8)
- this.scene.add(group)
- this.currentModel = group
- }
+ this.scene.add(group)
+ this.currentModel = group
+ }
- private clearScene(): void {
- if (!this.scene) return
+ private clearScene(): void {
+ if (!this.scene) return
- while (this.scene.children.length > 0) {
- const child = this.scene.children[0]
- this.scene.remove(child)
+ while (this.scene.children.length > 0) {
+ const child = this.scene.children[0]
+ this.scene.remove(child)
- if (child instanceof THREE.Mesh) {
- if (child.geometry) child.geometry.dispose()
- if (child.material) {
- if (Array.isArray(child.material)) {
- child.material.forEach((material) => material.dispose())
- } else {
- child.material.dispose()
- }
- }
- }
- }
+ if (child instanceof THREE.Mesh) {
+ if (child.geometry) child.geometry.dispose()
+ if (child.material) {
+ if (Array.isArray(child.material)) {
+ child.material.forEach((material) => material.dispose())
+ } else {
+ child.material.dispose()
+ }
+ }
+ }
+ }
- const ambientLight = new THREE.AmbientLight(0xffffff, 2)
- const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2)
- directionalLight.castShadow = true
- directionalLight.position.set(2, 4, 3)
- this.scene.add(ambientLight)
- this.scene.add(directionalLight)
+ const ambientLight = new THREE.AmbientLight(0xffffff, 2)
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2)
+ directionalLight.castShadow = true
+ directionalLight.position.set(2, 4, 3)
+ this.scene.add(ambientLight)
+ this.scene.add(directionalLight)
- this.currentModel = null
- }
+ this.currentModel = null
+ }
- public dispose(): void {
- if (this.renderer) {
- this.renderer.dispose()
- }
- disposeCaches()
- }
+ public dispose(): void {
+ if (this.renderer) {
+ this.renderer.dispose()
+ }
+ disposeCaches()
+ }
}
function getModelUrlForVariant(variant: string): string {
- switch (variant) {
- case 'SLIM':
- return SlimPlayerModel
- case 'CLASSIC':
- case 'UNKNOWN':
- default:
- return ClassicPlayerModel
- }
+ switch (variant) {
+ case 'SLIM':
+ return SlimPlayerModel
+ case 'CLASSIC':
+ case 'UNKNOWN':
+ default:
+ return ClassicPlayerModel
+ }
}
export const skinBlobUrlMap = reactive(new Map())
@@ -194,253 +195,253 @@ const DEBUG_MODE = false
let sharedRenderer: BatchSkinRenderer | null = null
function getSharedRenderer(): BatchSkinRenderer {
- if (!sharedRenderer) {
- sharedRenderer = new BatchSkinRenderer()
- }
- return sharedRenderer
+ if (!sharedRenderer) {
+ sharedRenderer = new BatchSkinRenderer()
+ }
+ return sharedRenderer
}
export function disposeSharedRenderer(): void {
- if (sharedRenderer) {
- sharedRenderer.dispose()
- sharedRenderer = null
- }
+ if (sharedRenderer) {
+ sharedRenderer.dispose()
+ sharedRenderer = null
+ }
}
export async function cleanupUnusedPreviews(skins: Skin[]): Promise {
- const validKeys = new Set()
- const validHeadKeys = new Set()
+ const validKeys = new Set()
+ const validHeadKeys = new Set()
- for (const skin of skins) {
- const key = `${skin.texture_key}+${skin.variant}+${skin.cape_id ?? 'no-cape'}`
- const headKey = `${skin.texture_key}-head`
- validKeys.add(key)
- validHeadKeys.add(headKey)
- }
+ for (const skin of skins) {
+ const key = `${skin.texture_key}+${skin.variant}+${skin.cape_id ?? 'no-cape'}`
+ const headKey = `${skin.texture_key}-head`
+ validKeys.add(key)
+ validHeadKeys.add(headKey)
+ }
- try {
- await skinPreviewStorage.cleanupInvalidKeys(validKeys)
- await headStorage.cleanupInvalidKeys(validHeadKeys)
- } catch (error) {
- console.warn('Failed to cleanup unused skin previews:', error)
- }
+ try {
+ await skinPreviewStorage.cleanupInvalidKeys(validKeys)
+ await headStorage.cleanupInvalidKeys(validHeadKeys)
+ } catch (error) {
+ console.warn('Failed to cleanup unused skin previews:', error)
+ }
}
export async function generatePlayerHeadBlob(skinUrl: string, size: number = 64): Promise {
- return new Promise((resolve, reject) => {
- const img = new Image()
- img.crossOrigin = 'anonymous'
+ return new Promise((resolve, reject) => {
+ const img = new Image()
+ img.crossOrigin = 'anonymous'
- img.onload = () => {
- try {
- const sourceCanvas = document.createElement('canvas')
- const sourceCtx = sourceCanvas.getContext('2d')
+ img.onload = () => {
+ try {
+ const sourceCanvas = document.createElement('canvas')
+ const sourceCtx = sourceCanvas.getContext('2d')
- if (!sourceCtx) {
- throw new Error('Could not get 2D context from source canvas')
- }
+ if (!sourceCtx) {
+ throw new Error('Could not get 2D context from source canvas')
+ }
- sourceCanvas.width = img.width
- sourceCanvas.height = img.height
+ sourceCanvas.width = img.width
+ sourceCanvas.height = img.height
- sourceCtx.drawImage(img, 0, 0)
+ sourceCtx.drawImage(img, 0, 0)
- const outputCanvas = document.createElement('canvas')
- const outputCtx = outputCanvas.getContext('2d')
+ const outputCanvas = document.createElement('canvas')
+ const outputCtx = outputCanvas.getContext('2d')
- if (!outputCtx) {
- throw new Error('Could not get 2D context from output canvas')
- }
+ if (!outputCtx) {
+ throw new Error('Could not get 2D context from output canvas')
+ }
- outputCanvas.width = size
- outputCanvas.height = size
+ outputCanvas.width = size
+ outputCanvas.height = size
- outputCtx.imageSmoothingEnabled = false
+ outputCtx.imageSmoothingEnabled = false
- const headImageData = sourceCtx.getImageData(8, 8, 8, 8)
+ const headImageData = sourceCtx.getImageData(8, 8, 8, 8)
- const headCanvas = document.createElement('canvas')
- const headCtx = headCanvas.getContext('2d')
+ const headCanvas = document.createElement('canvas')
+ const headCtx = headCanvas.getContext('2d')
- if (!headCtx) {
- throw new Error('Could not get 2D context from head canvas')
- }
+ if (!headCtx) {
+ throw new Error('Could not get 2D context from head canvas')
+ }
- headCanvas.width = 8
- headCanvas.height = 8
- headCtx.putImageData(headImageData, 0, 0)
+ headCanvas.width = 8
+ headCanvas.height = 8
+ headCtx.putImageData(headImageData, 0, 0)
- outputCtx.drawImage(headCanvas, 0, 0, 8, 8, 0, 0, size, size)
+ outputCtx.drawImage(headCanvas, 0, 0, 8, 8, 0, 0, size, size)
- const hatImageData = sourceCtx.getImageData(40, 8, 8, 8)
+ const hatImageData = sourceCtx.getImageData(40, 8, 8, 8)
- const hatCanvas = document.createElement('canvas')
- const hatCtx = hatCanvas.getContext('2d')
+ const hatCanvas = document.createElement('canvas')
+ const hatCtx = hatCanvas.getContext('2d')
- if (!hatCtx) {
- throw new Error('Could not get 2D context from hat canvas')
- }
+ if (!hatCtx) {
+ throw new Error('Could not get 2D context from hat canvas')
+ }
- hatCanvas.width = 8
- hatCanvas.height = 8
- hatCtx.putImageData(hatImageData, 0, 0)
+ hatCanvas.width = 8
+ hatCanvas.height = 8
+ hatCtx.putImageData(hatImageData, 0, 0)
- const hatPixels = hatImageData.data
- let hasHat = false
+ const hatPixels = hatImageData.data
+ let hasHat = false
- for (let i = 3; i < hatPixels.length; i += 4) {
- if (hatPixels[i] > 0) {
- hasHat = true
- break
- }
- }
+ for (let i = 3; i < hatPixels.length; i += 4) {
+ if (hatPixels[i] > 0) {
+ hasHat = true
+ break
+ }
+ }
- if (hasHat) {
- outputCtx.drawImage(hatCanvas, 0, 0, 8, 8, 0, 0, size, size)
- }
+ if (hasHat) {
+ outputCtx.drawImage(hatCanvas, 0, 0, 8, 8, 0, 0, size, size)
+ }
- outputCanvas.toBlob(
- (blob) => {
- if (blob) {
- resolve(blob)
- } else {
- reject(new Error('Failed to create blob from canvas'))
- }
- },
- 'image/webp',
- 0.9,
- )
- } catch (error) {
- reject(error)
- }
- }
+ outputCanvas.toBlob(
+ (blob) => {
+ if (blob) {
+ resolve(blob)
+ } else {
+ reject(new Error('Failed to create blob from canvas'))
+ }
+ },
+ 'image/webp',
+ 0.9,
+ )
+ } catch (error) {
+ reject(error)
+ }
+ }
- img.onerror = () => {
- reject(new Error('Failed to load skin texture image'))
- }
+ img.onerror = () => {
+ reject(new Error('Failed to load skin texture image'))
+ }
- img.src = skinUrl
- })
+ img.src = skinUrl
+ })
}
async function generateHeadRender(skin: Skin): Promise {
- const headKey = `${skin.texture_key}-head`
+ const headKey = `${skin.texture_key}-head`
- if (headBlobUrlMap.has(headKey)) {
- if (DEBUG_MODE) {
- const url = headBlobUrlMap.get(headKey)!
- URL.revokeObjectURL(url)
- headBlobUrlMap.delete(headKey)
- } else {
- return headBlobUrlMap.get(headKey)!
- }
- }
+ if (headBlobUrlMap.has(headKey)) {
+ if (DEBUG_MODE) {
+ const url = headBlobUrlMap.get(headKey)!
+ URL.revokeObjectURL(url)
+ headBlobUrlMap.delete(headKey)
+ } else {
+ return headBlobUrlMap.get(headKey)!
+ }
+ }
- const skinUrl = await get_normalized_skin_texture(skin)
- const headBlob = await generatePlayerHeadBlob(skinUrl, 64)
- const headUrl = URL.createObjectURL(headBlob)
+ const skinUrl = await get_normalized_skin_texture(skin)
+ const headBlob = await generatePlayerHeadBlob(skinUrl, 64)
+ const headUrl = URL.createObjectURL(headBlob)
- headBlobUrlMap.set(headKey, headUrl)
+ headBlobUrlMap.set(headKey, headUrl)
- try {
- await headStorage.store(headKey, headBlob)
- } catch (error) {
- console.warn('Failed to store head render in persistent storage:', error)
- }
+ try {
+ await headStorage.store(headKey, headBlob)
+ } catch (error) {
+ console.warn('Failed to store head render in persistent storage:', error)
+ }
- return headUrl
+ return headUrl
}
export async function getPlayerHeadUrl(skin: Skin): Promise {
- return await generateHeadRender(skin)
+ return await generateHeadRender(skin)
}
export async function generateSkinPreviews(skins: Skin[], capes: Cape[]): Promise {
- try {
- const skinKeys = skins.map(
- (skin) => `${skin.texture_key}+${skin.variant}+${skin.cape_id ?? 'no-cape'}`,
- )
- const headKeys = skins.map((skin) => `${skin.texture_key}-head`)
+ try {
+ const skinKeys = skins.map(
+ (skin) => `${skin.texture_key}+${skin.variant}+${skin.cape_id ?? 'no-cape'}`,
+ )
+ const headKeys = skins.map((skin) => `${skin.texture_key}-head`)
- const [cachedSkinPreviews, cachedHeadPreviews] = await Promise.all([
- skinPreviewStorage.batchRetrieve(skinKeys),
- headStorage.batchRetrieve(headKeys),
- ])
+ const [cachedSkinPreviews, cachedHeadPreviews] = await Promise.all([
+ skinPreviewStorage.batchRetrieve(skinKeys),
+ headStorage.batchRetrieve(headKeys),
+ ])
- for (let i = 0; i < skins.length; i++) {
- const skinKey = skinKeys[i]
- const headKey = headKeys[i]
+ for (let i = 0; i < skins.length; i++) {
+ const skinKey = skinKeys[i]
+ const headKey = headKeys[i]
- const rawCached = cachedSkinPreviews[skinKey]
- if (rawCached) {
- const cached: RenderResult = {
- forwards: URL.createObjectURL(rawCached.forwards),
- backwards: URL.createObjectURL(rawCached.backwards),
- }
- skinBlobUrlMap.set(skinKey, cached)
- }
+ const rawCached = cachedSkinPreviews[skinKey]
+ if (rawCached) {
+ const cached: RenderResult = {
+ forwards: URL.createObjectURL(rawCached.forwards),
+ backwards: URL.createObjectURL(rawCached.backwards),
+ }
+ skinBlobUrlMap.set(skinKey, cached)
+ }
- const cachedHead = cachedHeadPreviews[headKey]
- if (cachedHead) {
- headBlobUrlMap.set(headKey, URL.createObjectURL(cachedHead))
- }
- }
+ const cachedHead = cachedHeadPreviews[headKey]
+ if (cachedHead) {
+ headBlobUrlMap.set(headKey, URL.createObjectURL(cachedHead))
+ }
+ }
- for (const skin of skins) {
- const key = `${skin.texture_key}+${skin.variant}+${skin.cape_id ?? 'no-cape'}`
+ for (const skin of skins) {
+ const key = `${skin.texture_key}+${skin.variant}+${skin.cape_id ?? 'no-cape'}`
- if (skinBlobUrlMap.has(key)) {
- if (DEBUG_MODE) {
- const result = skinBlobUrlMap.get(key)!
- URL.revokeObjectURL(result.forwards)
- URL.revokeObjectURL(result.backwards)
- skinBlobUrlMap.delete(key)
- } else continue
- }
+ if (skinBlobUrlMap.has(key)) {
+ if (DEBUG_MODE) {
+ const result = skinBlobUrlMap.get(key)!
+ URL.revokeObjectURL(result.forwards)
+ URL.revokeObjectURL(result.backwards)
+ skinBlobUrlMap.delete(key)
+ } else continue
+ }
- const renderer = getSharedRenderer()
+ const renderer = getSharedRenderer()
- let variant = skin.variant
- if (variant === 'UNKNOWN') {
- try {
- variant = await determineModelType(skin.texture)
- } catch (error) {
- console.error(`Failed to determine model type for skin ${key}:`, error)
- variant = 'CLASSIC'
- }
- }
+ let variant = skin.variant
+ if (variant === 'UNKNOWN') {
+ try {
+ variant = await determineModelType(skin.texture)
+ } catch (error) {
+ console.error(`Failed to determine model type for skin ${key}:`, error)
+ variant = 'CLASSIC'
+ }
+ }
- const modelUrl = getModelUrlForVariant(variant)
- const cape: Cape | undefined = capes.find((_cape) => _cape.id === skin.cape_id)
- const rawRenderResult = await renderer.renderSkin(
- await get_normalized_skin_texture(skin),
- modelUrl,
- cape?.texture,
- )
+ const modelUrl = getModelUrlForVariant(variant)
+ const cape: Cape | undefined = capes.find((_cape) => _cape.id === skin.cape_id)
+ const rawRenderResult = await renderer.renderSkin(
+ await get_normalized_skin_texture(skin),
+ modelUrl,
+ cape?.texture,
+ )
- const renderResult: RenderResult = {
- forwards: URL.createObjectURL(rawRenderResult.forwards),
- backwards: URL.createObjectURL(rawRenderResult.backwards),
- }
+ const renderResult: RenderResult = {
+ forwards: URL.createObjectURL(rawRenderResult.forwards),
+ backwards: URL.createObjectURL(rawRenderResult.backwards),
+ }
- skinBlobUrlMap.set(key, renderResult)
+ skinBlobUrlMap.set(key, renderResult)
- try {
- await skinPreviewStorage.store(key, rawRenderResult)
- } catch (error) {
- console.warn('Failed to store skin preview in persistent storage:', error)
- }
+ try {
+ await skinPreviewStorage.store(key, rawRenderResult)
+ } catch (error) {
+ console.warn('Failed to store skin preview in persistent storage:', error)
+ }
- const headKey = `${skin.texture_key}-head`
- if (!headBlobUrlMap.has(headKey)) {
- await generateHeadRender(skin)
- }
- }
- } finally {
- disposeSharedRenderer()
- await cleanupUnusedPreviews(skins)
+ const headKey = `${skin.texture_key}-head`
+ if (!headBlobUrlMap.has(headKey)) {
+ await generateHeadRender(skin)
+ }
+ }
+ } finally {
+ disposeSharedRenderer()
+ await cleanupUnusedPreviews(skins)
- await skinPreviewStorage.debugCalculateStorage()
- await headStorage.debugCalculateStorage()
- }
+ await skinPreviewStorage.debugCalculateStorage()
+ await headStorage.debugCalculateStorage()
+ }
}
diff --git a/apps/app-frontend/src/helpers/settings.ts b/apps/app-frontend/src/helpers/settings.ts
index c256575a..f9d46a61 100644
--- a/apps/app-frontend/src/helpers/settings.ts
+++ b/apps/app-frontend/src/helpers/settings.ts
@@ -4,8 +4,9 @@
* and deserialized into a usable JS object.
*/
import { invoke } from '@tauri-apps/api/core'
-import type { ColorTheme, FeatureFlag } from '@/store/theme.ts'
+
import type { Hooks, MemorySettings, WindowSize } from '@/helpers/types'
+import type { ColorTheme, FeatureFlag } from '@/store/theme.ts'
// Settings object
/*
@@ -31,49 +32,49 @@ Memorysettings {
*/
export type AppSettings = {
- max_concurrent_downloads: number
- max_concurrent_writes: number
+ max_concurrent_downloads: number
+ max_concurrent_writes: number
- theme: ColorTheme
- default_page: 'home' | 'library'
- collapsed_navigation: boolean
- hide_nametag_skins_page: boolean
- advanced_rendering: boolean
- native_decorations: boolean
- toggle_sidebar: boolean
+ theme: ColorTheme
+ default_page: 'home' | 'library'
+ collapsed_navigation: boolean
+ hide_nametag_skins_page: boolean
+ advanced_rendering: boolean
+ native_decorations: boolean
+ toggle_sidebar: boolean
- telemetry: boolean
- discord_rpc: boolean
- personalized_ads: boolean
+ telemetry: boolean
+ discord_rpc: boolean
+ personalized_ads: boolean
- onboarded: boolean
+ onboarded: boolean
- extra_launch_args: string[]
- custom_env_vars: [string, string][]
- memory: MemorySettings
- force_fullscreen: boolean
- game_resolution: WindowSize
- hide_on_process_start: boolean
- hooks: Hooks
+ extra_launch_args: string[]
+ custom_env_vars: [string, string][]
+ memory: MemorySettings
+ force_fullscreen: boolean
+ game_resolution: WindowSize
+ hide_on_process_start: boolean
+ hooks: Hooks
- custom_dir?: string | null
- prev_custom_dir?: string | null
- migrated: boolean
+ custom_dir?: string | null
+ prev_custom_dir?: string | null
+ migrated: boolean
- developer_mode: boolean
- feature_flags: Record
+ developer_mode: boolean
+ feature_flags: Record
}
// Get full settings object
export async function get() {
- return (await invoke('plugin:settings|settings_get')) as AppSettings
+ return (await invoke('plugin:settings|settings_get')) as AppSettings
}
// Set full settings object
export async function set(settings: AppSettings) {
- return await invoke('plugin:settings|settings_set', { settings })
+ return await invoke('plugin:settings|settings_set', { settings })
}
export async function cancel_directory_change(): Promise {
- return await invoke('plugin:settings|cancel_directory_change')
+ return await invoke('plugin:settings|cancel_directory_change')
}
diff --git a/apps/app-frontend/src/helpers/skins.ts b/apps/app-frontend/src/helpers/skins.ts
index e31b67b1..75dea749 100644
--- a/apps/app-frontend/src/helpers/skins.ts
+++ b/apps/app-frontend/src/helpers/skins.ts
@@ -1,164 +1,163 @@
-import { invoke } from '@tauri-apps/api/core'
-import { handleError } from '@/store/notifications'
import { arrayBufferToBase64 } from '@modrinth/utils'
+import { invoke } from '@tauri-apps/api/core'
export interface Cape {
- id: string
- name: string
- texture: string
- is_default: boolean
- is_equipped: boolean
+ id: string
+ name: string
+ texture: string
+ is_default: boolean
+ is_equipped: boolean
}
export type SkinModel = 'CLASSIC' | 'SLIM' | 'UNKNOWN'
export type SkinSource = 'default' | 'custom_external' | 'custom'
export interface Skin {
- texture_key: string
- name?: string
- variant: SkinModel
- cape_id?: string
- texture: string
- source: SkinSource
- is_equipped: boolean
+ texture_key: string
+ name?: string
+ variant: SkinModel
+ cape_id?: string
+ texture: string
+ source: SkinSource
+ is_equipped: boolean
}
export const DEFAULT_MODEL_SORTING = ['Steve', 'Alex'] as string[]
export const DEFAULT_MODELS: Record = {
- Steve: 'CLASSIC',
- Alex: 'SLIM',
- Zuri: 'CLASSIC',
- Sunny: 'CLASSIC',
- Noor: 'SLIM',
- Makena: 'SLIM',
- Kai: 'CLASSIC',
- Efe: 'SLIM',
- Ari: 'CLASSIC',
+ Steve: 'CLASSIC',
+ Alex: 'SLIM',
+ Zuri: 'CLASSIC',
+ Sunny: 'CLASSIC',
+ Noor: 'SLIM',
+ Makena: 'SLIM',
+ Kai: 'CLASSIC',
+ Efe: 'SLIM',
+ Ari: 'CLASSIC',
}
export function filterSavedSkins(list: Skin[]) {
- const customSkins = list.filter((s) => s.source !== 'default')
- fixUnknownSkins(customSkins).catch(handleError)
- return customSkins
+ const customSkins = list.filter((s) => s.source !== 'default')
+ fixUnknownSkins(customSkins)
+ return customSkins
}
export async function determineModelType(texture: string): Promise<'SLIM' | 'CLASSIC'> {
- return new Promise((resolve, reject) => {
- const canvas = document.createElement('canvas')
- const context = canvas.getContext('2d')
+ return new Promise((resolve, reject) => {
+ const canvas = document.createElement('canvas')
+ const context = canvas.getContext('2d')
- if (!context) {
- return reject(new Error('Failed to create canvas rendering context.'))
- }
+ if (!context) {
+ return reject(new Error('Failed to create canvas rendering context.'))
+ }
- const image = new Image()
- image.crossOrigin = 'anonymous'
- image.src = texture
+ const image = new Image()
+ image.crossOrigin = 'anonymous'
+ image.src = texture
- image.onload = () => {
- canvas.width = image.width
- canvas.height = image.height
+ image.onload = () => {
+ canvas.width = image.width
+ canvas.height = image.height
- context.drawImage(image, 0, 0)
+ context.drawImage(image, 0, 0)
- const armX = 54
- const armY = 20
- const armWidth = 2
- const armHeight = 12
- const imageData = context.getImageData(armX, armY, armWidth, armHeight).data
- for (let alphaIndex = 3; alphaIndex < imageData.length; alphaIndex += 4) {
- if (imageData[alphaIndex] !== 0) {
- resolve('CLASSIC')
- return
- }
- }
+ const armX = 54
+ const armY = 20
+ const armWidth = 2
+ const armHeight = 12
+ const imageData = context.getImageData(armX, armY, armWidth, armHeight).data
+ for (let alphaIndex = 3; alphaIndex < imageData.length; alphaIndex += 4) {
+ if (imageData[alphaIndex] !== 0) {
+ resolve('CLASSIC')
+ return
+ }
+ }
- canvas.remove()
- resolve('SLIM')
- }
+ canvas.remove()
+ resolve('SLIM')
+ }
- image.onerror = () => {
- canvas.remove()
- reject(new Error('Failed to load the image.'))
- }
- })
+ image.onerror = () => {
+ canvas.remove()
+ reject(new Error('Failed to load the image.'))
+ }
+ })
}
export async function fixUnknownSkins(list: Skin[]) {
- const unknownSkins = list.filter((s) => s.variant === 'UNKNOWN')
- for (const unknownSkin of unknownSkins) {
- unknownSkin.variant = await determineModelType(unknownSkin.texture)
- }
+ const unknownSkins = list.filter((s) => s.variant === 'UNKNOWN')
+ for (const unknownSkin of unknownSkins) {
+ unknownSkin.variant = await determineModelType(unknownSkin.texture)
+ }
}
export function filterDefaultSkins(list: Skin[]) {
- return list
- .filter(
- (s) =>
- s.source === 'default' &&
- (!s.name || !(s.name in DEFAULT_MODELS) || s.variant === DEFAULT_MODELS[s.name]),
- )
- .sort((a, b) => {
- const aIndex = a.name ? DEFAULT_MODEL_SORTING.indexOf(a.name) : -1
- const bIndex = b.name ? DEFAULT_MODEL_SORTING.indexOf(b.name) : -1
- return (aIndex === -1 ? Infinity : aIndex) - (bIndex === -1 ? Infinity : bIndex)
- })
+ return list
+ .filter(
+ (s) =>
+ s.source === 'default' &&
+ (!s.name || !(s.name in DEFAULT_MODELS) || s.variant === DEFAULT_MODELS[s.name]),
+ )
+ .sort((a, b) => {
+ const aIndex = a.name ? DEFAULT_MODEL_SORTING.indexOf(a.name) : -1
+ const bIndex = b.name ? DEFAULT_MODEL_SORTING.indexOf(b.name) : -1
+ return (aIndex === -1 ? Infinity : aIndex) - (bIndex === -1 ? Infinity : bIndex)
+ })
}
export async function get_available_capes(): Promise {
- return invoke('plugin:minecraft-skins|get_available_capes', {})
+ return invoke('plugin:minecraft-skins|get_available_capes', {})
}
export async function get_available_skins(): Promise {
- return invoke('plugin:minecraft-skins|get_available_skins', {})
+ return invoke('plugin:minecraft-skins|get_available_skins', {})
}
export async function add_and_equip_custom_skin(
- textureBlob: Uint8Array,
- variant: SkinModel,
- capeOverride?: Cape,
+ textureBlob: Uint8Array,
+ variant: SkinModel,
+ capeOverride?: Cape,
): Promise {
- await invoke('plugin:minecraft-skins|add_and_equip_custom_skin', {
- textureBlob,
- variant,
- capeOverride,
- })
+ await invoke('plugin:minecraft-skins|add_and_equip_custom_skin', {
+ textureBlob,
+ variant,
+ capeOverride,
+ })
}
export async function set_default_cape(cape?: Cape): Promise {
- await invoke('plugin:minecraft-skins|set_default_cape', {
- cape,
- })
+ await invoke('plugin:minecraft-skins|set_default_cape', {
+ cape,
+ })
}
export async function equip_skin(skin: Skin): Promise {
- await invoke('plugin:minecraft-skins|equip_skin', {
- skin,
- })
+ await invoke('plugin:minecraft-skins|equip_skin', {
+ skin,
+ })
}
export async function remove_custom_skin(skin: Skin): Promise {
- await invoke('plugin:minecraft-skins|remove_custom_skin', {
- skin,
- })
+ await invoke('plugin:minecraft-skins|remove_custom_skin', {
+ skin,
+ })
}
export async function get_normalized_skin_texture(skin: Skin): Promise {
- const data = await normalize_skin_texture(skin.texture)
- const base64 = arrayBufferToBase64(data)
- return `data:image/png;base64,${base64}`
+ const data = await normalize_skin_texture(skin.texture)
+ const base64 = arrayBufferToBase64(data)
+ return `data:image/png;base64,${base64}`
}
export async function normalize_skin_texture(texture: Uint8Array | string): Promise {
- return await invoke('plugin:minecraft-skins|normalize_skin_texture', { texture })
+ return await invoke('plugin:minecraft-skins|normalize_skin_texture', { texture })
}
export async function unequip_skin(): Promise {
- await invoke('plugin:minecraft-skins|unequip_skin')
+ await invoke('plugin:minecraft-skins|unequip_skin')
}
export async function get_dragged_skin_data(path: string): Promise {
- const data = await invoke('plugin:minecraft-skins|get_dragged_skin_data', { path })
- return new Uint8Array(data)
+ const data = await invoke('plugin:minecraft-skins|get_dragged_skin_data', { path })
+ return new Uint8Array(data)
}
diff --git a/apps/app-frontend/src/helpers/state.js b/apps/app-frontend/src/helpers/state.js
index 99b496e1..8d177e47 100644
--- a/apps/app-frontend/src/helpers/state.js
+++ b/apps/app-frontend/src/helpers/state.js
@@ -8,12 +8,12 @@ import { invoke } from '@tauri-apps/api/core'
// Initialize the theseus API state
// This should be called during the initializion/opening of the launcher
export async function initialize_state() {
- return await invoke('initialize_state')
+ return await invoke('initialize_state')
}
// Gets active progress bars
export async function progress_bars_list() {
- return await invoke('plugin:utils|progress_bars_list')
+ return await invoke('plugin:utils|progress_bars_list')
}
// Get opening command
@@ -21,5 +21,5 @@ export async function progress_bars_list() {
// This should be called once and only when the app is done booting up and ready to receive a command
// Returns a Command struct- see events.js
export async function get_opening_command() {
- return await invoke('plugin:utils|get_opening_command')
+ return await invoke('plugin:utils|get_opening_command')
}
diff --git a/apps/app-frontend/src/helpers/storage/head-storage.ts b/apps/app-frontend/src/helpers/storage/head-storage.ts
index e088f575..a7fc56c2 100644
--- a/apps/app-frontend/src/helpers/storage/head-storage.ts
+++ b/apps/app-frontend/src/helpers/storage/head-storage.ts
@@ -1,229 +1,229 @@
interface StoredHead {
- blob: Blob
- timestamp: number
+ blob: Blob
+ timestamp: number
}
export class HeadStorage {
- private dbName = 'head-storage'
- private version = 1
- private db: IDBDatabase | null = null
+ private dbName = 'head-storage'
+ private version = 1
+ private db: IDBDatabase | null = null
- async init(): Promise {
- return new Promise((resolve, reject) => {
- const request = indexedDB.open(this.dbName, this.version)
+ async init(): Promise {
+ return new Promise((resolve, reject) => {
+ const request = indexedDB.open(this.dbName, this.version)
- request.onerror = () => reject(request.error)
- request.onsuccess = () => {
- this.db = request.result
- resolve()
- }
+ request.onerror = () => reject(request.error)
+ request.onsuccess = () => {
+ this.db = request.result
+ resolve()
+ }
- request.onupgradeneeded = () => {
- const db = request.result
- if (!db.objectStoreNames.contains('heads')) {
- db.createObjectStore('heads')
- }
- }
- })
- }
+ request.onupgradeneeded = () => {
+ const db = request.result
+ if (!db.objectStoreNames.contains('heads')) {
+ db.createObjectStore('heads')
+ }
+ }
+ })
+ }
- async store(key: string, blob: Blob): Promise {
- if (!this.db) await this.init()
+ async store(key: string, blob: Blob): Promise {
+ if (!this.db) await this.init()
- const transaction = this.db!.transaction(['heads'], 'readwrite')
- const store = transaction.objectStore('heads')
+ const transaction = this.db!.transaction(['heads'], 'readwrite')
+ const store = transaction.objectStore('heads')
- const storedHead: StoredHead = {
- blob,
- timestamp: Date.now(),
- }
+ const storedHead: StoredHead = {
+ blob,
+ timestamp: Date.now(),
+ }
- return new Promise((resolve, reject) => {
- const request = store.put(storedHead, key)
+ return new Promise((resolve, reject) => {
+ const request = store.put(storedHead, key)
- request.onsuccess = () => resolve()
- request.onerror = () => reject(request.error)
- })
- }
+ request.onsuccess = () => resolve()
+ request.onerror = () => reject(request.error)
+ })
+ }
- async retrieve(key: string): Promise {
- if (!this.db) await this.init()
+ async retrieve(key: string): Promise {
+ if (!this.db) await this.init()
- const transaction = this.db!.transaction(['heads'], 'readonly')
- const store = transaction.objectStore('heads')
+ const transaction = this.db!.transaction(['heads'], 'readonly')
+ const store = transaction.objectStore('heads')
- return new Promise((resolve, reject) => {
- const request = store.get(key)
+ return new Promise((resolve, reject) => {
+ const request = store.get(key)
- request.onsuccess = () => {
- const result = request.result as StoredHead | undefined
+ request.onsuccess = () => {
+ const result = request.result as StoredHead | undefined
- if (!result) {
- resolve(null)
- return
- }
+ if (!result) {
+ resolve(null)
+ return
+ }
- const url = URL.createObjectURL(result.blob)
- resolve(url)
- }
- request.onerror = () => reject(request.error)
- })
- }
+ const url = URL.createObjectURL(result.blob)
+ resolve(url)
+ }
+ request.onerror = () => reject(request.error)
+ })
+ }
- async batchRetrieve(keys: string[]): Promise> {
- if (!this.db) await this.init()
+ async batchRetrieve(keys: string[]): Promise> {
+ if (!this.db) await this.init()
- const transaction = this.db!.transaction(['heads'], 'readonly')
- const store = transaction.objectStore('heads')
- const results: Record = {}
+ const transaction = this.db!.transaction(['heads'], 'readonly')
+ const store = transaction.objectStore('heads')
+ const results: Record = {}
- return new Promise((resolve, _reject) => {
- let completedRequests = 0
+ return new Promise((resolve, _reject) => {
+ let completedRequests = 0
- if (keys.length === 0) {
- resolve(results)
- return
- }
+ if (keys.length === 0) {
+ resolve(results)
+ return
+ }
- for (const key of keys) {
- const request = store.get(key)
+ for (const key of keys) {
+ const request = store.get(key)
- request.onsuccess = () => {
- const result = request.result as StoredHead | undefined
+ request.onsuccess = () => {
+ const result = request.result as StoredHead | undefined
- if (result) {
- results[key] = result.blob
- } else {
- results[key] = null
- }
+ if (result) {
+ results[key] = result.blob
+ } else {
+ results[key] = null
+ }
- completedRequests++
- if (completedRequests === keys.length) {
- resolve(results)
- }
- }
+ completedRequests++
+ if (completedRequests === keys.length) {
+ resolve(results)
+ }
+ }
- request.onerror = () => {
- results[key] = null
- completedRequests++
- if (completedRequests === keys.length) {
- resolve(results)
- }
- }
- }
- })
- }
+ request.onerror = () => {
+ results[key] = null
+ completedRequests++
+ if (completedRequests === keys.length) {
+ resolve(results)
+ }
+ }
+ }
+ })
+ }
- async cleanupInvalidKeys(validKeys: Set): Promise {
- if (!this.db) await this.init()
+ async cleanupInvalidKeys(validKeys: Set): Promise {
+ if (!this.db) await this.init()
- const transaction = this.db!.transaction(['heads'], 'readwrite')
- const store = transaction.objectStore('heads')
- let deletedCount = 0
+ const transaction = this.db!.transaction(['heads'], 'readwrite')
+ const store = transaction.objectStore('heads')
+ let deletedCount = 0
- return new Promise((resolve, reject) => {
- const request = store.openCursor()
+ return new Promise((resolve, reject) => {
+ const request = store.openCursor()
- request.onsuccess = (event) => {
- const cursor = (event.target as IDBRequest).result
+ request.onsuccess = (event) => {
+ const cursor = (event.target as IDBRequest).result
- if (cursor) {
- const key = cursor.primaryKey as string
+ if (cursor) {
+ const key = cursor.primaryKey as string
- if (!validKeys.has(key)) {
- const deleteRequest = cursor.delete()
- deleteRequest.onsuccess = () => {
- deletedCount++
- }
- deleteRequest.onerror = () => {
- console.warn('Failed to delete invalid head entry:', key)
- }
- }
+ if (!validKeys.has(key)) {
+ const deleteRequest = cursor.delete()
+ deleteRequest.onsuccess = () => {
+ deletedCount++
+ }
+ deleteRequest.onerror = () => {
+ console.warn('Failed to delete invalid head entry:', key)
+ }
+ }
- cursor.continue()
- } else {
- resolve(deletedCount)
- }
- }
+ cursor.continue()
+ } else {
+ resolve(deletedCount)
+ }
+ }
- request.onerror = () => reject(request.error)
- })
- }
+ request.onerror = () => reject(request.error)
+ })
+ }
- async debugCalculateStorage(): Promise {
- if (!this.db) await this.init()
+ async debugCalculateStorage(): Promise {
+ if (!this.db) await this.init()
- const transaction = this.db!.transaction(['heads'], 'readonly')
- const store = transaction.objectStore('heads')
+ const transaction = this.db!.transaction(['heads'], 'readonly')
+ const store = transaction.objectStore('heads')
- let totalSize = 0
- let count = 0
- const entries: Array<{ key: string; size: number }> = []
+ let totalSize = 0
+ let count = 0
+ const entries: Array<{ key: string; size: number }> = []
- return new Promise((resolve, reject) => {
- const request = store.openCursor()
+ return new Promise((resolve, reject) => {
+ const request = store.openCursor()
- request.onsuccess = (event) => {
- const cursor = (event.target as IDBRequest).result
+ request.onsuccess = (event) => {
+ const cursor = (event.target as IDBRequest).result
- if (cursor) {
- const key = cursor.primaryKey as string
- const value = cursor.value as StoredHead
+ if (cursor) {
+ const key = cursor.primaryKey as string
+ const value = cursor.value as StoredHead
- const entrySize = value.blob.size
- totalSize += entrySize
- count++
+ const entrySize = value.blob.size
+ totalSize += entrySize
+ count++
- entries.push({
- key,
- size: entrySize,
- })
+ entries.push({
+ key,
+ size: entrySize,
+ })
- cursor.continue()
- } else {
- console.group('🗄️ Head Storage Debug Info')
- console.log(`Total entries: ${count}`)
- console.log(`Total size: ${(totalSize / 1024 / 1024).toFixed(2)} MB`)
- console.log(
- `Average size per entry: ${count > 0 ? (totalSize / count / 1024).toFixed(2) : 0} KB`,
- )
+ cursor.continue()
+ } else {
+ console.group('🗄️ Head Storage Debug Info')
+ console.log(`Total entries: ${count}`)
+ console.log(`Total size: ${(totalSize / 1024 / 1024).toFixed(2)} MB`)
+ console.log(
+ `Average size per entry: ${count > 0 ? (totalSize / count / 1024).toFixed(2) : 0} KB`,
+ )
- if (entries.length > 0) {
- const sortedEntries = entries.sort((a, b) => b.size - a.size)
- console.log(
- 'Largest entry:',
- sortedEntries[0].key,
- '(' + (sortedEntries[0].size / 1024).toFixed(2) + ' KB)',
- )
- console.log(
- 'Smallest entry:',
- sortedEntries[sortedEntries.length - 1].key,
- '(' + (sortedEntries[sortedEntries.length - 1].size / 1024).toFixed(2) + ' KB)',
- )
- }
+ if (entries.length > 0) {
+ const sortedEntries = entries.sort((a, b) => b.size - a.size)
+ console.log(
+ 'Largest entry:',
+ sortedEntries[0].key,
+ '(' + (sortedEntries[0].size / 1024).toFixed(2) + ' KB)',
+ )
+ console.log(
+ 'Smallest entry:',
+ sortedEntries[sortedEntries.length - 1].key,
+ '(' + (sortedEntries[sortedEntries.length - 1].size / 1024).toFixed(2) + ' KB)',
+ )
+ }
- console.groupEnd()
- resolve()
- }
- }
+ console.groupEnd()
+ resolve()
+ }
+ }
- request.onerror = () => reject(request.error)
- })
- }
+ request.onerror = () => reject(request.error)
+ })
+ }
- async clearAll(): Promise {
- if (!this.db) await this.init()
+ async clearAll(): Promise {
+ if (!this.db) await this.init()
- const transaction = this.db!.transaction(['heads'], 'readwrite')
- const store = transaction.objectStore('heads')
+ const transaction = this.db!.transaction(['heads'], 'readwrite')
+ const store = transaction.objectStore('heads')
- return new Promise((resolve, reject) => {
- const request = store.clear()
+ return new Promise((resolve, reject) => {
+ const request = store.clear()
- request.onsuccess = () => resolve()
- request.onerror = () => reject(request.error)
- })
- }
+ request.onsuccess = () => resolve()
+ request.onerror = () => reject(request.error)
+ })
+ }
}
export const headStorage = new HeadStorage()
diff --git a/apps/app-frontend/src/helpers/storage/skin-preview-storage.ts b/apps/app-frontend/src/helpers/storage/skin-preview-storage.ts
index bcf27c8c..29bc2552 100644
--- a/apps/app-frontend/src/helpers/storage/skin-preview-storage.ts
+++ b/apps/app-frontend/src/helpers/storage/skin-preview-storage.ts
@@ -1,218 +1,218 @@
import type { RawRenderResult } from '../rendering/batch-skin-renderer'
interface StoredPreview {
- forwards: Blob
- backwards: Blob
- timestamp: number
+ forwards: Blob
+ backwards: Blob
+ timestamp: number
}
export class SkinPreviewStorage {
- private dbName = 'skin-previews'
- private version = 1
- private db: IDBDatabase | null = null
+ private dbName = 'skin-previews'
+ private version = 1
+ private db: IDBDatabase | null = null
- async init(): Promise {
- return new Promise((resolve, reject) => {
- const request = indexedDB.open(this.dbName, this.version)
+ async init(): Promise {
+ return new Promise((resolve, reject) => {
+ const request = indexedDB.open(this.dbName, this.version)
- request.onerror = () => reject(request.error)
- request.onsuccess = () => {
- this.db = request.result
- resolve()
- }
+ request.onerror = () => reject(request.error)
+ request.onsuccess = () => {
+ this.db = request.result
+ resolve()
+ }
- request.onupgradeneeded = () => {
- const db = request.result
- if (!db.objectStoreNames.contains('previews')) {
- db.createObjectStore('previews')
- }
- }
- })
- }
+ request.onupgradeneeded = () => {
+ const db = request.result
+ if (!db.objectStoreNames.contains('previews')) {
+ db.createObjectStore('previews')
+ }
+ }
+ })
+ }
- async store(key: string, result: RawRenderResult): Promise {
- if (!this.db) await this.init()
+ async store(key: string, result: RawRenderResult): Promise {
+ if (!this.db) await this.init()
- const transaction = this.db!.transaction(['previews'], 'readwrite')
- const store = transaction.objectStore('previews')
+ const transaction = this.db!.transaction(['previews'], 'readwrite')
+ const store = transaction.objectStore('previews')
- const storedPreview: StoredPreview = {
- forwards: result.forwards,
- backwards: result.backwards,
- timestamp: Date.now(),
- }
+ const storedPreview: StoredPreview = {
+ forwards: result.forwards,
+ backwards: result.backwards,
+ timestamp: Date.now(),
+ }
- return new Promise((resolve, reject) => {
- const request = store.put(storedPreview, key)
+ return new Promise((resolve, reject) => {
+ const request = store.put(storedPreview, key)
- request.onsuccess = () => resolve()
- request.onerror = () => reject(request.error)
- })
- }
+ request.onsuccess = () => resolve()
+ request.onerror = () => reject(request.error)
+ })
+ }
- async retrieve(key: string): Promise {
- if (!this.db) await this.init()
+ async retrieve(key: string): Promise {
+ if (!this.db) await this.init()
- const transaction = this.db!.transaction(['previews'], 'readonly')
- const store = transaction.objectStore('previews')
+ const transaction = this.db!.transaction(['previews'], 'readonly')
+ const store = transaction.objectStore('previews')
- return new Promise((resolve, reject) => {
- const request = store.get(key)
+ return new Promise((resolve, reject) => {
+ const request = store.get(key)
- request.onsuccess = () => {
- const result = request.result as StoredPreview | undefined
+ request.onsuccess = () => {
+ const result = request.result as StoredPreview | undefined
- if (!result) {
- resolve(null)
- return
- }
+ if (!result) {
+ resolve(null)
+ return
+ }
- resolve({ forwards: result.forwards, backwards: result.backwards })
- }
- request.onerror = () => reject(request.error)
- })
- }
+ resolve({ forwards: result.forwards, backwards: result.backwards })
+ }
+ request.onerror = () => reject(request.error)
+ })
+ }
- async batchRetrieve(keys: string[]): Promise> {
- if (!this.db) await this.init()
+ async batchRetrieve(keys: string[]): Promise> {
+ if (!this.db) await this.init()
- const transaction = this.db!.transaction(['previews'], 'readonly')
- const store = transaction.objectStore('previews')
- const results: Record = {}
+ const transaction = this.db!.transaction(['previews'], 'readonly')
+ const store = transaction.objectStore('previews')
+ const results: Record = {}
- return new Promise((resolve, _reject) => {
- let completedRequests = 0
+ return new Promise((resolve, _reject) => {
+ let completedRequests = 0
- if (keys.length === 0) {
- resolve(results)
- return
- }
+ if (keys.length === 0) {
+ resolve(results)
+ return
+ }
- for (const key of keys) {
- const request = store.get(key)
+ for (const key of keys) {
+ const request = store.get(key)
- request.onsuccess = () => {
- const result = request.result as StoredPreview | undefined
+ request.onsuccess = () => {
+ const result = request.result as StoredPreview | undefined
- if (result) {
- results[key] = { forwards: result.forwards, backwards: result.backwards }
- } else {
- results[key] = null
- }
+ if (result) {
+ results[key] = { forwards: result.forwards, backwards: result.backwards }
+ } else {
+ results[key] = null
+ }
- completedRequests++
- if (completedRequests === keys.length) {
- resolve(results)
- }
- }
+ completedRequests++
+ if (completedRequests === keys.length) {
+ resolve(results)
+ }
+ }
- request.onerror = () => {
- results[key] = null
- completedRequests++
- if (completedRequests === keys.length) {
- resolve(results)
- }
- }
- }
- })
- }
+ request.onerror = () => {
+ results[key] = null
+ completedRequests++
+ if (completedRequests === keys.length) {
+ resolve(results)
+ }
+ }
+ }
+ })
+ }
- async cleanupInvalidKeys(validKeys: Set): Promise {
- if (!this.db) await this.init()
+ async cleanupInvalidKeys(validKeys: Set): Promise {
+ if (!this.db) await this.init()
- const transaction = this.db!.transaction(['previews'], 'readwrite')
- const store = transaction.objectStore('previews')
- let deletedCount = 0
+ const transaction = this.db!.transaction(['previews'], 'readwrite')
+ const store = transaction.objectStore('previews')
+ let deletedCount = 0
- return new Promise((resolve, reject) => {
- const request = store.openCursor()
+ return new Promise((resolve, reject) => {
+ const request = store.openCursor()
- request.onsuccess = (event) => {
- const cursor = (event.target as IDBRequest).result
+ request.onsuccess = (event) => {
+ const cursor = (event.target as IDBRequest).result
- if (cursor) {
- const key = cursor.primaryKey as string
+ if (cursor) {
+ const key = cursor.primaryKey as string
- if (!validKeys.has(key)) {
- const deleteRequest = cursor.delete()
- deleteRequest.onsuccess = () => {
- deletedCount++
- }
- deleteRequest.onerror = () => {
- console.warn('Failed to delete invalid entry:', key)
- }
- }
+ if (!validKeys.has(key)) {
+ const deleteRequest = cursor.delete()
+ deleteRequest.onsuccess = () => {
+ deletedCount++
+ }
+ deleteRequest.onerror = () => {
+ console.warn('Failed to delete invalid entry:', key)
+ }
+ }
- cursor.continue()
- } else {
- resolve(deletedCount)
- }
- }
+ cursor.continue()
+ } else {
+ resolve(deletedCount)
+ }
+ }
- request.onerror = () => reject(request.error)
- })
- }
+ request.onerror = () => reject(request.error)
+ })
+ }
- async debugCalculateStorage(): Promise {
- if (!this.db) await this.init()
+ async debugCalculateStorage(): Promise {
+ if (!this.db) await this.init()
- const transaction = this.db!.transaction(['previews'], 'readonly')
- const store = transaction.objectStore('previews')
+ const transaction = this.db!.transaction(['previews'], 'readonly')
+ const store = transaction.objectStore('previews')
- let totalSize = 0
- let count = 0
- const entries: Array<{ key: string; size: number }> = []
+ let totalSize = 0
+ let count = 0
+ const entries: Array<{ key: string; size: number }> = []
- return new Promise((resolve, reject) => {
- const request = store.openCursor()
+ return new Promise((resolve, reject) => {
+ const request = store.openCursor()
- request.onsuccess = (event) => {
- const cursor = (event.target as IDBRequest).result
+ request.onsuccess = (event) => {
+ const cursor = (event.target as IDBRequest).result
- if (cursor) {
- const key = cursor.primaryKey as string
- const value = cursor.value as StoredPreview
+ if (cursor) {
+ const key = cursor.primaryKey as string
+ const value = cursor.value as StoredPreview
- const entrySize = value.forwards.size + value.backwards.size
- totalSize += entrySize
- count++
+ const entrySize = value.forwards.size + value.backwards.size
+ totalSize += entrySize
+ count++
- entries.push({
- key,
- size: entrySize,
- })
+ entries.push({
+ key,
+ size: entrySize,
+ })
- cursor.continue()
- } else {
- console.group('🗄️ Skin Preview Storage Debug Info')
- console.log(`Total entries: ${count}`)
- console.log(`Total size: ${(totalSize / 1024 / 1024).toFixed(2)} MB`)
- console.log(
- `Average size per entry: ${count > 0 ? (totalSize / count / 1024).toFixed(2) : 0} KB`,
- )
+ cursor.continue()
+ } else {
+ console.group('🗄️ Skin Preview Storage Debug Info')
+ console.log(`Total entries: ${count}`)
+ console.log(`Total size: ${(totalSize / 1024 / 1024).toFixed(2)} MB`)
+ console.log(
+ `Average size per entry: ${count > 0 ? (totalSize / count / 1024).toFixed(2) : 0} KB`,
+ )
- if (entries.length > 0) {
- const sortedEntries = entries.sort((a, b) => b.size - a.size)
- console.log(
- 'Largest entry:',
- sortedEntries[0].key,
- '(' + (sortedEntries[0].size / 1024).toFixed(2) + ' KB)',
- )
- console.log(
- 'Smallest entry:',
- sortedEntries[sortedEntries.length - 1].key,
- '(' + (sortedEntries[sortedEntries.length - 1].size / 1024).toFixed(2) + ' KB)',
- )
- }
+ if (entries.length > 0) {
+ const sortedEntries = entries.sort((a, b) => b.size - a.size)
+ console.log(
+ 'Largest entry:',
+ sortedEntries[0].key,
+ '(' + (sortedEntries[0].size / 1024).toFixed(2) + ' KB)',
+ )
+ console.log(
+ 'Smallest entry:',
+ sortedEntries[sortedEntries.length - 1].key,
+ '(' + (sortedEntries[sortedEntries.length - 1].size / 1024).toFixed(2) + ' KB)',
+ )
+ }
- console.groupEnd()
- resolve()
- }
- }
+ console.groupEnd()
+ resolve()
+ }
+ }
- request.onerror = () => reject(request.error)
- })
- }
+ request.onerror = () => reject(request.error)
+ })
+ }
}
export const skinPreviewStorage = new SkinPreviewStorage()
diff --git a/apps/app-frontend/src/helpers/tags.js b/apps/app-frontend/src/helpers/tags.js
index 07ee7589..42fd29c5 100644
--- a/apps/app-frontend/src/helpers/tags.js
+++ b/apps/app-frontend/src/helpers/tags.js
@@ -7,25 +7,25 @@ import { invoke } from '@tauri-apps/api/core'
// Gets cached category tags
export async function get_categories() {
- return await invoke('plugin:tags|tags_get_categories')
+ return await invoke('plugin:tags|tags_get_categories')
}
// Gets cached loaders tags
export async function get_loaders() {
- return await invoke('plugin:tags|tags_get_loaders')
+ return await invoke('plugin:tags|tags_get_loaders')
}
// Gets cached game_versions tags
export async function get_game_versions() {
- return await invoke('plugin:tags|tags_get_game_versions')
+ return await invoke('plugin:tags|tags_get_game_versions')
}
// Gets cached donation_platforms tags
export async function get_donation_platforms() {
- return await invoke('plugin:tags|tags_get_donation_platforms')
+ return await invoke('plugin:tags|tags_get_donation_platforms')
}
// Gets cached licenses tags
export async function get_report_types() {
- return await invoke('plugin:tags|tags_get_report_types')
+ return await invoke('plugin:tags|tags_get_report_types')
}
diff --git a/apps/app-frontend/src/helpers/types.d.ts b/apps/app-frontend/src/helpers/types.d.ts
index aa60ec2f..8e6ac8b4 100644
--- a/apps/app-frontend/src/helpers/types.d.ts
+++ b/apps/app-frontend/src/helpers/types.d.ts
@@ -1,142 +1,142 @@
import type { ModrinthId } from '@modrinth/utils'
type GameInstance = {
- path: string
- install_stage: InstallStage
+ path: string
+ install_stage: InstallStage
- name: string
- icon_path?: string
+ name: string
+ icon_path?: string
- game_version: string
- loader: InstanceLoader
- loader_version?: string
+ game_version: string
+ loader: InstanceLoader
+ loader_version?: string
- groups: string[]
+ groups: string[]
- linked_data?: LinkedData
+ linked_data?: LinkedData
- created: Date
- modified: Date
- last_played?: Date
+ created: Date
+ modified: Date
+ last_played?: Date
- submitted_time_played: number
- recent_time_played: number
+ submitted_time_played: number
+ recent_time_played: number
- java_path?: string
- extra_launch_args?: string[]
- custom_env_vars?: [string, string][]
+ java_path?: string
+ extra_launch_args?: string[]
+ custom_env_vars?: [string, string][]
- memory?: MemorySettings
- force_fullscreen?: boolean
- game_resolution?: [number, number]
- hooks: Hooks
+ memory?: MemorySettings
+ force_fullscreen?: boolean
+ game_resolution?: [number, number]
+ hooks: Hooks
}
type InstallStage =
- | 'installed'
- | 'minecraft_installing'
- | 'pack_installed'
- | 'pack_installing'
- | 'not_installed'
+ | 'installed'
+ | 'minecraft_installing'
+ | 'pack_installed'
+ | 'pack_installing'
+ | 'not_installed'
type LinkedData = {
- project_id: ModrinthId
- version_id: ModrinthId
+ project_id: ModrinthId
+ version_id: ModrinthId
- locked: boolean
+ locked: boolean
}
type InstanceLoader = 'vanilla' | 'forge' | 'fabric' | 'quilt' | 'neoforge'
type ContentFile = {
- hash: string
- file_name: string
- size: number
- metadata?: FileMetadata
- update_version_id?: string
- project_type: ContentFileProjectType
+ hash: string
+ file_name: string
+ size: number
+ metadata?: FileMetadata
+ update_version_id?: string
+ project_type: ContentFileProjectType
}
type FileMetadata = {
- project_id: string
- version_id: string
+ project_id: string
+ version_id: string
}
type ContentFileProjectType = 'mod' | 'datapack' | 'resourcepack' | 'shaderpack'
type CacheBehaviour =
- // Serve expired data. If fetch fails / launcher is offline, errors are ignored
- | 'stale_while_revalidate_skip_offline'
- // Serve expired data, revalidate in background
- | 'stale_while_revalidate'
- // Must revalidate if data is expired
- | 'must_revalidate'
- // Ignore cache- always fetch updated data from origin
- | 'bypass'
+ // Serve expired data. If fetch fails / launcher is offline, errors are ignored
+ | 'stale_while_revalidate_skip_offline'
+ // Serve expired data, revalidate in background
+ | 'stale_while_revalidate'
+ // Must revalidate if data is expired
+ | 'must_revalidate'
+ // Ignore cache- always fetch updated data from origin
+ | 'bypass'
type MemorySettings = {
- maximum: number
+ maximum: number
}
type WindowSize = {
- width: number
- height: number
+ width: number
+ height: number
}
type Hooks = {
- pre_launch?: string
- wrapper?: string
- post_exit?: string
+ pre_launch?: string
+ wrapper?: string
+ post_exit?: string
}
type Manifest = {
- gameVersions: ManifestGameVersion[]
+ gameVersions: ManifestGameVersion[]
}
type ManifestGameVersion = {
- id: string
- stable: boolean
- loaders: ManifestLoaderVersion[]
+ id: string
+ stable: boolean
+ loaders: ManifestLoaderVersion[]
}
type ManifestLoaderVersion = {
- id: string
- url: string
- stable: boolean
+ id: string
+ url: string
+ stable: boolean
}
type AppSettings = {
- max_concurrent_downloads: number
- max_concurrent_writes: number
+ max_concurrent_downloads: number
+ max_concurrent_writes: number
- theme: 'dark' | 'light' | 'oled'
- default_page: 'Home' | 'Library'
- collapsed_navigation: boolean
- advanced_rendering: boolean
- native_decorations: boolean
- worlds_in_home: boolean
+ theme: 'dark' | 'light' | 'oled'
+ default_page: 'Home' | 'Library'
+ collapsed_navigation: boolean
+ advanced_rendering: boolean
+ native_decorations: boolean
+ worlds_in_home: boolean
- telemetry: boolean
- discord_rpc: boolean
- developer_mode: boolean
- personalized_ads: boolean
+ telemetry: boolean
+ discord_rpc: boolean
+ developer_mode: boolean
+ personalized_ads: boolean
- onboarded: boolean
+ onboarded: boolean
- extra_launch_args: string[]
- custom_env_vars: [string, string][]
- memory: MemorySettings
- force_fullscreen: boolean
- game_resolution: [number, number]
- hide_on_process_start: boolean
- hooks: Hooks
+ extra_launch_args: string[]
+ custom_env_vars: [string, string][]
+ memory: MemorySettings
+ force_fullscreen: boolean
+ game_resolution: [number, number]
+ hide_on_process_start: boolean
+ hooks: Hooks
- custom_dir?: string
- prev_custom_dir?: string
- migrated: boolean
+ custom_dir?: string
+ prev_custom_dir?: string
+ migrated: boolean
}
export type InstanceSettingsTabProps = {
- instance: GameInstance
- offline?: boolean
+ instance: GameInstance
+ offline?: boolean
}
diff --git a/apps/app-frontend/src/helpers/utils.js b/apps/app-frontend/src/helpers/utils.js
index 7c26af90..504371fa 100644
--- a/apps/app-frontend/src/helpers/utils.js
+++ b/apps/app-frontend/src/helpers/utils.js
@@ -1,13 +1,14 @@
-import { get_full_path, get_mod_full_path } from '@/helpers/profile'
import { invoke } from '@tauri-apps/api/core'
+import { get_full_path, get_mod_full_path } from '@/helpers/profile'
+
export async function isDev() {
- return await invoke('is_dev')
+ return await invoke('is_dev')
}
// One of 'Windows', 'Linux', 'MacOS'
export async function getOS() {
- return await invoke('plugin:utils|get_os')
+ return await invoke('plugin:utils|get_os')
}
// [AR] Feature. Updater
@@ -27,52 +28,52 @@ export async function initAuthlibPatching(minecraftVersion, isMojang) {
}
export async function openPath(path) {
- return await invoke('plugin:utils|open_path', { path })
+ return await invoke('plugin:utils|open_path', { path })
}
export async function highlightInFolder(path) {
- return await invoke('plugin:utils|highlight_in_folder', { path })
+ return await invoke('plugin:utils|highlight_in_folder', { path })
}
export async function showLauncherLogsFolder() {
- return await invoke('plugin:utils|show_launcher_logs_folder', {})
+ return await invoke('plugin:utils|show_launcher_logs_folder', {})
}
// Opens a profile's folder in the OS file explorer
export async function showProfileInFolder(path) {
- const fullPath = await get_full_path(path)
- return await openPath(fullPath)
+ const fullPath = await get_full_path(path)
+ return await openPath(fullPath)
}
export async function highlightModInProfile(profilePath, projectPath) {
- const fullPath = await get_mod_full_path(profilePath, projectPath)
- return await highlightInFolder(fullPath)
+ const fullPath = await get_mod_full_path(profilePath, projectPath)
+ return await highlightInFolder(fullPath)
}
export async function restartApp() {
- return await invoke('restart_app')
+ return await invoke('restart_app')
}
/**
* @deprecated This method is no longer needed, and just returns its parameter
*/
export function sanitizePotentialFileUrl(url) {
- return url
+ return url
}
export const releaseColor = (releaseType) => {
- switch (releaseType) {
- case 'release':
- return 'green'
- case 'beta':
- return 'orange'
- case 'alpha':
- return 'red'
- default:
- return ''
- }
+ switch (releaseType) {
+ case 'release':
+ return 'green'
+ case 'beta':
+ return 'orange'
+ case 'alpha':
+ return 'red'
+ default:
+ return ''
+ }
}
export async function copyToClipboard(text) {
- await navigator.clipboard.writeText(text)
+ await navigator.clipboard.writeText(text)
}
diff --git a/apps/app-frontend/src/helpers/worlds.ts b/apps/app-frontend/src/helpers/worlds.ts
index 89f98d7d..8665cb8b 100644
--- a/apps/app-frontend/src/helpers/worlds.ts
+++ b/apps/app-frontend/src/helpers/worlds.ts
@@ -1,327 +1,351 @@
+import { autoToHTML } from '@geometrically/minecraft-motd-parser'
+import type { GameVersion } from '@modrinth/ui'
import { invoke } from '@tauri-apps/api/core'
+import dayjs from 'dayjs'
+
import { get_full_path } from '@/helpers/profile'
import { openPath } from '@/helpers/utils'
-import { autoToHTML } from '@geometrically/minecraft-motd-parser'
-import dayjs from 'dayjs'
-import type { GameVersion } from '@modrinth/ui'
type BaseWorld = {
- name: string
- last_played?: string
- icon?: string
- display_status: DisplayStatus
- type: WorldType
+ name: string
+ last_played?: string
+ icon?: string
+ display_status: DisplayStatus
+ type: WorldType
}
export type WorldType = 'singleplayer' | 'server'
export type DisplayStatus = 'normal' | 'hidden' | 'favorite'
export type SingleplayerWorld = BaseWorld & {
- type: 'singleplayer'
- path: string
- game_mode: SingleplayerGameMode
- hardcore: boolean
- locked: boolean
+ type: 'singleplayer'
+ path: string
+ game_mode: SingleplayerGameMode
+ hardcore: boolean
+ locked: boolean
}
export type ServerWorld = BaseWorld & {
- type: 'server'
- index: number
- address: string
- pack_status: ServerPackStatus
+ type: 'server'
+ index: number
+ address: string
+ pack_status: ServerPackStatus
}
export type World = SingleplayerWorld | ServerWorld
export type WorldWithProfile = {
- profile: string
+ profile: string
} & World
export type SingleplayerGameMode = 'survival' | 'creative' | 'adventure' | 'spectator'
export type ServerPackStatus = 'enabled' | 'disabled' | 'prompt'
export type ServerStatus = {
- // https://minecraft.wiki/w/Text_component_format
- description?: string | Chat
- players?: {
- max: number
- online: number
- sample: { name: string; id: string }[]
- }
- version?: {
- name: string
- protocol: number
- }
- favicon?: string
- enforces_secure_chat: boolean
- ping?: number
+ // https://minecraft.wiki/w/Text_component_format
+ description?: string | Chat
+ players?: {
+ max: number
+ online: number
+ sample: { name: string; id: string }[]
+ }
+ version?: {
+ name: string
+ protocol: number
+ legacy: boolean
+ }
+ favicon?: string
+ enforces_secure_chat: boolean
+ ping?: number
}
export interface Chat {
- text: string
- bold: boolean
- italic: boolean
- underlined: boolean
- strikethrough: boolean
- obfuscated: boolean
- color?: string
- extra: Chat[]
+ text: string
+ bold: boolean
+ italic: boolean
+ underlined: boolean
+ strikethrough: boolean
+ obfuscated: boolean
+ color?: string
+ extra: Chat[]
}
export type ServerData = {
- refreshing: boolean
- status?: ServerStatus
- rawMotd?: string | Chat
- renderedMotd?: string
+ refreshing: boolean
+ lastSuccessfulRefresh?: number
+ status?: ServerStatus
+ rawMotd?: string | Chat
+ renderedMotd?: string
+}
+
+export type ProtocolVersion = {
+ version: number
+ legacy: boolean
}
export async function get_recent_worlds(
- limit: number,
- displayStatuses?: DisplayStatus[],
+ limit: number,
+ displayStatuses?: DisplayStatus[],
): Promise {
- return await invoke('plugin:worlds|get_recent_worlds', { limit, displayStatuses })
+ return await invoke('plugin:worlds|get_recent_worlds', { limit, displayStatuses })
}
export async function get_profile_worlds(path: string): Promise {
- return await invoke('plugin:worlds|get_profile_worlds', { path })
+ return await invoke('plugin:worlds|get_profile_worlds', { path })
}
export async function get_singleplayer_world(
- instance: string,
- world: string,
+ instance: string,
+ world: string,
): Promise {
- return await invoke('plugin:worlds|get_singleplayer_world', { instance, world })
+ return await invoke('plugin:worlds|get_singleplayer_world', { instance, world })
}
export async function set_world_display_status(
- instance: string,
- worldType: WorldType,
- worldId: string,
- displayStatus: DisplayStatus,
+ instance: string,
+ worldType: WorldType,
+ worldId: string,
+ displayStatus: DisplayStatus,
): Promise {
- return await invoke('plugin:worlds|set_world_display_status', {
- instance,
- worldType,
- worldId,
- displayStatus,
- })
+ return await invoke('plugin:worlds|set_world_display_status', {
+ instance,
+ worldType,
+ worldId,
+ displayStatus,
+ })
}
export async function rename_world(
- instance: string,
- world: string,
- newName: string,
+ instance: string,
+ world: string,
+ newName: string,
): Promise {
- return await invoke('plugin:worlds|rename_world', { instance, world, newName })
+ return await invoke('plugin:worlds|rename_world', { instance, world, newName })
}
export async function reset_world_icon(instance: string, world: string): Promise {
- return await invoke('plugin:worlds|reset_world_icon', { instance, world })
+ return await invoke('plugin:worlds|reset_world_icon', { instance, world })
}
export async function backup_world(instance: string, world: string): Promise {
- return await invoke('plugin:worlds|backup_world', { instance, world })
+ return await invoke('plugin:worlds|backup_world', { instance, world })
}
export async function delete_world(instance: string, world: string): Promise {
- return await invoke('plugin:worlds|delete_world', { instance, world })
+ return await invoke('plugin:worlds|delete_world', { instance, world })
}
export async function add_server_to_profile(
- path: string,
- name: string,
- address: string,
- packStatus: ServerPackStatus,
+ path: string,
+ name: string,
+ address: string,
+ packStatus: ServerPackStatus,
): Promise {
- return await invoke('plugin:worlds|add_server_to_profile', { path, name, address, packStatus })
+ return await invoke('plugin:worlds|add_server_to_profile', { path, name, address, packStatus })
}
export async function edit_server_in_profile(
- path: string,
- index: number,
- name: string,
- address: string,
- packStatus: ServerPackStatus,
+ path: string,
+ index: number,
+ name: string,
+ address: string,
+ packStatus: ServerPackStatus,
): Promise {
- return await invoke('plugin:worlds|edit_server_in_profile', {
- path,
- index,
- name,
- address,
- packStatus,
- })
+ return await invoke('plugin:worlds|edit_server_in_profile', {
+ path,
+ index,
+ name,
+ address,
+ packStatus,
+ })
}
export async function remove_server_from_profile(path: string, index: number): Promise {
- return await invoke('plugin:worlds|remove_server_from_profile', { path, index })
+ return await invoke('plugin:worlds|remove_server_from_profile', { path, index })
}
-export async function get_profile_protocol_version(path: string): Promise {
- return await invoke('plugin:worlds|get_profile_protocol_version', { path })
+export async function get_profile_protocol_version(path: string): Promise {
+ return await invoke('plugin:worlds|get_profile_protocol_version', { path })
}
export async function get_server_status(
- address: string,
- protocolVersion: number | null = null,
+ address: string,
+ protocolVersion: ProtocolVersion | null = null,
): Promise {
- return await invoke('plugin:worlds|get_server_status', { address, protocolVersion })
+ return await invoke('plugin:worlds|get_server_status', { address, protocolVersion })
}
export async function start_join_singleplayer_world(path: string, world: string): Promise {
- return await invoke('plugin:worlds|start_join_singleplayer_world', { path, world })
+ return await invoke('plugin:worlds|start_join_singleplayer_world', { path, world })
}
export async function start_join_server(path: string, address: string): Promise {
- return await invoke('plugin:worlds|start_join_server', { path, address })
+ return await invoke('plugin:worlds|start_join_server', { path, address })
}
export async function showWorldInFolder(instancePath: string, worldPath: string) {
- const fullPath = await get_full_path(instancePath)
- return await openPath(fullPath + '/saves/' + worldPath)
+ const fullPath = await get_full_path(instancePath)
+ return await openPath(fullPath + '/saves/' + worldPath)
}
export function getWorldIdentifier(world: World) {
- return world.type === 'singleplayer' ? world.path : world.address
+ return world.type === 'singleplayer' ? world.path : world.address
}
export function sortWorlds(worlds: World[]) {
- worlds.sort((a, b) => {
- if (!a.last_played) {
- return 1
- }
- if (!b.last_played) {
- return -1
- }
- return dayjs(b.last_played).diff(dayjs(a.last_played))
- })
+ worlds.sort((a, b) => {
+ if (!a.last_played) {
+ return 1
+ }
+ if (!b.last_played) {
+ return -1
+ }
+ return dayjs(b.last_played).diff(dayjs(a.last_played))
+ })
}
export function isSingleplayerWorld(world: World): world is SingleplayerWorld {
- return world.type === 'singleplayer'
+ return world.type === 'singleplayer'
}
export function isServerWorld(world: World): world is ServerWorld {
- return world.type === 'server'
+ return world.type === 'server'
}
export async function refreshServerData(
- serverData: ServerData,
- protocolVersion: number | null,
- address: string,
+ serverData: ServerData,
+ protocolVersion: ProtocolVersion | null,
+ address: string,
): Promise {
- serverData.refreshing = true
- await get_server_status(address, protocolVersion)
- .then((status) => {
- serverData.status = status
- if (status.description) {
- serverData.rawMotd = status.description
- serverData.renderedMotd = autoToHTML(status.description)
- }
- })
- .catch((err) => {
- console.error(`Refreshing addr: ${address}`, err)
- })
- .finally(() => {
- serverData.refreshing = false
- })
+ const refreshTime = Date.now()
+ serverData.refreshing = true
+ await get_server_status(address, protocolVersion)
+ .then((status) => {
+ if (serverData.lastSuccessfulRefresh && serverData.lastSuccessfulRefresh > refreshTime) {
+ // Don't update if there was a more recent successful refresh
+ return
+ }
+ serverData.lastSuccessfulRefresh = Date.now()
+ serverData.status = status
+ if (status.description) {
+ serverData.rawMotd = status.description
+ serverData.renderedMotd = autoToHTML(status.description)
+ }
+ })
+ .finally(() => {
+ serverData.refreshing = false
+ })
+ .catch((err) => {
+ console.error(`Refreshing addr ${address}`, protocolVersion, err)
+ if (!protocolVersion?.legacy) {
+ refreshServerData(serverData, { version: 74, legacy: true }, address)
+ }
+ })
}
-export async function refreshServers(
- worlds: World[],
- serverData: Record,
- protocolVersion: number | null,
+export function refreshServers(
+ worlds: World[],
+ serverData: Record,
+ protocolVersion: ProtocolVersion | null,
) {
- const servers = worlds.filter(isServerWorld)
- servers.forEach((server) => {
- if (!serverData[server.address]) {
- serverData[server.address] = {
- refreshing: true,
- }
- } else {
- serverData[server.address].refreshing = true
- }
- })
+ const servers = worlds.filter(isServerWorld)
+ servers.forEach((server) => {
+ if (!serverData[server.address]) {
+ serverData[server.address] = {
+ refreshing: true,
+ }
+ } else {
+ serverData[server.address].refreshing = true
+ }
+ })
- // noinspection ES6MissingAwait - handled with .then by refreshServerData already
- Promise.all(
- Object.keys(serverData).map((address) =>
- refreshServerData(serverData[address], protocolVersion, address),
- ),
- )
+ // noinspection ES6MissingAwait - handled with .then by refreshServerData already
+ Object.keys(serverData).forEach((address) =>
+ refreshServerData(serverData[address], protocolVersion, address),
+ )
}
export async function refreshWorld(worlds: World[], instancePath: string, worldPath: string) {
- const index = worlds.findIndex((w) => w.type === 'singleplayer' && w.path === worldPath)
- const newWorld = await get_singleplayer_world(instancePath, worldPath)
- if (index !== -1) {
- worlds[index] = newWorld
- } else {
- console.info(`Adding new world at path: ${worldPath}.`)
- worlds.push(newWorld)
- }
- sortWorlds(worlds)
+ const index = worlds.findIndex((w) => w.type === 'singleplayer' && w.path === worldPath)
+ const newWorld = await get_singleplayer_world(instancePath, worldPath)
+ if (index !== -1) {
+ worlds[index] = newWorld
+ } else {
+ console.info(`Adding new world at path: ${worldPath}.`)
+ worlds.push(newWorld)
+ }
+ sortWorlds(worlds)
}
export async function handleDefaultProfileUpdateEvent(
- worlds: World[],
- instancePath: string,
- e: ProfileEvent,
+ worlds: World[],
+ instancePath: string,
+ e: ProfileEvent,
) {
- if (e.event === 'world_updated') {
- await refreshWorld(worlds, instancePath, e.world)
- }
+ if (e.event === 'world_updated') {
+ await refreshWorld(worlds, instancePath, e.world)
+ }
- if (e.event === 'server_joined') {
- const world = worlds.find(
- (w) =>
- w.type === 'server' &&
- (w.address === `${e.host}:${e.port}` || (e.port == 25565 && w.address == e.host)),
- )
- if (world) {
- world.last_played = e.timestamp
- sortWorlds(worlds)
- } else {
- console.error(`Could not find world for server join event: ${e.host}:${e.port}`)
- }
- }
+ if (e.event === 'server_joined') {
+ const world = worlds.find(
+ (w) =>
+ w.type === 'server' &&
+ (w.address === `${e.host}:${e.port}` || (e.port == 25565 && w.address == e.host)),
+ )
+ if (world) {
+ world.last_played = e.timestamp
+ sortWorlds(worlds)
+ } else {
+ console.error(`Could not find world for server join event: ${e.host}:${e.port}`)
+ }
+ }
}
export async function refreshWorlds(instancePath: string): Promise {
- const worlds = await get_profile_worlds(instancePath).catch((err) => {
- console.error(`Error refreshing worlds for instance: ${instancePath}`, err)
- })
- if (worlds) {
- sortWorlds(worlds)
- }
+ const worlds = await get_profile_worlds(instancePath).catch((err) => {
+ console.error(`Error refreshing worlds for instance: ${instancePath}`, err)
+ })
+ if (worlds) {
+ sortWorlds(worlds)
+ }
- return worlds ?? []
+ return worlds ?? []
}
-const FIRST_QUICK_PLAY_VERSION = '23w14a'
+export function hasServerQuickPlaySupport(gameVersions: GameVersion[], currentVersion: string) {
+ if (!gameVersions.length) {
+ return true
+ }
-export function hasQuickPlaySupport(gameVersions: GameVersion[], currentVersion: string) {
- if (!gameVersions.length) {
- return false
- }
+ const versionIndex = gameVersions.findIndex((v) => v.version === currentVersion)
+ const targetIndex = gameVersions.findIndex((v) => v.version === 'a1.0.5_01')
- const versionIndex = gameVersions.findIndex((v) => v.version === currentVersion)
- const targetIndex = gameVersions.findIndex((v) => v.version === FIRST_QUICK_PLAY_VERSION)
+ return versionIndex === -1 || targetIndex === -1 || versionIndex <= targetIndex
+}
- return versionIndex !== -1 && targetIndex !== -1 && versionIndex <= targetIndex
+export function hasWorldQuickPlaySupport(gameVersions: GameVersion[], currentVersion: string) {
+ if (!gameVersions.length) {
+ return false
+ }
+
+ const versionIndex = gameVersions.findIndex((v) => v.version === currentVersion)
+ const targetIndex = gameVersions.findIndex((v) => v.version === '23w14a')
+
+ return versionIndex !== -1 && targetIndex !== -1 && versionIndex <= targetIndex
}
export type ProfileEvent = { profile_path_id: string } & (
- | {
- event: 'servers_updated'
- }
- | {
- event: 'world_updated'
- world: string
- }
- | {
- event: 'server_joined'
- host: string
- port: number
- timestamp: string
- }
+ | {
+ event: 'servers_updated'
+ }
+ | {
+ event: 'world_updated'
+ world: string
+ }
+ | {
+ event: 'server_joined'
+ host: string
+ port: number
+ timestamp: string
+ }
)
diff --git a/apps/app-frontend/src/locales/en-US/index.json b/apps/app-frontend/src/locales/en-US/index.json
index b2410efc..cd8044ad 100644
--- a/apps/app-frontend/src/locales/en-US/index.json
+++ b/apps/app-frontend/src/locales/en-US/index.json
@@ -383,11 +383,11 @@
"instance.worlds.no_contact": {
"message": "Server couldn't be contacted"
},
- "instance.worlds.no_quick_play": {
- "message": "You can only jump straight into worlds on Minecraft 1.20+"
+ "instance.worlds.no_server_quick_play": {
+ "message": "You can only jump straight into servers on Minecraft Alpha 1.0.5+"
},
- "instance.worlds.play_anyway": {
- "message": "Play anyway"
+ "instance.worlds.no_singleplayer_quick_play": {
+ "message": "You can only jump straight into singleplayer worlds on Minecraft 1.20+"
},
"instance.worlds.play_instance": {
"message": "Play instance"
diff --git a/apps/app-frontend/src/main.js b/apps/app-frontend/src/main.js
index a37a7018..e9160d23 100644
--- a/apps/app-frontend/src/main.js
+++ b/apps/app-frontend/src/main.js
@@ -1,35 +1,37 @@
-import { createApp } from 'vue'
-import router from '@/routes'
-import App from '@/App.vue'
-import { createPinia } from 'pinia'
-import FloatingVue from 'floating-vue'
import 'floating-vue/dist/style.css'
-import { createPlugin } from '@vintl/vintl/plugin'
+
import * as Sentry from '@sentry/vue'
import { VueScanPlugin } from '@taijased/vue-render-tracker'
+import { createPlugin } from '@vintl/vintl/plugin'
+import FloatingVue from 'floating-vue'
+import { createPinia } from 'pinia'
+import { createApp } from 'vue'
+
+import App from '@/App.vue'
+import router from '@/routes'
const VIntlPlugin = createPlugin({
- controllerOpts: {
- defaultLocale: 'en-US',
- locale: 'en-US',
- locales: [
- {
- tag: 'en-US',
- meta: {
- displayName: 'American English',
- },
- },
- ],
- },
- globalMixin: true,
- injectInto: [],
+ controllerOpts: {
+ defaultLocale: 'en-US',
+ locale: 'en-US',
+ locales: [
+ {
+ tag: 'en-US',
+ meta: {
+ displayName: 'American English',
+ },
+ },
+ ],
+ },
+ globalMixin: true,
+ injectInto: [],
})
const vueScan = new VueScanPlugin({
- enabled: false, // Enable or disable the tracker
- showOverlay: true, // Show overlay to visualize renders
- log: false, // Log render events to the console
- playSound: false, // Play sound on each render
+ enabled: false, // Enable or disable the tracker
+ showOverlay: true, // Show overlay to visualize renders
+ log: false, // Log render events to the console
+ playSound: false, // Play sound on each render
})
const pinia = createPinia()
@@ -37,24 +39,24 @@ const pinia = createPinia()
let app = createApp(App)
Sentry.init({
- app,
- dsn: 'https://9508775ee5034536bc70433f5f531dd4@o485889.ingest.us.sentry.io/4504579615227904',
- integrations: [Sentry.browserTracingIntegration({ router })],
- tracesSampleRate: 0.1,
+ app,
+ dsn: 'https://9508775ee5034536bc70433f5f531dd4@o485889.ingest.us.sentry.io/4504579615227904',
+ integrations: [Sentry.browserTracingIntegration({ router })],
+ tracesSampleRate: 0.1,
})
app.use(vueScan)
app.use(router)
app.use(pinia)
app.use(FloatingVue, {
- themes: {
- 'ribbit-popout': {
- $extend: 'dropdown',
- placement: 'bottom-end',
- instantMove: true,
- distance: 8,
- },
- },
+ themes: {
+ 'ribbit-popout': {
+ $extend: 'dropdown',
+ placement: 'bottom-end',
+ instantMove: true,
+ distance: 8,
+ },
+ },
})
app.use(VIntlPlugin)
diff --git a/apps/app-frontend/src/pages/Browse.vue b/apps/app-frontend/src/pages/Browse.vue
index 16bfefac..ce5ca621 100644
--- a/apps/app-frontend/src/pages/Browse.vue
+++ b/apps/app-frontend/src/pages/Browse.vue
@@ -1,67 +1,69 @@
-
-
-
-
-
-
- {{ filter.formatted_name }}
-
-
- {{ formatMessage(messages.gameVersionProvidedByInstance) }}
-
-
- {{ formatMessage(messages.modLoaderProvidedByInstance) }}
-
- {{ formatMessage(messages.syncFilterButton) }}
-
-
-
-
-
- Install content to instance
-
-
-
-
-
- clearSearch()">
-
-
-
-
-
- Sort by:
- {{ selected }}
-
-
- View:
- {{ selected }}
-
-
-
-
-
-
-
- You are currently offline. Connect to the internet to browse Modrinth!
-
-
- {
- newlyInstalled.push(id)
- }
- "
- @contextmenu.prevent.stop="(event) => handleRightClick(event, result)"
- />
-
- Open in Modrinth
- Copy link
-
-
-
-
-
-
-
+
+
+
+
+
+
+ {{ filter.formatted_name }}
+
+
+ {{ formatMessage(messages.gameVersionProvidedByInstance) }}
+
+
+ {{ formatMessage(messages.modLoaderProvidedByInstance) }}
+
+ {{ formatMessage(messages.syncFilterButton) }}
+
+
+
+
+
+ Install content to instance
+
+
+
+
+
+ clearSearch()">
+
+
+
+
+
+ Sort by:
+ {{ selected }}
+
+
+ View:
+ {{ selected }}
+
+
+
+
+
+
+
+ You are currently offline. Connect to the internet to browse Modrinth!
+
+
+ {
+ newlyInstalled.push(id)
+ }
+ "
+ @contextmenu.prevent.stop="(event) => handleRightClick(event, result)"
+ />
+
+ Open in Modrinth
+ Copy link
+
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/pages/Index.vue b/apps/app-frontend/src/pages/Index.vue
index 30ea5d95..d0c14e36 100644
--- a/apps/app-frontend/src/pages/Index.vue
+++ b/apps/app-frontend/src/pages/Index.vue
@@ -1,17 +1,19 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/pages/Skins.vue b/apps/app-frontend/src/pages/Skins.vue
index 8f275494..cab38f2f 100644
--- a/apps/app-frontend/src/pages/Skins.vue
+++ b/apps/app-frontend/src/pages/Skins.vue
@@ -1,53 +1,55 @@
- loadSkins()"
- @open-upload-modal="openUploadSkinModal"
- />
-
-
-
+ loadSkins()"
+ @open-upload-modal="openUploadSkinModal"
+ />
+
+
+
-
-
-
- Skins
- Beta
-
-
-
-
-
-
- selectCapeModal?.show(
- e,
- selectedSkin?.texture_key,
- currentCape,
- skinTexture,
- skinVariant,
- )
- "
- >
-
- Change cape
-
-
-
-
-
-
+
+
+
+ Skins
+ Beta
+
+
+
+
+
+
+ selectCapeModal?.show(
+ e,
+ selectedSkin?.texture_key,
+ currentCape,
+ skinTexture,
+ skinVariant,
+ )
+ "
+ >
+
+ Change cape
+
+
+
+
+
+
-
-
- Saved skins
-
-
-
-
-
- Add a skin
-
+
+
+ Saved skins
+
+
+
+
+
+ Add a skin
+
-
-
- editSkinModal?.show(e, skin)"
- >
- Edit
-
- confirmDeleteSkin(skin)"
- >
-
-
-
-
-
-
+
+
+ editSkinModal?.show(e, skin)"
+ >
+ Edit
+
+ confirmDeleteSkin(skin)"
+ >
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
- Please sign into your Minecraft account to use the skin management features of the
- Modrinth app.
-
-
-
-
-
- Sign In
-
-
-
-
-
+
+
+
+ Please sign into your Minecraft account to use the skin management features of the
+ Modrinth app.
+
+
+
+
+
+ Sign In
+
+
+
+
+
diff --git a/apps/app-frontend/src/pages/Worlds.vue b/apps/app-frontend/src/pages/Worlds.vue
index 8c1f57bf..896f54fe 100644
--- a/apps/app-frontend/src/pages/Worlds.vue
+++ b/apps/app-frontend/src/pages/Worlds.vue
@@ -1,4 +1,4 @@
- Worlds
+ Worlds
diff --git a/apps/app-frontend/src/pages/index.js b/apps/app-frontend/src/pages/index.js
index 2e0361cd..d08a3fbe 100644
--- a/apps/app-frontend/src/pages/index.js
+++ b/apps/app-frontend/src/pages/index.js
@@ -1,6 +1,6 @@
-import Index from './Index.vue'
import Browse from './Browse.vue'
-import Worlds from './Worlds.vue'
+import Index from './Index.vue'
import Skins from './Skins.vue'
+import Worlds from './Worlds.vue'
-export { Index, Browse, Worlds, Skins }
+export { Browse, Index, Skins, Worlds }
diff --git a/apps/app-frontend/src/pages/instance/Index.vue b/apps/app-frontend/src/pages/instance/Index.vue
index 8b6d63bf..35d4676a 100644
--- a/apps/app-frontend/src/pages/instance/Index.vue
+++ b/apps/app-frontend/src/pages/instance/Index.vue
@@ -1,214 +1,217 @@
-
-
handleRightClick(event, instance.path)"
- >
-
-
-
-
-
-
-
- {{ instance.name }}
-
-
-
-
-
- {{ instance.loader }} {{ instance.game_version }}
-
-
-
-
- {{ timePlayedHumanized }}
-
- Never played
-
-
-
-
-
- Installing...
-
-
-
-
- Repair
-
-
-
-
-
- Stop
-
-
-
-
-
- Play
-
-
-
- Loading...
-
-
-
-
-
-
-
-
-
- Share instance
- Create a server
- Open folder
- Export modpack
-
-
-
-
-
-
-
-
-
-
-
-
-
- stopInstance('InstanceSubpage')"
- >
-
-
-
-
-
-
-
-
- Play
- Stop
- Add content
- Edit
- Copy path
- Open folder
- Copy link
- Open in Modrinth
- Copy names
- Copy slugs
- Copy links
- Toggle selected
- Disable selected
- Enable selected
- Show/Hide unselected
- Update {{ selected.length > 0 ? 'selected' : 'all' }}
- Select Updatable
-
-
+
+
handleRightClick(event, instance.path)"
+ >
+
+
+
+
+
+
+
+ {{ instance.name }}
+
+
+
+
+
+ {{ instance.loader }} {{ instance.game_version }}
+
+
+
+
+ {{ timePlayedHumanized }}
+
+ Never played
+
+
+
+
+
+ Installing...
+
+
+
+
+ Repair
+
+
+
+
+
+ Stop
+
+
+
+
+
+ Play
+
+
+
+ Loading...
+
+
+
+
+
+
+
+
+
+ Share instance
+ Create a server
+ Open folder
+ Export modpack
+
+
+
+
+
+
+
+
+
+
+
+
+
+ stopInstance('InstanceSubpage')"
+ >
+
+
+
+
+
+
+
+
+ Play
+ Stop
+ Add content
+ Edit
+ Copy path
+ Open folder
+ Copy link
+ Open in Modrinth
+ Copy names
+ Copy slugs
+ Copy links
+ Toggle selected
+ Disable selected
+ Enable selected
+ Show/Hide unselected
+ Update {{ selected.length > 0 ? 'selected' : 'all' }}
+ Select Updatable
+
+
diff --git a/apps/app-frontend/src/pages/instance/Logs.vue b/apps/app-frontend/src/pages/instance/Logs.vue
index 83d0cbe8..43ebaf6a 100644
--- a/apps/app-frontend/src/pages/instance/Logs.vue
+++ b/apps/app-frontend/src/pages/instance/Logs.vue
@@ -1,154 +1,156 @@
-
-
+
+
+
+
+ {{
+ item.prefix
+ }}
+ {{ item.text }}
+
+
+
+
+
diff --git a/apps/app-frontend/src/pages/instance/Mods.vue b/apps/app-frontend/src/pages/instance/Mods.vue
index d14da99f..be9371da 100644
--- a/apps/app-frontend/src/pages/instance/Mods.vue
+++ b/apps/app-frontend/src/pages/instance/Mods.vue
@@ -1,471 +1,477 @@
-
-
-
-
-
-
- (searchFilter = '')">
-
-
-
-
-
-
-
-
-
- {{ filter.formattedName }}
-
-
-
(currentPage = page)"
- />
-
+
+
+
+
+
+
+ (searchFilter = '')">
+
+
+
+
+
+
+
+
+
+ {{ filter.formattedName }}
+
+
+
(currentPage = page)"
+ />
+
-
-
-
-
- Update
-
-
-
- Share
- Project names
- File names
- Project links
- Markdown links
-
-
-
- Enable
-
-
- Disable
-
-
- Remove
-
-
-
-
-
-
-
- Refresh
-
-
-
- Update all
-
-
-
- Update pack
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ return item
+ })
+ "
+ :sort-column="sortColumn"
+ :sort-ascending="ascending"
+ :update-sort="sortProjects"
+ :current-page="currentPage"
+ >
+
+
+
+ Update
+
+
+
+ Share
+ Project names
+ File names
+ Project links
+ Markdown links
+
+
+
+ Enable
+
+
+ Disable
+
+
+ Remove
+
+
+
+
+
+
+
+ Refresh
+
+
+
+ Update all
+
+
+
+ Update pack
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
- Show file
- Copy link
-
-
-
-
-
-
(currentPage = page)"
- />
-
-
-
-
-
-
-
You haven't added any content to this instance yet.
-
-
-
-
-
-
-
-
+
+
+
+ Show file
+ Copy link
+
+
+
+
+
+
(currentPage = page)"
+ />
+
+
+
+
+
+
+
You haven't added any content to this instance yet.
+
+
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/pages/instance/Overview.vue b/apps/app-frontend/src/pages/instance/Overview.vue
index 37df1f92..06b73e04 100644
--- a/apps/app-frontend/src/pages/instance/Overview.vue
+++ b/apps/app-frontend/src/pages/instance/Overview.vue
@@ -1,15 +1,16 @@
{{ instance.name }} overview
diff --git a/apps/app-frontend/src/pages/instance/Worlds.vue b/apps/app-frontend/src/pages/instance/Worlds.vue
index 8490269e..2dd2988a 100644
--- a/apps/app-frontend/src/pages/instance/Worlds.vue
+++ b/apps/app-frontend/src/pages/instance/Worlds.vue
@@ -1,172 +1,176 @@
- {
- addServer(server)
- if (start) {
- joinWorld(server)
- }
- }
- "
- />
-
-
-
-
-
-
-
-
-
- (searchFilter = '')">
-
-
-
-
-
-
-
- Refreshing...
-
-
-
- Refresh
-
-
-
-
-
-
- Add a server
-
-
-
-
-
- joinWorld(world)"
- @stop="() => emit('stop')"
- @refresh="() => refreshServer((world as ServerWorld).address)"
- @edit="
- () =>
- world.type === 'server' ? editServerModal?.show(world) : editWorldModal?.show(world)
- "
- @delete="() => promptToRemoveWorld(world)"
- @open-folder="(world: SingleplayerWorld) => showWorldInFolder(instance.path, world.path)"
- />
-
-
-
-
-
-
-
You don't have any worlds yet.
-
-
-
-
-
-
- Add a server
-
-
-
-
-
-
- Refreshing...
-
-
-
- Refresh
-
-
-
-
-
+ {
+ addServer(server)
+ if (start) {
+ joinWorld(server)
+ }
+ }
+ "
+ />
+
+
+
+
+
+
+
+
+
+ (searchFilter = '')">
+
+
+
+
+
+
+
+ Refreshing...
+
+
+
+ Refresh
+
+
+
+
+
+
+ Add a server
+
+
+
+
+
+ joinWorld(world)"
+ @stop="() => emit('stop')"
+ @refresh="() => refreshServer((world as ServerWorld).address)"
+ @edit="
+ () =>
+ world.type === 'server' ? editServerModal?.show(world) : editWorldModal?.show(world)
+ "
+ @delete="() => promptToRemoveWorld(world)"
+ @open-folder="(world: SingleplayerWorld) => showWorldInFolder(instance.path, world.path)"
+ />
+
+
+
+
+
+
+
You don't have any worlds yet.
+
+
+
+
+
+
+ Add a server
+
+
+
+
+
+
+ Refreshing...
+
+
+
+ Refresh
+
+
+
+
+
diff --git a/apps/app-frontend/src/pages/instance/index.js b/apps/app-frontend/src/pages/instance/index.js
index fa77df52..be2167e6 100644
--- a/apps/app-frontend/src/pages/instance/index.js
+++ b/apps/app-frontend/src/pages/instance/index.js
@@ -1,7 +1,7 @@
import Index from './Index.vue'
+import Logs from './Logs.vue'
+import Mods from './Mods.vue'
import Overview from './Overview.vue'
import Worlds from './Worlds.vue'
-import Mods from './Mods.vue'
-import Logs from './Logs.vue'
-export { Index, Overview, Worlds, Mods, Logs }
+export { Index, Logs, Mods, Overview, Worlds }
diff --git a/apps/app-frontend/src/pages/library/Custom.vue b/apps/app-frontend/src/pages/library/Custom.vue
index 619b4111..41a204e2 100644
--- a/apps/app-frontend/src/pages/library/Custom.vue
+++ b/apps/app-frontend/src/pages/library/Custom.vue
@@ -2,16 +2,16 @@
import GridDisplay from '@/components/GridDisplay.vue'
defineProps({
- instances: {
- type: Array,
- required: true,
- },
+ instances: {
+ type: Array,
+ required: true,
+ },
})
-
+
diff --git a/apps/app-frontend/src/pages/library/Downloaded.vue b/apps/app-frontend/src/pages/library/Downloaded.vue
index 4fa48812..d41c7e61 100644
--- a/apps/app-frontend/src/pages/library/Downloaded.vue
+++ b/apps/app-frontend/src/pages/library/Downloaded.vue
@@ -2,16 +2,16 @@
import GridDisplay from '@/components/GridDisplay.vue'
defineProps({
- instances: {
- type: Array,
- required: true,
- },
+ instances: {
+ type: Array,
+ required: true,
+ },
})
-
+
diff --git a/apps/app-frontend/src/pages/library/Index.vue b/apps/app-frontend/src/pages/library/Index.vue
index 2176f8e9..93d039fa 100644
--- a/apps/app-frontend/src/pages/library/Index.vue
+++ b/apps/app-frontend/src/pages/library/Index.vue
@@ -1,16 +1,17 @@
-
-
Library
-
-
-
-
-
-
-
-
-
No instances found
-
-
- Create new instance
-
-
-
-
+
+
Library
+
+
+
+
+
+
+
+
+
No instances found
+
+
+ Create new instance
+
+
+
+
diff --git a/apps/app-frontend/src/pages/library/Overview.vue b/apps/app-frontend/src/pages/library/Overview.vue
index 06c9bcdf..2f153976 100644
--- a/apps/app-frontend/src/pages/library/Overview.vue
+++ b/apps/app-frontend/src/pages/library/Overview.vue
@@ -2,12 +2,12 @@
import GridDisplay from '@/components/GridDisplay.vue'
defineProps({
- instances: {
- type: Array,
- required: true,
- },
+ instances: {
+ type: Array,
+ required: true,
+ },
})
-
+
diff --git a/apps/app-frontend/src/pages/library/index.js b/apps/app-frontend/src/pages/library/index.js
index 2dcbd635..ac8094e7 100644
--- a/apps/app-frontend/src/pages/library/index.js
+++ b/apps/app-frontend/src/pages/library/index.js
@@ -1,6 +1,6 @@
+import Custom from './Custom.vue'
+import Downloaded from './Downloaded.vue'
import Index from './Index.vue'
import Overview from './Overview.vue'
-import Downloaded from './Downloaded.vue'
-import Custom from './Custom.vue'
-export { Index, Overview, Downloaded, Custom }
+export { Custom, Downloaded, Index, Overview }
diff --git a/apps/app-frontend/src/pages/project/Changelog.vue b/apps/app-frontend/src/pages/project/Changelog.vue
index f9aae657..a4b40a96 100644
--- a/apps/app-frontend/src/pages/project/Changelog.vue
+++ b/apps/app-frontend/src/pages/project/Changelog.vue
@@ -1,10 +1,10 @@
-
+
diff --git a/apps/app-frontend/src/pages/project/Description.vue b/apps/app-frontend/src/pages/project/Description.vue
index ea6e0f20..825b35d7 100644
--- a/apps/app-frontend/src/pages/project/Description.vue
+++ b/apps/app-frontend/src/pages/project/Description.vue
@@ -1,22 +1,22 @@
-
-
-
+
+
+
diff --git a/apps/app-frontend/src/pages/project/Gallery.vue b/apps/app-frontend/src/pages/project/Gallery.vue
index 5aa4afa2..5012c8ed 100644
--- a/apps/app-frontend/src/pages/project/Gallery.vue
+++ b/apps/app-frontend/src/pages/project/Gallery.vue
@@ -1,105 +1,107 @@
-
-
-
-
-
-
-
{{ image.title }}
- {{ image.description }}
-
-
-
- {{
- new Date(image.created).toLocaleDateString('en-US', {
- year: 'numeric',
- month: 'long',
- day: 'numeric',
- })
- }}
-
-
-
-
-
-
{}"
- />
+
+
+
+
+
+
+
{{ image.title }}
+ {{ image.description }}
+
+
+
+ {{
+ new Date(image.created).toLocaleDateString('en-US', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ })
+ }}
+
+
+
+
+
+
{}"
+ />
-
{}">
-
-
- {{ expandedGalleryItem.title }}
-
-
- {{ expandedGalleryItem.description }}
-
-
-
-
-
-
+
{}">
+
+
+ {{ expandedGalleryItem.title }}
+
+
+ {{ expandedGalleryItem.description }}
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/pages/project/Index.vue b/apps/app-frontend/src/pages/project/Index.vue
index 941ab0d0..fee1f252 100644
--- a/apps/app-frontend/src/pages/project/Index.vue
+++ b/apps/app-frontend/src/pages/project/Index.vue
@@ -1,174 +1,175 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ installing ? 'Installing...' : installed ? 'Installed' : 'Install' }}
-
-
-
-
-
- Open in browser
- Follow
- Save
- Report
-
-
-
-
-
-
-
-
Project data couldn't not be loaded.
-
-
- Install
- Open in Modrinth
- Copy link
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ installing ? 'Installing...' : installed ? 'Installed' : 'Install' }}
+
+
+
+
+
+ Open in browser
+ Follow
+ Save
+ Report
+
+
+
+
+
+
+
+
Project data couldn't not be loaded.
+
+
+ Install
+ Open in Modrinth
+ Copy link
+
+
diff --git a/apps/app-frontend/src/pages/project/Version.vue b/apps/app-frontend/src/pages/project/Version.vue
index d40f3da9..337fd978 100644
--- a/apps/app-frontend/src/pages/project/Version.vue
+++ b/apps/app-frontend/src/pages/project/Version.vue
@@ -1,468 +1,469 @@
-
-
-
-
-
{{ version.name }}
-
-
-
-
-
-
- Changelog
-
-
-
- Files
-
-
-
-
-
- {{ file.filename }}
-
- ({{ formatBytes(file.size) }})
- Primary
-
-
-
-
-
- {{ installed ? 'Installed' : 'Install' }}
-
-
-
-
- Dependencies
-
-
-
-
- {{ dependency.title }}
- {{ dependency.subtitle }}
-
-
-
-
-
-
{{ dependency.title }}
-
{{ dependency.subtitle }}
-
-
-
-
-
-
- Metadata
-
-
-
-
+
+
+
+
+
{{ version.name }}
+
+
+
+
+
+
+ Changelog
+
+
+
+ Files
+
+
+
+
+
+ {{ file.filename }}
+
+ ({{ formatBytes(file.size) }})
+ Primary
+
+
+
+
+
+ {{ installed ? 'Installed' : 'Install' }}
+
+
+
+
+ Dependencies
+
+
+
+
+ {{ dependency.title }}
+ {{ dependency.subtitle }}
+
+
+
+
+
+
{{ dependency.title }}
+
{{ dependency.subtitle }}
+
+
+
+
+
+
+ Metadata
+
+
+
+
diff --git a/apps/app-frontend/src/pages/project/Versions.vue b/apps/app-frontend/src/pages/project/Versions.vue
index d52a9f21..a28fbe02 100644
--- a/apps/app-frontend/src/pages/project/Versions.vue
+++ b/apps/app-frontend/src/pages/project/Versions.vue
@@ -1,195 +1,202 @@
-
-
-
-
- install(version.id)"
- >
-
-
-
-
-
-
-
-
-
-
- Add to another instance
-
- Open in browser
-
-
-
-
-
-
-
-
+
+
+
+
+ install(version.id)"
+ >
+
+
+
+
+
+
+
+
+
+
+ Add to another instance
+
+ Open in browser
+
+
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/pages/project/index.js b/apps/app-frontend/src/pages/project/index.js
index 56a7b3b9..924bbf1b 100644
--- a/apps/app-frontend/src/pages/project/index.js
+++ b/apps/app-frontend/src/pages/project/index.js
@@ -1,7 +1,7 @@
-import Index from './Index.vue'
import Description from './Description.vue'
-import Versions from './Versions.vue'
import Gallery from './Gallery.vue'
+import Index from './Index.vue'
import Version from './Version.vue'
+import Versions from './Versions.vue'
-export { Index, Description, Versions, Gallery, Version }
+export { Description, Gallery, Index, Version, Versions }
diff --git a/apps/app-frontend/src/providers/app-notifications.ts b/apps/app-frontend/src/providers/app-notifications.ts
new file mode 100644
index 00000000..20879a4c
--- /dev/null
+++ b/apps/app-frontend/src/providers/app-notifications.ts
@@ -0,0 +1,48 @@
+import {
+ AbstractWebNotificationManager,
+ type NotificationPanelLocation,
+ type WebNotification,
+} from '@modrinth/ui'
+import { type Ref, ref } from 'vue'
+
+export class AppNotificationManager extends AbstractWebNotificationManager {
+ private readonly state: Ref
+ private readonly locationState: Ref
+
+ public constructor() {
+ super()
+ this.state = ref([])
+ this.locationState = ref('right')
+ }
+
+ public getNotificationLocation(): NotificationPanelLocation {
+ return this.locationState.value
+ }
+
+ public setNotificationLocation(location: NotificationPanelLocation): void {
+ this.locationState.value = location
+ }
+
+ public getNotifications(): WebNotification[] {
+ return this.state.value
+ }
+
+ protected addNotificationToStorage(notification: WebNotification): void {
+ this.state.value.push(notification)
+ }
+
+ protected removeNotificationFromStorage(id: string | number): void {
+ const index = this.state.value.findIndex((n) => n.id === id)
+ if (index > -1) {
+ this.state.value.splice(index, 1)
+ }
+ }
+
+ protected removeNotificationFromStorageByIndex(index: number): void {
+ this.state.value.splice(index, 1)
+ }
+
+ protected clearAllNotificationsFromStorage(): void {
+ this.state.value.splice(0)
+ }
+}
diff --git a/apps/app-frontend/src/routes.js b/apps/app-frontend/src/routes.js
index 67172e68..22ae62ad 100644
--- a/apps/app-frontend/src/routes.js
+++ b/apps/app-frontend/src/routes.js
@@ -1,183 +1,184 @@
import { createRouter, createWebHistory } from 'vue-router'
+
import * as Pages from '@/pages'
-import * as Project from '@/pages/project'
import * as Instance from '@/pages/instance'
import * as Library from '@/pages/library'
+import * as Project from '@/pages/project'
/**
* Configures application routing. Add page to pages/index and then add to route table here.
*/
export default new createRouter({
- history: createWebHistory(),
- routes: [
- {
- path: '/',
- name: 'Home',
- component: Pages.Index,
- meta: {
- breadcrumb: [{ name: 'Home' }],
- },
- },
- {
- path: '/worlds',
- name: 'Worlds',
- component: Pages.Worlds,
- meta: {
- breadcrumb: [{ name: 'Worlds' }],
- },
- },
- {
- path: '/browse/:projectType',
- name: 'Discover content',
- component: Pages.Browse,
- meta: {
- breadcrumb: [{ name: 'Discover content' }],
- },
- },
- {
- path: '/skins',
- name: 'Skins',
- component: Pages.Skins,
- meta: {
- breadcrumb: [{ name: 'Skins' }],
- },
- },
- {
- path: '/library',
- name: 'Library',
- component: Library.Index,
- meta: {
- breadcrumb: [{ name: 'Library' }],
- },
- children: [
- {
- path: '',
- name: 'Overview',
- component: Library.Overview,
- },
- {
- path: 'downloaded',
- name: 'Downloaded',
- component: Library.Downloaded,
- },
- {
- path: 'custom',
- name: 'Custom',
- component: Library.Custom,
- },
- ],
- },
- {
- path: '/project/:id',
- name: 'Project',
- component: Project.Index,
- props: true,
- children: [
- {
- path: '',
- name: 'Description',
- component: Project.Description,
- meta: {
- useContext: true,
- breadcrumb: [{ name: '?Project' }],
- },
- },
- {
- path: 'versions',
- name: 'Versions',
- component: Project.Versions,
- meta: {
- useContext: true,
- breadcrumb: [{ name: '?Project', link: '/project/{id}/' }, { name: 'Versions' }],
- },
- },
- {
- path: 'version/:version',
- name: 'Version',
- component: Project.Version,
- props: true,
- meta: {
- useContext: true,
- breadcrumb: [
- { name: '?Project', link: '/project/{id}/' },
- { name: 'Versions', link: '/project/{id}/versions' },
- { name: '?Version' },
- ],
- },
- },
- {
- path: 'gallery',
- name: 'Gallery',
- component: Project.Gallery,
- meta: {
- useContext: true,
- breadcrumb: [{ name: '?Project', link: '/project/{id}/' }, { name: 'Gallery' }],
- },
- },
- ],
- },
- {
- path: '/instance/:id',
- name: 'Instance',
- component: Instance.Index,
- props: true,
- children: [
- // {
- // path: '',
- // name: 'Overview',
- // component: Instance.Overview,
- // meta: {
- // useRootContext: true,
- // breadcrumb: [{ name: '?Instance' }],
- // },
- // },
- {
- path: 'worlds',
- name: 'InstanceWorlds',
- component: Instance.Worlds,
- meta: {
- useRootContext: true,
- breadcrumb: [{ name: '?Instance', link: '/instance/{id}/' }, { name: 'Worlds' }],
- },
- },
- {
- path: '',
- name: 'Mods',
- component: Instance.Mods,
- meta: {
- useRootContext: true,
- breadcrumb: [{ name: '?Instance', link: '/instance/{id}/' }, { name: 'Content' }],
- },
- },
- {
- path: 'projects/:type',
- name: 'ModsFilter',
- component: Instance.Mods,
- meta: {
- useRootContext: true,
- breadcrumb: [{ name: '?Instance', link: '/instance/{id}/' }, { name: 'Content' }],
- },
- },
- {
- path: 'logs',
- name: 'Logs',
- component: Instance.Logs,
- meta: {
- useRootContext: true,
- breadcrumb: [{ name: '?Instance', link: '/instance/{id}/' }, { name: 'Logs' }],
- },
- },
- ],
- },
- ],
- linkActiveClass: 'router-link-active',
- linkExactActiveClass: 'router-link-exact-active',
- scrollBehavior() {
- // Sometimes Vue's scroll behavior is not working as expected, so we need to manually scroll to top (especially on Linux)
- document.querySelector('.app-viewport')?.scrollTo(0, 0)
- return {
- el: '.app-viewport',
- top: 0,
- }
- },
+ history: createWebHistory(),
+ routes: [
+ {
+ path: '/',
+ name: 'Home',
+ component: Pages.Index,
+ meta: {
+ breadcrumb: [{ name: 'Home' }],
+ },
+ },
+ {
+ path: '/worlds',
+ name: 'Worlds',
+ component: Pages.Worlds,
+ meta: {
+ breadcrumb: [{ name: 'Worlds' }],
+ },
+ },
+ {
+ path: '/browse/:projectType',
+ name: 'Discover content',
+ component: Pages.Browse,
+ meta: {
+ breadcrumb: [{ name: 'Discover content' }],
+ },
+ },
+ {
+ path: '/skins',
+ name: 'Skins',
+ component: Pages.Skins,
+ meta: {
+ breadcrumb: [{ name: 'Skins' }],
+ },
+ },
+ {
+ path: '/library',
+ name: 'Library',
+ component: Library.Index,
+ meta: {
+ breadcrumb: [{ name: 'Library' }],
+ },
+ children: [
+ {
+ path: '',
+ name: 'Overview',
+ component: Library.Overview,
+ },
+ {
+ path: 'downloaded',
+ name: 'Downloaded',
+ component: Library.Downloaded,
+ },
+ {
+ path: 'custom',
+ name: 'Custom',
+ component: Library.Custom,
+ },
+ ],
+ },
+ {
+ path: '/project/:id',
+ name: 'Project',
+ component: Project.Index,
+ props: true,
+ children: [
+ {
+ path: '',
+ name: 'Description',
+ component: Project.Description,
+ meta: {
+ useContext: true,
+ breadcrumb: [{ name: '?Project' }],
+ },
+ },
+ {
+ path: 'versions',
+ name: 'Versions',
+ component: Project.Versions,
+ meta: {
+ useContext: true,
+ breadcrumb: [{ name: '?Project', link: '/project/{id}/' }, { name: 'Versions' }],
+ },
+ },
+ {
+ path: 'version/:version',
+ name: 'Version',
+ component: Project.Version,
+ props: true,
+ meta: {
+ useContext: true,
+ breadcrumb: [
+ { name: '?Project', link: '/project/{id}/' },
+ { name: 'Versions', link: '/project/{id}/versions' },
+ { name: '?Version' },
+ ],
+ },
+ },
+ {
+ path: 'gallery',
+ name: 'Gallery',
+ component: Project.Gallery,
+ meta: {
+ useContext: true,
+ breadcrumb: [{ name: '?Project', link: '/project/{id}/' }, { name: 'Gallery' }],
+ },
+ },
+ ],
+ },
+ {
+ path: '/instance/:id',
+ name: 'Instance',
+ component: Instance.Index,
+ props: true,
+ children: [
+ // {
+ // path: '',
+ // name: 'Overview',
+ // component: Instance.Overview,
+ // meta: {
+ // useRootContext: true,
+ // breadcrumb: [{ name: '?Instance' }],
+ // },
+ // },
+ {
+ path: 'worlds',
+ name: 'InstanceWorlds',
+ component: Instance.Worlds,
+ meta: {
+ useRootContext: true,
+ breadcrumb: [{ name: '?Instance', link: '/instance/{id}/' }, { name: 'Worlds' }],
+ },
+ },
+ {
+ path: '',
+ name: 'Mods',
+ component: Instance.Mods,
+ meta: {
+ useRootContext: true,
+ breadcrumb: [{ name: '?Instance', link: '/instance/{id}/' }, { name: 'Content' }],
+ },
+ },
+ {
+ path: 'projects/:type',
+ name: 'ModsFilter',
+ component: Instance.Mods,
+ meta: {
+ useRootContext: true,
+ breadcrumb: [{ name: '?Instance', link: '/instance/{id}/' }, { name: 'Content' }],
+ },
+ },
+ {
+ path: 'logs',
+ name: 'Logs',
+ component: Instance.Logs,
+ meta: {
+ useRootContext: true,
+ breadcrumb: [{ name: '?Instance', link: '/instance/{id}/' }, { name: 'Logs' }],
+ },
+ },
+ ],
+ },
+ ],
+ linkActiveClass: 'router-link-active',
+ linkExactActiveClass: 'router-link-exact-active',
+ scrollBehavior() {
+ // Sometimes Vue's scroll behavior is not working as expected, so we need to manually scroll to top (especially on Linux)
+ document.querySelector('.app-viewport')?.scrollTo(0, 0)
+ return {
+ el: '.app-viewport',
+ top: 0,
+ }
+ },
})
diff --git a/apps/app-frontend/src/store/breadcrumbs.js b/apps/app-frontend/src/store/breadcrumbs.js
index da07d414..ff13440c 100644
--- a/apps/app-frontend/src/store/breadcrumbs.js
+++ b/apps/app-frontend/src/store/breadcrumbs.js
@@ -1,37 +1,37 @@
import { defineStore } from 'pinia'
export const useBreadcrumbs = defineStore('breadcrumbsStore', {
- state: () => ({
- names: new Map(),
- context: null,
- rootContext: null,
- }),
- actions: {
- getName(route) {
- return this.names.get(route) ?? ''
- },
- setName(route, title) {
- this.names.set(route, title)
- },
- // resets breadcrumbs to only included ones as to not have stale breadcrumbs
- resetToNames(breadcrumbs) {
- if (!breadcrumbs) return
- // names is an array of every breadcrumb.name that starts with a ?
- const names = breadcrumbs
- .filter((breadcrumb) => breadcrumb.name.charAt(0) === '?')
- .map((breadcrumb) => breadcrumb.name.slice(1))
- // remove all names that are not in the names array
- for (const [route] of this.names) {
- if (!names.includes(route)) {
- this.names.delete(route)
- }
- }
- },
- setContext(context) {
- this.context = context
- },
- setRootContext(context) {
- this.rootContext = context
- },
- },
+ state: () => ({
+ names: new Map(),
+ context: null,
+ rootContext: null,
+ }),
+ actions: {
+ getName(route) {
+ return this.names.get(route) ?? ''
+ },
+ setName(route, title) {
+ this.names.set(route, title)
+ },
+ // resets breadcrumbs to only included ones as to not have stale breadcrumbs
+ resetToNames(breadcrumbs) {
+ if (!breadcrumbs) return
+ // names is an array of every breadcrumb.name that starts with a ?
+ const names = breadcrumbs
+ .filter((breadcrumb) => breadcrumb.name.charAt(0) === '?')
+ .map((breadcrumb) => breadcrumb.name.slice(1))
+ // remove all names that are not in the names array
+ for (const [route] of this.names) {
+ if (!names.includes(route)) {
+ this.names.delete(route)
+ }
+ }
+ },
+ setContext(context) {
+ this.context = context
+ },
+ setRootContext(context) {
+ this.rootContext = context
+ },
+ },
})
diff --git a/apps/app-frontend/src/store/error.js b/apps/app-frontend/src/store/error.js
index 6c3c0c12..0e7213fe 100644
--- a/apps/app-frontend/src/store/error.js
+++ b/apps/app-frontend/src/store/error.js
@@ -1,21 +1,21 @@
import { defineStore } from 'pinia'
export const useError = defineStore('errorsStore', {
- state: () => ({
- errorModal: null,
- }),
- actions: {
- setErrorModal(ref) {
- this.errorModal = ref
- },
- showError(error, context, closable = true, source = null) {
- this.errorModal.show(error, context, closable, source)
- },
- },
+ state: () => ({
+ errorModal: null,
+ }),
+ actions: {
+ setErrorModal(ref) {
+ this.errorModal = ref
+ },
+ showError(error, context, closable = true, source = null) {
+ this.errorModal.show(error, context, closable, source)
+ },
+ },
})
export const handleSevereError = (err, context) => {
- const error = useError()
- error.showError(err, context)
- console.error(err)
+ const error = useError()
+ error.showError(err, context)
+ console.error(err)
}
diff --git a/apps/app-frontend/src/store/install.js b/apps/app-frontend/src/store/install.js
index 4746b907..1e9f9486 100644
--- a/apps/app-frontend/src/store/install.js
+++ b/apps/app-frontend/src/store/install.js
@@ -1,195 +1,193 @@
+import dayjs from 'dayjs'
import { defineStore } from 'pinia'
-import {
- add_project_from_version,
- check_installed,
- get,
- get_projects,
- list,
- remove_project,
-} from '@/helpers/profile.js'
-import { handleError } from '@/store/notifications.js'
+
+import { trackEvent } from '@/helpers/analytics.js'
import { get_project, get_version_many } from '@/helpers/cache.js'
import { create_profile_and_install as packInstall } from '@/helpers/pack.js'
-import { trackEvent } from '@/helpers/analytics.js'
-import dayjs from 'dayjs'
+import {
+ add_project_from_version,
+ check_installed,
+ get,
+ get_projects,
+ list,
+ remove_project,
+} from '@/helpers/profile.js'
export const useInstall = defineStore('installStore', {
- state: () => ({
- installConfirmModal: null,
- modInstallModal: null,
- incompatibilityWarningModal: null,
- }),
- actions: {
- setInstallConfirmModal(ref) {
- this.installConfirmModal = ref
- },
- showInstallConfirmModal(project, version_id, onInstall, createInstanceCallback) {
- this.installConfirmModal.show(project, version_id, onInstall, createInstanceCallback)
- },
- setIncompatibilityWarningModal(ref) {
- this.incompatibilityWarningModal = ref
- },
- showIncompatibilityWarningModal(instance, project, versions, onInstall) {
- this.incompatibilityWarningModal.show(instance, project, versions, onInstall)
- },
- setModInstallModal(ref) {
- this.modInstallModal = ref
- },
- showModInstallModal(project, versions, onInstall) {
- this.modInstallModal.show(project, versions, onInstall)
- },
- },
+ state: () => ({
+ installConfirmModal: null,
+ modInstallModal: null,
+ incompatibilityWarningModal: null,
+ }),
+ actions: {
+ setInstallConfirmModal(ref) {
+ this.installConfirmModal = ref
+ },
+ showInstallConfirmModal(project, version_id, onInstall, createInstanceCallback) {
+ this.installConfirmModal.show(project, version_id, onInstall, createInstanceCallback)
+ },
+ setIncompatibilityWarningModal(ref) {
+ this.incompatibilityWarningModal = ref
+ },
+ showIncompatibilityWarningModal(instance, project, versions, selected, onInstall) {
+ this.incompatibilityWarningModal.show(instance, project, versions, selected, onInstall)
+ },
+ setModInstallModal(ref) {
+ this.modInstallModal = ref
+ },
+ showModInstallModal(project, versions, onInstall) {
+ this.modInstallModal.show(project, versions, onInstall)
+ },
+ },
})
export const install = async (
- projectId,
- versionId,
- instancePath,
- source,
- callback = () => {},
- createInstanceCallback = () => {},
+ projectId,
+ versionId,
+ instancePath,
+ source,
+ callback = () => {},
+ createInstanceCallback = () => {},
) => {
- const project = await get_project(projectId, 'must_revalidate').catch(handleError)
+ const project = await get_project(projectId, 'must_revalidate')
- if (project.project_type === 'modpack') {
- const version = versionId ?? project.versions[project.versions.length - 1]
- const packs = await list().catch(handleError)
+ if (project.project_type === 'modpack') {
+ const version = versionId ?? project.versions[project.versions.length - 1]
+ const packs = await list()
- if (packs.length === 0 || !packs.find((pack) => pack.linked_data?.project_id === project.id)) {
- await packInstall(
- project.id,
- version,
- project.title,
- project.icon_url,
- createInstanceCallback,
- ).catch(handleError)
+ if (packs.length === 0 || !packs.find((pack) => pack.linked_data?.project_id === project.id)) {
+ await packInstall(
+ project.id,
+ version,
+ project.title,
+ project.icon_url,
+ createInstanceCallback,
+ )
- trackEvent('PackInstall', {
- id: project.id,
- version_id: version,
- title: project.title,
- source,
- })
+ trackEvent('PackInstall', {
+ id: project.id,
+ version_id: version,
+ title: project.title,
+ source,
+ })
- callback(version)
- } else {
- const install = useInstall()
- install.showInstallConfirmModal(project, version, callback, createInstanceCallback)
- }
- } else {
- if (instancePath) {
- const [instance, instanceProjects, versions] = await Promise.all([
- await get(instancePath).catch(handleError),
- await get_projects(instancePath).catch(handleError),
- await get_version_many(project.versions, 'must_revalidate'),
- ])
+ callback(version)
+ } else {
+ const install = useInstall()
+ install.showInstallConfirmModal(project, version, callback, createInstanceCallback)
+ }
+ } else {
+ if (instancePath) {
+ const [instance, instanceProjects, versions] = await Promise.all([
+ await get(instancePath),
+ await get_projects(instancePath),
+ await get_version_many(project.versions, 'must_revalidate'),
+ ])
- const projectVersions = versions.sort(
- (a, b) => dayjs(b.date_published) - dayjs(a.date_published),
- )
+ const projectVersions = versions.sort(
+ (a, b) => dayjs(b.date_published) - dayjs(a.date_published),
+ )
- let version
- if (versionId) {
- version = projectVersions.find((x) => x.id === versionId)
- } else {
- version = projectVersions.find(
- (v) =>
- v.game_versions.includes(instance.game_version) &&
- (project.project_type === 'mod'
- ? v.loaders.includes(instance.loader) || v.loaders.includes('minecraft')
- : true),
- )
- }
+ let version
+ if (versionId) {
+ version = projectVersions.find((x) => x.id === versionId)
+ } else {
+ version = projectVersions.find(
+ (v) =>
+ v.game_versions.includes(instance.game_version) &&
+ (project.project_type === 'mod'
+ ? v.loaders.includes(instance.loader) || v.loaders.includes('minecraft')
+ : true),
+ )
+ }
- if (!version) {
- version = projectVersions[0]
- }
+ if (!version) {
+ version = projectVersions[0]
+ }
- if (
- version.game_versions.includes(instance.game_version) &&
- (project.project_type === 'mod'
- ? version.loaders.includes(instance.loader) || version.loaders.includes('minecraft')
- : true)
- ) {
- for (const [path, file] of Object.entries(instanceProjects)) {
- if (file.metadata && file.metadata.project_id === project.id) {
- await remove_project(instance.path, path)
- }
- }
+ if (
+ version.game_versions.includes(instance.game_version) &&
+ (project.project_type === 'mod'
+ ? version.loaders.includes(instance.loader) || version.loaders.includes('minecraft')
+ : true)
+ ) {
+ for (const [path, file] of Object.entries(instanceProjects)) {
+ if (file.metadata && file.metadata.project_id === project.id) {
+ await remove_project(instance.path, path)
+ }
+ }
- await add_project_from_version(instance.path, version.id).catch(handleError)
- await installVersionDependencies(instance, version)
+ await add_project_from_version(instance.path, version.id)
+ await installVersionDependencies(instance, version)
- trackEvent('ProjectInstall', {
- loader: instance.loader,
- game_version: instance.game_version,
- id: project.id,
- project_type: project.project_type,
- version_id: version.id,
- title: project.title,
- source,
- })
+ trackEvent('ProjectInstall', {
+ loader: instance.loader,
+ game_version: instance.game_version,
+ id: project.id,
+ project_type: project.project_type,
+ version_id: version.id,
+ title: project.title,
+ source,
+ })
- callback(version.id)
- } else {
- const install = useInstall()
- install.showIncompatibilityWarningModal(instance, project, projectVersions, callback)
- }
- } else {
- const versions = (await get_version_many(project.versions).catch(handleError)).sort(
- (a, b) => dayjs(b.date_published) - dayjs(a.date_published),
- )
+ callback(version.id)
+ } else {
+ const install = useInstall()
+ install.showIncompatibilityWarningModal(
+ instance,
+ project,
+ projectVersions,
+ version,
+ callback,
+ )
+ }
+ } else {
+ const versions = (await get_version_many(project.versions)).sort(
+ (a, b) => dayjs(b.date_published) - dayjs(a.date_published),
+ )
- const install = useInstall()
- install.showModInstallModal(project, versions, callback)
- }
- }
+ const install = useInstall()
+ install.showModInstallModal(project, versions, callback)
+ }
+ }
- // If project is modpack:
- // - We check all available instances if modpack is already installed
- // If true: show confirmation modal
- // If false: install it (latest version if passed version is null)
- // If project is mod:
- // - If instance is selected:
- // - If project is already installed
- // We first uninstall the project
- // - If no version is selected, we look check the instance for versions to select based on the versions
- // - If there are no versions, we show the incompat modal
- // - If a version is selected, and the version is incompatible, we show the incompat modal
- // - Version is inarlled, as well as version dependencies
+ // If project is modpack:
+ // - We check all available instances if modpack is already installed
+ // If true: show confirmation modal
+ // If false: install it (latest version if passed version is null)
+ // If project is mod:
+ // - If instance is selected:
+ // - If project is already installed
+ // We first uninstall the project
+ // - If no version is selected, we look check the instance for versions to select based on the versions
+ // - If there are no versions, we show the incompat modal
+ // - If a version is selected, and the version is incompatible, we show the incompat modal
+ // - Version is inarlled, as well as version dependencies
}
export const installVersionDependencies = async (profile, version) => {
- for (const dep of version.dependencies) {
- if (dep.dependency_type !== 'required') continue
- // disallow fabric api install on quilt
- if (dep.project_id === 'P7dR8mSH' && profile.loader === 'quilt') continue
- if (dep.version_id) {
- if (
- dep.project_id &&
- (await check_installed(profile.path, dep.project_id).catch(handleError))
- )
- continue
- await add_project_from_version(profile.path, dep.version_id)
- } else {
- if (
- dep.project_id &&
- (await check_installed(profile.path, dep.project_id).catch(handleError))
- )
- continue
+ for (const dep of version.dependencies) {
+ if (dep.dependency_type !== 'required') continue
+ // disallow fabric api install on quilt
+ if (dep.project_id === 'P7dR8mSH' && profile.loader === 'quilt') continue
+ if (dep.version_id) {
+ if (dep.project_id && (await check_installed(profile.path, dep.project_id))) continue
+ await add_project_from_version(profile.path, dep.version_id)
+ } else {
+ if (dep.project_id && (await check_installed(profile.path, dep.project_id))) continue
- const depProject = await get_project(dep.project_id, 'must_revalidate').catch(handleError)
+ const depProject = await get_project(dep.project_id, 'must_revalidate')
- const depVersions = (
- await get_version_many(depProject.versions, 'must_revalidate').catch(handleError)
- ).sort((a, b) => dayjs(b.date_published) - dayjs(a.date_published))
+ const depVersions = (await get_version_many(depProject.versions, 'must_revalidate')).sort(
+ (a, b) => dayjs(b.date_published) - dayjs(a.date_published),
+ )
- const latest = depVersions.find(
- (v) => v.game_versions.includes(profile.game_version) && v.loaders.includes(profile.loader),
- )
- if (latest) {
- await add_project_from_version(profile.path, latest.id).catch(handleError)
- }
- }
- }
+ const latest = depVersions.find(
+ (v) => v.game_versions.includes(profile.game_version) && v.loaders.includes(profile.loader),
+ )
+ if (latest) {
+ await add_project_from_version(profile.path, latest.id)
+ }
+ }
+ }
}
diff --git a/apps/app-frontend/src/store/loading.js b/apps/app-frontend/src/store/loading.js
index 8c300a1f..43f76c5f 100644
--- a/apps/app-frontend/src/store/loading.js
+++ b/apps/app-frontend/src/store/loading.js
@@ -1,19 +1,19 @@
import { defineStore } from 'pinia'
export const useLoading = defineStore('loadingStore', {
- state: () => ({
- loading: false,
- barEnabled: false,
- }),
- actions: {
- setEnabled(enabled) {
- this.barEnabled = enabled
- },
- startLoading() {
- this.loading = true
- },
- stopLoading() {
- this.loading = false
- },
- },
+ state: () => ({
+ loading: false,
+ barEnabled: false,
+ }),
+ actions: {
+ setEnabled(enabled) {
+ this.barEnabled = enabled
+ },
+ startLoading() {
+ this.loading = true
+ },
+ stopLoading() {
+ this.loading = false
+ },
+ },
})
diff --git a/apps/app-frontend/src/store/notifications.js b/apps/app-frontend/src/store/notifications.js
deleted file mode 100644
index 52cc5347..00000000
--- a/apps/app-frontend/src/store/notifications.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import { defineStore } from 'pinia'
-
-export const useNotifications = defineStore('notificationsStore', {
- state: () => ({
- notificationsWrapper: null,
- }),
- actions: {
- setNotifs(notifs) {
- this.notificationsWrapper = notifs
- },
- addNotification(notif) {
- this.notificationsWrapper.addNotification(notif)
- },
- },
-})
-
-export const handleError = (err) => {
- const notifs = useNotifications()
- notifs.addNotification({
- title: 'An error occurred',
- text: err.message ?? err,
- type: 'error',
- })
- console.error(err)
-}
diff --git a/apps/app-frontend/src/store/state.js b/apps/app-frontend/src/store/state.js
index e9811e62..1d7dd04d 100644
--- a/apps/app-frontend/src/store/state.js
+++ b/apps/app-frontend/src/store/state.js
@@ -1,7 +1,6 @@
-import { useTheming } from './theme.ts'
import { useBreadcrumbs } from './breadcrumbs'
-import { useLoading } from './loading'
-import { useNotifications, handleError } from './notifications'
import { useInstall } from './install'
+import { useLoading } from './loading'
+import { useTheming } from './theme.ts'
-export { useTheming, useBreadcrumbs, useLoading, useNotifications, handleError, useInstall }
+export { useBreadcrumbs, useInstall, useLoading, useTheming }
diff --git a/apps/app-frontend/src/store/theme.ts b/apps/app-frontend/src/store/theme.ts
index a7909416..b187f1a4 100644
--- a/apps/app-frontend/src/store/theme.ts
+++ b/apps/app-frontend/src/store/theme.ts
@@ -1,10 +1,10 @@
import { defineStore } from 'pinia'
export const DEFAULT_FEATURE_FLAGS = {
- project_background: false,
- page_path: false,
- worlds_tab: false,
- worlds_in_home: true,
+ project_background: false,
+ page_path: false,
+ worlds_tab: false,
+ worlds_in_home: true,
}
export const THEME_OPTIONS = ['dark', 'light', 'oled', 'system'] as const
@@ -14,57 +14,57 @@ export type FeatureFlags = Record
export type ColorTheme = (typeof THEME_OPTIONS)[number]
export type ThemeStore = {
- selectedTheme: ColorTheme
- advancedRendering: boolean
- toggleSidebar: boolean
+ selectedTheme: ColorTheme
+ advancedRendering: boolean
+ toggleSidebar: boolean
- devMode: boolean
- featureFlags: FeatureFlags
+ devMode: boolean
+ featureFlags: FeatureFlags
}
export const DEFAULT_THEME_STORE: ThemeStore = {
- selectedTheme: 'dark',
- advancedRendering: true,
- toggleSidebar: false,
+ selectedTheme: 'dark',
+ advancedRendering: true,
+ toggleSidebar: false,
- devMode: false,
- featureFlags: DEFAULT_FEATURE_FLAGS,
+ devMode: false,
+ featureFlags: DEFAULT_FEATURE_FLAGS,
}
export const useTheming = defineStore('themeStore', {
- state: () => DEFAULT_THEME_STORE,
- actions: {
- setThemeState(newTheme: ColorTheme) {
- if (THEME_OPTIONS.includes(newTheme)) {
- this.selectedTheme = newTheme
- } else {
- console.warn('Selected theme is not present. Check themeOptions.')
- }
+ state: () => DEFAULT_THEME_STORE,
+ actions: {
+ setThemeState(newTheme: ColorTheme) {
+ if (THEME_OPTIONS.includes(newTheme)) {
+ this.selectedTheme = newTheme
+ } else {
+ console.warn('Selected theme is not present. Check themeOptions.')
+ }
- this.setThemeClass()
- },
- setThemeClass() {
- for (const theme of THEME_OPTIONS) {
- document.getElementsByTagName('html')[0].classList.remove(`${theme}-mode`)
- }
+ this.setThemeClass()
+ },
+ setThemeClass() {
+ for (const theme of THEME_OPTIONS) {
+ document.getElementsByTagName('html')[0].classList.remove(`${theme}-mode`)
+ }
- let theme = this.selectedTheme
- if (this.selectedTheme === 'system') {
- const darkThemeMq = window.matchMedia('(prefers-color-scheme: dark)')
- if (darkThemeMq.matches) {
- theme = 'dark'
- } else {
- theme = 'light'
- }
- }
+ let theme = this.selectedTheme
+ if (this.selectedTheme === 'system') {
+ const darkThemeMq = window.matchMedia('(prefers-color-scheme: dark)')
+ if (darkThemeMq.matches) {
+ theme = 'dark'
+ } else {
+ theme = 'light'
+ }
+ }
- document.getElementsByTagName('html')[0].classList.add(`${theme}-mode`)
- },
- getFeatureFlag(key: FeatureFlag) {
- return this.featureFlags[key] ?? DEFAULT_FEATURE_FLAGS[key]
- },
- getThemeOptions() {
- return THEME_OPTIONS
- },
- },
+ document.getElementsByTagName('html')[0].classList.add(`${theme}-mode`)
+ },
+ getFeatureFlag(key: FeatureFlag) {
+ return this.featureFlags[key] ?? DEFAULT_FEATURE_FLAGS[key]
+ },
+ getThemeOptions() {
+ return THEME_OPTIONS
+ },
+ },
})
diff --git a/apps/app-frontend/tailwind.config.js b/apps/app-frontend/tailwind.config.js
index b5196b36..167087d3 100644
--- a/apps/app-frontend/tailwind.config.js
+++ b/apps/app-frontend/tailwind.config.js
@@ -1,153 +1,153 @@
/** @type {import('tailwindcss').Config} */
export default {
- content: [
- './src/components/**/*.{js,vue,ts}',
- './src/layouts/**/*.vue',
- './src/pages/**/*.vue',
- './src/plugins/**/*.{js,ts}',
- './src/App.vue',
- './src/error.vue',
- // monorepo - TODO: migrate this to its own package
- '../../packages/**/*.{js,vue,ts}',
- ],
- theme: {
- extend: {
- colors: {
- icon: 'var(--color-base)',
- // Text
- primary: 'var(--color-base)',
- contrast: 'var(--color-contrast)',
- secondary: 'var(--color-secondary)',
- inactive: 'var(--color-text-inactive)',
- dark: 'var(--color-text-dark)',
- inverted: 'var(--color-text-inverted)',
- heading: 'var(--color-heading)',
- red: 'var(--color-red)',
- orange: 'var(--color-orange)',
- purple: 'var(--color-purple)',
- bg: {
- DEFAULT: 'var(--color-bg)',
- red: 'var(--color-red-bg)',
- orange: 'var(--color-orange-bg)',
- green: 'var(--color-green-bg)',
- blue: 'var(--color-blue-bg)',
- purple: 'var(--color-purple-bg)',
- raised: 'var(--color-raised-bg)',
- },
- highlight: {
- DEFAULT: 'var(--color-brand-highlight)',
- red: 'var(--color-red-highlight)',
- orange: 'var(--color-orange-highlight)',
- green: 'var(--color-green-highlight)',
- blue: 'var(--color-blue-highlight)',
- purple: 'var(--color-purple-highlight)',
- gray: 'var(--color-gray-highlight)',
- },
- divider: {
- DEFAULT: 'var(--color-divider)',
- dark: 'var(--color-divider-dark)',
- },
- brand: {
- DEFAULT: 'var(--color-brand)',
- red: 'var(--color-red)',
- orange: 'var(--color-orange)',
- green: 'var(--color-green)',
- blue: 'var(--color-blue)',
- purple: 'var(--color-purple)',
- highlight: 'var(--color-brand-highlight)',
- shadow: 'var(--color-brand-shadow)',
- inverted: 'var(--color-accent-contrast)',
- },
- tabUnderlineHovered: 'var(--tab-underline-hovered)',
- button: {
- bg: 'var(--color-button-bg)',
- text: 'var(--color-button-text)',
- bgHover: 'var(--color-button-bg-hover)',
- textHover: 'var(--color-button-text-hover)',
- bgActive: 'var(--color-button-bg-active)',
- textActive: 'var(--color-button-text-active)',
- border: 'var(--color-button-border)',
- bgSelected: 'var(--color-button-bg-selected)',
- textSelected: 'var(--color-button-text-selected)',
- },
- toggleHandle: 'var(--color-toggle-handle)',
- dropdown: {
- bg: 'var(--color-dropdown-bg)',
- text: 'var(--color-dropdown-text)',
- },
- tooltip: {
- bg: 'var(--color-tooltip-bg)',
- text: 'var(--color-tooltip-text)',
- },
- code: {
- bg: 'var(--color-code-bg)',
- text: 'var(--color-code-text)',
- },
- kbdShadow: 'var(--color-kbd-shadow)',
- ad: {
- DEFAULT: 'var(--color-ad)',
- raised: 'var(--color-ad-raised)',
- contrast: 'var(--color-ad-contrast)',
- highlight: 'var(--color-ad-highlight)',
- },
- greyLink: {
- DEFAULT: 'var(--color-grey-link)',
- hover: 'var(--color-grey-link-hover)',
- active: 'var(--color-grey-link-active)',
- },
- link: {
- DEFAULT: 'var(--color-link)',
- hover: 'var(--color-link-hover)',
- active: 'var(--color-link-active)',
- },
- warning: {
- bg: 'var(--color-warning-bg)',
- text: 'var(--color-warning-text)',
- banner: {
- text: 'var(--color-warning-banner-text)',
- bg: 'var(--color-warning-banner-bg)',
- side: 'var(--color-warning-banner-side)',
- },
- },
- infoBanner: {
- text: 'var(--color-info-banner-text)',
- bg: 'var(--color-info-banner-bg)',
- side: 'var(--color-info-banner-side)',
- },
- blockQuote: 'var(--color-block-quote)',
- headerUnderline: 'var(--color-header-underline)',
- hr: 'var(--color-hr)',
- table: {
- border: 'var(--color-table-border)',
- alternateRow: ' var(--color-table-alternate-row)',
- },
- },
- backgroundImage: {
- mazeBg: 'var(--landing-maze-bg)',
- mazeGradientBg: 'var(--landing-maze-gradient-bg)',
- landing: {
- mazeOuterBg: 'var(--landing-maze-outer-bg)',
- colorHeading: 'var(--landing-color-heading)',
- colorSubheading: 'var(--landing-color-subheading)',
- transitionGradientStart: 'var(--landing-transition-gradient-start)',
- transitionGradientEnd: 'var(--landing-transition-gradient-end)',
- hoverCardGradient: 'var(--landing-hover-card-gradient)',
- borderGradient: 'var(--landing-border-gradient)',
- borderColor: 'var(--landing-border-color)',
- creatorGradient: 'var(--landing-creator-gradient)',
- blobGradient: 'var(--landing-blob-gradient)',
- cardBg: 'var(--landing-card-bg)',
- blueLabel: 'var(--landing-blue-label)',
- blueLabelBg: 'var(--landing-blue-label-bg)',
- greenLabel: 'var(--landing-green-label)',
- greenLabelBg: 'var(--landing-green-label-bg)',
- rawBg: 'var(--landing-raw-bg)',
- },
- },
- },
- },
- plugins: [],
- corePlugins: {
- preflight: false,
- },
+ content: [
+ './src/components/**/*.{js,vue,ts}',
+ './src/layouts/**/*.vue',
+ './src/pages/**/*.vue',
+ './src/plugins/**/*.{js,ts}',
+ './src/App.vue',
+ './src/error.vue',
+ // monorepo - TODO: migrate this to its own package
+ '../../packages/**/*.{js,vue,ts}',
+ ],
+ theme: {
+ extend: {
+ colors: {
+ icon: 'var(--color-base)',
+ // Text
+ primary: 'var(--color-base)',
+ contrast: 'var(--color-contrast)',
+ secondary: 'var(--color-secondary)',
+ inactive: 'var(--color-text-inactive)',
+ dark: 'var(--color-text-dark)',
+ inverted: 'var(--color-text-inverted)',
+ heading: 'var(--color-heading)',
+ red: 'var(--color-red)',
+ orange: 'var(--color-orange)',
+ purple: 'var(--color-purple)',
+ bg: {
+ DEFAULT: 'var(--color-bg)',
+ red: 'var(--color-red-bg)',
+ orange: 'var(--color-orange-bg)',
+ green: 'var(--color-green-bg)',
+ blue: 'var(--color-blue-bg)',
+ purple: 'var(--color-purple-bg)',
+ raised: 'var(--color-raised-bg)',
+ },
+ highlight: {
+ DEFAULT: 'var(--color-brand-highlight)',
+ red: 'var(--color-red-highlight)',
+ orange: 'var(--color-orange-highlight)',
+ green: 'var(--color-green-highlight)',
+ blue: 'var(--color-blue-highlight)',
+ purple: 'var(--color-purple-highlight)',
+ gray: 'var(--color-gray-highlight)',
+ },
+ divider: {
+ DEFAULT: 'var(--color-divider)',
+ dark: 'var(--color-divider-dark)',
+ },
+ brand: {
+ DEFAULT: 'var(--color-brand)',
+ red: 'var(--color-red)',
+ orange: 'var(--color-orange)',
+ green: 'var(--color-green)',
+ blue: 'var(--color-blue)',
+ purple: 'var(--color-purple)',
+ highlight: 'var(--color-brand-highlight)',
+ shadow: 'var(--color-brand-shadow)',
+ inverted: 'var(--color-accent-contrast)',
+ },
+ tabUnderlineHovered: 'var(--tab-underline-hovered)',
+ button: {
+ bg: 'var(--color-button-bg)',
+ text: 'var(--color-button-text)',
+ bgHover: 'var(--color-button-bg-hover)',
+ textHover: 'var(--color-button-text-hover)',
+ bgActive: 'var(--color-button-bg-active)',
+ textActive: 'var(--color-button-text-active)',
+ border: 'var(--color-button-border)',
+ bgSelected: 'var(--color-button-bg-selected)',
+ textSelected: 'var(--color-button-text-selected)',
+ },
+ toggleHandle: 'var(--color-toggle-handle)',
+ dropdown: {
+ bg: 'var(--color-dropdown-bg)',
+ text: 'var(--color-dropdown-text)',
+ },
+ tooltip: {
+ bg: 'var(--color-tooltip-bg)',
+ text: 'var(--color-tooltip-text)',
+ },
+ code: {
+ bg: 'var(--color-code-bg)',
+ text: 'var(--color-code-text)',
+ },
+ kbdShadow: 'var(--color-kbd-shadow)',
+ ad: {
+ DEFAULT: 'var(--color-ad)',
+ raised: 'var(--color-ad-raised)',
+ contrast: 'var(--color-ad-contrast)',
+ highlight: 'var(--color-ad-highlight)',
+ },
+ greyLink: {
+ DEFAULT: 'var(--color-grey-link)',
+ hover: 'var(--color-grey-link-hover)',
+ active: 'var(--color-grey-link-active)',
+ },
+ link: {
+ DEFAULT: 'var(--color-link)',
+ hover: 'var(--color-link-hover)',
+ active: 'var(--color-link-active)',
+ },
+ warning: {
+ bg: 'var(--color-warning-bg)',
+ text: 'var(--color-warning-text)',
+ banner: {
+ text: 'var(--color-warning-banner-text)',
+ bg: 'var(--color-warning-banner-bg)',
+ side: 'var(--color-warning-banner-side)',
+ },
+ },
+ infoBanner: {
+ text: 'var(--color-info-banner-text)',
+ bg: 'var(--color-info-banner-bg)',
+ side: 'var(--color-info-banner-side)',
+ },
+ blockQuote: 'var(--color-block-quote)',
+ headerUnderline: 'var(--color-header-underline)',
+ hr: 'var(--color-hr)',
+ table: {
+ border: 'var(--color-table-border)',
+ alternateRow: ' var(--color-table-alternate-row)',
+ },
+ },
+ backgroundImage: {
+ mazeBg: 'var(--landing-maze-bg)',
+ mazeGradientBg: 'var(--landing-maze-gradient-bg)',
+ landing: {
+ mazeOuterBg: 'var(--landing-maze-outer-bg)',
+ colorHeading: 'var(--landing-color-heading)',
+ colorSubheading: 'var(--landing-color-subheading)',
+ transitionGradientStart: 'var(--landing-transition-gradient-start)',
+ transitionGradientEnd: 'var(--landing-transition-gradient-end)',
+ hoverCardGradient: 'var(--landing-hover-card-gradient)',
+ borderGradient: 'var(--landing-border-gradient)',
+ borderColor: 'var(--landing-border-color)',
+ creatorGradient: 'var(--landing-creator-gradient)',
+ blobGradient: 'var(--landing-blob-gradient)',
+ cardBg: 'var(--landing-card-bg)',
+ blueLabel: 'var(--landing-blue-label)',
+ blueLabelBg: 'var(--landing-blue-label-bg)',
+ greenLabel: 'var(--landing-green-label)',
+ greenLabelBg: 'var(--landing-green-label-bg)',
+ rawBg: 'var(--landing-raw-bg)',
+ },
+ },
+ },
+ },
+ plugins: [],
+ corePlugins: {
+ preflight: false,
+ },
}
diff --git a/apps/app-frontend/tsconfig.app.json b/apps/app-frontend/tsconfig.app.json
index 000aadc2..8d5b455f 100644
--- a/apps/app-frontend/tsconfig.app.json
+++ b/apps/app-frontend/tsconfig.app.json
@@ -1,24 +1,24 @@
{
- "compilerOptions": {
- "target": "ES2020",
- "useDefineForClassFields": true,
- "module": "ESNext",
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
- "skipLibCheck": true,
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "skipLibCheck": true,
- "moduleResolution": "bundler",
- "allowJs": true,
- "allowImportingTsExtensions": true,
- "isolatedModules": true,
- "moduleDetection": "force",
- "noEmit": true,
- "jsx": "preserve",
+ "moduleResolution": "bundler",
+ "allowJs": true,
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "preserve",
- "strict": true,
+ "strict": true,
- "paths": {
- "@/*": ["./src/*"]
- }
- },
- "include": ["src"]
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["src"]
}
diff --git a/apps/app-frontend/tsconfig.json b/apps/app-frontend/tsconfig.json
index d32ff682..88a659fb 100644
--- a/apps/app-frontend/tsconfig.json
+++ b/apps/app-frontend/tsconfig.json
@@ -1,4 +1,4 @@
{
- "files": [],
- "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
+ "files": [],
+ "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
}
diff --git a/apps/app-frontend/tsconfig.node.json b/apps/app-frontend/tsconfig.node.json
index ac300be8..99847dfd 100644
--- a/apps/app-frontend/tsconfig.node.json
+++ b/apps/app-frontend/tsconfig.node.json
@@ -1,18 +1,18 @@
{
- "compilerOptions": {
- "target": "ES2022",
- "lib": ["ES2023"],
- "module": "ESNext",
- "skipLibCheck": true,
+ "compilerOptions": {
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
- "moduleResolution": "bundler",
- "allowImportingTsExtensions": true,
- "isolatedModules": true,
- "moduleDetection": "force",
- "noEmit": true,
- "resolveJsonModule": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "resolveJsonModule": true,
- "strict": true
- },
- "include": ["vite.config.ts"]
+ "strict": true
+ },
+ "include": ["vite.config.ts"]
}
diff --git a/apps/app-frontend/vite.config.ts b/apps/app-frontend/vite.config.ts
index 8adf5fb2..ac1c29a0 100644
--- a/apps/app-frontend/vite.config.ts
+++ b/apps/app-frontend/vite.config.ts
@@ -1,76 +1,75 @@
+import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import { defineConfig } from 'vite'
import svgLoader from 'vite-svg-loader'
-import vue from '@vitejs/plugin-vue'
-
import tauriConf from '../app/tauri.conf.json'
const projectRootDir = resolve(__dirname)
// https://vitejs.dev/config/
export default defineConfig({
- resolve: {
- alias: [
- {
- find: '@',
- replacement: resolve(projectRootDir, 'src'),
- },
- ],
- },
- plugins: [
- vue(),
- svgLoader({
- svgoConfig: {
- plugins: [
- {
- name: 'preset-default',
- params: {
- overrides: {
- removeViewBox: false,
- },
- },
- },
- ],
- },
- }),
- ],
+ resolve: {
+ alias: [
+ {
+ find: '@',
+ replacement: resolve(projectRootDir, 'src'),
+ },
+ ],
+ },
+ plugins: [
+ vue(),
+ svgLoader({
+ svgoConfig: {
+ plugins: [
+ {
+ name: 'preset-default',
+ params: {
+ overrides: {
+ removeViewBox: false,
+ },
+ },
+ },
+ ],
+ },
+ }),
+ ],
- // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
- // prevent vite from obscuring rust errors
- clearScreen: false,
- // tauri expects a fixed port, fail if that port is not available
- server: {
- port: 1420,
- strictPort: true,
- headers: {
- 'content-security-policy': Object.entries(tauriConf.app.security.csp)
- .map(([directive, sources]) => {
- // An additional websocket connect-src is required for Vite dev tools to work
- if (directive === 'connect-src') {
- sources = Array.isArray(sources) ? sources : [sources]
- sources.push('ws://localhost:1420')
- }
+ // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
+ // prevent vite from obscuring rust errors
+ clearScreen: false,
+ // tauri expects a fixed port, fail if that port is not available
+ server: {
+ port: 1420,
+ strictPort: true,
+ headers: {
+ 'content-security-policy': Object.entries(tauriConf.app.security.csp)
+ .map(([directive, sources]) => {
+ // An additional websocket connect-src is required for Vite dev tools to work
+ if (directive === 'connect-src') {
+ sources = Array.isArray(sources) ? sources : [sources]
+ sources.push('ws://localhost:1420')
+ }
- return Array.isArray(sources)
- ? `${directive} ${sources.join(' ')}`
- : `${directive} ${sources}`
- })
- .join('; '),
- },
- },
- // to make use of `TAURI_ENV_DEBUG` and other env variables
- // https://v2.tauri.app/reference/environment-variables/#tauri-cli-hook-commands
- envPrefix: ['VITE_', 'TAURI_'],
- build: {
- // Tauri supports es2021
- target: process.env.TAURI_ENV_PLATFORM == 'windows' ? 'chrome105' : 'safari13', // eslint-disable-line turbo/no-undeclared-env-vars
- // don't minify for debug builds
- minify: !process.env.TAURI_ENV_DEBUG ? 'esbuild' : false, // eslint-disable-line turbo/no-undeclared-env-vars
- // produce sourcemaps for debug builds
- sourcemap: !!process.env.TAURI_ENV_DEBUG, // eslint-disable-line turbo/no-undeclared-env-vars
- commonjsOptions: {
- esmExternals: true,
- },
- },
+ return Array.isArray(sources)
+ ? `${directive} ${sources.join(' ')}`
+ : `${directive} ${sources}`
+ })
+ .join('; '),
+ },
+ },
+ // to make use of `TAURI_ENV_DEBUG` and other env variables
+ // https://v2.tauri.app/reference/environment-variables/#tauri-cli-hook-commands
+ envPrefix: ['VITE_', 'TAURI_'],
+ build: {
+ // Tauri supports es2021
+ target: process.env.TAURI_ENV_PLATFORM == 'windows' ? 'chrome105' : 'safari13', // eslint-disable-line turbo/no-undeclared-env-vars
+ // don't minify for debug builds
+ minify: !process.env.TAURI_ENV_DEBUG ? 'esbuild' : false, // eslint-disable-line turbo/no-undeclared-env-vars
+ // produce sourcemaps for debug builds
+ sourcemap: !!process.env.TAURI_ENV_DEBUG, // eslint-disable-line turbo/no-undeclared-env-vars
+ commonjsOptions: {
+ esmExternals: true,
+ },
+ },
})
diff --git a/apps/app-playground/.prettierignore b/apps/app-playground/.prettierignore
new file mode 100644
index 00000000..ecc487ec
--- /dev/null
+++ b/apps/app-playground/.prettierignore
@@ -0,0 +1 @@
+**/*.rs
diff --git a/apps/app-playground/package.json b/apps/app-playground/package.json
index 342b3cec..7d9fdaa6 100644
--- a/apps/app-playground/package.json
+++ b/apps/app-playground/package.json
@@ -1,10 +1,12 @@
{
- "name": "@modrinth/app-playground",
- "scripts": {
- "build": "cargo build --release",
- "lint": "cargo fmt --check && cargo clippy --all-targets",
- "fix": "cargo clippy --all-targets --fix --allow-dirty && cargo fmt",
- "dev": "cargo run",
- "test": "cargo nextest run --all-targets --no-fail-fast"
- }
+ "name": "@modrinth/app-playground",
+ "scripts": {
+ "build": "cargo build --release",
+ "lint": "cargo fmt --check && cargo clippy --all-targets",
+ "lint:ancillary": "prettier --check .",
+ "fix": "cargo clippy --all-targets --fix --allow-dirty && cargo fmt",
+ "fix:ancillary": "prettier --check .",
+ "dev": "cargo run",
+ "test": "cargo nextest run --all-targets --no-fail-fast"
+ }
}
diff --git a/apps/app/.prettierignore b/apps/app/.prettierignore
new file mode 100644
index 00000000..06dd4658
--- /dev/null
+++ b/apps/app/.prettierignore
@@ -0,0 +1,2 @@
+**/*.rs
+src/api/oauth_utils/auth_code_reply/page.html
diff --git a/apps/app/Cargo.toml b/apps/app/Cargo.toml
index e1a612e5..b0a489bd 100644
--- a/apps/app/Cargo.toml
+++ b/apps/app/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "theseus_gui"
-version = "1.0.0-local" # The actual version is set by the theseus-build workflow on tagging
+version = "1.0.0-local" # The actual version is set by the theseus-build workflow on tagging
description = "The Modrinth App is a desktop application for managing your Minecraft mods"
license = "GPL-3.0-only"
repository = "https://github.com/modrinth/code/apps/app/"
diff --git a/apps/app/Info.plist b/apps/app/Info.plist
index 18e7a26a..68d93a14 100644
--- a/apps/app/Info.plist
+++ b/apps/app/Info.plist
@@ -1,42 +1,43 @@
-
-
+
+
-
- CFBundleURLTypes
-
-
- CFBundleURLName
- AstralRinthApp
- CFBundleURLSchemes
-
- astralrinth
- astralrinthscheme
-
-
-
- NSCameraUsageDescription
- A Minecraft mod wants to access your camera.
- NSMicrophoneUsageDescription
- A Minecraft mod wants to access your microphone.
- NSAppTransportSecurity
-
- NSExceptionDomains
-
- asset.localhost
-
- NSExceptionAllowsInsecureHTTPLoads
-
- NSIncludesSubdomains
-
-
- textures.minecraft.net
-
- NSExceptionAllowsInsecureHTTPLoads
-
- NSIncludesSubdomains
-
-
-
-
-
+
+ CFBundleURLTypes
+
+
+ CFBundleURLName
+ ModrinthApp
+ CFBundleURLSchemes
+
+ modrinth
+ modrinthscheme
+
+
+
+ NSCameraUsageDescription
+ A Minecraft mod wants to access your camera.
+ NSMicrophoneUsageDescription
+ A Minecraft mod wants to access your microphone.
+ NSAppTransportSecurity
+
+ NSExceptionDomains
+
+ asset.localhost
+
+ NSExceptionAllowsInsecureHTTPLoads
+
+ NSIncludesSubdomains
+
+
+ textures.minecraft.net
+
+ NSExceptionAllowsInsecureHTTPLoads
+
+ NSIncludesSubdomains
+
+
+
+
+
diff --git a/apps/app/capabilities/core.json b/apps/app/capabilities/core.json
index ac4c012b..ff4f7b14 100644
--- a/apps/app/capabilities/core.json
+++ b/apps/app/capabilities/core.json
@@ -1,28 +1,28 @@
{
- "identifier": "core",
- "description": "",
- "local": true,
- "windows": ["main"],
- "permissions": [
- "core:default",
- "core:path:default",
- "core:event:default",
- "core:window:default",
- "core:app:default",
- "core:resources:default",
- "core:menu:default",
- "core:tray:default",
- "core:window:allow-create",
- "core:window:allow-maximize",
- "core:window:allow-toggle-maximize",
- "core:window:allow-unmaximize",
- "core:window:allow-minimize",
- "core:window:allow-unminimize",
- "core:window:allow-show",
- "core:window:allow-hide",
- "core:window:allow-close",
- "core:window:allow-set-decorations",
- "core:window:allow-start-dragging",
- "core:webview:allow-set-webview-zoom"
- ]
+ "identifier": "core",
+ "description": "",
+ "local": true,
+ "windows": ["main"],
+ "permissions": [
+ "core:default",
+ "core:path:default",
+ "core:event:default",
+ "core:window:default",
+ "core:app:default",
+ "core:resources:default",
+ "core:menu:default",
+ "core:tray:default",
+ "core:window:allow-create",
+ "core:window:allow-maximize",
+ "core:window:allow-toggle-maximize",
+ "core:window:allow-unmaximize",
+ "core:window:allow-minimize",
+ "core:window:allow-unminimize",
+ "core:window:allow-show",
+ "core:window:allow-hide",
+ "core:window:allow-close",
+ "core:window:allow-set-decorations",
+ "core:window:allow-start-dragging",
+ "core:webview:allow-set-webview-zoom"
+ ]
}
diff --git a/apps/app/capabilities/plugins.json b/apps/app/capabilities/plugins.json
index 26a0d64a..58ea35fb 100644
--- a/apps/app/capabilities/plugins.json
+++ b/apps/app/capabilities/plugins.json
@@ -1,46 +1,53 @@
{
- "identifier": "plugins",
- "description": "",
- "local": true,
- "windows": ["main"],
- "permissions": [
- "dialog:allow-open",
- "dialog:allow-confirm",
- "opener:default",
- "os:allow-platform",
- "os:allow-version",
- "os:allow-os-type",
- "os:allow-family",
- "os:allow-arch",
- "os:allow-exe-extension",
- "os:allow-locale",
- "os:allow-hostname",
- "deep-link:default",
- "window-state:default",
- "window-state:allow-restore-state",
- "window-state:allow-save-window-state",
-
- {
- "identifier": "http:default",
- "allow": [{ "url": "https://modrinth.com/*" }, { "url": "https://*.modrinth.com/*" }]
- },
-
- "auth:default",
- "import:default",
- "jre:default",
- "logs:default",
- "metadata:default",
- "minecraft-skins:default",
- "mr-auth:default",
- "profile-create:default",
- "pack:default",
- "process:default",
- "profile:default",
- "cache:default",
- "settings:default",
- "tags:default",
- "utils:default",
- "friends:default",
- "worlds:default"
- ]
+ "identifier": "plugins",
+ "description": "",
+ "local": true,
+ "windows": [
+ "main"
+ ],
+ "permissions": [
+ "dialog:allow-open",
+ "dialog:allow-confirm",
+ "opener:default",
+ "os:allow-platform",
+ "os:allow-version",
+ "os:allow-os-type",
+ "os:allow-family",
+ "os:allow-arch",
+ "os:allow-exe-extension",
+ "os:allow-locale",
+ "os:allow-hostname",
+ "deep-link:default",
+ "window-state:default",
+ "window-state:allow-restore-state",
+ "window-state:allow-save-window-state",
+ {
+ "identifier": "http:default",
+ "allow": [
+ {
+ "url": "https://modrinth.com/*"
+ },
+ {
+ "url": "https://*.modrinth.com/*"
+ }
+ ]
+ },
+ "auth:default",
+ "import:default",
+ "jre:default",
+ "logs:default",
+ "metadata:default",
+ "minecraft-skins:default",
+ "mr-auth:default",
+ "profile-create:default",
+ "pack:default",
+ "process:default",
+ "profile:default",
+ "cache:default",
+ "settings:default",
+ "tags:default",
+ "utils:default",
+ "friends:default",
+ "worlds:default"
+ ]
}
diff --git a/apps/app/capabilities/updater.json b/apps/app/capabilities/updater.json
index cdc28e94..6719d96a 100644
--- a/apps/app/capabilities/updater.json
+++ b/apps/app/capabilities/updater.json
@@ -1,7 +1,7 @@
{
- "identifier": "updater",
- "description": "",
- "local": true,
- "windows": ["main"],
- "permissions": ["updater:default"]
+ "identifier": "updater",
+ "description": "",
+ "local": true,
+ "windows": ["main"],
+ "permissions": ["updater:default"]
}
diff --git a/apps/app/nsis/hooks.nsi b/apps/app/nsis/hooks.nsi
index bfb20d68..4331240d 100644
--- a/apps/app/nsis/hooks.nsi
+++ b/apps/app/nsis/hooks.nsi
@@ -1,41 +1,67 @@
-!macro NSIS_HOOK_POSTINSTALL
- SetShellVarContext current
-
- IfFileExists "$LOCALAPPDATA${PRODUCTNAME}\theseus_gui.exe" file_found file_not_found
- file_found:
- Delete "$LOCALAPPDATA${PRODUCTNAME}\theseus_gui.exe"
-
- Delete "$LOCALAPPDATA${PRODUCTNAME}\uninstall.exe"
- RMDir "$LOCALAPPDATA${PRODUCTNAME}"
-
- !insertmacro DeleteAppUserModelId
-
- ; Remove start menu shortcut
- !insertmacro MUI_STARTMENU_GETFOLDER Application $AppStartMenuFolder
- !insertmacro IsShortcutTarget "$SMPROGRAMS$AppStartMenuFolder${PRODUCTNAME}.lnk" "$LOCALAPPDATA${PRODUCTNAME}\theseus_gui.exe"
- Pop $0
- ${If} $0 = 1
- !insertmacro UnpinShortcut "$SMPROGRAMS$AppStartMenuFolder${PRODUCTNAME}.lnk"
- Delete "$SMPROGRAMS$AppStartMenuFolder${PRODUCTNAME}.lnk"
- RMDir "$SMPROGRAMS$AppStartMenuFolder"
- ${EndIf}
- !insertmacro IsShortcutTarget "$SMPROGRAMS${PRODUCTNAME}.lnk" "$LOCALAPPDATA${PRODUCTNAME}\theseus_gui.exe"
- Pop $0
- ${If} $0 = 1
- !insertmacro UnpinShortcut "$SMPROGRAMS${PRODUCTNAME}.lnk"
- Delete "$SMPROGRAMS${PRODUCTNAME}.lnk"
- ${EndIf}
-
- !insertmacro IsShortcutTarget "$DESKTOP${PRODUCTNAME}.lnk" "$LOCALAPPDATA${PRODUCTNAME}\theseus_gui.exe"
- Pop $0
- ${If} $0 = 1
- !insertmacro UnpinShortcut "$DESKTOP${PRODUCTNAME}.lnk"
- Delete "$DESKTOP${PRODUCTNAME}.lnk"
- ${EndIf}
-
- DeleteRegKey HKCU "${UNINSTKEY}"
-
- goto end_of_test ;<== important for not continuing on the else branch
- file_not_found:
- end_of_test:
+; https://nsis.sourceforge.io/ShellExecWait
+!macro ShellExecWait verb app param workdir show exitoutvar ;only app and show must be != "", every thing else is optional
+ #define SEE_MASK_NOCLOSEPROCESS 0x40
+ System::Store S
+ !if "${NSIS_PTR_SIZE}" > 4
+ !define /ReDef /math SYSSIZEOF_SHELLEXECUTEINFO 14 * ${NSIS_PTR_SIZE}
+ !else ifndef SYSSIZEOF_SHELLEXECUTEINFO
+ !define SYSSIZEOF_SHELLEXECUTEINFO 60
+ !endif
+ System::Call '*(&i${SYSSIZEOF_SHELLEXECUTEINFO})i.r0'
+ System::Call '*$0(i ${SYSSIZEOF_SHELLEXECUTEINFO},i 0x40,p $hwndparent,t "${verb}",t $\'${app}$\',t $\'${param}$\',t "${workdir}",i ${show})p.r0'
+ System::Call 'shell32::ShellExecuteEx(t)(pr0)i.r1 ?e' ; (t) to trigger A/W selection
+ ${If} $1 <> 0
+ System::Call '*$0(is,i,p,p,p,p,p,p,p,p,p,p,p,p,p.r1)' ;stack value not really used, just a fancy pop ;)
+ System::Call 'kernel32::WaitForSingleObject(pr1,i-1)'
+ System::Call 'kernel32::GetExitCodeProcess(pr1,*i.s)'
+ System::Call 'kernel32::CloseHandle(pr1)'
+ ${EndIf}
+ System::Free $0
+ !if "${exitoutvar}" == ""
+ pop $0
+ !endif
+ System::Store L
+ !if "${exitoutvar}" != ""
+ pop ${exitoutvar}
+ !endif
+!macroend
+
+; --------------------------------------------------------------------------------
+
+Var /GLOBAL OldInstallDir
+
+!macro NSIS_HOOK_PREINSTALL
+ SetShellVarContext all
+ ${If} ${FileExists} "$SMPROGRAMS\${PRODUCTNAME}.lnk"
+ UserInfo::GetAccountType
+ Pop $0
+ ${If} $0 != "Admin"
+ MessageBox MB_ICONINFORMATION|MB_OK "An old installation of the Modrinth App was detected that requires administrator permission to update from. You will be prompted with an admin prompt shortly."
+ ${EndIf}
+
+ ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" ""
+ ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString"
+
+ ReadRegStr $OldInstallDir SHCTX "${UNINSTKEY}" "InstallLocation"
+ StrCpy $OldInstallDir $OldInstallDir "" 1
+ StrCpy $OldInstallDir $OldInstallDir -1 ""
+
+ DetailPrint "Executing $R1"
+ !insertmacro ShellExecWait "runas" '$R1' '/P _?=$4' "" ${SW_SHOW} $3
+ ${If} $3 <> 0
+ SetErrorLevel $3
+ MessageBox MB_ICONEXCLAMATION|MB_OK "Failed to uninstall old global installation"
+ Abort
+ ${EndIf}
+ ${EndIf}
+ SetShellVarContext current
+!macroend
+
+!macro NSIS_HOOK_POSTINSTALL
+ !insertmacro IsShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$OldInstallDir\${MAINBINARYNAME}.exe"
+ Pop $0
+ ${If} $0 = 1
+ !insertmacro SetShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
+ Return
+ ${EndIf}
!macroend
diff --git a/apps/app/package.json b/apps/app/package.json
index 43f01720..ddcd1d07 100644
--- a/apps/app/package.json
+++ b/apps/app/package.json
@@ -1,19 +1,21 @@
{
- "name": "@modrinth/app",
- "scripts": {
- "tauri": "tauri",
- "build": "tauri build",
- "dev": "tauri dev",
- "test": "cargo nextest run --all-targets --no-fail-fast",
- "lint": "cargo fmt --check && cargo clippy --all-targets",
- "fix": "cargo clippy --all-targets --fix --allow-dirty && cargo fmt"
- },
- "devDependencies": {
- "@tauri-apps/cli": "2.5.0"
- },
- "dependencies": {
- "@modrinth/app-frontend": "workspace:*",
- "@modrinth/app-lib": "workspace:*",
- "@modrinth/daedalus": "workspace:*"
- }
+ "name": "@modrinth/app",
+ "scripts": {
+ "tauri": "tauri",
+ "build": "tauri build",
+ "dev": "tauri dev",
+ "test": "cargo nextest run --all-targets --no-fail-fast",
+ "lint": "cargo fmt --check && cargo clippy --all-targets",
+ "lint:ancillary": "prettier --check .",
+ "fix": "cargo clippy --all-targets --fix --allow-dirty && cargo fmt",
+ "fix:ancillary": "prettier --write ."
+ },
+ "devDependencies": {
+ "@tauri-apps/cli": "2.5.0"
+ },
+ "dependencies": {
+ "@modrinth/app-frontend": "workspace:*",
+ "@modrinth/app-lib": "workspace:*",
+ "@modrinth/daedalus": "workspace:*"
+ }
}
diff --git a/apps/app/src/api/auth.rs b/apps/app/src/api/auth.rs
index cafb5958..c833fce6 100644
--- a/apps/app/src/api/auth.rs
+++ b/apps/app/src/api/auth.rs
@@ -122,16 +122,13 @@ pub async fn login(
.url()?
.as_str()
.starts_with("https://login.live.com/oauth20_desktop.srf")
- {
- if let Some((_, code)) =
+ && let Some((_, code)) =
window.url()?.query_pairs().find(|x| x.0 == "code")
- {
- window.close()?;
- let val =
- minecraft_auth::finish_login(&code.clone(), flow).await?;
+ {
+ window.close()?;
+ let val = minecraft_auth::finish_login(&code.clone(), flow).await?;
- return Ok(Some(val));
- }
+ return Ok(Some(val));
}
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
diff --git a/apps/app/src/api/profile.rs b/apps/app/src/api/profile.rs
index 1d812639..7a4cd375 100644
--- a/apps/app/src/api/profile.rs
+++ b/apps/app/src/api/profile.rs
@@ -250,7 +250,7 @@ pub async fn profile_get_pack_export_candidates(
// invoke('plugin:profile|profile_run', path)
#[tauri::command]
pub async fn profile_run(path: &str) -> Result {
- let process = profile::run(path, &QuickPlayType::None).await?;
+ let process = profile::run(path, QuickPlayType::None).await?;
Ok(process)
}
diff --git a/apps/app/src/api/utils.rs b/apps/app/src/api/utils.rs
index 3ced20de..94d8d2a6 100644
--- a/apps/app/src/api/utils.rs
+++ b/apps/app/src/api/utils.rs
@@ -103,11 +103,11 @@ pub async fn should_disable_mouseover() -> bool {
// We try to match version to 12.2 or higher. If unrecognizable to pattern or lower, we default to the css with disabled mouseover for safety
if let tauri_plugin_os::Version::Semantic(major, minor, _) =
tauri_plugin_os::version()
+ && major >= 12
+ && minor >= 3
{
- if major >= 12 && minor >= 3 {
- // Mac os version is 12.3 or higher, we allow mouseover
- return false;
- }
+ // Mac os version is 12.3 or higher, we allow mouseover
+ return false;
}
true
} else {
diff --git a/apps/app/src/api/worlds.rs b/apps/app/src/api/worlds.rs
index 544ce05d..5ef65de2 100644
--- a/apps/app/src/api/worlds.rs
+++ b/apps/app/src/api/worlds.rs
@@ -4,9 +4,10 @@ use enumset::EnumSet;
use tauri::{AppHandle, Manager, Runtime};
use theseus::prelude::ProcessMetadata;
use theseus::profile::{QuickPlayType, get_full_path};
+use theseus::server_address::ServerAddress;
use theseus::worlds::{
- DisplayStatus, ServerPackStatus, ServerStatus, World, WorldType,
- WorldWithProfile,
+ DisplayStatus, ProtocolVersion, ServerPackStatus, ServerStatus, World,
+ WorldType, WorldWithProfile,
};
use theseus::{profile, worlds};
@@ -183,14 +184,16 @@ pub async fn remove_server_from_profile(
}
#[tauri::command]
-pub async fn get_profile_protocol_version(path: &str) -> Result> {
+pub async fn get_profile_protocol_version(
+ path: &str,
+) -> Result > {
Ok(worlds::get_profile_protocol_version(path).await?)
}
#[tauri::command]
pub async fn get_server_status(
address: &str,
- protocol_version: Option,
+ protocol_version: Option,
) -> Result {
Ok(worlds::get_server_status(address, protocol_version).await?)
}
@@ -201,7 +204,7 @@ pub async fn start_join_singleplayer_world(
world: String,
) -> Result {
let process =
- profile::run(path, &QuickPlayType::Singleplayer(world)).await?;
+ profile::run(path, QuickPlayType::Singleplayer(world)).await?;
Ok(process)
}
@@ -211,8 +214,11 @@ pub async fn start_join_server(
path: &str,
address: &str,
) -> Result {
- let process =
- profile::run(path, &QuickPlayType::Server(address.to_owned())).await?;
+ let process = profile::run(
+ path,
+ QuickPlayType::Server(ServerAddress::Unresolved(address.to_owned())),
+ )
+ .await?;
Ok(process)
}
diff --git a/apps/app/src/main.rs b/apps/app/src/main.rs
index 94427776..aecaf1bc 100644
--- a/apps/app/src/main.rs
+++ b/apps/app/src/main.rs
@@ -243,10 +243,10 @@ fn main() {
});
#[cfg(not(target_os = "linux"))]
- if let Some(window) = app.get_window("main") {
- if let Err(e) = window.set_shadow(true) {
- tracing::warn!("Failed to set window shadow: {e}");
- }
+ if let Some(window) = app.get_window("main")
+ && let Err(e) = window.set_shadow(true)
+ {
+ tracing::warn!("Failed to set window shadow: {e}");
}
Ok(())
diff --git a/apps/app/tauri.conf.json b/apps/app/tauri.conf.json
index 78086935..f2a6bf38 100644
--- a/apps/app/tauri.conf.json
+++ b/apps/app/tauri.conf.json
@@ -1,100 +1,114 @@
{
- "$schema": "https://schema.tauri.app/config/2",
- "build": {
- "beforeDevCommand": "pnpm turbo run dev --filter=@modrinth/app-frontend",
- "beforeBuildCommand": "pnpm turbo run build --filter=@modrinth/app-frontend",
- "frontendDist": "../app-frontend/dist",
- "devUrl": "http://localhost:1420"
- },
- "bundle": {
- "active": true,
- "category": "Game",
- "copyright": "",
- "targets": "all",
- "externalBin": [],
- "icon": ["icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"],
- "windows": {
- "nsis": {
- "installMode": "perMachine",
- "installerHooks": "./nsis/hooks.nsi"
- }
- },
- "longDescription": "",
- "macOS": {
- "entitlements": "App.entitlements",
- "exceptionDomain": "",
- "frameworks": [],
- "providerShortName": null,
- "signingIdentity": null
- },
- "shortDescription": "",
- "linux": {
- "deb": {
- "depends": []
- }
- },
- "fileAssociations": [
- {
- "ext": ["mrpack"],
- "mimeType": "application/x-modrinth-modpack+zip"
- }
- ]
- },
- "productName": "AstralRinth App",
- "version": "0.10.305",
- "mainBinaryName": "AstralRinth App",
- "identifier": "AstralRinthApp",
- "plugins": {
- "deep-link": {
- "desktop": {
- "schemes": ["modrinth"]
- },
- "mobile": []
- }
- },
- "app": {
- "withGlobalTauri": false,
- "macOSPrivateApi": true,
- "windows": [
- {
- "titleBarStyle": "Overlay",
- "hiddenTitle": true,
- "fullscreen": false,
- "height": 800,
- "resizable": true,
- "title": "AstralRinth",
- "label": "main",
- "width": 1280,
- "minHeight": 700,
- "minWidth": 1100,
- "visible": true,
- "zoomHotkeysEnabled": false,
- "decorations": false
- }
- ],
- "security": {
- "assetProtocol": {
- "scope": [
- "$APPDATA/caches/icons/*",
- "$APPCONFIG/caches/icons/*",
- "$CONFIG/caches/icons/*",
- "$APPDATA/profiles/*/saves/*/icon.png",
- "$APPCONFIG/profiles/*/saves/*/icon.png",
- "$CONFIG/profiles/*/saves/*/icon.png"
- ],
- "enable": true
- },
- "capabilities": ["core", "plugins"],
- "csp": {
- "default-src": "'self' customprotocol: asset:",
- "connect-src": "ipc: https://git.astralium.su https://authserver.ely.by http://ipc.localhost https://modrinth.com https://*.modrinth.com https://*.posthog.com https://*.sentry.io https://api.mclo.gs 'self' data: blob:",
- "font-src": ["https://cdn-raw.modrinth.com/fonts/"],
- "img-src": "https: 'unsafe-inline' 'self' asset: http://asset.localhost http://textures.minecraft.net blob: data:",
- "style-src": "'unsafe-inline' 'self'",
- "script-src": "https://*.posthog.com 'self'",
- "frame-src": "https://www.youtube.com https://www.youtube-nocookie.com https://discord.com 'self'",
- "media-src": "https://*.githubusercontent.com"
- }
- }
- }
+ "$schema": "https://schema.tauri.app/config/2",
+ "build": {
+ "beforeDevCommand": "pnpm turbo run dev --filter=@modrinth/app-frontend",
+ "beforeBuildCommand": "pnpm turbo run build --filter=@modrinth/app-frontend",
+ "frontendDist": "../app-frontend/dist",
+ "devUrl": "http://localhost:1420"
+ },
+ "bundle": {
+ "active": true,
+ "category": "Game",
+ "copyright": "",
+ "targets": "all",
+ "externalBin": [],
+ "icon": [
+ "icons/128x128.png",
+ "icons/128x128@2x.png",
+ "icons/icon.icns",
+ "icons/icon.ico"
+ ],
+ "windows": {
+ "nsis": {
+ "installMode": "currentUser",
+ "installerHooks": "./nsis/hooks.nsi"
+ }
+ },
+ "longDescription": "",
+ "macOS": {
+ "entitlements": "App.entitlements",
+ "exceptionDomain": "",
+ "frameworks": [],
+ "providerShortName": null,
+ "signingIdentity": null
+ },
+ "shortDescription": "",
+ "linux": {
+ "deb": {
+ "depends": []
+ }
+ },
+ "fileAssociations": [
+ {
+ "ext": [
+ "mrpack"
+ ],
+ "mimeType": "application/x-modrinth-modpack+zip"
+ }
+ ]
+ },
+ "productName": "AstralRinth App",
+ "version": "0.10.601",
+ "mainBinaryName": "AstralRinth App",
+ "identifier": "AstralRinthApp",
+ "plugins": {
+ "deep-link": {
+ "desktop": {
+ "schemes": [
+ "modrinth"
+ ]
+ },
+ "mobile": []
+ }
+ },
+ "app": {
+ "withGlobalTauri": false,
+ "macOSPrivateApi": true,
+ "windows": [
+ {
+ "titleBarStyle": "Overlay",
+ "hiddenTitle": true,
+ "fullscreen": false,
+ "height": 800,
+ "resizable": true,
+ "title": "AstralRinth",
+ "label": "main",
+ "width": 1280,
+ "minHeight": 700,
+ "minWidth": 1100,
+ "visible": true,
+ "zoomHotkeysEnabled": false,
+ "decorations": false
+ }
+ ],
+ "security": {
+ "assetProtocol": {
+ "scope": [
+ "$APPDATA/caches/icons/*",
+ "$APPCONFIG/caches/icons/*",
+ "$CONFIG/caches/icons/*",
+ "$APPDATA/profiles/*/saves/*/icon.png",
+ "$APPCONFIG/profiles/*/saves/*/icon.png",
+ "$CONFIG/profiles/*/saves/*/icon.png"
+ ],
+ "enable": true
+ },
+ "capabilities": [
+ "core",
+ "plugins"
+ ],
+ "csp": {
+ "default-src": "'self' customprotocol: asset:",
+ "connect-src": "ipc: https://git.astralium.su https://authserver.ely.by http://ipc.localhost https://modrinth.com https://*.modrinth.com https://*.posthog.com https://*.sentry.io https://api.mclo.gs 'self' data: blob:",
+ "font-src": [
+ "https://cdn-raw.modrinth.com/fonts/"
+ ],
+ "img-src": "https: 'unsafe-inline' 'self' asset: http://asset.localhost http://textures.minecraft.net blob: data:",
+ "style-src": "'unsafe-inline' 'self'",
+ "script-src": "https://*.posthog.com https://tally.so/widgets/embed.js 'self'",
+ "frame-src": "https://www.youtube.com https://www.youtube-nocookie.com https://discord.com https://tally.so/popup/ 'self'",
+ "media-src": "https://*.githubusercontent.com"
+ }
+ }
+ }
}
diff --git a/apps/app/tauri.linux.conf.json b/apps/app/tauri.linux.conf.json
index 2dfc6edd..5b2e9ec6 100644
--- a/apps/app/tauri.linux.conf.json
+++ b/apps/app/tauri.linux.conf.json
@@ -1,3 +1,3 @@
{
- "mainBinaryName": "ModrinthApp"
+ "mainBinaryName": "ModrinthApp"
}
diff --git a/apps/app/tauri.macos.conf.json b/apps/app/tauri.macos.conf.json
index 36a54d5c..363f00e8 100644
--- a/apps/app/tauri.macos.conf.json
+++ b/apps/app/tauri.macos.conf.json
@@ -1,20 +1,24 @@
{
- "app": {
- "windows": [
- {
- "titleBarStyle": "Overlay",
- "hiddenTitle": true,
- "fullscreen": false,
- "height": 800,
- "resizable": true,
- "title": "AstralRinth",
- "width": 1280,
- "minHeight": 700,
- "minWidth": 1100,
- "visible": false,
- "zoomHotkeysEnabled": false,
- "decorations": true
- }
- ]
- }
+ "app": {
+ "windows": [
+ {
+ "titleBarStyle": "Overlay",
+ "hiddenTitle": true,
+ "fullscreen": false,
+ "height": 800,
+ "resizable": true,
+ "title": "Modrinth App",
+ "width": 1280,
+ "minHeight": 700,
+ "minWidth": 1100,
+ "visible": false,
+ "zoomHotkeysEnabled": false,
+ "decorations": true,
+ "trafficLightPosition": {
+ "x": 15.0,
+ "y": 22.0
+ }
+ }
+ ]
+ }
}
diff --git a/apps/app/turbo.jsonc b/apps/app/turbo.jsonc
index 7cdf6bd4..91b8afaa 100644
--- a/apps/app/turbo.jsonc
+++ b/apps/app/turbo.jsonc
@@ -1,14 +1,14 @@
{
- "$schema": "../../node_modules/turbo/schema.json",
- "extends": ["//"],
- "tasks": {
- // Running Clippy and tests on a Tauri application requires
- // the frontend to be built at least once first
- "lint": {
- "dependsOn": ["@modrinth/app-frontend#build"]
- },
- "test": {
- "dependsOn": ["@modrinth/app-frontend#build"]
- }
- }
+ "$schema": "../../node_modules/turbo/schema.json",
+ "extends": ["//"],
+ "tasks": {
+ // Running Clippy and tests on a Tauri application requires
+ // the frontend to be built at least once first
+ "lint": {
+ "dependsOn": ["@modrinth/app-frontend#build"]
+ },
+ "test": {
+ "dependsOn": ["@modrinth/app-frontend#build"]
+ }
+ }
}
diff --git a/apps/daedalus_client/.prettierignore b/apps/daedalus_client/.prettierignore
new file mode 100644
index 00000000..ecc487ec
--- /dev/null
+++ b/apps/daedalus_client/.prettierignore
@@ -0,0 +1 @@
+**/*.rs
diff --git a/apps/daedalus_client/Cargo.toml b/apps/daedalus_client/Cargo.toml
index ffec1a47..feb1f52d 100644
--- a/apps/daedalus_client/Cargo.toml
+++ b/apps/daedalus_client/Cargo.toml
@@ -16,7 +16,14 @@ serde_json.workspace = true
serde-xml-rs.workspace = true
thiserror.workspace = true
reqwest = { workspace = true, features = ["stream", "json", "rustls-tls-native-roots"] }
-async_zip = { workspace = true, features = ["chrono", "tokio-fs", "deflate", "bzip2", "zstd", "deflate64"] }
+async_zip = { workspace = true, features = [
+ "chrono",
+ "tokio-fs",
+ "deflate",
+ "bzip2",
+ "zstd",
+ "deflate64",
+] }
chrono = { workspace = true, features = ["serde"] }
bytes.workspace = true
rust-s3.workspace = true
diff --git a/apps/daedalus_client/Dockerfile b/apps/daedalus_client/Dockerfile
index 271c829a..e5f083fc 100644
--- a/apps/daedalus_client/Dockerfile
+++ b/apps/daedalus_client/Dockerfile
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
-FROM rust:1.88.0 AS build
+FROM rust:1.89.0 AS build
WORKDIR /usr/src/daedalus
COPY . .
@@ -17,6 +17,11 @@ RUN --mount=type=cache,target=/usr/src/daedalus/target \
FROM debian:bookworm-slim
+LABEL org.opencontainers.image.source=https://github.com/modrinth/code
+LABEL org.opencontainers.image.title=daedalus
+LABEL org.opencontainers.image.description="Modrinth game metadata query client"
+LABEL org.opencontainers.image.licenses=MIT
+
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates openssl \
&& rm -rf /var/lib/apt/lists/*
diff --git a/apps/daedalus_client/library-patches.json b/apps/daedalus_client/library-patches.json
index 10987aff..fa9bfe93 100644
--- a/apps/daedalus_client/library-patches.json
+++ b/apps/daedalus_client/library-patches.json
@@ -1,2780 +1,2780 @@
[
- {
- "_comment": "Only allow osx-arm64 for existing LWJGL 3.3.2/3.3.3",
- "match": [
- "org.lwjgl:lwjgl-freetype-natives-macos-arm64:3.3.2",
- "org.lwjgl:lwjgl-glfw-natives-macos-arm64:3.3.2",
- "org.lwjgl:lwjgl-jemalloc-natives-macos-arm64:3.3.2",
- "org.lwjgl:lwjgl-openal-natives-macos-arm64:3.3.2",
- "org.lwjgl:lwjgl-opengl-natives-macos-arm64:3.3.2",
- "org.lwjgl:lwjgl-stb-natives-macos-arm64:3.3.2",
- "org.lwjgl:lwjgl-tinyfd-natives-macos-arm64:3.3.2",
- "org.lwjgl:lwjgl-natives-macos-arm64:3.3.2",
- "org.lwjgl:lwjgl-freetype-natives-macos-arm64:3.3.3",
- "org.lwjgl:lwjgl-glfw-natives-macos-arm64:3.3.3",
- "org.lwjgl:lwjgl-jemalloc-natives-macos-arm64:3.3.3",
- "org.lwjgl:lwjgl-openal-natives-macos-arm64:3.3.3",
- "org.lwjgl:lwjgl-opengl-natives-macos-arm64:3.3.3",
- "org.lwjgl:lwjgl-stb-natives-macos-arm64:3.3.3",
- "org.lwjgl:lwjgl-tinyfd-natives-macos-arm64:3.3.3",
- "org.lwjgl:lwjgl-natives-macos-arm64:3.3.3"
- ],
- "override": {
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- }
- },
- {
- "_comment": "Only allow windows-arm64 for existing LWJGL 3.3.2/3.3.3",
- "match": [
- "org.lwjgl:lwjgl-freetype-natives-windows-arm64:3.3.2",
- "org.lwjgl:lwjgl-glfw-natives-windows-arm64:3.3.2",
- "org.lwjgl:lwjgl-jemalloc-natives-windows-arm64:3.3.2",
- "org.lwjgl:lwjgl-openal-natives-windows-arm64:3.3.2",
- "org.lwjgl:lwjgl-opengl-natives-windows-arm64:3.3.2",
- "org.lwjgl:lwjgl-stb-natives-windows-arm64:3.3.2",
- "org.lwjgl:lwjgl-tinyfd-natives-windows-arm64:3.3.2",
- "org.lwjgl:lwjgl-natives-windows-arm64:3.3.2",
- "org.lwjgl:lwjgl-freetype-natives-windows-arm64:3.3.3",
- "org.lwjgl:lwjgl-glfw-natives-windows-arm64:3.3.3",
- "org.lwjgl:lwjgl-jemalloc-natives-windows-arm64:3.3.3",
- "org.lwjgl:lwjgl-openal-natives-windows-arm64:3.3.3",
- "org.lwjgl:lwjgl-opengl-natives-windows-arm64:3.3.3",
- "org.lwjgl:lwjgl-stb-natives-windows-arm64:3.3.3",
- "org.lwjgl:lwjgl-tinyfd-natives-windows-arm64:3.3.3",
- "org.lwjgl:lwjgl-natives-windows-arm64:3.3.3"
- ],
- "override": {
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "windows-arm64"
- }
- }
- ]
- }
- },
- {
- "_comment": "Add missing tinyfd to the broken LWJGL 3.2.2 variant",
- "match": ["org.lwjgl:lwjgl:3.2.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "fcbe606c8f8da6f8f9a05e2c540eb1ee8632b0e9",
- "size": 7092,
- "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd:3.2.2"
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "fcbe606c8f8da6f8f9a05e2c540eb1ee8632b0e9",
- "size": 7092,
- "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2.jar"
- },
- "classifiers": {
- "natives-linux": {
- "sha1": "39e35b161c130635d9c8918ce04e887a30c5b687",
- "size": 38804,
- "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2-natives-linux.jar"
- },
- "natives-macos": {
- "sha1": "46d0798228b8a28e857a2a0f02310fd6ba2a4eab",
- "size": 42136,
- "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2-natives-macos.jar"
- },
- "natives-windows": {
- "sha1": "e9115958773644e863332a6a06488d26f9e1fc9f",
- "size": 208314,
- "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2-natives-windows.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd:3.2.2",
- "natives": {
- "linux": "natives-linux",
- "osx": "natives-macos",
- "windows": "natives-windows"
- }
- }
- ],
- "patchAdditionalLibraries": true
- },
- {
- "_comment": "Add additional library just for osx-arm64. No override needed",
- "match": ["ca.weblite:java-objc-bridge:1.0.0"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "369a83621e3c65496348491e533cb97fe5f2f37d",
- "size": 91947,
- "url": "https://github.com/MinecraftMachina/Java-Objective-C-Bridge/releases/download/1.1.0-mmachina.1/java-objc-bridge-1.1.jar"
- }
- },
- "name": "ca.weblite:java-objc-bridge:1.1.0-mmachina.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add additional classifiers for jinput-platform",
- "match": ["net.java.jinput:jinput-platform:2.0.5"],
- "override": {
- "downloads": {
- "classifiers": {
- "natives-osx-arm64": {
- "sha1": "5189eb40db3087fb11ca063b68fa4f4c20b199dd",
- "size": 10031,
- "url": "https://github.com/r58Playz/jinput-m1/raw/main/plugins/OSX/bin/jinput-platform-2.0.5.jar"
- },
- "natives-linux-arm64": {
- "sha1": "42b388ccb7c63cec4e9f24f4dddef33325f8b212",
- "size": 10932,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-2.9.4/jinput-platform-2.0.5-natives-linux.jar"
- },
- "natives-linux-arm32": {
- "sha1": "f3c455b71c5146acb5f8a9513247fc06db182fd5",
- "size": 4521,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-2.9.4/jinput-platform-2.0.5-natives-linux.jar"
- }
- }
- },
- "natives": {
- "linux-arm64": "natives-linux-arm64",
- "linux-arm32": "natives-linux-arm32",
- "osx-arm64": "natives-osx-arm64"
- }
- }
- },
- {
- "_comment": "Use a newer version on osx-arm64",
- "match": [
- "com.mojang:text2speech:1.0.10",
- "com.mojang:text2speech:1.5",
- "com.mojang:text2speech:1.6",
- "com.mojang:text2speech:1.7",
- "com.mojang:text2speech:1.10.1",
- "com.mojang:text2speech:1.10.3",
- "com.mojang:text2speech:1.11.2"
- ],
- "override": {
- "rules": [
- {
- "action": "allow"
- },
- {
- "action": "disallow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "f378f889797edd7df8d32272c06ca80a1b6b0f58",
- "size": 13164,
- "url": "https://libraries.minecraft.net/com/mojang/text2speech/1.11.3/text2speech-1.11.3.jar"
- }
- },
- "name": "com.mojang:text2speech:1.11.3",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Use a newer version on osx-arm64, linux-arm64, and linux-arm32",
- "match": [
- "org.lwjgl.lwjgl:lwjgl:2.9.3",
- "org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20131120",
- "org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20131017",
- "org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20130708-debug3",
- "org.lwjgl.lwjgl:lwjgl:2.9.1"
- ],
- "override": {
- "rules": [
- {
- "action": "allow"
- },
- {
- "action": "disallow",
- "os": {
- "name": "osx-arm64"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm64"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "697517568c68e78ae0b4544145af031c81082dfe",
- "size": 1047168,
- "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar"
- }
- },
- "name": "org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- },
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- },
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Use a newer version on osx-arm64, linux-arm64, and linux-arm32",
- "match": [
- "org.lwjgl.lwjgl:lwjgl_util:2.9.3",
- "org.lwjgl.lwjgl:lwjgl_util:2.9.1-nightly-20131120",
- "org.lwjgl.lwjgl:lwjgl_util:2.9.1-nightly-20131017",
- "org.lwjgl.lwjgl:lwjgl_util:2.9.1-nightly-20130708-debug3",
- "org.lwjgl.lwjgl:lwjgl_util:2.9.1"
- ],
- "override": {
- "rules": [
- {
- "action": "allow"
- },
- {
- "action": "disallow",
- "os": {
- "name": "osx-arm64"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm64"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "d51a7c040a721d13efdfbd34f8b257b2df882ad0",
- "size": 173887,
- "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.4-nightly-20150209/lwjgl_util-2.9.4-nightly-20150209.jar"
- }
- },
- "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- },
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- },
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
- "match": [
- "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
- "org.lwjgl.lwjgl:lwjgl-platform:2.9.3",
- "org.lwjgl.lwjgl:lwjgl-platform:2.9.1-nightly-20131120",
- "org.lwjgl.lwjgl:lwjgl-platform:2.9.1-nightly-20131017",
- "org.lwjgl.lwjgl:lwjgl-platform:2.9.1-nightly-20130708-debug3",
- "org.lwjgl.lwjgl:lwjgl-platform:2.9.1"
- ],
- "override": {
- "downloads": {
- "classifiers": {
- "natives-osx-arm64": {
- "sha1": "eff546c0b319d6ffc7a835652124c18089c67f36",
- "size": 488316,
- "url": "https://github.com/MinecraftMachina/lwjgl/releases/download/2.9.4-20150209-mmachina.2/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"
- },
- "natives-linux-arm64": {
- "sha1": "63ac7da0f4a4785c7eadc0f8edc1e9dcc4dd08cb",
- "size": 579979,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-2.9.4/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar"
- },
- "natives-linux-arm32": {
- "sha1": "fa483e540a9a753a5ffbb23dcf7879a5bf752611",
- "size": 475177,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-2.9.4/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar"
- }
- }
- },
- "natives": {
- "linux-arm64": "natives-linux-arm64",
- "linux-arm32": "natives-linux-arm32",
- "osx-arm64": "natives-osx-arm64"
- }
- }
- },
- {
- "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
- "match": [
- "org.lwjgl:lwjgl-glfw:3.2.2",
- "org.lwjgl:lwjgl-glfw:3.2.1",
- "org.lwjgl:lwjgl-glfw:3.1.6",
- "org.lwjgl:lwjgl-glfw:3.1.2"
- ],
- "override": {
- "rules": [
- {
- "action": "allow"
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm64"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm32"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "155d175037efc76630940c197ca6dea2b17d7e18",
- "size": 108691,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-glfw.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-glfw:3.2.2-gman64.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "155d175037efc76630940c197ca6dea2b17d7e18",
- "size": 108691,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-glfw.jar"
- },
- "classifiers": {
- "natives-linux-arm64": {
- "sha1": "074ad243761147df0d060fbefc814614d2ff75cc",
- "size": 85072,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-glfw-natives-linux-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-glfw:3.2.2-gman64.1",
- "natives": {
- "linux-arm64": "natives-linux-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "99e9a39fa8ed4167e3ff9e04d47eb32c9e69804d",
- "size": 108691,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-glfw.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-glfw:3.2.2-gman32.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "99e9a39fa8ed4167e3ff9e04d47eb32c9e69804d",
- "size": 108691,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-glfw.jar"
- },
- "classifiers": {
- "natives-linux-arm32": {
- "sha1": "4265f2fbe3b9d642591165165a17cf406cf7b98e",
- "size": 80186,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-glfw-natives-linux-arm32.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-glfw:3.2.2-gman32.1",
- "natives": {
- "linux-arm32": "natives-linux-arm32"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "e9a101bca4fa30d26b21b526ff28e7c2d8927f1b",
- "size": 130128,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-glfw.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-glfw:3.3.1-mmachina.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "e9a101bca4fa30d26b21b526ff28e7c2d8927f1b",
- "size": 130128,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-glfw.jar"
- },
- "classifiers": {
- "natives-osx-arm64": {
- "sha1": "71d793d0a5a42e3dfe78eb882abc2523a2c6b496",
- "size": 129076,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-glfw-natives-macos-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-glfw:3.3.1-mmachina.1",
- "natives": {
- "osx-arm64": "natives-osx-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
- "match": [
- "org.lwjgl:lwjgl-jemalloc:3.2.2",
- "org.lwjgl:lwjgl-jemalloc:3.2.1",
- "org.lwjgl:lwjgl-jemalloc:3.1.6",
- "org.lwjgl:lwjgl-jemalloc:3.1.2"
- ],
- "override": {
- "rules": [
- {
- "action": "allow"
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm64"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm32"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "cc04eec29b2fa8c298791af9800a3766d9617954",
- "size": 33790,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-jemalloc.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-jemalloc:3.2.2-gman64.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "cc04eec29b2fa8c298791af9800a3766d9617954",
- "size": 33790,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-jemalloc.jar"
- },
- "classifiers": {
- "natives-linux-arm64": {
- "sha1": "762d7d80c9cdf3a3f3fc80c8a5f86612255edfe0",
- "size": 156343,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-jemalloc-patched-natives-linux-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-jemalloc:3.2.2-gman64.2",
- "natives": {
- "linux-arm64": "natives-linux-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "8224ae2e8fc6d8e1a0fc7d84dc917aa3c440620c",
- "size": 33790,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-jemalloc.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-jemalloc:3.2.2-gman32.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "8224ae2e8fc6d8e1a0fc7d84dc917aa3c440620c",
- "size": 33790,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-jemalloc.jar"
- },
- "classifiers": {
- "natives-linux-arm32": {
- "sha1": "9163a2a5559ef87bc13ead8fea84417ea3928748",
- "size": 134237,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-jemalloc-natives-linux-arm32.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-jemalloc:3.2.2-gman32.1",
- "natives": {
- "linux-arm32": "natives-linux-arm32"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "4fb94224378d3588d52d2beb172f2eeafea2d546",
- "size": 36976,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-jemalloc.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-jemalloc:3.3.1-mmachina.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "4fb94224378d3588d52d2beb172f2eeafea2d546",
- "size": 36976,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-jemalloc.jar"
- },
- "classifiers": {
- "natives-osx-arm64": {
- "sha1": "b0be721188d2e7195798780b1c5fe7eafe8091c1",
- "size": 103478,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-jemalloc-natives-macos-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-jemalloc:3.3.1-mmachina.1",
- "natives": {
- "osx-arm64": "natives-osx-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
- "match": [
- "org.lwjgl:lwjgl-openal:3.2.2",
- "org.lwjgl:lwjgl-openal:3.2.1",
- "org.lwjgl:lwjgl-openal:3.1.6",
- "org.lwjgl:lwjgl-openal:3.1.2"
- ],
- "override": {
- "rules": [
- {
- "action": "allow"
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm64"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm32"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "6dfce9dc6a9629c75b2ae01a8df7e7be80ba0261",
- "size": 79582,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-openal.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-openal:3.2.2-gman64.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "6dfce9dc6a9629c75b2ae01a8df7e7be80ba0261",
- "size": 79582,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-openal.jar"
- },
- "classifiers": {
- "natives-linux-arm64": {
- "sha1": "948e415b5b2a2c650c25b377a4a9f443b21ce92e",
- "size": 469432,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-openal-natives-linux-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-openal:3.2.2-gman64.1",
- "natives": {
- "linux-arm64": "natives-linux-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "304f0571fd5971621ee6da86a4c1e90f6f52e2ee",
- "size": 79582,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-openal.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-openal:3.2.2-gman32.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "304f0571fd5971621ee6da86a4c1e90f6f52e2ee",
- "size": 79582,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-openal.jar"
- },
- "classifiers": {
- "natives-linux-arm32": {
- "sha1": "ecbc981fdd996492a1f6334f003ed62e5a8c0cd5",
- "size": 398418,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-openal-natives-linux-arm32.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-openal:3.2.2-gman32.1",
- "natives": {
- "linux-arm32": "natives-linux-arm32"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "d48e753d85916fc8a200ccddc709b36e3865cc4e",
- "size": 88880,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-openal.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-openal:3.3.1-mmachina.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "d48e753d85916fc8a200ccddc709b36e3865cc4e",
- "size": 88880,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-openal.jar"
- },
- "classifiers": {
- "natives-osx-arm64": {
- "sha1": "6b80fc0b982a0723b141e88859c42d6f71bd723f",
- "size": 346131,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-openal-natives-macos-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-openal:3.3.1-mmachina.1",
- "natives": {
- "osx-arm64": "natives-osx-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
- "match": [
- "org.lwjgl:lwjgl-opengl:3.2.2",
- "org.lwjgl:lwjgl-opengl:3.2.1",
- "org.lwjgl:lwjgl-opengl:3.1.6",
- "org.lwjgl:lwjgl-opengl:3.1.2"
- ],
- "override": {
- "rules": [
- {
- "action": "allow"
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm64"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm32"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "198bc2f72e0b2eb401eb6f5999aea52909b31ac4",
- "size": 937609,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-opengl.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-opengl:3.2.2-gman64.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "198bc2f72e0b2eb401eb6f5999aea52909b31ac4",
- "size": 937609,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-opengl.jar"
- },
- "classifiers": {
- "natives-linux-arm64": {
- "sha1": "bd40897077bf7d12f562da898b18ac2c68e1f9d7",
- "size": 56109,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-opengl-natives-linux-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-opengl:3.2.2-gman64.1",
- "natives": {
- "linux-arm64": "natives-linux-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "9762ae928d02147e716cd82e929b74a97ea9600a",
- "size": 937609,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-opengl.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-opengl:3.2.2-gman32.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "9762ae928d02147e716cd82e929b74a97ea9600a",
- "size": 937609,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-opengl.jar"
- },
- "classifiers": {
- "natives-linux-arm32": {
- "sha1": "3af5599c74dd76dd8dbb567b3f9b4963a6abeed5",
- "size": 56388,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-opengl-natives-linux-arm32.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-opengl:3.2.2-gman32.1",
- "natives": {
- "linux-arm32": "natives-linux-arm32"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "962c2a8d2a8cdd3b89de3d78d766ab5e2133c2f4",
- "size": 929233,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-opengl.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-opengl:3.3.1-mmachina.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "962c2a8d2a8cdd3b89de3d78d766ab5e2133c2f4",
- "size": 929233,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-opengl.jar"
- },
- "classifiers": {
- "natives-osx-arm64": {
- "sha1": "bb575058e0372f515587b5d2d04ff7db185f3ffe",
- "size": 41667,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-opengl-natives-macos-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-opengl:3.3.1-mmachina.1",
- "natives": {
- "osx-arm64": "natives-osx-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
- "match": [
- "org.lwjgl:lwjgl-stb:3.2.2",
- "org.lwjgl:lwjgl-stb:3.2.1",
- "org.lwjgl:lwjgl-stb:3.1.6",
- "org.lwjgl:lwjgl-stb:3.1.2"
- ],
- "override": {
- "rules": [
- {
- "action": "allow"
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm64"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm32"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "46a5735f3eb9d17eb5dcbdd5afa194066d2a6555",
- "size": 104075,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-stb.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-stb:3.2.2-gman64.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "46a5735f3eb9d17eb5dcbdd5afa194066d2a6555",
- "size": 104075,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-stb.jar"
- },
- "classifiers": {
- "natives-linux-arm64": {
- "sha1": "077efa7d7ea41b32df5c6078e912e724cccd06db",
- "size": 202038,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-stb-natives-linux-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-stb:3.2.2-gman64.1",
- "natives": {
- "linux-arm64": "natives-linux-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "ea979b0af45b8e689f5f47c989aa8550c148d8a2",
- "size": 104075,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-stb.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-stb:3.2.2-gman32.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "ea979b0af45b8e689f5f47c989aa8550c148d8a2",
- "size": 104075,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-stb.jar"
- },
- "classifiers": {
- "natives-linux-arm32": {
- "sha1": "ec9d70aaebd0ff76dfeecf8f00b56118bf3706b1",
- "size": 149387,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-stb-natives-linux-arm32.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-stb:3.2.2-gman32.1",
- "natives": {
- "linux-arm32": "natives-linux-arm32"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "703e4b533e2542560e9f94d6d8bd148be1c1d572",
- "size": 113273,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-stb.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-stb:3.3.1-mmachina.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "703e4b533e2542560e9f94d6d8bd148be1c1d572",
- "size": 113273,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-stb.jar"
- },
- "classifiers": {
- "natives-osx-arm64": {
- "sha1": "98f0ad956c754723ef354d50057cc30417ef376a",
- "size": 178409,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-stb-natives-macos-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-stb:3.3.1-mmachina.1",
- "natives": {
- "osx-arm64": "natives-osx-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
- "match": [
- "org.lwjgl:lwjgl-tinyfd:3.2.2",
- "org.lwjgl:lwjgl-tinyfd:3.2.1",
- "org.lwjgl:lwjgl-tinyfd:3.1.6",
- "org.lwjgl:lwjgl-tinyfd:3.1.2"
- ],
- "override": {
- "rules": [
- {
- "action": "allow"
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm64"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm32"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "3a75b9811607633bf33c978f53964df1534a4bc1",
- "size": 5571,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-tinyfd.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd:3.2.2-gman64.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "3a75b9811607633bf33c978f53964df1534a4bc1",
- "size": 5571,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-tinyfd.jar"
- },
- "classifiers": {
- "natives-linux-arm64": {
- "sha1": "37c744ca289b5d7ae155d79e39029488b3254e5b",
- "size": 37893,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-tinyfd-natives-linux-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd:3.2.2-gman64.1",
- "natives": {
- "linux-arm64": "natives-linux-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "a8c09f5b7fa24bd53ec329c231b566497a163d5b",
- "size": 5571,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-tinyfd.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd:3.2.2-gman32.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "a8c09f5b7fa24bd53ec329c231b566497a163d5b",
- "size": 5571,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-tinyfd.jar"
- },
- "classifiers": {
- "natives-linux-arm32": {
- "sha1": "82d16054ada6633297a3108fb6d8bae98800c76f",
- "size": 41663,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-tinyfd-natives-linux-arm32.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd:3.2.2-gman32.1",
- "natives": {
- "linux-arm32": "natives-linux-arm32"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "1203660b3131cbb8681b17ce6437412545be95e0",
- "size": 6802,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-tinyfd.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd:3.3.1-mmachina.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "1203660b3131cbb8681b17ce6437412545be95e0",
- "size": 6802,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-tinyfd.jar"
- },
- "classifiers": {
- "natives-osx-arm64": {
- "sha1": "015b931a2daba8f0c317d84c9d14e8e98ae56e0c",
- "size": 41384,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-tinyfd-natives-macos-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd:3.3.1-mmachina.1",
- "natives": {
- "osx-arm64": "natives-osx-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
- "match": [
- "org.lwjgl:lwjgl:3.2.2",
- "org.lwjgl:lwjgl:3.2.1",
- "org.lwjgl:lwjgl:3.1.6",
- "org.lwjgl:lwjgl:3.1.2"
- ],
- "override": {
- "rules": [
- {
- "action": "allow"
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm64"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "linux-arm32"
- }
- },
- {
- "action": "disallow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "360899386df83d6a8407844a94478607af937f97",
- "size": 318833,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-core.jar"
- }
- },
- "name": "org.lwjgl:lwjgl:3.2.2-gman64.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "360899386df83d6a8407844a94478607af937f97",
- "size": 318833,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-core.jar"
- },
- "classifiers": {
- "natives-linux-arm64": {
- "sha1": "612efd57d12b2e48e554858eb35e7e2eb46ebb4c",
- "size": 87121,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-natives-linux-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl:3.2.2-gman64.1",
- "natives": {
- "linux-arm64": "natives-linux-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "16ea3934fca417368250d1ddac01a30c1809d317",
- "size": 318413,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-core.jar"
- }
- },
- "name": "org.lwjgl:lwjgl:3.2.2-gman32.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "16ea3934fca417368250d1ddac01a30c1809d317",
- "size": 318413,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-core.jar"
- },
- "classifiers": {
- "natives-linux-arm32": {
- "sha1": "6bd0b37fef777a309936a72dc7f63126e8c79ea5",
- "size": 90296,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-natives-linux-arm32.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl:3.2.2-gman32.1",
- "natives": {
- "linux-arm32": "natives-linux-arm32"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "8e664dd69ad7bbcf2053da23efc7848e39e498db",
- "size": 719038,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl.jar"
- }
- },
- "name": "org.lwjgl:lwjgl:3.3.1-mmachina.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- },
- {
- "downloads": {
- "artifact": {
- "sha1": "8e664dd69ad7bbcf2053da23efc7848e39e498db",
- "size": 719038,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl.jar"
- },
- "classifiers": {
- "natives-osx-arm64": {
- "sha1": "984df31fadaab86838877b112e5b4e4f68a00ccf",
- "size": 42693,
- "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-natives-macos-arm64.jar"
- }
- }
- },
- "name": "org.lwjgl:lwjgl:3.3.1-mmachina.1",
- "natives": {
- "osx-arm64": "natives-osx-arm64"
- },
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Only allow osx-arm64 for existing LWJGL 3.3.1",
- "match": [
- "org.lwjgl:lwjgl-glfw-natives-macos-arm64:3.3.1",
- "org.lwjgl:lwjgl-jemalloc-natives-macos-arm64:3.3.1",
- "org.lwjgl:lwjgl-openal-natives-macos-arm64:3.3.1",
- "org.lwjgl:lwjgl-opengl-natives-macos-arm64:3.3.1",
- "org.lwjgl:lwjgl-stb-natives-macos-arm64:3.3.1",
- "org.lwjgl:lwjgl-tinyfd-natives-macos-arm64:3.3.1",
- "org.lwjgl:lwjgl-natives-macos-arm64:3.3.1"
- ],
- "override": {
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- }
- },
- {
- "_comment": "Only allow osx-arm64 for existing java-objc-bridge:1.1",
- "match": ["ca.weblite:java-objc-bridge:1.1"],
- "override": {
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "osx-arm64"
- }
- }
- ]
- }
- },
- {
- "_comment": "Only allow windows-arm64 for existing LWJGL 3.3.1",
- "match": [
- "org.lwjgl:lwjgl-glfw-natives-windows-arm64:3.3.1",
- "org.lwjgl:lwjgl-jemalloc-natives-windows-arm64:3.3.1",
- "org.lwjgl:lwjgl-openal-natives-windows-arm64:3.3.1",
- "org.lwjgl:lwjgl-opengl-natives-windows-arm64:3.3.1",
- "org.lwjgl:lwjgl-stb-natives-windows-arm64:3.3.1",
- "org.lwjgl:lwjgl-tinyfd-natives-windows-arm64:3.3.1",
- "org.lwjgl:lwjgl-natives-windows-arm64:3.3.1"
- ],
- "override": {
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "windows-arm64"
- }
- }
- ]
- }
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl-glfw:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "513eb39b866d0fe131a18d5c517087805433b029",
- "size": 112350,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm64:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl-jemalloc:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "749be48a9b86ee2c3a2da5fd77511208adcfb33b",
- "size": 159993,
- "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.3.1/lwjgl-jemalloc-patched-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm64:3.3.1-gman64.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl-openal:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "cf4e303257e82981b8b2e31bba3d7f8f7b8f42b2",
- "size": 470743,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-openal-natives-linux-arm64:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl-opengl:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "1c528fb258a6e63e8fceb4482d8db0f3af10a634",
- "size": 57908,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm64:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl-stb:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "8e8348a1813aad7f30aaf75ea197151ebb7beba9",
- "size": 205491,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-stb-natives-linux-arm64:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl-tinyfd:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "964f628b7a82fd909def086c0dd9a4b84bb259ae",
- "size": 42654,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm64:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "b597401014acb7196c76d97e15a6288f54f1f692",
- "size": 86308,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl/lwjgl-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-natives-linux-arm64:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl-glfw:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "816d935933f2dd743074c4e717cc25b55720f294",
- "size": 104027,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm32:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl-jemalloc:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "a96a6d6cb3876d7813fcee53c3c24f246aeba3b3",
- "size": 136157,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm32:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl-openal:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "ffbe35d7fa5ec9b7eca136a7c71f24d4025a510b",
- "size": 400129,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-openal-natives-linux-arm32:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl-opengl:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "e3550fa91097fd56e361b4370fa822220fef3595",
- "size": 58474,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm32:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl-stb:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "b08226bab162c06ae69337d8a1b0ee0a3fdf0b90",
- "size": 153889,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-stb-natives-linux-arm32:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl-tinyfd:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "d53d331e859217a61298fcbcf8d79137f3df345c",
- "size": 48061,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm32:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
- "match": ["org.lwjgl:lwjgl:3.3.1"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "41a3c1dd15d6b964eb8196dde69720a3e3e5e969",
- "size": 82374,
- "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl/lwjgl-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-natives-linux-arm32:3.3.1-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-freetype:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "896e7d9b8f60d7273f3d491c69270afc67ece3ce",
- "size": 1073374,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm64:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-glfw:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "bc49e64bae0f7ff103a312ee8074a34c4eb034c7",
- "size": 120168,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm64:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-jemalloc:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "5249f18a9ae20ea86c5816bc3107a888ce7a17d2",
- "size": 206402,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm64:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-openal:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "22408980cc579709feaf9acb807992d3ebcf693f",
- "size": 590865,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-openal-natives-linux-arm64:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-opengl:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "bb9eb56da6d1d549d6a767218e675e36bc568eb9",
- "size": 58627,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm64:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-stb:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "11a380c37b0f03cb46db235e064528f84d736ff7",
- "size": 207419,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-stb-natives-linux-arm64:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-tinyfd:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "93f8c5bc1984963cd79109891fb5a9d1e580373e",
- "size": 43381,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm64:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "8bd89332c90a90e6bc4aa997a25c05b7db02c90a",
- "size": 90795,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl/lwjgl-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-natives-linux-arm64:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-freetype:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "b7f77ceb951182659fd400437272aa7e96709968",
- "size": 924657,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm32:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-glfw:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "5907d9a6b7c44fb0612a63bb1cff5992588f65be",
- "size": 110067,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm32:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-jemalloc:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "9367437ce192e4d6f5725d53d85520644c0b0d6f",
- "size": 177571,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm32:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-openal:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "7c82bbc33ef49ee4094b216c940db564b2998224",
- "size": 503352,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-openal-natives-linux-arm32:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-opengl:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "821f9a2d1d583c44893f42b96f6977682b48a99b",
- "size": 59265,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm32:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-stb:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "ca9333da184aade20757151f4615f1e27ca521ae",
- "size": 154928,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-stb-natives-linux-arm32:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl-tinyfd:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "807e220913aa0740449ff90d3b3d825cf5f359ed",
- "size": 48788,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm32:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
- "match": ["org.lwjgl:lwjgl:3.3.2"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "afcbfaaa46f217e98a6da4208550f71de1f2a225",
- "size": 89347,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl/lwjgl-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-natives-linux-arm32:3.3.2-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-freetype:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "498965aac06c4a0d42df1fbef6bacd05bde7f974",
- "size": 1093516,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm64:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-glfw:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "492a0f11f85b85899a6568f07511160c1b87cd38",
- "size": 122159,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm64:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-jemalloc:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "eff8b86798191192fe2cba2dc2776109f30c239d",
- "size": 209315,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm64:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-openal:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "ad8f302118a65bb8d615f8a2a680db58fb8f835e",
- "size": 592963,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-openal-natives-linux-arm64:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-opengl:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "2096f6b94b2d68745d858fbfe53aacf5f0c8074c",
- "size": 58625,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm64:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-stb:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "ddc177afc2be1ee8d93684b11363b80589a13fe1",
- "size": 207418,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-stb-natives-linux-arm64:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-tinyfd:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "2823a8c955c758d0954d282888075019ef99cec7",
- "size": 43864,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm64:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "f35d8b6ffe1ac1e3a5eb1d4e33de80f044ad5fd8",
- "size": 91294,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl/lwjgl-natives-linux-arm64.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-natives-linux-arm64:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm64"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-freetype:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "7dd3b1f751571adaf2c4dc882bc675a5d1e796e6",
- "size": 942636,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm32:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-glfw:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "d9af485c32545b37dd5359b163161d42d7534dcf",
- "size": 112560,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm32:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-jemalloc:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "109b6931880d02d4e65ced38928a16e41d19873e",
- "size": 178324,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm32:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-openal:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "e1702aa09d20359d6cf5cb2999fa7685a785eca7",
- "size": 505618,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-openal-natives-linux-arm32:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-opengl:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "dbba17fc5ac0985d14a57c11f9537617d67b9952",
- "size": 59263,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm32:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-stb:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "1ae28ff044699ff29b0e980ffabd73fba8a664b3",
- "size": 154931,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-stb-natives-linux-arm32:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl-tinyfd:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "c2a0a05c82c4b9f69ded0b6ad5f417addea78ce2",
- "size": 49495,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm32:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
- "match": ["org.lwjgl:lwjgl:3.3.3"],
- "additionalLibraries": [
- {
- "downloads": {
- "artifact": {
- "sha1": "2075c51a80f0ef0f22ba616ba54007ac2b0debd4",
- "size": 89565,
- "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl/lwjgl-natives-linux-arm32.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-natives-linux-arm32:3.3.3-lwjgl.1",
- "rules": [
- {
- "action": "allow",
- "os": {
- "name": "linux-arm32"
- }
- }
- ]
- }
- ]
- },
- {
- "_comment": "Replace glfw from 3.3.1 with version from 3.3.2 to prevent stack smashing",
- "match": [
- "org.lwjgl:lwjgl-glfw-natives-linux:3.3.1",
- "org.lwjgl:lwjgl-glfw:3.3.1:natives-linux"
- ],
- "override": {
- "downloads": {
- "artifact": {
- "sha1": "0766bb0e8e829598b1c8052fd8173c62af741c52",
- "size": 115553,
- "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-glfw/lwjgl-glfw-natives-linux.jar"
- }
- },
- "name": "org.lwjgl:lwjgl-glfw-natives-linux:3.3.2-lwjgl.1"
- }
- }
+ {
+ "_comment": "Only allow osx-arm64 for existing LWJGL 3.3.2/3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-freetype-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-glfw-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-jemalloc-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-openal-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-opengl-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-stb-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-tinyfd-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-freetype-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-glfw-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-jemalloc-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-openal-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-opengl-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-stb-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-tinyfd-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-natives-macos-arm64:3.3.3"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "_comment": "Only allow windows-arm64 for existing LWJGL 3.3.2/3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-freetype-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-glfw-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-jemalloc-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-openal-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-opengl-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-stb-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-tinyfd-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-freetype-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-glfw-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-jemalloc-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-openal-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-opengl-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-stb-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-tinyfd-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-natives-windows-arm64:3.3.3"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "windows-arm64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "_comment": "Add missing tinyfd to the broken LWJGL 3.2.2 variant",
+ "match": ["org.lwjgl:lwjgl:3.2.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "fcbe606c8f8da6f8f9a05e2c540eb1ee8632b0e9",
+ "size": 7092,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.2.2"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "fcbe606c8f8da6f8f9a05e2c540eb1ee8632b0e9",
+ "size": 7092,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2.jar"
+ },
+ "classifiers": {
+ "natives-linux": {
+ "sha1": "39e35b161c130635d9c8918ce04e887a30c5b687",
+ "size": 38804,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2-natives-linux.jar"
+ },
+ "natives-macos": {
+ "sha1": "46d0798228b8a28e857a2a0f02310fd6ba2a4eab",
+ "size": 42136,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2-natives-macos.jar"
+ },
+ "natives-windows": {
+ "sha1": "e9115958773644e863332a6a06488d26f9e1fc9f",
+ "size": 208314,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2-natives-windows.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.2.2",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-macos",
+ "windows": "natives-windows"
+ }
+ }
+ ],
+ "patchAdditionalLibraries": true
+ },
+ {
+ "_comment": "Add additional library just for osx-arm64. No override needed",
+ "match": ["ca.weblite:java-objc-bridge:1.0.0"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "369a83621e3c65496348491e533cb97fe5f2f37d",
+ "size": 91947,
+ "url": "https://github.com/MinecraftMachina/Java-Objective-C-Bridge/releases/download/1.1.0-mmachina.1/java-objc-bridge-1.1.jar"
+ }
+ },
+ "name": "ca.weblite:java-objc-bridge:1.1.0-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add additional classifiers for jinput-platform",
+ "match": ["net.java.jinput:jinput-platform:2.0.5"],
+ "override": {
+ "downloads": {
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "5189eb40db3087fb11ca063b68fa4f4c20b199dd",
+ "size": 10031,
+ "url": "https://github.com/r58Playz/jinput-m1/raw/main/plugins/OSX/bin/jinput-platform-2.0.5.jar"
+ },
+ "natives-linux-arm64": {
+ "sha1": "42b388ccb7c63cec4e9f24f4dddef33325f8b212",
+ "size": 10932,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-2.9.4/jinput-platform-2.0.5-natives-linux.jar"
+ },
+ "natives-linux-arm32": {
+ "sha1": "f3c455b71c5146acb5f8a9513247fc06db182fd5",
+ "size": 4521,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-2.9.4/jinput-platform-2.0.5-natives-linux.jar"
+ }
+ }
+ },
+ "natives": {
+ "linux-arm64": "natives-linux-arm64",
+ "linux-arm32": "natives-linux-arm32",
+ "osx-arm64": "natives-osx-arm64"
+ }
+ }
+ },
+ {
+ "_comment": "Use a newer version on osx-arm64",
+ "match": [
+ "com.mojang:text2speech:1.0.10",
+ "com.mojang:text2speech:1.5",
+ "com.mojang:text2speech:1.6",
+ "com.mojang:text2speech:1.7",
+ "com.mojang:text2speech:1.10.1",
+ "com.mojang:text2speech:1.10.3",
+ "com.mojang:text2speech:1.11.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "f378f889797edd7df8d32272c06ca80a1b6b0f58",
+ "size": 13164,
+ "url": "https://libraries.minecraft.net/com/mojang/text2speech/1.11.3/text2speech-1.11.3.jar"
+ }
+ },
+ "name": "com.mojang:text2speech:1.11.3",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl.lwjgl:lwjgl:2.9.3",
+ "org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20131120",
+ "org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20131017",
+ "org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20130708-debug3",
+ "org.lwjgl.lwjgl:lwjgl:2.9.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "697517568c68e78ae0b4544145af031c81082dfe",
+ "size": 1047168,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar"
+ }
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ },
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl.lwjgl:lwjgl_util:2.9.3",
+ "org.lwjgl.lwjgl:lwjgl_util:2.9.1-nightly-20131120",
+ "org.lwjgl.lwjgl:lwjgl_util:2.9.1-nightly-20131017",
+ "org.lwjgl.lwjgl:lwjgl_util:2.9.1-nightly-20130708-debug3",
+ "org.lwjgl.lwjgl:lwjgl_util:2.9.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "d51a7c040a721d13efdfbd34f8b257b2df882ad0",
+ "size": 173887,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.4-nightly-20150209/lwjgl_util-2.9.4-nightly-20150209.jar"
+ }
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ },
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
+ "org.lwjgl.lwjgl:lwjgl-platform:2.9.3",
+ "org.lwjgl.lwjgl:lwjgl-platform:2.9.1-nightly-20131120",
+ "org.lwjgl.lwjgl:lwjgl-platform:2.9.1-nightly-20131017",
+ "org.lwjgl.lwjgl:lwjgl-platform:2.9.1-nightly-20130708-debug3",
+ "org.lwjgl.lwjgl:lwjgl-platform:2.9.1"
+ ],
+ "override": {
+ "downloads": {
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "eff546c0b319d6ffc7a835652124c18089c67f36",
+ "size": 488316,
+ "url": "https://github.com/MinecraftMachina/lwjgl/releases/download/2.9.4-20150209-mmachina.2/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"
+ },
+ "natives-linux-arm64": {
+ "sha1": "63ac7da0f4a4785c7eadc0f8edc1e9dcc4dd08cb",
+ "size": 579979,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-2.9.4/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar"
+ },
+ "natives-linux-arm32": {
+ "sha1": "fa483e540a9a753a5ffbb23dcf7879a5bf752611",
+ "size": 475177,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-2.9.4/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar"
+ }
+ }
+ },
+ "natives": {
+ "linux-arm64": "natives-linux-arm64",
+ "linux-arm32": "natives-linux-arm32",
+ "osx-arm64": "natives-osx-arm64"
+ }
+ }
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.2.2",
+ "org.lwjgl:lwjgl-glfw:3.2.1",
+ "org.lwjgl:lwjgl-glfw:3.1.6",
+ "org.lwjgl:lwjgl-glfw:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "155d175037efc76630940c197ca6dea2b17d7e18",
+ "size": 108691,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-glfw.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "155d175037efc76630940c197ca6dea2b17d7e18",
+ "size": 108691,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-glfw.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "074ad243761147df0d060fbefc814614d2ff75cc",
+ "size": 85072,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-glfw-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw:3.2.2-gman64.1",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "99e9a39fa8ed4167e3ff9e04d47eb32c9e69804d",
+ "size": 108691,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-glfw.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "99e9a39fa8ed4167e3ff9e04d47eb32c9e69804d",
+ "size": 108691,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-glfw.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "4265f2fbe3b9d642591165165a17cf406cf7b98e",
+ "size": 80186,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-glfw-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "e9a101bca4fa30d26b21b526ff28e7c2d8927f1b",
+ "size": 130128,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-glfw.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "e9a101bca4fa30d26b21b526ff28e7c2d8927f1b",
+ "size": 130128,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-glfw.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "71d793d0a5a42e3dfe78eb882abc2523a2c6b496",
+ "size": 129076,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-glfw-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.2.2",
+ "org.lwjgl:lwjgl-jemalloc:3.2.1",
+ "org.lwjgl:lwjgl-jemalloc:3.1.6",
+ "org.lwjgl:lwjgl-jemalloc:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "cc04eec29b2fa8c298791af9800a3766d9617954",
+ "size": 33790,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-jemalloc.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "cc04eec29b2fa8c298791af9800a3766d9617954",
+ "size": 33790,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-jemalloc.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "762d7d80c9cdf3a3f3fc80c8a5f86612255edfe0",
+ "size": 156343,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-jemalloc-patched-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc:3.2.2-gman64.2",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8224ae2e8fc6d8e1a0fc7d84dc917aa3c440620c",
+ "size": 33790,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-jemalloc.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8224ae2e8fc6d8e1a0fc7d84dc917aa3c440620c",
+ "size": 33790,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-jemalloc.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "9163a2a5559ef87bc13ead8fea84417ea3928748",
+ "size": 134237,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-jemalloc-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "4fb94224378d3588d52d2beb172f2eeafea2d546",
+ "size": 36976,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-jemalloc.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "4fb94224378d3588d52d2beb172f2eeafea2d546",
+ "size": 36976,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-jemalloc.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "b0be721188d2e7195798780b1c5fe7eafe8091c1",
+ "size": 103478,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-jemalloc-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.2.2",
+ "org.lwjgl:lwjgl-openal:3.2.1",
+ "org.lwjgl:lwjgl-openal:3.1.6",
+ "org.lwjgl:lwjgl-openal:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "6dfce9dc6a9629c75b2ae01a8df7e7be80ba0261",
+ "size": 79582,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-openal.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "6dfce9dc6a9629c75b2ae01a8df7e7be80ba0261",
+ "size": 79582,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-openal.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "948e415b5b2a2c650c25b377a4a9f443b21ce92e",
+ "size": 469432,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-openal-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal:3.2.2-gman64.1",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "304f0571fd5971621ee6da86a4c1e90f6f52e2ee",
+ "size": 79582,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-openal.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "304f0571fd5971621ee6da86a4c1e90f6f52e2ee",
+ "size": 79582,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-openal.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "ecbc981fdd996492a1f6334f003ed62e5a8c0cd5",
+ "size": 398418,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-openal-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "d48e753d85916fc8a200ccddc709b36e3865cc4e",
+ "size": 88880,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-openal.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "d48e753d85916fc8a200ccddc709b36e3865cc4e",
+ "size": 88880,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-openal.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "6b80fc0b982a0723b141e88859c42d6f71bd723f",
+ "size": 346131,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-openal-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.2.2",
+ "org.lwjgl:lwjgl-opengl:3.2.1",
+ "org.lwjgl:lwjgl-opengl:3.1.6",
+ "org.lwjgl:lwjgl-opengl:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "198bc2f72e0b2eb401eb6f5999aea52909b31ac4",
+ "size": 937609,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-opengl.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "198bc2f72e0b2eb401eb6f5999aea52909b31ac4",
+ "size": 937609,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-opengl.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "bd40897077bf7d12f562da898b18ac2c68e1f9d7",
+ "size": 56109,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-opengl-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl:3.2.2-gman64.1",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "9762ae928d02147e716cd82e929b74a97ea9600a",
+ "size": 937609,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-opengl.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "9762ae928d02147e716cd82e929b74a97ea9600a",
+ "size": 937609,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-opengl.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "3af5599c74dd76dd8dbb567b3f9b4963a6abeed5",
+ "size": 56388,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-opengl-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "962c2a8d2a8cdd3b89de3d78d766ab5e2133c2f4",
+ "size": 929233,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-opengl.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "962c2a8d2a8cdd3b89de3d78d766ab5e2133c2f4",
+ "size": 929233,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-opengl.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "bb575058e0372f515587b5d2d04ff7db185f3ffe",
+ "size": 41667,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-opengl-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.2.2",
+ "org.lwjgl:lwjgl-stb:3.2.1",
+ "org.lwjgl:lwjgl-stb:3.1.6",
+ "org.lwjgl:lwjgl-stb:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "46a5735f3eb9d17eb5dcbdd5afa194066d2a6555",
+ "size": 104075,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-stb.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "46a5735f3eb9d17eb5dcbdd5afa194066d2a6555",
+ "size": 104075,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-stb.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "077efa7d7ea41b32df5c6078e912e724cccd06db",
+ "size": 202038,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-stb-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb:3.2.2-gman64.1",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ea979b0af45b8e689f5f47c989aa8550c148d8a2",
+ "size": 104075,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-stb.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ea979b0af45b8e689f5f47c989aa8550c148d8a2",
+ "size": 104075,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-stb.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "ec9d70aaebd0ff76dfeecf8f00b56118bf3706b1",
+ "size": 149387,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-stb-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "703e4b533e2542560e9f94d6d8bd148be1c1d572",
+ "size": 113273,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-stb.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "703e4b533e2542560e9f94d6d8bd148be1c1d572",
+ "size": 113273,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-stb.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "98f0ad956c754723ef354d50057cc30417ef376a",
+ "size": 178409,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-stb-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.2.2",
+ "org.lwjgl:lwjgl-tinyfd:3.2.1",
+ "org.lwjgl:lwjgl-tinyfd:3.1.6",
+ "org.lwjgl:lwjgl-tinyfd:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "3a75b9811607633bf33c978f53964df1534a4bc1",
+ "size": 5571,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-tinyfd.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "3a75b9811607633bf33c978f53964df1534a4bc1",
+ "size": 5571,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-tinyfd.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "37c744ca289b5d7ae155d79e39029488b3254e5b",
+ "size": 37893,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-tinyfd-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.2.2-gman64.1",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "a8c09f5b7fa24bd53ec329c231b566497a163d5b",
+ "size": 5571,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-tinyfd.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "a8c09f5b7fa24bd53ec329c231b566497a163d5b",
+ "size": 5571,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-tinyfd.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "82d16054ada6633297a3108fb6d8bae98800c76f",
+ "size": 41663,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-tinyfd-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "1203660b3131cbb8681b17ce6437412545be95e0",
+ "size": 6802,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-tinyfd.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "1203660b3131cbb8681b17ce6437412545be95e0",
+ "size": 6802,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-tinyfd.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "015b931a2daba8f0c317d84c9d14e8e98ae56e0c",
+ "size": 41384,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-tinyfd-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl:3.2.2",
+ "org.lwjgl:lwjgl:3.2.1",
+ "org.lwjgl:lwjgl:3.1.6",
+ "org.lwjgl:lwjgl:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "360899386df83d6a8407844a94478607af937f97",
+ "size": 318833,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-core.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "360899386df83d6a8407844a94478607af937f97",
+ "size": 318833,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-core.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "612efd57d12b2e48e554858eb35e7e2eb46ebb4c",
+ "size": 87121,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl:3.2.2-gman64.1",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "16ea3934fca417368250d1ddac01a30c1809d317",
+ "size": 318413,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-core.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "16ea3934fca417368250d1ddac01a30c1809d317",
+ "size": 318413,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-core.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "6bd0b37fef777a309936a72dc7f63126e8c79ea5",
+ "size": 90296,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8e664dd69ad7bbcf2053da23efc7848e39e498db",
+ "size": 719038,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8e664dd69ad7bbcf2053da23efc7848e39e498db",
+ "size": 719038,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "984df31fadaab86838877b112e5b4e4f68a00ccf",
+ "size": 42693,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Only allow osx-arm64 for existing LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-glfw-natives-macos-arm64:3.3.1",
+ "org.lwjgl:lwjgl-jemalloc-natives-macos-arm64:3.3.1",
+ "org.lwjgl:lwjgl-openal-natives-macos-arm64:3.3.1",
+ "org.lwjgl:lwjgl-opengl-natives-macos-arm64:3.3.1",
+ "org.lwjgl:lwjgl-stb-natives-macos-arm64:3.3.1",
+ "org.lwjgl:lwjgl-tinyfd-natives-macos-arm64:3.3.1",
+ "org.lwjgl:lwjgl-natives-macos-arm64:3.3.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "_comment": "Only allow osx-arm64 for existing java-objc-bridge:1.1",
+ "match": ["ca.weblite:java-objc-bridge:1.1"],
+ "override": {
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "_comment": "Only allow windows-arm64 for existing LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-glfw-natives-windows-arm64:3.3.1",
+ "org.lwjgl:lwjgl-jemalloc-natives-windows-arm64:3.3.1",
+ "org.lwjgl:lwjgl-openal-natives-windows-arm64:3.3.1",
+ "org.lwjgl:lwjgl-opengl-natives-windows-arm64:3.3.1",
+ "org.lwjgl:lwjgl-stb-natives-windows-arm64:3.3.1",
+ "org.lwjgl:lwjgl-tinyfd-natives-windows-arm64:3.3.1",
+ "org.lwjgl:lwjgl-natives-windows-arm64:3.3.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "windows-arm64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl-glfw:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "513eb39b866d0fe131a18d5c517087805433b029",
+ "size": 112350,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm64:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl-jemalloc:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "749be48a9b86ee2c3a2da5fd77511208adcfb33b",
+ "size": 159993,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.3.1/lwjgl-jemalloc-patched-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm64:3.3.1-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl-openal:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "cf4e303257e82981b8b2e31bba3d7f8f7b8f42b2",
+ "size": 470743,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm64:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl-opengl:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "1c528fb258a6e63e8fceb4482d8db0f3af10a634",
+ "size": 57908,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm64:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl-stb:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8e8348a1813aad7f30aaf75ea197151ebb7beba9",
+ "size": 205491,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm64:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl-tinyfd:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "964f628b7a82fd909def086c0dd9a4b84bb259ae",
+ "size": 42654,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm64:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "b597401014acb7196c76d97e15a6288f54f1f692",
+ "size": 86308,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl/lwjgl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm64:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl-glfw:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "816d935933f2dd743074c4e717cc25b55720f294",
+ "size": 104027,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl-jemalloc:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "a96a6d6cb3876d7813fcee53c3c24f246aeba3b3",
+ "size": 136157,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl-openal:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ffbe35d7fa5ec9b7eca136a7c71f24d4025a510b",
+ "size": 400129,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl-opengl:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "e3550fa91097fd56e361b4370fa822220fef3595",
+ "size": 58474,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl-stb:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "b08226bab162c06ae69337d8a1b0ee0a3fdf0b90",
+ "size": 153889,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl-tinyfd:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "d53d331e859217a61298fcbcf8d79137f3df345c",
+ "size": 48061,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": ["org.lwjgl:lwjgl:3.3.1"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "41a3c1dd15d6b964eb8196dde69720a3e3e5e969",
+ "size": 82374,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl/lwjgl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-freetype:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "896e7d9b8f60d7273f3d491c69270afc67ece3ce",
+ "size": 1073374,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-glfw:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "bc49e64bae0f7ff103a312ee8074a34c4eb034c7",
+ "size": 120168,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-jemalloc:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "5249f18a9ae20ea86c5816bc3107a888ce7a17d2",
+ "size": 206402,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-openal:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "22408980cc579709feaf9acb807992d3ebcf693f",
+ "size": 590865,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-opengl:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "bb9eb56da6d1d549d6a767218e675e36bc568eb9",
+ "size": 58627,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-stb:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "11a380c37b0f03cb46db235e064528f84d736ff7",
+ "size": 207419,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-tinyfd:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "93f8c5bc1984963cd79109891fb5a9d1e580373e",
+ "size": 43381,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8bd89332c90a90e6bc4aa997a25c05b7db02c90a",
+ "size": 90795,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl/lwjgl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-freetype:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "b7f77ceb951182659fd400437272aa7e96709968",
+ "size": 924657,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-glfw:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "5907d9a6b7c44fb0612a63bb1cff5992588f65be",
+ "size": 110067,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-jemalloc:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "9367437ce192e4d6f5725d53d85520644c0b0d6f",
+ "size": 177571,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-openal:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "7c82bbc33ef49ee4094b216c940db564b2998224",
+ "size": 503352,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-opengl:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "821f9a2d1d583c44893f42b96f6977682b48a99b",
+ "size": 59265,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-stb:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ca9333da184aade20757151f4615f1e27ca521ae",
+ "size": 154928,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl-tinyfd:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "807e220913aa0740449ff90d3b3d825cf5f359ed",
+ "size": 48788,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": ["org.lwjgl:lwjgl:3.3.2"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "afcbfaaa46f217e98a6da4208550f71de1f2a225",
+ "size": 89347,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl/lwjgl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-freetype:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "498965aac06c4a0d42df1fbef6bacd05bde7f974",
+ "size": 1093516,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-glfw:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "492a0f11f85b85899a6568f07511160c1b87cd38",
+ "size": 122159,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-jemalloc:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "eff8b86798191192fe2cba2dc2776109f30c239d",
+ "size": 209315,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-openal:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ad8f302118a65bb8d615f8a2a680db58fb8f835e",
+ "size": 592963,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-opengl:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "2096f6b94b2d68745d858fbfe53aacf5f0c8074c",
+ "size": 58625,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-stb:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ddc177afc2be1ee8d93684b11363b80589a13fe1",
+ "size": 207418,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-tinyfd:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "2823a8c955c758d0954d282888075019ef99cec7",
+ "size": 43864,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "f35d8b6ffe1ac1e3a5eb1d4e33de80f044ad5fd8",
+ "size": 91294,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl/lwjgl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-freetype:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "7dd3b1f751571adaf2c4dc882bc675a5d1e796e6",
+ "size": 942636,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-glfw:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "d9af485c32545b37dd5359b163161d42d7534dcf",
+ "size": 112560,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-jemalloc:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "109b6931880d02d4e65ced38928a16e41d19873e",
+ "size": 178324,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-openal:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "e1702aa09d20359d6cf5cb2999fa7685a785eca7",
+ "size": 505618,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-opengl:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "dbba17fc5ac0985d14a57c11f9537617d67b9952",
+ "size": 59263,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-stb:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "1ae28ff044699ff29b0e980ffabd73fba8a664b3",
+ "size": 154931,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl-tinyfd:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "c2a0a05c82c4b9f69ded0b6ad5f417addea78ce2",
+ "size": 49495,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": ["org.lwjgl:lwjgl:3.3.3"],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "2075c51a80f0ef0f22ba616ba54007ac2b0debd4",
+ "size": 89565,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl/lwjgl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Replace glfw from 3.3.1 with version from 3.3.2 to prevent stack smashing",
+ "match": [
+ "org.lwjgl:lwjgl-glfw-natives-linux:3.3.1",
+ "org.lwjgl:lwjgl-glfw:3.3.1:natives-linux"
+ ],
+ "override": {
+ "downloads": {
+ "artifact": {
+ "sha1": "0766bb0e8e829598b1c8052fd8173c62af741c52",
+ "size": 115553,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-glfw/lwjgl-glfw-natives-linux.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux:3.3.2-lwjgl.1"
+ }
+ }
]
diff --git a/apps/daedalus_client/package.json b/apps/daedalus_client/package.json
index f75b9d76..e7e94f8a 100644
--- a/apps/daedalus_client/package.json
+++ b/apps/daedalus_client/package.json
@@ -1,13 +1,15 @@
{
- "name": "@modrinth/daedalus_client",
- "scripts": {
- "build": "cargo build --release",
- "lint": "cargo fmt --check && cargo clippy --all-targets",
- "fix": "cargo clippy --all-targets --fix --allow-dirty && cargo fmt",
- "dev": "cargo run",
- "test": "cargo nextest run --all-targets --no-fail-fast"
- },
- "dependencies": {
- "@modrinth/daedalus": "workspace:*"
- }
+ "name": "@modrinth/daedalus_client",
+ "scripts": {
+ "build": "cargo build --release",
+ "lint": "cargo fmt --check && cargo clippy --all-targets",
+ "lint:ancillary": "prettier --check .",
+ "fix": "cargo clippy --all-targets --fix --allow-dirty && cargo fmt",
+ "fix:ancillary": "prettier --write .",
+ "dev": "cargo run",
+ "test": "cargo nextest run --all-targets --no-fail-fast"
+ },
+ "dependencies": {
+ "@modrinth/daedalus": "workspace:*"
+ }
}
diff --git a/apps/daedalus_client/src/forge.rs b/apps/daedalus_client/src/forge.rs
index ab67ae91..c1bf6056 100644
--- a/apps/daedalus_client/src/forge.rs
+++ b/apps/daedalus_client/src/forge.rs
@@ -506,27 +506,25 @@ async fn fetch(
return Ok(lib);
}
- } else if let Some(url) = &lib.url {
- if !url.is_empty() {
- insert_mirrored_artifact(
- &lib.name,
- None,
- vec![
- url.clone(),
- "https://libraries.minecraft.net/"
- .to_string(),
- "https://maven.creeperhost.net/"
- .to_string(),
- maven_url.to_string(),
- ],
- false,
- mirror_artifacts,
- )?;
+ } else if let Some(url) = &lib.url
+ && !url.is_empty()
+ {
+ insert_mirrored_artifact(
+ &lib.name,
+ None,
+ vec![
+ url.clone(),
+ "https://libraries.minecraft.net/".to_string(),
+ "https://maven.creeperhost.net/".to_string(),
+ maven_url.to_string(),
+ ],
+ false,
+ mirror_artifacts,
+ )?;
- lib.url = Some(format_url("maven/"));
+ lib.url = Some(format_url("maven/"));
- return Ok(lib);
- }
+ return Ok(lib);
}
// Other libraries are generally available in the "maven" directory of the installer. If they are
diff --git a/apps/daedalus_client/src/main.rs b/apps/daedalus_client/src/main.rs
index dcd61055..a0945471 100644
--- a/apps/daedalus_client/src/main.rs
+++ b/apps/daedalus_client/src/main.rs
@@ -93,22 +93,22 @@ async fn main() -> Result<()> {
.ok()
.and_then(|x| x.parse::().ok())
.unwrap_or(false)
+ && let Ok(token) = dotenvy::var("CLOUDFLARE_TOKEN")
+ && let Ok(zone_id) = dotenvy::var("CLOUDFLARE_ZONE_ID")
{
- if let Ok(token) = dotenvy::var("CLOUDFLARE_TOKEN") {
- if let Ok(zone_id) = dotenvy::var("CLOUDFLARE_ZONE_ID") {
- let cache_clears = upload_files
+ let cache_clears = upload_files
+ .into_iter()
+ .map(|x| format_url(&x.0))
+ .chain(
+ mirror_artifacts
.into_iter()
- .map(|x| format_url(&x.0))
- .chain(
- mirror_artifacts
- .into_iter()
- .map(|x| format_url(&format!("maven/{}", x.0))),
- )
- .collect::>();
+ .map(|x| format_url(&format!("maven/{}", x.0))),
+ )
+ .collect::>();
- // Cloudflare ratelimits cache clears to 500 files per request
- for chunk in cache_clears.chunks(500) {
- REQWEST_CLIENT.post(format!("https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache"))
+ // Cloudflare ratelimits cache clears to 500 files per request
+ for chunk in cache_clears.chunks(500) {
+ REQWEST_CLIENT.post(format!("https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache"))
.bearer_auth(&token)
.json(&serde_json::json!({
"files": chunk
@@ -128,8 +128,6 @@ async fn main() -> Result<()> {
item: "cloudflare clear cache".to_string(),
}
})?;
- }
- }
}
}
diff --git a/apps/daedalus_client/src/util.rs b/apps/daedalus_client/src/util.rs
index 3f8f11e5..6d331d83 100644
--- a/apps/daedalus_client/src/util.rs
+++ b/apps/daedalus_client/src/util.rs
@@ -167,20 +167,18 @@ pub async fn download_file(
let bytes = x.bytes().await;
if let Ok(bytes) = bytes {
- if let Some(sha1) = sha1 {
- if &*sha1_async(bytes.clone()).await? != sha1 {
- if attempt <= 3 {
- continue;
- } else {
- return Err(
- crate::ErrorKind::ChecksumFailure {
- hash: sha1.to_string(),
- url: url.to_string(),
- tries: attempt,
- }
- .into(),
- );
+ if let Some(sha1) = sha1
+ && &*sha1_async(bytes.clone()).await? != sha1
+ {
+ if attempt <= 3 {
+ continue;
+ } else {
+ return Err(crate::ErrorKind::ChecksumFailure {
+ hash: sha1.to_string(),
+ url: url.to_string(),
+ tries: attempt,
}
+ .into());
}
}
diff --git a/apps/docs/.prettierignore b/apps/docs/.prettierignore
new file mode 100644
index 00000000..abc76812
--- /dev/null
+++ b/apps/docs/.prettierignore
@@ -0,0 +1 @@
+**/*.svg
diff --git a/apps/docs/.vscode/extensions.json b/apps/docs/.vscode/extensions.json
index 22a15055..3a1c9ecd 100644
--- a/apps/docs/.vscode/extensions.json
+++ b/apps/docs/.vscode/extensions.json
@@ -1,4 +1,4 @@
{
- "recommendations": ["astro-build.astro-vscode"],
- "unwantedRecommendations": []
+ "recommendations": ["astro-build.astro-vscode"],
+ "unwantedRecommendations": []
}
diff --git a/apps/docs/.vscode/launch.json b/apps/docs/.vscode/launch.json
index d6422097..230708db 100644
--- a/apps/docs/.vscode/launch.json
+++ b/apps/docs/.vscode/launch.json
@@ -1,11 +1,11 @@
{
- "version": "0.2.0",
- "configurations": [
- {
- "command": "./node_modules/.bin/astro dev",
- "name": "Development server",
- "request": "launch",
- "type": "node-terminal"
- }
- ]
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "command": "./node_modules/.bin/astro dev",
+ "name": "Development server",
+ "request": "launch",
+ "type": "node-terminal"
+ }
+ ]
}
diff --git a/apps/docs/astro.config.mjs b/apps/docs/astro.config.mjs
index 3baeb6f4..63e97938 100644
--- a/apps/docs/astro.config.mjs
+++ b/apps/docs/astro.config.mjs
@@ -4,53 +4,53 @@ import starlightOpenAPI, { openAPISidebarGroups } from 'starlight-openapi'
// https://astro.build/config
export default defineConfig({
- site: 'https://docs.modrinth.com',
- integrations: [
- starlight({
- title: 'Modrinth Documentation',
- favicon: '/favicon.ico',
- editLink: {
- baseUrl: 'https://github.com/modrinth/code/edit/main/apps/docs/',
- },
- social: {
- github: 'https://github.com/modrinth/code',
- discord: 'https://discord.modrinth.com',
- 'x.com': 'https://x.com/modrinth',
- mastodon: 'https://floss.social/@modrinth',
- threads: 'https://threads.net/@modrinth',
- },
- logo: {
- light: './src/assets/light-logo.svg',
- dark: './src/assets/dark-logo.svg',
- replacesTitle: true,
- },
- customCss: [
- '@modrinth/assets/styles/variables.scss',
- '@modrinth/assets/styles/inter.scss',
- './src/styles/modrinth.css',
- ],
- plugins: [
- // Generate the OpenAPI documentation pages.
- starlightOpenAPI([
- {
- base: 'api',
- label: 'Modrinth API',
- schema: './public/openapi.yaml',
- },
- ]),
- ],
- sidebar: [
- {
- label: 'Contributing to Modrinth',
- autogenerate: { directory: 'contributing' },
- },
- {
- label: 'Guides',
- autogenerate: { directory: 'guide' },
- },
- // Add the generated sidebar group to the sidebar.
- ...openAPISidebarGroups,
- ],
- }),
- ],
+ site: 'https://docs.modrinth.com',
+ integrations: [
+ starlight({
+ title: 'Modrinth Documentation',
+ favicon: '/favicon.ico',
+ editLink: {
+ baseUrl: 'https://github.com/modrinth/code/edit/main/apps/docs/',
+ },
+ social: {
+ github: 'https://github.com/modrinth/code',
+ discord: 'https://discord.modrinth.com',
+ 'x.com': 'https://x.com/modrinth',
+ mastodon: 'https://floss.social/@modrinth',
+ threads: 'https://threads.net/@modrinth',
+ },
+ logo: {
+ light: './src/assets/light-logo.svg',
+ dark: './src/assets/dark-logo.svg',
+ replacesTitle: true,
+ },
+ customCss: [
+ '@modrinth/assets/styles/variables.scss',
+ '@modrinth/assets/styles/inter.scss',
+ './src/styles/modrinth.css',
+ ],
+ plugins: [
+ // Generate the OpenAPI documentation pages.
+ starlightOpenAPI([
+ {
+ base: 'api',
+ label: 'Modrinth API',
+ schema: './public/openapi.yaml',
+ },
+ ]),
+ ],
+ sidebar: [
+ {
+ label: 'Contributing to Modrinth',
+ autogenerate: { directory: 'contributing' },
+ },
+ {
+ label: 'Guides',
+ autogenerate: { directory: 'guide' },
+ },
+ // Add the generated sidebar group to the sidebar.
+ ...openAPISidebarGroups,
+ ],
+ }),
+ ],
})
diff --git a/apps/docs/package.json b/apps/docs/package.json
index 274ddd55..4dc9a77b 100644
--- a/apps/docs/package.json
+++ b/apps/docs/package.json
@@ -1,22 +1,24 @@
{
- "name": "@modrinth/docs",
- "type": "module",
- "version": "0.0.1",
- "scripts": {
- "dev": "astro dev",
- "start": "astro dev",
- "lint": "astro check",
- "build": "astro build",
- "preview": "astro preview",
- "astro": "astro"
- },
- "dependencies": {
- "@astrojs/check": "^0.9.4",
- "@astrojs/starlight": "^0.32.2",
- "@modrinth/assets": "workspace:*",
- "astro": "^5.4.1",
- "sharp": "^0.33.5",
- "starlight-openapi": "^0.14.0",
- "typescript": "^5.8.2"
- }
+ "name": "@modrinth/docs",
+ "type": "module",
+ "version": "0.0.1",
+ "scripts": {
+ "dev": "astro dev",
+ "start": "astro dev",
+ "lint": "astro check",
+ "lint:ancillary": "prettier --check .",
+ "fix:ancillary": "prettier --write .",
+ "build": "astro build",
+ "preview": "astro preview",
+ "astro": "astro"
+ },
+ "dependencies": {
+ "@astrojs/check": "^0.9.4",
+ "@astrojs/starlight": "^0.32.2",
+ "@modrinth/assets": "workspace:*",
+ "astro": "^5.4.1",
+ "sharp": "^0.33.5",
+ "starlight-openapi": "^0.14.0",
+ "typescript": "^5.8.2"
+ }
}
diff --git a/apps/docs/src/content.config.ts b/apps/docs/src/content.config.ts
index 6a7b7a02..8fa5a436 100644
--- a/apps/docs/src/content.config.ts
+++ b/apps/docs/src/content.config.ts
@@ -1,7 +1,7 @@
-import { defineCollection } from 'astro:content';
-import { docsLoader } from '@astrojs/starlight/loaders';
-import { docsSchema } from '@astrojs/starlight/schema';
+import { defineCollection } from 'astro:content'
+import { docsLoader } from '@astrojs/starlight/loaders'
+import { docsSchema } from '@astrojs/starlight/schema'
export const collections = {
- docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
-};
+ docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
+}
diff --git a/apps/docs/src/content/docs/contributing/labrinth.md b/apps/docs/src/content/docs/contributing/labrinth.md
index 1be7dd3e..02c50b0f 100644
--- a/apps/docs/src/content/docs/contributing/labrinth.md
+++ b/apps/docs/src/content/docs/contributing/labrinth.md
@@ -3,77 +3,61 @@ title: Labrinth (API)
description: Guide for contributing to Modrinth's backend
---
-This project is part of our [monorepo](https://github.com/modrinth/code). You can find it in the `apps/labrinth` directory.
+This project is part of our [monorepo](https://github.com/modrinth/code). You can find it in the `apps/labrinth` directory. The instructions below assume that you have switched your working directory to the `apps/labrinth` subdirectory.
-[labrinth] is the Rust-based backend serving Modrinth's API with the help of the [Actix](https://actix.rs) framework. To get started with a labrinth instance, install docker, docker-compose (which comes with Docker), and [Rust]. The initial startup can be done simply with the command `docker-compose up`, or with `docker compose up` (Compose V2 and later). That will deploy a PostgreSQL database on port 5432 and a MeiliSearch instance on port 7700. To run the API itself, you'll need to use the `cargo run` command, this will deploy the API on port 8000.
+[labrinth] is the Rust-based backend serving Modrinth's API with the help of the [Actix](https://actix.rs) framework. To get started with a labrinth instance, install docker, docker-compose (which comes with Docker), and [Rust]. The initial startup can be done simply with the command `docker-compose up`, or with `docker compose up` (Compose V2 and later). That will deploy a PostgreSQL database on port 5432, a MeiliSearch instance on port 7700, and a [Mailpit](https://mailpit.axllent.org/) SMTP server on port 1025, with a web UI to inspect sent emails on port 8025. To run the API itself, you'll need to use the `cargo run` command, this will deploy the API on port 8000.
To get a basic configuration, copy the `.env.local` file to `.env`. Now, you'll have to install the sqlx CLI, which can be done with cargo:
-```bash
-cargo install --git https://github.com/launchbadge/sqlx sqlx-cli --no-default-features --features postgres,rustls
+```sh
+cargo install sqlx-cli --no-default-features --features mysql,sqlite,postgres,rustls,completions
```
-From there, you can create the database and perform all database migrations with one simple command:
+From there, you can create the database and set up its schema with one simple command:
-```bash
-sqlx database setup
+```sh
+cargo sqlx database setup
```
-To enable labrinth to create a project, you need to add two things.
+To enable labrinth to create projects and serve useful metadata to the frontend build scripts, you'll need to seed the database with several key entities:
-1. An entry in the `loaders` table.
-2. An entry in the `loaders_project_types` table.
+1. Categories, in the `categories` table.
+2. Loaders and their fields, in the `loaders`, `loader_fields`, `loader_field_enums`, `loader_field_enum_values`, and `loader_fields_loaders` tables.
+3. Project types and their allowed loaders and games, in the `project_types`, `loaders_project_types`, and `loaders_project_types_games` tables.
+4. Optionally, to moderate projects from the frontend, an admin user, in the `users` table.
-A minimal setup can be done from the command line with [psql](https://www.postgresql.org/docs/current/app-psql.html):
+The most convenient way to do this seeding is with the [psql](https://www.postgresql.org/docs/current/app-psql.html) command line tool and the pre-existing seed data fixture. This fixture was generated by dumping the official staging environment database at a specific point in time, and defines an admin user with email `admin@modrinth.invalid` and password `admin`:
-```bash
-psql --host=localhost --port=5432 -U -W
+```sh
+source .env
+psql "$DATABASE_URL" < fixtures/labrinth-seed-data-202508052143.sql
```
-The default password for the database is `labrinth`. Once you've connected, run
-
-```sql
-INSERT INTO loaders VALUES (0, 'placeholder_loader');
-INSERT INTO loaders_project_types VALUES (0, 1); -- modloader id, supported type id
-INSERT INTO categories VALUES (0, 'placeholder_category', 1); -- category id, category, project type id
-```
-
-This will initialize your database with a modloader called 'placeholder_loader', with id 0, and marked as supporting mods only. It will also create a category called 'placeholder_category' that is marked as supporting mods only
-If you would like 'placeholder_loader' to be marked as supporting modpacks too, run
-
-```sql
-INSERT INTO loaders_project_types VALUES (0, 2); -- modloader id, supported type id
-```
-
-If you would like 'placeholder_category' to be marked as supporting modpacks too, run
-
-```sql
-INSERT INTO categories VALUES (0, 'placeholder_category', 2); -- modloader id, supported type id
-```
-
-You can find more example SQL statements for seeding the database in the `apps/labrinth/tests/files/dummy_data.sql` file.
+You can find more example SQL statements for seeding the database in the `tests/files/dummy_data.sql` file.
The majority of configuration is done at runtime using [dotenvy](https://crates.io/crates/dotenvy) and the `.env` file. Each of the variables and what they do can be found in the dropdown below. Additionally, there are three command line options that can be used to specify to MeiliSearch what you want to do.
-During development, you might notice that changes made directly to entities in the PostgreSQL database do not seem to take effect. This is often because the Redis cache still holds outdated data. To ensure your updates are reflected, clear the cache by e.g. running `redis-cli FLUSHALL`, which will force Labrinth to fetch the latest data from the database the next time it is needed.
+During development, you might notice that changes made directly to entities in the PostgreSQL database do not seem to take effect. This is often because the Redis cache still holds outdated data. To ensure your updates are reflected, clear the cache by e.g. running `redis-cli FLUSHALL`, which will force labrinth to fetch the latest data from the database the next time it is needed.
+
+You can also start labrinth and its backing services at once using `docker compose --profile with-labrinth up`, which will build and start labrinth through its Docker image as if it was yet another service container. To have that container be automatically rebuilt during development as changes to the source code are made, add the `--watch` flag, which enables [Compose Watch](https://docs.docker.com/compose/how-tos/file-watch/). Keep in mind, however, that Compose Watch is bound to be slower than other similar solutions that work outside of a container, particularly on Windows or macOS, where Docker runs in a virtual machine.
.env variables & command line options
#### Basic configuration
-`DEBUG`: Whether debugging tools should be enabled
-`RUST_LOG`: Specifies what information to log, from rust's [`env-logger`](https://github.com/env-logger-rs/env_logger); a reasonable default is `info,sqlx::query=warn`
-`SITE_URL`: The main URL to be used for CORS
-`CDN_URL`: The publicly accessible base URL for files uploaded to the CDN
-`MODERATION_DISCORD_WEBHOOK`: The URL for a Discord webhook where projects pending approval will be sent
-`CLOUDFLARE_INTEGRATION`: Whether labrinth should integrate with Cloudflare's spam protection
-`DATABASE_URL`: The URL for the PostgreSQL database
-`DATABASE_MIN_CONNECTIONS`: The minimum number of concurrent connections allowed to the database at the same time
-`DATABASE_MAX_CONNECTIONS`: The maximum number of concurrent connections allowed to the database at the same time
-`MEILISEARCH_ADDR`: The URL for the MeiliSearch instance used for search
-`MEILISEARCH_KEY`: The name that MeiliSearch is given
-`BIND_ADDR`: The bind address for the server. Supports both IPv4 and IPv6
+`DEBUG`: Whether debugging tools should be enabled
+`RUST_LOG`: Specifies what information to log, from rust's [`env-logger`](https://github.com/env-logger-rs/env_logger); a reasonable default is `info,sqlx::query=warn`
+`SITE_URL`: The main URL to be used for CORS
+`CDN_URL`: The publicly accessible base URL for files uploaded to the CDN
+`MODERATION_DISCORD_WEBHOOK`: The URL for a Discord webhook where projects pending approval will be sent
+`CLOUDFLARE_INTEGRATION`: Whether labrinth should integrate with Cloudflare's spam protection
+`DATABASE_URL`: The URL for the PostgreSQL database, including its username, password, host, port, and database name
+`DATABASE_MIN_CONNECTIONS`: The minimum number of concurrent connections allowed to the database at the same time
+`DATABASE_MAX_CONNECTIONS`: The maximum number of concurrent connections allowed to the database at the same time
+`MEILISEARCH_ADDR`: The URL for the MeiliSearch instance used for search
+`MEILISEARCH_KEY`: The name that MeiliSearch is given
+`BIND_ADDR`: The bind address for the server. Supports both IPv4 and IPv6
`MOCK_FILE_PATH`: The path used to store uploaded files; this has no default value and will panic if unspecified
`SMTP_USERNAME`: The username used to authenticate with the SMTP server
`SMTP_PASSWORD`: The password associated with the `SMTP_USERNAME` for SMTP authentication
@@ -90,7 +74,7 @@ The S3 configuration options are fairly self-explanatory in name, so here's simp
#### Search, OAuth, and miscellaneous options
-`LOCAL_INDEX_INTERVAL`: The interval, in seconds, at which the local database is reindexed for searching. Defaults to `3600` seconds (1 hour).
+`LOCAL_INDEX_INTERVAL`: The interval, in seconds, at which the local database is reindexed for searching. Defaults to `3600` seconds (1 hour).
`VERSION_INDEX_INTERVAL`: The interval, in seconds, at which versions are reindexed for searching. Defaults to `1800` seconds (30 minutes).
The OAuth configuration options are fairly self-explanatory. For help setting up authentication, please contact us on [Discord].
@@ -99,8 +83,8 @@ The OAuth configuration options are fairly self-explanatory. For help setting up
#### Command line options
-`--skip-first-index`: Skips indexing the local database on startup. This is useful to prevent doing unnecessary work when frequently restarting.
-`--reconfigure-indices`: Resets the MeiliSearch settings for the search indices and exits.
+`--skip-first-index`: Skips indexing the local database on startup. This is useful to prevent doing unnecessary work when frequently restarting.
+`--reconfigure-indices`: Resets the MeiliSearch settings for the search indices and exits.
`--reset-indices`: Resets the MeiliSearch indices and exits; this clears all previously indexed mods.
@@ -109,14 +93,13 @@ The OAuth configuration options are fairly self-explanatory. For help setting up
If you're prepared to contribute by submitting a pull request, ensure you have met the following criteria:
-- `cargo fmt` has been run.
-- `cargo clippy` has been run.
-- `cargo check` has been run.
+- `cargo fmt --all` has been run.
+- `cargo clippy --all-targets` has been run.
- `cargo sqlx prepare` has been run.
> Note: If you encounter issues with `sqlx` saying 'no queries found' after running `cargo sqlx prepare`, you may need to ensure the installed version of `sqlx-cli` matches the current version of `sqlx` used [in labrinth](https://github.com/modrinth/labrinth/blob/master/Cargo.toml).
[Discord]: https://discord.modrinth.com
[GitHub]: https://github.com/modrinth
-[labrinth]: https://github.com/modrinth/labrinth
+[labrinth]: https://github.com/modrinth/code/tree/main/apps/labrinth
[Rust]: https://www.rust-lang.org/tools/install
diff --git a/apps/docs/src/content/docs/guide/oauth.md b/apps/docs/src/content/docs/guide/oauth.md
index a7833b10..33827eb5 100644
--- a/apps/docs/src/content/docs/guide/oauth.md
+++ b/apps/docs/src/content/docs/guide/oauth.md
@@ -8,7 +8,7 @@ Modrinth allows developers to create applications which, once authorized by a Mo
If you're familiar with OAuth 2, these are the URLs you will need:
| Name | URL |
-|--------------------|--------------------------------------------------|
+| ------------------ | ------------------------------------------------ |
| Authorization page | `https://modrinth.com/auth/authorize` |
| Token exchange | `https://api.modrinth.com/_internal/oauth/token` |
@@ -31,7 +31,7 @@ After you've registered your application, it is important that you take note of
Once the user is ready to authorize your application, you need to construct a URL to redirect them to. The authorization URL for Modrinth is `https://api.modrinth.com/_internal/oauth/token`. Supply the following query parameters:
| Query parameter | Description |
-|-----------------|-------------------------------------------------------------------------------------------|
+| --------------- | ----------------------------------------------------------------------------------------- |
| `response_type` | In Modrinth this always needs to be `code`, since only code grants are supported |
| `client_id` | The application identifier found in the settings |
| `scope` | The permissions you need access to |
@@ -45,7 +45,7 @@ The scope identifiers are currently best found in the backend source code locate
The redirect URI is the endpoint on your server that will receive the code which can eventually be used to act on the user's behalf. For security reasons the redirect URI used has to be allowlisted in your application settings. The redirect will contain the following query parameters:
| Query parameter | Description |
-|-----------------|----------------------------------------------------|
+| --------------- | -------------------------------------------------- |
| `code` | The code that can be exchanged for an access token |
| `client_id` | Your client id |
| `redirect_uri` | The redirect URI which was used |
@@ -58,7 +58,7 @@ If you've followed the previous section on getting authorization, you should now
In the body use these fields:
| Field | Description |
-|----------------|--------------------------------------------------------------|
+| -------------- | ------------------------------------------------------------ |
| `code` | The authorization code |
| `client_id` | Your client id, the same as in the authorization request |
| `redirect_uri` | The redirect URI which was redirected to after authorization |
@@ -67,7 +67,7 @@ In the body use these fields:
If the request succeeds, you should receive a JSON payload with these fields:
| Field | Description |
-|----------------|------------------------------------------------------|
+| -------------- | ---------------------------------------------------- |
| `access_token` | The access token you can use to access the API |
| `token_type` | Currently only `Bearer` |
| `expires_in` | The amount of seconds until the access token expires |
@@ -77,19 +77,11 @@ To use this access token, you attach it to API requests in the `Authorization` h
If you have any questions, you're welcome to ask in #api-development in the [Discord guild], or create a ticket on the [support portal].
[RFC 6749]: https://datatracker.ietf.org/doc/html/rfc6749
-
[register an application]: https://modrinth.com/settings/applications
-
[principle of least privilege]: https://en.wikipedia.org/wiki/Principle_of_least_privilege
-
[`apps/labrinth/src/models/v3/pats.rs`]: https://github.com/modrinth/code/blob/main/apps/labrinth/src/models/v3/pats.rs
-
[CSRF]: https://en.wikipedia.org/wiki/Cross-site_request_forgery
-
[Clickjacking]: https://en.wikipedia.org/wiki/Clickjacking
-
[`/user` endpoint]: https://docs.modrinth.com/api/operations/getuserfromauth/
-
[Discord guild]: https://discord.modrinth.com
-
[support portal]: https://support.modrinth.com/en/
diff --git a/apps/docs/src/styles/modrinth.css b/apps/docs/src/styles/modrinth.css
index 4b35aa62..4f149c26 100644
--- a/apps/docs/src/styles/modrinth.css
+++ b/apps/docs/src/styles/modrinth.css
@@ -2,53 +2,53 @@
::backdrop,
:root[data-theme='light'],
[data-theme='light'] ::backdrop {
- --sl-font-system: Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto,
- Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ --sl-font-system: Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto,
+ Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
- --sl-color-white: var(--color-contrast); /* “white” */
- --sl-color-gray-1: var(--color-base);
- --sl-color-gray-2: var(--color-base);
- --sl-color-gray-3: var(--color-base);
- --sl-color-gray-4: var(--color-raised-bg);
- --sl-color-gray-5: var(--color-button-bg);
- --sl-color-gray-6: var(--color-raised-bg);
- --sl-color-black: var(--color-accent-contrast);
+ --sl-color-white: var(--color-contrast); /* “white” */
+ --sl-color-gray-1: var(--color-base);
+ --sl-color-gray-2: var(--color-base);
+ --sl-color-gray-3: var(--color-base);
+ --sl-color-gray-4: var(--color-raised-bg);
+ --sl-color-gray-5: var(--color-button-bg);
+ --sl-color-gray-6: var(--color-raised-bg);
+ --sl-color-black: var(--color-accent-contrast);
- --sl-color-accent-low: var(--color-green-highlight);
- --sl-color-accent: var(--color-brand);
- --sl-color-accent-high: var(--color-brand-highlight);
+ --sl-color-accent-low: var(--color-green-highlight);
+ --sl-color-accent: var(--color-brand);
+ --sl-color-accent-high: var(--color-brand-highlight);
- --sl-color-orange-low: var(--color-orange-highlight);
- --sl-color-orange: var(--color-orange);
- --sl-color-orange-high: var(--color-orange-highlight);
+ --sl-color-orange-low: var(--color-orange-highlight);
+ --sl-color-orange: var(--color-orange);
+ --sl-color-orange-high: var(--color-orange-highlight);
- --sl-color-green-low: var(--color-green-highlight);
- --sl-color-green: var(--color-green);
- --sl-color-green-high: var(--color-green-highlight);
+ --sl-color-green-low: var(--color-green-highlight);
+ --sl-color-green: var(--color-green);
+ --sl-color-green-high: var(--color-green-highlight);
- --sl-color-blue-low: var(--color-blue-highlight);
- --sl-color-blue: var(--color-blue);
- --sl-color-blue-high: var(--color-blue-highlight);
+ --sl-color-blue-low: var(--color-blue-highlight);
+ --sl-color-blue: var(--color-blue);
+ --sl-color-blue-high: var(--color-blue-highlight);
- --sl-color-purple-low: var(--color-purple-highlight);
- --sl-color-purple: var(--color-purple);
- --sl-color-purple-high: var(--color-purple-highlight);
+ --sl-color-purple-low: var(--color-purple-highlight);
+ --sl-color-purple: var(--color-purple);
+ --sl-color-purple-high: var(--color-purple-highlight);
- --sl-color-red-low: var(--color-red-highlight);
- --sl-color-red: var(--color-red);
- --sl-color-red-high: var(--color-red-highlight);
+ --sl-color-red-low: var(--color-red-highlight);
+ --sl-color-red: var(--color-red);
+ --sl-color-red-high: var(--color-red-highlight);
- --sl-color-text: var(--color-base);
- --sl-color-text-accent: var(--color-brand);
- --sl-color-text-invert: var(--color-accent-contrast);
- --sl-color-bg: var(--color-bg);
- --sl-color-bg-nav: var(--color-raised-bg);
- --sl-color-bg-sidebar: var(--color-raised-bg);
- --sl-color-bg-inline-code: var(--color-button-bg);
- --sl-color-bg-accent: var(--color-brand-highlight);
+ --sl-color-text: var(--color-base);
+ --sl-color-text-accent: var(--color-brand);
+ --sl-color-text-invert: var(--color-accent-contrast);
+ --sl-color-bg: var(--color-bg);
+ --sl-color-bg-nav: var(--color-raised-bg);
+ --sl-color-bg-sidebar: var(--color-raised-bg);
+ --sl-color-bg-inline-code: var(--color-button-bg);
+ --sl-color-bg-accent: var(--color-brand-highlight);
}
:root[data-theme='light'],
[data-theme='light'] ::backdrop {
- --sl-color-bg: var(--color-raised-bg);
+ --sl-color-bg: var(--color-raised-bg);
}
diff --git a/apps/docs/tsconfig.json b/apps/docs/tsconfig.json
index bcbf8b50..a3f69810 100644
--- a/apps/docs/tsconfig.json
+++ b/apps/docs/tsconfig.json
@@ -1,3 +1,3 @@
{
- "extends": "astro/tsconfigs/strict"
+ "extends": "astro/tsconfigs/strict"
}
diff --git a/apps/frontend/.eslintrc.cjs b/apps/frontend/.eslintrc.cjs
deleted file mode 100644
index b0faf894..00000000
--- a/apps/frontend/.eslintrc.cjs
+++ /dev/null
@@ -1,7 +0,0 @@
-module.exports = {
- root: true,
- extends: ["../../packages/eslint-config-custom/nuxt.js"],
- rules: {
- "import/no-unresolved": "off",
- },
-};
diff --git a/apps/frontend/.prettierignore b/apps/frontend/.prettierignore
index 4987eb4d..d4f9ef96 100644
--- a/apps/frontend/.prettierignore
+++ b/apps/frontend/.prettierignore
@@ -2,3 +2,6 @@
**/dist
**/.output
src/generated/**
+src/locales/**
+src/public/news/feed
+src/assets/**/*.svg
diff --git a/apps/frontend/.prettierrc b/apps/frontend/.prettierrc
deleted file mode 100644
index 8c662d19..00000000
--- a/apps/frontend/.prettierrc
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "endOfLine": "auto",
- "plugins": ["prettier-plugin-tailwindcss"]
-}
diff --git a/apps/frontend/crowdin.yml b/apps/frontend/crowdin.yml
index e7c47c7d..2817cde4 100644
--- a/apps/frontend/crowdin.yml
+++ b/apps/frontend/crowdin.yml
@@ -1,6 +1,6 @@
project_id: 518556
preserve_hierarchy: true
-commit_message: "[ci skip]"
+commit_message: '[ci skip]'
files:
- source: /locales/en-US/*
diff --git a/apps/frontend/eslint.config.mjs b/apps/frontend/eslint.config.mjs
new file mode 100644
index 00000000..36a67d41
--- /dev/null
+++ b/apps/frontend/eslint.config.mjs
@@ -0,0 +1,10 @@
+import config from '@modrinth/tooling-config/eslint/nuxt.mjs'
+export default config.append([
+ {
+ rules: {
+ '@typescript-eslint/no-explicit-any': 'off',
+ 'import/no-unresolved': 'off',
+ 'no-undef': 'off',
+ },
+ },
+])
diff --git a/apps/frontend/nuxt.config.ts b/apps/frontend/nuxt.config.ts
index 269ee2e7..ab532a20 100644
--- a/apps/frontend/nuxt.config.ts
+++ b/apps/frontend/nuxt.config.ts
@@ -1,27 +1,28 @@
-import { promises as fs } from "fs";
-import { pathToFileURL } from "node:url";
-import svgLoader from "vite-svg-loader";
-import { resolve, basename, relative } from "pathe";
-import { defineNuxtConfig } from "nuxt/config";
-import { $fetch } from "ofetch";
-import { globIterate } from "glob";
-import { match as matchLocale } from "@formatjs/intl-localematcher";
-import { consola } from "consola";
+import { pathToFileURL } from 'node:url'
-const API_URL = "https://staging-api.modrinth.com/v2/";
+import { match as matchLocale } from '@formatjs/intl-localematcher'
+import { consola } from 'consola'
+import { promises as fs } from 'fs'
+import { globIterate } from 'glob'
+import { defineNuxtConfig } from 'nuxt/config'
+import { $fetch } from 'ofetch'
+import { basename, relative, resolve } from 'pathe'
+import svgLoader from 'vite-svg-loader'
+
+const STAGING_API_URL = 'https://staging-api.modrinth.com/v2/'
const preloadedFonts = [
- "inter/Inter-Regular.woff2",
- "inter/Inter-Medium.woff2",
- "inter/Inter-SemiBold.woff2",
- "inter/Inter-Bold.woff2",
-];
+ 'inter/Inter-Regular.woff2',
+ 'inter/Inter-Medium.woff2',
+ 'inter/Inter-SemiBold.woff2',
+ 'inter/Inter-Bold.woff2',
+]
const favicons = {
- "(prefers-color-scheme:no-preference)": "/favicon-light.ico",
- "(prefers-color-scheme:light)": "/favicon-light.ico",
- "(prefers-color-scheme:dark)": "/favicon.ico",
-};
+ '(prefers-color-scheme:no-preference)': '/favicon-light.ico',
+ '(prefers-color-scheme:light)': '/favicon-light.ico',
+ '(prefers-color-scheme:dark)': '/favicon.ico',
+}
/**
* Tags of locales that are auto-discovered besides the default locale.
@@ -29,459 +30,467 @@ const favicons = {
* Preferably only the locales that reach a certain threshold of complete
* translations would be included in this array.
*/
-const enabledLocales: string[] = [];
+const enabledLocales: string[] = []
/**
* Overrides for the categories of the certain locales.
*/
-const localesCategoriesOverrides: Partial> = {
- "en-x-pirate": "fun",
- "en-x-updown": "fun",
- "en-x-lolcat": "fun",
- "en-x-uwu": "fun",
- "ru-x-bandit": "fun",
- ar: "experimental",
- he: "experimental",
- pes: "experimental",
-};
+const localesCategoriesOverrides: Partial> = {
+ 'en-x-pirate': 'fun',
+ 'en-x-updown': 'fun',
+ 'en-x-lolcat': 'fun',
+ 'en-x-uwu': 'fun',
+ 'ru-x-bandit': 'fun',
+ ar: 'experimental',
+ he: 'experimental',
+ pes: 'experimental',
+}
export default defineNuxtConfig({
- srcDir: "src/",
- app: {
- head: {
- htmlAttrs: {
- lang: "en",
- },
- title: "Modrinth",
- link: [
- // The type is necessary because the linter can't always compare this very nested/complex type on itself
- ...preloadedFonts.map((font): object => {
- return {
- rel: "preload",
- href: `https://cdn-raw.modrinth.com/fonts/${font}?v=3.19`,
- as: "font",
- type: "font/woff2",
- crossorigin: "anonymous",
- };
- }),
- ...Object.entries(favicons).map(([media, href]): object => {
- return { rel: "icon", type: "image/x-icon", href, media };
- }),
- ...Object.entries(favicons).map(([media, href]): object => {
- return { rel: "apple-touch-icon", type: "image/x-icon", href, media, sizes: "64x64" };
- }),
- {
- rel: "search",
- type: "application/opensearchdescription+xml",
- href: "/opensearch.xml",
- title: "Modrinth mods",
- },
- ],
- },
- },
- vite: {
- define: {
- global: {},
- },
- esbuild: {
- define: {
- global: "globalThis",
- },
- },
- cacheDir: "../../node_modules/.vite/apps/knossos",
- resolve: {
- dedupe: ["vue"],
- },
- plugins: [
- svgLoader({
- svgoConfig: {
- plugins: [
- {
- name: "preset-default",
- params: {
- overrides: {
- removeViewBox: false,
- },
- },
- },
- ],
- },
- }),
- ],
- },
- hooks: {
- async "build:before"() {
- // 30 minutes
- const TTL = 30 * 60 * 1000;
+ srcDir: 'src/',
+ app: {
+ head: {
+ htmlAttrs: {
+ lang: 'en',
+ },
+ title: 'Modrinth',
+ link: [
+ // The type is necessary because the linter can't always compare this very nested/complex type on itself
+ ...preloadedFonts.map((font): object => {
+ return {
+ rel: 'preload',
+ href: `https://cdn-raw.modrinth.com/fonts/${font}?v=3.19`,
+ as: 'font',
+ type: 'font/woff2',
+ crossorigin: 'anonymous',
+ }
+ }),
+ ...Object.entries(favicons).map(([media, href]): object => {
+ return { rel: 'icon', type: 'image/x-icon', href, media }
+ }),
+ ...Object.entries(favicons).map(([media, href]): object => {
+ return { rel: 'apple-touch-icon', type: 'image/x-icon', href, media, sizes: '64x64' }
+ }),
+ {
+ rel: 'search',
+ type: 'application/opensearchdescription+xml',
+ href: '/opensearch.xml',
+ title: 'Modrinth mods',
+ },
+ ],
+ },
+ },
+ vite: {
+ define: {
+ global: {},
+ },
+ esbuild: {
+ define: {
+ global: 'globalThis',
+ },
+ },
+ cacheDir: '../../node_modules/.vite/apps/knossos',
+ resolve: {
+ dedupe: ['vue'],
+ },
+ plugins: [
+ svgLoader({
+ svgoConfig: {
+ plugins: [
+ {
+ name: 'preset-default',
+ params: {
+ overrides: {
+ removeViewBox: false,
+ },
+ },
+ },
+ ],
+ },
+ }),
+ ],
+ },
+ hooks: {
+ async 'build:before'() {
+ // 30 minutes
+ const TTL = 30 * 60 * 1000
- let state: {
- lastGenerated?: string;
- apiUrl?: string;
- categories?: any[];
- loaders?: any[];
- gameVersions?: any[];
- donationPlatforms?: any[];
- reportTypes?: any[];
- homePageProjects?: any[];
- homePageSearch?: any[];
- homePageNotifs?: any[];
- products?: any[];
- errors?: number[];
- } = {};
+ let state: {
+ lastGenerated?: string
+ apiUrl?: string
+ categories?: any[]
+ loaders?: any[]
+ gameVersions?: any[]
+ donationPlatforms?: any[]
+ reportTypes?: any[]
+ homePageProjects?: any[]
+ homePageSearch?: any[]
+ homePageNotifs?: any[]
+ products?: any[]
+ errors?: number[]
+ } = {}
- try {
- state = JSON.parse(await fs.readFile("./src/generated/state.json", "utf8"));
- } catch {
- // File doesn't exist, create folder
- await fs.mkdir("./src/generated", { recursive: true });
- }
+ try {
+ state = JSON.parse(await fs.readFile('./src/generated/state.json', 'utf8'))
+ } catch {
+ // File doesn't exist, create folder
+ await fs.mkdir('./src/generated', { recursive: true })
+ }
- const API_URL = getApiUrl();
+ const API_URL = getApiUrl()
- if (
- // Skip regeneration if within TTL...
- state.lastGenerated &&
- new Date(state.lastGenerated).getTime() + TTL > new Date().getTime() &&
- // ...but only if the API URL is the same
- state.apiUrl === API_URL
- ) {
- return;
- }
+ if (
+ // Skip regeneration if within TTL...
+ state.lastGenerated &&
+ new Date(state.lastGenerated).getTime() + TTL > new Date().getTime() &&
+ // ...but only if the API URL is the same
+ state.apiUrl === API_URL &&
+ // ...and if no errors were caught during the last generation
+ (state.errors ?? []).length === 0
+ ) {
+ console.log(
+ 'Tags already recently generated. Delete apps/frontend/generated/state.json to force regeneration.',
+ )
+ return
+ }
- state.lastGenerated = new Date().toISOString();
+ state.lastGenerated = new Date().toISOString()
- state.apiUrl = API_URL;
+ state.apiUrl = API_URL
- const headers = {
- headers: {
- "user-agent": "Knossos generator (support@modrinth.com)",
- },
- };
+ const headers = {
+ headers: {
+ 'user-agent': 'Knossos generator (support@modrinth.com)',
+ },
+ }
- const caughtErrorCodes = new Set();
+ const caughtErrorCodes = new Set()
- function handleFetchError(err: any, defaultValue: any) {
- console.error("Error generating state: ", err);
- caughtErrorCodes.add(err.status);
- return defaultValue;
- }
+ function handleFetchError(err: any, defaultValue: any) {
+ console.error('Error generating state: ', err)
+ caughtErrorCodes.add(err.status)
+ return defaultValue
+ }
- const [
- categories,
- loaders,
- gameVersions,
- donationPlatforms,
- reportTypes,
- homePageProjects,
- homePageSearch,
- homePageNotifs,
- products,
- ] = await Promise.all([
- $fetch(`${API_URL}tag/category`, headers).catch((err) => handleFetchError(err, [])),
- $fetch(`${API_URL}tag/loader`, headers).catch((err) => handleFetchError(err, [])),
- $fetch(`${API_URL}tag/game_version`, headers).catch((err) => handleFetchError(err, [])),
- $fetch(`${API_URL}tag/donation_platform`, headers).catch((err) =>
- handleFetchError(err, []),
- ),
- $fetch(`${API_URL}tag/report_type`, headers).catch((err) => handleFetchError(err, [])),
- $fetch(`${API_URL}projects_random?count=60`, headers).catch((err) =>
- handleFetchError(err, []),
- ),
- $fetch(`${API_URL}search?limit=3&query=leave&index=relevance`, headers).catch((err) =>
- handleFetchError(err, {}),
- ),
- $fetch(`${API_URL}search?limit=3&query=&index=updated`, headers).catch((err) =>
- handleFetchError(err, {}),
- ),
- $fetch(`${API_URL.replace("/v2/", "/_internal/")}billing/products`, headers).catch((err) =>
- handleFetchError(err, []),
- ),
- ]);
+ const [
+ categories,
+ loaders,
+ gameVersions,
+ donationPlatforms,
+ reportTypes,
+ homePageProjects,
+ homePageSearch,
+ homePageNotifs,
+ products,
+ ] = await Promise.all([
+ $fetch(`${API_URL}tag/category`, headers).catch((err) => handleFetchError(err, [])),
+ $fetch(`${API_URL}tag/loader`, headers).catch((err) => handleFetchError(err, [])),
+ $fetch(`${API_URL}tag/game_version`, headers).catch((err) => handleFetchError(err, [])),
+ $fetch(`${API_URL}tag/donation_platform`, headers).catch((err) =>
+ handleFetchError(err, []),
+ ),
+ $fetch(`${API_URL}tag/report_type`, headers).catch((err) => handleFetchError(err, [])),
+ $fetch(`${API_URL}projects_random?count=60`, headers).catch((err) =>
+ handleFetchError(err, []),
+ ),
+ $fetch(`${API_URL}search?limit=3&query=leave&index=relevance`, headers).catch((err) =>
+ handleFetchError(err, {}),
+ ),
+ $fetch(`${API_URL}search?limit=3&query=&index=updated`, headers).catch((err) =>
+ handleFetchError(err, {}),
+ ),
+ $fetch(`${API_URL.replace('/v2/', '/_internal/')}billing/products`, headers).catch((err) =>
+ handleFetchError(err, []),
+ ),
+ ])
- state.categories = categories;
- state.loaders = loaders;
- state.gameVersions = gameVersions;
- state.donationPlatforms = donationPlatforms;
- state.reportTypes = reportTypes;
- state.homePageProjects = homePageProjects;
- state.homePageSearch = homePageSearch;
- state.homePageNotifs = homePageNotifs;
- state.products = products;
- state.errors = [...caughtErrorCodes];
+ state.categories = categories
+ state.loaders = loaders
+ state.gameVersions = gameVersions
+ state.donationPlatforms = donationPlatforms
+ state.reportTypes = reportTypes
+ state.homePageProjects = homePageProjects
+ state.homePageSearch = homePageSearch
+ state.homePageNotifs = homePageNotifs
+ state.products = products
+ state.errors = [...caughtErrorCodes]
- await fs.writeFile("./src/generated/state.json", JSON.stringify(state));
+ await fs.writeFile('./src/generated/state.json', JSON.stringify(state))
- console.log("Tags generated!");
- },
- "pages:extend"(routes) {
- routes.splice(
- routes.findIndex((x) => x.name === "search-searchProjectType"),
- 1,
- );
+ console.log('Tags generated!')
+ },
+ 'pages:extend'(routes) {
+ routes.splice(
+ routes.findIndex((x) => x.name === 'search-searchProjectType'),
+ 1,
+ )
- const types = ["mods", "modpacks", "plugins", "resourcepacks", "shaders", "datapacks"];
+ const types = ['mods', 'modpacks', 'plugins', 'resourcepacks', 'shaders', 'datapacks']
- types.forEach((type) =>
- routes.push({
- name: `search-${type}`,
- path: `/${type}`,
- file: resolve(__dirname, "src/pages/search/[searchProjectType].vue"),
- children: [],
- }),
- );
- },
- async "vintl:extendOptions"(opts) {
- opts.locales ??= [];
+ types.forEach((type) =>
+ routes.push({
+ name: `search-${type}`,
+ path: `/${type}`,
+ file: resolve(__dirname, 'src/pages/search/[searchProjectType].vue'),
+ children: [],
+ }),
+ )
+ },
+ async 'vintl:extendOptions'(opts) {
+ opts.locales ??= []
- const isProduction = getDomain() === "https://modrinth.com";
+ const isProduction = getDomain() === 'https://modrinth.com'
- const resolveCompactNumberDataImport = await (async () => {
- const compactNumberLocales: string[] = [];
+ const resolveCompactNumberDataImport = await (async () => {
+ const compactNumberLocales: string[] = []
- for await (const localeFile of globIterate(
- "node_modules/@vintl/compact-number/dist/locale-data/*.mjs",
- { ignore: "**/*.data.mjs" },
- )) {
- const tag = basename(localeFile, ".mjs");
- compactNumberLocales.push(tag);
- }
+ for await (const localeFile of globIterate(
+ 'node_modules/@vintl/compact-number/dist/locale-data/*.mjs',
+ { ignore: '**/*.data.mjs' },
+ )) {
+ const tag = basename(localeFile, '.mjs')
+ compactNumberLocales.push(tag)
+ }
- function resolveImport(tag: string) {
- const matchedTag = matchLocale([tag], compactNumberLocales, "en-x-placeholder");
- return matchedTag === "en-x-placeholder"
- ? undefined
- : `@vintl/compact-number/locale-data/${matchedTag}`;
- }
+ function resolveImport(tag: string) {
+ const matchedTag = matchLocale([tag], compactNumberLocales, 'en-x-placeholder')
+ return matchedTag === 'en-x-placeholder'
+ ? undefined
+ : `@vintl/compact-number/locale-data/${matchedTag}`
+ }
- return resolveImport;
- })();
+ return resolveImport
+ })()
- const resolveOmorphiaLocaleImport = await (async () => {
- const omorphiaLocales: string[] = [];
- const omorphiaLocaleSets = new Map();
+ const resolveOmorphiaLocaleImport = await (async () => {
+ const omorphiaLocales: string[] = []
+ const omorphiaLocaleSets = new Map()
- for await (const localeDir of globIterate("node_modules/@modrinth/ui/src/locales/*", {
- posix: true,
- })) {
- const tag = basename(localeDir);
- omorphiaLocales.push(tag);
+ for (const pkgLocales of [`node_modules/@modrinth/**/src/locales/*`]) {
+ for await (const localeDir of globIterate(pkgLocales, {
+ posix: true,
+ })) {
+ const tag = basename(localeDir)
+ if (!omorphiaLocales.includes(tag)) {
+ omorphiaLocales.push(tag)
+ }
- const localeFiles: { from: string; format?: string }[] = [];
+ const entry = omorphiaLocaleSets.get(tag) ?? { files: [] }
+ omorphiaLocaleSets.set(tag, entry)
- omorphiaLocaleSets.set(tag, { files: localeFiles });
+ for await (const localeFile of globIterate(`${localeDir}/*`, { posix: true })) {
+ entry.files.push({
+ from: pathToFileURL(localeFile).toString(),
+ format: 'default',
+ })
+ }
+ }
+ }
- for await (const localeFile of globIterate(`${localeDir}/*`, { posix: true })) {
- localeFiles.push({
- from: pathToFileURL(localeFile).toString(),
- format: "default",
- });
- }
- }
+ return function resolveLocaleImport(tag: string) {
+ return omorphiaLocaleSets.get(matchLocale([tag], omorphiaLocales, 'en-x-placeholder'))
+ }
+ })()
- return function resolveLocaleImport(tag: string) {
- return omorphiaLocaleSets.get(matchLocale([tag], omorphiaLocales, "en-x-placeholder"));
- };
- })();
+ for await (const localeDir of globIterate('src/locales/*/', { posix: true })) {
+ const tag = basename(localeDir)
+ if (isProduction && !enabledLocales.includes(tag) && opts.defaultLocale !== tag) continue
- for await (const localeDir of globIterate("src/locales/*/", { posix: true })) {
- const tag = basename(localeDir);
- if (isProduction && !enabledLocales.includes(tag) && opts.defaultLocale !== tag) continue;
+ const locale =
+ opts.locales.find((locale) => locale.tag === tag) ??
+ opts.locales[opts.locales.push({ tag }) - 1]!
- const locale =
- opts.locales.find((locale) => locale.tag === tag) ??
- opts.locales[opts.locales.push({ tag }) - 1]!;
+ const localeFiles = (locale.files ??= [])
- const localeFiles = (locale.files ??= []);
+ for await (const localeFile of globIterate(`${localeDir}/*`, { posix: true })) {
+ const fileName = basename(localeFile)
+ if (fileName === 'index.json') {
+ localeFiles.push({
+ from: `./${relative('./src', localeFile)}`,
+ format: 'crowdin',
+ })
+ } else if (fileName === 'meta.json') {
+ const meta: Record = await fs
+ .readFile(localeFile, 'utf8')
+ .then((date) => JSON.parse(date))
+ const localeMeta = (locale.meta ??= {})
+ for (const key in meta) {
+ const value = meta[key]
+ if (value === undefined) continue
+ localeMeta[key] = value.message
+ }
+ } else {
+ ;(locale.resources ??= {})[fileName] = `./${relative('./src', localeFile)}`
+ }
+ }
- for await (const localeFile of globIterate(`${localeDir}/*`, { posix: true })) {
- const fileName = basename(localeFile);
- if (fileName === "index.json") {
- localeFiles.push({
- from: `./${relative("./src", localeFile)}`,
- format: "crowdin",
- });
- } else if (fileName === "meta.json") {
- const meta: Record = await fs
- .readFile(localeFile, "utf8")
- .then((date) => JSON.parse(date));
- const localeMeta = (locale.meta ??= {});
- for (const key in meta) {
- const value = meta[key];
- if (value === undefined) continue;
- localeMeta[key] = value.message;
- }
- } else {
- (locale.resources ??= {})[fileName] = `./${relative("./src", localeFile)}`;
- }
- }
+ const categoryOverride = localesCategoriesOverrides[tag]
+ if (categoryOverride != null) {
+ ;(locale.meta ??= {}).category = categoryOverride
+ }
- const categoryOverride = localesCategoriesOverrides[tag];
- if (categoryOverride != null) {
- (locale.meta ??= {}).category = categoryOverride;
- }
+ const omorphiaLocaleData = resolveOmorphiaLocaleImport(tag)
+ if (omorphiaLocaleData != null) {
+ localeFiles.push(...omorphiaLocaleData.files)
+ }
- const omorphiaLocaleData = resolveOmorphiaLocaleImport(tag);
- if (omorphiaLocaleData != null) {
- localeFiles.push(...omorphiaLocaleData.files);
- }
+ const cnDataImport = resolveCompactNumberDataImport(tag)
+ if (cnDataImport != null) {
+ ;(locale.additionalImports ??= []).push({
+ from: cnDataImport,
+ resolve: false,
+ })
+ }
+ }
+ },
+ },
+ runtimeConfig: {
+ // @ts-ignore
+ apiBaseUrl: process.env.BASE_URL ?? globalThis.BASE_URL ?? getApiUrl(),
+ // @ts-ignore
+ rateLimitKey: process.env.RATE_LIMIT_IGNORE_KEY ?? globalThis.RATE_LIMIT_IGNORE_KEY,
+ pyroBaseUrl: process.env.PYRO_BASE_URL,
+ public: {
+ apiBaseUrl: getApiUrl(),
+ pyroBaseUrl: process.env.PYRO_BASE_URL,
+ siteUrl: getDomain(),
+ production: isProduction(),
+ featureFlagOverrides: getFeatureFlagOverrides(),
- const cnDataImport = resolveCompactNumberDataImport(tag);
- if (cnDataImport != null) {
- (locale.additionalImports ??= []).push({
- from: cnDataImport,
- resolve: false,
- });
- }
- }
- },
- },
- runtimeConfig: {
- // @ts-ignore
- apiBaseUrl: process.env.BASE_URL ?? globalThis.BASE_URL ?? getApiUrl(),
- // @ts-ignore
- rateLimitKey: process.env.RATE_LIMIT_IGNORE_KEY ?? globalThis.RATE_LIMIT_IGNORE_KEY,
- pyroBaseUrl: process.env.PYRO_BASE_URL,
- public: {
- apiBaseUrl: getApiUrl(),
- pyroBaseUrl: process.env.PYRO_BASE_URL,
- siteUrl: getDomain(),
- production: isProduction(),
- featureFlagOverrides: getFeatureFlagOverrides(),
+ owner: process.env.VERCEL_GIT_REPO_OWNER || 'modrinth',
+ slug: process.env.VERCEL_GIT_REPO_SLUG || 'code',
+ branch:
+ process.env.VERCEL_GIT_COMMIT_REF ||
+ process.env.CF_PAGES_BRANCH ||
+ // @ts-ignore
+ globalThis.CF_PAGES_BRANCH ||
+ 'master',
+ hash:
+ process.env.VERCEL_GIT_COMMIT_SHA ||
+ process.env.CF_PAGES_COMMIT_SHA ||
+ // @ts-ignore
+ globalThis.CF_PAGES_COMMIT_SHA ||
+ 'unknown',
- owner: process.env.VERCEL_GIT_REPO_OWNER || "modrinth",
- slug: process.env.VERCEL_GIT_REPO_SLUG || "code",
- branch:
- process.env.VERCEL_GIT_COMMIT_REF ||
- process.env.CF_PAGES_BRANCH ||
- // @ts-ignore
- globalThis.CF_PAGES_BRANCH ||
- "master",
- hash:
- process.env.VERCEL_GIT_COMMIT_SHA ||
- process.env.CF_PAGES_COMMIT_SHA ||
- // @ts-ignore
- globalThis.CF_PAGES_COMMIT_SHA ||
- "unknown",
+ stripePublishableKey:
+ process.env.STRIPE_PUBLISHABLE_KEY ||
+ globalThis.STRIPE_PUBLISHABLE_KEY ||
+ 'pk_test_51JbFxJJygY5LJFfKV50mnXzz3YLvBVe2Gd1jn7ljWAkaBlRz3VQdxN9mXcPSrFbSqxwAb0svte9yhnsmm7qHfcWn00R611Ce7b',
+ },
+ },
+ typescript: {
+ shim: false,
+ strict: true,
+ typeCheck: false,
+ tsConfig: {
+ compilerOptions: {
+ moduleResolution: 'bundler',
+ allowImportingTsExtensions: true,
+ },
+ },
+ },
+ modules: ['@vintl/nuxt', '@pinia/nuxt'],
+ vintl: {
+ defaultLocale: 'en-US',
+ locales: [
+ {
+ tag: 'en-US',
+ meta: {
+ static: {
+ iso: 'en',
+ },
+ },
+ },
+ ],
+ storage: 'cookie',
+ parserless: 'only-prod',
+ seo: {
+ defaultLocaleHasParameter: false,
+ },
+ onParseError({ error, message, messageId, moduleId, parseMessage, parserOptions }) {
+ const errorMessage = String(error)
+ const modulePath = relative(__dirname, moduleId)
- stripePublishableKey:
- process.env.STRIPE_PUBLISHABLE_KEY ||
- globalThis.STRIPE_PUBLISHABLE_KEY ||
- "pk_test_51JbFxJJygY5LJFfKV50mnXzz3YLvBVe2Gd1jn7ljWAkaBlRz3VQdxN9mXcPSrFbSqxwAb0svte9yhnsmm7qHfcWn00R611Ce7b",
- },
- },
- typescript: {
- shim: false,
- strict: true,
- typeCheck: false,
- tsConfig: {
- compilerOptions: {
- moduleResolution: "bundler",
- allowImportingTsExtensions: true,
- },
- },
- },
- modules: ["@vintl/nuxt", "@pinia/nuxt"],
- vintl: {
- defaultLocale: "en-US",
- locales: [
- {
- tag: "en-US",
- meta: {
- static: {
- iso: "en",
- },
- },
- },
- ],
- storage: "cookie",
- parserless: "only-prod",
- seo: {
- defaultLocaleHasParameter: false,
- },
- onParseError({ error, message, messageId, moduleId, parseMessage, parserOptions }) {
- const errorMessage = String(error);
- const modulePath = relative(__dirname, moduleId);
+ try {
+ const fallback = parseMessage(message, { ...parserOptions, ignoreTag: true })
- try {
- const fallback = parseMessage(message, { ...parserOptions, ignoreTag: true });
+ consola.warn(
+ `[i18n] ${messageId} in ${modulePath} cannot be parsed normally due to ${errorMessage}. The tags will will not be parsed.`,
+ )
- consola.warn(
- `[i18n] ${messageId} in ${modulePath} cannot be parsed normally due to ${errorMessage}. The tags will will not be parsed.`,
- );
+ return fallback
+ } catch (err) {
+ const secondaryErrorMessage = String(err)
- return fallback;
- } catch (err) {
- const secondaryErrorMessage = String(err);
+ const reason =
+ errorMessage === secondaryErrorMessage
+ ? errorMessage
+ : `${errorMessage} and ${secondaryErrorMessage}`
- const reason =
- errorMessage === secondaryErrorMessage
- ? errorMessage
- : `${errorMessage} and ${secondaryErrorMessage}`;
-
- consola.warn(
- `[i18n] ${messageId} in ${modulePath} cannot be parsed due to ${reason}. It will be skipped.`,
- );
- }
- },
- },
- nitro: {
- moduleSideEffects: ["@vintl/compact-number/locale-data"],
- },
- devtools: {
- enabled: true,
- },
- css: ["~/assets/styles/tailwind.css"],
- postcss: {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
- },
- routeRules: {
- "/**": {
- headers: {
- "Accept-CH": "Sec-CH-Prefers-Color-Scheme",
- "Critical-CH": "Sec-CH-Prefers-Color-Scheme",
- },
- },
- },
- compatibilityDate: "2024-07-03",
- telemetry: false,
-});
+ consola.warn(
+ `[i18n] ${messageId} in ${modulePath} cannot be parsed due to ${reason}. It will be skipped.`,
+ )
+ }
+ },
+ },
+ nitro: {
+ moduleSideEffects: ['@vintl/compact-number/locale-data'],
+ },
+ devtools: {
+ enabled: true,
+ },
+ css: ['~/assets/styles/tailwind.css'],
+ postcss: {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+ },
+ routeRules: {
+ '/**': {
+ headers: {
+ 'Accept-CH': 'Sec-CH-Prefers-Color-Scheme',
+ 'Critical-CH': 'Sec-CH-Prefers-Color-Scheme',
+ },
+ },
+ },
+ compatibilityDate: '2024-07-03',
+ telemetry: false,
+})
function getApiUrl() {
- // @ts-ignore
- return process.env.BROWSER_BASE_URL ?? globalThis.BROWSER_BASE_URL ?? API_URL;
+ // @ts-ignore
+ return process.env.BROWSER_BASE_URL ?? globalThis.BROWSER_BASE_URL ?? STAGING_API_URL
}
function isProduction() {
- return process.env.NODE_ENV === "production";
+ return process.env.NODE_ENV === 'production'
}
function getFeatureFlagOverrides() {
- return JSON.parse(process.env.FLAG_OVERRIDES ?? "{}");
+ return JSON.parse(process.env.FLAG_OVERRIDES ?? '{}')
}
function getDomain() {
- if (process.env.NODE_ENV === "production") {
- if (process.env.SITE_URL) {
- return process.env.SITE_URL;
- }
- // @ts-ignore
- else if (process.env.CF_PAGES_URL || globalThis.CF_PAGES_URL) {
- // @ts-ignore
- return process.env.CF_PAGES_URL ?? globalThis.CF_PAGES_URL;
- } else if (process.env.HEROKU_APP_NAME) {
- return `https://${process.env.HEROKU_APP_NAME}.herokuapp.com`;
- } else if (process.env.VERCEL_URL) {
- return `https://${process.env.VERCEL_URL}`;
- } else if (getApiUrl() === API_URL) {
- return "https://staging.modrinth.com";
- } else {
- return "https://modrinth.com";
- }
- } else {
- const port = process.env.PORT || 3000;
- return `http://localhost:${port}`;
- }
+ if (process.env.NODE_ENV === 'production') {
+ if (process.env.SITE_URL) {
+ return process.env.SITE_URL
+ }
+ // @ts-ignore
+ else if (process.env.CF_PAGES_URL || globalThis.CF_PAGES_URL) {
+ // @ts-ignore
+ return process.env.CF_PAGES_URL ?? globalThis.CF_PAGES_URL
+ } else if (process.env.HEROKU_APP_NAME) {
+ return `https://${process.env.HEROKU_APP_NAME}.herokuapp.com`
+ } else if (process.env.VERCEL_URL) {
+ return `https://${process.env.VERCEL_URL}`
+ } else if (getApiUrl() === STAGING_API_URL) {
+ return 'https://staging.modrinth.com'
+ } else {
+ return 'https://modrinth.com'
+ }
+ } else {
+ const port = process.env.PORT || 3000
+ return `http://localhost:${port}`
+ }
}
diff --git a/apps/frontend/package.json b/apps/frontend/package.json
index 7cded831..a4c0fe7f 100644
--- a/apps/frontend/package.json
+++ b/apps/frontend/package.json
@@ -1,73 +1,76 @@
{
- "name": "@modrinth/frontend",
- "private": true,
- "type": "module",
- "scripts": {
- "build": "nuxi build",
- "dev": "nuxi dev",
- "generate": "nuxi generate",
- "preview": "nuxi preview",
- "postinstall": "nuxi prepare",
- "lint": "eslint . && prettier --check .",
- "fix": "eslint . --fix && prettier --write .",
- "intl:extract": "formatjs extract \"{,src/components,src/composables,src/layouts,src/middleware,src/modules,src/pages,src/plugins,src/utils}/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" \"src/error.vue\" --ignore '**/*.d.ts' --ignore 'node_modules' --out-file src/locales/en-US/index.json --format crowdin --preserve-whitespace",
- "test": "nuxi build"
- },
- "devDependencies": {
- "@formatjs/cli": "^6.2.12",
- "@nuxt/devtools": "^1.3.3",
- "@types/dompurify": "^3.0.5",
- "@types/node": "^20.1.0",
- "@vintl/compact-number": "^2.0.5",
- "@vintl/how-ago": "^3.0.1",
- "@vintl/nuxt": "^1.9.2",
- "autoprefixer": "^10.4.19",
- "eslint": "^8.57.0",
- "glob": "^10.2.7",
- "nuxt": "^3.14.1592",
- "postcss": "^8.4.39",
- "prettier-plugin-tailwindcss": "^0.6.5",
- "sass": "^1.58.0",
- "tailwindcss": "^3.4.4",
- "typescript": "^5.4.5",
- "vite-svg-loader": "^5.1.0",
- "vue-tsc": "^2.0.24"
- },
- "dependencies": {
- "@formatjs/intl-localematcher": "^0.5.4",
- "@intercom/messenger-js-sdk": "^0.0.14",
- "@ltd/j-toml": "^1.38.0",
- "@modrinth/assets": "workspace:*",
- "@modrinth/blog": "workspace:*",
- "@modrinth/moderation": "workspace:*",
- "@modrinth/ui": "workspace:*",
- "@modrinth/utils": "workspace:*",
- "@pinia/nuxt": "^0.5.1",
- "@types/three": "^0.172.0",
- "@vintl/vintl": "^4.4.1",
- "@vueuse/core": "^11.1.0",
- "ace-builds": "^1.36.2",
- "ansi-to-html": "^0.7.2",
- "dayjs": "^1.11.7",
- "dompurify": "^3.1.7",
- "floating-vue": "^5.2.2",
- "fuse.js": "^6.6.2",
- "highlight.js": "^11.7.0",
- "iso-3166-1": "^2.1.1",
- "js-yaml": "^4.1.0",
- "jszip": "^3.10.1",
- "markdown-it": "14.1.0",
- "pathe": "^1.1.2",
- "pinia": "^2.1.7",
- "prettier": "^3.6.2",
- "qrcode.vue": "^3.4.0",
- "semver": "^7.5.4",
- "three": "^0.172.0",
- "vue-multiselect": "3.0.0-alpha.2",
- "vue-typed-virtual-list": "^1.0.10",
- "vue3-ace-editor": "^2.2.4",
- "vue3-apexcharts": "^1.5.2",
- "xss": "^1.0.14"
- },
- "web-types": "../../web-types.json"
+ "name": "@modrinth/frontend",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "build": "nuxi build",
+ "dev": "nuxi dev",
+ "generate": "nuxi generate",
+ "preview": "nuxi preview",
+ "postinstall": "nuxi prepare",
+ "lint": "eslint . && prettier --check .",
+ "fix": "eslint . --fix && prettier --write .",
+ "intl:extract": "formatjs extract \"{,src/components,src/composables,src/layouts,src/middleware,src/modules,src/pages,src/plugins,src/utils}/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" \"src/error.vue\" --ignore '**/*.d.ts' --ignore 'node_modules' --out-file src/locales/en-US/index.json --format crowdin --preserve-whitespace",
+ "test": "nuxi build"
+ },
+ "devDependencies": {
+ "@formatjs/cli": "^6.2.12",
+ "@nuxt/devtools": "^1.3.3",
+ "@types/dompurify": "^3.0.5",
+ "@types/node": "^20.1.0",
+ "@vintl/compact-number": "^2.0.5",
+ "@vintl/how-ago": "^3.0.1",
+ "@vintl/nuxt": "^1.9.2",
+ "autoprefixer": "^10.4.19",
+ "eslint": "^8.57.0",
+ "glob": "^10.2.7",
+ "nuxt": "^3.14.1592",
+ "postcss": "^8.4.39",
+ "prettier-plugin-tailwindcss": "^0.6.5",
+ "sass": "^1.58.0",
+ "tailwindcss": "^3.4.4",
+ "typescript": "^5.4.5",
+ "vite-svg-loader": "^5.1.0",
+ "vue-tsc": "^2.0.24"
+ },
+ "dependencies": {
+ "@formatjs/intl-localematcher": "^0.5.4",
+ "@intercom/messenger-js-sdk": "^0.0.14",
+ "@ltd/j-toml": "^1.38.0",
+ "@modrinth/assets": "workspace:*",
+ "@modrinth/blog": "workspace:*",
+ "@modrinth/moderation": "workspace:*",
+ "@modrinth/ui": "workspace:*",
+ "@modrinth/utils": "workspace:*",
+ "@pinia/nuxt": "^0.5.1",
+ "@types/three": "^0.172.0",
+ "@vintl/vintl": "^4.4.1",
+ "@vueuse/core": "^11.1.0",
+ "ace-builds": "^1.36.2",
+ "ansi-to-html": "^0.7.2",
+ "dayjs": "^1.11.7",
+ "dompurify": "^3.1.7",
+ "floating-vue": "^5.2.2",
+ "fuse.js": "^6.6.2",
+ "highlight.js": "^11.7.0",
+ "iso-3166-1": "^2.1.1",
+ "js-yaml": "^4.1.0",
+ "jszip": "^3.10.1",
+ "markdown-it": "14.1.0",
+ "pathe": "^1.1.2",
+ "pinia": "^2.1.7",
+ "pinia-plugin-persistedstate": "^4.4.1",
+ "prettier": "^3.6.2",
+ "qrcode.vue": "^3.4.0",
+ "semver": "^7.5.4",
+ "three": "^0.172.0",
+ "vue-confetti-explosion": "^1.0.2",
+ "vue-multiselect": "3.0.0-alpha.2",
+ "vue-typed-virtual-list": "^1.0.10",
+ "vue3-ace-editor": "^2.2.4",
+ "vue3-apexcharts": "^1.5.2",
+ "xss": "^1.0.14"
+ },
+ "web-types": "../../web-types.json",
+ "prettier": "@modrinth/tooling-config/frontend.prettier.config.cjs"
}
diff --git a/apps/frontend/src/app.vue b/apps/frontend/src/app.vue
index ebd9fa56..c79296bc 100644
--- a/apps/frontend/src/app.vue
+++ b/apps/frontend/src/app.vue
@@ -1,11 +1,16 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/apps/frontend/src/assets/styles/components.scss b/apps/frontend/src/assets/styles/components.scss
index f647e7e2..956f922e 100644
--- a/apps/frontend/src/assets/styles/components.scss
+++ b/apps/frontend/src/assets/styles/components.scss
@@ -3,368 +3,368 @@
*/
.known-error .multiselect__tags {
- border-color: var(--color-red) !important;
- background-color: var(--color-warning-bg) !important;
+ border-color: var(--color-red) !important;
+ background-color: var(--color-warning-bg) !important;
- &::placeholder {
- color: var(--color-warning-text);
- }
+ &::placeholder {
+ color: var(--color-warning-text);
+ }
}
.grid-display {
- display: grid;
- grid-gap: var(--spacing-card-md);
- grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
+ display: grid;
+ grid-gap: var(--spacing-card-md);
+ grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
- .grid-display__item {
- display: flex;
- flex-grow: 1;
- flex-direction: column;
- justify-content: flex-start;
- background-color: var(--color-bg);
- border-radius: var(--size-rounded-card);
- padding: var(--spacing-card-lg);
- gap: var(--spacing-card-md);
- outline: 1px solid transparent;
+ .grid-display__item {
+ display: flex;
+ flex-grow: 1;
+ flex-direction: column;
+ justify-content: flex-start;
+ background-color: var(--color-bg);
+ border-radius: var(--size-rounded-card);
+ padding: var(--spacing-card-lg);
+ gap: var(--spacing-card-md);
+ outline: 1px solid transparent;
- .label {
- color: var(--color-heading);
- font-weight: bold;
- font-size: 1rem;
- }
+ .label {
+ color: var(--color-heading);
+ font-weight: bold;
+ font-size: 1rem;
+ }
- .value {
- color: var(--color-text-dark);
- font-weight: bold;
- font-size: 2rem;
- }
+ .value {
+ color: var(--color-text-dark);
+ font-weight: bold;
+ font-size: 2rem;
+ }
- .goto-link {
- margin-top: auto;
- }
- }
+ .goto-link {
+ margin-top: auto;
+ }
+ }
- &.width-12 {
- grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
- }
+ &.width-12 {
+ grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
+ }
- &.width-16 {
- grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
- }
+ &.width-16 {
+ grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
+ }
}
/*
Cards and body styling
*/
.base-card {
- @extend .padding-lg;
+ @extend .padding-lg;
- position: relative;
+ position: relative;
- background-color: var(--color-raised-bg);
- border-radius: var(--size-rounded-card);
+ background-color: var(--color-raised-bg);
+ border-radius: var(--size-rounded-card);
- margin-bottom: var(--spacing-card-md);
- outline: 2px solid transparent;
- outline-offset: -2px;
+ margin-bottom: var(--spacing-card-md);
+ outline: 2px solid transparent;
+ outline-offset: -2px;
- box-shadow: var(--shadow-card);
+ box-shadow: var(--shadow-card);
- .card__overlay {
- position: absolute;
- top: 1rem;
- right: 1rem;
- display: flex;
- flex-direction: column;
- align-items: flex-end;
- grid-gap: 0.5rem;
- z-index: 2;
- }
+ .card__overlay {
+ position: absolute;
+ top: 1rem;
+ right: 1rem;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ grid-gap: 0.5rem;
+ z-index: 2;
+ }
- &.moderation-card {
- background-color: var(--color-warning-banner-bg);
- }
+ &.moderation-card {
+ background-color: var(--color-warning-banner-bg);
+ }
- &.recessed {
- background-color: var(--color-bg);
- box-shadow: none;
- }
+ &.recessed {
+ background-color: var(--color-bg);
+ box-shadow: none;
+ }
}
.universal-labels {
- label,
- .label {
- :where(.label__title) {
- display: block;
- margin-block: var(--spacing-card-md) var(--spacing-card-sm);
+ label,
+ .label {
+ :where(.label__title) {
+ display: block;
+ margin-block: var(--spacing-card-md) var(--spacing-card-sm);
- // Same styling as h3
- color: var(--color-text-dark);
- font-size: 1.17rem;
- font-weight: bold;
+ // Same styling as h3
+ color: var(--color-text-dark);
+ font-size: 1.17rem;
+ font-weight: bold;
- .required {
- color: var(--color-red);
- }
+ .required {
+ color: var(--color-red);
+ }
- &.size-card-header {
- font-size: var(--font-size-xl);
- margin-bottom: 1rem;
- }
- }
+ &.size-card-header {
+ font-size: var(--font-size-xl);
+ margin-bottom: 1rem;
+ }
+ }
- :where(.label__description) {
- display: block;
- margin-block-end: var(--spacing-card-sm);
+ :where(.label__description) {
+ display: block;
+ margin-block-end: var(--spacing-card-sm);
- .label__subdescription {
- display: block;
- margin-block-start: var(--spacing-card-md);
- }
- }
+ .label__subdescription {
+ display: block;
+ margin-block-start: var(--spacing-card-md);
+ }
+ }
- :where(h1, h2, h3, h4) {
- margin-block: 0;
- }
- }
+ :where(h1, h2, h3, h4) {
+ margin-block: 0;
+ }
+ }
}
.padding-lg {
- padding: var(--spacing-card-lg);
+ padding: var(--spacing-card-lg);
}
.padding-bg {
- padding: var(--spacing-card-bg);
+ padding: var(--spacing-card-bg);
}
.padding-md {
- padding: var(--spacing-card-md);
+ padding: var(--spacing-card-md);
}
.padding-sm {
- padding: var(--spacing-card-sm);
+ padding: var(--spacing-card-sm);
}
.padding-0 {
- padding: 0;
+ padding: 0;
}
.padding-block-lg {
- padding-block: var(--spacing-card-lg);
+ padding-block: var(--spacing-card-lg);
}
.padding-block-bg {
- padding-block: var(--spacing-card-bg);
+ padding-block: var(--spacing-card-bg);
}
.padding-block-md {
- padding-block: var(--spacing-card-md);
+ padding-block: var(--spacing-card-md);
}
.padding-block-sm {
- padding-block: var(--spacing-card-sm);
+ padding-block: var(--spacing-card-sm);
}
.padding-block-0 {
- padding-block: 0;
+ padding-block: 0;
}
.padding-inline-lg {
- padding-inline: var(--spacing-card-lg);
+ padding-inline: var(--spacing-card-lg);
}
.padding-inline-bg {
- padding-inline: var(--spacing-card-bg);
+ padding-inline: var(--spacing-card-bg);
}
.padding-inline-md {
- padding-inline: var(--spacing-card-md);
+ padding-inline: var(--spacing-card-md);
}
.padding-inline-sm {
- padding-inline: var(--spacing-card-sm);
+ padding-inline: var(--spacing-card-sm);
}
.padding-inline-0 {
- padding-inline: 0;
+ padding-inline: 0;
}
.universal-body {
- @extend .universal-labels;
+ @extend .universal-labels;
- .multiselect {
- width: 15rem;
- }
+ .multiselect {
+ width: 15rem;
+ }
- > :where(
- input + *,
- .input-group + *,
- .textarea-wrapper + *,
- .chips + *,
- .resizable-textarea-wrapper + *,
- .input-div + *
- ) {
- &:not(:empty) {
- margin-block-start: var(--spacing-card-md);
- }
- }
+ > :where(
+ input + *,
+ .input-group + *,
+ .textarea-wrapper + *,
+ .chips + *,
+ .resizable-textarea-wrapper + *,
+ .input-div + *
+ ) {
+ &:not(:empty) {
+ margin-block-start: var(--spacing-card-md);
+ }
+ }
- :where(button, .button, .iconified-button) {
- width: fit-content;
- }
+ :where(button, .button, .iconified-button) {
+ width: fit-content;
+ }
- .input-group {
- input {
- width: auto;
- flex-basis: 0;
- }
- }
+ .input-group {
+ input {
+ width: auto;
+ flex-basis: 0;
+ }
+ }
- :where(input) {
- box-sizing: border-box;
- max-height: 40px;
+ :where(input) {
+ box-sizing: border-box;
+ max-height: 40px;
- &:not(.stylized-toggle) {
- max-width: 100%;
- }
- }
+ &:not(.stylized-toggle) {
+ max-width: 100%;
+ }
+ }
- :where(.adjacent-input, &.adjacent-input) {
- display: flex;
- flex-direction: row;
- align-items: center;
- flex-wrap: wrap;
- gap: var(--spacing-card-sm);
- margin-bottom: calc(var(--spacing-card-sm) + var(--spacing-card-md));
+ :where(.adjacent-input, &.adjacent-input) {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: var(--spacing-card-sm);
+ margin-bottom: calc(var(--spacing-card-sm) + var(--spacing-card-md));
- .iconified-button,
- .input-group {
- flex-shrink: 0;
- }
+ .iconified-button,
+ .input-group {
+ flex-shrink: 0;
+ }
- input {
- flex-shrink: 1;
- }
+ input {
+ flex-shrink: 1;
+ }
- > :first-child {
- flex-shrink: 2;
- flex-grow: 1;
- flex-basis: min-content;
- }
+ > :first-child {
+ flex-shrink: 2;
+ flex-grow: 1;
+ flex-basis: min-content;
+ }
- label,
- .label {
- .label__title {
- margin-block: 0;
- }
+ label,
+ .label {
+ .label__title {
+ margin-block: 0;
+ }
- .label__description {
- margin-block-end: 0;
- }
+ .label__description {
+ margin-block-end: 0;
+ }
- .label__description:not(:first-child) {
- margin-top: var(--spacing-card-sm);
- }
- }
+ .label__description:not(:first-child) {
+ margin-top: var(--spacing-card-sm);
+ }
+ }
- @media screen and (max-width: 750px) {
- &:not(&.small) {
- flex-direction: column;
- align-items: flex-start;
+ @media screen and (max-width: 750px) {
+ &:not(&.small) {
+ flex-direction: column;
+ align-items: flex-start;
- .stylized-toggle {
- flex-basis: 0;
- }
- }
- }
- }
+ .stylized-toggle {
+ flex-basis: 0;
+ }
+ }
+ }
+ }
- h1 {
- display: flex;
- align-items: center;
- }
+ h1 {
+ display: flex;
+ align-items: center;
+ }
- .markdown-body h1 {
- display: block;
- }
+ .markdown-body h1 {
+ display: block;
+ }
- > :first-child {
- :first-child {
- margin-block-start: 0;
- }
+ > :first-child {
+ :first-child {
+ margin-block-start: 0;
+ }
- margin-block-start: 0;
- }
+ margin-block-start: 0;
+ }
- > :last-child {
- margin-block-end: 0;
- }
+ > :last-child {
+ margin-block-end: 0;
+ }
- :where(.header__row) {
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
- gap: var(--spacing-card-sm);
+ :where(.header__row) {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ gap: var(--spacing-card-sm);
- * {
- flex-shrink: 0;
- }
+ * {
+ flex-shrink: 0;
+ }
- .header__title {
- margin: 0;
- flex-grow: 1;
- }
+ .header__title {
+ margin: 0;
+ flex-grow: 1;
+ }
- &:not(:last-child) {
- margin-bottom: var(--spacing-card-md);
- }
- }
+ &:not(:last-child) {
+ margin-bottom: var(--spacing-card-md);
+ }
+ }
}
.universal-card {
- @extend .base-card;
- @extend .universal-body;
+ @extend .base-card;
+ @extend .universal-body;
}
.universal-modal {
- @extend .universal-body;
+ @extend .universal-body;
- padding: var(--spacing-card-bg);
- display: flex;
- flex-direction: column;
+ padding: var(--spacing-card-bg);
+ display: flex;
+ flex-direction: column;
- > p:first-child {
- margin-top: 0;
- }
+ > p:first-child {
+ margin-top: 0;
+ }
- @media screen and (max-width: 750px) {
- .adjacent-input,
- &.adjacent-input &:not(&.small) {
- flex-direction: row;
- align-items: center;
- }
- }
+ @media screen and (max-width: 750px) {
+ .adjacent-input,
+ &.adjacent-input &:not(&.small) {
+ flex-direction: row;
+ align-items: center;
+ }
+ }
- @media screen and (max-width: calc(600px + 2rem)) {
- .adjacent-input,
- &.adjacent-input &:not(&.small) {
- flex-direction: column;
- align-items: flex-start;
- }
- }
+ @media screen and (max-width: calc(600px + 2rem)) {
+ .adjacent-input,
+ &.adjacent-input &:not(&.small) {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+ }
}
.navigation-card {
- @extend .base-card;
- @extend .padding-inline-lg;
- @extend .padding-block-md;
+ @extend .base-card;
+ @extend .padding-inline-lg;
+ @extend .padding-block-md;
- align-items: center;
- display: flex;
- justify-content: space-between;
- flex-wrap: wrap;
- row-gap: 0.5rem;
- min-height: 3.75rem;
+ align-items: center;
+ display: flex;
+ justify-content: space-between;
+ flex-wrap: wrap;
+ row-gap: 0.5rem;
+ min-height: 3.75rem;
}
/*
@@ -372,921 +372,921 @@
*/
.text-link {
- color: var(--color-link);
+ color: var(--color-link);
- &:focus-visible,
- &:hover {
- color: var(--color-link-hover);
- cursor: pointer;
- text-decoration: underline;
- }
+ &:focus-visible,
+ &:hover {
+ color: var(--color-link-hover);
+ cursor: pointer;
+ text-decoration: underline;
+ }
- &:active {
- color: var(--color-link-active);
- }
+ &:active {
+ color: var(--color-link-active);
+ }
}
.title-link {
- text-decoration: underline;
+ text-decoration: underline;
- &:focus-visible,
- &:hover {
- color: var(--color-heading);
- }
+ &:focus-visible,
+ &:hover {
+ color: var(--color-heading);
+ }
- &:active {
- color: var(--color-text-dark);
- }
+ &:active {
+ color: var(--color-text-dark);
+ }
}
.button-base {
- @extend .button-animation;
- font-weight: 500;
- outline: 2px solid transparent;
+ @extend .button-animation;
+ font-weight: 500;
+ outline: 2px solid transparent;
- &:focus-visible:not(&:disabled),
- &:hover:not(&:disabled) {
- cursor: pointer;
- filter: brightness(0.85);
- }
+ &:focus-visible:not(&:disabled),
+ &:hover:not(&:disabled) {
+ cursor: pointer;
+ filter: brightness(0.85);
+ }
- &:active:not(&:disabled) {
- filter: brightness(0.8);
- }
+ &:active:not(&:disabled) {
+ filter: brightness(0.8);
+ }
- &:disabled,
- &[disabled="true"] {
- cursor: not-allowed;
- filter: grayscale(50%);
- opacity: 0.5;
- box-shadow: none;
- }
+ &:disabled,
+ &[disabled='true'] {
+ cursor: not-allowed;
+ filter: grayscale(50%);
+ opacity: 0.5;
+ box-shadow: none;
+ }
}
:not(tr).button-transparent {
- @extend .button-base;
- background-color: transparent;
- border-radius: var(--size-rounded-sm);
+ @extend .button-base;
+ background-color: transparent;
+ border-radius: var(--size-rounded-sm);
- &:focus-visible:not(&:disabled),
- &:hover:not(&:disabled),
- &:active:not(&:disabled) {
- background-color: var(--color-raised-bg);
- }
+ &:focus-visible:not(&:disabled),
+ &:hover:not(&:disabled),
+ &:active:not(&:disabled) {
+ background-color: var(--color-raised-bg);
+ }
- &.brand-button {
- color: var(--color-brand);
- }
+ &.brand-button {
+ color: var(--color-brand);
+ }
- &.danger-button {
- color: var(--color-red);
- }
+ &.danger-button {
+ color: var(--color-red);
+ }
}
tr.button-transparent {
- @extend .button-animation;
- background-color: transparent;
- border-radius: var(--size-rounded-sm);
+ @extend .button-animation;
+ background-color: transparent;
+ border-radius: var(--size-rounded-sm);
- &:focus-visible:not(&:disabled) > *,
- &:hover:not(&:disabled) > * {
- cursor: pointer;
- filter: brightness(0.85);
- background-color: var(--color-raised-bg);
- }
+ &:focus-visible:not(&:disabled) > *,
+ &:hover:not(&:disabled) > * {
+ cursor: pointer;
+ filter: brightness(0.85);
+ background-color: var(--color-raised-bg);
+ }
- &:active:not(&:disabled) > * {
- filter: brightness(0.8);
- background-color: var(--color-raised-bg);
- }
+ &:active:not(&:disabled) > * {
+ filter: brightness(0.8);
+ background-color: var(--color-raised-bg);
+ }
- &:disabled > *,
- &[disabled="true"] > * {
- cursor: not-allowed;
- filter: grayscale(50%);
- opacity: 0.5;
- box-shadow: none;
- }
+ &:disabled > *,
+ &[disabled='true'] > * {
+ cursor: not-allowed;
+ filter: grayscale(50%);
+ opacity: 0.5;
+ box-shadow: none;
+ }
}
.button-within {
- transition:
- opacity 0.5s ease-in-out,
- filter 0.2s ease-in-out,
- transform 0.05s ease-in-out,
- outline 0.2s ease-in-out;
+ transition:
+ opacity 0.5s ease-in-out,
+ filter 0.2s ease-in-out,
+ transform 0.05s ease-in-out,
+ outline 0.2s ease-in-out;
- &:focus-visible:not(&.disabled),
- &:hover:not(&.disabled) {
- filter: brightness(0.85);
- }
+ &:focus-visible:not(&.disabled),
+ &:hover:not(&.disabled) {
+ filter: brightness(0.85);
+ }
- &:active:not(&.disabled) {
- filter: brightness(0.8);
- }
+ &:active:not(&.disabled) {
+ filter: brightness(0.8);
+ }
- &.disabled {
- cursor: not-allowed;
- filter: grayscale(50%);
- opacity: 0.5;
- box-shadow: none;
+ &.disabled {
+ cursor: not-allowed;
+ filter: grayscale(50%);
+ opacity: 0.5;
+ box-shadow: none;
- &disabled,
- &[disabled="true"] {
- cursor: not-allowed;
- box-shadow: none;
- }
- }
+ &disabled,
+ &[disabled='true'] {
+ cursor: not-allowed;
+ box-shadow: none;
+ }
+ }
}
.button-color-base {
- box-sizing: border-box;
- --text-color: var(--color-button-text);
- --background-color: var(--color-button-bg);
+ box-sizing: border-box;
+ --text-color: var(--color-button-text);
+ --background-color: var(--color-button-bg);
- color: var(--text-color);
- background-color: var(--background-color);
- box-shadow:
- var(--shadow-inset-sm),
- 0 0 0 0 transparent;
- border-radius: var(--size-rounded-sm);
+ color: var(--text-color);
+ background-color: var(--background-color);
+ box-shadow:
+ var(--shadow-inset-sm),
+ 0 0 0 0 transparent;
+ border-radius: var(--size-rounded-sm);
}
.iconified-button {
- @extend .button-base;
- @extend .button-color-base;
+ @extend .button-base;
+ @extend .button-color-base;
- display: flex;
- padding: var(--spacing-card-sm) var(--spacing-card-bg);
- margin: 0;
- font-size: var(--font-size-nm);
- align-items: center;
- cursor: pointer;
- width: fit-content;
- height: fit-content;
- transition:
- opacity 0.5s ease-in-out,
- filter 0.2s ease-in-out,
- scale 0.05s ease-in-out,
- outline 0.2s ease-in-out;
+ display: flex;
+ padding: var(--spacing-card-sm) var(--spacing-card-bg);
+ margin: 0;
+ font-size: var(--font-size-nm);
+ align-items: center;
+ cursor: pointer;
+ width: fit-content;
+ height: fit-content;
+ transition:
+ opacity 0.5s ease-in-out,
+ filter 0.2s ease-in-out,
+ scale 0.05s ease-in-out,
+ outline 0.2s ease-in-out;
- text-decoration: none;
+ text-decoration: none;
- svg {
- width: 1.1rem;
- height: 1.1rem;
- margin-right: 0.5rem;
- }
+ svg {
+ width: 1.1rem;
+ height: 1.1rem;
+ margin-right: 0.5rem;
+ }
- &.icon-only {
- padding: 0 0.5rem;
+ &.icon-only {
+ padding: 0 0.5rem;
- svg {
- margin-right: 0;
- }
- }
+ svg {
+ margin-right: 0;
+ }
+ }
- &.transparent {
- background: none;
- box-shadow: none;
- }
+ &.transparent {
+ background: none;
+ box-shadow: none;
+ }
- &.bold-button {
- font-weight: bold;
- }
+ &.bold-button {
+ font-weight: bold;
+ }
}
.square-button {
- @extend .button-base;
+ @extend .button-base;
- --text-color: var(--color-button-text);
- --background-color: var(--color-button-bg);
+ --text-color: var(--color-button-text);
+ --background-color: var(--color-button-bg);
- display: flex;
- align-items: center;
- justify-content: center;
- height: 2.25rem;
- width: 2.25rem;
- border-radius: var(--size-rounded-sm);
- color: var(--text-color);
- background-color: var(--background-color);
- box-shadow:
- var(--shadow-inset-sm),
- 0 0 0 0 transparent;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 2.25rem;
+ width: 2.25rem;
+ border-radius: var(--size-rounded-sm);
+ color: var(--text-color);
+ background-color: var(--background-color);
+ box-shadow:
+ var(--shadow-inset-sm),
+ 0 0 0 0 transparent;
- svg {
- min-width: 1.25rem;
- max-width: 1.25rem;
- min-height: 1.25rem;
- max-height: 1.25rem;
- }
+ svg {
+ min-width: 1.25rem;
+ max-width: 1.25rem;
+ min-height: 1.25rem;
+ max-height: 1.25rem;
+ }
- flex-shrink: 0;
+ flex-shrink: 0;
}
.header-button {
- @extend .iconified-button;
+ @extend .iconified-button;
- box-sizing: content-box;
- min-height: unset;
- border-radius: var(--size-rounded-max);
- white-space: nowrap;
- padding: 0.5rem 0.75rem;
- max-height: 1.75rem;
+ box-sizing: content-box;
+ min-height: unset;
+ border-radius: var(--size-rounded-max);
+ white-space: nowrap;
+ padding: 0.5rem 0.75rem;
+ max-height: 1.75rem;
- svg {
- vertical-align: middle;
- margin-right: 0.5rem;
- height: 1.25rem;
- width: 1.25rem;
- }
+ svg {
+ vertical-align: middle;
+ margin-right: 0.5rem;
+ height: 1.25rem;
+ width: 1.25rem;
+ }
}
.raised-button {
- --background-color: var(--color-raised-bg);
- box-shadow: var(--shadow-inset-sm), var(--shadow-raised);
+ --background-color: var(--color-raised-bg);
+ box-shadow: var(--shadow-inset-sm), var(--shadow-raised);
}
.danger-button {
- --background-color: var(--color-red);
- --text-color: var(--color-brand-inverted);
+ --background-color: var(--color-red);
+ --text-color: var(--color-brand-inverted);
}
.moderation-button {
- --background-color: var(--color-orange);
- --text-color: var(--color-brand-inverted);
+ --background-color: var(--color-orange);
+ --text-color: var(--color-brand-inverted);
}
.brand-button {
- --background-color: var(--color-brand);
- --text-color: var(--color-brand-inverted);
+ --background-color: var(--color-brand);
+ --text-color: var(--color-brand-inverted);
}
.alt-brand-button {
- --background-color: var(--color-brand-highlight);
- --text-color: var(--color-text);
+ --background-color: var(--color-brand-highlight);
+ --text-color: var(--color-text);
}
.button-group {
- display: flex;
- grid-gap: var(--spacing-card-sm);
- flex-wrap: wrap;
- margin-top: var(--spacing-card-md);
- justify-content: right;
+ display: flex;
+ grid-gap: var(--spacing-card-sm);
+ flex-wrap: wrap;
+ margin-top: var(--spacing-card-md);
+ justify-content: right;
}
.multiselect--above .multiselect__content-wrapper {
- border-top: none !important;
- border-top-left-radius: var(--size-rounded-card) !important;
- border-top-right-radius: var(--size-rounded-card) !important;
+ border-top: none !important;
+ border-top-left-radius: var(--size-rounded-card) !important;
+ border-top-right-radius: var(--size-rounded-card) !important;
}
.known-error .multiselect__tags {
- border-color: var(--color-red) !important;
- background-color: var(--color-warning-bg) !important;
+ border-color: var(--color-red) !important;
+ background-color: var(--color-warning-bg) !important;
- &::placeholder {
- color: var(--color-warning-text);
- }
+ &::placeholder {
+ color: var(--color-warning-text);
+ }
}
.switch {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- -webkit-tap-highlight-color: transparent;
- cursor: pointer;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ -webkit-tap-highlight-color: transparent;
+ cursor: pointer;
- &:focus {
- //outline: 0; Bad for accessibility
- }
+ &:focus {
+ //outline: 0; Bad for accessibility
+ }
}
.stylized-toggle {
- @extend .button-base;
+ @extend .button-base;
- box-sizing: content-box;
- min-height: 32px;
- height: 32px;
- width: 52px;
- max-width: 52px;
- border-radius: var(--size-rounded-max);
- display: inline-block;
- position: relative;
- margin: 0;
- transition: all 0.2s ease;
- background: var(--color-button-bg);
+ box-sizing: content-box;
+ min-height: 32px;
+ height: 32px;
+ width: 52px;
+ max-width: 52px;
+ border-radius: var(--size-rounded-max);
+ display: inline-block;
+ position: relative;
+ margin: 0;
+ transition: all 0.2s ease;
+ background: var(--color-button-bg);
- &:after {
- content: "";
- position: absolute;
- top: 7px;
- left: 7px;
- width: 18px;
- height: 18px;
- border-radius: 50%;
- background: var(--color-toggle-handle);
- transition: all 0.2s cubic-bezier(0.5, 0.1, 0.75, 1.35);
- outline: 2px solid transparent;
+ &:after {
+ content: '';
+ position: absolute;
+ top: 7px;
+ left: 7px;
+ width: 18px;
+ height: 18px;
+ border-radius: 50%;
+ background: var(--color-toggle-handle);
+ transition: all 0.2s cubic-bezier(0.5, 0.1, 0.75, 1.35);
+ outline: 2px solid transparent;
- @media (prefers-reduced-motion) {
- transition: none;
- }
- }
+ @media (prefers-reduced-motion) {
+ transition: none;
+ }
+ }
- &:checked {
- background-color: var(--color-brand);
+ &:checked {
+ background-color: var(--color-brand);
- &:after {
- transform: translatex(20px);
- background: var(--color-brand-inverted);
- }
- }
+ &:after {
+ transform: translatex(20px);
+ background: var(--color-brand-inverted);
+ }
+ }
- &:hover &:focus {
- background: var(--color-button-bg);
- }
+ &:hover &:focus {
+ background: var(--color-button-bg);
+ }
}
.textarea-wrapper {
- display: flex;
- flex-direction: column;
- align-items: stretch;
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
- textarea {
- border-radius: var(--size-rounded-sm);
- flex: 1;
- overflow-y: auto;
- resize: none;
- max-width: 100%;
- }
+ textarea {
+ border-radius: var(--size-rounded-sm);
+ flex: 1;
+ overflow-y: auto;
+ resize: none;
+ max-width: 100%;
+ }
}
.resizable-textarea-wrapper {
- display: block;
+ display: block;
- textarea {
- border-radius: var(--size-rounded-sm);
- min-height: 10rem;
- width: calc(100% - var(--spacing-card-lg) - var(--spacing-card-sm));
- resize: vertical;
- }
+ textarea {
+ border-radius: var(--size-rounded-sm);
+ min-height: 10rem;
+ width: calc(100% - var(--spacing-card-lg) - var(--spacing-card-sm));
+ resize: vertical;
+ }
}
.error {
- display: flex;
- flex-direction: column;
- width: 100%;
- justify-content: center;
- align-items: center;
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ justify-content: center;
+ align-items: center;
- .icon {
- width: 8rem;
- height: 8rem;
- margin: 1.5rem 0;
- }
+ .icon {
+ width: 8rem;
+ height: 8rem;
+ margin: 1.5rem 0;
+ }
- .text {
- margin-bottom: 2rem;
- font-size: 1.25rem;
- text-align: center;
- }
+ .text {
+ margin-bottom: 2rem;
+ font-size: 1.25rem;
+ text-align: center;
+ }
- .link {
- cursor: pointer;
- text-decoration: underline;
- }
+ .link {
+ cursor: pointer;
+ text-decoration: underline;
+ }
}
.card-divider {
- background-color: var(--color-button-bg);
- border: none;
- color: var(--color-button-bg);
- height: 1px;
- margin: var(--spacing-card-bg) 0;
+ background-color: var(--color-button-bg);
+ border: none;
+ color: var(--color-button-bg);
+ height: 1px;
+ margin: var(--spacing-card-bg) 0;
}
.text-input-wrapper.known-error,
input.known-error,
textarea.known-error {
- outline: 2px solid var(--color-red);
- background-color: var(--color-warning-bg) !important;
+ outline: 2px solid var(--color-red);
+ background-color: var(--color-warning-bg) !important;
- &::placeholder {
- color: var(--color-warning-text);
- }
+ &::placeholder {
+ color: var(--color-warning-text);
+ }
}
.known-errors {
- min-height: 0;
- color: var(--color-red);
+ min-height: 0;
+ color: var(--color-red);
- ul {
- margin: 0;
- }
+ ul {
+ margin: 0;
+ }
}
.goto-link {
- display: flex;
- align-items: center;
- gap: 3px;
+ display: flex;
+ align-items: center;
+ gap: 3px;
- color: var(--color-link);
+ color: var(--color-link);
}
.goto-link:hover,
.goto-link:focus-visible {
- color: var(--color-link-hover);
- text-decoration: underline;
+ color: var(--color-link-hover);
+ text-decoration: underline;
}
.goto-link:active {
- color: var(--color-link-active);
+ color: var(--color-link-active);
}
h1 {
- .beta-badge {
- font-size: 0.4em;
- }
+ .beta-badge {
+ font-size: 0.4em;
+ }
}
.beta-badge {
- font-size: 0.7em;
- padding: 0.2rem 0.4rem;
- background-color: transparent;
- box-sizing: border-box;
- border: 2px solid var(--color-text);
- color: var(--color-text);
- border-radius: var(--size-rounded-max);
- margin-left: 0.5rem;
- font-weight: bold;
+ font-size: 0.7em;
+ padding: 0.2rem 0.4rem;
+ background-color: transparent;
+ box-sizing: border-box;
+ border: 2px solid var(--color-text);
+ color: var(--color-text);
+ border-radius: var(--size-rounded-max);
+ margin-left: 0.5rem;
+ font-weight: bold;
}
.router-link-exact-active,
h1,
h2,
h3 {
- .beta-badge {
- background-color: var(--color-button-text-active);
- box-sizing: border-box;
- border-color: transparent;
- color: var(--color-raised-bg);
- }
+ .beta-badge {
+ background-color: var(--color-button-text-active);
+ box-sizing: border-box;
+ border-color: transparent;
+ color: var(--color-raised-bg);
+ }
}
@media (prefers-reduced-motion) {
- .button-animation,
- button {
- transform: none !important;
- }
+ .button-animation,
+ button {
+ transform: none !important;
+ }
}
.push-right:not(.input-group),
.push-right.input-group > :first-child {
- margin-left: auto;
- margin-right: 0;
+ margin-left: auto;
+ margin-right: 0;
}
.full-width-inputs {
- .multiselect,
- input,
- .iconified-input {
- width: 100%;
- flex-basis: 100%;
- }
+ .multiselect,
+ input,
+ .iconified-input {
+ width: 100%;
+ flex-basis: 100%;
+ }
}
input,
button {
- &:disabled {
- cursor: not-allowed !important;
- }
+ &:disabled {
+ cursor: not-allowed !important;
+ }
}
.input-group {
- display: flex;
- flex-direction: row;
- grid-gap: var(--spacing-card-sm);
- flex-wrap: wrap;
- max-width: 100%;
- align-items: center;
+ display: flex;
+ flex-direction: row;
+ grid-gap: var(--spacing-card-sm);
+ flex-wrap: wrap;
+ max-width: 100%;
+ align-items: center;
- .multiselect {
- width: 15rem;
- }
+ .multiselect {
+ width: 15rem;
+ }
- input {
- flex-shrink: 2;
- }
+ input {
+ flex-shrink: 2;
+ }
- &.shrink-first {
- :first-child {
- flex-shrink: 2;
- flex-grow: 1;
- flex-basis: min-content;
- }
+ &.shrink-first {
+ :first-child {
+ flex-shrink: 2;
+ flex-grow: 1;
+ flex-basis: min-content;
+ }
- :not(:first-child) {
- flex-shrink: 1;
- }
- }
+ :not(:first-child) {
+ flex-shrink: 1;
+ }
+ }
- &.right-aligned {
- justify-content: end;
- }
+ &.right-aligned {
+ justify-content: end;
+ }
}
.input-stack {
- display: flex;
- flex-direction: column;
+ display: flex;
+ flex-direction: column;
- > *:not(:last-child) {
- margin-bottom: var(--spacing-card-sm);
- }
+ > *:not(:last-child) {
+ margin-bottom: var(--spacing-card-sm);
+ }
- > .multiselect {
- width: unset;
- height: inherit;
- }
+ > .multiselect {
+ width: unset;
+ height: inherit;
+ }
}
.text-input-wrapper {
- display: flex;
- flex-direction: row;
- flex-wrap: nowrap;
- background: var(--color-button-bg);
- width: fit-content;
- border-radius: var(--size-rounded-sm);
- box-shadow:
- var(--shadow-inset-sm),
- 0 0 0 0 transparent;
- transition: box-shadow 0.1s ease-in-out;
- overflow: hidden;
- max-width: 100%;
- outline: 2px solid transparent;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: nowrap;
+ background: var(--color-button-bg);
+ width: fit-content;
+ border-radius: var(--size-rounded-sm);
+ box-shadow:
+ var(--shadow-inset-sm),
+ 0 0 0 0 transparent;
+ transition: box-shadow 0.1s ease-in-out;
+ overflow: hidden;
+ max-width: 100%;
+ outline: 2px solid transparent;
- .text-input-wrapper__before {
- display: flex;
- color: var(--color-text);
- padding: 0.5rem 0 0.5rem 1rem;
- font-weight: var(--font-weight-medium);
- min-height: 36px;
- box-sizing: border-box;
- width: fit-content;
- align-items: center;
- filter: grayscale(50%);
- opacity: 0.5;
- box-shadow: none;
- flex-shrink: 0;
- }
+ .text-input-wrapper__before {
+ display: flex;
+ color: var(--color-text);
+ padding: 0.5rem 0 0.5rem 1rem;
+ font-weight: var(--font-weight-medium);
+ min-height: 36px;
+ box-sizing: border-box;
+ width: fit-content;
+ align-items: center;
+ filter: grayscale(50%);
+ opacity: 0.5;
+ box-shadow: none;
+ flex-shrink: 0;
+ }
- input,
- textarea {
- border-radius: 0;
- background-color: transparent;
- box-shadow: unset !important;
- padding-left: 0;
- flex-grow: 1;
- outline: none !important;
- }
+ input,
+ textarea {
+ border-radius: 0;
+ background-color: transparent;
+ box-shadow: unset !important;
+ padding-left: 0;
+ flex-grow: 1;
+ outline: none !important;
+ }
- &:focus,
- &:focus-visible,
- &:focus-within {
- box-shadow:
- inset 0 0 0 transparent,
- 0 0 0 0.25rem var(--color-brand-shadow);
- color: var(--color-button-text-active);
- }
+ &:focus,
+ &:focus-visible,
+ &:focus-within {
+ box-shadow:
+ inset 0 0 0 transparent,
+ 0 0 0 0.25rem var(--color-brand-shadow);
+ color: var(--color-button-text-active);
+ }
}
.primary-stat {
- align-items: center;
- display: flex;
- margin-bottom: 0.6rem;
+ align-items: center;
+ display: flex;
+ margin-bottom: 0.6rem;
- .primary-stat__icon {
- height: 1rem;
- width: 1rem;
- }
+ .primary-stat__icon {
+ height: 1rem;
+ width: 1rem;
+ }
- .primary-stat__text {
- margin-left: 0.4rem;
- }
+ .primary-stat__text {
+ margin-left: 0.4rem;
+ }
- .primary-stat__counter {
- font-size: var(--font-size-lg);
- font-weight: bold;
- }
+ .primary-stat__counter {
+ font-size: var(--font-size-lg);
+ font-weight: bold;
+ }
- &.no-margin {
- margin: 0;
- }
+ &.no-margin {
+ margin: 0;
+ }
}
.project-list {
- width: 100%;
- gap: var(--spacing-card-md);
- overflow: hidden;
+ width: 100%;
+ gap: var(--spacing-card-md);
+ overflow: hidden;
- &:not(:first-child) {
- margin-top: var(--spacing-card-md);
- }
+ &:not(:first-child) {
+ margin-top: var(--spacing-card-md);
+ }
- &:not(:empty) {
- margin-bottom: var(--spacing-card-md);
- }
+ &:not(:empty) {
+ margin-bottom: var(--spacing-card-md);
+ }
}
.project-list.display-mode--list {
- display: flex;
- flex-direction: column;
+ display: flex;
+ flex-direction: column;
}
.project-list.display-mode--gallery {
- display: grid;
- grid-template-columns: repeat(2, minmax(0, 1fr));
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
- @media screen and (max-width: 750px) {
- grid-template-columns: repeat(1, minmax(0, 1fr));
- }
+ @media screen and (max-width: 750px) {
+ grid-template-columns: repeat(1, minmax(0, 1fr));
+ }
}
.project-list.display-mode--grid {
- display: grid;
- grid-template-columns: repeat(3, minmax(0, 1fr));
+ display: grid;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
- @media screen and (max-width: 80rem) {
- grid-template-columns: repeat(2, minmax(0, 1fr));
- }
+ @media screen and (max-width: 80rem) {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ }
- @media screen and (max-width: 1024px) {
- grid-template-columns: repeat(3, minmax(0, 1fr));
- }
+ @media screen and (max-width: 1024px) {
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ }
- @media screen and (max-width: 860px) {
- grid-template-columns: repeat(2, minmax(0, 1fr));
- }
+ @media screen and (max-width: 860px) {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ }
- @media screen and (max-width: 550px) {
- display: flex;
- flex-direction: column;
- }
+ @media screen and (max-width: 550px) {
+ display: flex;
+ flex-direction: column;
+ }
}
.wrap-as-needed {
- overflow-wrap: break-word;
- word-wrap: break-word;
- word-break: break-word;
- -webkit-hyphens: auto;
- hyphens: auto;
+ overflow-wrap: break-word;
+ word-wrap: break-word;
+ word-break: break-word;
+ -webkit-hyphens: auto;
+ hyphens: auto;
}
.sr-only {
- position: absolute;
- width: 0;
- height: 0;
- overflow: hidden;
+ position: absolute;
+ width: 0;
+ height: 0;
+ overflow: hidden;
}
.backed-svg {
- --size: 2.5rem;
- border-radius: var(--size-rounded-sm);
- background-color: var(--color-button-bg);
- width: var(--size);
- height: var(--size);
- display: inline-flex;
- justify-content: center;
- align-items: center;
+ --size: 2.5rem;
+ border-radius: var(--size-rounded-sm);
+ background-color: var(--color-button-bg);
+ width: var(--size);
+ height: var(--size);
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
- svg {
- width: calc(0.6 * var(--size));
- height: calc(0.6 * var(--size));
- }
+ svg {
+ width: calc(0.6 * var(--size));
+ height: calc(0.6 * var(--size));
+ }
- &.circle {
- border-radius: 50%;
- }
+ &.circle {
+ border-radius: 50%;
+ }
- &.raised {
- background-color: var(--color-raised-bg);
- }
+ &.raised {
+ background-color: var(--color-raised-bg);
+ }
}
a.iconified-link,
a.iconified-stacked-link {
- display: contents;
+ display: contents;
- .space {
- opacity: 0;
- }
+ .space {
+ opacity: 0;
+ }
- .title {
- font-weight: bold;
- }
+ .title {
+ font-weight: bold;
+ }
- .stacked {
- display: inline-flex;
- flex-direction: column;
- }
+ .stacked {
+ display: inline-flex;
+ flex-direction: column;
+ }
- &:focus-visible .title,
- &:hover .title {
- text-decoration: underline;
- filter: var(--hover-filter);
- }
+ &:focus-visible .title,
+ &:hover .title {
+ text-decoration: underline;
+ filter: var(--hover-filter);
+ }
- &:active .title {
- filter: var(--active-filter);
- }
+ &:active .title {
+ filter: var(--active-filter);
+ }
}
a.iconified-link {
- &:focus-visible span,
- &:hover span {
- text-decoration: underline;
- filter: var(--hover-filter);
- }
+ &:focus-visible span,
+ &:hover span {
+ text-decoration: underline;
+ filter: var(--hover-filter);
+ }
- &:active span {
- filter: var(--active-filter);
- }
+ &:active span {
+ filter: var(--active-filter);
+ }
}
a.subtle-link {
- &:focus-visible,
- &:hover {
- text-decoration: underline;
- filter: var(--hover-filter);
- }
+ &:focus-visible,
+ &:hover {
+ text-decoration: underline;
+ filter: var(--hover-filter);
+ }
- &:active {
- filter: var(--active-filter);
- }
+ &:active {
+ filter: var(--active-filter);
+ }
}
.inline-svg svg,
svg.inline-svg {
- vertical-align: middle;
+ vertical-align: middle;
}
// START STUFF FOR OMORPHIA
.experimental-styles-within {
- .tag-list {
- display: flex;
- flex-wrap: wrap;
- gap: var(--gap-4);
- }
+ .tag-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--gap-4);
+ }
- .tag-list__item {
- background-color: var(--_bg-color, var(--color-button-bg));
- padding: var(--gap-4) var(--gap-8);
- border-radius: var(--radius-max);
- font-weight: var(--weight-bold);
- font-size: var(--text-14);
- display: flex;
- gap: var(--gap-4);
- align-items: center;
- vertical-align: middle;
- color: var(--_color, var(--color-secondary));
+ .tag-list__item {
+ background-color: var(--_bg-color, var(--color-button-bg));
+ padding: var(--gap-4) var(--gap-8);
+ border-radius: var(--radius-max);
+ font-weight: var(--weight-bold);
+ font-size: var(--text-14);
+ display: flex;
+ gap: var(--gap-4);
+ align-items: center;
+ vertical-align: middle;
+ color: var(--_color, var(--color-secondary));
- svg {
- width: var(--icon-14);
- height: var(--icon-14);
- display: flex;
- }
- }
+ svg {
+ width: var(--icon-14);
+ height: var(--icon-14);
+ display: flex;
+ }
+ }
- .status-list {
- display: flex;
- flex-direction: column;
- gap: var(--gap-8);
- padding-left: var(--gap-6);
+ .status-list {
+ display: flex;
+ flex-direction: column;
+ gap: var(--gap-8);
+ padding-left: var(--gap-6);
- color: var(--color-base);
- font-weight: var(--weight-bold);
- }
+ color: var(--color-base);
+ font-weight: var(--weight-bold);
+ }
- .status-list__item {
- display: flex;
- align-items: center;
- gap: var(--gap-4);
+ .status-list__item {
+ display: flex;
+ align-items: center;
+ gap: var(--gap-4);
- svg {
- width: var(--icon-16);
- height: var(--icon-16);
- margin-right: var(--gap-4);
- }
+ svg {
+ width: var(--icon-16);
+ height: var(--icon-16);
+ margin-right: var(--gap-4);
+ }
- span {
- color: var(--color-secondary);
- font-style: italic;
- font-weight: var(--weight-normal);
- }
- }
+ span {
+ color: var(--color-secondary);
+ font-style: italic;
+ font-weight: var(--weight-normal);
+ }
+ }
- .status-list__item--color-green svg {
- color: var(--color-green);
- }
+ .status-list__item--color-green svg {
+ color: var(--color-green);
+ }
- .status-list__item--color-orange svg {
- color: var(--color-orange);
- }
+ .status-list__item--color-orange svg {
+ color: var(--color-orange);
+ }
- .status-list__item--color-red svg {
- color: var(--color-red);
- }
+ .status-list__item--color-red svg {
+ color: var(--color-red);
+ }
- .status-list__item--color-blue svg {
- color: var(--color-blue);
- }
+ .status-list__item--color-blue svg {
+ color: var(--color-blue);
+ }
- .status-list__item--color-purple svg {
- color: var(--color-purple);
- }
+ .status-list__item--color-purple svg {
+ color: var(--color-purple);
+ }
- &.flex-card,
- .flex-card {
- display: flex;
- flex-direction: column;
- gap: var(--gap-12);
- padding: var(--gap-16) var(--gap-24);
+ &.flex-card,
+ .flex-card {
+ display: flex;
+ flex-direction: column;
+ gap: var(--gap-12);
+ padding: var(--gap-16) var(--gap-24);
- h2 {
- font-size: var(--text-18);
- font-weight: var(--weight-extrabold);
- color: var(--color-contrast);
- line-height: initial;
- margin: 0;
- }
+ h2 {
+ font-size: var(--text-18);
+ font-weight: var(--weight-extrabold);
+ color: var(--color-contrast);
+ line-height: initial;
+ margin: 0;
+ }
- h3 {
- font-size: var(--text-16);
- font-weight: var(--weight-bold);
- color: var(--color-base);
- margin: 0;
- }
+ h3 {
+ font-size: var(--text-16);
+ font-weight: var(--weight-bold);
+ color: var(--color-base);
+ margin: 0;
+ }
- > section {
- display: flex;
- flex-direction: column;
- gap: var(--gap-8);
- }
- }
+ > section {
+ display: flex;
+ flex-direction: column;
+ gap: var(--gap-8);
+ }
+ }
- .list-style {
- display: flex;
- flex-direction: column;
- gap: var(--gap-12);
- font-weight: var(--weight-bold);
+ .list-style {
+ display: flex;
+ flex-direction: column;
+ gap: var(--gap-12);
+ font-weight: var(--weight-bold);
- hr {
- width: 100%;
- border-color: var(--color-button-border);
- margin-block: var(--gap-2);
- }
- }
+ hr {
+ width: 100%;
+ border-color: var(--color-button-border);
+ margin-block: var(--gap-2);
+ }
+ }
- .iconified-list-item {
- display: flex;
- gap: var(--gap-8);
- vertical-align: middle;
- align-items: center;
- width: fit-content;
+ .iconified-list-item {
+ display: flex;
+ gap: var(--gap-8);
+ vertical-align: middle;
+ align-items: center;
+ width: fit-content;
- svg {
- width: var(--icon-16);
- height: var(--icon-16);
- }
+ svg {
+ width: var(--icon-16);
+ height: var(--icon-16);
+ }
- > svg:first-child {
- flex-shrink: 0;
- }
- }
+ > svg:first-child {
+ flex-shrink: 0;
+ }
+ }
- .links-list {
- @extend .list-style;
+ .links-list {
+ @extend .list-style;
- > a {
- @extend .iconified-list-item;
+ > a {
+ @extend .iconified-list-item;
- &:hover {
- text-decoration: underline;
- }
- }
- }
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ }
- .details-list {
- @extend .list-style;
- }
+ .details-list {
+ @extend .list-style;
+ }
- .details-list__item {
- @extend .iconified-list-item;
+ .details-list__item {
+ @extend .iconified-list-item;
- .details-list__item__text--style-secondary {
- color: var(--color-secondary);
- font-weight: var(--weight-normal);
- font-size: var(--text-14);
- }
- }
+ .details-list__item__text--style-secondary {
+ color: var(--color-secondary);
+ font-weight: var(--weight-normal);
+ font-size: var(--text-14);
+ }
+ }
}
diff --git a/apps/frontend/src/assets/styles/global.scss b/apps/frontend/src/assets/styles/global.scss
index cefb9460..aa7b2406 100644
--- a/apps/frontend/src/assets/styles/global.scss
+++ b/apps/frontend/src/assets/styles/global.scss
@@ -1,558 +1,558 @@
html {
- @extend .dark-mode;
- --dark-color-text: #b0bac5;
- --dark-color-text-dark: #ecf9fb;
- --color-text-secondary: var(--color-icon);
+ @extend .dark-mode;
+ --dark-color-text: #b0bac5;
+ --dark-color-text-dark: #ecf9fb;
+ --color-text-secondary: var(--color-icon);
}
// TO BE MOVED TO OMORPHIA
:root {
- --gap-2: 0.125rem;
- --gap-4: calc(2 * var(--gap-2));
- --gap-6: calc(3 * var(--gap-2));
- --gap-8: calc(2 * var(--gap-4));
- --gap-12: calc(3 * var(--gap-4));
- --gap-16: calc(2 * var(--gap-8));
- --gap-24: calc(3 * var(--gap-8));
+ --gap-2: 0.125rem;
+ --gap-4: calc(2 * var(--gap-2));
+ --gap-6: calc(3 * var(--gap-2));
+ --gap-8: calc(2 * var(--gap-4));
+ --gap-12: calc(3 * var(--gap-4));
+ --gap-16: calc(2 * var(--gap-8));
+ --gap-24: calc(3 * var(--gap-8));
- --radius-card: 1rem;
- --radius-max: 999999999px;
+ --radius-card: 1rem;
+ --radius-max: 999999999px;
- --radius-btn: 0.75rem;
- --radius-btn-large: 1rem;
- --radius-btn-circle: var(--radius-max);
+ --radius-btn: 0.75rem;
+ --radius-btn-large: 1rem;
+ --radius-btn-circle: var(--radius-max);
- --text-14: 0.875rem;
- --text-16: 1rem;
- --text-18: 1.125rem;
- --text-24: 1.5rem;
- --text-32: 2rem;
+ --text-14: 0.875rem;
+ --text-16: 1rem;
+ --text-18: 1.125rem;
+ --text-24: 1.5rem;
+ --text-32: 2rem;
- --weight-normal: 500; // used for general body text
- --weight-bold: 600; // used for text needing extra emphasis
- --weight-extrabold: 800; // used for main titles and headings
+ --weight-normal: 500; // used for general body text
+ --weight-bold: 600; // used for text needing extra emphasis
+ --weight-extrabold: 800; // used for main titles and headings
- --icon-14: 0.875rem; // used for icons inside a small container alongside a label
- --icon-16: 1rem; // used for normal-sized icons alongside a label
- --icon-20: 1.25rem; // used for icons in normal sized buttons
- --icon-24: 1.5rem; // used for icons that are used as a primary label or in large buttons
- --icon-32: 2rem;
+ --icon-14: 0.875rem; // used for icons inside a small container alongside a label
+ --icon-16: 1rem; // used for normal-sized icons alongside a label
+ --icon-20: 1.25rem; // used for icons in normal sized buttons
+ --icon-24: 1.5rem; // used for icons that are used as a primary label or in large buttons
+ --icon-32: 2rem;
- interpolate-size: allow-keywords;
+ interpolate-size: allow-keywords;
}
.light-mode {
- --color-secondary: #6b7280;
- --color-icon: var(--color-secondary);
- --color-text: hsl(221, 39%, 11%);
- --color-text-inactive: hsl(215, 14%, 34%);
- --color-text-dark: #1a202c;
- --color-heading: #2c313d;
- --color-bg: #e5e7eb;
- --color-raised-bg: #ffffff;
- --color-divider: hsl(220, 13%, 91%);
- --color-divider-dark: #c8cdd3;
+ --color-secondary: #6b7280;
+ --color-icon: var(--color-secondary);
+ --color-text: hsl(221, 39%, 11%);
+ --color-text-inactive: hsl(215, 14%, 34%);
+ --color-text-dark: #1a202c;
+ --color-heading: #2c313d;
+ --color-bg: #e5e7eb;
+ --color-raised-bg: #ffffff;
+ --color-divider: hsl(220, 13%, 91%);
+ --color-divider-dark: #c8cdd3;
- --color-text-inverted: var(--color-bg);
- --color-bg-inverted: var(--color-text);
+ --color-text-inverted: var(--color-bg);
+ --color-bg-inverted: var(--color-text);
- --color-brand: var(--color-green);
- --color-brand-highlight: rgba(0, 175, 92, 0.25);
- --color-brand-shadow: rgba(0, 175, 92, 0.7);
- --color-brand-inverted: #ffffff;
+ --color-brand: var(--color-green);
+ --color-brand-highlight: rgba(0, 175, 92, 0.25);
+ --color-brand-shadow: rgba(0, 175, 92, 0.7);
+ --color-brand-inverted: #ffffff;
- --tab-underline-hovered: #e2e8f0;
+ --tab-underline-hovered: #e2e8f0;
- --color-button-bg: hsl(220, 13%, 91%);
- --color-button-text: var(--color-text-dark);
- --color-button-bg-hover: #d9dce0;
- --color-button-text-hover: #1b1e24;
- --color-button-bg-active: #c3c6cb;
- --color-button-text-active: var(--color-button-text-hover);
+ --color-button-bg: hsl(220, 13%, 91%);
+ --color-button-text: var(--color-text-dark);
+ --color-button-bg-hover: #d9dce0;
+ --color-button-text-hover: #1b1e24;
+ --color-button-bg-active: #c3c6cb;
+ --color-button-text-active: var(--color-button-text-hover);
- --color-toggle-handle: var(--color-icon);
+ --color-toggle-handle: var(--color-icon);
- --color-dropdown-bg: var(--color-button-bg);
- --color-dropdown-text: var(--color-button-text);
+ --color-dropdown-bg: var(--color-button-bg);
+ --color-dropdown-text: var(--color-button-text);
- --color-code-bg: var(--color-bg);
- --color-code-text: var(--color-text-dark);
+ --color-code-bg: var(--color-bg);
+ --color-code-text: var(--color-text-dark);
- --color-kbd-shadow: rgba(0, 0, 0, 0.25);
+ --color-kbd-shadow: rgba(0, 0, 0, 0.25);
- --color-ad: #d6e6f9;
- --color-ad-raised: #b1c8e4;
- --color-ad-contrast: var(--color-text);
- --color-ad-highlight: #088cdb;
+ --color-ad: #d6e6f9;
+ --color-ad-raised: #b1c8e4;
+ --color-ad-contrast: var(--color-text);
+ --color-ad-highlight: #088cdb;
- --color-grey-link: var(--color-text);
- --color-grey-link-hover: var(--color-heading);
- --color-grey-link-active: var(--color-text-dark);
- --color-link: #0d60bb;
- --color-link-hover: #1a76e7;
- --color-link-active: #146fd7;
+ --color-grey-link: var(--color-text);
+ --color-grey-link-hover: var(--color-heading);
+ --color-grey-link-active: var(--color-text-dark);
+ --color-link: #0d60bb;
+ --color-link-hover: #1a76e7;
+ --color-link-active: #146fd7;
- --color-warning-bg: hsl(355, 70%, 88%);
- --color-warning-text: hsl(342, 70%, 35%);
+ --color-warning-bg: hsl(355, 70%, 88%);
+ --color-warning-text: hsl(342, 70%, 35%);
- --color-warning-banner-text: hsl(0, 11%, 16%);
- --color-warning-banner-bg: hsl(0, 100%, 95%);
- --color-warning-banner-side: hsl(357, 78%, 40%);
+ --color-warning-banner-text: hsl(0, 11%, 16%);
+ --color-warning-banner-bg: hsl(0, 100%, 95%);
+ --color-warning-banner-side: hsl(357, 78%, 40%);
- --color-info-banner-text: var(--color-text);
- --color-info-banner-bg: var(--color-ad);
- --color-info-banner-side: var(--color-blue);
+ --color-info-banner-text: var(--color-text);
+ --color-info-banner-bg: var(--color-ad);
+ --color-info-banner-side: var(--color-blue);
- --color-block-quote: var(--color-tooltip-bg);
- --color-header-underline: var(--color-divider-dark);
- --color-hr: var(--color-text);
+ --color-block-quote: var(--color-tooltip-bg);
+ --color-header-underline: var(--color-divider-dark);
+ --color-hr: var(--color-text);
- --color-table-border: #dfe2e5;
- --color-table-alternate-row: #f2f4f7;
+ --color-table-border: #dfe2e5;
+ --color-table-alternate-row: #f2f4f7;
- --shadow-inset-lg: inset 0px -2px 2px hsla(221, 39%, 11%, 0.1);
- --shadow-inset: inset 0px -2px 2px hsla(221, 39%, 11%, 0.05);
- --shadow-inset-sm: inset 0px -1px 2px hsla(221, 39%, 11%, 0.15);
+ --shadow-inset-lg: inset 0px -2px 2px hsla(221, 39%, 11%, 0.1);
+ --shadow-inset: inset 0px -2px 2px hsla(221, 39%, 11%, 0.05);
+ --shadow-inset-sm: inset 0px -1px 2px hsla(221, 39%, 11%, 0.15);
- --shadow-raised-lg: 0px 2px 4px hsla(221, 39%, 11%, 0.2);
- --shadow-raised:
- 0.3px 0.5px 0.6px hsl(var(--shadow-color) / 0.15),
- 1px 2px 2.2px -1.7px hsl(var(--shadow-color) / 0.12),
- 4.4px 8.8px 9.7px -3.4px hsl(var(--shadow-color) / 0.09);
- --shadow-floating:
- hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px,
- hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px, hsla(0, 0%, 0%, 0.1) 0px 2px 4px -1px;
+ --shadow-raised-lg: 0px 2px 4px hsla(221, 39%, 11%, 0.2);
+ --shadow-raised:
+ 0.3px 0.5px 0.6px hsl(var(--shadow-color) / 0.15),
+ 1px 2px 2.2px -1.7px hsl(var(--shadow-color) / 0.12),
+ 4.4px 8.8px 9.7px -3.4px hsl(var(--shadow-color) / 0.09);
+ --shadow-floating:
+ hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px,
+ hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px, hsla(0, 0%, 0%, 0.1) 0px 2px 4px -1px;
- --shadow-card: rgba(50, 50, 100, 0.1) 0px 2px 4px 0px;
+ --shadow-card: rgba(50, 50, 100, 0.1) 0px 2px 4px 0px;
- --landing-maze-bg: url("https://cdn.modrinth.com/landing-new/landing-light.webp");
- --landing-maze-gradient-bg: url("https://cdn.modrinth.com/landing-new/landing-lower-light.webp");
- --landing-maze-outer-bg: linear-gradient(180deg, #f0f0f0 0%, #ffffff 100%);
+ --landing-maze-bg: url('https://cdn.modrinth.com/landing-new/landing-light.webp');
+ --landing-maze-gradient-bg: url('https://cdn.modrinth.com/landing-new/landing-lower-light.webp');
+ --landing-maze-outer-bg: linear-gradient(180deg, #f0f0f0 0%, #ffffff 100%);
- --landing-color-heading: #000;
- --landing-color-subheading: #3a3f45;
+ --landing-color-heading: #000;
+ --landing-color-subheading: #3a3f45;
- --landing-transition-gradient-start: rgba(255, 255, 255, 0);
- --landing-transition-gradient-end: #ffffff;
- --landing-hover-card-gradient: radial-gradient(
- 50% 50% at 50% 50%,
- #fff 0%,
- rgba(204, 204, 204, 0.77) 100%
- );
- --landing-border-gradient: linear-gradient(
- to bottom right,
- rgba(129, 137, 175, 0.75) 0%,
- rgba(66, 71, 97, 0.34) 100%
- );
- --landing-border-color: rgba(129, 137, 175, 0.55);
- --landing-creator-gradient: linear-gradient(180deg, #f8f8f8 0%, #f8f8f8 63.19%);
+ --landing-transition-gradient-start: rgba(255, 255, 255, 0);
+ --landing-transition-gradient-end: #ffffff;
+ --landing-hover-card-gradient: radial-gradient(
+ 50% 50% at 50% 50%,
+ #fff 0%,
+ rgba(204, 204, 204, 0.77) 100%
+ );
+ --landing-border-gradient: linear-gradient(
+ to bottom right,
+ rgba(129, 137, 175, 0.75) 0%,
+ rgba(66, 71, 97, 0.34) 100%
+ );
+ --landing-border-color: rgba(129, 137, 175, 0.55);
+ --landing-creator-gradient: linear-gradient(180deg, #f8f8f8 0%, #f8f8f8 63.19%);
- --landing-blob-gradient: radial-gradient(
- 50% 50% at 50% 50%,
- rgba(255, 255, 255, 0.35) 0%,
- rgba(255, 255, 255, 0.2695) 100%
- );
- --landing-blob-shadow:
- 2px 2px 12px rgba(0, 0, 0, 0.16), inset 2px 2px 64px rgba(255, 255, 255, 0.45);
+ --landing-blob-gradient: radial-gradient(
+ 50% 50% at 50% 50%,
+ rgba(255, 255, 255, 0.35) 0%,
+ rgba(255, 255, 255, 0.2695) 100%
+ );
+ --landing-blob-shadow:
+ 2px 2px 12px rgba(0, 0, 0, 0.16), inset 2px 2px 64px rgba(255, 255, 255, 0.45);
- --landing-card-bg: rgba(255, 255, 255, 0.8);
- --landing-card-shadow: 2px 2px 12px rgba(0, 0, 0, 0.16);
+ --landing-card-bg: rgba(255, 255, 255, 0.8);
+ --landing-card-shadow: 2px 2px 12px rgba(0, 0, 0, 0.16);
- --landing-blue-label: #0098ba;
- --landing-blue-label-bg: rgba(0, 177, 216, 0.15);
- --landing-green-label: #00a936;
- --landing-green-label-bg: rgba(0, 216, 69, 0.15);
+ --landing-blue-label: #0098ba;
+ --landing-blue-label-bg: rgba(0, 177, 216, 0.15);
+ --landing-green-label: #00a936;
+ --landing-green-label-bg: rgba(0, 216, 69, 0.15);
- --landing-raw-bg: #fff;
+ --landing-raw-bg: #fff;
- --banner-error-bg: #fee2e2;
- --banner-error-text: #991b1b;
- --banner-error-border: #ef4444;
+ --banner-error-bg: #fee2e2;
+ --banner-error-text: #991b1b;
+ --banner-error-border: #ef4444;
- --banner-warning-bg: #ffedd5;
- --banner-warning-text: #713f12;
- --banner-warning-border: #f97316;
+ --banner-warning-bg: #ffedd5;
+ --banner-warning-text: #713f12;
+ --banner-warning-border: #f97316;
- --banner-info-bg: #dbeafe;
- --banner-info-text: #1e3a8a;
- --banner-info-border: #3b82f6;
+ --banner-info-bg: #dbeafe;
+ --banner-info-text: #1e3a8a;
+ --banner-info-border: #3b82f6;
}
.dark,
.dark-mode,
.oled-mode,
.retro-mode {
- --color-secondary: #96a2b0;
- --color-icon: var(--color-secondary);
- --color-text: var(--dark-color-text);
- --color-text-inactive: #929aa3;
- --color-text-dark: var(--dark-color-text-dark);
- --color-heading: #c4cfdd;
- --color-bg: #16181c;
- --color-raised-bg: #26292f;
- --color-divider: #474b54;
- --color-divider-dark: #646c75;
+ --color-secondary: #96a2b0;
+ --color-icon: var(--color-secondary);
+ --color-text: var(--dark-color-text);
+ --color-text-inactive: #929aa3;
+ --color-text-dark: var(--dark-color-text-dark);
+ --color-heading: #c4cfdd;
+ --color-bg: #16181c;
+ --color-raised-bg: #26292f;
+ --color-divider: #474b54;
+ --color-divider-dark: #646c75;
- --color-text-inverted: var(--color-bg);
- --color-bg-inverted: var(--color-text);
+ --color-text-inverted: var(--color-bg);
+ --color-bg-inverted: var(--color-text);
- --color-brand: var(--color-green);
- --color-brand-highlight: rgba(27, 217, 106, 0.25);
- --color-brand-shadow: rgba(27, 217, 106, 0.7);
- --color-brand-inverted: #000;
+ --color-brand: var(--color-green);
+ --color-brand-highlight: rgba(27, 217, 106, 0.25);
+ --color-brand-shadow: rgba(27, 217, 106, 0.7);
+ --color-brand-inverted: #000;
- --tab-underline-hovered: #414146;
+ --tab-underline-hovered: #414146;
- --color-button-bg: hsl(222, 13%, 30%);
- --color-button-text: var(--color-text);
- --color-button-bg-hover: #494f58;
- --color-button-text-hover: #ffffff;
- --color-button-bg-active: #616570;
- --color-button-text-active: var(--color-button-text-hover);
+ --color-button-bg: hsl(222, 13%, 30%);
+ --color-button-text: var(--color-text);
+ --color-button-bg-hover: #494f58;
+ --color-button-text-hover: #ffffff;
+ --color-button-bg-active: #616570;
+ --color-button-text-active: var(--color-button-text-hover);
- --color-toggle-handle: var(--color-button-text);
+ --color-toggle-handle: var(--color-button-text);
- --color-dropdown-bg: var(--color-button-bg);
- --color-dropdown-text: var(--color-button-text);
+ --color-dropdown-bg: var(--color-button-bg);
+ --color-dropdown-text: var(--color-button-text);
- --color-code-bg: var(--color-button-bg);
- --color-code-text: var(--color-text-dark);
+ --color-code-bg: var(--color-button-bg);
+ --color-code-text: var(--color-text-dark);
- --color-kbd-shadow: rgba(0, 0, 0, 0.35);
+ --color-kbd-shadow: rgba(0, 0, 0, 0.35);
- --color-ad: #1f324a;
- --color-ad-raised: #2e4057;
- --color-ad-contrast: var(--color-text);
- --color-ad-highlight: #088cdb;
+ --color-ad: #1f324a;
+ --color-ad-raised: #2e4057;
+ --color-ad-contrast: var(--color-text);
+ --color-ad-highlight: #088cdb;
- --color-link: #74b6f3;
- --color-link-hover: #92c0f5;
- --color-link-active: #b5d5fd;
+ --color-link: #74b6f3;
+ --color-link-hover: #92c0f5;
+ --color-link-active: #b5d5fd;
- --color-warning-bg: hsl(355, 70%, 20%);
- --color-warning-text: hsl(342, 70%, 75%);
+ --color-warning-bg: hsl(355, 70%, 20%);
+ --color-warning-text: hsl(342, 70%, 75%);
- --color-warning-banner-text: hsl(0, 100%, 96%);
- --color-warning-banner-bg: hsl(356, 18%, 18%);
- --color-warning-banner-side: hsl(357, 78%, 40%);
+ --color-warning-banner-text: hsl(0, 100%, 96%);
+ --color-warning-banner-bg: hsl(356, 18%, 18%);
+ --color-warning-banner-side: hsl(357, 78%, 40%);
- --color-info-banner-text: var(--color-text);
- --color-info-banner-bg: var(--color-ad);
- --color-info-banner-side: var(--color-blue);
+ --color-info-banner-text: var(--color-text);
+ --color-info-banner-bg: var(--color-ad);
+ --color-info-banner-side: var(--color-blue);
- --color-block-quote: var(--color-code-bg);
- --color-header-underline: var(--color-divider-dark);
- --color-hr: var(--color-text);
+ --color-block-quote: var(--color-code-bg);
+ --color-header-underline: var(--color-divider-dark);
+ --color-hr: var(--color-text);
- --color-table-border: #4f5864;
- --color-table-alternate-row: #202228;
+ --color-table-border: #4f5864;
+ --color-table-alternate-row: #202228;
- --shadow-inset-lg: inset 0px -2px 2px hsla(221, 39%, 11%, 0.1);
- --shadow-inset: inset 0px -2px 2px hsla(221, 39%, 11%, 0.05);
- --shadow-inset-sm: inset 0px -1px 1px hsla(221, 39%, 11%, 0.25);
+ --shadow-inset-lg: inset 0px -2px 2px hsla(221, 39%, 11%, 0.1);
+ --shadow-inset: inset 0px -2px 2px hsla(221, 39%, 11%, 0.05);
+ --shadow-inset-sm: inset 0px -1px 1px hsla(221, 39%, 11%, 0.25);
- --shadow-raised-lg: 0px 2px 4px hsla(221, 39%, 11%, 0.2);
- --shadow-raised: 0px -2px 4px hsla(221, 39%, 11%, 0.1);
- --shadow-floating:
- hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px,
- hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;
+ --shadow-raised-lg: 0px 2px 4px hsla(221, 39%, 11%, 0.2);
+ --shadow-raised: 0px -2px 4px hsla(221, 39%, 11%, 0.1);
+ --shadow-floating:
+ hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px,
+ hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;
- --shadow-card: rgba(0, 0, 0, 0.25) 0px 2px 4px 0px;
+ --shadow-card: rgba(0, 0, 0, 0.25) 0px 2px 4px 0px;
- --landing-maze-bg: url("https://cdn.modrinth.com/landing-new/landing.webp");
- --landing-maze-gradient-bg:
- linear-gradient(0deg, #31375f 0%, rgba(8, 14, 55, 0) 100%),
- url("https://cdn.modrinth.com/landing-new/landing-lower.webp");
- --landing-maze-outer-bg: linear-gradient(180deg, #06060d 0%, #000000 100%);
+ --landing-maze-bg: url('https://cdn.modrinth.com/landing-new/landing.webp');
+ --landing-maze-gradient-bg:
+ linear-gradient(0deg, #31375f 0%, rgba(8, 14, 55, 0) 100%),
+ url('https://cdn.modrinth.com/landing-new/landing-lower.webp');
+ --landing-maze-outer-bg: linear-gradient(180deg, #06060d 0%, #000000 100%);
- --landing-color-heading: #fff;
- --landing-color-subheading: #afb6be;
+ --landing-color-heading: #fff;
+ --landing-color-subheading: #afb6be;
- --landing-transition-gradient-start: rgba(14, 16, 32, 0);
- --landing-transition-gradient-end: #060a1c;
- --landing-hover-card-gradient: radial-gradient(
- 50% 50% at 50% 50%,
- #2c304f 0%,
- rgba(32, 35, 50, 0.77) 100%
- );
- --landing-border-gradient: linear-gradient(
- to bottom right,
- rgba(168, 177, 221, 0.75) 0%,
- rgba(168, 177, 221, 0.18) 100%
- );
- --landing-border-color: rgba(168, 177, 221, 0.55);
- --landing-creator-gradient: linear-gradient(180deg, #000000 0%, #0e101d 100%);
+ --landing-transition-gradient-start: rgba(14, 16, 32, 0);
+ --landing-transition-gradient-end: #060a1c;
+ --landing-hover-card-gradient: radial-gradient(
+ 50% 50% at 50% 50%,
+ #2c304f 0%,
+ rgba(32, 35, 50, 0.77) 100%
+ );
+ --landing-border-gradient: linear-gradient(
+ to bottom right,
+ rgba(168, 177, 221, 0.75) 0%,
+ rgba(168, 177, 221, 0.18) 100%
+ );
+ --landing-border-color: rgba(168, 177, 221, 0.55);
+ --landing-creator-gradient: linear-gradient(180deg, #000000 0%, #0e101d 100%);
- --landing-blob-gradient: radial-gradient(
- 50% 50% at 50% 50%,
- rgba(44, 48, 79, 0.35) 0%,
- rgba(32, 35, 50, 0.2695) 100%
- );
- --landing-blob-shadow:
- 2px 2px 12px rgba(0, 0, 0, 0.16), inset 2px 2px 64px rgba(57, 61, 94, 0.45);
+ --landing-blob-gradient: radial-gradient(
+ 50% 50% at 50% 50%,
+ rgba(44, 48, 79, 0.35) 0%,
+ rgba(32, 35, 50, 0.2695) 100%
+ );
+ --landing-blob-shadow:
+ 2px 2px 12px rgba(0, 0, 0, 0.16), inset 2px 2px 64px rgba(57, 61, 94, 0.45);
- --landing-card-bg: rgba(59, 63, 85, 0.15);
- --landing-card-shadow: 2px 2px 12px rgba(0, 0, 0, 0.16);
+ --landing-card-bg: rgba(59, 63, 85, 0.15);
+ --landing-card-shadow: 2px 2px 12px rgba(0, 0, 0, 0.16);
- --landing-blue-label: #10c0e7;
- --landing-blue-label-bg: rgba(0, 177, 216, 0.15);
- --landing-green-label: #00d845;
- --landing-green-label-bg: rgba(0, 216, 69, 0.15);
+ --landing-blue-label: #10c0e7;
+ --landing-blue-label-bg: rgba(0, 177, 216, 0.15);
+ --landing-green-label: #00d845;
+ --landing-green-label-bg: rgba(0, 216, 69, 0.15);
- --landing-raw-bg: #000;
+ --landing-raw-bg: #000;
- --hover-filter: brightness(120%);
- --active-filter: brightness(140%);
+ --hover-filter: brightness(120%);
+ --active-filter: brightness(140%);
- --banner-error-bg: #4c1515;
- --banner-error-text: #fee2e2;
- --banner-error-border: #7f1d1d;
+ --banner-error-bg: #4c1515;
+ --banner-error-text: #fee2e2;
+ --banner-error-border: #7f1d1d;
- --banner-warning-bg: #4a2a0a;
- --banner-warning-text: #ffe6c0;
- --banner-warning-border: #b54708;
+ --banner-warning-bg: #4a2a0a;
+ --banner-warning-text: #ffe6c0;
+ --banner-warning-border: #b54708;
- --banner-info-bg: #1e2a44;
- --banner-info-text: #dbeafe;
- --banner-info-border: #2563eb;
+ --banner-info-bg: #1e2a44;
+ --banner-info-text: #dbeafe;
+ --banner-info-border: #2563eb;
}
.oled-mode {
- --color-bg: #000000;
- --color-raised-bg: #101013;
+ --color-bg: #000000;
+ --color-raised-bg: #101013;
- --color-button-bg: #222329;
- --color-button-bg-hover: #2d2d32;
- --color-button-bg-active: #3c3c40;
- --color-table-alternate-row: #19191c;
- --color-divider-dark: #2c3134;
+ --color-button-bg: #222329;
+ --color-button-bg-hover: #2d2d32;
+ --color-button-bg-active: #3c3c40;
+ --color-table-alternate-row: #19191c;
+ --color-divider-dark: #2c3134;
- --color-warning-banner-bg: hsl(0, 45%, 11%);
- --color-ad: #0d1828;
+ --color-warning-banner-bg: hsl(0, 45%, 11%);
+ --color-ad: #0d1828;
}
.retro-mode {
- --color-bg: #191917;
- --color-raised-bg: #1d1e1b;
- --color-button-bg: #3a3b38;
- --color-base: #c3c4b3;
- --color-secondary: #777a74;
- --color-contrast: #e6e2d1;
+ --color-bg: #191917;
+ --color-raised-bg: #1d1e1b;
+ --color-button-bg: #3a3b38;
+ --color-base: #c3c4b3;
+ --color-secondary: #777a74;
+ --color-contrast: #e6e2d1;
- --color-brand: #4d9227;
- --color-brand-highlight: #25421e;
- --color-ad: var(--color-brand-highlight);
- --color-ad-raised: var(--color-brand);
- --color-ad-contrast: black;
- --color-ad-highlight: var(--color-brand);
+ --color-brand: #4d9227;
+ --color-brand-highlight: #25421e;
+ --color-ad: var(--color-brand-highlight);
+ --color-ad-raised: var(--color-brand);
+ --color-ad-contrast: black;
+ --color-ad-highlight: var(--color-brand);
- --color-red: rgb(232, 32, 13);
- --color-orange: rgb(232, 141, 13);
- --color-green: rgb(60, 219, 54);
- --color-blue: rgb(9, 159, 239);
- --color-purple: rgb(139, 129, 230);
- --color-gray: #718096;
+ --color-red: rgb(232, 32, 13);
+ --color-orange: rgb(232, 141, 13);
+ --color-green: rgb(60, 219, 54);
+ --color-blue: rgb(9, 159, 239);
+ --color-purple: rgb(139, 129, 230);
+ --color-gray: #718096;
- --color-red-highlight: rgba(232, 32, 13, 0.25);
- --color-orange-highlight: rgba(232, 141, 13, 0.25);
- --color-green-highlight: rgba(60, 219, 54, 0.25);
- --color-blue-highlight: rgba(9, 159, 239, 0.25);
- --color-purple-highlight: rgba(139, 129, 230, 0.25);
- --color-gray-highlight: rgba(113, 128, 150, 0.25);
+ --color-red-highlight: rgba(232, 32, 13, 0.25);
+ --color-orange-highlight: rgba(232, 141, 13, 0.25);
+ --color-green-highlight: rgba(60, 219, 54, 0.25);
+ --color-blue-highlight: rgba(9, 159, 239, 0.25);
+ --color-purple-highlight: rgba(139, 129, 230, 0.25);
+ --color-gray-highlight: rgba(113, 128, 150, 0.25);
}
body {
- // Defaults
- background-color: var(--color-bg);
- color: var(--color-text);
- --font-standard:
- Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto, Cantarell,
- Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
- --mono-font: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
- font-family: var(--font-standard);
- font-size: 16px;
- font-weight: var(--font-weight-regular);
- margin: 0;
- padding: 0;
+ // Defaults
+ background-color: var(--color-bg);
+ color: var(--color-text);
+ --font-standard:
+ Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto, Cantarell,
+ Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ --mono-font: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
+ font-family: var(--font-standard);
+ font-size: 16px;
+ font-weight: var(--font-weight-regular);
+ margin: 0;
+ padding: 0;
- // Rounding sizes
- --size-rounded-xs: 0.5rem;
- --size-rounded-sm: 0.75rem;
- --size-rounded-md: 1rem;
- --size-rounded-lg: 1.25rem;
+ // Rounding sizes
+ --size-rounded-xs: 0.5rem;
+ --size-rounded-sm: 0.75rem;
+ --size-rounded-md: 1rem;
+ --size-rounded-lg: 1.25rem;
- --size-rounded-max: 999999999px;
- --size-rounded-card: 1rem;
- --size-rounded-icon: 1rem;
- --size-rounded-control: 0.25rem;
- --size-rounded-tooltip: 0.25rem;
+ --size-rounded-max: 999999999px;
+ --size-rounded-card: 1rem;
+ --size-rounded-icon: 1rem;
+ --size-rounded-control: 0.25rem;
+ --size-rounded-tooltip: 0.25rem;
- --size-navbar-height: 3.5rem;
- --size-mobile-navbar-height: 3.5rem;
- --size-mobile-navbar-height-expanded: 13.75rem;
+ --size-navbar-height: 3.5rem;
+ --size-mobile-navbar-height: 3.5rem;
+ --size-mobile-navbar-height-expanded: 13.75rem;
- --spacing-card-lg: 1.5rem;
- --spacing-card-bg: 1rem;
- --spacing-card-md: 0.75rem;
- --spacing-card-sm: 0.5rem;
- --spacing-card-xs: 0.25rem;
+ --spacing-card-lg: 1.5rem;
+ --spacing-card-bg: 1rem;
+ --spacing-card-md: 0.75rem;
+ --spacing-card-sm: 0.5rem;
+ --spacing-card-xs: 0.25rem;
- // Font Sizes
- --font-size-xxs: 0.625rem; //10px
- --font-size-xs: 0.75rem; //12px
- --font-size-sm: 0.875rem; //14px
- --font-size-nm: 1rem; //16px
- --font-size-md: 1.125rem; //18px
- --font-size-lg: 1.25rem; //20px
- --font-size-xl: 1.5rem; //24px
- --font-size-2xl: 2rem; //32px
- --font-size-3xl: 3rem; //48px
+ // Font Sizes
+ --font-size-xxs: 0.625rem; //10px
+ --font-size-xs: 0.75rem; //12px
+ --font-size-sm: 0.875rem; //14px
+ --font-size-nm: 1rem; //16px
+ --font-size-md: 1.125rem; //18px
+ --font-size-lg: 1.25rem; //20px
+ --font-size-xl: 1.5rem; //24px
+ --font-size-2xl: 2rem; //32px
+ --font-size-3xl: 3rem; //48px
- // Font Weights
- --font-weight-regular: 400;
- --font-weight-medium: 500;
- --font-weight-bold: 700;
- --font-weight-extrabold: 800;
+ // Font Weights
+ --font-weight-regular: 400;
+ --font-weight-medium: 500;
+ --font-weight-bold: 700;
+ --font-weight-extrabold: 800;
- --font-weight-text: var(--font-weight-medium);
- --font-weight-heading: var(--font-weight-extrabold);
- --font-weight-title: var(--font-weight-extrabold);
+ --font-weight-text: var(--font-weight-medium);
+ --font-weight-heading: var(--font-weight-extrabold);
+ --font-weight-title: var(--font-weight-extrabold);
- @media screen and (min-width: 320px) {
- --size-mobile-navbar-height-expanded: 11.5rem;
- }
+ @media screen and (min-width: 320px) {
+ --size-mobile-navbar-height-expanded: 11.5rem;
+ }
- @media screen and (min-width: 432px) {
- --size-mobile-navbar-height-expanded: 9.25rem;
- }
+ @media screen and (min-width: 432px) {
+ --size-mobile-navbar-height-expanded: 9.25rem;
+ }
- @media screen and (min-width: 765px) {
- --size-mobile-navbar-height-expanded: 7rem;
- }
+ @media screen and (min-width: 765px) {
+ --size-mobile-navbar-height-expanded: 7rem;
+ }
}
svg {
- height: 1em;
- width: 1em;
+ height: 1em;
+ width: 1em;
}
a {
- color: inherit;
- text-decoration: none;
+ color: inherit;
+ text-decoration: none;
}
h1 {
- color: var(--color-text-dark);
+ color: var(--color-text-dark);
}
h2 {
- margin-top: 0;
- margin-bottom: 1rem;
- color: var(--color-text-dark);
+ margin-top: 0;
+ margin-bottom: 1rem;
+ color: var(--color-text-dark);
}
h3 {
- margin-block: var(--spacing-card-md) var(--spacing-card-sm);
- color: var(--color-text-dark);
+ margin-block: var(--spacing-card-md) var(--spacing-card-sm);
+ color: var(--color-text-dark);
}
input {
- border-radius: var(--size-rounded-sm);
- box-sizing: border-box;
- border: 2px solid transparent;
- // safari iOS rounds inputs by default
- // set the appearance to none to prevent this
- appearance: none !important;
+ border-radius: var(--size-rounded-sm);
+ box-sizing: border-box;
+ border: 2px solid transparent;
+ // safari iOS rounds inputs by default
+ // set the appearance to none to prevent this
+ appearance: none !important;
}
pre {
- font-weight: var(--font-weight-regular);
+ font-weight: var(--font-weight-regular);
}
input,
textarea {
- background: var(--color-button-bg);
- color: var(--color-text);
- padding: 0.5rem 1rem;
- font-weight: var(--font-weight-medium);
- border: none;
- outline: 2px solid transparent;
- box-shadow:
- var(--shadow-inset-sm),
- 0 0 0 0 transparent;
- transition: box-shadow 0.1s ease-in-out;
- min-height: 36px;
+ background: var(--color-button-bg);
+ color: var(--color-text);
+ padding: 0.5rem 1rem;
+ font-weight: var(--font-weight-medium);
+ border: none;
+ outline: 2px solid transparent;
+ box-shadow:
+ var(--shadow-inset-sm),
+ 0 0 0 0 transparent;
+ transition: box-shadow 0.1s ease-in-out;
+ min-height: 36px;
- &:focus,
- &:focus-visible {
- box-shadow:
- inset 0 0 0 transparent,
- 0 0 0 0.25rem var(--color-brand-shadow);
- color: var(--color-button-text-active);
- }
+ &:focus,
+ &:focus-visible {
+ box-shadow:
+ inset 0 0 0 transparent,
+ 0 0 0 0.25rem var(--color-brand-shadow);
+ color: var(--color-button-text-active);
+ }
- &:disabled,
- &[disabled="true"] {
- opacity: 0.6;
- pointer-events: none;
- cursor: not-allowed;
- }
+ &:disabled,
+ &[disabled='true'] {
+ opacity: 0.6;
+ pointer-events: none;
+ cursor: not-allowed;
+ }
- &:focus::placeholder {
- opacity: 0.8;
- }
+ &:focus::placeholder {
+ opacity: 0.8;
+ }
- &::placeholder {
- color: var(--color-button-text);
- opacity: 0.6;
- }
+ &::placeholder {
+ color: var(--color-button-text);
+ opacity: 0.6;
+ }
}
button,
-input[type="button"] {
- cursor: pointer;
- border: none;
- outline: 2px solid transparent;
+input[type='button'] {
+ cursor: pointer;
+ border: none;
+ outline: 2px solid transparent;
}
kbd {
- background-color: var(--color-code-bg);
- color: var(--color-code-text);
- box-shadow: 0 2px 1px var(--color-kbd-shadow);
- padding: 0.2em 0.5em 0.1em;
- border-radius: 3px;
- line-height: 1;
- font-size: 0.85em !important;
+ background-color: var(--color-code-bg);
+ color: var(--color-code-text);
+ box-shadow: 0 2px 1px var(--color-kbd-shadow);
+ padding: 0.2em 0.5em 0.1em;
+ border-radius: 3px;
+ line-height: 1;
+ font-size: 0.85em !important;
}
-@import "~/assets/styles/layout.scss";
-@import "~/assets/styles/utils.scss";
-@import "~/assets/styles/components.scss";
+@import '~/assets/styles/layout.scss';
+@import '~/assets/styles/utils.scss';
+@import '~/assets/styles/components.scss';
button:focus-visible,
a:focus-visible,
-[tabindex="0"]:focus-visible {
- outline: 0.25rem solid #ea80ff;
- border-radius: 0.25rem;
+[tabindex='0']:focus-visible {
+ outline: 0.25rem solid #ea80ff;
+ border-radius: 0.25rem;
}
// OMORPHIA FIXES
.card {
- outline-offset: -2px;
+ outline-offset: -2px;
}
input {
- outline: 2px solid transparent !important;
+ outline: 2px solid transparent !important;
}
.button-animation {
- transition:
- opacity 0.5s ease-in-out,
- filter 0.2s ease-in-out,
- transform 0.05s ease-in-out,
- outline-width 0.2s ease-in-out;
+ transition:
+ opacity 0.5s ease-in-out,
+ filter 0.2s ease-in-out,
+ transform 0.05s ease-in-out,
+ outline-width 0.2s ease-in-out;
}
.button-transparent {
- box-shadow: none;
+ box-shadow: none;
}
diff --git a/apps/frontend/src/assets/styles/layout.scss b/apps/frontend/src/assets/styles/layout.scss
index 60e05cfd..396481ed 100644
--- a/apps/frontend/src/assets/styles/layout.scss
+++ b/apps/frontend/src/assets/styles/layout.scss
@@ -1,227 +1,227 @@
.columns {
- display: flex;
+ display: flex;
- @for $i from 1 through 5 {
- .column-grow-#{$i} {
- flex-grow: $i;
- }
- }
+ @for $i from 1 through 5 {
+ .column-grow-#{$i} {
+ flex-grow: $i;
+ }
+ }
}
.rows {
- display: flex;
- flex-direction: column;
+ display: flex;
+ flex-direction: column;
- @for $i from 1 through 4 {
- .row-grow-#{$i} {
- flex-grow: $i;
- }
- }
+ @for $i from 1 through 4 {
+ .row-grow-#{$i} {
+ flex-grow: $i;
+ }
+ }
}
.page-container {
- margin: var(--spacing-card-md);
- margin-top: 0;
+ margin: var(--spacing-card-md);
+ margin-top: 0;
- .page-contents {
- display: flex;
- flex-direction: column;
- .content {
- width: 100%;
- }
- @media screen and (min-width: 1024px) {
- flex-direction: row;
- //max-width: 1280px;
- margin-left: auto;
- margin-right: auto;
- }
- }
+ .page-contents {
+ display: flex;
+ flex-direction: column;
+ .content {
+ width: 100%;
+ }
+ @media screen and (min-width: 1024px) {
+ flex-direction: row;
+ //max-width: 1280px;
+ margin-left: auto;
+ margin-right: auto;
+ }
+ }
}
.normal-page {
- display: grid;
- padding: 0 1.5rem;
+ display: grid;
+ padding: 0 1.5rem;
- grid-template:
- "sidebar"
- "content"
- "info"
- / 100%;
+ grid-template:
+ 'sidebar'
+ 'content'
+ 'info'
+ / 100%;
- @media screen and (max-width: 1024px) {
- margin-top: var(--spacing-card-md);
- }
+ @media screen and (max-width: 1024px) {
+ margin-top: var(--spacing-card-md);
+ }
- .normal-page__sidebar {
- grid-area: sidebar;
- }
+ .normal-page__sidebar {
+ grid-area: sidebar;
+ }
- .normal-page__info {
- grid-area: info;
- }
+ .normal-page__info {
+ grid-area: info;
+ }
- .normal-page__content {
- grid-area: content;
- }
+ .normal-page__content {
+ grid-area: content;
+ }
- .normal-page__header {
- grid-area: header;
- }
+ .normal-page__header {
+ grid-area: header;
+ }
}
@media (min-width: 1024px) {
- .full-page {
- margin: 0 auto;
- max-width: min(1280px, 100vw);
- width: 80rem;
- }
+ .full-page {
+ margin: 0 auto;
+ max-width: min(1280px, 100vw);
+ width: 80rem;
+ }
- .normal-page {
- margin: 0 auto;
- max-width: 80rem;
- column-gap: 0.75rem;
+ .normal-page {
+ margin: 0 auto;
+ max-width: 80rem;
+ column-gap: 0.75rem;
- grid-template:
- "sidebar content" auto
- "info content" auto
- "dummy content" 1fr
- / 18.75rem 1fr;
+ grid-template:
+ 'sidebar content' auto
+ 'info content' auto
+ 'dummy content' 1fr
+ / 18.75rem 1fr;
- &.alt-layout {
- grid-template:
- "content sidebar" auto
- "content info" auto
- "content dummy" 1fr
- / 1fr 18.75rem;
- }
+ &.alt-layout {
+ grid-template:
+ 'content sidebar' auto
+ 'content info' auto
+ 'content dummy' 1fr
+ / 1fr 18.75rem;
+ }
- &.no-sidebar {
- grid-template:
- "header header" auto
- "content content" auto
- "info info" auto
- "dummy dummy" 1fr
- / 1fr 1fr;
+ &.no-sidebar {
+ grid-template:
+ 'header header' auto
+ 'content content' auto
+ 'info info' auto
+ 'dummy dummy' 1fr
+ / 1fr 1fr;
- .normal-page__content {
- grid-area: content;
- max-width: 100%;
- }
- }
- }
+ .normal-page__content {
+ grid-area: content;
+ max-width: 100%;
+ }
+ }
+ }
- .normal-page__sidebar {
- min-width: 18.75rem;
- width: 18.75rem;
- }
+ .normal-page__sidebar {
+ min-width: 18.75rem;
+ width: 18.75rem;
+ }
- .normal-page__content {
- max-width: calc(80rem - 18.75rem - 1.5rem);
- //overflow-x: hidden;
- }
+ .normal-page__content {
+ max-width: calc(80rem - 18.75rem - 1.5rem);
+ //overflow-x: hidden;
+ }
}
.new-page {
- display: grid;
- margin: 0 auto;
- max-width: 80rem;
- column-gap: 0.75rem;
- padding: 0 1.5rem;
- padding-bottom: 1.5rem;
+ display: grid;
+ margin: 0 auto;
+ max-width: 80rem;
+ column-gap: 0.75rem;
+ padding: 0 1.5rem;
+ padding-bottom: 1.5rem;
- grid-template:
- "header"
- "content"
- "sidebar"
- / 100%;
+ grid-template:
+ 'header'
+ 'content'
+ 'sidebar'
+ / 100%;
- .normal-page__ultimate-sidebar {
- grid-area: ultimate-sidebar;
- position: fixed;
- bottom: 1rem;
- right: 1rem;
- z-index: 100;
- max-width: calc(100% - 2rem);
- max-height: calc(100vh - 2rem);
- overflow-y: auto;
+ .normal-page__ultimate-sidebar {
+ grid-area: ultimate-sidebar;
+ position: fixed;
+ bottom: 1rem;
+ right: 1rem;
+ z-index: 100;
+ max-width: calc(100% - 2rem);
+ max-height: calc(100vh - 2rem);
+ overflow-y: auto;
- > div {
- box-shadow: 0 0 15px rgba(0, 0, 0, 0.3);
- }
- }
+ > div {
+ box-shadow: 0 0 15px rgba(0, 0, 0, 0.3);
+ }
+ }
- @media screen and (min-width: 1024px) {
- &.sidebar {
- grid-template:
- "header header" auto
- "content sidebar" auto
- "content dummy" 1fr
- / 1fr 18.75rem;
+ @media screen and (min-width: 1024px) {
+ &.sidebar {
+ grid-template:
+ 'header header' auto
+ 'content sidebar' auto
+ 'content dummy' 1fr
+ / 1fr 18.75rem;
- &.alt-layout {
- grid-template:
- "header header" auto
- "sidebar content" auto
- "dummy content" 1fr
- / 18.75rem 1fr;
- }
- }
+ &.alt-layout {
+ grid-template:
+ 'header header' auto
+ 'sidebar content' auto
+ 'dummy content' 1fr
+ / 18.75rem 1fr;
+ }
+ }
- .normal-page__sidebar {
- min-width: 18.75rem;
- width: 18.75rem;
- }
- }
+ .normal-page__sidebar {
+ min-width: 18.75rem;
+ width: 18.75rem;
+ }
+ }
- @media screen and (min-width: 1400px) {
- &.ultimate-sidebar {
- max-width: calc(80rem + 0.75rem + 600px);
+ @media screen and (min-width: 1400px) {
+ &.ultimate-sidebar {
+ max-width: calc(80rem + 0.75rem + 600px);
- grid-template:
- "header header ultimate-sidebar" auto
- "content sidebar ultimate-sidebar" auto
- "content dummy ultimate-sidebar" 1fr
- / 1fr 18.75rem auto;
+ grid-template:
+ 'header header ultimate-sidebar' auto
+ 'content sidebar ultimate-sidebar' auto
+ 'content dummy ultimate-sidebar' 1fr
+ / 1fr 18.75rem auto;
- .normal-page__header {
- max-width: 80rem;
- }
+ .normal-page__header {
+ max-width: 80rem;
+ }
- .normal-page__ultimate-sidebar {
- position: sticky;
- top: 4.5rem;
- bottom: unset;
- right: unset;
- z-index: unset;
- align-self: start;
- display: flex;
- height: calc(100vh - 4.5rem * 2);
+ .normal-page__ultimate-sidebar {
+ position: sticky;
+ top: 4.5rem;
+ bottom: unset;
+ right: unset;
+ z-index: unset;
+ align-self: start;
+ display: flex;
+ height: calc(100vh - 4.5rem * 2);
- > div {
- box-shadow: none;
- }
- }
+ > div {
+ box-shadow: none;
+ }
+ }
- &.alt-layout {
- grid-template:
- "ultimate-sidebar header header" auto
- "ultimate-sidebar sidebar content" auto
- "ultimate-sidebar dummy content" 1fr
- / auto 18.75rem 1fr;
- }
- }
- }
+ &.alt-layout {
+ grid-template:
+ 'ultimate-sidebar header header' auto
+ 'ultimate-sidebar sidebar content' auto
+ 'ultimate-sidebar dummy content' 1fr
+ / auto 18.75rem 1fr;
+ }
+ }
+ }
- .normal-page__sidebar {
- grid-area: sidebar;
- }
+ .normal-page__sidebar {
+ grid-area: sidebar;
+ }
- .normal-page__content {
- grid-area: content;
- max-width: calc(80rem - 18.75rem - 1.5rem);
- //overflow-x: hidden;
- }
+ .normal-page__content {
+ grid-area: content;
+ max-width: calc(80rem - 18.75rem - 1.5rem);
+ //overflow-x: hidden;
+ }
- .normal-page__header {
- grid-area: header;
- }
+ .normal-page__header {
+ grid-area: header;
+ }
}
diff --git a/apps/frontend/src/assets/styles/tailwind.css b/apps/frontend/src/assets/styles/tailwind.css
index f56d34f7..2f3b0d6d 100644
--- a/apps/frontend/src/assets/styles/tailwind.css
+++ b/apps/frontend/src/assets/styles/tailwind.css
@@ -5,5 +5,5 @@
h1,
h2,
h3 {
- @apply font-bold;
+ @apply font-bold;
}
diff --git a/apps/frontend/src/assets/styles/utils.scss b/apps/frontend/src/assets/styles/utils.scss
index b2e96ea6..5592fd8b 100644
--- a/apps/frontend/src/assets/styles/utils.scss
+++ b/apps/frontend/src/assets/styles/utils.scss
@@ -1,10 +1,10 @@
body {
- overflow-y: scroll;
- overflow-x: hidden;
+ overflow-y: scroll;
+ overflow-x: hidden;
}
.text-container p {
- line-height: 1.3;
+ line-height: 1.3;
}
// From the Bootstrap project
@@ -12,20 +12,20 @@ body {
// Copyright (c) 2011-2023 The Bootstrap Authors
// https://github.com/twbs/bootstrap/blob/2f617215755b066904248525a8c56ea425dde871/scss/mixins/_visually-hidden.scss#L8
.visually-hidden {
- width: 1px !important;
- height: 1px !important;
- padding: 0 !important;
- margin: -1px !important;
- overflow: hidden !important;
- clip: rect(0, 0, 0, 0) !important;
- white-space: nowrap !important;
- border: 0 !important;
+ width: 1px !important;
+ height: 1px !important;
+ padding: 0 !important;
+ margin: -1px !important;
+ overflow: hidden !important;
+ clip: rect(0, 0, 0, 0) !important;
+ white-space: nowrap !important;
+ border: 0 !important;
- &:not(caption) {
- position: absolute !important;
- }
+ &:not(caption) {
+ position: absolute !important;
+ }
}
.preserve-lines {
- white-space: pre-line;
+ white-space: pre-line;
}
diff --git a/apps/frontend/src/components/brand/LogoAnimated.vue b/apps/frontend/src/components/brand/LogoAnimated.vue
index a49454f2..d19eca50 100644
--- a/apps/frontend/src/components/brand/LogoAnimated.vue
+++ b/apps/frontend/src/components/brand/LogoAnimated.vue
@@ -1,101 +1,101 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/brand/TextLogo.vue b/apps/frontend/src/components/brand/TextLogo.vue
index a942c140..4bfb0c8f 100644
--- a/apps/frontend/src/components/brand/TextLogo.vue
+++ b/apps/frontend/src/components/brand/TextLogo.vue
@@ -1,97 +1,97 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/Accordion.vue b/apps/frontend/src/components/ui/Accordion.vue
index 31fcfae6..f255fb48 100644
--- a/apps/frontend/src/components/ui/Accordion.vue
+++ b/apps/frontend/src/components/ui/Accordion.vue
@@ -1,92 +1,92 @@
-
-
- (isOpen ? close() : open())">
-
-
-
-
-
+
+
+ (isOpen ? close() : open())">
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/AdPlaceholder.vue b/apps/frontend/src/components/ui/AdPlaceholder.vue
index a812a60c..70c713a7 100644
--- a/apps/frontend/src/components/ui/AdPlaceholder.vue
+++ b/apps/frontend/src/components/ui/AdPlaceholder.vue
@@ -1,122 +1,122 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/AutomaticAccordion.vue b/apps/frontend/src/components/ui/AutomaticAccordion.vue
index 154f3fd0..c06e3c59 100644
--- a/apps/frontend/src/components/ui/AutomaticAccordion.vue
+++ b/apps/frontend/src/components/ui/AutomaticAccordion.vue
@@ -1,70 +1,70 @@
-
+
diff --git a/apps/frontend/src/components/ui/Breadcrumbs.vue b/apps/frontend/src/components/ui/Breadcrumbs.vue
index 889a2484..b3dd258a 100644
--- a/apps/frontend/src/components/ui/Breadcrumbs.vue
+++ b/apps/frontend/src/components/ui/Breadcrumbs.vue
@@ -1,54 +1,54 @@
-
-
-
- {{ link.label }}
-
-
-
- {{ currentTitle }}
-
+
+
+
+ {{ link.label }}
+
+
+
+ {{ currentTitle }}
+
diff --git a/apps/frontend/src/components/ui/Checkbox.vue b/apps/frontend/src/components/ui/Checkbox.vue
index b21786c7..a4e027d7 100644
--- a/apps/frontend/src/components/ui/Checkbox.vue
+++ b/apps/frontend/src/components/ui/Checkbox.vue
@@ -1,151 +1,151 @@
-
+
diff --git a/apps/frontend/src/components/ui/Chips.vue b/apps/frontend/src/components/ui/Chips.vue
index 3fd24832..a824028c 100644
--- a/apps/frontend/src/components/ui/Chips.vue
+++ b/apps/frontend/src/components/ui/Chips.vue
@@ -1,103 +1,103 @@
-
-
-
- {{ formatLabel(item) }}
-
-
+
+
+
+ {{ formatLabel(item) }}
+
+
diff --git a/apps/frontend/src/components/ui/CollectionCreateModal.vue b/apps/frontend/src/components/ui/CollectionCreateModal.vue
index 02b07560..44086a79 100644
--- a/apps/frontend/src/components/ui/CollectionCreateModal.vue
+++ b/apps/frontend/src/components/ui/CollectionCreateModal.vue
@@ -1,128 +1,128 @@
-
-
-
-
-
- Name
- *
-
-
-
-
-
-
- Summary
- A sentence or two that describes your collection.
-
-
-
-
-
-
- Your new collection will be created as a public collection with
- {{ projectIds.length > 0 ? projectIds.length : "no" }}
- {{ projectIds.length !== 1 ? "projects" : "project" }}.
-
-
-
-
-
- Create collection
-
-
-
-
-
- Cancel
-
-
-
-
-
+
+
+
+
+
+ Name
+ *
+
+
+
+
+
+
+ Summary
+ A sentence or two that describes your collection.
+
+
+
+
+
+
+ Your new collection will be created as a public collection with
+ {{ projectIds.length > 0 ? projectIds.length : 'no' }}
+ {{ projectIds.length !== 1 ? 'projects' : 'project' }}.
+
+
+
+
+
+ Create collection
+
+
+
+
+
+ Cancel
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/ConditionalNuxtLink.vue b/apps/frontend/src/components/ui/ConditionalNuxtLink.vue
index 8a9ac6b5..333ca953 100644
--- a/apps/frontend/src/components/ui/ConditionalNuxtLink.vue
+++ b/apps/frontend/src/components/ui/ConditionalNuxtLink.vue
@@ -1,21 +1,21 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/DoubleIcon.vue b/apps/frontend/src/components/ui/DoubleIcon.vue
index 7855a9b3..a1132e40 100644
--- a/apps/frontend/src/components/ui/DoubleIcon.vue
+++ b/apps/frontend/src/components/ui/DoubleIcon.vue
@@ -1,33 +1,33 @@
-
+
diff --git a/apps/frontend/src/components/ui/DropArea.vue b/apps/frontend/src/components/ui/DropArea.vue
index 515364b7..a688c0cc 100644
--- a/apps/frontend/src/components/ui/DropArea.vue
+++ b/apps/frontend/src/components/ui/DropArea.vue
@@ -1,94 +1,94 @@
- {
- $refs.drop_area.style.visibility = 'hidden';
+
{
+ $refs.drop_area.style.visibility = 'hidden'
- if (event.dataTransfer && event.dataTransfer.files && fileAllowed) {
- $emit('change', event.dataTransfer.files);
- }
- }
- "
- @dragenter.prevent="allowDrag"
- @dragover.prevent="allowDrag"
- @dragleave.prevent="$refs.drop_area.style.visibility = 'hidden'"
- />
+ if (event.dataTransfer && event.dataTransfer.files && fileAllowed) {
+ $emit('change', event.dataTransfer.files)
+ }
+ }
+ "
+ @dragenter.prevent="allowDrag"
+ @dragover.prevent="allowDrag"
+ @dragleave.prevent="$refs.drop_area.style.visibility = 'hidden'"
+ />
diff --git a/apps/frontend/src/components/ui/EnvironmentIndicator.vue b/apps/frontend/src/components/ui/EnvironmentIndicator.vue
index 84254dde..0725737e 100644
--- a/apps/frontend/src/components/ui/EnvironmentIndicator.vue
+++ b/apps/frontend/src/components/ui/EnvironmentIndicator.vue
@@ -1,105 +1,105 @@
-
-
- A {{ type }}
-
-
-
-
- Client or server
-
-
-
- Client and server
-
-
-
- Client
-
-
-
- Server
-
-
-
- Unsupported
-
-
-
- A {{ type }}
-
-
+
+
+ A {{ type }}
+
+
+
+
+ Client or server
+
+
+
+ Client and server
+
+
+
+ Client
+
+
+
+ Server
+
+
+
+ Unsupported
+
+
+
+ A {{ type }}
+
+
diff --git a/apps/frontend/src/components/ui/FileInput.vue b/apps/frontend/src/components/ui/FileInput.vue
index ec1558ec..6ff1605e 100644
--- a/apps/frontend/src/components/ui/FileInput.vue
+++ b/apps/frontend/src/components/ui/FileInput.vue
@@ -1,117 +1,117 @@
-
-
- {{ prompt }}
-
-
+
+
+ {{ prompt }}
+
+
diff --git a/apps/frontend/src/components/ui/HCaptcha.vue b/apps/frontend/src/components/ui/HCaptcha.vue
index bacc2516..ebbec75f 100644
--- a/apps/frontend/src/components/ui/HCaptcha.vue
+++ b/apps/frontend/src/components/ui/HCaptcha.vue
@@ -1,63 +1,63 @@
-
+
diff --git a/apps/frontend/src/components/ui/MessageBanner.vue b/apps/frontend/src/components/ui/MessageBanner.vue
index 3adb6fc5..62ba9a9a 100644
--- a/apps/frontend/src/components/ui/MessageBanner.vue
+++ b/apps/frontend/src/components/ui/MessageBanner.vue
@@ -1,58 +1,58 @@
-
+
diff --git a/apps/frontend/src/components/ui/Modal.vue b/apps/frontend/src/components/ui/Modal.vue
index f815e049..0a15a66e 100644
--- a/apps/frontend/src/components/ui/Modal.vue
+++ b/apps/frontend/src/components/ui/Modal.vue
@@ -1,152 +1,152 @@
-
-
+
+
diff --git a/apps/frontend/src/components/ui/ModalCreation.vue b/apps/frontend/src/components/ui/ModalCreation.vue
index bfc5b140..b36cf052 100644
--- a/apps/frontend/src/components/ui/ModalCreation.vue
+++ b/apps/frontend/src/components/ui/ModalCreation.vue
@@ -1,215 +1,215 @@
-
-
-
-
-
- Name
- *
-
-
-
-
-
-
-
- URL
- *
-
-
-
-
https://modrinth.com/project/
-
-
-
-
-
-
- Visibility
- *
-
- The visibility of your project after it has been approved.
-
-
-
-
-
-
- Summary
- *
-
- A sentence or two that describes your project.
-
-
-
-
-
-
-
-
-
- Create project
-
-
-
-
-
- Cancel
-
-
-
-
-
+
+
+
+
+
+ Name
+ *
+
+
+
+
+
+
+
+ URL
+ *
+
+
+
+
https://modrinth.com/project/
+
+
+
+
+
+
+ Visibility
+ *
+
+ The visibility of your project after it has been approved.
+
+
+
+
+
+
+ Summary
+ *
+
+ A sentence or two that describes your project.
+
+
+
+
+
+
+
+
+
+ Create project
+
+
+
+
+
+ Cancel
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/ModerationChecklist.vue b/apps/frontend/src/components/ui/ModerationChecklist.vue
deleted file mode 100644
index b21fd995..00000000
--- a/apps/frontend/src/components/ui/ModerationChecklist.vue
+++ /dev/null
@@ -1,1133 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
You are done moderating this project! There are {{ futureProjects.length }} left.
-
-
-
- Enter your moderation message here. Remember to check the Moderation tab to answer any
- questions an author might have!
-
-
-
-
-
-
-
-
Loading data...
-
-
All permissions obtained. You may skip this step!
-
-
-
All permission checks complete!
-
-
-
-
- Previous
-
-
-
-
-
-
-
-
-
- Does this project provide identification and permission for
- {{ modPackData[modPackIndex].file_name }} ?
-
-
- Does this project provide attribution for
- {{ modPackData[modPackIndex].file_name }} ?
-
-
- Does this project provide proof of permission for
- {{ modPackData[modPackIndex].file_name }} ?
-
-
-
- {{ option.name }}
-
-
-
-
-
-
-
- Previous
-
-
-
-
-
- Next project
-
-
-
-
-
-
-
-
-
-
-
-
- Skip
- Exit
-
-
-
-
- Previous
-
-
-
-
-
- Next
-
-
-
- Generate message
-
-
-
-
-
- Approve
-
-
-
-
-
- Reject
-
-
-
-
-
- Withhold
-
-
-
-
-
- Next project
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/frontend/src/components/ui/NavRow.vue b/apps/frontend/src/components/ui/NavRow.vue
index b654cdd7..5d2544fa 100644
--- a/apps/frontend/src/components/ui/NavRow.vue
+++ b/apps/frontend/src/components/ui/NavRow.vue
@@ -1,160 +1,160 @@
-
-
- {{ link.label }}
-
-
-
+
+
+ {{ link.label }}
+
+
+
diff --git a/apps/frontend/src/components/ui/NavStack.vue b/apps/frontend/src/components/ui/NavStack.vue
index 9ba713ea..f7bb9fcc 100644
--- a/apps/frontend/src/components/ui/NavStack.vue
+++ b/apps/frontend/src/components/ui/NavStack.vue
@@ -1,32 +1,32 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/NavStackItem.vue b/apps/frontend/src/components/ui/NavStackItem.vue
index c1471ca9..06146758 100644
--- a/apps/frontend/src/components/ui/NavStackItem.vue
+++ b/apps/frontend/src/components/ui/NavStackItem.vue
@@ -1,116 +1,116 @@
-
-
-
- {{ label }}
- BETA
-
-
-
-
-
-
- {{ label }}
- BETA
-
-
- i forgor 💀
+
+
+
+ {{ label }}
+ BETA
+
+
+
+
+
+
+ {{ label }}
+ BETA
+
+
+ i forgor 💀
diff --git a/apps/frontend/src/components/ui/NavTabs.vue b/apps/frontend/src/components/ui/NavTabs.vue
index 629b47f5..5a2c0b78 100644
--- a/apps/frontend/src/components/ui/NavTabs.vue
+++ b/apps/frontend/src/components/ui/NavTabs.vue
@@ -1,173 +1,173 @@
-
-
-
- {{ link.label }}
-
-
-
+
+
+
+ {{ link.label }}
+
+
+
diff --git a/apps/frontend/src/components/ui/NewsletterButton.vue b/apps/frontend/src/components/ui/NewsletterButton.vue
index 61778eaa..3766b83b 100644
--- a/apps/frontend/src/components/ui/NewsletterButton.vue
+++ b/apps/frontend/src/components/ui/NewsletterButton.vue
@@ -1,51 +1,57 @@
-
-
- Subscribe
- Subscribed!
-
-
+
+
+ Subscribe
+ Subscribed!
+
+
diff --git a/apps/frontend/src/components/ui/NotificationItem.vue b/apps/frontend/src/components/ui/NotificationItem.vue
index 4a293684..25a377bc 100644
--- a/apps/frontend/src/components/ui/NotificationItem.vue
+++ b/apps/frontend/src/components/ui/NotificationItem.vue
@@ -1,609 +1,599 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A project you follow,
- {{ project.title }}
- , has been updated:
-
-
-
-
-
- {{ invitedBy.username }}
-
-
- has invited you to join
-
- {{ project.title }} .
-
-
-
-
-
-
- {{ invitedBy.username }}
-
-
- has invited you to join
-
- {{ organization.name }} .
-
-
-
-
- {{ project.title }}
-
-
- has been
-
-
-
- updated from
-
- to
-
-
- by the moderators.
-
-
- Your project,
- {{ project.title }}
- , has received
- messages
- a message
- from the moderators.
-
-
- A moderator replied to your report of
-
- version
-
- {{ version.name }}
-
- of project
-
-
- {{ project.title }}
-
-
- {{ user.username }}
-
- .
-
-
-
-
-
-
-
-
-
-
-
-
- {{ notif.extra_data.version.name }}
-
-
- for
-
- {{ $formatVersion(notif.extra_data.version.game_versions) }}
-
- {{ formatRelativeTime(notif.extra_data.version.date_published) }}
-
-
-
-
-
- {{ notification.text }}
-
-
-
-
- Read
-
-
- Received {{ formatRelativeTime(notification.created) }}
-
-
-
-
- {
- acceptTeamInvite(notification.body.team_id);
- read();
- }
- "
- >
-
-
- {
- removeSelfFromTeam(notification.body.team_id);
- read();
- }
- "
- >
-
-
-
-
-
-
-
-
-
-
- {
- acceptTeamInvite(notification.body.team_id);
- read();
- }
- "
- >
-
- Accept
-
- {
- removeSelfFromTeam(notification.body.team_id);
- read();
- }
- "
- >
-
- Decline
-
-
-
-
- Mark as read
-
-
-
-
-
-
- Open link
-
-
-
-
- {{ action.title }}
-
-
-
- Mark as read
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A project you follow,
+ {{ project.title }}
+ , has been updated:
+
+
+
+
+
+ {{ invitedBy.username }}
+
+
+ has invited you to join
+
+ {{ project.title }} .
+
+
+
+
+
+
+ {{ invitedBy.username }}
+
+
+ has invited you to join
+
+ {{ organization.name }} .
+
+
+
+
+ {{ project.title }}
+
+
+ has been
+
+
+
+ updated from
+
+ to
+
+
+ by the moderators.
+
+
+ Your project,
+ {{ project.title }}
+ , has received
+ messages
+ a message
+ from the moderators.
+
+
+ A moderator replied to your report of
+
+ version
+
+ {{ version.name }}
+
+ of project
+
+
+ {{ project.title }}
+
+
+ {{ user.username }}
+
+ .
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ notif.extra_data.version.name }}
+
+
+ for
+
+ {{ $formatVersion(notif.extra_data.version.game_versions) }}
+
+ {{ formatRelativeTime(notif.extra_data.version.date_published) }}
+
+
+
+
+
+ {{ notification.text }}
+
+
+
+
+ Read
+
+
+ Received
+ {{ formatRelativeTime(notification.created) }}
+
+
+
+
+ {
+ acceptTeamInvite(notification.body.team_id)
+ read()
+ }
+ "
+ >
+
+
+ {
+ removeSelfFromTeam(notification.body.team_id)
+ read()
+ }
+ "
+ >
+
+
+
+
+
+
+
+
+
+
+ {
+ acceptTeamInvite(notification.body.team_id)
+ read()
+ }
+ "
+ >
+
+ Accept
+
+ {
+ removeSelfFromTeam(notification.body.team_id)
+ read()
+ }
+ "
+ >
+
+ Decline
+
+
+
+
+ Mark as read
+
+
+
+
+
+
+ Open link
+
+
+
+
+ {{ action.title }}
+
+
+
+ Mark as read
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/Notifications.vue b/apps/frontend/src/components/ui/Notifications.vue
deleted file mode 100644
index ebb43c2e..00000000
--- a/apps/frontend/src/components/ui/Notifications.vue
+++ /dev/null
@@ -1,213 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- x{{ item.count }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/frontend/src/components/ui/OptionGroup.vue b/apps/frontend/src/components/ui/OptionGroup.vue
index f00cd327..556e2cdb 100644
--- a/apps/frontend/src/components/ui/OptionGroup.vue
+++ b/apps/frontend/src/components/ui/OptionGroup.vue
@@ -1,128 +1,128 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/OrganizationCreateModal.vue b/apps/frontend/src/components/ui/OrganizationCreateModal.vue
index c9e96663..e1389eda 100644
--- a/apps/frontend/src/components/ui/OrganizationCreateModal.vue
+++ b/apps/frontend/src/components/ui/OrganizationCreateModal.vue
@@ -1,156 +1,166 @@
-
-
-
-
-
- Name
- *
-
-
-
-
-
-
-
- URL
- *
-
-
-
-
https://modrinth.com/organization/
-
-
-
-
-
-
- Summary
- *
-
- A sentence or two that describes your organization.
-
-
-
-
-
-
- You will be the owner of this organization, but you can invite other members and transfer
- ownership at any time.
-
-
-
-
-
- Create organization
-
-
-
-
-
- Cancel
-
-
-
-
-
+
+
+
+
+
+ Name
+ *
+
+
+
+
+
+
+
+ URL
+ *
+
+
+
+
https://modrinth.com/organization/
+
+
+
+
+
+
+ Summary
+ *
+
+ A sentence or two that describes your organization.
+
+
+
+
+
+
+ You will be the owner of this organization, but you can invite other members and transfer
+ ownership at any time.
+
+
+
+
+
+ Create organization
+
+
+
+
+
+ Cancel
+
+
+
+
+
-
diff --git a/apps/frontend/src/components/ui/OrganizationProjectTransferModal.vue b/apps/frontend/src/components/ui/OrganizationProjectTransferModal.vue
index 73ded455..7cd718af 100644
--- a/apps/frontend/src/components/ui/OrganizationProjectTransferModal.vue
+++ b/apps/frontend/src/components/ui/OrganizationProjectTransferModal.vue
@@ -1,247 +1,247 @@
-
-
-
-
-
-
-
-
-
Icon
-
Name
-
ID
-
Type
-
-
-
-
- it !== project))
- : selectedProjects.push(project)
- "
- />
-
-
+
+
+
+
+
+
+
+
+
Icon
+
Name
+
ID
+
Type
+
+
+
+
+ it !== project))
+ : selectedProjects.push(project)
+ "
+ />
+
+
-
-
-
- {{ project.title }}
-
-
-
+
+
+
+ {{ project.title }}
+
+
+
-
-
-
+
+
+
-
-
- {{
- formatProjectType(
- $getProjectTypeForDisplay(
- project.project_types?.[0] ?? "project",
- project.loaders,
- ),
- )
- }}
-
+
+
+ {{
+ formatProjectType(
+ $getProjectTypeForDisplay(
+ project.project_types?.[0] ?? 'project',
+ project.loaders,
+ ),
+ )
+ }}
+
-
-
-
-
-
-
-
-
-
-
- Cancel
-
-
-
-
- Transfer
-
- {{
- selectedProjects.length === props.projects.length
- ? "All"
- : selectedProjects.length
- }}
-
-
- {{ " " }}
- {{ selectedProjects.length === 1 ? "project" : "projects" }}
-
-
-
-
-
-
-
-
- Transfer projects
-
-
+
+
+
+
+
+
+
+
+
+
+ Cancel
+
+
+
+
+ Transfer
+
+ {{
+ selectedProjects.length === props.projects.length
+ ? 'All'
+ : selectedProjects.length
+ }}
+
+
+ {{ ' ' }}
+ {{ selectedProjects.length === 1 ? 'project' : 'projects' }}
+
+
+
+
+
+
+
+
+ Transfer projects
+
+
diff --git a/apps/frontend/src/components/ui/ProjectCard.vue b/apps/frontend/src/components/ui/ProjectCard.vue
index 1be6f86c..97d0b70e 100644
--- a/apps/frontend/src/components/ui/ProjectCard.vue
+++ b/apps/frontend/src/components/ui/ProjectCard.vue
@@ -1,525 +1,526 @@
-
-
-
-
-
-
-
-
-
-
- {{ name }}
-
-
-
- by
-
- {{ author }}
-
-
-
-
-
- {{ description }}
-
-
-
-
-
-
-
-
- {{ $formatNumber(downloads) }} downloads
-
-
-
-
-
- {{ $formatNumber(follows) }} followers
-
-
-
-
-
-
-
- Updated {{ formatRelativeTime(updatedAt) }}
-
-
-
- Published {{ formatRelativeTime(createdAt) }}
-
-
-
+
+
+
+
+
+
+
+
+
+
+ {{ name }}
+
+
+
+ by
+
+ {{ author }}
+
+
+
+
+
+ {{ description }}
+
+
+
+
+
+
+
+
+ {{ $formatNumber(downloads) }} downloads
+
+
+
+
+
+ {{ $formatNumber(follows) }} followers
+
+
+
+
+
+
+
+ Updated {{ formatRelativeTime(updatedAt) }}
+
+
+
+ Published {{ formatRelativeTime(createdAt) }}
+
+
+
diff --git a/apps/frontend/src/components/ui/ProjectMemberHeader.vue b/apps/frontend/src/components/ui/ProjectMemberHeader.vue
index 9bef2085..ca0b5a83 100644
--- a/apps/frontend/src/components/ui/ProjectMemberHeader.vue
+++ b/apps/frontend/src/components/ui/ProjectMemberHeader.vue
@@ -1,510 +1,480 @@
-
-
-
-
-
-
-
-
- {{ nag.title }}
- {{ nag.description }}
-
- {{ nag.link.title }}
-
-
-
-
- {{ nag.action.title }}
-
-
-
-
+
+
+
+
+
+ {{ getFormattedMessage(messages.publishingChecklist) }}
+
+
+
+
+
{{ getFormattedMessage(messages.required) }}
+
+ |
+
+
+ {{ getFormattedMessage(messages.warning) }}
+
+ |
+
+
+ {{ getFormattedMessage(messages.suggestion) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ getFormattedMessage(nag.title) }}
+
+ {{ getNagDescription(nag) }}
+
+ {{ getFormattedMessage(nag.link.title) }}
+
+
+
+
+
+ {{ getFormattedMessage(messages.submitForReview) }}
+
+
+
+
+
-
diff --git a/apps/frontend/src/components/ui/ShareArticleButtons.vue b/apps/frontend/src/components/ui/ShareArticleButtons.vue
index 8813a7ca..386fd273 100644
--- a/apps/frontend/src/components/ui/ShareArticleButtons.vue
+++ b/apps/frontend/src/components/ui/ShareArticleButtons.vue
@@ -1,86 +1,86 @@
-
+
diff --git a/apps/frontend/src/components/ui/charts/Chart.client.vue b/apps/frontend/src/components/ui/charts/Chart.client.vue
index 9769c64b..fccd41a1 100644
--- a/apps/frontend/src/components/ui/charts/Chart.client.vue
+++ b/apps/frontend/src/components/ui/charts/Chart.client.vue
@@ -1,91 +1,91 @@
-
+
diff --git a/apps/frontend/src/components/ui/charts/ChartDisplay.vue b/apps/frontend/src/components/ui/charts/ChartDisplay.vue
index 39c93e98..d3a1ff49 100644
--- a/apps/frontend/src/components/ui/charts/ChartDisplay.vue
+++ b/apps/frontend/src/components/ui/charts/ChartDisplay.vue
@@ -1,529 +1,527 @@
-
-
-
- Error
-
-
- {{ analytics.error.value }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ formatCategoryHeader(selectedChart) }}
-
-
- {{ formattedCategorySubtitle }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- projectIsOnDisplay(project.id) &&
- analytics.validProjectIds.value.includes(project.id)
- ? removeProjectFromDisplay(project.id)
- : addProjectToDisplay(project.id)
- "
- >
-
- {{ project.title }}
-
-
-
-
-
-
-
-
-
- Downloads by region
-
-
-
-
-
-
-
-
-
-
-
-
- Other
- {{ countryCodeToName(name) }}
-
- {{ formatNumber(count) }}
-
-
-
-
-
-
-
-
-
- Page views by region
-
-
-
-
-
-
-
-
-
-
-
-
-
- Other
- {{ countryCodeToName(name) }}
-
- {{ formatNumber(count) }}
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ Error
+
+
+ {{ analytics.error.value }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatCategoryHeader(selectedChart) }}
+
+
+ {{ formattedCategorySubtitle }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ projectIsOnDisplay(project.id) &&
+ analytics.validProjectIds.value.includes(project.id)
+ ? removeProjectFromDisplay(project.id)
+ : addProjectToDisplay(project.id)
+ "
+ >
+
+ {{ project.title }}
+
+
+
+
+
+
+
+
+
+ Downloads by region
+
+
+
+
+
+
+
+
+
+
+
+
+ Other
+ {{ countryCodeToName(name) }}
+
+ {{ formatNumber(count) }}
+
+
+
+
+
+
+
+
+
+ Page views by region
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Other
+ {{ countryCodeToName(name) }}
+
+ {{ formatNumber(count) }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/charts/CompactChart.client.vue b/apps/frontend/src/components/ui/charts/CompactChart.client.vue
index 17d88443..22d3eb7c 100644
--- a/apps/frontend/src/components/ui/charts/CompactChart.client.vue
+++ b/apps/frontend/src/components/ui/charts/CompactChart.client.vue
@@ -1,6 +1,6 @@
-
-
- {{ value }}
-
-
- {{ title }}
-
-
-
-
-
+
+
+ {{ value }}
+
+
+ {{ title }}
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/moderation/ChecklistKeybindsModal.vue b/apps/frontend/src/components/ui/moderation/ChecklistKeybindsModal.vue
deleted file mode 100644
index 787474bc..00000000
--- a/apps/frontend/src/components/ui/moderation/ChecklistKeybindsModal.vue
+++ /dev/null
@@ -1,116 +0,0 @@
-
-
-
-
-
-
-
{{ keybind.description }}
-
-
- {{ key }}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/frontend/src/components/ui/moderation/ModerationDelphiReportCard.vue b/apps/frontend/src/components/ui/moderation/ModerationDelphiReportCard.vue
new file mode 100644
index 00000000..2b4dc2d5
--- /dev/null
+++ b/apps/frontend/src/components/ui/moderation/ModerationDelphiReportCard.vue
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+
+
{{ report.project.title }}
+
+
+
+
+
+
+ {{ report.target.name }}
+
+
+
+
+
+ Score: {{ report.priority_score }}
+
+
+ {{ report.status.charAt(0).toUpperCase() + report.status.slice(1) }}
+
+
+ {{
+ report.version.files.find((file) => file.primary)?.filename ||
+ 'Unknown primary file'
+ }}
+
+
+
+
+
+
+
+
+ {{ formatRelativeTime(dayjs(report.detected_at).toDate()) }}
+
+
+
+
+
+
+ Accept
+
+
+
+
+ Reject
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Copy ID
+
+
+
+ Copy link
+
+
+
+
+
+
+
+
+
+ {{ formatRelativeTime(dayjs(report.detected_at).toDate()) }}
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/moderation/ModerationQueueCard.vue b/apps/frontend/src/components/ui/moderation/ModerationQueueCard.vue
new file mode 100644
index 00000000..3fd78900
--- /dev/null
+++ b/apps/frontend/src/components/ui/moderation/ModerationQueueCard.vue
@@ -0,0 +1,200 @@
+
+
+
+
+
+
+ {{ queueEntry.project.name }}
+
+
+
+ {{ queueEntry.owner.user.username }}
+
+
+
+ {{ queueEntry.org.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ props.queueEntry.project.project_types.map(formatProjectType).join(', ')
+ }}
+ {{
+ formatProjectType(props.queueEntry.project.project_type ?? 'project').substring(0, 3)
+ }}
+
+
+
•
+
+
+ Requesting
+
+
+
+
•
+
+
+ {{ getSubmittedTime(queueEntry) }}
+ {{
+ getSubmittedTime(queueEntry).replace('Submitted ', '')
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/moderation/ModerationReportCard.vue b/apps/frontend/src/components/ui/moderation/ModerationReportCard.vue
new file mode 100644
index 00000000..80a590c4
--- /dev/null
+++ b/apps/frontend/src/components/ui/moderation/ModerationReportCard.vue
@@ -0,0 +1,282 @@
+
+
+
+
+
+ Reported for
+
+ {{ formattedReportType }}
+
+
+
+ By
+ Reporter:
+
+
+ {{ report.reporter_user.username }}
+
+
+
+
+
+ {{
+ formatRelativeTime(report.created)
+ }}
+
+
+ Quick Reply
+ Quick Reply
+
+
+
+
+
+
+
+
+
+
+ Copy ID
+
+
+
+ Copy link
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ reportItemTitle }}
+
+
+
+
+
+ {{ report.target.name || 'Unknown User' }}
+
+
+
+
+
+ {{ formattedItemType }}
+
+
+ {{
+ report.version.files.find((file) => file.primary)?.filename || 'Unknown Version'
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/moderation/ModpackPermissionsFlow.vue b/apps/frontend/src/components/ui/moderation/ModpackPermissionsFlow.vue
deleted file mode 100644
index cdb97d7c..00000000
--- a/apps/frontend/src/components/ui/moderation/ModpackPermissionsFlow.vue
+++ /dev/null
@@ -1,513 +0,0 @@
-
-
-
-
-
Loading data...
-
-
-
All permissions already obtained.
-
-
-
-
All permission checks complete!
-
-
-
-
-
-
-
-
-
- Does this project provide identification and permission for
- {{ modPackData[currentIndex].file_name }} ?
-
-
- Does this project provide attribution for
- {{ modPackData[currentIndex].file_name }} ?
-
-
- Does this project provide proof of permission for
- {{ modPackData[currentIndex].file_name }} ?
-
-
-
-
- {{ option.name }}
-
-
-
-
-
-
-
-
-
-
- Previous
-
-
-
-
-
- {{ currentIndex + 1 >= modPackData.length ? "Complete" : "Next" }}
-
-
-
-
-
-
-
-
-
diff --git a/apps/frontend/src/components/ui/moderation/NewModerationChecklist.vue b/apps/frontend/src/components/ui/moderation/NewModerationChecklist.vue
deleted file mode 100644
index de6d5443..00000000
--- a/apps/frontend/src/components/ui/moderation/NewModerationChecklist.vue
+++ /dev/null
@@ -1,1361 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- You are done moderating this project!
-
- There are
- {{ futureProjectCount }} left.
-
-
-
-
-
-
-
-
-
-
-
-
-
Loading stage content...
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ action.label }}
-
-
-
- {{ option.label }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Skip
-
-
-
-
-
-
-
-
-
- Next Project
-
-
-
-
-
- Done
-
-
-
-
-
-
-
-
- Edit
-
-
-
-
-
- Reject
-
-
-
-
-
- Withhold
-
-
-
-
-
- Approve
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ opt.text }}
-
-
-
-
- Previous
-
-
-
- Next
-
-
-
-
- {{ loadingMessage ? "Generating..." : "Generate Message" }}
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/frontend/src/components/ui/moderation/checklist/ChecklistKeybindsModal.vue b/apps/frontend/src/components/ui/moderation/checklist/ChecklistKeybindsModal.vue
new file mode 100644
index 00000000..31a41369
--- /dev/null
+++ b/apps/frontend/src/components/ui/moderation/checklist/ChecklistKeybindsModal.vue
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
{{ keybind.description }}
+
+
+ {{ key }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/moderation/checklist/ModerationChecklist.vue b/apps/frontend/src/components/ui/moderation/checklist/ModerationChecklist.vue
new file mode 100644
index 00000000..3b393e07
--- /dev/null
+++ b/apps/frontend/src/components/ui/moderation/checklist/ModerationChecklist.vue
@@ -0,0 +1,1407 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ You are done moderating this project!
+
+ There are
+ {{ moderationStore.queueLength }} left.
+
+
+
+
+
+
+
+
+
+ Use simple mode
+
+
+
+ Use advanced mode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading stage content...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ action.label }}
+
+
+
+ {{ option.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Skip ({{ moderationStore.queueLength }} left)
+
+
+
+
+
+
+
+
+
+
+ Next Project ({{ moderationStore.queueLength }} left)
+
+
+
+ All Done!
+
+
+
+
+
+
+
+
+
+ Edit
+
+
+
+
+
+ Reject
+
+
+
+
+
+ Withhold
+
+
+
+
+
+ Approve
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ opt.text }}
+
+
+
+
+ Previous
+
+
+
+ Next
+
+
+
+
+ {{ loadingMessage ? 'Generating...' : 'Generate Message' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/moderation/checklist/ModpackPermissionsFlow.vue b/apps/frontend/src/components/ui/moderation/checklist/ModpackPermissionsFlow.vue
new file mode 100644
index 00000000..8cdbdbe1
--- /dev/null
+++ b/apps/frontend/src/components/ui/moderation/checklist/ModpackPermissionsFlow.vue
@@ -0,0 +1,513 @@
+
+
+
+
+
Loading data...
+
+
+
All permissions already obtained.
+
+
+
+
All permission checks complete!
+
+
+
+
+
+
+
+
+
+ Does this project provide identification and permission for
+ {{ modPackData[currentIndex].file_name }} ?
+
+
+ Does this project provide attribution for
+ {{ modPackData[currentIndex].file_name }} ?
+
+
+ Does this project provide proof of permission for
+ {{ modPackData[currentIndex].file_name }} ?
+
+
+
+
+ {{ option.name }}
+
+
+
+
+
+
+
+
+
+
+ Previous
+
+
+
+
+
+ {{ currentIndex + 1 >= modPackData.length ? 'Complete' : 'Next' }}
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/modrinth-loading-indicator.ts b/apps/frontend/src/components/ui/modrinth-loading-indicator.ts
index 041c51ef..efb645af 100644
--- a/apps/frontend/src/components/ui/modrinth-loading-indicator.ts
+++ b/apps/frontend/src/components/ui/modrinth-loading-indicator.ts
@@ -1,141 +1,142 @@
-import { computed, defineComponent, h, onBeforeUnmount, ref, watch } from "vue";
-import { startLoading, stopLoading, useNuxtApp } from "#imports";
+import { computed, defineComponent, h, onBeforeUnmount, ref, watch } from 'vue'
+
+import { startLoading, stopLoading, useNuxtApp } from '#imports'
export default defineComponent({
- name: "ModrinthLoadingIndicator",
- props: {
- throttle: {
- type: Number,
- default: 50,
- },
- duration: {
- type: Number,
- default: 500,
- },
- height: {
- type: Number,
- default: 3,
- },
- color: {
- type: [String, Boolean],
- default:
- "repeating-linear-gradient(to right, var(--color-green) 0%, var(--landing-green-label) 100%)",
- },
- },
- setup(props, { slots }) {
- const indicator = useLoadingIndicator({
- duration: props.duration,
- throttle: props.throttle,
- });
+ name: 'ModrinthLoadingIndicator',
+ props: {
+ throttle: {
+ type: Number,
+ default: 50,
+ },
+ duration: {
+ type: Number,
+ default: 500,
+ },
+ height: {
+ type: Number,
+ default: 3,
+ },
+ color: {
+ type: [String, Boolean],
+ default:
+ 'repeating-linear-gradient(to right, var(--color-green) 0%, var(--landing-green-label) 100%)',
+ },
+ },
+ setup(props, { slots }) {
+ const indicator = useLoadingIndicator({
+ duration: props.duration,
+ throttle: props.throttle,
+ })
- const nuxtApp = useNuxtApp();
- nuxtApp.hook("page:start", () => {
- startLoading();
- indicator.start();
- });
- nuxtApp.hook("page:finish", () => {
- stopLoading();
- indicator.finish();
- });
- onBeforeUnmount(() => indicator.clear);
+ const nuxtApp = useNuxtApp()
+ nuxtApp.hook('page:start', () => {
+ startLoading()
+ indicator.start()
+ })
+ nuxtApp.hook('page:finish', () => {
+ stopLoading()
+ indicator.finish()
+ })
+ onBeforeUnmount(() => indicator.clear)
- const loading = useLoading();
+ const loading = useLoading()
- watch(loading, (newValue) => {
- if (newValue) {
- indicator.start();
- } else {
- indicator.finish();
- }
- });
+ watch(loading, (newValue) => {
+ if (newValue) {
+ indicator.start()
+ } else {
+ indicator.finish()
+ }
+ })
- return () =>
- h(
- "div",
- {
- class: "nuxt-loading-indicator",
- style: {
- position: "fixed",
- top: 0,
- right: 0,
- left: 0,
- pointerEvents: "none",
- width: `${indicator.progress.value}%`,
- height: `${props.height}px`,
- opacity: indicator.isLoading.value ? 1 : 0,
- background: props.color || undefined,
- backgroundSize: `${(100 / indicator.progress.value) * 100}% auto`,
- transition: "width 0.1s, height 0.4s, opacity 0.4s",
- zIndex: 999999,
- },
- },
- slots,
- );
- },
-});
+ return () =>
+ h(
+ 'div',
+ {
+ class: 'nuxt-loading-indicator',
+ style: {
+ position: 'fixed',
+ top: 0,
+ right: 0,
+ left: 0,
+ pointerEvents: 'none',
+ width: `${indicator.progress.value}%`,
+ height: `${props.height}px`,
+ opacity: indicator.isLoading.value ? 1 : 0,
+ background: props.color || undefined,
+ backgroundSize: `${(100 / indicator.progress.value) * 100}% auto`,
+ transition: 'width 0.1s, height 0.4s, opacity 0.4s',
+ zIndex: 999999,
+ },
+ },
+ slots,
+ )
+ },
+})
function useLoadingIndicator(opts: { duration: number; throttle: number }) {
- const progress = ref(0);
- const isLoading = ref(false);
- const step = computed(() => 10000 / opts.duration);
+ const progress = ref(0)
+ const isLoading = ref(false)
+ const step = computed(() => 10000 / opts.duration)
- let _timer: any = null;
- let _throttle: any = null;
+ let _timer: any = null
+ let _throttle: any = null
- function start() {
- clear();
- progress.value = 0;
- if (opts.throttle && import.meta.client) {
- _throttle = setTimeout(() => {
- isLoading.value = true;
- _startTimer();
- }, opts.throttle);
- } else {
- isLoading.value = true;
- _startTimer();
- }
- }
- function finish() {
- progress.value = 100;
- _hide();
- }
+ function start() {
+ clear()
+ progress.value = 0
+ if (opts.throttle && import.meta.client) {
+ _throttle = setTimeout(() => {
+ isLoading.value = true
+ _startTimer()
+ }, opts.throttle)
+ } else {
+ isLoading.value = true
+ _startTimer()
+ }
+ }
+ function finish() {
+ progress.value = 100
+ _hide()
+ }
- function clear() {
- clearInterval(_timer);
- clearTimeout(_throttle);
- _timer = null;
- _throttle = null;
- }
+ function clear() {
+ clearInterval(_timer)
+ clearTimeout(_throttle)
+ _timer = null
+ _throttle = null
+ }
- function _increase(num: number) {
- progress.value = Math.min(100, progress.value + num);
- }
+ function _increase(num: number) {
+ progress.value = Math.min(100, progress.value + num)
+ }
- function _hide() {
- clear();
- if (import.meta.client) {
- setTimeout(() => {
- isLoading.value = false;
- setTimeout(() => {
- progress.value = 0;
- }, 400);
- }, 500);
- }
- }
+ function _hide() {
+ clear()
+ if (import.meta.client) {
+ setTimeout(() => {
+ isLoading.value = false
+ setTimeout(() => {
+ progress.value = 0
+ }, 400)
+ }, 500)
+ }
+ }
- function _startTimer() {
- if (import.meta.client) {
- _timer = setInterval(() => {
- _increase(step.value);
- }, 100);
- }
- }
+ function _startTimer() {
+ if (import.meta.client) {
+ _timer = setInterval(() => {
+ _increase(step.value)
+ }, 100)
+ }
+ }
- return {
- progress,
- isLoading,
- start,
- finish,
- clear,
- };
+ return {
+ progress,
+ isLoading,
+ start,
+ finish,
+ clear,
+ }
}
diff --git a/apps/frontend/src/components/ui/news/LatestNewsRow.vue b/apps/frontend/src/components/ui/news/LatestNewsRow.vue
index 198c5564..0a8305e4 100644
--- a/apps/frontend/src/components/ui/news/LatestNewsRow.vue
+++ b/apps/frontend/src/components/ui/news/LatestNewsRow.vue
@@ -1,49 +1,49 @@
-
-
-
-
+
+
+
+
-
-
-
-
-
- View all news
-
-
-
-
+
+
+
+
+
+ View all news
+
+
+
+
diff --git a/apps/frontend/src/components/ui/report/ReportInfo.vue b/apps/frontend/src/components/ui/report/ReportInfo.vue
index 74bdfd0d..c81fb4ea 100644
--- a/apps/frontend/src/components/ui/report/ReportInfo.vue
+++ b/apps/frontend/src/components/ui/report/ReportInfo.vue
@@ -1,211 +1,212 @@
-
-
-
-
-
- {{ report.project.title }}
- {{
- formatProjectType(
- getProjectTypeForUrl(report.project.project_type, report.project.loaders),
- )
- }}
-
-
-
-
-
-
-
- {{ report.user.username }}
- User
-
-
-
-
-
-
-
Reported user not found:
-
-
-
-
-
-
-
- {{ report.version.name }}
-
- of
-
-
-
- {{ report.project.title }}
- {{
- formatProjectType(
- getProjectTypeForUrl(report.project.project_type, report.project.loaders),
- )
- }}
-
-
-
-
-
-
-
-
Unknown report type: {{ report.item_type }}
-
-
-
-
-
-
-
-
-
- Reported by
-
you
-
-
- {{ report.reporterUser.username }}
-
-
-
{{
- formatRelativeTime(report.created)
- }}
-
-
-
+
+
+
+
+
+ {{ report.project.title }}
+ {{
+ formatProjectType(
+ getProjectTypeForUrl(report.project.project_type, report.project.loaders),
+ )
+ }}
+
+
+
+
+
+
+
+ {{ report.user.username }}
+ User
+
+
+
+
+
+
+
Reported user not found:
+
+
+
+
+
+
+
+ {{ report.version.name }}
+
+ of
+
+
+
+ {{ report.project.title }}
+ {{
+ formatProjectType(
+ getProjectTypeForUrl(report.project.project_type, report.project.loaders),
+ )
+ }}
+
+
+
+
+
+
+
+
Unknown report type: {{ report.item_type }}
+
+
+
+
+
+
+
+
+
+ Reported by
+
you
+
+
+ {{ report.reporterUser.username }}
+
+
+
{{
+ formatRelativeTime(report.created)
+ }}
+
+
+
diff --git a/apps/frontend/src/components/ui/report/ReportView.vue b/apps/frontend/src/components/ui/report/ReportView.vue
index ce3c2eb6..67594cbb 100644
--- a/apps/frontend/src/components/ui/report/ReportView.vue
+++ b/apps/frontend/src/components/ui/report/ReportView.vue
@@ -1,119 +1,119 @@
-
-
-
-
+
+
+
+
diff --git a/apps/frontend/src/components/ui/report/ReportsList.vue b/apps/frontend/src/components/ui/report/ReportsList.vue
index 09e1f4f8..d0e97403 100644
--- a/apps/frontend/src/components/ui/report/ReportsList.vue
+++ b/apps/frontend/src/components/ui/report/ReportsList.vue
@@ -1,96 +1,121 @@
-
- You don't have any active reports.
+
+
+
+ There are at least {{ MAX_REPORTS }} open reports. This page is at its max reports and will
+ not show any more recent ones.
+
+ There are {{ filteredReports.length }} open reports.
+
+ There are {{ filteredReports.length }}/{{ reports.length }} open '{{ reasonFilter }}' reports.
+
+
+
+ You don't have any active reports.
diff --git a/apps/frontend/src/components/ui/search/Categories.vue b/apps/frontend/src/components/ui/search/Categories.vue
index 7ef1efaf..814b1b7f 100644
--- a/apps/frontend/src/components/ui/search/Categories.vue
+++ b/apps/frontend/src/components/ui/search/Categories.vue
@@ -1,72 +1,72 @@
-
-
-
-
+
+
+
+
diff --git a/apps/frontend/src/components/ui/search/SearchFilter.vue b/apps/frontend/src/components/ui/search/SearchFilter.vue
index caa5fb02..4f9e6c5e 100644
--- a/apps/frontend/src/components/ui/search/SearchFilter.vue
+++ b/apps/frontend/src/components/ui/search/SearchFilter.vue
@@ -1,77 +1,77 @@
-
-
-
-
-
-
-
{{ displayName }}
-
-
+
+
+
+
+
+
+
{{ displayName }}
+
+
diff --git a/apps/frontend/src/components/ui/servers/BackupCreateModal.vue b/apps/frontend/src/components/ui/servers/BackupCreateModal.vue
index 427142a5..95844d15 100644
--- a/apps/frontend/src/components/ui/servers/BackupCreateModal.vue
+++ b/apps/frontend/src/components/ui/servers/BackupCreateModal.vue
@@ -1,123 +1,126 @@
-
-
-
- Name
-
-
-
-
-
- You already have a backup named '{{ trimmedName }} '
-
-
-
- You're creating backups too fast. Please wait a moment before trying again.
-
-
-
-
-
-
- Create backup
-
-
-
-
-
- Cancel
-
-
-
-
+
+
+
+ Name
+
+
+
+
+
+ You already have a backup named '{{ trimmedName }} '
+
+
+
+ You're creating backups too fast. Please wait a moment before trying again.
+
+
+
+
+
+
+ Create backup
+
+
+
+
+
+ Cancel
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/BackupDeleteModal.vue b/apps/frontend/src/components/ui/servers/BackupDeleteModal.vue
index 35b5bfc7..1b885faf 100644
--- a/apps/frontend/src/components/ui/servers/BackupDeleteModal.vue
+++ b/apps/frontend/src/components/ui/servers/BackupDeleteModal.vue
@@ -1,41 +1,42 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/BackupItem.vue b/apps/frontend/src/components/ui/servers/BackupItem.vue
index de3af15d..b254a8da 100644
--- a/apps/frontend/src/components/ui/servers/BackupItem.vue
+++ b/apps/frontend/src/components/ui/servers/BackupItem.vue
@@ -1,345 +1,345 @@
-
-
-
-
-
-
-
- {{ backup.name }}
-
-
-
- {{ formatMessage(messages.locked) }}
-
- •
-
- {{ formatMessage(messages.automated) }}
-
- •
-
-
- {{
- formatMessage(
- failedToCreate
- ? messages.failedToCreateBackup
- : failedToRestore
- ? messages.failedToRestoreBackup
- : messages.failedToPrepareFile,
- )
- }}
-
-
-
-
-
- {{ formatMessage(messages.queuedForBackup) }}
-
-
{{ formatMessage(messages.creatingBackup) }}
-
-
-
- {{ formatMessage(messages.restoringBackup) }}
-
-
-
-
- {{ dayjs(backup.created_at).format("MMMM D, YYYY [at] h:mm A") }}
-
- {{ 245 }} MiB
-
-
-
-
- emit('retry')">
-
- {{ formatMessage(messages.retry) }}
-
-
-
- emit('delete', true)">
-
- Remove
-
-
-
-
- emit('delete')">
-
- {{ formatMessage(commonMessages.cancelButton) }}
-
-
-
-
- emit('download')"
- >
-
- {{ formatMessage(commonMessages.downloadButton) }}
-
- {
- initiatedPrepare = true;
- emit('prepare');
- }
- "
- >
-
-
- {{
- formatMessage(
- preparingFile
- ? messages.preparingDownload
- : failedToPrepareFile
- ? messages.prepareDownloadAgain
- : messages.prepareDownload,
- )
- }}
-
-
-
-
-
- {{ formatMessage(messages.rename) }}
- {{ formatMessage(messages.restore) }}
-
- {{ formatMessage(messages.unlock) }}
-
- {{ formatMessage(messages.lock) }}
-
- {{ formatMessage(commonMessages.deleteLabel) }}
-
-
-
-
-
-
{{ backup }}
-
+
+
+
+
+
+
+
+ {{ backup.name }}
+
+
+
+ {{ formatMessage(messages.locked) }}
+
+ •
+
+ {{ formatMessage(messages.automated) }}
+
+ •
+
+
+ {{
+ formatMessage(
+ failedToCreate
+ ? messages.failedToCreateBackup
+ : failedToRestore
+ ? messages.failedToRestoreBackup
+ : messages.failedToPrepareFile,
+ )
+ }}
+
+
+
+
+
+ {{ formatMessage(messages.queuedForBackup) }}
+
+
{{ formatMessage(messages.creatingBackup) }}
+
+
+
+ {{ formatMessage(messages.restoringBackup) }}
+
+
+
+
+ {{ dayjs(backup.created_at).format('MMMM D, YYYY [at] h:mm A') }}
+
+ {{ 245 }} MiB
+
+
+
+
+ emit('retry')">
+
+ {{ formatMessage(messages.retry) }}
+
+
+
+ emit('delete', true)">
+
+ Remove
+
+
+
+
+ emit('delete')">
+
+ {{ formatMessage(commonMessages.cancelButton) }}
+
+
+
+
+ emit('download')"
+ >
+
+ {{ formatMessage(commonMessages.downloadButton) }}
+
+ {
+ initiatedPrepare = true
+ emit('prepare')
+ }
+ "
+ >
+
+
+ {{
+ formatMessage(
+ preparingFile
+ ? messages.preparingDownload
+ : failedToPrepareFile
+ ? messages.prepareDownloadAgain
+ : messages.prepareDownload,
+ )
+ }}
+
+
+
+
+
+ {{ formatMessage(messages.rename) }}
+ {{ formatMessage(messages.restore) }}
+
+ {{ formatMessage(messages.unlock) }}
+
+ {{ formatMessage(messages.lock) }}
+
+ {{ formatMessage(commonMessages.deleteLabel) }}
+
+
+
+
+
+
{{ backup }}
+
diff --git a/apps/frontend/src/components/ui/servers/BackupRenameModal.vue b/apps/frontend/src/components/ui/servers/BackupRenameModal.vue
index d5db4ba3..4fe1f614 100644
--- a/apps/frontend/src/components/ui/servers/BackupRenameModal.vue
+++ b/apps/frontend/src/components/ui/servers/BackupRenameModal.vue
@@ -1,141 +1,144 @@
-
-
-
- Name
-
-
-
-
-
- You already have a backup named '{{ trimmedName }} '
-
-
-
-
-
-
-
-
- Renaming...
-
-
-
- Save changes
-
-
-
-
-
-
- Cancel
-
-
-
-
+
+
+
+ Name
+
+
+
+
+
+ You already have a backup named '{{ trimmedName }} '
+
+
+
+
+
+
+
+
+ Renaming...
+
+
+
+ Save changes
+
+
+
+
+
+
+ Cancel
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/BackupRestoreModal.vue b/apps/frontend/src/components/ui/servers/BackupRestoreModal.vue
index b77c5f4c..7e262d04 100644
--- a/apps/frontend/src/components/ui/servers/BackupRestoreModal.vue
+++ b/apps/frontend/src/components/ui/servers/BackupRestoreModal.vue
@@ -1,59 +1,63 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/BackupSettingsModal.vue b/apps/frontend/src/components/ui/servers/BackupSettingsModal.vue
index fe4c32bb..947f59b0 100644
--- a/apps/frontend/src/components/ui/servers/BackupSettingsModal.vue
+++ b/apps/frontend/src/components/ui/servers/BackupSettingsModal.vue
@@ -1,172 +1,172 @@
-
-
-
-
Auto backup
-
- Automatically create a backup of your server
- {{ backupIntervalsLabel.toLowerCase() }}
-
-
+
+
+
+
Auto backup
+
+ Automatically create a backup of your server
+ {{ backupIntervalsLabel.toLowerCase() }}
+
+
-
Loading settings...
-
-
+ Loading settings...
+
+
-
-
Interval
-
- The amount of time between each backup. This will only backup your server if it has been
- modified since the last backup.
-
-
+
+
Interval
+
+ The amount of time between each backup. This will only backup your server if it has been
+ modified since the last backup.
+
+
-
+
-
-
-
-
- {{ isSaving ? "Saving..." : "Save changes" }}
-
-
-
-
-
- Cancel
-
-
-
-
-
-
+
+
+
+
+ {{ isSaving ? 'Saving...' : 'Save changes' }}
+
+
+
+
+
+ Cancel
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/ContentVersionEditModal.vue b/apps/frontend/src/components/ui/servers/ContentVersionEditModal.vue
index d204e7ae..1b37810a 100644
--- a/apps/frontend/src/components/ui/servers/ContentVersionEditModal.vue
+++ b/apps/frontend/src/components/ui/servers/ContentVersionEditModal.vue
@@ -1,532 +1,532 @@
-
-
-
-
-
-
-
-
-
- {{ type }} version
-
-
-
-
-
-
- Show any beta and alpha releases
-
-
-
+
+
+
+
+
+
+
+
+
+ {{ type }} version
+
+
+
+
+
+
+ Show any beta and alpha releases
+
+
+
-
-
-
-
{{ type }} version
-
-
- {{ formattedVersions.game_versions[0] }}
-
-
- {{ formattedVersions.loaders[0] }}
-
-
-
-
-
-
- Show any beta and alpha releases
-
-
+
+
+
+
{{ type }} version
+
+
+ {{ formattedVersions.game_versions[0] }}
+
+
+ {{ formattedVersions.loaders[0] }}
+
+
+
+
+
+
+ Show any beta and alpha releases
+
+
-
-
-
- {{
- noCompatibleVersions
- ? `No compatible versions of this ${type.toLowerCase()} were found`
- : versionFilter
- ? "Game version and platform is provided by the server"
- : "Incompatible game version and platform versions are unlocked"
- }}
-
-
-
- {{
- noCompatibleVersions
- ? `No versions compatible with your server were found. You can still select any available version.`
- : versionFilter
- ? `Unlocking this filter may allow you to change this ${type.toLowerCase()}
+
+
+
+ {{
+ noCompatibleVersions
+ ? `No compatible versions of this ${type.toLowerCase()} were found`
+ : versionFilter
+ ? 'Game version and platform is provided by the server'
+ : 'Incompatible game version and platform versions are unlocked'
+ }}
+
+
+
+ {{
+ noCompatibleVersions
+ ? `No versions compatible with your server were found. You can still select any available version.`
+ : versionFilter
+ ? `Unlocking this filter may allow you to change this ${type.toLowerCase()}
to an incompatible version.`
- : "You might see versions listed that aren't compatible with your server configuration."
- }}
-
-
-
-
-
+ : "You might see versions listed that aren't compatible with your server configuration."
+ }}
+
+
+
+
+
-
- {{
- filtersRef?.selectedPlatforms.length === 0
- ? "All platforms"
- : filtersRef?.selectedPlatforms.map((x) => formatCategory(x)).join(", ")
- }}
-
-
-
-
-
- {{
- filtersRef?.selectedGameVersions.length === 0
- ? "All game versions"
- : filtersRef?.selectedGameVersions.join(", ")
- }}
-
-
-
+
+ {{
+ filtersRef?.selectedPlatforms.length === 0
+ ? 'All platforms'
+ : filtersRef?.selectedPlatforms.map((x) => formatCategory(x)).join(', ')
+ }}
+
+
+
+
+
+ {{
+ filtersRef?.selectedGameVersions.length === 0
+ ? 'All game versions'
+ : filtersRef?.selectedGameVersions.join(', ')
+ }}
+
+
+
-
- {
- versionFilter = !versionFilter;
- setInitialFilters();
- updateFiltersToUi();
- }
- "
- >
-
- {{
- gameVersions.length < 2 && platforms.length < 2
- ? "No other platforms or versions available"
- : versionFilter
- ? "Unlock"
- : "Return to compatibility"
- }}
-
-
-
+
+ {
+ versionFilter = !versionFilter
+ setInitialFilters()
+ updateFiltersToUi()
+ }
+ "
+ >
+
+ {{
+ gameVersions.length < 2 && platforms.length < 2
+ ? 'No other platforms or versions available'
+ : versionFilter
+ ? 'Unlock'
+ : 'Return to compatibility'
+ }}
+
+
+
-
-
-
- Something went wrong trying to load versions for this {{ type.toLocaleLowerCase() }}.
- Please try again later or contact support if the issue persists.
-
-
-
-
+
+
+
+ Something went wrong trying to load versions for this
+ {{ type.toLocaleLowerCase() }}. Please try again later or contact support if the issue
+ persists.
+
+
+
+
-
- Your server was created using a modpack. It's recommended to use the modpack's version of
- the mod.
-
- Modify modpack version
-
-
+
+ Your server was created using a modpack. It's recommended to use the modpack's version of
+ the mod.
+
+ Modify modpack version
+
+
-
-
-
-
- Install
-
-
-
-
-
- Cancel
-
-
-
-
-
+
+
+
+
+ Install
+
+
+
+
+
+ Cancel
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/ContentVersionFilter.vue b/apps/frontend/src/components/ui/servers/ContentVersionFilter.vue
index 9ce8bf85..4e2a503a 100644
--- a/apps/frontend/src/components/ui/servers/ContentVersionFilter.vue
+++ b/apps/frontend/src/components/ui/servers/ContentVersionFilter.vue
@@ -1,171 +1,171 @@
-
-
-
-
- Platform
-
-
- {{ formatCategory(option) }}
-
-
-
-
-
-
-
-
- Game versions
-
-
-
-
-
-
+
+
+
+
+ Platform
+
+
+ {{ formatCategory(option) }}
+
+
+
+
+
+
+
+
+ Game versions
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FileItem.vue b/apps/frontend/src/components/ui/servers/FileItem.vue
index 5889503b..6187d14b 100644
--- a/apps/frontend/src/components/ui/servers/FileItem.vue
+++ b/apps/frontend/src/components/ui/servers/FileItem.vue
@@ -1,412 +1,410 @@
- e.key === 'Enter' && selectItem()"
- @dragstart="handleDragStart"
- @dragend="handleDragEnd"
- @dragenter.prevent="handleDragEnter"
- @dragover.prevent="handleDragOver"
- @dragleave.prevent="handleDragLeave"
- @drop.prevent="handleDrop"
- >
-
-
-
-
-
-
- {{ name }}
-
-
- {{ subText }}
-
-
-
-
-
- {{ formattedCreationDate }}
-
-
- {{ formattedModifiedDate }}
-
-
-
-
- Extract
- Rename
- Move
- Download
- Delete
-
-
-
-
+ e.key === 'Enter' && selectItem()"
+ @dragstart="handleDragStart"
+ @dragend="handleDragEnd"
+ @dragenter.prevent="handleDragEnter"
+ @dragover.prevent="handleDragOver"
+ @dragleave.prevent="handleDragLeave"
+ @drop.prevent="handleDrop"
+ >
+
+
+
+
+
+
+ {{ name }}
+
+
+ {{ subText }}
+
+
+
+
+
+ {{ formattedCreationDate }}
+
+
+ {{ formattedModifiedDate }}
+
+
+
+
+ Extract
+ Rename
+ Move
+ Download
+ Delete
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FileManagerError.vue b/apps/frontend/src/components/ui/servers/FileManagerError.vue
index a15b5f82..682aad50 100644
--- a/apps/frontend/src/components/ui/servers/FileManagerError.vue
+++ b/apps/frontend/src/components/ui/servers/FileManagerError.vue
@@ -1,40 +1,39 @@
-
-
-
-
{{ title }}
-
- {{ message }}
-
-
-
-
-
- Try again
-
-
-
-
-
- Go to home folder
-
-
-
-
-
+
+
+
+
{{ title }}
+
+ {{ message }}
+
+
+
+
+
+ Try again
+
+
+
+
+
+ Go to home folder
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FileVirtualList.vue b/apps/frontend/src/components/ui/servers/FileVirtualList.vue
index ecc38ce7..9025693f 100644
--- a/apps/frontend/src/components/ui/servers/FileVirtualList.vue
+++ b/apps/frontend/src/components/ui/servers/FileVirtualList.vue
@@ -1,121 +1,121 @@
-
-
-
- $emit('contextmenu', item, x, y)"
- />
-
-
-
+
+
+
+ $emit('contextmenu', item, x, y)"
+ />
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesBrowseNavbar.vue b/apps/frontend/src/components/ui/servers/FilesBrowseNavbar.vue
index 5f9f1afe..8d0f61fe 100644
--- a/apps/frontend/src/components/ui/servers/FilesBrowseNavbar.vue
+++ b/apps/frontend/src/components/ui/servers/FilesBrowseNavbar.vue
@@ -1,248 +1,247 @@
-
-
-
-
-
-
-
-
-
- Home
-
-
-
-
-
-
-
-
-
-
-
- {{ segment || "" }}
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ Home
+
+
+
+
+
+
+
+
+
+
+
+ {{ segment || '' }}
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
- {{ filterLabel }}
-
-
-
- Show all
- Files only
- Folders only
-
-
-
-
Search folder
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {{ filterLabel }}
+
+
+
+ Show all
+ Files only
+ Folders only
+
+
+
+
Search folder
+
+
+
+
+
+
-
-
-
-
- New file
- New folder
- Upload file
-
- Upload from .zip file
-
-
- Upload from .zip URL
-
-
- Install CurseForge pack
-
-
-
-
-
+
+
+
+
+ New file
+ New folder
+ Upload file
+
+ Upload from .zip file
+
+
+ Upload from .zip URL
+
+
+ Install CurseForge pack
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesContextMenu.vue b/apps/frontend/src/components/ui/servers/FilesContextMenu.vue
index 8788b763..2a3a5aaa 100644
--- a/apps/frontend/src/components/ui/servers/FilesContextMenu.vue
+++ b/apps/frontend/src/components/ui/servers/FilesContextMenu.vue
@@ -1,106 +1,104 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesCreateItemModal.vue b/apps/frontend/src/components/ui/servers/FilesCreateItemModal.vue
index 21a6ba3d..06931622 100644
--- a/apps/frontend/src/components/ui/servers/FilesCreateItemModal.vue
+++ b/apps/frontend/src/components/ui/servers/FilesCreateItemModal.vue
@@ -1,96 +1,96 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesDeleteItemModal.vue b/apps/frontend/src/components/ui/servers/FilesDeleteItemModal.vue
index f3879a58..2d46e6fc 100644
--- a/apps/frontend/src/components/ui/servers/FilesDeleteItemModal.vue
+++ b/apps/frontend/src/components/ui/servers/FilesDeleteItemModal.vue
@@ -1,77 +1,77 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesEditingNavbar.vue b/apps/frontend/src/components/ui/servers/FilesEditingNavbar.vue
index 2e5e88c1..a852ef1e 100644
--- a/apps/frontend/src/components/ui/servers/FilesEditingNavbar.vue
+++ b/apps/frontend/src/components/ui/servers/FilesEditingNavbar.vue
@@ -1,140 +1,138 @@
-
-
-
-
-
-
-
-
- Home
-
-
-
-
-
-
-
-
-
- {{ segment || "" }}
-
-
-
-
-
- {{
- fileName
- }}
-
-
-
-
-
-
-
-
-
-
-
-
-
- Save
- Save as...
-
-
-
-
- Save & restart
-
-
-
-
-
+
+
+
+
+
+
+
+
+ Home
+
+
+
+
+
+
+
+
+
+ {{ segment || '' }}
+
+
+
+
+
+ {{
+ fileName
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Save
+ Save as...
+
+
+
+
+ Save & restart
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesImageViewer.vue b/apps/frontend/src/components/ui/servers/FilesImageViewer.vue
index 9eb752d5..e88cd839 100644
--- a/apps/frontend/src/components/ui/servers/FilesImageViewer.vue
+++ b/apps/frontend/src/components/ui/servers/FilesImageViewer.vue
@@ -1,178 +1,178 @@
-
-
-
-
-
-
{{ state.errorMessage || "Invalid or empty image file." }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ Math.round(state.scale * 100) }}%
- Reset
-
-
-
-
+
+
+
+
+
+
{{ state.errorMessage || 'Invalid or empty image file.' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ Math.round(state.scale * 100) }}%
+ Reset
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesLabelBar.vue b/apps/frontend/src/components/ui/servers/FilesLabelBar.vue
index efbfcc00..717888cb 100644
--- a/apps/frontend/src/components/ui/servers/FilesLabelBar.vue
+++ b/apps/frontend/src/components/ui/servers/FilesLabelBar.vue
@@ -1,65 +1,65 @@
-
-
-
- Name
-
-
-
-
-
- Created
-
-
-
-
- Modified
-
-
-
-
-
-
+
+
+
+ Name
+
+
+
+
+
+ Created
+
+
+
+
+ Modified
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesMoveItemModal.vue b/apps/frontend/src/components/ui/servers/FilesMoveItemModal.vue
index 9ca1a802..0183adc7 100644
--- a/apps/frontend/src/components/ui/servers/FilesMoveItemModal.vue
+++ b/apps/frontend/src/components/ui/servers/FilesMoveItemModal.vue
@@ -1,82 +1,82 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesRenameItemModal.vue b/apps/frontend/src/components/ui/servers/FilesRenameItemModal.vue
index de6657dd..8a3fd8d0 100644
--- a/apps/frontend/src/components/ui/servers/FilesRenameItemModal.vue
+++ b/apps/frontend/src/components/ui/servers/FilesRenameItemModal.vue
@@ -1,94 +1,94 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesUploadConflictModal.vue b/apps/frontend/src/components/ui/servers/FilesUploadConflictModal.vue
index ab4dfc51..b655d29d 100644
--- a/apps/frontend/src/components/ui/servers/FilesUploadConflictModal.vue
+++ b/apps/frontend/src/components/ui/servers/FilesUploadConflictModal.vue
@@ -1,56 +1,56 @@
-
-
-
-
- Over 100 files will be overwritten if you proceed with extraction; here is just some of
- them:
-
-
- The following {{ files.length }} files already exist on your server, and will be
- overwritten if you proceed with extraction:
-
-
-
-
-
+
+
+
+
+ Over 100 files will be overwritten if you proceed with extraction; here is just some of
+ them:
+
+
+ The following {{ files.length }} files already exist on your server, and will be
+ overwritten if you proceed with extraction:
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesUploadDragAndDrop.vue b/apps/frontend/src/components/ui/servers/FilesUploadDragAndDrop.vue
index 68fd5c92..918b9fc3 100644
--- a/apps/frontend/src/components/ui/servers/FilesUploadDragAndDrop.vue
+++ b/apps/frontend/src/components/ui/servers/FilesUploadDragAndDrop.vue
@@ -1,75 +1,75 @@
-
-
-
-
-
-
- Drop {{ type ? type.toLocaleLowerCase() : "file" }}s here to upload
-
-
-
-
+
+
+
+
+
+
+ Drop {{ type ? type.toLocaleLowerCase() : 'file' }}s here to upload
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesUploadDropdown.vue b/apps/frontend/src/components/ui/servers/FilesUploadDropdown.vue
index 001b6624..8edf5f6a 100644
--- a/apps/frontend/src/components/ui/servers/FilesUploadDropdown.vue
+++ b/apps/frontend/src/components/ui/servers/FilesUploadDropdown.vue
@@ -1,333 +1,335 @@
-
-
-
-
-
-
-
-
-
- {{ props.fileType ? props.fileType : "File" }} uploads
-
- {{ activeUploads.length > 0 ? ` - ${activeUploads.length} left` : "" }}
-
-
-
+
+
+
+
+
+
+
+
+
+ {{ props.fileType ? props.fileType : 'File' }} uploads
+
+ {{ activeUploads.length > 0 ? ` - ${activeUploads.length} left` : '' }}
+
+
+
-
-
-
-
-
-
-
-
- {{ item.file.name }}
- {{ item.size }}
-
-
-
- Done
-
-
- Failed - File already exists
-
-
- Failed - {{ item.error?.message || "An unexpected error occured." }}
-
-
- Failed - Incorrect file type
-
-
-
- {{ item.progress }}%
-
-
- Cancel
-
-
-
- Cancelled
-
-
- {{ item.progress }}%
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ {{ item.file.name }}
+ {{ item.size }}
+
+
+
+ Done
+
+
+ Failed - File already exists
+
+
+ Failed - {{ item.error?.message || 'An unexpected error occured.' }}
+
+
+ Failed - Incorrect file type
+
+
+
+ {{ item.progress }}%
+
+
+ Cancel
+
+
+
+ Cancelled
+
+
+ {{ item.progress }}%
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/FilesUploadZipUrlModal.vue b/apps/frontend/src/components/ui/servers/FilesUploadZipUrlModal.vue
index 88a72958..9ac96845 100644
--- a/apps/frontend/src/components/ui/servers/FilesUploadZipUrlModal.vue
+++ b/apps/frontend/src/components/ui/servers/FilesUploadZipUrlModal.vue
@@ -1,154 +1,159 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/Globe.vue b/apps/frontend/src/components/ui/servers/Globe.vue
index 56c9b826..969cf9e9 100644
--- a/apps/frontend/src/components/ui/servers/Globe.vue
+++ b/apps/frontend/src/components/ui/servers/Globe.vue
@@ -1,134 +1,134 @@
-
+
diff --git a/apps/frontend/src/components/ui/servers/InstallingTicker.vue b/apps/frontend/src/components/ui/servers/InstallingTicker.vue
index d248d2e1..5d43a284 100644
--- a/apps/frontend/src/components/ui/servers/InstallingTicker.vue
+++ b/apps/frontend/src/components/ui/servers/InstallingTicker.vue
@@ -1,76 +1,76 @@
-
+
diff --git a/apps/frontend/src/components/ui/servers/LoaderSelector.vue b/apps/frontend/src/components/ui/servers/LoaderSelector.vue
index b5f52655..3673b0fa 100644
--- a/apps/frontend/src/components/ui/servers/LoaderSelector.vue
+++ b/apps/frontend/src/components/ui/servers/LoaderSelector.vue
@@ -1,95 +1,95 @@
-
+
-
+
-
+
diff --git a/apps/frontend/src/components/ui/servers/LoaderSelectorCard.vue b/apps/frontend/src/components/ui/servers/LoaderSelectorCard.vue
index c9e8a8aa..0d9537b7 100644
--- a/apps/frontend/src/components/ui/servers/LoaderSelectorCard.vue
+++ b/apps/frontend/src/components/ui/servers/LoaderSelectorCard.vue
@@ -1,71 +1,71 @@
-
-
-
-
-
-
-
-
- {{ loader.displayName }}
-
-
-
- Current
-
-
-
- {{ loaderVersion }}
-
-
-
+
+
+
+
+
+
+
+
+ {{ loader.displayName }}
+
+
+
+ Current
+
+
+
+ {{ loaderVersion }}
+
+
+
-
-
-
- {{ isCurrentLoader ? "Reinstall" : "Install" }}
-
-
-
+
+
+
+ {{ isCurrentLoader ? 'Reinstall' : 'Install' }}
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/LogLine.vue b/apps/frontend/src/components/ui/servers/LogLine.vue
index 1e8f4e02..07df871a 100644
--- a/apps/frontend/src/components/ui/servers/LogLine.vue
+++ b/apps/frontend/src/components/ui/servers/LogLine.vue
@@ -1,91 +1,91 @@
-
+
diff --git a/apps/frontend/src/components/ui/servers/ModrinthServersIcon.vue b/apps/frontend/src/components/ui/servers/ModrinthServersIcon.vue
index ea883278..93f7d9b1 100644
--- a/apps/frontend/src/components/ui/servers/ModrinthServersIcon.vue
+++ b/apps/frontend/src/components/ui/servers/ModrinthServersIcon.vue
@@ -1,53 +1,53 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/PanelServerActionButton.vue b/apps/frontend/src/components/ui/servers/PanelServerActionButton.vue
index 8b1632cd..07e625ef 100644
--- a/apps/frontend/src/components/ui/servers/PanelServerActionButton.vue
+++ b/apps/frontend/src/components/ui/servers/PanelServerActionButton.vue
@@ -1,291 +1,291 @@
-
-
-
-
- Are you sure you want to {{ confirmActionText }} the
- server?
-
-
-
-
-
-
- {{ confirmActionText }} server
-
-
-
-
-
- Cancel
-
-
-
-
-
+
+
+
+
+ Are you sure you want to
+ {{ confirmActionText }} the server?
+
+
+
+
+
+
+ {{ confirmActionText }} server
+
+
+
+
+
+ Cancel
+
+
+
+
+
-
-
-
-
- Close
-
-
+
+
+
+
+ Close
+
+
-
-
-
- Installing...
-
-
+
+
+
+ Installing...
+
+
-
-
-
-
-
- {{ isStoppingState ? "Stopping..." : "Stop" }}
-
-
-
+
+
+
+
+
+ {{ isStoppingState ? 'Stopping...' : 'Stop' }}
+
+
+
-
-
-
-
-
-
- {{ primaryActionText }}
-
-
+
+
+
+
+
+
+ {{ primaryActionText }}
+
+
-
-
-
-
-
- Kill server
-
-
-
- All servers
-
-
-
- Details
-
-
-
- Copy ID
-
-
-
-
-
-
+
+
+
+
+
+ Kill server
+
+
+
+ All servers
+
+
+
+ Details
+
+
+
+ Copy ID
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/PanelServerStatus.vue b/apps/frontend/src/components/ui/servers/PanelServerStatus.vue
index fb7a1fcf..f5b42fa0 100644
--- a/apps/frontend/src/components/ui/servers/PanelServerStatus.vue
+++ b/apps/frontend/src/components/ui/servers/PanelServerStatus.vue
@@ -1,75 +1,75 @@
-
-
-
-
-
- {{ getStatusText(state) }}
-
-
-
+
+
+
+
+
+ {{ getStatusText(state) }}
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/PanelSpinner.vue b/apps/frontend/src/components/ui/servers/PanelSpinner.vue
index d9b5721d..c2c7f55e 100644
--- a/apps/frontend/src/components/ui/servers/PanelSpinner.vue
+++ b/apps/frontend/src/components/ui/servers/PanelSpinner.vue
@@ -1,22 +1,22 @@
-
-
-
-
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/PanelTerminal.vue b/apps/frontend/src/components/ui/servers/PanelTerminal.vue
index d3c7c457..1ab98c11 100644
--- a/apps/frontend/src/components/ui/servers/PanelTerminal.vue
+++ b/apps/frontend/src/components/ui/servers/PanelTerminal.vue
@@ -1,1409 +1,1409 @@
-
-
-
-
-
-
-
-
-
-
-
- {{ pyroConsole.filteredOutput.value.length }}
- {{ pyroConsole.filteredOutput.value.length === 1 ? "result" : "results" }}
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ {{ pyroConsole.filteredOutput.value.length }}
+ {{ pyroConsole.filteredOutput.value.length === 1 ? 'result' : 'results' }}
+
+
+
+
+
+
+
+
+
-
handleListScroll()"
- >
-
-
-
-
-
-
-
-
- jumpToLine(item)"
- >
-
- Jump
-
-
-
-
-
-
-
-
-
- {{
- shouldShowSeparator(
- visibleStartIndex + index,
- visibleStartIndex + index + 1,
- )
- }}
- line{{
- shouldShowSeparator(
- visibleStartIndex + index,
- visibleStartIndex + index + 1,
- ) === 1
- ? ""
- : "s"
- }}
- between
-
-
-
-
-
-
-
-
-
+ }"
+ />
+
+
+
handleListScroll()"
+ >
+
+
+
+
+
+
+
+
+ jumpToLine(item)"
+ >
+
+ Jump
+
+
+
+
+
+
+
+
+
+ {{
+ shouldShowSeparator(
+ visibleStartIndex + index,
+ visibleStartIndex + index + 1,
+ )
+ }}
+ line{{
+ shouldShowSeparator(
+ visibleStartIndex + index,
+ visibleStartIndex + index + 1,
+ ) === 1
+ ? ''
+ : 's'
+ }}
+ between
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
- Copy
-
-
-
-
- View
-
-
-
-
+
+
+
+
+ Copy
+
+
+
+
+ View
+
+
+
+
-
-
-
- Scroll to bottom
-
-
-
-
-
-
-
+
+
+
+ Scroll to bottom
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/PlatformChangeModpackVersionModal.vue b/apps/frontend/src/components/ui/servers/PlatformChangeModpackVersionModal.vue
index 853b83c6..3005cb3d 100644
--- a/apps/frontend/src/components/ui/servers/PlatformChangeModpackVersionModal.vue
+++ b/apps/frontend/src/components/ui/servers/PlatformChangeModpackVersionModal.vue
@@ -1,164 +1,165 @@
-
-
-
-
- Select the version of {{ props.project?.title || "the modpack" }} you want to install on
- your server.
-
-
- Currently installed: {{ props.currentVersion.version_number }}
-
-
+
+
+
+
+ Select the version of {{ props.project?.title || 'the modpack' }} you want to install on
+ your server.
+
+
+ Currently installed: {{ props.currentVersion.version_number }}
+
+
-
-
+
+
-
-
-
- Erase all data
-
-
-
-
- If enabled, existing mods, worlds, and configurations, will be deleted before installing
- the new modpack version.
-
-
+
+
+
+ Erase all data
+
+
+
+
+ If enabled, existing mods, worlds, and configurations, will be deleted before installing
+ the new modpack version.
+
+
-
-
-
-
- {{ isLoading ? "Installing..." : hardReset ? "Erase and install" : "Install" }}
-
-
-
-
-
- Cancel
-
-
-
-
-
-
+
+
+
+
+ {{ isLoading ? 'Installing...' : hardReset ? 'Erase and install' : 'Install' }}
+
+
+
+
+
+ Cancel
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/PlatformMrpackModal.vue b/apps/frontend/src/components/ui/servers/PlatformMrpackModal.vue
index a9810f4f..691508b2 100644
--- a/apps/frontend/src/components/ui/servers/PlatformMrpackModal.vue
+++ b/apps/frontend/src/components/ui/servers/PlatformMrpackModal.vue
@@ -1,362 +1,362 @@
-
-
-
-
-
-
- {{
- currentPhrase
- }}
-
-
- {{ Math.round(uploadProgress) }}%
- {{ formatBytes(uploadedBytes) }} / {{ formatBytes(totalBytes) }}
-
-
-
-
-
+
+
+
+
+
+
+ {{
+ currentPhrase
+ }}
+
+
+ {{ Math.round(uploadProgress) }}%
+ {{ formatBytes(uploadedBytes) }} / {{ formatBytes(totalBytes) }}
+
+
+
+
+
-
-
-
- This will reinstall your server and erase all data. You may want to back up your server
- before proceeding. Are you sure you want to continue?
-
-
-
-
+
+
+
+ This will reinstall your server and erase all data. You may want to back up your server
+ before proceeding. Are you sure you want to continue?
+
+
+
+
-
-
-
- Erase all data
-
-
-
-
- Removes all data on your server, including your worlds, mods, and configuration
- files, then reinstalls it with the selected version.
-
-
- This does not affect your backups, which are stored off-site.
-
-
+
+
+
+ Erase all data
+
+
+
+
+ Removes all data on your server, including your worlds, mods, and configuration
+ files, then reinstalls it with the selected version.
+
+
+ This does not affect your backups, which are stored off-site.
+
+
-
-
-
-
-
-
- {{
- isMrpackModalSecondPhase
- ? "Erase and install"
- : loadingServerCheck
- ? "Loading..."
- : isDangerous
- ? "Erase and install"
- : "Install"
- }}
-
-
-
- {
- if (isMrpackModalSecondPhase) {
- isMrpackModalSecondPhase = false;
- } else {
- hide();
- }
- }
- "
- >
-
- {{ isMrpackModalSecondPhase ? "Go back" : "Cancel" }}
-
-
-
-
-
-
-
+
+
+
+
+
+
+ {{
+ isMrpackModalSecondPhase
+ ? 'Erase and install'
+ : loadingServerCheck
+ ? 'Loading...'
+ : isDangerous
+ ? 'Erase and install'
+ : 'Install'
+ }}
+
+
+
+ {
+ if (isMrpackModalSecondPhase) {
+ isMrpackModalSecondPhase = false
+ } else {
+ hide()
+ }
+ }
+ "
+ >
+
+ {{ isMrpackModalSecondPhase ? 'Go back' : 'Cancel' }}
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/PlatformVersionSelectModal.vue b/apps/frontend/src/components/ui/servers/PlatformVersionSelectModal.vue
index 1ed8a614..06c248b7 100644
--- a/apps/frontend/src/components/ui/servers/PlatformVersionSelectModal.vue
+++ b/apps/frontend/src/components/ui/servers/PlatformVersionSelectModal.vue
@@ -1,532 +1,537 @@
-
-
-
- {{
- "This will reinstall your server and erase all data. Are you sure you want to continue?"
- }}
-
-
-
+ "
+ @hide="onHide"
+ @show="onShow"
+ >
+
+
+ {{
+ 'This will reinstall your server and erase all data. Are you sure you want to continue?'
+ }}
+
+
+
-
-
Minecraft version
-
-
-
Show snapshot versions
-
-
-
-
-
+
+
Minecraft version
+
+
+
Show snapshot versions
+
+
+
+
+
-
-
-
{{ selectedLoader }} version
+
+
+
{{ selectedLoader }} version
-
-
- Select a Minecraft version to see available versions
-
-
-
-
-
-
- Loading versions...
-
-
-
-
-
-
-
- No versions available for Minecraft {{ selectedMCVersion }}.
-
-
-
+
+
+ Select a Minecraft version to see available versions
+
+
+
+
+
+
+ Loading versions...
+
+
+
+
+
+
+
+ No versions available for Minecraft {{ selectedMCVersion }}.
+
+
+
-
-
-
- Erase all data
-
-
-
-
- Removes all data on your server, including your worlds, mods, and configuration files,
- then reinstalls it with the selected version.
-
-
This does not affect your backups, which are stored off-site.
-
+
+
+
+ Erase all data
+
+
+
+
+ Removes all data on your server, including your worlds, mods, and configuration files,
+ then reinstalls it with the selected version.
+
+
This does not affect your backups, which are stored off-site.
+
-
-
+
+
-
-
-
-
- {{
- isLoading
- ? "Installing..."
- : isSecondPhase
- ? "Erase and install"
- : hardReset
- ? "Continue"
- : "Install"
- }}
-
-
-
- {
- if (isSecondPhase) {
- isSecondPhase = false;
- } else {
- hide();
- }
- }
- "
- >
-
- {{ isSecondPhase ? "Go back" : "Cancel" }}
-
-
-
-
-
+
+
+
+
+ {{
+ isLoading
+ ? 'Installing...'
+ : isSecondPhase
+ ? 'Erase and install'
+ : hardReset
+ ? 'Continue'
+ : 'Install'
+ }}
+
+
+
+ {
+ if (isSecondPhase) {
+ isSecondPhase = false
+ } else {
+ hide()
+ }
+ }
+ "
+ >
+
+ {{ isSecondPhase ? 'Go back' : 'Cancel' }}
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/SaveBanner.vue b/apps/frontend/src/components/ui/servers/SaveBanner.vue
index 13835f39..91f73f91 100644
--- a/apps/frontend/src/components/ui/servers/SaveBanner.vue
+++ b/apps/frontend/src/components/ui/servers/SaveBanner.vue
@@ -1,75 +1,76 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/ServerGameLabel.vue b/apps/frontend/src/components/ui/servers/ServerGameLabel.vue
index 6c7fd043..1ad02268 100644
--- a/apps/frontend/src/components/ui/servers/ServerGameLabel.vue
+++ b/apps/frontend/src/components/ui/servers/ServerGameLabel.vue
@@ -1,39 +1,39 @@
-
-
-
-
- {{ game[0].toUpperCase() + game.slice(1) }}
- {{ mcVersion }}
-
-
-
-
- {{ game[0].toUpperCase() + game.slice(1) }}
- {{ mcVersion }}
-
-
-
+
+
+
+
+ {{ game[0].toUpperCase() + game.slice(1) }}
+ {{ mcVersion }}
+
+
+
+
+ {{ game[0].toUpperCase() + game.slice(1) }}
+ {{ mcVersion }}
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/ServerIcon.vue b/apps/frontend/src/components/ui/servers/ServerIcon.vue
index 9e8d00b2..9cc7132b 100644
--- a/apps/frontend/src/components/ui/servers/ServerIcon.vue
+++ b/apps/frontend/src/components/ui/servers/ServerIcon.vue
@@ -1,26 +1,26 @@
-
+
diff --git a/apps/frontend/src/components/ui/servers/ServerInfoLabels.vue b/apps/frontend/src/components/ui/servers/ServerInfoLabels.vue
index 56f257d3..5c766f45 100644
--- a/apps/frontend/src/components/ui/servers/ServerInfoLabels.vue
+++ b/apps/frontend/src/components/ui/servers/ServerInfoLabels.vue
@@ -1,40 +1,40 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/ServerInstallation.vue b/apps/frontend/src/components/ui/servers/ServerInstallation.vue
index 636e33db..186d3013 100644
--- a/apps/frontend/src/components/ui/servers/ServerInstallation.vue
+++ b/apps/frontend/src/components/ui/servers/ServerInstallation.vue
@@ -1,278 +1,279 @@
-
+
-
+
-
+
-
-
-
-
-
-
Modpack
-
- Update available
-
-
-
-
-
- Import .mrpack
-
-
-
-
-
-
-
- Switch modpack
-
-
-
-
- Switch modpack
-
-
-
-
-
-
-
Something went wrong while loading your modpack.
-
- {{ versionsError || currentVersionError }}
-
-
- Retry
-
-
+
+
+
+
+
+
Modpack
+
+ Update available
+
+
+
+
+
+ Import .mrpack
+
+
+
+
+
+
+
+ Switch modpack
+
+
+
+
+ Switch modpack
+
+
+
+
+
+
+
Something went wrong while loading your modpack.
+
+ {{ versionsError || currentVersionError }}
+
+
+ Retry
+
+
-
-
-
-
-
- Change version
-
-
-
-
-
-
-
-
- Find a modpack
-
-
- or
-
-
- Upload .mrpack file
-
-
-
-
+
+
+
+
+
+ Change version
+
+
+
+
+
+
+
+
+ Find a modpack
+
+
+ or
+
+
+ Upload .mrpack file
+
+
+
+
-
-
-
Platform
-
Your server's platform is the software that runs mods and plugins.
-
-
-
- The current platform was automatically selected based on your modpack.
-
-
-
-
-
-
-
-
+
+
+
Platform
+
Your server's platform is the software that runs mods and plugins.
+
+
+
+ The current platform was automatically selected based on your modpack.
+
+
+
+
+
+
+
+
-
-
+
+
diff --git a/apps/frontend/src/components/ui/servers/ServerListing.vue b/apps/frontend/src/components/ui/servers/ServerListing.vue
index b8222751..fe9c1edd 100644
--- a/apps/frontend/src/components/ui/servers/ServerListing.vue
+++ b/apps/frontend/src/components/ui/servers/ServerListing.vue
@@ -1,119 +1,137 @@
-
-
+
+
+ Your server's hardware is currently being upgraded and will be back online shortly.
+
+
+
+ Your server has been cancelled. Please
+ update your billing information or contact Modrinth Support for more information.
+
+
+
+
+
+ Your server has been suspended:
+ {{ suspension_reason }}. Please update your billing information or contact Modrinth Support
+ for more information.
+
+
+
+
+
+ Your server has been suspended. Please
+ update your billing information or contact Modrinth Support for more information.
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/ServerListingSkeleton.vue b/apps/frontend/src/components/ui/servers/ServerListingSkeleton.vue
index 8ebe506e..eb7f2faf 100644
--- a/apps/frontend/src/components/ui/servers/ServerListingSkeleton.vue
+++ b/apps/frontend/src/components/ui/servers/ServerListingSkeleton.vue
@@ -1,20 +1,20 @@
-
-
-
-
-
-
-
-
-
Your new server is being prepared.
-
It'll appear here once it's ready.
-
-
+
+
+
+
+
+
+
+
+
Your new server is being prepared.
+
It'll appear here once it's ready.
+
+
diff --git a/apps/frontend/src/components/ui/servers/ServerLoaderLabel.vue b/apps/frontend/src/components/ui/servers/ServerLoaderLabel.vue
index c9920099..0ec2ab5a 100644
--- a/apps/frontend/src/components/ui/servers/ServerLoaderLabel.vue
+++ b/apps/frontend/src/components/ui/servers/ServerLoaderLabel.vue
@@ -1,46 +1,46 @@
-
-
-
-
-
-
-
- {{ loader }}
- {{ loaderVersion }}
-
-
-
-
-
-
-
-
- {{ loader }}
- {{ loaderVersion }}
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {{ loader }}
+ {{ loaderVersion }}
+
+
+
+
+
+
+
+
+ {{ loader }}
+ {{ loaderVersion }}
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/ServerManageEmptyState.vue b/apps/frontend/src/components/ui/servers/ServerManageEmptyState.vue
index dd7cde95..cc2ab2ba 100644
--- a/apps/frontend/src/components/ui/servers/ServerManageEmptyState.vue
+++ b/apps/frontend/src/components/ui/servers/ServerManageEmptyState.vue
@@ -1,19 +1,19 @@
-
-
-
You don't have any servers yet!
-
Modrinth Servers is a new way to play modded Minecraft with your friends.
-
- Create a Server
-
-
+
+
+
You don't have any servers yet!
+
Modrinth Servers is a new way to play modded Minecraft with your friends.
+
+ Create a Server
+
+
diff --git a/apps/frontend/src/components/ui/servers/ServerSidebar.vue b/apps/frontend/src/components/ui/servers/ServerSidebar.vue
index c3edaab6..ee89fbc1 100644
--- a/apps/frontend/src/components/ui/servers/ServerSidebar.vue
+++ b/apps/frontend/src/components/ui/servers/ServerSidebar.vue
@@ -1,52 +1,62 @@
-
-
-
-
-
-
-
- {{ link.label }}
-
+
+
+
+
+
+
+
+ {{ link.label }}
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/ServerStats.vue b/apps/frontend/src/components/ui/servers/ServerStats.vue
index d6b60c1d..600d1c78 100644
--- a/apps/frontend/src/components/ui/servers/ServerStats.vue
+++ b/apps/frontend/src/components/ui/servers/ServerStats.vue
@@ -1,254 +1,256 @@
-
-
-
-
-
-
-
/ {{ metric.max }}
-
-
- {{ metric.title }}
-
-
-
-
-
+
+
+
+
+
+
+
/ {{ metric.max }}
+
+
+ {{ metric.title }}
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
- Storage usage
-
-
-
+
+
+
+
+
+
+
+
+
+
+ Storage usage
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/ServerSubdomainLabel.vue b/apps/frontend/src/components/ui/servers/ServerSubdomainLabel.vue
index d27d44b9..2a0ca5d3 100644
--- a/apps/frontend/src/components/ui/servers/ServerSubdomainLabel.vue
+++ b/apps/frontend/src/components/ui/servers/ServerSubdomainLabel.vue
@@ -1,48 +1,50 @@
-
-
-
-
-
- {{ subdomain }}.modrinth.gg
-
-
-
+
+
+
+
+
+ {{ subdomain }}.modrinth.gg
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/ServerUptimeLabel.vue b/apps/frontend/src/components/ui/servers/ServerUptimeLabel.vue
index f90be664..d7874f47 100644
--- a/apps/frontend/src/components/ui/servers/ServerUptimeLabel.vue
+++ b/apps/frontend/src/components/ui/servers/ServerUptimeLabel.vue
@@ -1,65 +1,65 @@
-
diff --git a/apps/frontend/src/components/ui/servers/TeleportDropdownMenu.vue b/apps/frontend/src/components/ui/servers/TeleportDropdownMenu.vue
index 1eecea3a..33094ed6 100644
--- a/apps/frontend/src/components/ui/servers/TeleportDropdownMenu.vue
+++ b/apps/frontend/src/components/ui/servers/TeleportDropdownMenu.vue
@@ -1,459 +1,458 @@
-
-
- {{ selectedOption }}
-
-
+
+
+ {{ selectedOption }}
+
+
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/TeleportOverflowMenu.vue b/apps/frontend/src/components/ui/servers/TeleportOverflowMenu.vue
index da6ac622..0004115c 100644
--- a/apps/frontend/src/components/ui/servers/TeleportOverflowMenu.vue
+++ b/apps/frontend/src/components/ui/servers/TeleportOverflowMenu.vue
@@ -1,447 +1,447 @@
-
-
-
-
-
-
-
-
-
- {{ option.id }}
-
-
- {{ option.id }}
-
-
- {{ option.id }}
-
-
- {{ option.id }}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ {{ option.id }}
+
+
+ {{ option.id }}
+
+
+ {{ option.id }}
+
+
+ {{ option.id }}
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/ChevronDownIcon.vue b/apps/frontend/src/components/ui/servers/icons/ChevronDownIcon.vue
index 214e3062..783d18a4 100644
--- a/apps/frontend/src/components/ui/servers/icons/ChevronDownIcon.vue
+++ b/apps/frontend/src/components/ui/servers/icons/ChevronDownIcon.vue
@@ -1,16 +1,16 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/ChevronUpIcon.vue b/apps/frontend/src/components/ui/servers/icons/ChevronUpIcon.vue
index 1aeb315c..da6cf408 100644
--- a/apps/frontend/src/components/ui/servers/icons/ChevronUpIcon.vue
+++ b/apps/frontend/src/components/ui/servers/icons/ChevronUpIcon.vue
@@ -1,16 +1,16 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/CodeFileIcon.vue b/apps/frontend/src/components/ui/servers/icons/CodeFileIcon.vue
index 6f7f6000..42022a33 100644
--- a/apps/frontend/src/components/ui/servers/icons/CodeFileIcon.vue
+++ b/apps/frontend/src/components/ui/servers/icons/CodeFileIcon.vue
@@ -1,18 +1,18 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/CogFolderIcon.vue b/apps/frontend/src/components/ui/servers/icons/CogFolderIcon.vue
index f3e65a3f..cc8fc1bc 100644
--- a/apps/frontend/src/components/ui/servers/icons/CogFolderIcon.vue
+++ b/apps/frontend/src/components/ui/servers/icons/CogFolderIcon.vue
@@ -1,26 +1,26 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/EarthIcon.vue b/apps/frontend/src/components/ui/servers/icons/EarthIcon.vue
index 3e617ec8..e96f944b 100644
--- a/apps/frontend/src/components/ui/servers/icons/EarthIcon.vue
+++ b/apps/frontend/src/components/ui/servers/icons/EarthIcon.vue
@@ -1,20 +1,20 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/FullscreenIcon.vue b/apps/frontend/src/components/ui/servers/icons/FullscreenIcon.vue
index c908aeab..383912d2 100644
--- a/apps/frontend/src/components/ui/servers/icons/FullscreenIcon.vue
+++ b/apps/frontend/src/components/ui/servers/icons/FullscreenIcon.vue
@@ -1,19 +1,19 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/ImageFileIcon.vue b/apps/frontend/src/components/ui/servers/icons/ImageFileIcon.vue
index e7287ebf..6aa81c27 100644
--- a/apps/frontend/src/components/ui/servers/icons/ImageFileIcon.vue
+++ b/apps/frontend/src/components/ui/servers/icons/ImageFileIcon.vue
@@ -1,18 +1,18 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/LoaderIcon.vue b/apps/frontend/src/components/ui/servers/icons/LoaderIcon.vue
index 5e53075a..02d0ae05 100644
--- a/apps/frontend/src/components/ui/servers/icons/LoaderIcon.vue
+++ b/apps/frontend/src/components/ui/servers/icons/LoaderIcon.vue
@@ -1,232 +1,232 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/LoadingIcon.vue b/apps/frontend/src/components/ui/servers/icons/LoadingIcon.vue
index c2277f28..9e9a8ad3 100644
--- a/apps/frontend/src/components/ui/servers/icons/LoadingIcon.vue
+++ b/apps/frontend/src/components/ui/servers/icons/LoadingIcon.vue
@@ -1,9 +1,9 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/MinimizeIcon.vue.vue b/apps/frontend/src/components/ui/servers/icons/MinimizeIcon.vue.vue
index 109f532f..27b0fcad 100644
--- a/apps/frontend/src/components/ui/servers/icons/MinimizeIcon.vue.vue
+++ b/apps/frontend/src/components/ui/servers/icons/MinimizeIcon.vue.vue
@@ -1,19 +1,19 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/PanelErrorIcon.vue b/apps/frontend/src/components/ui/servers/icons/PanelErrorIcon.vue
index 0904de9d..2ecad74d 100644
--- a/apps/frontend/src/components/ui/servers/icons/PanelErrorIcon.vue
+++ b/apps/frontend/src/components/ui/servers/icons/PanelErrorIcon.vue
@@ -1,16 +1,16 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/SlashIcon.vue b/apps/frontend/src/components/ui/servers/icons/SlashIcon.vue
index 613ec271..7f6e62fc 100644
--- a/apps/frontend/src/components/ui/servers/icons/SlashIcon.vue
+++ b/apps/frontend/src/components/ui/servers/icons/SlashIcon.vue
@@ -1,10 +1,10 @@
-
-
-
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/TextFileIcon.vue b/apps/frontend/src/components/ui/servers/icons/TextFileIcon.vue
index fb118911..99bcee1a 100644
--- a/apps/frontend/src/components/ui/servers/icons/TextFileIcon.vue
+++ b/apps/frontend/src/components/ui/servers/icons/TextFileIcon.vue
@@ -1,20 +1,20 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/icons/Timer.vue b/apps/frontend/src/components/ui/servers/icons/Timer.vue
index 0de5f7a9..e1ead004 100644
--- a/apps/frontend/src/components/ui/servers/icons/Timer.vue
+++ b/apps/frontend/src/components/ui/servers/icons/Timer.vue
@@ -1,17 +1,17 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/marketing/ServerPlanSelector.vue b/apps/frontend/src/components/ui/servers/marketing/ServerPlanSelector.vue
index c6cd32b1..3cfa1fa9 100644
--- a/apps/frontend/src/components/ui/servers/marketing/ServerPlanSelector.vue
+++ b/apps/frontend/src/components/ui/servers/marketing/ServerPlanSelector.vue
@@ -1,151 +1,151 @@
-
-
+
-
-
-
{{ formatMessage(plans[plan].name) }}
-
- Most popular
-
-
-
- {{ formatPrice(locale, price / billingMonths, currency, true) }}
- {{ isUsa ? "" : currency }}
-
- / month, billed {{ interval }}
-
-
-
{{ formatMessage(plans[plan].description) }}
-
-
- Out of Stock
- emit('select')">Select plan
-
-
emit('scroll-to-faq')"
- />
-
-
+ border: `1px solid rgba(12, 107, 52, 0.55)`,
+ 'box-shadow': `0px 12px 38.1px rgba(27, 217, 106, 0.13)`,
+ }
+ : undefined
+ "
+ class="flex w-full flex-col justify-between gap-4 rounded-2xl bg-bg p-8 text-left"
+ >
+
+
+
{{ formatMessage(plans[plan].name) }}
+
+ Most popular
+
+
+
+ {{ formatPrice(locale, price / billingMonths, currency, true) }}
+ {{ isUsa ? '' : currency }}
+
+ / month, billed {{ interval }}
+
+
+
{{ formatMessage(plans[plan].description) }}
+
+
+ Out of Stock
+ emit('select')">Select plan
+
+
emit('scroll-to-faq')"
+ />
+
+
diff --git a/apps/frontend/src/components/ui/servers/notice/AssignNoticeModal.vue b/apps/frontend/src/components/ui/servers/notice/AssignNoticeModal.vue
index 4b10b7a4..0e255538 100644
--- a/apps/frontend/src/components/ui/servers/notice/AssignNoticeModal.vue
+++ b/apps/frontend/src/components/ui/servers/notice/AssignNoticeModal.vue
@@ -1,208 +1,212 @@
-
-
-
-
-
-
-
-
- Assigned servers
-
-
- {{ assignedServers.length }} servers
-
-
-
- {{ server.id }}
-
-
-
-
No servers assigned yet
+
+
+
+
+
+
+
+
+ Assigned servers
+
+
+ {{ assignedServers.length }} servers
+
+
+
+ {{ server.id }}
+
+
+
+
No servers assigned yet
-
-
- Assigned nodes
-
-
- {{ assignedNodes.length }} nodes
-
-
-
- {{ node.id }}
-
-
-
-
No nodes assigned yet
-
-
-
-
- assign(true)">
-
- Add server
-
-
-
- assign(false)">
-
- Add node
-
-
-
- unassignDetect()">
-
- Remove
-
-
-
-
-
-
+
+
+ Assigned nodes
+
+
+ {{ assignedNodes.length }} nodes
+
+
+
+ {{ node.id }}
+
+
+
+
No nodes assigned yet
+
+
+
+
+ assign(true)">
+
+ Add server
+
+
+
+ assign(false)">
+
+ Add node
+
+
+
+ unassignDetect()">
+
+ Remove
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/servers/notice/NoticeDashboardItem.vue b/apps/frontend/src/components/ui/servers/notice/NoticeDashboardItem.vue
index e76cb723..461ef39f 100644
--- a/apps/frontend/src/components/ui/servers/notice/NoticeDashboardItem.vue
+++ b/apps/frontend/src/components/ui/servers/notice/NoticeDashboardItem.vue
@@ -1,116 +1,124 @@
-
-
-
-
-
-
-
- {{ dayjs(notice.announce_at).format("MMM D, YYYY [at] h:mm A") }} ({{
- formatRelativeTime(notice.announce_at)
- }})
-
- Never begins
-
-
-
- {{ formatRelativeTime(notice.expires) }}
-
- Never expires
-
-
-
- {{
- NOTICE_LEVELS[notice.level]
- ? formatMessage(NOTICE_LEVELS[notice.level].name)
- : notice.level
- }}
-
-
-
-
- {{ formatMessage(getDismissableMetadata(notice.dismissable).name) }}
-
-
-
-
- startEditing(notice)">
- {{ formatMessage(commonMessages.editButton) }}
-
-
-
- deleteNotice(notice)">
- {{ formatMessage(commonMessages.deleteLabel) }}
-
-
-
-
-
-
-
- Not assigned to any servers
-
- Assigned to
- {{ notice.assigned.filter((n) => n.kind === "node").length }} nodes
-
-
- Assigned to
- {{ notice.assigned.filter((n) => n.kind === "server").length }} servers
-
-
- Assigned to
- {{ notice.assigned.filter((n) => n.kind === "server").length }} servers and
- {{ notice.assigned.filter((n) => n.kind === "node").length }} nodes
-
- •
- startEditing(notice, true)"
- >
-
- Edit assignments
-
-
-
-
+
+
+
+
+
+
+
+ {{ dayjs(notice.announce_at).format('MMM D, YYYY [at] h:mm A') }} ({{
+ formatRelativeTime(notice.announce_at)
+ }})
+
+ Never begins
+
+
+
+ {{ formatRelativeTime(notice.expires) }}
+
+ Never expires
+
+
+
+ {{
+ NOTICE_LEVELS[notice.level]
+ ? formatMessage(NOTICE_LEVELS[notice.level].name)
+ : notice.level
+ }}
+
+
+
+
+ {{ formatMessage(getDismissableMetadata(notice.dismissable).name) }}
+
+
+
+
+ startEditing(notice)">
+ {{ formatMessage(commonMessages.editButton) }}
+
+
+
+ deleteNotice(notice)">
+ {{ formatMessage(commonMessages.deleteLabel) }}
+
+
+
+
+
+
+
+ Not assigned to any servers
+
+ Assigned to
+ {{ notice.assigned.filter((n) => n.kind === 'node').length }} nodes
+
+
+ Assigned to
+ {{ notice.assigned.filter((n) => n.kind === 'server').length }} servers
+
+
+ Assigned to
+ {{ notice.assigned.filter((n) => n.kind === 'server').length }} servers and
+ {{ notice.assigned.filter((n) => n.kind === 'node').length }} nodes
+
+ •
+ startEditing(notice, true)"
+ >
+
+ Edit assignments
+
+
+
+
diff --git a/apps/frontend/src/components/ui/thread/ConversationThread.vue b/apps/frontend/src/components/ui/thread/ConversationThread.vue
index 9109822e..7efeb349 100644
--- a/apps/frontend/src/components/ui/thread/ConversationThread.vue
+++ b/apps/frontend/src/components/ui/thread/ConversationThread.vue
@@ -1,475 +1,524 @@
-
-
-
-
- You're submitting {{ project.title }} to be reviewed
- again by the moderators.
-
-
- Make sure you have addressed the comments from the moderation team.
-
- Repeated submissions without addressing the moderators' comments may result in an
- account suspension.
-
-
-
- I confirm that I have properly addressed the moderators' comments.
-
-
-
-
- Resubmit for review
-
-
-
-
-
- Thread ID:
-
-
-
- updateThreadLocal()"
- />
-
-
- This thread is closed and new messages cannot be sent to it.
-
-
- Reopen thread
-
-
-
-
-
-
-
-
-
+
+
+
+
+ You're submitting {{ project.title }} to be reviewed
+ again by the moderators.
+
+
+ Make sure you have addressed the comments from the moderation team.
+
+ Repeated submissions without addressing the moderators' comments may result in an
+ account suspension.
+
+
+
+ I confirm that I have properly addressed the moderators' comments.
+
+
+
+
+ Resubmit for review
+
+
+
+
+
+
+
+ Your project is already approved. As such, the moderation team does not actively monitor
+ this thread. However, they may still see your message if there is a problem with your
+ project.
+
+
+ If you need to get in contact with the moderation team, please use the
+
+ Modrinth Help Center
+
+ and click the green bubble to contact support.
+
+
+ I acknowledge that the moderators do not actively monitor the thread.
+
+
+
+
+ Reply to thread
+
+
+
+
+
+ Thread ID:
+
+
+
+ updateThreadLocal()"
+ />
+
+
+ This thread is closed and new messages cannot be sent to it.
+
+
+ Reopen thread
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/thread/ReportThread.vue b/apps/frontend/src/components/ui/thread/ReportThread.vue
new file mode 100644
index 00000000..7053f8e9
--- /dev/null
+++ b/apps/frontend/src/components/ui/thread/ReportThread.vue
@@ -0,0 +1,286 @@
+
+
+
+ Thread ID:
+
+
+
+
+ updateThreadLocal()"
+ />
+
+
+
+ This thread is closed and new messages cannot be sent to it.
+
+
+
+ Reopen Thread
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reply
+
+
+
+
+
+ Send
+
+
+
+
+
+ Add private note
+ Private note
+
+
+
+
+
+
+
+
+
+ Close with reply
+ Close & reply
+
+
+
+
+
+ Close report
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/frontend/src/components/ui/thread/ThreadMessage.vue b/apps/frontend/src/components/ui/thread/ThreadMessage.vue
index 9d962c98..a599329d 100644
--- a/apps/frontend/src/components/ui/thread/ThreadMessage.vue
+++ b/apps/frontend/src/components/ui/thread/ThreadMessage.vue
@@ -1,335 +1,336 @@
-
-
-
-
-
-
-
-
- {{ members[message.author_id].username }}
-
-
-
-
-
-
-
-
-
-
-
- Moderator
-
-
-
-
-
- posted a message that has been deleted.
-
-
- submitted the project for review.
-
-
- changed the project's status from to
- .
-
-
- closed the thread.
- reopened the thread.
-
-
-
- {{ timeSincePosted }}
-
-
-
-
-
- Delete
-
-
-
+
+
+
+
+
+
+
+
+ {{ members[message.author_id].username }}
+
+
+
+
+
+
+
+
+
+
+
+ Moderator
+
+
+
+
+
+ posted a message that has been deleted.
+
+
+ submitted the project for review.
+
+
+ changed the project's status from to
+ .
+
+
+ closed the thread.
+ reopened the thread.
+
+
+
+ {{ timeSincePosted }}
+
+
+
+
+
+ Delete
+
+
+
diff --git a/apps/frontend/src/components/ui/thread/ThreadSummary.vue b/apps/frontend/src/components/ui/thread/ThreadSummary.vue
index d1192e54..3a348256 100644
--- a/apps/frontend/src/components/ui/thread/ThreadSummary.vue
+++ b/apps/frontend/src/components/ui/thread/ThreadSummary.vue
@@ -1,147 +1,148 @@
-
-
- Report thread
- Thread
- {{ props.thread.messages.length }} messages
-
-
-
-
- There are no messages in this thread yet.
-
+
+
+ Report thread
+ Thread
+ {{ props.thread.messages.length }} messages
+
+
+
+
+ There are no messages in this thread yet.
+
diff --git a/apps/frontend/src/composables/auth.js b/apps/frontend/src/composables/auth.js
index 978a4d84..33e8643c 100644
--- a/apps/frontend/src/composables/auth.js
+++ b/apps/frontend/src/composables/auth.js
@@ -1,140 +1,133 @@
export const useAuth = async (oldToken = null) => {
- const auth = useState("auth", () => ({
- user: null,
- token: "",
- headers: {},
- }));
+ const auth = useState('auth', () => ({
+ user: null,
+ token: '',
+ headers: {},
+ }))
- if (!auth.value.user || oldToken) {
- auth.value = await initAuth(oldToken);
- }
+ if (!auth.value.user || oldToken) {
+ auth.value = await initAuth(oldToken)
+ }
- return auth;
-};
+ return auth
+}
export const initAuth = async (oldToken = null) => {
- const auth = {
- user: null,
- token: "",
- };
+ const auth = {
+ user: null,
+ token: '',
+ }
- if (oldToken === "none") {
- return auth;
- }
+ if (oldToken === 'none') {
+ return auth
+ }
- const route = useRoute();
- const authCookie = useCookie("auth-token", {
- maxAge: 60 * 60 * 24 * 365 * 10,
- sameSite: "lax",
- secure: true,
- httpOnly: false,
- path: "/",
- });
+ const route = useRoute()
+ const authCookie = useCookie('auth-token', {
+ maxAge: 60 * 60 * 24 * 365 * 10,
+ sameSite: 'lax',
+ secure: true,
+ httpOnly: false,
+ path: '/',
+ })
- if (oldToken) {
- authCookie.value = oldToken;
- }
+ if (oldToken) {
+ authCookie.value = oldToken
+ }
- if (route.query.code && !route.fullPath.includes("new_account=true")) {
- authCookie.value = route.query.code;
- }
+ if (route.query.code && !route.fullPath.includes('new_account=true')) {
+ authCookie.value = route.query.code
+ }
- if (route.fullPath.includes("new_account=true") && route.path !== "/auth/welcome") {
- const redirect = route.path.startsWith("/auth/") ? null : route.fullPath;
+ if (route.fullPath.includes('new_account=true') && route.path !== '/auth/welcome') {
+ const redirect = route.path.startsWith('/auth/') ? null : route.fullPath
- await navigateTo(
- `/auth/welcome?authToken=${route.query.code}${
- redirect ? `&redirect=${encodeURIComponent(redirect)}` : ""
- }`,
- );
- }
+ await navigateTo(
+ `/auth/welcome?authToken=${route.query.code}${
+ redirect ? `&redirect=${encodeURIComponent(redirect)}` : ''
+ }`,
+ )
+ }
- if (authCookie.value) {
- auth.token = authCookie.value;
+ if (authCookie.value) {
+ auth.token = authCookie.value
- if (!auth.token || !auth.token.startsWith("mra_")) {
- return auth;
- }
+ if (!auth.token || !auth.token.startsWith('mra_')) {
+ return auth
+ }
- try {
- auth.user = await useBaseFetch(
- "user",
- {
- headers: {
- Authorization: auth.token,
- },
- },
- true,
- );
- } catch {
- /* empty */
- }
- }
+ try {
+ auth.user = await useBaseFetch(
+ 'user',
+ {
+ headers: {
+ Authorization: auth.token,
+ },
+ },
+ true,
+ )
+ } catch {
+ /* empty */
+ }
+ }
- if (!auth.user && auth.token) {
- try {
- const session = await useBaseFetch(
- "session/refresh",
- {
- method: "POST",
- headers: {
- Authorization: auth.token,
- },
- },
- true,
- );
+ if (!auth.user && auth.token) {
+ try {
+ const session = await useBaseFetch(
+ 'session/refresh',
+ {
+ method: 'POST',
+ headers: {
+ Authorization: auth.token,
+ },
+ },
+ true,
+ )
- auth.token = session.session;
- authCookie.value = auth.token;
+ auth.token = session.session
+ authCookie.value = auth.token
- auth.user = await useBaseFetch(
- "user",
- {
- headers: {
- Authorization: auth.token,
- },
- },
- true,
- );
- } catch {
- authCookie.value = null;
- }
- }
+ auth.user = await useBaseFetch(
+ 'user',
+ {
+ headers: {
+ Authorization: auth.token,
+ },
+ },
+ true,
+ )
+ } catch {
+ authCookie.value = null
+ }
+ }
- return auth;
-};
+ return auth
+}
-export const getAuthUrl = (provider, redirect = "/dashboard") => {
- const config = useRuntimeConfig();
- const route = useNativeRoute();
+export const getAuthUrl = (provider, redirect = '/dashboard') => {
+ const config = useRuntimeConfig()
+ const route = useNativeRoute()
- const fullURL = route.query.launcher
- ? "https://launcher-files.modrinth.com"
- : `${config.public.siteUrl}/auth/sign-in?redirect=${redirect}`;
+ const fullURL = route.query.launcher
+ ? 'https://launcher-files.modrinth.com'
+ : `${config.public.siteUrl}/auth/sign-in?redirect=${redirect}`
- return `${config.public.apiBaseUrl}auth/init?provider=${provider}&url=${encodeURIComponent(fullURL)}`;
-};
+ return `${config.public.apiBaseUrl}auth/init?provider=${provider}&url=${encodeURIComponent(fullURL)}`
+}
export const removeAuthProvider = async (provider) => {
- startLoading();
- try {
- const auth = await useAuth();
+ startLoading()
- await useBaseFetch("auth/provider", {
- method: "DELETE",
- body: {
- provider,
- },
- });
- await useAuth(auth.value.token);
- } catch (err) {
- const data = useNuxtApp();
- data.$notify({
- group: "main",
- title: "An error occurred",
- text: err.data.description,
- type: "error",
- });
- }
- stopLoading();
-};
+ const auth = await useAuth()
+
+ await useBaseFetch('auth/provider', {
+ method: 'DELETE',
+ body: {
+ provider,
+ },
+ })
+
+ await useAuth(auth.value.token)
+
+ stopLoading()
+}
diff --git a/apps/frontend/src/composables/auth/scopes.ts b/apps/frontend/src/composables/auth/scopes.ts
index a9c54de0..6db1dd9c 100644
--- a/apps/frontend/src/composables/auth/scopes.ts
+++ b/apps/frontend/src/composables/auth/scopes.ts
@@ -1,678 +1,678 @@
export const scopeMessages = defineMessages({
- userReadEmailLabel: {
- id: "scopes.userReadEmail.label",
- defaultMessage: "Read user email",
- },
- userReadEmailDescription: {
- id: "scopes.userReadEmail.description",
- defaultMessage: "Read your email",
- },
- userReadLabel: {
- id: "scopes.userRead.label",
- defaultMessage: "Read user data",
- },
- userReadDescription: {
- id: "scopes.userRead.description",
- defaultMessage: "Access your public profile information",
- },
- userWriteLabel: {
- id: "scopes.userWrite.label",
- defaultMessage: "Write user data",
- },
- userWriteDescription: {
- id: "scopes.userWrite.description",
- defaultMessage: "Write to your profile",
- },
- userDeleteLabel: {
- id: "scopes.userDelete.label",
- defaultMessage: "Delete your account",
- },
- userDeleteDescription: {
- id: "scopes.userDelete.description",
- defaultMessage: "Delete your account",
- },
- userAuthWriteLabel: {
- id: "scopes.userAuthWrite.label",
- defaultMessage: "Write auth data",
- },
- userAuthWriteDescription: {
- id: "scopes.userAuthWrite.description",
- defaultMessage: "Modify your authentication data",
- },
- notificationReadLabel: {
- id: "scopes.notificationRead.label",
- defaultMessage: "Read notifications",
- },
- notificationReadDescription: {
- id: "scopes.notificationRead.description",
- defaultMessage: "Read your notifications",
- },
- notificationWriteLabel: {
- id: "scopes.notificationWrite.label",
- defaultMessage: "Write notifications",
- },
- notificationWriteDescription: {
- id: "scopes.notificationWrite.description",
- defaultMessage: "Delete/View your notifications",
- },
- payoutsReadLabel: {
- id: "scopes.payoutsRead.label",
- defaultMessage: "Read payouts",
- },
- payoutsReadDescription: {
- id: "scopes.payoutsRead.description",
- defaultMessage: "Read your payouts data",
- },
- payoutsWriteLabel: {
- id: "scopes.payoutsWrite.label",
- defaultMessage: "Write payouts",
- },
- payoutsWriteDescription: {
- id: "scopes.payoutsWrite.description",
- defaultMessage: "Withdraw money",
- },
- analyticsLabel: {
- id: "scopes.analytics.label",
- defaultMessage: "Read analytics",
- },
- analyticsDescription: {
- id: "scopes.analytics.description",
- defaultMessage: "Access your analytics data",
- },
- projectCreateLabel: {
- id: "scopes.projectCreate.label",
- defaultMessage: "Create projects",
- },
- projectCreateDescription: {
- id: "scopes.projectCreate.description",
- defaultMessage: "Create new projects",
- },
- projectReadLabel: {
- id: "scopes.projectRead.label",
- defaultMessage: "Read projects",
- },
- projectReadDescription: {
- id: "scopes.projectRead.description",
- defaultMessage: "Read all your projects",
- },
- projectWriteLabel: {
- id: "scopes.projectWrite.label",
- defaultMessage: "Write projects",
- },
- projectWriteDescription: {
- id: "scopes.projectWrite.description",
- defaultMessage: "Write to project data",
- },
- projectDeleteLabel: {
- id: "scopes.projectDelete.label",
- defaultMessage: "Delete projects",
- },
- projectDeleteDescription: {
- id: "scopes.projectDelete.description",
- defaultMessage: "Delete your projects",
- },
- versionCreateLabel: {
- id: "scopes.versionCreate.label",
- defaultMessage: "Create versions",
- },
- versionCreateDescription: {
- id: "scopes.versionCreate.description",
- defaultMessage: "Create new versions",
- },
- versionReadLabel: {
- id: "scopes.versionRead.label",
- defaultMessage: "Read versions",
- },
- versionReadDescription: {
- id: "scopes.versionRead.description",
- defaultMessage: "Read all versions",
- },
- versionWriteLabel: {
- id: "scopes.versionWrite.label",
- defaultMessage: "Write versions",
- },
- versionWriteDescription: {
- id: "scopes.versionWrite.description",
- defaultMessage: "Write to version data",
- },
- versionDeleteLabel: {
- id: "scopes.versionDelete.label",
- defaultMessage: "Delete versions",
- },
- versionDeleteDescription: {
- id: "scopes.versionDelete.description",
- defaultMessage: "Delete a version",
- },
- reportCreateLabel: {
- id: "scopes.reportCreate.label",
- defaultMessage: "Create reports",
- },
- reportCreateDescription: {
- id: "scopes.reportCreate.description",
- defaultMessage: "Create reports",
- },
- reportReadLabel: {
- id: "scopes.reportRead.label",
- defaultMessage: "Read reports",
- },
- reportReadDescription: {
- id: "scopes.reportRead.description",
- defaultMessage: "Read reports",
- },
- reportWriteLabel: {
- id: "scopes.reportWrite.label",
- defaultMessage: "Write reports",
- },
- reportWriteDescription: {
- id: "scopes.reportWrite.description",
- defaultMessage: "Edit reports",
- },
- reportDeleteLabel: {
- id: "scopes.reportDelete.label",
- defaultMessage: "Delete reports",
- },
- reportDeleteDescription: {
- id: "scopes.reportDelete.description",
- defaultMessage: "Delete reports",
- },
- threadReadLabel: {
- id: "scopes.threadRead.label",
- defaultMessage: "Read threads",
- },
- threadReadDescription: {
- id: "scopes.threadRead.description",
- defaultMessage: "Read threads",
- },
- threadWriteLabel: {
- id: "scopes.threadWrite.label",
- defaultMessage: "Write threads",
- },
- threadWriteDescription: {
- id: "scopes.threadWrite.description",
- defaultMessage: "Write to threads",
- },
- patCreateLabel: {
- id: "scopes.patCreate.label",
- defaultMessage: "Create PATs",
- },
- patCreateDescription: {
- id: "scopes.patCreate.description",
- defaultMessage: "Create personal API tokens",
- },
- patReadLabel: {
- id: "scopes.patRead.label",
- defaultMessage: "Read PATs",
- },
- patReadDescription: {
- id: "scopes.patRead.description",
- defaultMessage: "View created API tokens",
- },
- patWriteLabel: {
- id: "scopes.patWrite.label",
- defaultMessage: "Write PATs",
- },
- patWriteDescription: {
- id: "scopes.patWrite.description",
- defaultMessage: "Edit personal API tokens",
- },
- patDeleteLabel: {
- id: "scopes.patDelete.label",
- defaultMessage: "Delete PATs",
- },
- patDeleteDescription: {
- id: "scopes.patDelete.description",
- defaultMessage: "Delete your personal API tokens",
- },
- sessionReadLabel: {
- id: "scopes.sessionRead.label",
- defaultMessage: "Read sessions",
- },
- sessionReadDescription: {
- id: "scopes.sessionRead.description",
- defaultMessage: "Read active sessions",
- },
- sessionDeleteLabel: {
- id: "scopes.sessionDelete.label",
- defaultMessage: "Delete sessions",
- },
- sessionDeleteDescription: {
- id: "scopes.sessionDelete.description",
- defaultMessage: "Delete sessions",
- },
- performAnalyticsLabel: {
- id: "scopes.performAnalytics.label",
- defaultMessage: "Perform analytics",
- },
- performAnalyticsDescription: {
- id: "scopes.performAnalytics.description",
- defaultMessage: "Perform analytics actions",
- },
- collectionCreateLabel: {
- id: "scopes.collectionCreate.label",
- defaultMessage: "Create collections",
- },
- collectionCreateDescription: {
- id: "scopes.collectionCreate.description",
- defaultMessage: "Create collections",
- },
- collectionReadLabel: {
- id: "scopes.collectionRead.label",
- defaultMessage: "Read collections",
- },
- collectionReadDescription: {
- id: "scopes.collectionRead.description",
- defaultMessage: "Read collections",
- },
- collectionWriteLabel: {
- id: "scopes.collectionWrite.label",
- defaultMessage: "Write collections",
- },
- collectionWriteDescription: {
- id: "scopes.collectionWrite.description",
- defaultMessage: "Write to collections",
- },
- collectionDeleteLabel: {
- id: "scopes.collectionDelete.label",
- defaultMessage: "Delete collections",
- },
- collectionDeleteDescription: {
- id: "scopes.collectionDelete.description",
- defaultMessage: "Delete collections",
- },
- organizationCreateLabel: {
- id: "scopes.organizationCreate.label",
- defaultMessage: "Create organizations",
- },
- organizationCreateDescription: {
- id: "scopes.organizationCreate.description",
- defaultMessage: "Create organizations",
- },
- organizationReadLabel: {
- id: "scopes.organizationRead.label",
- defaultMessage: "Read organizations",
- },
- organizationReadDescription: {
- id: "scopes.organizationRead.description",
- defaultMessage: "Read organizations",
- },
- organizationWriteLabel: {
- id: "scopes.organizationWrite.label",
- defaultMessage: "Write organizations",
- },
- organizationWriteDescription: {
- id: "scopes.organizationWrite.description",
- defaultMessage: "Write to organizations",
- },
- organizationDeleteLabel: {
- id: "scopes.organizationDelete.label",
- defaultMessage: "Delete organizations",
- },
- organizationDeleteDescription: {
- id: "scopes.organizationDelete.description",
- defaultMessage: "Delete organizations",
- },
- sessionAccessLabel: {
- id: "scopes.sessionAccess.label",
- defaultMessage: "Access sessions",
- },
- sessionAccessDescription: {
- id: "scopes.sessionAccess.description",
- defaultMessage: "Access modrinth-issued sessions",
- },
-});
+ userReadEmailLabel: {
+ id: 'scopes.userReadEmail.label',
+ defaultMessage: 'Read user email',
+ },
+ userReadEmailDescription: {
+ id: 'scopes.userReadEmail.description',
+ defaultMessage: 'Read your email',
+ },
+ userReadLabel: {
+ id: 'scopes.userRead.label',
+ defaultMessage: 'Read user data',
+ },
+ userReadDescription: {
+ id: 'scopes.userRead.description',
+ defaultMessage: 'Access your public profile information',
+ },
+ userWriteLabel: {
+ id: 'scopes.userWrite.label',
+ defaultMessage: 'Write user data',
+ },
+ userWriteDescription: {
+ id: 'scopes.userWrite.description',
+ defaultMessage: 'Write to your profile',
+ },
+ userDeleteLabel: {
+ id: 'scopes.userDelete.label',
+ defaultMessage: 'Delete your account',
+ },
+ userDeleteDescription: {
+ id: 'scopes.userDelete.description',
+ defaultMessage: 'Delete your account',
+ },
+ userAuthWriteLabel: {
+ id: 'scopes.userAuthWrite.label',
+ defaultMessage: 'Write auth data',
+ },
+ userAuthWriteDescription: {
+ id: 'scopes.userAuthWrite.description',
+ defaultMessage: 'Modify your authentication data',
+ },
+ notificationReadLabel: {
+ id: 'scopes.notificationRead.label',
+ defaultMessage: 'Read notifications',
+ },
+ notificationReadDescription: {
+ id: 'scopes.notificationRead.description',
+ defaultMessage: 'Read your notifications',
+ },
+ notificationWriteLabel: {
+ id: 'scopes.notificationWrite.label',
+ defaultMessage: 'Write notifications',
+ },
+ notificationWriteDescription: {
+ id: 'scopes.notificationWrite.description',
+ defaultMessage: 'Delete/View your notifications',
+ },
+ payoutsReadLabel: {
+ id: 'scopes.payoutsRead.label',
+ defaultMessage: 'Read payouts',
+ },
+ payoutsReadDescription: {
+ id: 'scopes.payoutsRead.description',
+ defaultMessage: 'Read your payouts data',
+ },
+ payoutsWriteLabel: {
+ id: 'scopes.payoutsWrite.label',
+ defaultMessage: 'Write payouts',
+ },
+ payoutsWriteDescription: {
+ id: 'scopes.payoutsWrite.description',
+ defaultMessage: 'Withdraw money',
+ },
+ analyticsLabel: {
+ id: 'scopes.analytics.label',
+ defaultMessage: 'Read analytics',
+ },
+ analyticsDescription: {
+ id: 'scopes.analytics.description',
+ defaultMessage: 'Access your analytics data',
+ },
+ projectCreateLabel: {
+ id: 'scopes.projectCreate.label',
+ defaultMessage: 'Create projects',
+ },
+ projectCreateDescription: {
+ id: 'scopes.projectCreate.description',
+ defaultMessage: 'Create new projects',
+ },
+ projectReadLabel: {
+ id: 'scopes.projectRead.label',
+ defaultMessage: 'Read projects',
+ },
+ projectReadDescription: {
+ id: 'scopes.projectRead.description',
+ defaultMessage: 'Read all your projects',
+ },
+ projectWriteLabel: {
+ id: 'scopes.projectWrite.label',
+ defaultMessage: 'Write projects',
+ },
+ projectWriteDescription: {
+ id: 'scopes.projectWrite.description',
+ defaultMessage: 'Write to project data',
+ },
+ projectDeleteLabel: {
+ id: 'scopes.projectDelete.label',
+ defaultMessage: 'Delete projects',
+ },
+ projectDeleteDescription: {
+ id: 'scopes.projectDelete.description',
+ defaultMessage: 'Delete your projects',
+ },
+ versionCreateLabel: {
+ id: 'scopes.versionCreate.label',
+ defaultMessage: 'Create versions',
+ },
+ versionCreateDescription: {
+ id: 'scopes.versionCreate.description',
+ defaultMessage: 'Create new versions',
+ },
+ versionReadLabel: {
+ id: 'scopes.versionRead.label',
+ defaultMessage: 'Read versions',
+ },
+ versionReadDescription: {
+ id: 'scopes.versionRead.description',
+ defaultMessage: 'Read all versions',
+ },
+ versionWriteLabel: {
+ id: 'scopes.versionWrite.label',
+ defaultMessage: 'Write versions',
+ },
+ versionWriteDescription: {
+ id: 'scopes.versionWrite.description',
+ defaultMessage: 'Write to version data',
+ },
+ versionDeleteLabel: {
+ id: 'scopes.versionDelete.label',
+ defaultMessage: 'Delete versions',
+ },
+ versionDeleteDescription: {
+ id: 'scopes.versionDelete.description',
+ defaultMessage: 'Delete a version',
+ },
+ reportCreateLabel: {
+ id: 'scopes.reportCreate.label',
+ defaultMessage: 'Create reports',
+ },
+ reportCreateDescription: {
+ id: 'scopes.reportCreate.description',
+ defaultMessage: 'Create reports',
+ },
+ reportReadLabel: {
+ id: 'scopes.reportRead.label',
+ defaultMessage: 'Read reports',
+ },
+ reportReadDescription: {
+ id: 'scopes.reportRead.description',
+ defaultMessage: 'Read reports',
+ },
+ reportWriteLabel: {
+ id: 'scopes.reportWrite.label',
+ defaultMessage: 'Write reports',
+ },
+ reportWriteDescription: {
+ id: 'scopes.reportWrite.description',
+ defaultMessage: 'Edit reports',
+ },
+ reportDeleteLabel: {
+ id: 'scopes.reportDelete.label',
+ defaultMessage: 'Delete reports',
+ },
+ reportDeleteDescription: {
+ id: 'scopes.reportDelete.description',
+ defaultMessage: 'Delete reports',
+ },
+ threadReadLabel: {
+ id: 'scopes.threadRead.label',
+ defaultMessage: 'Read threads',
+ },
+ threadReadDescription: {
+ id: 'scopes.threadRead.description',
+ defaultMessage: 'Read threads',
+ },
+ threadWriteLabel: {
+ id: 'scopes.threadWrite.label',
+ defaultMessage: 'Write threads',
+ },
+ threadWriteDescription: {
+ id: 'scopes.threadWrite.description',
+ defaultMessage: 'Write to threads',
+ },
+ patCreateLabel: {
+ id: 'scopes.patCreate.label',
+ defaultMessage: 'Create PATs',
+ },
+ patCreateDescription: {
+ id: 'scopes.patCreate.description',
+ defaultMessage: 'Create personal API tokens',
+ },
+ patReadLabel: {
+ id: 'scopes.patRead.label',
+ defaultMessage: 'Read PATs',
+ },
+ patReadDescription: {
+ id: 'scopes.patRead.description',
+ defaultMessage: 'View created API tokens',
+ },
+ patWriteLabel: {
+ id: 'scopes.patWrite.label',
+ defaultMessage: 'Write PATs',
+ },
+ patWriteDescription: {
+ id: 'scopes.patWrite.description',
+ defaultMessage: 'Edit personal API tokens',
+ },
+ patDeleteLabel: {
+ id: 'scopes.patDelete.label',
+ defaultMessage: 'Delete PATs',
+ },
+ patDeleteDescription: {
+ id: 'scopes.patDelete.description',
+ defaultMessage: 'Delete your personal API tokens',
+ },
+ sessionReadLabel: {
+ id: 'scopes.sessionRead.label',
+ defaultMessage: 'Read sessions',
+ },
+ sessionReadDescription: {
+ id: 'scopes.sessionRead.description',
+ defaultMessage: 'Read active sessions',
+ },
+ sessionDeleteLabel: {
+ id: 'scopes.sessionDelete.label',
+ defaultMessage: 'Delete sessions',
+ },
+ sessionDeleteDescription: {
+ id: 'scopes.sessionDelete.description',
+ defaultMessage: 'Delete sessions',
+ },
+ performAnalyticsLabel: {
+ id: 'scopes.performAnalytics.label',
+ defaultMessage: 'Perform analytics',
+ },
+ performAnalyticsDescription: {
+ id: 'scopes.performAnalytics.description',
+ defaultMessage: 'Perform analytics actions',
+ },
+ collectionCreateLabel: {
+ id: 'scopes.collectionCreate.label',
+ defaultMessage: 'Create collections',
+ },
+ collectionCreateDescription: {
+ id: 'scopes.collectionCreate.description',
+ defaultMessage: 'Create collections',
+ },
+ collectionReadLabel: {
+ id: 'scopes.collectionRead.label',
+ defaultMessage: 'Read collections',
+ },
+ collectionReadDescription: {
+ id: 'scopes.collectionRead.description',
+ defaultMessage: 'Read collections',
+ },
+ collectionWriteLabel: {
+ id: 'scopes.collectionWrite.label',
+ defaultMessage: 'Write collections',
+ },
+ collectionWriteDescription: {
+ id: 'scopes.collectionWrite.description',
+ defaultMessage: 'Write to collections',
+ },
+ collectionDeleteLabel: {
+ id: 'scopes.collectionDelete.label',
+ defaultMessage: 'Delete collections',
+ },
+ collectionDeleteDescription: {
+ id: 'scopes.collectionDelete.description',
+ defaultMessage: 'Delete collections',
+ },
+ organizationCreateLabel: {
+ id: 'scopes.organizationCreate.label',
+ defaultMessage: 'Create organizations',
+ },
+ organizationCreateDescription: {
+ id: 'scopes.organizationCreate.description',
+ defaultMessage: 'Create organizations',
+ },
+ organizationReadLabel: {
+ id: 'scopes.organizationRead.label',
+ defaultMessage: 'Read organizations',
+ },
+ organizationReadDescription: {
+ id: 'scopes.organizationRead.description',
+ defaultMessage: 'Read organizations',
+ },
+ organizationWriteLabel: {
+ id: 'scopes.organizationWrite.label',
+ defaultMessage: 'Write organizations',
+ },
+ organizationWriteDescription: {
+ id: 'scopes.organizationWrite.description',
+ defaultMessage: 'Write to organizations',
+ },
+ organizationDeleteLabel: {
+ id: 'scopes.organizationDelete.label',
+ defaultMessage: 'Delete organizations',
+ },
+ organizationDeleteDescription: {
+ id: 'scopes.organizationDelete.description',
+ defaultMessage: 'Delete organizations',
+ },
+ sessionAccessLabel: {
+ id: 'scopes.sessionAccess.label',
+ defaultMessage: 'Access sessions',
+ },
+ sessionAccessDescription: {
+ id: 'scopes.sessionAccess.description',
+ defaultMessage: 'Access modrinth-issued sessions',
+ },
+})
const scopeDefinitions = [
- {
- id: "USER_READ_EMAIL",
- value: BigInt(1) << BigInt(0),
- label: scopeMessages.userReadEmailLabel,
- desc: scopeMessages.userReadEmailDescription,
- },
- {
- id: "USER_READ",
- value: BigInt(1) << BigInt(1),
- label: scopeMessages.userReadLabel,
- desc: scopeMessages.userReadDescription,
- },
- {
- id: "USER_WRITE",
- value: BigInt(1) << BigInt(2),
- label: scopeMessages.userWriteLabel,
- desc: scopeMessages.userWriteDescription,
- },
- {
- id: "USER_DELETE",
- value: BigInt(1) << BigInt(3),
- label: scopeMessages.userDeleteLabel,
- desc: scopeMessages.userDeleteDescription,
- },
- {
- id: "USER_AUTH_WRITE",
- value: BigInt(1) << BigInt(4),
- label: scopeMessages.userAuthWriteLabel,
- desc: scopeMessages.userAuthWriteDescription,
- },
- {
- id: "NOTIFICATION_READ",
- value: BigInt(1) << BigInt(5),
- label: scopeMessages.notificationReadLabel,
- desc: scopeMessages.notificationReadDescription,
- },
- {
- id: "NOTIFICATION_WRITE",
- value: BigInt(1) << BigInt(6),
- label: scopeMessages.notificationWriteLabel,
- desc: scopeMessages.notificationWriteDescription,
- },
- {
- id: "PAYOUTS_READ",
- value: BigInt(1) << BigInt(7),
- label: scopeMessages.payoutsReadLabel,
- desc: scopeMessages.payoutsReadDescription,
- },
- {
- id: "PAYOUTS_WRITE",
- value: BigInt(1) << BigInt(8),
- label: scopeMessages.payoutsWriteLabel,
- desc: scopeMessages.payoutsWriteDescription,
- },
- {
- id: "ANALYTICS",
- value: BigInt(1) << BigInt(9),
- label: scopeMessages.analyticsLabel,
- desc: scopeMessages.analyticsDescription,
- },
- {
- id: "PROJECT_CREATE",
- value: BigInt(1) << BigInt(10),
- label: scopeMessages.projectCreateLabel,
- desc: scopeMessages.projectCreateDescription,
- },
- {
- id: "PROJECT_READ",
- value: BigInt(1) << BigInt(11),
- label: scopeMessages.projectReadLabel,
- desc: scopeMessages.projectReadDescription,
- },
- {
- id: "PROJECT_WRITE",
- value: BigInt(1) << BigInt(12),
- label: scopeMessages.projectWriteLabel,
- desc: scopeMessages.projectWriteDescription,
- },
- {
- id: "PROJECT_DELETE",
- value: BigInt(1) << BigInt(13),
- label: scopeMessages.projectDeleteLabel,
- desc: scopeMessages.projectDeleteDescription,
- },
- {
- id: "VERSION_CREATE",
- value: BigInt(1) << BigInt(14),
- label: scopeMessages.versionCreateLabel,
- desc: scopeMessages.versionCreateDescription,
- },
- {
- id: "VERSION_READ",
- value: BigInt(1) << BigInt(15),
- label: scopeMessages.versionReadLabel,
- desc: scopeMessages.versionReadDescription,
- },
- {
- id: "VERSION_WRITE",
- value: BigInt(1) << BigInt(16),
- label: scopeMessages.versionWriteLabel,
- desc: scopeMessages.versionWriteDescription,
- },
- {
- id: "VERSION_DELETE",
- value: BigInt(1) << BigInt(17),
- label: scopeMessages.versionDeleteLabel,
- desc: scopeMessages.versionDeleteDescription,
- },
- {
- id: "REPORT_CREATE",
- value: BigInt(1) << BigInt(18),
- label: scopeMessages.reportCreateLabel,
- desc: scopeMessages.reportCreateDescription,
- },
- {
- id: "REPORT_READ",
- value: BigInt(1) << BigInt(19),
- label: scopeMessages.reportReadLabel,
- desc: scopeMessages.reportReadDescription,
- },
- {
- id: "REPORT_WRITE",
- value: BigInt(1) << BigInt(20),
- label: scopeMessages.reportWriteLabel,
- desc: scopeMessages.reportWriteDescription,
- },
- {
- id: "REPORT_DELETE",
- value: BigInt(1) << BigInt(21),
- label: scopeMessages.reportDeleteLabel,
- desc: scopeMessages.reportDeleteDescription,
- },
- {
- id: "THREAD_READ",
- value: BigInt(1) << BigInt(22),
- label: scopeMessages.threadReadLabel,
- desc: scopeMessages.threadReadDescription,
- },
- {
- id: "THREAD_WRITE",
- value: BigInt(1) << BigInt(23),
- label: scopeMessages.threadWriteLabel,
- desc: scopeMessages.threadWriteDescription,
- },
- {
- id: "PAT_CREATE",
- value: BigInt(1) << BigInt(24),
- label: scopeMessages.patCreateLabel,
- desc: scopeMessages.patCreateDescription,
- },
- {
- id: "PAT_READ",
- value: BigInt(1) << BigInt(25),
- label: scopeMessages.patReadLabel,
- desc: scopeMessages.patReadDescription,
- },
- {
- id: "PAT_WRITE",
- value: BigInt(1) << BigInt(26),
- label: scopeMessages.patWriteLabel,
- desc: scopeMessages.patWriteDescription,
- },
- {
- id: "PAT_DELETE",
- value: BigInt(1) << BigInt(27),
- label: scopeMessages.patDeleteLabel,
- desc: scopeMessages.patDeleteDescription,
- },
- {
- id: "SESSION_READ",
- value: BigInt(1) << BigInt(28),
- label: scopeMessages.sessionReadLabel,
- desc: scopeMessages.sessionReadDescription,
- },
- {
- id: "SESSION_DELETE",
- value: BigInt(1) << BigInt(29),
- label: scopeMessages.sessionDeleteLabel,
- desc: scopeMessages.sessionDeleteDescription,
- },
- {
- id: "PERFORM_ANALYTICS",
- value: BigInt(1) << BigInt(30),
- label: scopeMessages.performAnalyticsLabel,
- desc: scopeMessages.performAnalyticsDescription,
- },
- {
- id: "COLLECTION_CREATE",
- value: BigInt(1) << BigInt(31),
- label: scopeMessages.collectionCreateLabel,
- desc: scopeMessages.collectionCreateDescription,
- },
- {
- id: "COLLECTION_READ",
- value: BigInt(1) << BigInt(32),
- label: scopeMessages.collectionReadLabel,
- desc: scopeMessages.collectionReadDescription,
- },
- {
- id: "COLLECTION_WRITE",
- value: BigInt(1) << BigInt(33),
- label: scopeMessages.collectionWriteLabel,
- desc: scopeMessages.collectionWriteDescription,
- },
- {
- id: "COLLECTION_DELETE",
- value: BigInt(1) << BigInt(34),
- label: scopeMessages.collectionDeleteLabel,
- desc: scopeMessages.collectionDeleteDescription,
- },
- {
- id: "ORGANIZATION_CREATE",
- value: BigInt(1) << BigInt(35),
- label: scopeMessages.organizationCreateLabel,
- desc: scopeMessages.organizationCreateDescription,
- },
- {
- id: "ORGANIZATION_READ",
- value: BigInt(1) << BigInt(36),
- label: scopeMessages.organizationReadLabel,
- desc: scopeMessages.organizationReadDescription,
- },
- {
- id: "ORGANIZATION_WRITE",
- value: BigInt(1) << BigInt(37),
- label: scopeMessages.organizationWriteLabel,
- desc: scopeMessages.organizationWriteDescription,
- },
- {
- id: "ORGANIZATION_DELETE",
- value: BigInt(1) << BigInt(38),
- label: scopeMessages.organizationDeleteLabel,
- desc: scopeMessages.organizationDeleteDescription,
- },
- {
- id: "SESSION_ACCESS",
- value: BigInt(1) << BigInt(39),
- label: scopeMessages.sessionAccessLabel,
- desc: scopeMessages.sessionAccessDescription,
- },
-];
+ {
+ id: 'USER_READ_EMAIL',
+ value: BigInt(1) << BigInt(0),
+ label: scopeMessages.userReadEmailLabel,
+ desc: scopeMessages.userReadEmailDescription,
+ },
+ {
+ id: 'USER_READ',
+ value: BigInt(1) << BigInt(1),
+ label: scopeMessages.userReadLabel,
+ desc: scopeMessages.userReadDescription,
+ },
+ {
+ id: 'USER_WRITE',
+ value: BigInt(1) << BigInt(2),
+ label: scopeMessages.userWriteLabel,
+ desc: scopeMessages.userWriteDescription,
+ },
+ {
+ id: 'USER_DELETE',
+ value: BigInt(1) << BigInt(3),
+ label: scopeMessages.userDeleteLabel,
+ desc: scopeMessages.userDeleteDescription,
+ },
+ {
+ id: 'USER_AUTH_WRITE',
+ value: BigInt(1) << BigInt(4),
+ label: scopeMessages.userAuthWriteLabel,
+ desc: scopeMessages.userAuthWriteDescription,
+ },
+ {
+ id: 'NOTIFICATION_READ',
+ value: BigInt(1) << BigInt(5),
+ label: scopeMessages.notificationReadLabel,
+ desc: scopeMessages.notificationReadDescription,
+ },
+ {
+ id: 'NOTIFICATION_WRITE',
+ value: BigInt(1) << BigInt(6),
+ label: scopeMessages.notificationWriteLabel,
+ desc: scopeMessages.notificationWriteDescription,
+ },
+ {
+ id: 'PAYOUTS_READ',
+ value: BigInt(1) << BigInt(7),
+ label: scopeMessages.payoutsReadLabel,
+ desc: scopeMessages.payoutsReadDescription,
+ },
+ {
+ id: 'PAYOUTS_WRITE',
+ value: BigInt(1) << BigInt(8),
+ label: scopeMessages.payoutsWriteLabel,
+ desc: scopeMessages.payoutsWriteDescription,
+ },
+ {
+ id: 'ANALYTICS',
+ value: BigInt(1) << BigInt(9),
+ label: scopeMessages.analyticsLabel,
+ desc: scopeMessages.analyticsDescription,
+ },
+ {
+ id: 'PROJECT_CREATE',
+ value: BigInt(1) << BigInt(10),
+ label: scopeMessages.projectCreateLabel,
+ desc: scopeMessages.projectCreateDescription,
+ },
+ {
+ id: 'PROJECT_READ',
+ value: BigInt(1) << BigInt(11),
+ label: scopeMessages.projectReadLabel,
+ desc: scopeMessages.projectReadDescription,
+ },
+ {
+ id: 'PROJECT_WRITE',
+ value: BigInt(1) << BigInt(12),
+ label: scopeMessages.projectWriteLabel,
+ desc: scopeMessages.projectWriteDescription,
+ },
+ {
+ id: 'PROJECT_DELETE',
+ value: BigInt(1) << BigInt(13),
+ label: scopeMessages.projectDeleteLabel,
+ desc: scopeMessages.projectDeleteDescription,
+ },
+ {
+ id: 'VERSION_CREATE',
+ value: BigInt(1) << BigInt(14),
+ label: scopeMessages.versionCreateLabel,
+ desc: scopeMessages.versionCreateDescription,
+ },
+ {
+ id: 'VERSION_READ',
+ value: BigInt(1) << BigInt(15),
+ label: scopeMessages.versionReadLabel,
+ desc: scopeMessages.versionReadDescription,
+ },
+ {
+ id: 'VERSION_WRITE',
+ value: BigInt(1) << BigInt(16),
+ label: scopeMessages.versionWriteLabel,
+ desc: scopeMessages.versionWriteDescription,
+ },
+ {
+ id: 'VERSION_DELETE',
+ value: BigInt(1) << BigInt(17),
+ label: scopeMessages.versionDeleteLabel,
+ desc: scopeMessages.versionDeleteDescription,
+ },
+ {
+ id: 'REPORT_CREATE',
+ value: BigInt(1) << BigInt(18),
+ label: scopeMessages.reportCreateLabel,
+ desc: scopeMessages.reportCreateDescription,
+ },
+ {
+ id: 'REPORT_READ',
+ value: BigInt(1) << BigInt(19),
+ label: scopeMessages.reportReadLabel,
+ desc: scopeMessages.reportReadDescription,
+ },
+ {
+ id: 'REPORT_WRITE',
+ value: BigInt(1) << BigInt(20),
+ label: scopeMessages.reportWriteLabel,
+ desc: scopeMessages.reportWriteDescription,
+ },
+ {
+ id: 'REPORT_DELETE',
+ value: BigInt(1) << BigInt(21),
+ label: scopeMessages.reportDeleteLabel,
+ desc: scopeMessages.reportDeleteDescription,
+ },
+ {
+ id: 'THREAD_READ',
+ value: BigInt(1) << BigInt(22),
+ label: scopeMessages.threadReadLabel,
+ desc: scopeMessages.threadReadDescription,
+ },
+ {
+ id: 'THREAD_WRITE',
+ value: BigInt(1) << BigInt(23),
+ label: scopeMessages.threadWriteLabel,
+ desc: scopeMessages.threadWriteDescription,
+ },
+ {
+ id: 'PAT_CREATE',
+ value: BigInt(1) << BigInt(24),
+ label: scopeMessages.patCreateLabel,
+ desc: scopeMessages.patCreateDescription,
+ },
+ {
+ id: 'PAT_READ',
+ value: BigInt(1) << BigInt(25),
+ label: scopeMessages.patReadLabel,
+ desc: scopeMessages.patReadDescription,
+ },
+ {
+ id: 'PAT_WRITE',
+ value: BigInt(1) << BigInt(26),
+ label: scopeMessages.patWriteLabel,
+ desc: scopeMessages.patWriteDescription,
+ },
+ {
+ id: 'PAT_DELETE',
+ value: BigInt(1) << BigInt(27),
+ label: scopeMessages.patDeleteLabel,
+ desc: scopeMessages.patDeleteDescription,
+ },
+ {
+ id: 'SESSION_READ',
+ value: BigInt(1) << BigInt(28),
+ label: scopeMessages.sessionReadLabel,
+ desc: scopeMessages.sessionReadDescription,
+ },
+ {
+ id: 'SESSION_DELETE',
+ value: BigInt(1) << BigInt(29),
+ label: scopeMessages.sessionDeleteLabel,
+ desc: scopeMessages.sessionDeleteDescription,
+ },
+ {
+ id: 'PERFORM_ANALYTICS',
+ value: BigInt(1) << BigInt(30),
+ label: scopeMessages.performAnalyticsLabel,
+ desc: scopeMessages.performAnalyticsDescription,
+ },
+ {
+ id: 'COLLECTION_CREATE',
+ value: BigInt(1) << BigInt(31),
+ label: scopeMessages.collectionCreateLabel,
+ desc: scopeMessages.collectionCreateDescription,
+ },
+ {
+ id: 'COLLECTION_READ',
+ value: BigInt(1) << BigInt(32),
+ label: scopeMessages.collectionReadLabel,
+ desc: scopeMessages.collectionReadDescription,
+ },
+ {
+ id: 'COLLECTION_WRITE',
+ value: BigInt(1) << BigInt(33),
+ label: scopeMessages.collectionWriteLabel,
+ desc: scopeMessages.collectionWriteDescription,
+ },
+ {
+ id: 'COLLECTION_DELETE',
+ value: BigInt(1) << BigInt(34),
+ label: scopeMessages.collectionDeleteLabel,
+ desc: scopeMessages.collectionDeleteDescription,
+ },
+ {
+ id: 'ORGANIZATION_CREATE',
+ value: BigInt(1) << BigInt(35),
+ label: scopeMessages.organizationCreateLabel,
+ desc: scopeMessages.organizationCreateDescription,
+ },
+ {
+ id: 'ORGANIZATION_READ',
+ value: BigInt(1) << BigInt(36),
+ label: scopeMessages.organizationReadLabel,
+ desc: scopeMessages.organizationReadDescription,
+ },
+ {
+ id: 'ORGANIZATION_WRITE',
+ value: BigInt(1) << BigInt(37),
+ label: scopeMessages.organizationWriteLabel,
+ desc: scopeMessages.organizationWriteDescription,
+ },
+ {
+ id: 'ORGANIZATION_DELETE',
+ value: BigInt(1) << BigInt(38),
+ label: scopeMessages.organizationDeleteLabel,
+ desc: scopeMessages.organizationDeleteDescription,
+ },
+ {
+ id: 'SESSION_ACCESS',
+ value: BigInt(1) << BigInt(39),
+ label: scopeMessages.sessionAccessLabel,
+ desc: scopeMessages.sessionAccessDescription,
+ },
+]
const Scopes = scopeDefinitions.reduce(
- (acc, scope) => {
- acc[scope.id] = scope.value;
- return acc;
- },
- {} as Record
,
-);
+ (acc, scope) => {
+ acc[scope.id] = scope.value
+ return acc
+ },
+ {} as Record,
+)
export const restrictedScopes = [
- Scopes.PAT_READ,
- Scopes.PAT_CREATE,
- Scopes.PAT_WRITE,
- Scopes.PAT_DELETE,
- Scopes.SESSION_READ,
- Scopes.SESSION_DELETE,
- Scopes.SESSION_ACCESS,
- Scopes.USER_AUTH_WRITE,
- Scopes.USER_DELETE,
- Scopes.PERFORM_ANALYTICS,
-];
+ Scopes.PAT_READ,
+ Scopes.PAT_CREATE,
+ Scopes.PAT_WRITE,
+ Scopes.PAT_DELETE,
+ Scopes.SESSION_READ,
+ Scopes.SESSION_DELETE,
+ Scopes.SESSION_ACCESS,
+ Scopes.USER_AUTH_WRITE,
+ Scopes.USER_DELETE,
+ Scopes.PERFORM_ANALYTICS,
+]
export const scopeList = Object.entries(Scopes)
- .filter(([_, value]) => !restrictedScopes.includes(value))
- .map(([key, _]) => key);
+ .filter(([_, value]) => !restrictedScopes.includes(value))
+ .map(([key, _]) => key)
export const getScopeValue = (scope: string) => {
- return Scopes[scope];
-};
+ return Scopes[scope]
+}
export const encodeScopes = (scopes: string[]) => {
- let scopeFlag = BigInt(0);
+ let scopeFlag = BigInt(0)
- // We iterate over the provided scopes
- for (const scope of scopes) {
- // We iterate over the entries of the Scopes object
- for (const [scopeName, scopeFlagValue] of Object.entries(Scopes)) {
- // If the scope name is the same as the provided scope, add the scope flag to the scopeFlag variable
- if (scopeName === scope) {
- scopeFlag = scopeFlag | scopeFlagValue;
- }
- }
- }
+ // We iterate over the provided scopes
+ for (const scope of scopes) {
+ // We iterate over the entries of the Scopes object
+ for (const [scopeName, scopeFlagValue] of Object.entries(Scopes)) {
+ // If the scope name is the same as the provided scope, add the scope flag to the scopeFlag variable
+ if (scopeName === scope) {
+ scopeFlag = scopeFlag | scopeFlagValue
+ }
+ }
+ }
- return scopeFlag;
-};
+ return scopeFlag
+}
export const decodeScopes = (scopes: bigint | number) => {
- if (typeof scopes === "number") {
- scopes = BigInt(scopes);
- }
+ if (typeof scopes === 'number') {
+ scopes = BigInt(scopes)
+ }
- const authorizedScopes = [];
+ const authorizedScopes = []
- // We iterate over the entries of the Scopes object
- for (const [scopeName, scopeFlag] of Object.entries(Scopes)) {
- // If the scope flag is present in the provided number, add the scope name to the list
- if ((scopes & scopeFlag) === scopeFlag) {
- authorizedScopes.push(scopeName);
- }
- }
+ // We iterate over the entries of the Scopes object
+ for (const [scopeName, scopeFlag] of Object.entries(Scopes)) {
+ // If the scope flag is present in the provided number, add the scope name to the list
+ if ((scopes & scopeFlag) === scopeFlag) {
+ authorizedScopes.push(scopeName)
+ }
+ }
- return authorizedScopes;
-};
+ return authorizedScopes
+}
export const hasScope = (scopes: bigint, scope: string) => {
- const authorizedScopes = decodeScopes(scopes);
- return authorizedScopes.includes(scope);
-};
+ const authorizedScopes = decodeScopes(scopes)
+ return authorizedScopes.includes(scope)
+}
export const toggleScope = (scopes: bigint, scope: string) => {
- const authorizedScopes = decodeScopes(scopes);
- if (authorizedScopes.includes(scope)) {
- return encodeScopes(authorizedScopes.filter((authorizedScope) => authorizedScope !== scope));
- } else {
- return encodeScopes([...authorizedScopes, scope]);
- }
-};
+ const authorizedScopes = decodeScopes(scopes)
+ if (authorizedScopes.includes(scope)) {
+ return encodeScopes(authorizedScopes.filter((authorizedScope) => authorizedScope !== scope))
+ } else {
+ return encodeScopes([...authorizedScopes, scope])
+ }
+}
export const useScopes = () => {
- const { formatMessage } = useVIntl();
+ const { formatMessage } = useVIntl()
- const scopesToDefinitions = (scopes: bigint) => {
- const authorizedScopes = decodeScopes(scopes);
- return authorizedScopes.map((scope) => {
- const scopeDefinition = scopeDefinitions.find(
- (scopeDefinition) => scopeDefinition.id === scope,
- );
- if (!scopeDefinition) {
- throw new Error(`Scope ${scope} not found`);
- }
- return formatMessage(scopeDefinition.desc);
- });
- };
+ const scopesToDefinitions = (scopes: bigint) => {
+ const authorizedScopes = decodeScopes(scopes)
+ return authorizedScopes.map((scope) => {
+ const scopeDefinition = scopeDefinitions.find(
+ (scopeDefinition) => scopeDefinition.id === scope,
+ )
+ if (!scopeDefinition) {
+ throw new Error(`Scope ${scope} not found`)
+ }
+ return formatMessage(scopeDefinition.desc)
+ })
+ }
- const scopesToLabels = (scopes: bigint) => {
- const authorizedScopes = decodeScopes(scopes);
- return authorizedScopes.map((scope) => {
- const scopeDefinition = scopeDefinitions.find(
- (scopeDefinition) => scopeDefinition.id === scope,
- );
- if (!scopeDefinition) {
- throw new Error(`Scope ${scope} not found`);
- }
- return formatMessage(scopeDefinition.label);
- });
- };
+ const scopesToLabels = (scopes: bigint) => {
+ const authorizedScopes = decodeScopes(scopes)
+ return authorizedScopes.map((scope) => {
+ const scopeDefinition = scopeDefinitions.find(
+ (scopeDefinition) => scopeDefinition.id === scope,
+ )
+ if (!scopeDefinition) {
+ throw new Error(`Scope ${scope} not found`)
+ }
+ return formatMessage(scopeDefinition.label)
+ })
+ }
- return {
- scopesToDefinitions,
- scopesToLabels,
- };
-};
+ return {
+ scopesToDefinitions,
+ scopesToLabels,
+ }
+}
diff --git a/apps/frontend/src/composables/compact-number.ts b/apps/frontend/src/composables/compact-number.ts
index c635a389..298e3696 100644
--- a/apps/frontend/src/composables/compact-number.ts
+++ b/apps/frontend/src/composables/compact-number.ts
@@ -1,26 +1,26 @@
-const formatters = new WeakMap();
+const formatters = new WeakMap()
export function useCompactNumber(truncate = false, fractionDigits = 2, locale?: string) {
- const context = {};
+ const context = {}
- let formatter = formatters.get(context);
+ let formatter = formatters.get(context)
- if (!formatter) {
- formatter = new Intl.NumberFormat(locale, {
- notation: "compact",
- maximumFractionDigits: fractionDigits,
- });
- formatters.set(context, formatter);
- }
+ if (!formatter) {
+ formatter = new Intl.NumberFormat(locale, {
+ notation: 'compact',
+ maximumFractionDigits: fractionDigits,
+ })
+ formatters.set(context, formatter)
+ }
- function format(value: number): string {
- let formattedValue = value;
- if (truncate) {
- const scale = Math.pow(10, fractionDigits);
- formattedValue = Math.floor(value * scale) / scale;
- }
- return formatter!.format(formattedValue);
- }
+ function format(value: number): string {
+ let formattedValue = value
+ if (truncate) {
+ const scale = Math.pow(10, fractionDigits)
+ formattedValue = Math.floor(value * scale) / scale
+ }
+ return formatter!.format(formattedValue)
+ }
- return format;
+ return format
}
diff --git a/apps/frontend/src/composables/country.ts b/apps/frontend/src/composables/country.ts
index cde074ff..a47cf47f 100644
--- a/apps/frontend/src/composables/country.ts
+++ b/apps/frontend/src/composables/country.ts
@@ -1,37 +1,37 @@
-import { useState, useRequestHeaders } from "#imports";
+import { useRequestHeaders, useState } from '#imports'
export const useUserCountry = () => {
- const country = useState("userCountry", () => "US");
- const fromServer = useState("userCountryFromServer", () => false);
+ const country = useState('userCountry', () => 'US')
+ const fromServer = useState('userCountryFromServer', () => false)
- if (import.meta.server) {
- const headers = useRequestHeaders(["cf-ipcountry", "accept-language"]);
- const cf = headers["cf-ipcountry"];
- if (cf) {
- country.value = cf.toUpperCase();
- fromServer.value = true;
- } else {
- const al = headers["accept-language"] || "";
- const tag = al.split(",")[0];
- const val = tag.split("-")[1]?.toLowerCase();
- if (val) {
- country.value = val;
- fromServer.value = true;
- }
- }
- }
+ if (import.meta.server) {
+ const headers = useRequestHeaders(['cf-ipcountry', 'accept-language'])
+ const cf = headers['cf-ipcountry']
+ if (cf) {
+ country.value = cf.toUpperCase()
+ fromServer.value = true
+ } else {
+ const al = headers['accept-language'] || ''
+ const tag = al.split(',')[0]
+ const val = tag.split('-')[1]?.toLowerCase()
+ if (val) {
+ country.value = val
+ fromServer.value = true
+ }
+ }
+ }
- if (import.meta.client) {
- onMounted(() => {
- if (fromServer.value) return;
- // @ts-expect-error - ignore TS not knowing about navigator.userLanguage
- const lang = navigator.language || navigator.userLanguage || "";
- const region = lang.split("-")[1];
- if (region) {
- country.value = region.toUpperCase();
- }
- });
- }
+ if (import.meta.client) {
+ onMounted(() => {
+ if (fromServer.value) return
+ // @ts-expect-error - ignore TS not knowing about navigator.userLanguage
+ const lang = navigator.language || navigator.userLanguage || ''
+ const region = lang.split('-')[1]
+ if (region) {
+ country.value = region.toUpperCase()
+ }
+ })
+ }
- return country;
-};
+ return country
+}
diff --git a/apps/frontend/src/composables/display-names.ts b/apps/frontend/src/composables/display-names.ts
index c070ff7a..d88cc7dc 100644
--- a/apps/frontend/src/composables/display-names.ts
+++ b/apps/frontend/src/composables/display-names.ts
@@ -1,92 +1,90 @@
-const safeTags = new Map();
+const safeTags = new Map()
function safeTagFor(locale: string) {
- let safeTag = safeTags.get(locale);
- if (safeTag == null) {
- safeTag = new Intl.Locale(locale).baseName;
- safeTags.set(locale, safeTag);
- }
- return safeTag;
+ let safeTag = safeTags.get(locale)
+ if (safeTag == null) {
+ safeTag = new Intl.Locale(locale).baseName
+ safeTags.set(locale, safeTag)
+ }
+ return safeTag
}
type DisplayNamesWrapper = Intl.DisplayNames & {
- of(tag: string): string | undefined;
-};
+ of(tag: string): string | undefined
+}
-const displayNamesDicts = new Map();
+const displayNamesDicts = new Map()
function getWrapperKey(locale: string, options: Intl.DisplayNamesOptions) {
- return JSON.stringify({ ...options, locale });
+ return JSON.stringify({ ...options, locale })
}
export function createDisplayNames(
- locale: string,
- options: Intl.DisplayNamesOptions = { type: "language" },
+ locale: string,
+ options: Intl.DisplayNamesOptions = { type: 'language' },
) {
- const wrapperKey = getWrapperKey(locale, options);
- let wrapper = displayNamesDicts.get(wrapperKey);
+ const wrapperKey = getWrapperKey(locale, options)
+ let wrapper = displayNamesDicts.get(wrapperKey)
- if (wrapper == null) {
- const dict = new Intl.DisplayNames(locale, options);
+ if (wrapper == null) {
+ const dict = new Intl.DisplayNames(locale, options)
- const badTags: string[] = [];
+ const badTags: string[] = []
- wrapper = {
- resolvedOptions() {
- return dict.resolvedOptions();
- },
- of(tag: string) {
- let attempt = 0;
+ wrapper = {
+ resolvedOptions() {
+ return dict.resolvedOptions()
+ },
+ of(tag: string) {
+ let attempt = 0
- // eslint-disable-next-line no-labels
- lookupLoop: do {
- let lookup: string;
- switch (attempt) {
- case 0:
- lookup = tag;
- break;
- case 1:
- lookup = safeTagFor(tag);
- break;
- default:
- // eslint-disable-next-line no-labels
- break lookupLoop;
- }
+ lookupLoop: do {
+ let lookup: string
+ switch (attempt) {
+ case 0:
+ lookup = tag
+ break
+ case 1:
+ lookup = safeTagFor(tag)
+ break
+ default:
+ break lookupLoop
+ }
- if (badTags.includes(lookup)) continue;
+ if (badTags.includes(lookup)) continue
- try {
- return dict.of(lookup);
- } catch {
- console.warn(
- `Failed to get display name for ${lookup} using dictionary for ${
- this.resolvedOptions().locale
- }`,
- );
- badTags.push(lookup);
- continue;
- }
- } while (++attempt < 5);
+ try {
+ return dict.of(lookup)
+ } catch {
+ console.warn(
+ `Failed to get display name for ${lookup} using dictionary for ${
+ this.resolvedOptions().locale
+ }`,
+ )
+ badTags.push(lookup)
+ continue
+ }
+ } while (++attempt < 5)
- return undefined;
- },
- };
+ return undefined
+ },
+ }
- displayNamesDicts.set(wrapperKey, wrapper);
- }
+ displayNamesDicts.set(wrapperKey, wrapper)
+ }
- return wrapper;
+ return wrapper
}
export function useDisplayNames(
- locale: string | (() => string) | Ref,
- options?:
- | (Intl.DisplayNamesOptions | undefined)
- | (() => Intl.DisplayNamesOptions | undefined)
- | Ref,
+ locale: string | (() => string) | Ref,
+ options?:
+ | (Intl.DisplayNamesOptions | undefined)
+ | (() => Intl.DisplayNamesOptions | undefined)
+ | Ref,
) {
- const $locale = toRef(locale);
- const $options = toRef(options);
+ const $locale = toRef(locale)
+ const $options = toRef(options)
- return computed(() => createDisplayNames($locale.value, $options.value));
+ return computed(() => createDisplayNames($locale.value, $options.value))
}
diff --git a/apps/frontend/src/composables/featureFlags.ts b/apps/frontend/src/composables/featureFlags.ts
index 02166773..c1a9c196 100644
--- a/apps/frontend/src/composables/featureFlags.ts
+++ b/apps/frontend/src/composables/featureFlags.ts
@@ -1,107 +1,107 @@
-import type { CookieOptions } from "#app";
+import type { CookieOptions } from '#app'
-export type ProjectDisplayMode = "list" | "grid" | "gallery";
-export type DarkColorTheme = "dark" | "oled" | "retro";
+export type ProjectDisplayMode = 'list' | 'grid' | 'gallery'
+export type DarkColorTheme = 'dark' | 'oled' | 'retro'
export interface NumberFlag {
- min: number;
- max: number;
+ min: number
+ max: number
}
-export type BooleanFlag = boolean;
+export type BooleanFlag = boolean
-export type RadioFlag = ProjectDisplayMode | DarkColorTheme;
+export type RadioFlag = ProjectDisplayMode | DarkColorTheme
-export type FlagValue = BooleanFlag; /* | NumberFlag | RadioFlag */
+export type FlagValue = BooleanFlag /* | NumberFlag | RadioFlag */
-const validateValues = (flags: Record) => flags;
+const validateValues = (flags: Record) => flags
export const DEFAULT_FEATURE_FLAGS = validateValues({
- // Developer flags
- developerMode: false,
- showVersionFilesInTable: false,
-// showAdsWithPlus: false,
- alwaysShowChecklistAsPopup: true,
+ // Developer flags
+ developerMode: false,
+ showVersionFilesInTable: false,
+ // showAdsWithPlus: false,
+ alwaysShowChecklistAsPopup: true,
- // Feature toggles
- projectTypesPrimaryNav: false,
- hidePlusPromoInUserMenu: false,
- oldProjectCards: true,
- newProjectCards: false,
- projectBackground: false,
- searchBackground: false,
- advancedDebugInfo: false,
- showProjectPageDownloadModalServersPromo: false,
- showProjectPageCreateServersTooltip: true,
- showProjectPageQuickServerButton: false,
- // advancedRendering: true,
- // externalLinksNewTab: true,
- // notUsingBlockers: false,
- // hideModrinthAppPromos: false,
- // preferredDarkTheme: 'dark',
- // hideStagingBanner: false,
+ // Feature toggles
+ projectTypesPrimaryNav: false,
+ hidePlusPromoInUserMenu: false,
+ oldProjectCards: true,
+ newProjectCards: false,
+ projectBackground: false,
+ searchBackground: false,
+ advancedDebugInfo: false,
+ showProjectPageDownloadModalServersPromo: false,
+ showProjectPageCreateServersTooltip: true,
+ showProjectPageQuickServerButton: false,
+ // advancedRendering: true,
+ // externalLinksNewTab: true,
+ // notUsingBlockers: false,
+ // hideModrinthAppPromos: false,
+ // preferredDarkTheme: 'dark',
+ // hideStagingBanner: false,
- // Project display modes
- // modSearchDisplayMode: 'list',
- // pluginSearchDisplayMode: 'list',
- // resourcePackSearchDisplayMode: 'gallery',
- // modpackSearchDisplayMode: 'list',
- // shaderSearchDisplayMode: 'gallery',
- // dataPackSearchDisplayMode: 'list',
- // userProjectDisplayMode: 'list',
- // collectionProjectDisplayMode: 'list',
-} as const);
+ // Project display modes
+ // modSearchDisplayMode: 'list',
+ // pluginSearchDisplayMode: 'list',
+ // resourcePackSearchDisplayMode: 'gallery',
+ // modpackSearchDisplayMode: 'list',
+ // shaderSearchDisplayMode: 'gallery',
+ // dataPackSearchDisplayMode: 'list',
+ // userProjectDisplayMode: 'list',
+ // collectionProjectDisplayMode: 'list',
+} as const)
-export type FeatureFlag = keyof typeof DEFAULT_FEATURE_FLAGS;
+export type FeatureFlag = keyof typeof DEFAULT_FEATURE_FLAGS
export type AllFeatureFlags = {
- [key in FeatureFlag]: (typeof DEFAULT_FEATURE_FLAGS)[key];
-};
+ [key in FeatureFlag]: (typeof DEFAULT_FEATURE_FLAGS)[key]
+}
-export type PartialFeatureFlags = Partial;
+export type PartialFeatureFlags = Partial
const COOKIE_OPTIONS = {
- maxAge: 60 * 60 * 24 * 365 * 10,
- sameSite: "lax",
- secure: true,
- httpOnly: false,
- path: "/",
-} satisfies CookieOptions;
+ maxAge: 60 * 60 * 24 * 365 * 10,
+ sameSite: 'lax',
+ secure: true,
+ httpOnly: false,
+ path: '/',
+} satisfies CookieOptions
export const useFeatureFlags = () =>
- useState("featureFlags", () => {
- const config = useRuntimeConfig();
+ useState('featureFlags', () => {
+ const config = useRuntimeConfig()
- const savedFlags = useCookie("featureFlags", COOKIE_OPTIONS);
+ const savedFlags = useCookie('featureFlags', COOKIE_OPTIONS)
- if (!savedFlags.value) {
- savedFlags.value = {};
- }
+ if (!savedFlags.value) {
+ savedFlags.value = {}
+ }
- const flags: AllFeatureFlags = JSON.parse(JSON.stringify(DEFAULT_FEATURE_FLAGS));
+ const flags: AllFeatureFlags = JSON.parse(JSON.stringify(DEFAULT_FEATURE_FLAGS))
- const overrides = config.public.featureFlagOverrides as PartialFeatureFlags;
- for (const key in overrides) {
- if (key in flags) {
- const flag = key as FeatureFlag;
- const value = overrides[flag] as (typeof flags)[FeatureFlag];
- flags[flag] = value;
- }
- }
+ const overrides = config.public.featureFlagOverrides as PartialFeatureFlags
+ for (const key in overrides) {
+ if (key in flags) {
+ const flag = key as FeatureFlag
+ const value = overrides[flag] as (typeof flags)[FeatureFlag]
+ flags[flag] = value
+ }
+ }
- for (const key in savedFlags.value) {
- if (key in flags) {
- const flag = key as FeatureFlag;
- const value = savedFlags.value[flag] as (typeof flags)[FeatureFlag];
- flags[flag] = value;
- }
- }
+ for (const key in savedFlags.value) {
+ if (key in flags) {
+ const flag = key as FeatureFlag
+ const value = savedFlags.value[flag] as (typeof flags)[FeatureFlag]
+ flags[flag] = value
+ }
+ }
- return flags;
- });
+ return flags
+ })
export const saveFeatureFlags = () => {
- const flags = useFeatureFlags();
- const cookie = useCookie("featureFlags", COOKIE_OPTIONS);
- cookie.value = flags.value;
-};
+ const flags = useFeatureFlags()
+ const cookie = useCookie('featureFlags', COOKIE_OPTIONS)
+ cookie.value = flags.value
+}
diff --git a/apps/frontend/src/composables/fetch.js b/apps/frontend/src/composables/fetch.js
index 91f765ce..928caa64 100644
--- a/apps/frontend/src/composables/fetch.js
+++ b/apps/frontend/src/composables/fetch.js
@@ -1,36 +1,36 @@
export const useBaseFetch = async (url, options = {}, skipAuth = false) => {
- const config = useRuntimeConfig();
- let base = import.meta.server ? config.apiBaseUrl : config.public.apiBaseUrl;
+ const config = useRuntimeConfig()
+ let base = import.meta.server ? config.apiBaseUrl : config.public.apiBaseUrl
- if (!options.headers) {
- options.headers = {};
- }
+ if (!options.headers) {
+ options.headers = {}
+ }
- if (import.meta.server) {
- options.headers["x-ratelimit-key"] = config.rateLimitKey;
- }
+ if (import.meta.server) {
+ options.headers['x-ratelimit-key'] = config.rateLimitKey
+ }
- if (!skipAuth) {
- const auth = await useAuth();
+ if (!skipAuth) {
+ const auth = await useAuth()
- options.headers.Authorization = auth.value.token;
- }
+ options.headers.Authorization = auth.value.token
+ }
- if (options.apiVersion || options.internal) {
- // Base may end in /vD/ or /vD. We would need to replace the digit with the new version number
- // and keep the trailing slash if it exists
- const baseVersion = base.match(/\/v\d\//);
+ if (options.apiVersion || options.internal) {
+ // Base may end in /vD/ or /vD. We would need to replace the digit with the new version number
+ // and keep the trailing slash if it exists
+ const baseVersion = base.match(/\/v\d\//)
- const replaceStr = options.internal ? `/_internal/` : `/v${options.apiVersion}/`;
+ const replaceStr = options.internal ? `/_internal/` : `/v${options.apiVersion}/`
- if (baseVersion) {
- base = base.replace(baseVersion[0], replaceStr);
- } else {
- base = base.replace(/\/v\d$/, replaceStr);
- }
+ if (baseVersion) {
+ base = base.replace(baseVersion[0], replaceStr)
+ } else {
+ base = base.replace(/\/v\d$/, replaceStr)
+ }
- delete options.apiVersion;
- }
+ delete options.apiVersion
+ }
- return await $fetch(`${base}${url}`, options);
-};
+ return await $fetch(`${base}${url}`, options)
+}
diff --git a/apps/frontend/src/composables/image-upload.ts b/apps/frontend/src/composables/image-upload.ts
index 5e7e74e8..f8820d5b 100644
--- a/apps/frontend/src/composables/image-upload.ts
+++ b/apps/frontend/src/composables/image-upload.ts
@@ -1,46 +1,46 @@
type ImageUploadContext = {
- projectID?: string;
- context: "project" | "version" | "thread_message" | "report";
-};
+ projectID?: string
+ context: 'project' | 'version' | 'thread_message' | 'report'
+}
interface ImageUploadResponse {
- id: string;
- url: string;
+ id: string
+ url: string
}
export const useImageUpload = async (file: File, ctx: ImageUploadContext) => {
- // Make sure file is of type image/png, image/jpeg, image/gif, or image/webp
- if (
- !file.type.startsWith("image/") ||
- !["png", "jpeg", "gif", "webp"].includes(file.type.split("/")[1])
- ) {
- throw new Error("File is not an accepted image type");
- }
+ // Make sure file is of type image/png, image/jpeg, image/gif, or image/webp
+ if (
+ !file.type.startsWith('image/') ||
+ !['png', 'jpeg', 'gif', 'webp'].includes(file.type.split('/')[1])
+ ) {
+ throw new Error('File is not an accepted image type')
+ }
- // Make sure file is less than 1MB
- if (file.size > 1024 * 1024) {
- throw new Error("File exceeds the 1MiB size limit");
- }
+ // Make sure file is less than 1MB
+ if (file.size > 1024 * 1024) {
+ throw new Error('File exceeds the 1MiB size limit')
+ }
- const qs = new URLSearchParams();
- if (ctx.projectID) qs.set("project_id", ctx.projectID);
- qs.set("context", ctx.context);
- qs.set("ext", file.type.split("/")[1]);
- const url = `image?${qs.toString()}`;
+ const qs = new URLSearchParams()
+ if (ctx.projectID) qs.set('project_id', ctx.projectID)
+ qs.set('context', ctx.context)
+ qs.set('ext', file.type.split('/')[1])
+ const url = `image?${qs.toString()}`
- const response = (await useBaseFetch(url, {
- method: "POST",
- body: file,
- apiVersion: 3,
- })) as ImageUploadResponse;
+ const response = (await useBaseFetch(url, {
+ method: 'POST',
+ body: file,
+ apiVersion: 3,
+ })) as ImageUploadResponse
- // Type check to see if response has a url property and an id property
- if (!response?.id || typeof response.id !== "string") {
- throw new Error("Unexpected response from server");
- }
- if (!response?.url || typeof response.url !== "string") {
- throw new Error("Unexpected response from server");
- }
+ // Type check to see if response has a url property and an id property
+ if (!response?.id || typeof response.id !== 'string') {
+ throw new Error('Unexpected response from server')
+ }
+ if (!response?.url || typeof response.url !== 'string') {
+ throw new Error('Unexpected response from server')
+ }
- return response;
-};
+ return response
+}
diff --git a/apps/frontend/src/composables/loading.js b/apps/frontend/src/composables/loading.js
index eab1ef62..1cd5aaad 100644
--- a/apps/frontend/src/composables/loading.js
+++ b/apps/frontend/src/composables/loading.js
@@ -1,13 +1,13 @@
-export const useLoading = () => useState("loading", () => false);
+export const useLoading = () => useState('loading', () => false)
export const startLoading = () => {
- const loading = useLoading();
+ const loading = useLoading()
- loading.value = true;
-};
+ loading.value = true
+}
export const stopLoading = () => {
- const loading = useLoading();
+ const loading = useLoading()
- loading.value = false;
-};
+ loading.value = false
+}
diff --git a/apps/frontend/src/composables/notifs.js b/apps/frontend/src/composables/notifs.js
deleted file mode 100644
index 7ec7786c..00000000
--- a/apps/frontend/src/composables/notifs.js
+++ /dev/null
@@ -1,38 +0,0 @@
-export const useNotifications = () => useState("notifications", () => []);
-
-export const addNotification = (notification) => {
- const notifications = useNotifications();
-
- const existingNotif = notifications.value.find(
- (x) =>
- x.text === notification.text &&
- x.title === notification.title &&
- x.type === notification.type,
- );
- if (existingNotif) {
- setNotificationTimer(existingNotif);
- existingNotif.count++;
-
- return;
- }
-
- notification.id = new Date();
- notification.count = 1;
-
- setNotificationTimer(notification);
- notifications.value.push(notification);
-};
-
-export const setNotificationTimer = (notification) => {
- if (!notification) return;
-
- const notifications = useNotifications();
-
- if (notification.timer) {
- clearTimeout(notification.timer);
- }
-
- notification.timer = setTimeout(() => {
- notifications.value.splice(notifications.value.indexOf(notification), 1);
- }, 30000);
-};
diff --git a/apps/frontend/src/composables/nuxt-accessors.ts b/apps/frontend/src/composables/nuxt-accessors.ts
index 5130f626..ca09ae3a 100644
--- a/apps/frontend/src/composables/nuxt-accessors.ts
+++ b/apps/frontend/src/composables/nuxt-accessors.ts
@@ -1,7 +1,7 @@
export function useTheme() {
- return useNuxtApp().$theme;
+ return useNuxtApp().$theme
}
export function useCosmetics() {
- return useNuxtApp().$cosmetics;
+ return useNuxtApp().$cosmetics
}
diff --git a/apps/frontend/src/composables/nuxt-bugfest.ts b/apps/frontend/src/composables/nuxt-bugfest.ts
index d4391ca3..67e31806 100644
--- a/apps/frontend/src/composables/nuxt-bugfest.ts
+++ b/apps/frontend/src/composables/nuxt-bugfest.ts
@@ -1 +1 @@
-export { useRoute as useNativeRoute, useRouter as useNativeRouter } from "vue-router";
+export { useRoute as useNativeRoute, useRouter as useNativeRouter } from 'vue-router'
diff --git a/apps/frontend/src/composables/query.js b/apps/frontend/src/composables/query.js
index 1b5095de..240aae2b 100644
--- a/apps/frontend/src/composables/query.js
+++ b/apps/frontend/src/composables/query.js
@@ -1,7 +1,7 @@
export const getArrayOrString = (x) => {
- if (typeof x === "string" || x instanceof String) {
- return [x];
- } else {
- return x;
- }
-};
+ if (typeof x === 'string' || x instanceof String) {
+ return [x]
+ } else {
+ return x
+ }
+}
diff --git a/apps/frontend/src/composables/route-params.js b/apps/frontend/src/composables/route-params.js
index 84895782..a9ab322b 100644
--- a/apps/frontend/src/composables/route-params.js
+++ b/apps/frontend/src/composables/route-params.js
@@ -4,7 +4,7 @@
* @param {string?} key The key of the route param to extract.
* @returns {import('vue').Ref}
*/
-export const useRouteId = (key = "id") => {
- const route = useNativeRoute();
- return route.params?.[key] || undefined;
-};
+export const useRouteId = (key = 'id') => {
+ const route = useNativeRoute()
+ return route.params?.[key] || undefined
+}
diff --git a/apps/frontend/src/composables/servers/modrinth-servers.ts b/apps/frontend/src/composables/servers/modrinth-servers.ts
index d0e3cd92..d6f2f7b7 100644
--- a/apps/frontend/src/composables/servers/modrinth-servers.ts
+++ b/apps/frontend/src/composables/servers/modrinth-servers.ts
@@ -1,328 +1,329 @@
-import { ModrinthServerError } from "@modrinth/utils";
-import type { JWTAuth, ModuleError, ModuleName } from "@modrinth/utils";
-import { useServersFetch } from "./servers-fetch.ts";
+import type { AbstractWebNotificationManager } from '@modrinth/ui'
+import type { JWTAuth, ModuleError, ModuleName } from '@modrinth/utils'
+import { ModrinthServerError } from '@modrinth/utils'
import {
- GeneralModule,
- ContentModule,
- BackupsModule,
- NetworkModule,
- StartupModule,
- WSModule,
- FSModule,
-} from "./modules/index.ts";
+ BackupsModule,
+ ContentModule,
+ FSModule,
+ GeneralModule,
+ NetworkModule,
+ StartupModule,
+ WSModule,
+} from './modules/index.ts'
+import { useServersFetch } from './servers-fetch.ts'
-export function handleError(err: any) {
- if (err instanceof ModrinthServerError && err.v1Error) {
- addNotification({
- title: err.v1Error?.context ?? `An error occurred`,
- type: "error",
- text: err.v1Error.description,
- errorCode: err.v1Error.error,
- });
- } else {
- addNotification({
- title: "An error occurred",
- type: "error",
- text: err.message ?? (err.data ? err.data.description : err),
- });
- }
+export function handleServersError(err: any, notifications: AbstractWebNotificationManager) {
+ if (err instanceof ModrinthServerError && err.v1Error) {
+ notifications.addNotification({
+ title: err.v1Error?.context ?? `An error occurred`,
+ type: 'error',
+ text: err.v1Error.description,
+ errorCode: err.v1Error.error,
+ })
+ } else {
+ notifications.addNotification({
+ title: 'An error occurred',
+ type: 'error',
+ text: err.message ?? (err.data ? err.data.description : err),
+ })
+ }
}
export class ModrinthServer {
- readonly serverId: string;
- private errors: Partial> = {};
+ readonly serverId: string
+ private errors: Partial> = {}
- readonly general: GeneralModule;
- readonly content: ContentModule;
- readonly backups: BackupsModule;
- readonly network: NetworkModule;
- readonly startup: StartupModule;
- readonly ws: WSModule;
- readonly fs: FSModule;
+ readonly general: GeneralModule
+ readonly content: ContentModule
+ readonly backups: BackupsModule
+ readonly network: NetworkModule
+ readonly startup: StartupModule
+ readonly ws: WSModule
+ readonly fs: FSModule
- constructor(serverId: string) {
- this.serverId = serverId;
+ constructor(serverId: string) {
+ this.serverId = serverId
- this.general = new GeneralModule(this);
- this.content = new ContentModule(this);
- this.backups = new BackupsModule(this);
- this.network = new NetworkModule(this);
- this.startup = new StartupModule(this);
- this.ws = new WSModule(this);
- this.fs = new FSModule(this);
- }
+ this.general = new GeneralModule(this)
+ this.content = new ContentModule(this)
+ this.backups = new BackupsModule(this)
+ this.network = new NetworkModule(this)
+ this.startup = new StartupModule(this)
+ this.ws = new WSModule(this)
+ this.fs = new FSModule(this)
+ }
- async createMissingFolders(path: string): Promise {
- if (path.startsWith("/")) {
- path = path.substring(1);
- }
- const folders = path.split("/");
- let currentPath = "";
+ async createMissingFolders(path: string): Promise {
+ if (path.startsWith('/')) {
+ path = path.substring(1)
+ }
+ const folders = path.split('/')
+ let currentPath = ''
- for (const folder of folders) {
- currentPath += "/" + folder;
- try {
- await this.fs.createFileOrFolder(currentPath, "directory");
- } catch {
- // Folder might already exist, ignore error
- }
- }
- }
+ for (const folder of folders) {
+ currentPath += '/' + folder
+ try {
+ await this.fs.createFileOrFolder(currentPath, 'directory')
+ } catch {
+ // Folder might already exist, ignore error
+ }
+ }
+ }
- async fetchConfigFile(fileName: string): Promise {
- return await useServersFetch(`servers/${this.serverId}/config/${fileName}`);
- }
+ async fetchConfigFile(fileName: string): Promise {
+ return await useServersFetch(`servers/${this.serverId}/config/${fileName}`)
+ }
- constructServerProperties(properties: any): string {
- let fileContent = `#Minecraft server properties\n#${new Date().toUTCString()}\n`;
+ constructServerProperties(properties: any): string {
+ let fileContent = `#Minecraft server properties\n#${new Date().toUTCString()}\n`
- for (const [key, value] of Object.entries(properties)) {
- if (typeof value === "object") {
- fileContent += `${key}=${JSON.stringify(value)}\n`;
- } else if (typeof value === "boolean") {
- fileContent += `${key}=${value ? "true" : "false"}\n`;
- } else {
- fileContent += `${key}=${value}\n`;
- }
- }
+ for (const [key, value] of Object.entries(properties)) {
+ if (typeof value === 'object') {
+ fileContent += `${key}=${JSON.stringify(value)}\n`
+ } else if (typeof value === 'boolean') {
+ fileContent += `${key}=${value ? 'true' : 'false'}\n`
+ } else {
+ fileContent += `${key}=${value}\n`
+ }
+ }
- return fileContent;
- }
+ return fileContent
+ }
- async processImage(iconUrl: string | undefined): Promise {
- const sharedImage = useState(`server-icon-${this.serverId}`);
+ async processImage(iconUrl: string | undefined): Promise {
+ const sharedImage = useState(`server-icon-${this.serverId}`)
- if (sharedImage.value) {
- return sharedImage.value;
- }
+ if (sharedImage.value) {
+ return sharedImage.value
+ }
- try {
- const auth = await useServersFetch(`servers/${this.serverId}/fs`);
- try {
- const fileData = await useServersFetch(`/download?path=/server-icon-original.png`, {
- override: auth,
- retry: 1, // Reduce retries for optional resources
- });
+ try {
+ const auth = await useServersFetch(`servers/${this.serverId}/fs`)
+ try {
+ const fileData = await useServersFetch(`/download?path=/server-icon-original.png`, {
+ override: auth,
+ retry: 1, // Reduce retries for optional resources
+ })
- if (fileData instanceof Blob && import.meta.client) {
- const dataURL = await new Promise((resolve) => {
- const canvas = document.createElement("canvas");
- const ctx = canvas.getContext("2d");
- const img = new Image();
- img.onload = () => {
- canvas.width = 512;
- canvas.height = 512;
- ctx?.drawImage(img, 0, 0, 512, 512);
- const dataURL = canvas.toDataURL("image/png");
- sharedImage.value = dataURL;
- resolve(dataURL);
- URL.revokeObjectURL(img.src);
- };
- img.src = URL.createObjectURL(fileData);
- });
- return dataURL;
- }
- } catch (error) {
- if (error instanceof ModrinthServerError) {
- if (error.statusCode && error.statusCode >= 500) {
- console.debug("Service unavailable, skipping icon processing");
- sharedImage.value = undefined;
- return undefined;
- }
+ if (fileData instanceof Blob && import.meta.client) {
+ const dataURL = await new Promise((resolve) => {
+ const canvas = document.createElement('canvas')
+ const ctx = canvas.getContext('2d')
+ const img = new Image()
+ img.onload = () => {
+ canvas.width = 512
+ canvas.height = 512
+ ctx?.drawImage(img, 0, 0, 512, 512)
+ const dataURL = canvas.toDataURL('image/png')
+ sharedImage.value = dataURL
+ resolve(dataURL)
+ URL.revokeObjectURL(img.src)
+ }
+ img.src = URL.createObjectURL(fileData)
+ })
+ return dataURL
+ }
+ } catch (error) {
+ if (error instanceof ModrinthServerError) {
+ if (error.statusCode && error.statusCode >= 500) {
+ console.debug('Service unavailable, skipping icon processing')
+ sharedImage.value = undefined
+ return undefined
+ }
- if (error.statusCode === 404 && iconUrl) {
- try {
- const response = await fetch(iconUrl);
- if (!response.ok) throw new Error("Failed to fetch icon");
- const file = await response.blob();
- const originalFile = new File([file], "server-icon-original.png", {
- type: "image/png",
- });
+ if (error.statusCode === 404 && iconUrl) {
+ try {
+ const response = await fetch(iconUrl)
+ if (!response.ok) throw new Error('Failed to fetch icon')
+ const file = await response.blob()
+ const originalFile = new File([file], 'server-icon-original.png', {
+ type: 'image/png',
+ })
- if (import.meta.client) {
- const dataURL = await new Promise((resolve) => {
- const canvas = document.createElement("canvas");
- const ctx = canvas.getContext("2d");
- const img = new Image();
- img.onload = () => {
- canvas.width = 64;
- canvas.height = 64;
- ctx?.drawImage(img, 0, 0, 64, 64);
- canvas.toBlob(async (blob) => {
- if (blob) {
- const scaledFile = new File([blob], "server-icon.png", {
- type: "image/png",
- });
- await useServersFetch(`/create?path=/server-icon.png&type=file`, {
- method: "POST",
- contentType: "application/octet-stream",
- body: scaledFile,
- override: auth,
- });
- await useServersFetch(`/create?path=/server-icon-original.png&type=file`, {
- method: "POST",
- contentType: "application/octet-stream",
- body: originalFile,
- override: auth,
- });
- }
- }, "image/png");
- const dataURL = canvas.toDataURL("image/png");
- sharedImage.value = dataURL;
- resolve(dataURL);
- URL.revokeObjectURL(img.src);
- };
- img.src = URL.createObjectURL(file);
- });
- return dataURL;
- }
- } catch (externalError: any) {
- console.debug("Could not process external icon:", externalError.message);
- }
- }
- } else {
- throw error;
- }
- }
- } catch (error: any) {
- console.debug("Icon processing failed:", error.message);
- }
+ if (import.meta.client) {
+ const dataURL = await new Promise((resolve) => {
+ const canvas = document.createElement('canvas')
+ const ctx = canvas.getContext('2d')
+ const img = new Image()
+ img.onload = () => {
+ canvas.width = 64
+ canvas.height = 64
+ ctx?.drawImage(img, 0, 0, 64, 64)
+ canvas.toBlob(async (blob) => {
+ if (blob) {
+ const scaledFile = new File([blob], 'server-icon.png', {
+ type: 'image/png',
+ })
+ await useServersFetch(`/create?path=/server-icon.png&type=file`, {
+ method: 'POST',
+ contentType: 'application/octet-stream',
+ body: scaledFile,
+ override: auth,
+ })
+ await useServersFetch(`/create?path=/server-icon-original.png&type=file`, {
+ method: 'POST',
+ contentType: 'application/octet-stream',
+ body: originalFile,
+ override: auth,
+ })
+ }
+ }, 'image/png')
+ const dataURL = canvas.toDataURL('image/png')
+ sharedImage.value = dataURL
+ resolve(dataURL)
+ URL.revokeObjectURL(img.src)
+ }
+ img.src = URL.createObjectURL(file)
+ })
+ return dataURL
+ }
+ } catch (externalError: any) {
+ console.debug('Could not process external icon:', externalError.message)
+ }
+ }
+ } else {
+ throw error
+ }
+ }
+ } catch (error: any) {
+ console.debug('Icon processing failed:', error.message)
+ }
- sharedImage.value = undefined;
- return undefined;
- }
+ sharedImage.value = undefined
+ return undefined
+ }
- async testNodeReachability(): Promise {
- if (!this.general?.node?.instance) {
- console.warn("No node instance available for ping test");
- return false;
- }
+ async testNodeReachability(): Promise {
+ if (!this.general?.node?.instance) {
+ console.warn('No node instance available for ping test')
+ return false
+ }
- const wsUrl = `wss://${this.general.node.instance}/pingtest`;
+ const wsUrl = `wss://${this.general.node.instance}/pingtest`
- try {
- return await new Promise((resolve) => {
- const socket = new WebSocket(wsUrl);
- const timeout = setTimeout(() => {
- socket.close();
- resolve(false);
- }, 5000);
+ try {
+ return await new Promise((resolve) => {
+ const socket = new WebSocket(wsUrl)
+ const timeout = setTimeout(() => {
+ socket.close()
+ resolve(false)
+ }, 5000)
- socket.onopen = () => {
- clearTimeout(timeout);
- socket.send(performance.now().toString());
- };
+ socket.onopen = () => {
+ clearTimeout(timeout)
+ socket.send(performance.now().toString())
+ }
- socket.onmessage = () => {
- clearTimeout(timeout);
- socket.close();
- resolve(true);
- };
+ socket.onmessage = () => {
+ clearTimeout(timeout)
+ socket.close()
+ resolve(true)
+ }
- socket.onerror = () => {
- clearTimeout(timeout);
- resolve(false);
- };
- });
- } catch (error) {
- console.error(`Failed to ping node ${wsUrl}:`, error);
- return false;
- }
- }
+ socket.onerror = () => {
+ clearTimeout(timeout)
+ resolve(false)
+ }
+ })
+ } catch (error) {
+ console.error(`Failed to ping node ${wsUrl}:`, error)
+ return false
+ }
+ }
- async refresh(
- modules: ModuleName[] = [],
- options?: {
- preserveConnection?: boolean;
- preserveInstallState?: boolean;
- },
- ): Promise {
- const modulesToRefresh =
- modules.length > 0
- ? modules
- : (["general", "content", "backups", "network", "startup", "ws", "fs"] as ModuleName[]);
+ async refresh(
+ modules: ModuleName[] = [],
+ options?: {
+ preserveConnection?: boolean
+ preserveInstallState?: boolean
+ },
+ ): Promise {
+ const modulesToRefresh =
+ modules.length > 0
+ ? modules
+ : (['general', 'content', 'backups', 'network', 'startup', 'ws', 'fs'] as ModuleName[])
- for (const module of modulesToRefresh) {
- this.errors[module] = undefined;
+ for (const module of modulesToRefresh) {
+ this.errors[module] = undefined
- try {
- switch (module) {
- case "general": {
- if (options?.preserveConnection) {
- const currentImage = this.general.image;
- const currentMotd = this.general.motd;
- const currentStatus = this.general.status;
+ try {
+ switch (module) {
+ case 'general': {
+ if (options?.preserveConnection) {
+ const currentImage = this.general.image
+ const currentMotd = this.general.motd
+ const currentStatus = this.general.status
- await this.general.fetch();
+ await this.general.fetch()
- if (currentImage) {
- this.general.image = currentImage;
- }
- if (currentMotd) {
- this.general.motd = currentMotd;
- }
- if (options.preserveInstallState && currentStatus === "installing") {
- this.general.status = "installing";
- }
- } else {
- await this.general.fetch();
- }
- break;
- }
- case "content":
- await this.content.fetch();
- break;
- case "backups":
- await this.backups.fetch();
- break;
- case "network":
- await this.network.fetch();
- break;
- case "startup":
- await this.startup.fetch();
- break;
- case "ws":
- await this.ws.fetch();
- break;
- case "fs":
- await this.fs.fetch();
- break;
- }
- } catch (error) {
- if (error instanceof ModrinthServerError) {
- if (error.statusCode === 404 && ["fs", "content"].includes(module)) {
- console.debug(`Optional ${module} resource not found:`, error.message);
- continue;
- }
+ if (currentImage) {
+ this.general.image = currentImage
+ }
+ if (currentMotd) {
+ this.general.motd = currentMotd
+ }
+ if (options.preserveInstallState && currentStatus === 'installing') {
+ this.general.status = 'installing'
+ }
+ } else {
+ await this.general.fetch()
+ }
+ break
+ }
+ case 'content':
+ await this.content.fetch()
+ break
+ case 'backups':
+ await this.backups.fetch()
+ break
+ case 'network':
+ await this.network.fetch()
+ break
+ case 'startup':
+ await this.startup.fetch()
+ break
+ case 'ws':
+ await this.ws.fetch()
+ break
+ case 'fs':
+ await this.fs.fetch()
+ break
+ }
+ } catch (error) {
+ if (error instanceof ModrinthServerError) {
+ if (error.statusCode === 404 && ['fs', 'content'].includes(module)) {
+ console.debug(`Optional ${module} resource not found:`, error.message)
+ continue
+ }
- if (error.statusCode && error.statusCode >= 500) {
- console.debug(`Temporary ${module} unavailable:`, error.message);
- continue;
- }
- }
+ if (error.statusCode && error.statusCode >= 500) {
+ console.debug(`Temporary ${module} unavailable:`, error.message)
+ continue
+ }
+ }
- this.errors[module] = {
- error:
- error instanceof ModrinthServerError
- ? error
- : new ModrinthServerError("Unknown error", undefined, error as Error),
- timestamp: Date.now(),
- };
- }
- }
- }
+ this.errors[module] = {
+ error:
+ error instanceof ModrinthServerError
+ ? error
+ : new ModrinthServerError('Unknown error', undefined, error as Error),
+ timestamp: Date.now(),
+ }
+ }
+ }
+ }
- get moduleErrors() {
- return this.errors;
- }
+ get moduleErrors() {
+ return this.errors
+ }
}
export const useModrinthServers = async (
- serverId: string,
- includedModules: ModuleName[] = ["general"],
+ serverId: string,
+ includedModules: ModuleName[] = ['general'],
) => {
- const server = new ModrinthServer(serverId);
- await server.refresh(includedModules);
- return reactive(server);
-};
+ const server = new ModrinthServer(serverId)
+ await server.refresh(includedModules)
+ return reactive(server)
+}
diff --git a/apps/frontend/src/composables/servers/modules/backups.ts b/apps/frontend/src/composables/servers/modules/backups.ts
index 2dbaac1a..81a4bc81 100644
--- a/apps/frontend/src/composables/servers/modules/backups.ts
+++ b/apps/frontend/src/composables/servers/modules/backups.ts
@@ -1,79 +1,80 @@
-import type { Backup, AutoBackupSettings } from "@modrinth/utils";
-import { useServersFetch } from "../servers-fetch.ts";
-import { ServerModule } from "./base.ts";
+import type { AutoBackupSettings, Backup } from '@modrinth/utils'
+
+import { useServersFetch } from '../servers-fetch.ts'
+import { ServerModule } from './base.ts'
export class BackupsModule extends ServerModule {
- data: Backup[] = [];
+ data: Backup[] = []
- async fetch(): Promise {
- this.data = await useServersFetch(`servers/${this.serverId}/backups`, {}, "backups");
- }
+ async fetch(): Promise {
+ this.data = await useServersFetch(`servers/${this.serverId}/backups`, {}, 'backups')
+ }
- async create(backupName: string): Promise {
- const response = await useServersFetch<{ id: string }>(`servers/${this.serverId}/backups`, {
- method: "POST",
- body: { name: backupName },
- });
- await this.fetch(); // Refresh this module
- return response.id;
- }
+ async create(backupName: string): Promise {
+ const response = await useServersFetch<{ id: string }>(`servers/${this.serverId}/backups`, {
+ method: 'POST',
+ body: { name: backupName },
+ })
+ await this.fetch() // Refresh this module
+ return response.id
+ }
- async rename(backupId: string, newName: string): Promise {
- await useServersFetch(`servers/${this.serverId}/backups/${backupId}/rename`, {
- method: "POST",
- body: { name: newName },
- });
- await this.fetch(); // Refresh this module
- }
+ async rename(backupId: string, newName: string): Promise {
+ await useServersFetch(`servers/${this.serverId}/backups/${backupId}/rename`, {
+ method: 'POST',
+ body: { name: newName },
+ })
+ await this.fetch() // Refresh this module
+ }
- async delete(backupId: string): Promise {
- await useServersFetch(`servers/${this.serverId}/backups/${backupId}`, {
- method: "DELETE",
- });
- await this.fetch(); // Refresh this module
- }
+ async delete(backupId: string): Promise {
+ await useServersFetch(`servers/${this.serverId}/backups/${backupId}`, {
+ method: 'DELETE',
+ })
+ await this.fetch() // Refresh this module
+ }
- async restore(backupId: string): Promise {
- await useServersFetch(`servers/${this.serverId}/backups/${backupId}/restore`, {
- method: "POST",
- });
- await this.fetch(); // Refresh this module
- }
+ async restore(backupId: string): Promise {
+ await useServersFetch(`servers/${this.serverId}/backups/${backupId}/restore`, {
+ method: 'POST',
+ })
+ await this.fetch() // Refresh this module
+ }
- async prepare(backupId: string): Promise {
- await useServersFetch(`servers/${this.serverId}/backups/${backupId}/prepare-download`, {
- method: "POST",
- });
- }
+ async prepare(backupId: string): Promise {
+ await useServersFetch(`servers/${this.serverId}/backups/${backupId}/prepare-download`, {
+ method: 'POST',
+ })
+ }
- async lock(backupId: string): Promise {
- await useServersFetch(`servers/${this.serverId}/backups/${backupId}/lock`, {
- method: "POST",
- });
- await this.fetch(); // Refresh this module
- }
+ async lock(backupId: string): Promise {
+ await useServersFetch(`servers/${this.serverId}/backups/${backupId}/lock`, {
+ method: 'POST',
+ })
+ await this.fetch() // Refresh this module
+ }
- async unlock(backupId: string): Promise {
- await useServersFetch(`servers/${this.serverId}/backups/${backupId}/unlock`, {
- method: "POST",
- });
- await this.fetch(); // Refresh this module
- }
+ async unlock(backupId: string): Promise {
+ await useServersFetch(`servers/${this.serverId}/backups/${backupId}/unlock`, {
+ method: 'POST',
+ })
+ await this.fetch() // Refresh this module
+ }
- async retry(backupId: string): Promise {
- await useServersFetch(`servers/${this.serverId}/backups/${backupId}/retry`, {
- method: "POST",
- });
- }
+ async retry(backupId: string): Promise {
+ await useServersFetch(`servers/${this.serverId}/backups/${backupId}/retry`, {
+ method: 'POST',
+ })
+ }
- async updateAutoBackup(autoBackup: "enable" | "disable", interval: number): Promise {
- await useServersFetch(`servers/${this.serverId}/autobackup`, {
- method: "POST",
- body: { set: autoBackup, interval },
- });
- }
+ async updateAutoBackup(autoBackup: 'enable' | 'disable', interval: number): Promise {
+ await useServersFetch(`servers/${this.serverId}/autobackup`, {
+ method: 'POST',
+ body: { set: autoBackup, interval },
+ })
+ }
- async getAutoBackup(): Promise {
- return await useServersFetch(`servers/${this.serverId}/autobackup`);
- }
+ async getAutoBackup(): Promise {
+ return await useServersFetch(`servers/${this.serverId}/autobackup`)
+ }
}
diff --git a/apps/frontend/src/composables/servers/modules/base.ts b/apps/frontend/src/composables/servers/modules/base.ts
index 84495d74..151fadf2 100644
--- a/apps/frontend/src/composables/servers/modules/base.ts
+++ b/apps/frontend/src/composables/servers/modules/base.ts
@@ -1,15 +1,15 @@
-import type { ModrinthServer } from "../modrinth-servers.ts";
+import type { ModrinthServer } from '../modrinth-servers.ts'
export abstract class ServerModule {
- protected server: ModrinthServer;
+ protected server: ModrinthServer
- constructor(server: ModrinthServer) {
- this.server = server;
- }
+ constructor(server: ModrinthServer) {
+ this.server = server
+ }
- protected get serverId(): string {
- return this.server.serverId;
- }
+ protected get serverId(): string {
+ return this.server.serverId
+ }
- abstract fetch(): Promise;
+ abstract fetch(): Promise
}
diff --git a/apps/frontend/src/composables/servers/modules/content.ts b/apps/frontend/src/composables/servers/modules/content.ts
index e05c6723..2db34b76 100644
--- a/apps/frontend/src/composables/servers/modules/content.ts
+++ b/apps/frontend/src/composables/servers/modules/content.ts
@@ -1,36 +1,37 @@
-import type { Mod, ContentType } from "@modrinth/utils";
-import { useServersFetch } from "../servers-fetch.ts";
-import { ServerModule } from "./base.ts";
+import type { ContentType, Mod } from '@modrinth/utils'
+
+import { useServersFetch } from '../servers-fetch.ts'
+import { ServerModule } from './base.ts'
export class ContentModule extends ServerModule {
- data: Mod[] = [];
+ data: Mod[] = []
- async fetch(): Promise {
- const mods = await useServersFetch(`servers/${this.serverId}/mods`, {}, "content");
- this.data = mods.sort((a, b) => (a?.name ?? "").localeCompare(b?.name ?? ""));
- }
+ async fetch(): Promise {
+ const mods = await useServersFetch(`servers/${this.serverId}/mods`, {}, 'content')
+ this.data = mods.sort((a, b) => (a?.name ?? '').localeCompare(b?.name ?? ''))
+ }
- async install(contentType: ContentType, projectId: string, versionId: string): Promise {
- await useServersFetch(`servers/${this.serverId}/mods`, {
- method: "POST",
- body: {
- rinth_ids: { project_id: projectId, version_id: versionId },
- install_as: contentType,
- },
- });
- }
+ async install(contentType: ContentType, projectId: string, versionId: string): Promise {
+ await useServersFetch(`servers/${this.serverId}/mods`, {
+ method: 'POST',
+ body: {
+ rinth_ids: { project_id: projectId, version_id: versionId },
+ install_as: contentType,
+ },
+ })
+ }
- async remove(path: string): Promise {
- await useServersFetch(`servers/${this.serverId}/deleteMod`, {
- method: "POST",
- body: { path },
- });
- }
+ async remove(path: string): Promise {
+ await useServersFetch(`servers/${this.serverId}/deleteMod`, {
+ method: 'POST',
+ body: { path },
+ })
+ }
- async reinstall(replace: string, projectId: string, versionId: string): Promise {
- await useServersFetch(`servers/${this.serverId}/mods/update`, {
- method: "POST",
- body: { replace, project_id: projectId, version_id: versionId },
- });
- }
+ async reinstall(replace: string, projectId: string, versionId: string): Promise {
+ await useServersFetch(`servers/${this.serverId}/mods/update`, {
+ method: 'POST',
+ body: { replace, project_id: projectId, version_id: versionId },
+ })
+ }
}
diff --git a/apps/frontend/src/composables/servers/modules/fs.ts b/apps/frontend/src/composables/servers/modules/fs.ts
index 39fe75db..fdf2a1cf 100644
--- a/apps/frontend/src/composables/servers/modules/fs.ts
+++ b/apps/frontend/src/composables/servers/modules/fs.ts
@@ -1,247 +1,248 @@
import type {
- FileUploadQuery,
- JWTAuth,
- DirectoryResponse,
- FilesystemOp,
- FSQueuedOp,
-} from "@modrinth/utils";
-import { ModrinthServerError } from "@modrinth/utils";
-import { useServersFetch } from "../servers-fetch.ts";
-import { ServerModule } from "./base.ts";
+ DirectoryResponse,
+ FilesystemOp,
+ FileUploadQuery,
+ FSQueuedOp,
+ JWTAuth,
+} from '@modrinth/utils'
+import { ModrinthServerError } from '@modrinth/utils'
+
+import { useServersFetch } from '../servers-fetch.ts'
+import { ServerModule } from './base.ts'
export class FSModule extends ServerModule {
- auth!: JWTAuth;
- ops: FilesystemOp[] = [];
- queuedOps: FSQueuedOp[] = [];
- opsQueuedForModification: string[] = [];
+ auth!: JWTAuth
+ ops: FilesystemOp[] = []
+ queuedOps: FSQueuedOp[] = []
+ opsQueuedForModification: string[] = []
- async fetch(): Promise {
- this.auth = await useServersFetch(`servers/${this.serverId}/fs`, {}, "fs");
- this.ops = [];
- this.queuedOps = [];
- this.opsQueuedForModification = [];
- }
+ async fetch(): Promise {
+ this.auth = await useServersFetch(`servers/${this.serverId}/fs`, {}, 'fs')
+ this.ops = []
+ this.queuedOps = []
+ this.opsQueuedForModification = []
+ }
- private async retryWithAuth(
- requestFn: () => Promise,
- ignoreFailure: boolean = false,
- ): Promise {
- try {
- return await requestFn();
- } catch (error) {
- if (error instanceof ModrinthServerError && error.statusCode === 401) {
- console.debug("Auth failed, refreshing JWT and retrying");
- await this.fetch(); // Refresh auth
- return await requestFn();
- }
+ private async retryWithAuth(
+ requestFn: () => Promise,
+ ignoreFailure: boolean = false,
+ ): Promise {
+ try {
+ return await requestFn()
+ } catch (error) {
+ if (error instanceof ModrinthServerError && error.statusCode === 401) {
+ console.debug('Auth failed, refreshing JWT and retrying')
+ await this.fetch() // Refresh auth
+ return await requestFn()
+ }
- const available = await this.server.testNodeReachability();
- if (!available && !ignoreFailure) {
- this.server.moduleErrors.general = {
- error: new ModrinthServerError(
- "Unable to reach node. FS operation failed and subsequent ping test failed.",
- 500,
- error as Error,
- "fs",
- ),
- timestamp: Date.now(),
- };
- }
+ const available = await this.server.testNodeReachability()
+ if (!available && !ignoreFailure) {
+ this.server.moduleErrors.general = {
+ error: new ModrinthServerError(
+ 'Unable to reach node. FS operation failed and subsequent ping test failed.',
+ 500,
+ error as Error,
+ 'fs',
+ ),
+ timestamp: Date.now(),
+ }
+ }
- throw error;
- }
- }
+ throw error
+ }
+ }
- listDirContents(
- path: string,
- page: number,
- pageSize: number,
- ignoreFailure: boolean = false,
- ): Promise {
- return this.retryWithAuth(async () => {
- const encodedPath = encodeURIComponent(path);
- return await useServersFetch(`/list?path=${encodedPath}&page=${page}&page_size=${pageSize}`, {
- override: this.auth,
- retry: false,
- });
- }, ignoreFailure);
- }
+ listDirContents(
+ path: string,
+ page: number,
+ pageSize: number,
+ ignoreFailure: boolean = false,
+ ): Promise {
+ return this.retryWithAuth(async () => {
+ const encodedPath = encodeURIComponent(path)
+ return await useServersFetch(`/list?path=${encodedPath}&page=${page}&page_size=${pageSize}`, {
+ override: this.auth,
+ retry: false,
+ })
+ }, ignoreFailure)
+ }
- createFileOrFolder(path: string, type: "file" | "directory"): Promise {
- return this.retryWithAuth(async () => {
- const encodedPath = encodeURIComponent(path);
- await useServersFetch(`/create?path=${encodedPath}&type=${type}`, {
- method: "POST",
- contentType: "application/octet-stream",
- override: this.auth,
- });
- });
- }
+ createFileOrFolder(path: string, type: 'file' | 'directory'): Promise {
+ return this.retryWithAuth(async () => {
+ const encodedPath = encodeURIComponent(path)
+ await useServersFetch(`/create?path=${encodedPath}&type=${type}`, {
+ method: 'POST',
+ contentType: 'application/octet-stream',
+ override: this.auth,
+ })
+ })
+ }
- uploadFile(path: string, file: File): FileUploadQuery {
- const encodedPath = encodeURIComponent(path);
- const progressSubject = new EventTarget();
- const abortController = new AbortController();
+ uploadFile(path: string, file: File): FileUploadQuery {
+ const encodedPath = encodeURIComponent(path)
+ const progressSubject = new EventTarget()
+ const abortController = new AbortController()
- const uploadPromise = new Promise((resolve, reject) => {
- const xhr = new XMLHttpRequest();
+ const uploadPromise = new Promise((resolve, reject) => {
+ const xhr = new XMLHttpRequest()
- xhr.upload.addEventListener("progress", (e) => {
- if (e.lengthComputable) {
- const progress = (e.loaded / e.total) * 100;
- progressSubject.dispatchEvent(
- new CustomEvent("progress", {
- detail: { loaded: e.loaded, total: e.total, progress },
- }),
- );
- }
- });
+ xhr.upload.addEventListener('progress', (e) => {
+ if (e.lengthComputable) {
+ const progress = (e.loaded / e.total) * 100
+ progressSubject.dispatchEvent(
+ new CustomEvent('progress', {
+ detail: { loaded: e.loaded, total: e.total, progress },
+ }),
+ )
+ }
+ })
- xhr.onload = () => {
- if (xhr.status >= 200 && xhr.status < 300) {
- resolve(xhr.response);
- } else {
- reject(new Error(`Upload failed with status ${xhr.status}`));
- }
- };
+ xhr.onload = () => {
+ if (xhr.status >= 200 && xhr.status < 300) {
+ resolve(xhr.response)
+ } else {
+ reject(new Error(`Upload failed with status ${xhr.status}`))
+ }
+ }
- xhr.onerror = () => reject(new Error("Upload failed"));
- xhr.onabort = () => reject(new Error("Upload cancelled"));
+ xhr.onerror = () => reject(new Error('Upload failed'))
+ xhr.onabort = () => reject(new Error('Upload cancelled'))
- xhr.open("POST", `https://${this.auth.url}/create?path=${encodedPath}&type=file`);
- xhr.setRequestHeader("Authorization", `Bearer ${this.auth.token}`);
- xhr.setRequestHeader("Content-Type", "application/octet-stream");
- xhr.send(file);
+ xhr.open('POST', `https://${this.auth.url}/create?path=${encodedPath}&type=file`)
+ xhr.setRequestHeader('Authorization', `Bearer ${this.auth.token}`)
+ xhr.setRequestHeader('Content-Type', 'application/octet-stream')
+ xhr.send(file)
- abortController.signal.addEventListener("abort", () => xhr.abort());
- });
+ abortController.signal.addEventListener('abort', () => xhr.abort())
+ })
- return {
- promise: uploadPromise,
- onProgress: (
- callback: (progress: { loaded: number; total: number; progress: number }) => void,
- ) => {
- progressSubject.addEventListener("progress", ((e: CustomEvent) => {
- callback(e.detail);
- }) as EventListener);
- },
- cancel: () => abortController.abort(),
- } as FileUploadQuery;
- }
+ return {
+ promise: uploadPromise,
+ onProgress: (
+ callback: (progress: { loaded: number; total: number; progress: number }) => void,
+ ) => {
+ progressSubject.addEventListener('progress', ((e: CustomEvent) => {
+ callback(e.detail)
+ }) as EventListener)
+ },
+ cancel: () => abortController.abort(),
+ } as FileUploadQuery
+ }
- renameFileOrFolder(path: string, name: string): Promise {
- const pathName = path.split("/").slice(0, -1).join("/") + "/" + name;
- return this.retryWithAuth(async () => {
- await useServersFetch(`/move`, {
- method: "POST",
- override: this.auth,
- body: { source: path, destination: pathName },
- });
- });
- }
+ renameFileOrFolder(path: string, name: string): Promise {
+ const pathName = path.split('/').slice(0, -1).join('/') + '/' + name
+ return this.retryWithAuth(async () => {
+ await useServersFetch(`/move`, {
+ method: 'POST',
+ override: this.auth,
+ body: { source: path, destination: pathName },
+ })
+ })
+ }
- updateFile(path: string, content: string): Promise {
- const octetStream = new Blob([content], { type: "application/octet-stream" });
- return this.retryWithAuth(async () => {
- await useServersFetch(`/update?path=${path}`, {
- method: "PUT",
- contentType: "application/octet-stream",
- body: octetStream,
- override: this.auth,
- });
- });
- }
+ updateFile(path: string, content: string): Promise {
+ const octetStream = new Blob([content], { type: 'application/octet-stream' })
+ return this.retryWithAuth(async () => {
+ await useServersFetch(`/update?path=${path}`, {
+ method: 'PUT',
+ contentType: 'application/octet-stream',
+ body: octetStream,
+ override: this.auth,
+ })
+ })
+ }
- moveFileOrFolder(path: string, newPath: string): Promise {
- return this.retryWithAuth(async () => {
- await this.server.createMissingFolders(newPath.substring(0, newPath.lastIndexOf("/")));
- await useServersFetch(`/move`, {
- method: "POST",
- override: this.auth,
- body: { source: path, destination: newPath },
- });
- });
- }
+ moveFileOrFolder(path: string, newPath: string): Promise {
+ return this.retryWithAuth(async () => {
+ await this.server.createMissingFolders(newPath.substring(0, newPath.lastIndexOf('/')))
+ await useServersFetch(`/move`, {
+ method: 'POST',
+ override: this.auth,
+ body: { source: path, destination: newPath },
+ })
+ })
+ }
- deleteFileOrFolder(path: string, recursive: boolean): Promise {
- const encodedPath = encodeURIComponent(path);
- return this.retryWithAuth(async () => {
- await useServersFetch(`/delete?path=${encodedPath}&recursive=${recursive}`, {
- method: "DELETE",
- override: this.auth,
- });
- });
- }
+ deleteFileOrFolder(path: string, recursive: boolean): Promise {
+ const encodedPath = encodeURIComponent(path)
+ return this.retryWithAuth(async () => {
+ await useServersFetch(`/delete?path=${encodedPath}&recursive=${recursive}`, {
+ method: 'DELETE',
+ override: this.auth,
+ })
+ })
+ }
- downloadFile(path: string, raw: boolean = false, ignoreFailure: boolean = false): Promise {
- return this.retryWithAuth(async () => {
- const encodedPath = encodeURIComponent(path);
- const fileData = await useServersFetch(`/download?path=${encodedPath}`, {
- override: this.auth,
- });
+ downloadFile(path: string, raw: boolean = false, ignoreFailure: boolean = false): Promise {
+ return this.retryWithAuth(async () => {
+ const encodedPath = encodeURIComponent(path)
+ const fileData = await useServersFetch(`/download?path=${encodedPath}`, {
+ override: this.auth,
+ })
- if (fileData instanceof Blob) {
- return raw ? fileData : await fileData.text();
- }
- return fileData;
- }, ignoreFailure);
- }
+ if (fileData instanceof Blob) {
+ return raw ? fileData : await fileData.text()
+ }
+ return fileData
+ }, ignoreFailure)
+ }
- extractFile(
- path: string,
- override = true,
- dry = false,
- silentQueue = false,
- ): Promise<{ modpack_name: string | null; conflicting_files: string[] }> {
- return this.retryWithAuth(async () => {
- const encodedPath = encodeURIComponent(path);
+ extractFile(
+ path: string,
+ override = true,
+ dry = false,
+ silentQueue = false,
+ ): Promise<{ modpack_name: string | null; conflicting_files: string[] }> {
+ return this.retryWithAuth(async () => {
+ const encodedPath = encodeURIComponent(path)
- if (!silentQueue) {
- this.queuedOps.push({ op: "unarchive", src: path });
- setTimeout(() => this.removeQueuedOp("unarchive", path), 4000);
- }
+ if (!silentQueue) {
+ this.queuedOps.push({ op: 'unarchive', src: path })
+ setTimeout(() => this.removeQueuedOp('unarchive', path), 4000)
+ }
- try {
- return await useServersFetch(
- `/unarchive?src=${encodedPath}&trg=/&override=${override}&dry=${dry}`,
- {
- method: "POST",
- override: this.auth,
- version: 1,
- },
- undefined,
- "Error extracting file",
- );
- } catch (err) {
- this.removeQueuedOp("unarchive", path);
- throw err;
- }
- });
- }
+ try {
+ return await useServersFetch(
+ `/unarchive?src=${encodedPath}&trg=/&override=${override}&dry=${dry}`,
+ {
+ method: 'POST',
+ override: this.auth,
+ version: 1,
+ },
+ undefined,
+ 'Error extracting file',
+ )
+ } catch (err) {
+ this.removeQueuedOp('unarchive', path)
+ throw err
+ }
+ })
+ }
- modifyOp(id: string, action: "dismiss" | "cancel"): Promise {
- return this.retryWithAuth(async () => {
- await useServersFetch(
- `/ops/${action}?id=${id}`,
- {
- method: "POST",
- override: this.auth,
- version: 1,
- },
- undefined,
- `Error ${action === "dismiss" ? "dismissing" : "cancelling"} filesystem operation`,
- );
+ modifyOp(id: string, action: 'dismiss' | 'cancel'): Promise {
+ return this.retryWithAuth(async () => {
+ await useServersFetch(
+ `/ops/${action}?id=${id}`,
+ {
+ method: 'POST',
+ override: this.auth,
+ version: 1,
+ },
+ undefined,
+ `Error ${action === 'dismiss' ? 'dismissing' : 'cancelling'} filesystem operation`,
+ )
- this.opsQueuedForModification = this.opsQueuedForModification.filter((x: string) => x !== id);
- this.ops = this.ops.filter((x: FilesystemOp) => x.id !== id);
- });
- }
+ this.opsQueuedForModification = this.opsQueuedForModification.filter((x: string) => x !== id)
+ this.ops = this.ops.filter((x: FilesystemOp) => x.id !== id)
+ })
+ }
- removeQueuedOp(op: FSQueuedOp["op"], src: string): void {
- this.queuedOps = this.queuedOps.filter((x: FSQueuedOp) => x.op !== op || x.src !== src);
- }
+ removeQueuedOp(op: FSQueuedOp['op'], src: string): void {
+ this.queuedOps = this.queuedOps.filter((x: FSQueuedOp) => x.op !== op || x.src !== src)
+ }
- clearQueuedOps(): void {
- this.queuedOps = [];
- }
+ clearQueuedOps(): void {
+ this.queuedOps = []
+ }
}
diff --git a/apps/frontend/src/composables/servers/modules/general.ts b/apps/frontend/src/composables/servers/modules/general.ts
index e46e62b4..8ab0bd6a 100644
--- a/apps/frontend/src/composables/servers/modules/general.ts
+++ b/apps/frontend/src/composables/servers/modules/general.ts
@@ -1,223 +1,229 @@
-import { $fetch } from "ofetch";
-import type { ServerGeneral, Project, PowerAction, JWTAuth } from "@modrinth/utils";
-import { useServersFetch } from "../servers-fetch.ts";
-import { ServerModule } from "./base.ts";
+import type { JWTAuth, PowerAction, Project, ServerGeneral } from '@modrinth/utils'
+import { $fetch } from 'ofetch'
+
+import { useServersFetch } from '../servers-fetch.ts'
+import { ServerModule } from './base.ts'
export class GeneralModule extends ServerModule implements ServerGeneral {
- server_id!: string;
- name!: string;
- net!: { ip: string; port: number; domain: string };
- game!: string;
- backup_quota!: number;
- used_backup_quota!: number;
- status!: string;
- suspension_reason!: string;
- loader!: string;
- loader_version!: string;
- mc_version!: string;
- upstream!: {
- kind: "modpack" | "mod" | "resourcepack";
- version_id: string;
- project_id: string;
- } | null;
+ server_id!: string
+ name!: string
+ owner_id!: string
+ net!: { ip: string; port: number; domain: string }
+ game!: string
+ backup_quota!: number
+ used_backup_quota!: number
+ status!: string
+ suspension_reason!: string
+ loader!: string
+ loader_version!: string
+ mc_version!: string
+ upstream!: {
+ kind: 'modpack' | 'mod' | 'resourcepack'
+ version_id: string
+ project_id: string
+ } | null
- motd?: string;
- image?: string;
- project?: Project;
- sftp_username!: string;
- sftp_password!: string;
- sftp_host!: string;
- datacenter?: string;
- notices?: any[];
- node!: { token: string; instance: string };
- flows?: { intro?: boolean };
+ motd?: string
+ image?: string
+ project?: Project
+ sftp_username!: string
+ sftp_password!: string
+ sftp_host!: string
+ datacenter?: string
+ notices?: any[]
+ node!: { token: string; instance: string }
+ flows?: { intro?: boolean }
- async fetch(): Promise {
- const data = await useServersFetch(`servers/${this.serverId}`, {}, "general");
+ async fetch(): Promise {
+ const data = await useServersFetch(`servers/${this.serverId}`, {}, 'general')
- if (data.upstream?.project_id) {
- const project = await $fetch(
- `https://api.modrinth.com/v2/project/${data.upstream.project_id}`,
- );
- data.project = project as Project;
- }
+ if (data.upstream?.project_id) {
+ const project = await $fetch(
+ `https://api.modrinth.com/v2/project/${data.upstream.project_id}`,
+ )
+ data.project = project as Project
+ }
- if (import.meta.client) {
- data.image = (await this.server.processImage(data.project?.icon_url)) ?? undefined;
- }
+ if (import.meta.client) {
+ data.image = (await this.server.processImage(data.project?.icon_url)) ?? undefined
+ }
- try {
- const motd = await this.getMotd();
- if (motd === "A Minecraft Server") {
- await this.setMotd(
- `§b${data.project?.title || data.loader + " " + data.mc_version} §f♦ §aModrinth Servers`,
- );
- }
- data.motd = motd;
- } catch {
- console.error("[Modrinth Servers] [General] Failed to fetch MOTD.");
- data.motd = undefined;
- }
+ try {
+ const motd = await this.getMotd()
+ if (motd === 'A Minecraft Server') {
+ await this.setMotd(
+ `§b${data.project?.title || data.loader + ' ' + data.mc_version} §f♦ §aModrinth Servers`,
+ )
+ }
+ data.motd = motd
+ } catch {
+ console.error('[Modrinth Servers] [General] Failed to fetch MOTD.')
+ data.motd = undefined
+ }
- // Copy data to this module
- Object.assign(this, data);
- }
+ // Copy data to this module
+ Object.assign(this, data)
+ }
- async updateName(newName: string): Promise {
- await useServersFetch(`servers/${this.serverId}/name`, {
- method: "POST",
- body: { name: newName },
- });
- }
+ async updateName(newName: string): Promise {
+ await useServersFetch(`servers/${this.serverId}/name`, {
+ method: 'POST',
+ body: { name: newName },
+ })
+ }
- async power(action: PowerAction): Promise {
- await useServersFetch(`servers/${this.serverId}/power`, {
- method: "POST",
- body: { action },
- });
- await new Promise((resolve) => setTimeout(resolve, 1000));
- await this.fetch(); // Refresh this module
- }
+ async power(action: PowerAction): Promise {
+ await useServersFetch(`servers/${this.serverId}/power`, {
+ method: 'POST',
+ body: { action },
+ })
+ await new Promise((resolve) => setTimeout(resolve, 1000))
+ await this.fetch() // Refresh this module
+ }
- async reinstall(
- loader: boolean,
- projectId: string,
- versionId?: string,
- loaderVersionId?: string,
- hardReset: boolean = false,
- ): Promise {
- const hardResetParam = hardReset ? "true" : "false";
- if (loader) {
- if (projectId.toLowerCase() === "neoforge") {
- projectId = "NeoForge";
- }
- await useServersFetch(`servers/${this.serverId}/reinstall?hard=${hardResetParam}`, {
- method: "POST",
- body: { loader: projectId, loader_version: loaderVersionId, game_version: versionId },
- });
- } else {
- await useServersFetch(`servers/${this.serverId}/reinstall?hard=${hardResetParam}`, {
- method: "POST",
- body: { project_id: projectId, version_id: versionId },
- });
- }
- }
+ async reinstall(
+ loader: boolean,
+ projectId: string,
+ versionId?: string,
+ loaderVersionId?: string,
+ hardReset: boolean = false,
+ ): Promise {
+ const hardResetParam = hardReset ? 'true' : 'false'
+ if (loader) {
+ if (projectId.toLowerCase() === 'neoforge') {
+ projectId = 'NeoForge'
+ }
+ await useServersFetch(`servers/${this.serverId}/reinstall?hard=${hardResetParam}`, {
+ method: 'POST',
+ body: {
+ loader: projectId,
+ loader_version: loaderVersionId,
+ game_version: versionId,
+ },
+ })
+ } else {
+ await useServersFetch(`servers/${this.serverId}/reinstall?hard=${hardResetParam}`, {
+ method: 'POST',
+ body: { project_id: projectId, version_id: versionId },
+ })
+ }
+ }
- reinstallFromMrpack(
- mrpack: File,
- hardReset: boolean = false,
- ): {
- promise: Promise;
- onProgress: (cb: (p: { loaded: number; total: number; progress: number }) => void) => void;
- } {
- const hardResetParam = hardReset ? "true" : "false";
+ reinstallFromMrpack(
+ mrpack: File,
+ hardReset: boolean = false,
+ ): {
+ promise: Promise
+ onProgress: (cb: (p: { loaded: number; total: number; progress: number }) => void) => void
+ } {
+ const hardResetParam = hardReset ? 'true' : 'false'
- const progressSubject = new EventTarget();
+ const progressSubject = new EventTarget()
- const uploadPromise = (async () => {
- try {
- const auth = await useServersFetch(`servers/${this.serverId}/reinstallFromMrpack`);
+ const uploadPromise = (async () => {
+ try {
+ const auth = await useServersFetch(`servers/${this.serverId}/reinstallFromMrpack`)
- await new Promise((resolve, reject) => {
- const xhr = new XMLHttpRequest();
+ await new Promise((resolve, reject) => {
+ const xhr = new XMLHttpRequest()
- xhr.upload.addEventListener("progress", (e) => {
- if (e.lengthComputable) {
- progressSubject.dispatchEvent(
- new CustomEvent("progress", {
- detail: {
- loaded: e.loaded,
- total: e.total,
- progress: (e.loaded / e.total) * 100,
- },
- }),
- );
- }
- });
+ xhr.upload.addEventListener('progress', (e) => {
+ if (e.lengthComputable) {
+ progressSubject.dispatchEvent(
+ new CustomEvent('progress', {
+ detail: {
+ loaded: e.loaded,
+ total: e.total,
+ progress: (e.loaded / e.total) * 100,
+ },
+ }),
+ )
+ }
+ })
- xhr.onload = () =>
- xhr.status >= 200 && xhr.status < 300
- ? resolve()
- : reject(new Error(`[pyroservers] XHR error status: ${xhr.status}`));
+ xhr.onload = () =>
+ xhr.status >= 200 && xhr.status < 300
+ ? resolve()
+ : reject(new Error(`[pyroservers] XHR error status: ${xhr.status}`))
- xhr.onerror = () => reject(new Error("[pyroservers] .mrpack upload failed"));
- xhr.onabort = () => reject(new Error("[pyroservers] .mrpack upload cancelled"));
- xhr.ontimeout = () => reject(new Error("[pyroservers] .mrpack upload timed out"));
- xhr.timeout = 30 * 60 * 1000;
+ xhr.onerror = () => reject(new Error('[pyroservers] .mrpack upload failed'))
+ xhr.onabort = () => reject(new Error('[pyroservers] .mrpack upload cancelled'))
+ xhr.ontimeout = () => reject(new Error('[pyroservers] .mrpack upload timed out'))
+ xhr.timeout = 30 * 60 * 1000
- xhr.open("POST", `https://${auth.url}/reinstallMrpackMultiparted?hard=${hardResetParam}`);
- xhr.setRequestHeader("Authorization", `Bearer ${auth.token}`);
+ xhr.open('POST', `https://${auth.url}/reinstallMrpackMultiparted?hard=${hardResetParam}`)
+ xhr.setRequestHeader('Authorization', `Bearer ${auth.token}`)
- const formData = new FormData();
- formData.append("file", mrpack);
- xhr.send(formData);
- });
- } catch (err) {
- console.error("Error reinstalling from mrpack:", err);
- throw err;
- }
- })();
+ const formData = new FormData()
+ formData.append('file', mrpack)
+ xhr.send(formData)
+ })
+ } catch (err) {
+ console.error('Error reinstalling from mrpack:', err)
+ throw err
+ }
+ })()
- return {
- promise: uploadPromise,
- onProgress: (cb: (p: { loaded: number; total: number; progress: number }) => void) =>
- progressSubject.addEventListener("progress", ((e: CustomEvent) =>
- cb(e.detail)) as EventListener),
- };
- }
+ return {
+ promise: uploadPromise,
+ onProgress: (cb: (p: { loaded: number; total: number; progress: number }) => void) =>
+ progressSubject.addEventListener('progress', ((e: CustomEvent) =>
+ cb(e.detail)) as EventListener),
+ }
+ }
- async suspend(status: boolean): Promise {
- await useServersFetch(`servers/${this.serverId}/suspend`, {
- method: "POST",
- body: { suspended: status },
- });
- }
+ async suspend(status: boolean): Promise {
+ await useServersFetch(`servers/${this.serverId}/suspend`, {
+ method: 'POST',
+ body: { suspended: status },
+ })
+ }
- async endIntro(): Promise