🔨 chore: bump deps
Signed-off-by: Pauline <git@ethanlibs.co>
This commit is contained in:
parent
f50d99a2bc
commit
992af34764
97 changed files with 1211 additions and 1283 deletions
12
.github/actions/clippy/src/index.ts
vendored
12
.github/actions/clippy/src/index.ts
vendored
|
|
@ -1,11 +1,11 @@
|
|||
import { tmpdir as getTmpdir } from 'node:os';
|
||||
import { promises as fs } from 'node:fs';
|
||||
import { env, cwd as getCwd } from 'node:process';
|
||||
import { Buffer } from 'node:buffer';
|
||||
import { join, relative } from 'pathe';
|
||||
import { rmRF } from '@actions/io';
|
||||
import { exec } from '@actions/exec';
|
||||
import { promises as fs } from 'node:fs';
|
||||
import { tmpdir as getTmpdir } from 'node:os';
|
||||
import { env, cwd as getCwd } from 'node:process';
|
||||
import { getInput as getCoreInput, group } from '@actions/core';
|
||||
import { exec } from '@actions/exec';
|
||||
import { rmRF } from '@actions/io';
|
||||
import { join, relative } from 'pathe';
|
||||
import { installReviewdog } from './installer';
|
||||
|
||||
const getInput = <T = string>(name: string): T => getCoreInput(name) as T;
|
||||
|
|
|
|||
2
.github/actions/clippy/src/installer.ts
vendored
2
.github/actions/clippy/src/installer.ts
vendored
|
|
@ -1,7 +1,7 @@
|
|||
import { arch as getArch, platform as getPlatform } from 'node:process';
|
||||
import { join } from 'pathe';
|
||||
import { Headers, HttpClient, HttpCodes } from '@actions/http-client';
|
||||
import { downloadTool, extractTar } from '@actions/tool-cache';
|
||||
import { join } from 'pathe';
|
||||
|
||||
const getUrl = (version: string, platform: string, arch: string) => `https://github.com/reviewdog/reviewdog/releases/download/v${version}/reviewdog_${version}_${platform}_${arch}.tar.gz`;
|
||||
|
||||
|
|
|
|||
88
Cargo.lock
generated
88
Cargo.lock
generated
|
|
@ -3077,6 +3077,15 @@ dependencies = [
|
|||
"cfb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "infer"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc150e5ce2330295b8616ce0e3f53250e53af31759a9dbedad1621ba29151847"
|
||||
dependencies = [
|
||||
"cfb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.9.6"
|
||||
|
|
@ -7208,9 +7217,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|||
|
||||
[[package]]
|
||||
name = "tauri"
|
||||
version = "2.0.0-rc.3"
|
||||
version = "2.0.0-rc.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79776954e2cd6b6c3b56e2cd99905a3a166017495a39ac8eb4c85dd8ea8704b4"
|
||||
checksum = "e8345ccc676ef16e26b61fc0f5340b4e770678b1e1f53f08c69ebdac5e56b422"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
|
@ -7252,7 +7261,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"tray-icon",
|
||||
"url",
|
||||
"urlpattern",
|
||||
"urlpattern 0.2.0",
|
||||
"uuid 1.10.0",
|
||||
"webkit2gtk",
|
||||
"webview2-com",
|
||||
|
|
@ -7262,9 +7271,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-build"
|
||||
version = "2.0.0-rc.7"
|
||||
version = "2.0.0-rc.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d5ad5fcfaf02cf79aa6727f6c5df38567d8dce172b00b62690c6bc46c08b7ce"
|
||||
checksum = "4acec578ff9de14da177722c8fb5e3d6c88af296696190c70b83bec91437248a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo_toml",
|
||||
|
|
@ -7285,9 +7294,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-codegen"
|
||||
version = "2.0.0-rc.7"
|
||||
version = "2.0.0-rc.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "809ef6316726fc72593d296cf6f4e7461326e310c313d6a6c42b6e7f1e2671cf"
|
||||
checksum = "467d3e95b57c860bea13b7c812820d9e7425e4b700e5e69b358d906f22022007"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"brotli",
|
||||
|
|
@ -7343,9 +7352,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-plugin-clipboard-manager"
|
||||
version = "2.0.0-rc.1"
|
||||
version = "2.0.0-rc.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6719e5f3fcc6c6f5afda68da944a44a50c28f30a3506c457ea7dbcc13377bfe0"
|
||||
checksum = "4a9d78deb78704d9eeedc23892fc6b25a944c7f9c59354a0ea9a4fb5ab043794"
|
||||
dependencies = [
|
||||
"arboard",
|
||||
"image 0.24.9",
|
||||
|
|
@ -7359,9 +7368,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-plugin-deep-link"
|
||||
version = "2.0.0-rc.1"
|
||||
version = "2.0.0-rc.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c8e169df47aa4892184c812cc9753a486328835d38d2269a4b062179698a242"
|
||||
checksum = "694ba1e772040fcc3728ad16744ae851059e09394e3bc33353d80d9a945cf974"
|
||||
dependencies = [
|
||||
"dunce",
|
||||
"log",
|
||||
|
|
@ -7379,9 +7388,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-plugin-dialog"
|
||||
version = "2.0.0-rc.1"
|
||||
version = "2.0.0-rc.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcf99017391fdc40b6c8ae0dae8d970cc8151a8177d48b8805f320f52cac0e3c"
|
||||
checksum = "aa8bd381f75c47687f41fb603f67fdd99a1af377da22d03d8fb959d2481845c1"
|
||||
dependencies = [
|
||||
"dunce",
|
||||
"log",
|
||||
|
|
@ -7393,13 +7402,14 @@ dependencies = [
|
|||
"tauri-plugin",
|
||||
"tauri-plugin-fs",
|
||||
"thiserror",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-fs"
|
||||
version = "2.0.0-rc.0"
|
||||
version = "2.0.0-rc.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5df6b25b1f2b7b61565e66c4dbee9eb39e5635d2a763206e380e07cc3f601a67"
|
||||
checksum = "0704205734f3b4f37d7bf9e9072537716371741bf98b22a22cc5e5340e512467"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"glob",
|
||||
|
|
@ -7416,9 +7426,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-plugin-shell"
|
||||
version = "2.0.0-rc.1"
|
||||
version = "2.0.0-rc.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2133e5c6fe2ae0263ff5920feed477d3b1413f89033f537966831b0cb6f61f8e"
|
||||
checksum = "e83800ddf78b820172efb5ed7310344e8e4f97fd30cd8237a3f20c12a79eb136"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"log",
|
||||
|
|
@ -7437,31 +7447,31 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-plugin-single-instance"
|
||||
version = "2.0.0-rc.0"
|
||||
version = "2.0.0-rc.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de552151b4c9ba9ff72c7244dccaadd47f88d1f0d5caa2603c5c1c12b7636edc"
|
||||
checksum = "d73c92c98d44d4daba0118d905f45243dfcd6eaac82216c3382a02d17cb74cf2"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"thiserror",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-updater"
|
||||
version = "2.0.0-rc.1"
|
||||
version = "2.0.0-rc.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8dfd104b50e1c17998fc131edd21ced948a9605bac7eb6827f94e099a644f924"
|
||||
checksum = "f7048854b4271f3bc58ee850f0582f8d9bb0190118afa8397f36fc260daaa68b"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"dirs 5.0.1",
|
||||
"flate2",
|
||||
"futures-util",
|
||||
"http 1.1.0",
|
||||
"infer",
|
||||
"infer 0.15.0",
|
||||
"minisign-verify",
|
||||
"reqwest 0.12.7",
|
||||
"semver",
|
||||
|
|
@ -7481,9 +7491,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-plugin-window-state"
|
||||
version = "2.0.0-rc.1"
|
||||
version = "2.0.0-rc.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb6839228cbd225b95681c766cc51113e9dad62c4b3f6ebb102234413ba85ee2"
|
||||
checksum = "303569dd7858361d4c623845448b136b4c95d53b5d2bde6630bea9d7f0022d45"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"log",
|
||||
|
|
@ -7540,9 +7550,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-specta"
|
||||
version = "2.0.0-rc.17"
|
||||
version = "2.0.0-rc.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b37d5f9a690f0c5264e5461a2cd9a273565f9a12acf642692a16ea292e32f6b"
|
||||
checksum = "c2d58f5067f811ac923825ed15a95baa76313891ddc9ccfe28e4526e86477347"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"serde",
|
||||
|
|
@ -7569,9 +7579,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-utils"
|
||||
version = "2.0.0-rc.7"
|
||||
version = "2.0.0-rc.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d53d9fe87e985b273696ae22ce2b9f099a8f1b44bc8fb127467bda5fcb3e4371"
|
||||
checksum = "6746b87c4755f493b94920622e245aef2d771f001ddeffc203e315872d323e1c"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"brotli",
|
||||
|
|
@ -7581,7 +7591,7 @@ dependencies = [
|
|||
"getrandom 0.2.15",
|
||||
"glob",
|
||||
"html5ever",
|
||||
"infer",
|
||||
"infer 0.16.0",
|
||||
"json-patch",
|
||||
"kuchikiki",
|
||||
"log",
|
||||
|
|
@ -7601,7 +7611,7 @@ dependencies = [
|
|||
"thiserror",
|
||||
"toml 0.8.2",
|
||||
"url",
|
||||
"urlpattern",
|
||||
"urlpattern 0.3.0",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
|
|
@ -8043,9 +8053,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tray-icon"
|
||||
version = "0.15.2"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0aeee1ab20514132ef14bf3f4725f39246e82fd4866f7bbd209c36907be44e3"
|
||||
checksum = "131a65b2cef2081bc14dbcd414c906edbfa3bb5323dd7e748cc298614681196b"
|
||||
dependencies = [
|
||||
"core-graphics 0.24.0",
|
||||
"crossbeam-channel",
|
||||
|
|
@ -8280,6 +8290,18 @@ dependencies = [
|
|||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urlpattern"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d"
|
||||
dependencies = [
|
||||
"regex",
|
||||
"serde",
|
||||
"unic-ucd-ident",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "user-facing-error-macros"
|
||||
version = "0.1.0"
|
||||
|
|
|
|||
22
Cargo.toml
22
Cargo.toml
|
|
@ -34,7 +34,7 @@ onelauncher_prisma_cli = { path = "./packages/prisma-cli" }
|
|||
|
||||
# # ============= TAURI ============= # #
|
||||
# tauri uses latest crates.io rc channel
|
||||
tauri = { version = "=2.0.0-rc.3", features = [
|
||||
tauri = { version = "=2.0.0-rc.8", features = [
|
||||
"rustls-tls",
|
||||
"tracing",
|
||||
"specta",
|
||||
|
|
@ -43,21 +43,21 @@ tauri = { version = "=2.0.0-rc.3", features = [
|
|||
] }
|
||||
|
||||
# tauri-build is the codegen utility for our tauri buildscript.
|
||||
tauri-build = { version = "=2.0.0-rc.7" }
|
||||
tauri-build = { version = "=2.0.0-rc.8" }
|
||||
# tauri-plugin-shell adds a bridge for opening urls and paths in the frontend.
|
||||
tauri-plugin-shell = { version = "=2.0.0-rc.1" }
|
||||
tauri-plugin-shell = { version = "=2.0.0-rc.3" }
|
||||
# tauri-plugin-window-state saves the window position and size to be restored.
|
||||
tauri-plugin-window-state = { version = "=2.0.0-rc.1" }
|
||||
tauri-plugin-window-state = { version = "=2.0.0-rc.3" }
|
||||
# tauri-plugin-single-instance ensures that only one instance of the app is running.
|
||||
tauri-plugin-single-instance = { version = "=2.0.0-rc.0" }
|
||||
tauri-plugin-single-instance = { version = "=2.0.0-rc.1" }
|
||||
# tauri-plugin-clipboard-manager adds a bridge for reading/writing to the clipboard.
|
||||
tauri-plugin-clipboard-manager = { version = "=2.0.0-rc.1" }
|
||||
tauri-plugin-clipboard-manager = { version = "=2.0.0-rc.3" }
|
||||
# tauri-plugin-updater allows for us to use it's functionality for in-app updates.
|
||||
tauri-plugin-updater = { version = "=2.0.0-rc.1" }
|
||||
tauri-plugin-updater = { version = "=2.0.0-rc.2" }
|
||||
# tauri-plugin-dialog adds a bridge for opening file manager and message dialogs.
|
||||
tauri-plugin-dialog = { version = "=2.0.0-rc.1" }
|
||||
tauri-plugin-dialog = { version = "=2.0.0-rc.3" }
|
||||
# tauri-plugin-deep-link adds a way to handle custom uri schemes (onelauncher://)
|
||||
tauri-plugin-deep-link = { version = "=2.0.0-rc.1" }
|
||||
tauri-plugin-deep-link = { version = "=2.0.0-rc.3" }
|
||||
|
||||
# # ============= CORE ============= # #
|
||||
# rspc is used as a faster and more intuitive replacement for tauri-specta
|
||||
|
|
@ -88,13 +88,13 @@ specta = { version = "=2.0.0-rc.20", features = [
|
|||
] }
|
||||
|
||||
# tauri-specta is the tauri adapter for specta.
|
||||
tauri-specta = { version = "=2.0.0-rc.17", features = [ "javascript", "typescript", "derive" ] }
|
||||
tauri-specta = { version = "=2.0.0-rc.18", features = [ "javascript", "typescript", "derive" ] }
|
||||
# specta-typescript is the typescript adapter for specta.
|
||||
specta-typescript = { version = "=0.0.7" }
|
||||
# rspc-specta2 is the specta v2 (rc) adapter for rspc.
|
||||
rspc-tauri2 = { version = "=0.0.1" }
|
||||
# core utilities for minecraft and mod management with pulseflow apis
|
||||
interpulse = { version = "1.1.0", features = [ "specta" ] }
|
||||
interpulse = { version = "=1.1.0", features = [ "specta" ] }
|
||||
|
||||
# # ============= SECURITY ============= # #
|
||||
thiserror = { version = "1.0" }
|
||||
|
|
|
|||
|
|
@ -24,6 +24,6 @@
|
|||
"@onelauncher/frontend": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "=2.0.0-rc.4"
|
||||
"@tauri-apps/cli": "=2.0.0-rc.12"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,9 @@ pub async fn get_all_provider_package_versions(
|
|||
game_versions: Option<Vec<String>>,
|
||||
loaders: Option<Vec<Loader>>,
|
||||
) -> Result<Vec<ManagedVersion>, String> {
|
||||
Ok(provider.get_all_versions(&project_id, game_versions, loaders).await?)
|
||||
Ok(provider
|
||||
.get_all_versions(&project_id, game_versions, loaders)
|
||||
.await?)
|
||||
}
|
||||
|
||||
#[specta::specta]
|
||||
|
|
@ -65,7 +67,10 @@ pub struct ProviderSearchQuery {
|
|||
|
||||
#[specta::specta]
|
||||
#[tauri::command]
|
||||
pub async fn search_provider_packages(provider: Providers, query: ProviderSearchQuery) -> Result<ProviderSearchResults, String> {
|
||||
pub async fn search_provider_packages(
|
||||
provider: Providers,
|
||||
query: ProviderSearchQuery,
|
||||
) -> Result<ProviderSearchResults, String> {
|
||||
Ok(provider
|
||||
.search(
|
||||
query.query,
|
||||
|
|
@ -105,15 +110,25 @@ pub async fn download_provider_package(
|
|||
|
||||
let mgd_pkg = provider.get(&package_id).await?;
|
||||
|
||||
let (pkg_path, pkg) = package::download_package(&mgd_pkg, &mut cluster, game_version, loader, package_version).await?;
|
||||
package::add_package(&cluster.cluster_path(), pkg_path, pkg, Some(mgd_pkg.package_type)).await?;
|
||||
let (pkg_path, pkg) = package::download_package(
|
||||
&mgd_pkg,
|
||||
&mut cluster,
|
||||
game_version,
|
||||
loader,
|
||||
package_version,
|
||||
)
|
||||
.await?;
|
||||
package::add_package(
|
||||
&cluster.cluster_path(),
|
||||
pkg_path,
|
||||
pkg,
|
||||
Some(mgd_pkg.package_type),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#[specta::specta]
|
||||
#[tauri::command]
|
||||
pub async fn get_cluster_package(
|
||||
|
|
@ -165,7 +180,10 @@ pub async fn sync_cluster_packages(cluster_path: ClusterPath) -> Result<(), Stri
|
|||
|
||||
#[specta::specta]
|
||||
#[tauri::command]
|
||||
pub async fn sync_cluster_packages_by_type(cluster_path: ClusterPath, package_type: PackageType) -> Result<(), String> {
|
||||
pub async fn sync_cluster_packages_by_type(
|
||||
cluster_path: ClusterPath,
|
||||
package_type: PackageType,
|
||||
) -> Result<(), String> {
|
||||
package::sync_packages_by_type(&cluster_path, package_type).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/poppins": "^5.0.15",
|
||||
"@fontsource/poppins": "^5.0.16",
|
||||
"@formatjs/intl-durationformat": "^0.2.4",
|
||||
"@leeoniya/ufuzzy": "^1.0.14",
|
||||
"@onelauncher/client": "workspace:*",
|
||||
|
|
@ -26,11 +26,11 @@
|
|||
"@solid-primitives/refs": "^1.0.8",
|
||||
"@solidjs/router": "^0.14.3",
|
||||
"@t3-oss/env-core": "^0.11.0",
|
||||
"@tanstack/solid-query": "^5.53.1",
|
||||
"@tauri-apps/api": "=2.0.0-rc.1",
|
||||
"@tauri-apps/plugin-clipboard-manager": "=2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-dialog": "=2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-shell": "=2.0.0-rc.0",
|
||||
"@tanstack/solid-query": "^5.55.2",
|
||||
"@tauri-apps/api": "=2.0.0-rc.4",
|
||||
"@tauri-apps/plugin-clipboard-manager": "=2.0.0-rc.1",
|
||||
"@tauri-apps/plugin-dialog": "=2.0.0-rc.1",
|
||||
"@tauri-apps/plugin-shell": "=2.0.0-rc.1",
|
||||
"@unocss/reset": "^0.62.3",
|
||||
"@untitled-theme/icons-solid": "^0.10.5",
|
||||
"overlayscrollbars": "^2.10.0",
|
||||
|
|
@ -41,15 +41,15 @@
|
|||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sentry/vite-plugin": "^2.22.3",
|
||||
"@sentry/vite-plugin": "^2.22.4",
|
||||
"@solidjs/testing-library": "^0.8.9",
|
||||
"@tauri-apps/cli": "=2.0.0-rc.4",
|
||||
"@tauri-apps/cli": "=2.0.0-rc.12",
|
||||
"@testing-library/jest-dom": "^6.5.0",
|
||||
"jsdom": "^25.0.0",
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"sass": "^1.77.8",
|
||||
"sass": "^1.78.0",
|
||||
"unocss": "^0.62.3",
|
||||
"vite": "^5.4.2",
|
||||
"vite": "^5.4.3",
|
||||
"vite-plugin-solid": "^2.10.2",
|
||||
"vite-plugin-solid-svg": "^0.8.1",
|
||||
"vite-tsconfig-paths": "^5.0.1"
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
/* @refresh reload */
|
||||
import { render } from 'solid-js/web';
|
||||
|
||||
import { Route, Router } from '@solidjs/router';
|
||||
import { bridge } from './imports';
|
||||
|
||||
import BrowserRoot from '~ui/pages/browser/BrowserRoot';
|
||||
import ClusterRoot from '~ui/pages/cluster/ClusterRoot';
|
||||
|
||||
import SettingsRoot from '~ui/pages/settings/SettingsRoot';
|
||||
import { render } from 'solid-js/web';
|
||||
import { bridge } from './imports';
|
||||
import App from './ui/App';
|
||||
import HomePage from './ui/pages/Home';
|
||||
import UpdatesPage from './ui/pages/Updates';
|
||||
import ClusterRoot from '~ui/pages/cluster/ClusterRoot';
|
||||
import SettingsRoot from '~ui/pages/settings/SettingsRoot';
|
||||
import BrowserRoot from '~ui/pages/browser/BrowserRoot';
|
||||
|
||||
document.body.setAttribute('data-platform', bridge.PROGRAM_INFO.platform);
|
||||
|
||||
render(() => (
|
||||
<Router root={App}>
|
||||
<Route path="/" component={HomePage} />
|
||||
<Route path="/updates" component={UpdatesPage} />
|
||||
<Route path="/clusters" component={ClusterRoot} children={<ClusterRoot.Routes />} />
|
||||
<Route path="/settings" component={SettingsRoot} children={<SettingsRoot.Routes />} />
|
||||
<Route path="/browser" component={BrowserRoot} children={<BrowserRoot.Routes />} />
|
||||
<Route component={HomePage} path="/" />
|
||||
<Route component={UpdatesPage} path="/updates" />
|
||||
<Route children={<ClusterRoot.Routes />} component={ClusterRoot} path="/clusters" />
|
||||
<Route children={<SettingsRoot.Routes />} component={SettingsRoot} path="/settings" />
|
||||
<Route children={<BrowserRoot.Routes />} component={BrowserRoot} path="/browser" />
|
||||
</Router>
|
||||
), document.getElementById('root') as HTMLElement);
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
import type { ParentProps } from 'solid-js';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-solid';
|
||||
import { PROGRAM_INFO } from '@onelauncher/client/bindings';
|
||||
import WindowFrame from './components/WindowFrame';
|
||||
import Navbar from './components/Navbar';
|
||||
import ErrorBoundary from './components/ErrorBoundary';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-solid';
|
||||
import type { ParentProps } from 'solid-js';
|
||||
import AnimatedRoutes from './components/AnimatedRoutes';
|
||||
import NotificationOverlay from './components/overlay/notifications/NotificationOverlay';
|
||||
import { SettingsProvider } from './hooks/useSettings';
|
||||
import { ClusterModalControllerProvider } from './components/overlay/cluster/ClusterCreationModal';
|
||||
import ErrorBoundary from './components/ErrorBoundary';
|
||||
import { MultiProvider } from './components/MultiProvider';
|
||||
import Navbar from './components/Navbar';
|
||||
import { AccountControllerProvider } from './components/overlay/account/AddAccountModal';
|
||||
import { ClusterModalControllerProvider } from './components/overlay/cluster/ClusterCreationModal';
|
||||
import { ModalProvider, ModalRenderer } from './components/overlay/Modal';
|
||||
import NotificationOverlay from './components/overlay/notifications/NotificationOverlay';
|
||||
import WindowFrame from './components/WindowFrame';
|
||||
import { BrowserProvider } from './hooks/useBrowser';
|
||||
import { SettingsProvider } from './hooks/useSettings';
|
||||
|
||||
function App(props: ParentProps) {
|
||||
if (PROGRAM_INFO.dev_build !== true)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import useSettings from '~ui/hooks/useSettings';
|
||||
import { type ParentProps, Show } from 'solid-js';
|
||||
import { Transition, type TransitionProps } from 'solid-transition-group';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
|
||||
function AnimatedRoutes(props: TransitionProps & ParentProps) {
|
||||
const { settings } = useSettings();
|
||||
|
|
@ -17,10 +17,6 @@ function AnimatedRoutes(props: TransitionProps & ParentProps) {
|
|||
|
||||
return (
|
||||
<Show
|
||||
when={settings().disable_animations !== true}
|
||||
fallback={(
|
||||
<>{props.children}</>
|
||||
)}
|
||||
children={(
|
||||
<Transition
|
||||
mode="outin"
|
||||
|
|
@ -60,6 +56,10 @@ function AnimatedRoutes(props: TransitionProps & ParentProps) {
|
|||
{props.children}
|
||||
</Transition>
|
||||
)}
|
||||
fallback={(
|
||||
<>{props.children}</>
|
||||
)}
|
||||
when={settings().disable_animations !== true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { type ParentProps, createSignal, onCleanup, onMount } from 'solid-js';
|
||||
import { formatAsRelative } from '~utils';
|
||||
import { createSignal, onCleanup, onMount, type ParentProps } from 'solid-js';
|
||||
|
||||
type TimeProps = ParentProps & {
|
||||
timestamp: Date | number;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { ParentProps } from 'solid-js';
|
||||
import { ErrorBoundary as Boundary, Match, Switch } from 'solid-js';
|
||||
import type { ParentProps } from 'solid-js';
|
||||
|
||||
function ErrorBoundary(props: ParentProps) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* MIT LICENSE
|
||||
*/
|
||||
/* eslint-disable solid/reactivity -- . */
|
||||
import { type Context, type ContextProviderComponent, type FlowComponent, type JSX, createComponent } from 'solid-js';
|
||||
import { type Context, type ContextProviderComponent, createComponent, type FlowComponent, type JSX } from 'solid-js';
|
||||
|
||||
export function MultiProvider<T extends readonly [unknown?, ...unknown[]]>(props: {
|
||||
values: {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
import { A, useNavigate } from '@solidjs/router';
|
||||
import { createSignal } from 'solid-js';
|
||||
import { Bell01Icon, Cloud01Icon, Settings01Icon, TerminalBrowserIcon } from '@untitled-theme/icons-solid';
|
||||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import { WEBSITE } from '@onelauncher/client';
|
||||
import { A, useNavigate } from '@solidjs/router';
|
||||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import { Bell01Icon, Cloud01Icon, Settings01Icon, TerminalBrowserIcon } from '@untitled-theme/icons-solid';
|
||||
import { createSignal } from 'solid-js';
|
||||
import Button from './base/Button';
|
||||
import PlayerHead from './game/PlayerHead';
|
||||
import PolyfrostFull from './logos/PolyfrostFull';
|
||||
import AccountPopup from './overlay/account/AccountsPopup';
|
||||
import PlayerHead from './game/PlayerHead';
|
||||
import Button from './base/Button';
|
||||
import useAccountController from './overlay/account/AddAccountModal';
|
||||
import NotificationPopup from './overlay/notifications/NotificationPopup';
|
||||
import Popup from './overlay/Popup';
|
||||
import useAccountController from './overlay/account/AddAccountModal';
|
||||
|
||||
interface NavbarLinkProps {
|
||||
path: string;
|
||||
|
|
@ -19,11 +19,11 @@ interface NavbarLinkProps {
|
|||
function NavbarLink(props: NavbarLinkProps) {
|
||||
return (
|
||||
<A
|
||||
href={props.path}
|
||||
class="rounded-lg px-4 py-2 text-lg hover:bg-component-bg-hover hover:text-fg-primary-hover"
|
||||
inactiveClass="text-fg-secondary"
|
||||
activeClass="text-fg-primary"
|
||||
class="rounded-lg px-4 py-2 text-lg hover:bg-component-bg-hover hover:text-fg-primary-hover"
|
||||
end={props.path === '/'}
|
||||
href={props.path}
|
||||
inactiveClass="text-fg-secondary"
|
||||
>
|
||||
{props.label}
|
||||
</A>
|
||||
|
|
@ -43,14 +43,14 @@ function Navbar() {
|
|||
return (
|
||||
<div class="h-15 min-h-[60px] flex flex-row items-center *:flex-1">
|
||||
<div>
|
||||
<div onClick={() => open(WEBSITE)} class="w-min flex items-center justify-center transition-transform active:scale-90">
|
||||
<div class="w-min flex items-center justify-center transition-transform active:scale-90" onClick={() => open(WEBSITE)}>
|
||||
<PolyfrostFull />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row items-center justify-center gap-x-10 py-1">
|
||||
<NavbarLink path="/" label="Home" />
|
||||
<NavbarLink path="/browser" label="Browser" />
|
||||
<NavbarLink path="/updates" label="Updates" />
|
||||
<NavbarLink label="Home" path="/" />
|
||||
<NavbarLink label="Browser" path="/browser" />
|
||||
<NavbarLink label="Updates" path="/updates" />
|
||||
</div>
|
||||
<div class="relative flex flex-row items-center justify-end gap-x-2">
|
||||
<Button buttonStyle="icon">
|
||||
|
|
@ -64,9 +64,9 @@ function Navbar() {
|
|||
{/* Notification Manager Button */}
|
||||
<Button
|
||||
buttonStyle="icon"
|
||||
ref={notificationButton}
|
||||
class="relative [&>div]:absolute"
|
||||
onClick={() => setNotificationMenuOpen(!notificationMenuOpen())}
|
||||
ref={notificationButton}
|
||||
>
|
||||
<Bell01Icon />
|
||||
</Button>
|
||||
|
|
@ -78,26 +78,26 @@ function Navbar() {
|
|||
|
||||
{/* Account Menu Button */}
|
||||
<button
|
||||
ref={profileButton}
|
||||
onClick={() => setProfileMenuOpen(!profileMenuOpen())}
|
||||
class="hover:opacity-70"
|
||||
onClick={() => setProfileMenuOpen(!profileMenuOpen())}
|
||||
ref={profileButton}
|
||||
>
|
||||
<PlayerHead class="h-8 max-h-8 max-w-8 min-h-8 min-w-8 w-8 rounded-md" uuid={controller.defaultAccount()?.id} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<AccountPopup
|
||||
visible={profileMenuOpen}
|
||||
setVisible={setProfileMenuOpen}
|
||||
ref={el => Popup.setPos(profileButton, el)}
|
||||
class="mt-2"
|
||||
ref={el => Popup.setPos(profileButton, el)}
|
||||
setVisible={setProfileMenuOpen}
|
||||
visible={profileMenuOpen}
|
||||
/>
|
||||
|
||||
<NotificationPopup
|
||||
visible={notificationMenuOpen}
|
||||
setVisible={setNotificationMenuOpen}
|
||||
ref={el => Popup.setPos(notificationButton, el)}
|
||||
class="mt-2"
|
||||
ref={el => Popup.setPos(notificationButton, el)}
|
||||
setVisible={setNotificationMenuOpen}
|
||||
visible={notificationMenuOpen}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { useLocation, useNavigate } from '@solidjs/router';
|
||||
import { createEffect, For, splitProps } from 'solid-js';
|
||||
import type { JSX, ParentProps } from 'solid-js';
|
||||
import { For, createEffect, splitProps } from 'solid-js';
|
||||
|
||||
type SidebarProps = ParentProps & {
|
||||
base: string;
|
||||
|
|
@ -47,10 +47,10 @@ function Sidebar(props: SidebarProps) {
|
|||
|
||||
return (
|
||||
<a
|
||||
onClick={() => goto(link[2], link[3])}
|
||||
class={
|
||||
`px-3 py-1 rounded-md text-md border hover:bg-component-bg-hover active:bg-component-bg-pressed ${isActive(link[2], link[3]) ? 'bg-component-bg border-gray-05' : 'border-transparent'}`
|
||||
}
|
||||
onClick={() => goto(link[2], link[3])}
|
||||
>
|
||||
<span class="flex flex-row items-center gap-x-3 *:w-5">
|
||||
{link[0]}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type JSX, type ParentProps, Suspense, splitProps } from 'solid-js';
|
||||
import { type JSX, type ParentProps, splitProps, Suspense } from 'solid-js';
|
||||
|
||||
export interface SpinnerProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { Window } from '@tauri-apps/api/window';
|
||||
import { ChevronLeftIcon, Maximize02Icon, MinusIcon, XCloseIcon } from '@untitled-theme/icons-solid';
|
||||
import type { JSX } from 'solid-js';
|
||||
import { onMount } from 'solid-js';
|
||||
import Modal, { createModal } from './overlay/Modal';
|
||||
import Button from './base/Button';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import { onMount } from 'solid-js';
|
||||
import type { JSX } from 'solid-js';
|
||||
import Button from './base/Button';
|
||||
import Modal, { createModal } from './overlay/Modal';
|
||||
|
||||
interface TitlebarButtonProps {
|
||||
icon: (any: any) => JSX.Element;
|
||||
|
|
@ -33,11 +33,11 @@ function WindowFrame() {
|
|||
const modal = createModal(props => (
|
||||
<Modal.Simple
|
||||
{...props}
|
||||
title="Close OneLauncher?"
|
||||
buttons={[
|
||||
<Button buttonStyle="secondary" onClick={() => props.hide()}>No</Button>,
|
||||
<Button buttonStyle="danger" onClick={() => kill()}>Yes</Button>,
|
||||
]}
|
||||
title="Close OneLauncher?"
|
||||
/>
|
||||
));
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ function WindowFrame() {
|
|||
});
|
||||
|
||||
return (
|
||||
<div data-tauri-drag-region class="z-[99999] h-8 w-screen flex flex-row items-center justify-between gap-0.5 bg-page-elevated pr-0.5">
|
||||
<div class="z-[99999] h-8 w-screen flex flex-row items-center justify-between gap-0.5 bg-page-elevated pr-0.5" data-tauri-drag-region>
|
||||
<div class="flex flex-row items-center">
|
||||
<TitlebarButton icon={ChevronLeftIcon} onClick={() => history.back()} />
|
||||
</div>
|
||||
|
|
@ -59,7 +59,7 @@ function WindowFrame() {
|
|||
<div class="flex flex-row items-center justify-end">
|
||||
<TitlebarButton icon={MinusIcon} onClick={() => minimize()} />
|
||||
<TitlebarButton icon={Maximize02Icon} onClick={() => maximize()} />
|
||||
<TitlebarButton icon={XCloseIcon} onClick={() => quit()} danger />
|
||||
<TitlebarButton danger icon={XCloseIcon} onClick={() => quit()} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Accessor, JSX, ParentProps } from 'solid-js';
|
||||
import { createEffect, createSignal, mergeProps, on, splitProps, untrack } from 'solid-js';
|
||||
import type { Accessor, JSX, ParentProps } from 'solid-js';
|
||||
import styles from './Button.module.scss';
|
||||
|
||||
type ButtonProps = JSX.ButtonHTMLAttributes<HTMLButtonElement> & ParentProps & {
|
||||
|
|
@ -41,12 +41,12 @@ Button.Toggle = (props: ButtonToggleProps) => {
|
|||
|
||||
return (
|
||||
<Button
|
||||
aria-checked={checked()}
|
||||
onClick={(e) => {
|
||||
toggle();
|
||||
if (typeof split.onClick === 'function')
|
||||
split.onClick(e);
|
||||
}}
|
||||
aria-checked={checked()}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { type JSX, createSignal, splitProps } from 'solid-js';
|
||||
import { CheckIcon } from '@untitled-theme/icons-solid';
|
||||
import { createSignal, type JSX, splitProps } from 'solid-js';
|
||||
import styles from './Checkbox.module.scss';
|
||||
|
||||
type CheckboxProps = JSX.HTMLAttributes<HTMLDivElement> & {
|
||||
|
|
@ -19,8 +19,8 @@ function Checkbox(props: CheckboxProps) {
|
|||
|
||||
return (
|
||||
<div
|
||||
onClick={() => toggle()}
|
||||
class={`${styles.checkbox} ${` ${split.class}` ?? ''}`}
|
||||
onClick={() => toggle()}
|
||||
{...rest}
|
||||
>
|
||||
<div class={`${styles.box} ${checked() ? styles.checked : ''}`}>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { type Accessor, Index, type JSX, Match, type ParentProps, type ResolvedJSXElement, type Setter, Show, Switch, children, createEffect, createSignal, splitProps } from 'solid-js';
|
||||
import { ChevronDownIcon, ChevronUpIcon } from '@untitled-theme/icons-solid';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-solid';
|
||||
import { type Accessor, children, createEffect, createSignal, Index, type JSX, Match, type ParentProps, type ResolvedJSXElement, type Setter, Show, splitProps, Switch } from 'solid-js';
|
||||
import Popup from '../overlay/Popup';
|
||||
import Button from './Button';
|
||||
import styles from './Dropdown.module.scss';
|
||||
|
|
@ -47,10 +47,10 @@ function Dropdown(props: DropdownProps) {
|
|||
? split.component({ visible, setVisible, children: items })
|
||||
: (
|
||||
<Button
|
||||
class="h-full w-full"
|
||||
buttonStyle="secondary"
|
||||
onClick={() => setVisible(true)}
|
||||
class="h-full w-full"
|
||||
iconRight={<ChevronDownIcon />}
|
||||
onClick={() => setVisible(true)}
|
||||
>
|
||||
<div
|
||||
class="h-full flex flex-1 flex-row items-center gap-1 overflow-hidden text-nowrap"
|
||||
|
|
@ -63,18 +63,18 @@ function Dropdown(props: DropdownProps) {
|
|||
);
|
||||
|
||||
return (
|
||||
<div ref={ref} class={`${styles.dropdown} ${split.class || ''}`} data-disabled={split.disabled || false} {...rest}>
|
||||
<div class={`${styles.dropdown} ${split.class || ''}`} data-disabled={split.disabled || false} ref={ref} {...rest}>
|
||||
<Component />
|
||||
|
||||
<Popup
|
||||
mount={ref}
|
||||
visible={visible}
|
||||
setVisible={setVisible}
|
||||
ref={(ref) => {
|
||||
ref.classList.add('mt-1', 'w-full');
|
||||
if (split.dropdownClass)
|
||||
ref.classList.add(...split.dropdownClass.split(' '));
|
||||
}}
|
||||
setVisible={setVisible}
|
||||
visible={visible}
|
||||
>
|
||||
<div class={`${styles.dropdown_elements_container} ${visible() ? styles.visible : ''}`}>
|
||||
<OverlayScrollbarsComponent class={`${styles.list} ${styles.dropdown_element}`}>
|
||||
|
|
@ -119,10 +119,9 @@ Dropdown.Minimal = function (props: MinimalDropdownProps) {
|
|||
return (
|
||||
<Dropdown
|
||||
class="w-auto!"
|
||||
dropdownClass="w-max!"
|
||||
component={props => (
|
||||
<Button
|
||||
onClick={() => props.setVisible(true)}
|
||||
buttonStyle="iconSecondary"
|
||||
children={(
|
||||
<Switch>
|
||||
<Match when={split.icon}>
|
||||
|
|
@ -136,9 +135,10 @@ Dropdown.Minimal = function (props: MinimalDropdownProps) {
|
|||
</Match>
|
||||
</Switch>
|
||||
)}
|
||||
buttonStyle="iconSecondary"
|
||||
onClick={() => props.setVisible(true)}
|
||||
/>
|
||||
)}
|
||||
dropdownClass="w-max!"
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { type JSX, splitProps } from 'solid-js';
|
||||
import { LinkExternal01Icon } from '@untitled-theme/icons-solid';
|
||||
import styles from './Link.module.scss';
|
||||
import usePromptOpener from '~ui/hooks/usePromptOpener';
|
||||
import { type JSX, splitProps } from 'solid-js';
|
||||
import styles from './Link.module.scss';
|
||||
|
||||
export type LinkProps = JSX.IntrinsicElements['a'] & {
|
||||
prompt?: boolean;
|
||||
|
|
@ -15,12 +15,6 @@ function Link(props: LinkProps) {
|
|||
return (
|
||||
<button
|
||||
{...rest as JSX.ButtonHTMLAttributes<HTMLButtonElement>}
|
||||
class={`${styles.link} ${split.class || ''}`}
|
||||
onClick={(e) => {
|
||||
open(split.href, !!split.prompt);
|
||||
if (typeof split.onClick === 'function')
|
||||
split.onClick(e as any);
|
||||
}}
|
||||
children={(
|
||||
<div class="flex flex-row gap-x-1">
|
||||
{props.children}
|
||||
|
|
@ -29,6 +23,12 @@ function Link(props: LinkProps) {
|
|||
)}
|
||||
</div>
|
||||
)}
|
||||
class={`${styles.link} ${split.class || ''}`}
|
||||
onClick={(e) => {
|
||||
open(split.href, !!split.prompt);
|
||||
if (typeof split.onClick === 'function')
|
||||
split.onClick(e as any);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-solid';
|
||||
import { type Context, type JSX, type ParentProps, type Signal, createContext, createEffect, createSignal, splitProps, useContext } from 'solid-js';
|
||||
import { type Context, createContext, createEffect, createSignal, type JSX, type ParentProps, type Signal, splitProps, useContext } from 'solid-js';
|
||||
import styles from './SelectList.module.scss';
|
||||
|
||||
type SelectListContextHelpers = Signal<number | undefined>;
|
||||
|
|
@ -55,7 +55,7 @@ SelectList.Row = (props: SelectListRowProps) => {
|
|||
return (
|
||||
<div
|
||||
{...rest}
|
||||
tabIndex={0}
|
||||
class={`${styles.row} ${props.index !== undefined && selected() === props.index ? styles.selected : ''} ${split.class || ''}`}
|
||||
onClick={(e) => {
|
||||
if (props.index !== undefined)
|
||||
setSelected(props.index);
|
||||
|
|
@ -63,7 +63,7 @@ SelectList.Row = (props: SelectListRowProps) => {
|
|||
if (typeof split.onClick === 'function')
|
||||
split.onClick(e);
|
||||
}}
|
||||
class={`${styles.row} ${props.index !== undefined && selected() === props.index ? styles.selected : ''} ${split.class || ''}`}
|
||||
tabIndex={0}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { JSX } from 'solid-js';
|
||||
import { createSignal, createUniqueId, onMount, splitProps } from 'solid-js';
|
||||
import type { JSX } from 'solid-js';
|
||||
import styles from './TextField.module.scss';
|
||||
|
||||
type TextFieldProps = {
|
||||
|
|
@ -50,14 +50,14 @@ function TextField(props: TextFieldProps) {
|
|||
});
|
||||
|
||||
return (
|
||||
<label for={id} class={`${styles.textfield} ${isValid() ? '' : styles.invalid} ${split.labelClass || ''}`}>
|
||||
<label class={`${styles.textfield} ${isValid() ? '' : styles.invalid} ${split.labelClass || ''}`} for={id}>
|
||||
{split.iconLeft && <span class={styles.icon}>{split.iconLeft}</span>}
|
||||
<input
|
||||
id={id}
|
||||
type="text"
|
||||
ref={ref}
|
||||
onInput={onInput}
|
||||
onChange={onChange}
|
||||
onInput={onInput}
|
||||
ref={ref}
|
||||
type="text"
|
||||
{...rest}
|
||||
/>
|
||||
{split.iconRight && <span class={styles.icon}>{split.iconRight}</span>}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type Accessor, type JSX, createEffect, createSignal, splitProps } from 'solid-js';
|
||||
import { type Accessor, createEffect, createSignal, type JSX, splitProps } from 'solid-js';
|
||||
|
||||
type ToggleProps = JSX.HTMLAttributes<HTMLDivElement> & {
|
||||
checked?: Accessor<boolean>;
|
||||
|
|
@ -23,8 +23,8 @@ function Toggle(props: ToggleProps) {
|
|||
|
||||
return (
|
||||
<div
|
||||
onClick={() => toggle()}
|
||||
class={`w-[40px] h-[22px] p-3 flex flex-row relative rounded-full transition-colors overflow-hidden ${checked() ? 'bg-brand' : 'bg-gray-10'}${` ${split.class}` || ''}`}
|
||||
onClick={() => toggle()}
|
||||
{...rest}
|
||||
>
|
||||
<div class={`w-[16px] h-[16px] rounded-full mx-1 left-0 top-1/2 -translate-y-1/2 transition-transform bg-white absolute ${checked() ? 'translate-x-full' : 'translate-x-0'}`} />
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ function Tooltip(props: TooltipProps) {
|
|||
const [split, rest] = splitProps(props, ['class']);
|
||||
|
||||
return (
|
||||
<div data-text={props.text} class={`${styles.tooltip} ${split.class || ''}`} {...rest} />
|
||||
<div class={`${styles.tooltip} ${split.class || ''}`} data-text={props.text} {...rest} />
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Index, Show, createEffect, createMemo, createSignal, untrack } from 'solid-js';
|
||||
import { OverlayScrollbarsComponent, type OverlayScrollbarsComponentRef } from 'overlayscrollbars-solid';
|
||||
import type { Ref } from '@solid-primitives/refs';
|
||||
import { AlignBottom01Icon } from '@untitled-theme/icons-solid';
|
||||
import { OverlayScrollbarsComponent, type OverlayScrollbarsComponentRef } from 'overlayscrollbars-solid';
|
||||
import { createEffect, createMemo, createSignal, Index, Show, untrack } from 'solid-js';
|
||||
import type { Ref } from '@solid-primitives/refs';
|
||||
import type { OnUpdatedEventListenerArgs, OverlayScrollbars } from 'overlayscrollbars';
|
||||
import Button from '../base/Button';
|
||||
import styles from './FormattedLog.module.scss';
|
||||
|
|
@ -46,10 +46,10 @@ function FormattedLog(props: FormattedLogProps) {
|
|||
<div class="absolute right-0 top-0 z-1 h-6 w-full flex flex-row justify-end border border-gray-05 rounded-t-md bg-page p-px">
|
||||
<Button.Toggle
|
||||
buttonStyle="icon"
|
||||
children={<AlignBottom01Icon />}
|
||||
checked={shouldScroll}
|
||||
onChecked={toggleAutoScroll}
|
||||
children={<AlignBottom01Icon />}
|
||||
class="h-full! rounded-md! py-1!"
|
||||
onChecked={toggleAutoScroll}
|
||||
/>
|
||||
</div>
|
||||
</Show>
|
||||
|
|
@ -58,14 +58,14 @@ function FormattedLog(props: FormattedLogProps) {
|
|||
class={`${props.enableAutoScroll === true ? 'mt-6' : ''} h-full flex flex-1 overflow-auto font-medium font-mono`}
|
||||
>
|
||||
<OverlayScrollbarsComponent
|
||||
ref={overlayScrollbars}
|
||||
class="relative h-full flex-1"
|
||||
events={{
|
||||
updated: autoScrollUpdated,
|
||||
initialized: autoScrollInitialized,
|
||||
}}
|
||||
class="relative h-full flex-1"
|
||||
ref={overlayScrollbars}
|
||||
>
|
||||
<code ref={props.codeRef} class={styles.log}>
|
||||
<code class={styles.log} ref={props.codeRef}>
|
||||
<Index each={lines()}>
|
||||
{(line, index) => {
|
||||
if (index === lines().length - 1)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { ParentProps } from 'solid-js';
|
||||
import { renderHighlightedString } from '@onelauncher/client';
|
||||
import styles from './Markdown.module.scss';
|
||||
import usePromptOpener from '~ui/hooks/usePromptOpener';
|
||||
import type { ParentProps } from 'solid-js';
|
||||
import styles from './Markdown.module.scss';
|
||||
|
||||
export type MarkdownProps = ParentProps & {
|
||||
body: string;
|
||||
|
|
@ -15,10 +15,6 @@ function Markdown(props: MarkdownProps) {
|
|||
class={styles.markdown}
|
||||
// eslint-disable-next-line solid/no-innerhtml -- Should be sanitised properly
|
||||
innerHTML={renderHighlightedString(props.body)}
|
||||
onContextMenu={(e) => {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
onClick={(e) => {
|
||||
if (e.target.nodeName === 'A') {
|
||||
e.stopImmediatePropagation();
|
||||
|
|
@ -29,6 +25,10 @@ function Markdown(props: MarkdownProps) {
|
|||
promptOpen(target.href);
|
||||
}
|
||||
}}
|
||||
onContextMenu={(e) => {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import type { Providers, SearchResult } from '@onelauncher/client/bindings';
|
||||
import { ChevronDownIcon, Download01Icon, HeartIcon } from '@untitled-theme/icons-solid';
|
||||
import type { JSX } from 'solid-js';
|
||||
import { For, Match, Show, Switch, createSignal } from 'solid-js';
|
||||
import Button from '../base/Button';
|
||||
import useBrowser from '~ui/hooks/useBrowser';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import { abbreviateNumber } from '~utils';
|
||||
import { createSignal, For, Match, Show, Switch } from 'solid-js';
|
||||
import type { Providers, SearchResult } from '@onelauncher/client/bindings';
|
||||
import type { JSX } from 'solid-js';
|
||||
import Button from '../base/Button';
|
||||
|
||||
interface SearchResultsContainerProps {
|
||||
provider: Providers;
|
||||
|
|
@ -89,7 +89,7 @@ function PackageList(props: SearchResultsContainerProps) {
|
|||
<div class="flex flex-col gap-2">
|
||||
<For each={props.results}>
|
||||
{mod => (
|
||||
<PackageItem {...mod} row provider={props.provider} />
|
||||
<PackageItem {...mod} provider={props.provider} row />
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
|
|
@ -105,13 +105,13 @@ function PackageItem(props: SearchResult & { provider: Providers; row?: boolean
|
|||
|
||||
return (
|
||||
<div
|
||||
tabIndex={0}
|
||||
onClick={redirect}
|
||||
class="h-full min-w-50 flex overflow-hidden rounded-lg bg-component-bg hover:bg-component-bg-hover"
|
||||
classList={{
|
||||
'flex-row max-h-32 min-h-32': props.row,
|
||||
'flex-col max-h-74 min-h-74': !props.row,
|
||||
}}
|
||||
onClick={redirect}
|
||||
tabIndex={0}
|
||||
>
|
||||
<div
|
||||
class="relative flex items-center justify-center overflow-hidden"
|
||||
|
|
@ -132,15 +132,15 @@ function PackageItem(props: SearchResult & { provider: Providers; row?: boolean
|
|||
)}
|
||||
when={props.icon_url}
|
||||
>
|
||||
<img class="absolute z-0 max-w-none w-7/6 opacity-50 filter-blur-xl" src={props.icon_url!} alt={`Icon for ${props.title}`} />
|
||||
<img alt={`Icon for ${props.title}`} class="absolute z-0 max-w-none w-7/6 opacity-50 filter-blur-xl" src={props.icon_url!} />
|
||||
<img
|
||||
alt={`Icon for ${props.title}`}
|
||||
class="relative z-1 aspect-ratio-square rounded-md image-render-auto"
|
||||
classList={{
|
||||
'w-2/5': !props.row,
|
||||
'w-3/4': props.row,
|
||||
}}
|
||||
src={props.icon_url!}
|
||||
alt={`Icon for ${props.title}`}
|
||||
/>
|
||||
</Show>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { convertFileSrc } from '@tauri-apps/api/core';
|
||||
import defaultCover from '~assets/images/default_instance_cover.jpg';
|
||||
import { type JSX, type ParentProps, Show, splitProps } from 'solid-js';
|
||||
import type { Cluster } from '@onelauncher/client/bindings';
|
||||
import styles from './ClusterCover.module.scss';
|
||||
import defaultCover from '~assets/images/default_instance_cover.jpg';
|
||||
|
||||
type ClusterCoverProps = JSX.HTMLAttributes<HTMLImageElement> & {
|
||||
cluster: Cluster | undefined;
|
||||
|
|
@ -31,14 +31,14 @@ function ClusterCover(props: ClusterCoverProps) {
|
|||
};
|
||||
|
||||
const Wrapper = (props: ParentProps) => (
|
||||
<Show when={split.linearBlur !== undefined} fallback={<>{props.children}</>}>
|
||||
<Show fallback={<>{props.children}</>} when={split.linearBlur !== undefined}>
|
||||
<div
|
||||
children={props.children}
|
||||
class={`${styles.linearBlur} ${split.linearBlur?.class || ''}`}
|
||||
style={{
|
||||
'--degrees': `${split.linearBlur?.degrees ?? 0}deg`,
|
||||
'--blur': `${split.linearBlur?.blur ?? 0}px`,
|
||||
}}
|
||||
children={props.children}
|
||||
/>
|
||||
</Show>
|
||||
);
|
||||
|
|
@ -48,12 +48,12 @@ function ClusterCover(props: ClusterCoverProps) {
|
|||
<img
|
||||
{...rest}
|
||||
class={`${split.class || ''}`}
|
||||
src={image()}
|
||||
onError={(e) => {
|
||||
e.currentTarget.src = split.override ? convertFileSrc(split.override) : defaultCover;
|
||||
if (typeof split.onError === 'function')
|
||||
split.onError(e);
|
||||
}}
|
||||
src={image()}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { type JSX, splitProps } from 'solid-js';
|
||||
import type { Cluster, Loader } from '@onelauncher/client/bindings';
|
||||
import FabricImage from '~assets/logos/fabric.png';
|
||||
import ForgeImage from '~assets/logos/forge.png';
|
||||
import QuiltImage from '~assets/logos/quilt.png';
|
||||
import VanillaImage from '~assets/logos/vanilla.png';
|
||||
import { type JSX, splitProps } from 'solid-js';
|
||||
import type { Cluster, Loader } from '@onelauncher/client/bindings';
|
||||
|
||||
export function getLoaderLogoSrc(loader: Cluster | Loader): string {
|
||||
const loaderName = (typeof loader === 'string' ? loader : loader.meta.loader)?.toLowerCase() as Loader;
|
||||
|
|
@ -27,7 +27,7 @@ type LoaderIconProp = JSX.HTMLAttributes<HTMLImageElement> & {
|
|||
function LoaderIcon(props: LoaderIconProp) {
|
||||
const [{ loader = 'vanilla' }, rest] = splitProps(props, ['loader']);
|
||||
return (
|
||||
<img {...rest} src={getLoaderLogoSrc(loader)} alt={`${loader}'s logo`} />
|
||||
<img {...rest} alt={`${loader}'s logo`} src={getLoaderLogoSrc(loader)} />
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Show, createEffect, createSignal, on, splitProps } from 'solid-js';
|
||||
import { createEffect, createSignal, on, Show, splitProps } from 'solid-js';
|
||||
import type { JSX } from 'solid-js';
|
||||
import steveSrc from '../../../assets/images/steve.png';
|
||||
|
||||
|
|
@ -20,23 +20,23 @@ function PlayerHead(props: PlayerHeadProps) {
|
|||
return (
|
||||
<>
|
||||
<Show
|
||||
when={props.uuid !== null && props.uuid !== undefined}
|
||||
fallback={(
|
||||
<img
|
||||
src={steveSrc}
|
||||
class={`image-render-pixel ${split.class}`}
|
||||
{...rest}
|
||||
/>
|
||||
)}
|
||||
children={(
|
||||
<img
|
||||
src={headSrc(split.uuid!)}
|
||||
onLoad={() => setLoaded(true)}
|
||||
onError={() => props.onError && props.onError()}
|
||||
class={`image-render-pixel ${isLoaded() ? '' : 'hidden'} ${split.class}`}
|
||||
onError={() => props.onError && props.onError()}
|
||||
onLoad={() => setLoaded(true)}
|
||||
src={headSrc(split.uuid!)}
|
||||
{...rest}
|
||||
/>
|
||||
)}
|
||||
fallback={(
|
||||
<img
|
||||
class={`image-render-pixel ${split.class}`}
|
||||
src={steveSrc}
|
||||
{...rest}
|
||||
/>
|
||||
)}
|
||||
when={props.uuid !== null && props.uuid !== undefined}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { convertFileSrc } from '@tauri-apps/api/core';
|
||||
import DefaultWorld from '~assets/images/default_world.png?url';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import { join } from 'pathe';
|
||||
import { type JSX, splitProps } from 'solid-js';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import DefaultWorld from '~assets/images/default_world.png?url';
|
||||
|
||||
export type WorldIconProps = JSX.HTMLAttributes<HTMLImageElement> & {
|
||||
world_name: string;
|
||||
|
|
@ -17,12 +17,12 @@ function WorldIcon(props: WorldIconProps) {
|
|||
return (
|
||||
<img
|
||||
{...rest}
|
||||
alt={`${props.world_name} icon`}
|
||||
class={`w-16 h-16 rounded-md ${split.class || ''}`}
|
||||
src={path()}
|
||||
onError={(e) => {
|
||||
e.currentTarget.src = DefaultWorld;
|
||||
}}
|
||||
alt={`${props.world_name} icon`}
|
||||
src={path()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
function PolyfrostFull() {
|
||||
return (
|
||||
<svg width="174" height="30" viewBox="0 0 174 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.86 16.6283L13.8843 1.08171C13.0516 -0.36057 11.689 -0.36057 10.8564 1.08171L0.947095 18.2464C-1.74381 22.9075 1.61965 28.7332 7.00145 28.7332H15.8719L22.8601 16.629L29.8482 28.7331H34.7491C38.7858 28.7331 41.3082 24.3637 39.2898 20.8681L31.3646 7.14161C30.532 5.70003 29.1701 5.70003 28.3374 7.14161L22.86 16.6283Z" fill="#0A5BE8" />
|
||||
<svg fill="none" height="30" viewBox="0 0 174 30" width="174" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd" d="M22.86 16.6283L13.8843 1.08171C13.0516 -0.36057 11.689 -0.36057 10.8564 1.08171L0.947095 18.2464C-1.74381 22.9075 1.61965 28.7332 7.00145 28.7332H15.8719L22.8601 16.629L29.8482 28.7331H34.7491C38.7858 28.7331 41.3082 24.3637 39.2898 20.8681L31.3646 7.14161C30.532 5.70003 29.1701 5.70003 28.3374 7.14161L22.86 16.6283Z" fill="#0A5BE8" fill-rule="evenodd" />
|
||||
<path d="M117.79 11.03H120.95V14.6499H117.92V24.3499H113.26V14.6499H111.32V11.03H113.26V10.6699C113.26 9 113.74 7.66992 114.69 6.67993C115.65 5.67993 117.02 5.17993 118.8 5.17993C119.37 5.17993 119.93 5.23999 120.49 5.35986C121.04 5.47998 121.51 5.65991 121.89 5.8999L120.73 9.31982C120.54 9.19995 120.32 9.09985 120.07 9.02002C119.83 8.94995 119.58 8.90991 119.34 8.90991C118.85 8.90991 118.47 9.05981 118.2 9.35986C117.93 9.6499 117.79 10.1099 117.79 10.72V11.03Z" fill="#0A5BE8" />
|
||||
<path d="M131.74 10.29V14.6501L131.626 14.6343C131.457 14.6104 131.313 14.5901 131.19 14.5901C131.03 14.5801 130.86 14.5701 130.68 14.5701C129.74 14.5701 128.97 14.8401 128.38 15.3801C127.79 15.9102 127.5 16.79 127.5 17.99V24.3501H122.84V10.52H127.28V12.1799C127.61 11.72 128.03 11.3501 128.53 11.0601C129.41 10.55 130.48 10.29 131.74 10.29Z" fill="#0A5BE8" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M140.19 24.5701C138.74 24.5701 137.44 24.26 136.32 23.6501C135.19 23.04 134.31 22.1899 133.66 21.1101C133.01 20.03 132.69 18.79 132.69 17.4001C132.69 16.01 133.01 14.77 133.66 13.7C134.31 12.6301 135.19 11.79 136.32 11.1899C137.45 10.5901 138.74 10.28 140.19 10.28C141.64 10.28 142.94 10.5801 144.07 11.1899C145.2 11.79 146.09 12.6301 146.73 13.7C147.37 14.77 147.69 16.01 147.69 17.4001C147.69 18.79 147.37 20.03 146.73 21.1101C146.09 22.1899 145.21 23.04 144.07 23.6501C142.94 24.27 141.65 24.5701 140.19 24.5701ZM140.19 20.72C140.73 20.72 141.21 20.5901 141.62 20.3401C142.04 20.0801 142.37 19.71 142.61 19.2C142.85 18.6899 142.98 18.1001 142.98 17.4001C142.98 16.7 142.86 16.1101 142.61 15.6301C142.36 15.1401 142.03 14.77 141.62 14.52C141.403 14.3909 141.172 14.2937 140.926 14.23C140.695 14.1704 140.451 14.1401 140.19 14.1401C139.953 14.1401 139.727 14.167 139.51 14.22C139.252 14.2834 139.008 14.384 138.78 14.52C138.36 14.77 138.03 15.1401 137.78 15.6301C137.53 16.1101 137.4 16.71 137.4 17.4001C137.4 18.0901 137.53 18.7 137.78 19.2C138.03 19.7 138.37 20.0801 138.78 20.3401C139.2 20.5901 139.67 20.72 140.19 20.72Z" fill="#0A5BE8" />
|
||||
<path clip-rule="evenodd" d="M140.19 24.5701C138.74 24.5701 137.44 24.26 136.32 23.6501C135.19 23.04 134.31 22.1899 133.66 21.1101C133.01 20.03 132.69 18.79 132.69 17.4001C132.69 16.01 133.01 14.77 133.66 13.7C134.31 12.6301 135.19 11.79 136.32 11.1899C137.45 10.5901 138.74 10.28 140.19 10.28C141.64 10.28 142.94 10.5801 144.07 11.1899C145.2 11.79 146.09 12.6301 146.73 13.7C147.37 14.77 147.69 16.01 147.69 17.4001C147.69 18.79 147.37 20.03 146.73 21.1101C146.09 22.1899 145.21 23.04 144.07 23.6501C142.94 24.27 141.65 24.5701 140.19 24.5701ZM140.19 20.72C140.73 20.72 141.21 20.5901 141.62 20.3401C142.04 20.0801 142.37 19.71 142.61 19.2C142.85 18.6899 142.98 18.1001 142.98 17.4001C142.98 16.7 142.86 16.1101 142.61 15.6301C142.36 15.1401 142.03 14.77 141.62 14.52C141.403 14.3909 141.172 14.2937 140.926 14.23C140.695 14.1704 140.451 14.1401 140.19 14.1401C139.953 14.1401 139.727 14.167 139.51 14.22C139.252 14.2834 139.008 14.384 138.78 14.52C138.36 14.77 138.03 15.1401 137.78 15.6301C137.53 16.1101 137.4 16.71 137.4 17.4001C137.4 18.0901 137.53 18.7 137.78 19.2C138.03 19.7 138.37 20.0801 138.78 20.3401C139.2 20.5901 139.67 20.72 140.19 20.72Z" fill="#0A5BE8" fill-rule="evenodd" />
|
||||
<path d="M154.68 24.5701C153.55 24.5701 152.45 24.4299 151.38 24.1599C150.31 23.8901 149.45 23.55 148.8 23.1401L150.2 19.8201C150.82 20.21 151.55 20.52 152.38 20.75C153.21 20.98 154.03 21.0901 154.83 21.0901C155.61 21.0901 156.16 21.01 156.46 20.8301C156.76 20.6599 156.91 20.4299 156.91 20.1401C156.91 19.8701 156.77 19.6699 156.48 19.54C156.344 19.479 156.191 19.4248 156.018 19.3782C155.821 19.3252 155.6 19.282 155.35 19.25L154.92 19.1873L154.912 19.1858L154.893 19.1831C154.555 19.1339 154.196 19.0816 153.82 19.02C153.529 18.9724 153.235 18.9192 152.938 18.8589C152.674 18.8052 152.408 18.7458 152.14 18.6799C151.58 18.54 151.06 18.3101 150.6 18.02C150.14 17.73 149.76 17.3201 149.48 16.8101C149.2 16.3 149.06 15.6501 149.06 14.8701C149.06 13.99 149.31 13.2 149.81 12.51C150.31 11.8201 151.04 11.28 152 10.8801C152.96 10.48 154.14 10.28 155.53 10.28C155.979 10.28 156.433 10.3035 156.89 10.3489C157.378 10.3977 157.869 10.4719 158.36 10.5701C158.938 10.6855 159.463 10.8418 159.933 11.0339C160.236 11.158 160.515 11.2971 160.77 11.45L159.37 14.74C159.039 14.5415 158.706 14.374 158.372 14.239C158.05 14.1089 157.729 14.0088 157.41 13.9399C156.76 13.8 156.14 13.72 155.55 13.72C154.77 13.72 154.22 13.8101 153.9 14C153.58 14.1899 153.42 14.4199 153.42 14.6899C153.42 14.96 153.56 15.1699 153.84 15.3101C153.894 15.3369 153.95 15.3625 154.01 15.3872C154.265 15.491 154.578 15.5754 154.95 15.6401C155.32 15.7029 155.714 15.7598 156.134 15.8201L156.48 15.8701C156.8 15.9165 157.126 15.9731 157.454 16.042C157.689 16.0916 157.925 16.1472 158.16 16.21C158.401 16.2747 158.635 16.3542 158.86 16.448C159.157 16.5715 159.438 16.7195 159.7 16.8901C160.17 17.1899 160.54 17.5901 160.82 18.0901C161.1 18.5901 161.24 19.23 161.24 20.02C161.24 20.8701 160.99 21.6401 160.49 22.3201C159.99 23 159.26 23.54 158.28 23.95C157.32 24.3701 156.11 24.5701 154.68 24.5701Z" fill="#0A5BE8" />
|
||||
<path d="M172.91 23.79C172.749 23.9014 172.573 24.0007 172.38 24.0876C172.107 24.2114 171.801 24.3096 171.46 24.3799C171.26 24.4255 171.058 24.4636 170.852 24.4941C170.471 24.5503 170.079 24.5798 169.67 24.5798C167.98 24.5798 166.65 24.1399 165.71 23.26C164.76 22.3899 164.28 21.0598 164.28 19.29V14.6499H162.35V11.03H164.28V7.42993H168.94V11.03H171.98V14.6499H168.94V19.24C168.94 19.74 169.07 20.1199 169.33 20.3999C169.59 20.6799 169.93 20.8298 170.34 20.8298C170.89 20.8298 171.37 20.6799 171.76 20.3899L172.91 23.79Z" fill="#0A5BE8" />
|
||||
<path d="M87.8901 5.40991V24.3398H92.5503V5.40991H87.8901Z" fill="#0A5BE8" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M68.5298 9.56006C67.9102 8.56006 67.0298 7.80005 65.8999 7.28003C64.7598 6.75 63.4102 6.47998 61.8398 6.47998H54V24.3501H58.8501V19.6799H61.8398C63.4102 19.6799 64.7598 19.4099 65.8999 18.8699C67.0298 18.3401 67.9102 17.5801 68.5298 16.5901C69.1499 15.6001 69.46 14.4399 69.46 13.0901C69.46 11.73 69.1499 10.55 68.5298 9.56006ZM63.8101 15.01C63.3198 15.47 62.5601 15.7 61.5498 15.7H58.8501V10.46H61.5498C62.5601 10.46 63.3198 10.7 63.8101 11.1499C64.3101 11.6099 64.5601 12.26 64.5601 13.0901C64.5601 13.9099 64.3101 14.55 63.8101 15.01Z" fill="#0A5BE8" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M74.3696 23.6501C75.4897 24.26 76.7896 24.5701 78.2397 24.5701C79.6899 24.5701 80.9897 24.27 82.1196 23.6501C83.2598 23.04 84.1396 22.1899 84.7798 21.1101C85.4199 20.03 85.7397 18.79 85.7397 17.4001C85.7397 16.01 85.4199 14.77 84.7798 13.7C84.1396 12.6301 83.2495 11.79 82.1196 11.1899C80.9897 10.5801 79.6899 10.28 78.2397 10.28C76.7896 10.28 75.4995 10.5901 74.3696 11.1899C73.2397 11.79 72.3599 12.6301 71.71 13.7C71.0596 14.77 70.7397 16.01 70.7397 17.4001C70.7397 18.79 71.0596 20.03 71.71 21.1101C72.3599 22.1899 73.2397 23.04 74.3696 23.6501ZM79.6699 20.3401C79.2598 20.5901 78.7798 20.72 78.2397 20.72C77.71 20.72 77.2397 20.5901 76.8296 20.3401C76.4199 20.0801 76.0796 19.7 75.8296 19.2C75.6797 18.9001 75.5728 18.5608 75.5112 18.1882C75.4702 17.9397 75.4497 17.6763 75.4497 17.4001C75.4497 16.71 75.5796 16.1101 75.8296 15.6301C75.9697 15.3555 76.1348 15.1187 76.3267 14.9194C76.3916 14.8521 76.46 14.7888 76.5312 14.73C76.625 14.6526 76.7246 14.5825 76.8296 14.52C77.2495 14.27 77.7197 14.1401 78.2397 14.1401C78.4727 14.1401 78.6924 14.1643 78.9009 14.2119C79.1758 14.2747 79.4307 14.3779 79.6699 14.52C79.7417 14.564 79.811 14.6116 79.8784 14.6628C80.0581 14.8005 80.2202 14.9648 80.3643 15.1555C80.4146 15.2217 80.4624 15.291 80.5083 15.3638C80.5615 15.4482 80.6123 15.5369 80.6597 15.6301C80.7949 15.8894 80.8921 16.1807 80.9526 16.5042C81.0044 16.7795 81.0298 17.0781 81.0298 17.4001C81.0298 18.1001 80.8999 18.6899 80.6597 19.2C80.5703 19.3896 80.4688 19.5601 80.3545 19.7124C80.2446 19.8591 80.1235 19.9895 79.9907 20.1047C79.8901 20.1917 79.7832 20.2698 79.6699 20.3401Z" fill="#0A5BE8" />
|
||||
<path clip-rule="evenodd" d="M68.5298 9.56006C67.9102 8.56006 67.0298 7.80005 65.8999 7.28003C64.7598 6.75 63.4102 6.47998 61.8398 6.47998H54V24.3501H58.8501V19.6799H61.8398C63.4102 19.6799 64.7598 19.4099 65.8999 18.8699C67.0298 18.3401 67.9102 17.5801 68.5298 16.5901C69.1499 15.6001 69.46 14.4399 69.46 13.0901C69.46 11.73 69.1499 10.55 68.5298 9.56006ZM63.8101 15.01C63.3198 15.47 62.5601 15.7 61.5498 15.7H58.8501V10.46H61.5498C62.5601 10.46 63.3198 10.7 63.8101 11.1499C64.3101 11.6099 64.5601 12.26 64.5601 13.0901C64.5601 13.9099 64.3101 14.55 63.8101 15.01Z" fill="#0A5BE8" fill-rule="evenodd" />
|
||||
<path clip-rule="evenodd" d="M74.3696 23.6501C75.4897 24.26 76.7896 24.5701 78.2397 24.5701C79.6899 24.5701 80.9897 24.27 82.1196 23.6501C83.2598 23.04 84.1396 22.1899 84.7798 21.1101C85.4199 20.03 85.7397 18.79 85.7397 17.4001C85.7397 16.01 85.4199 14.77 84.7798 13.7C84.1396 12.6301 83.2495 11.79 82.1196 11.1899C80.9897 10.5801 79.6899 10.28 78.2397 10.28C76.7896 10.28 75.4995 10.5901 74.3696 11.1899C73.2397 11.79 72.3599 12.6301 71.71 13.7C71.0596 14.77 70.7397 16.01 70.7397 17.4001C70.7397 18.79 71.0596 20.03 71.71 21.1101C72.3599 22.1899 73.2397 23.04 74.3696 23.6501ZM79.6699 20.3401C79.2598 20.5901 78.7798 20.72 78.2397 20.72C77.71 20.72 77.2397 20.5901 76.8296 20.3401C76.4199 20.0801 76.0796 19.7 75.8296 19.2C75.6797 18.9001 75.5728 18.5608 75.5112 18.1882C75.4702 17.9397 75.4497 17.6763 75.4497 17.4001C75.4497 16.71 75.5796 16.1101 75.8296 15.6301C75.9697 15.3555 76.1348 15.1187 76.3267 14.9194C76.3916 14.8521 76.46 14.7888 76.5312 14.73C76.625 14.6526 76.7246 14.5825 76.8296 14.52C77.2495 14.27 77.7197 14.1401 78.2397 14.1401C78.4727 14.1401 78.6924 14.1643 78.9009 14.2119C79.1758 14.2747 79.4307 14.3779 79.6699 14.52C79.7417 14.564 79.811 14.6116 79.8784 14.6628C80.0581 14.8005 80.2202 14.9648 80.3643 15.1555C80.4146 15.2217 80.4624 15.291 80.5083 15.3638C80.5615 15.4482 80.6123 15.5369 80.6597 15.6301C80.7949 15.8894 80.8921 16.1807 80.9526 16.5042C81.0044 16.7795 81.0298 17.0781 81.0298 17.4001C81.0298 18.1001 80.8999 18.6899 80.6597 19.2C80.5703 19.3896 80.4688 19.5601 80.3545 19.7124C80.2446 19.8591 80.1235 19.9895 79.9907 20.1047C79.8901 20.1917 79.7832 20.2698 79.6699 20.3401Z" fill="#0A5BE8" fill-rule="evenodd" />
|
||||
<path d="M110.05 10.52L104.31 24.9099C104.09 25.4912 103.852 26.0103 103.595 26.4675C103.326 26.9463 103.037 27.3572 102.73 27.7C102.14 28.3701 101.47 28.8501 100.75 29.1201C100.02 29.3901 99.21 29.53 98.3301 29.53C97.6299 29.53 96.9199 29.4099 96.21 29.1799C95.5 28.95 94.9302 28.6499 94.4902 28.28L96.1001 24.8801C96.3799 25.1401 96.7002 25.3401 97.0698 25.48C97.2769 25.564 97.4805 25.6228 97.6831 25.6582C97.8428 25.6863 98.0015 25.7 98.1602 25.7C98.6699 25.7 99.0698 25.5801 99.3599 25.3401C99.4653 25.2563 99.5654 25.1555 99.6582 25.0378C99.7769 24.8882 99.8848 24.7117 99.98 24.51L94.29 10.52H99.0698L102.33 18.97L105.61 10.52H110.05Z" fill="#0A5BE8" />
|
||||
</svg>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type Accessor, type JSX, createEffect, createSignal } from 'solid-js';
|
||||
import { type Accessor, createEffect, createSignal, type JSX } from 'solid-js';
|
||||
import Popup, { type PopupProps } from './Popup';
|
||||
|
||||
type ContextMenuProps = {
|
||||
|
|
@ -33,10 +33,10 @@ function ContextMenu(props: ContextMenuProps) {
|
|||
el.style.left = `${pos().x}px`;
|
||||
el.style.top = `${pos().y}px`;
|
||||
}}
|
||||
visible={props.visible}
|
||||
setVisible={props.setVisible}
|
||||
visible={props.visible}
|
||||
>
|
||||
<div ref={setRef} class="border border-gray-05 rounded-xl bg-page-elevated p-1 shadow-black/30 shadow-md">
|
||||
<div class="border border-gray-05 rounded-xl bg-page-elevated p-1 shadow-black/30 shadow-md" ref={setRef}>
|
||||
<div class="flex flex-col gap-y-1 text-fg-primary">
|
||||
{props.children}
|
||||
</div>
|
||||
|
|
@ -58,8 +58,8 @@ interface ContextMenuRowProps {
|
|||
ContextMenu.Row = function (props: ContextMenuRowProps) {
|
||||
return (
|
||||
<div
|
||||
onClick={e => props.onClick?.(e)}
|
||||
class="m-px flex items-center gap-x-2 rounded-lg px-1.5 py-0.5 [&>svg]:w-[18px] active:bg-gray-10 hover:bg-gray-05"
|
||||
onClick={e => props.onClick?.(e)}
|
||||
>
|
||||
{props.icon}
|
||||
{props.text}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { Portal } from 'solid-js/web';
|
||||
import type {
|
||||
Accessor,
|
||||
ParentProps,
|
||||
Setter,
|
||||
} from 'solid-js';
|
||||
import { Portal } from 'solid-js/web';
|
||||
|
||||
export type FullscreenOverlayProps = {
|
||||
visible: Accessor<boolean>;
|
||||
|
|
@ -22,8 +22,8 @@ function FullscreenOverlay(props: FullscreenOverlayProps) {
|
|||
return (
|
||||
<Portal {...(props.mount ? { mount: props.mount } : {})}>
|
||||
<div
|
||||
style={{ 'z-index': props.zIndex || 1000 }}
|
||||
class={`fixed top-0 left-0 w-screen h-screen bg-black/60 backdrop-blur-sm backdrop-grayscale transition-opacity ${props.visible() ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}
|
||||
style={{ 'z-index': props.zIndex || 1000 }}
|
||||
>
|
||||
|
||||
<div class="absolute left-0 top-0 h-screen w-screen flex items-center justify-center" onClick={onBackdropClick}>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { mergeRefs } from '@solid-primitives/refs';
|
||||
import { createContext, createSignal, For, onCleanup, onMount, Show, splitProps, useContext } from 'solid-js';
|
||||
import { createStore } from 'solid-js/store';
|
||||
import { Transition } from 'solid-transition-group';
|
||||
import type { MakeOptional } from '@onelauncher/client';
|
||||
import type {
|
||||
Context,
|
||||
JSX,
|
||||
ParentProps,
|
||||
Ref,
|
||||
} from 'solid-js';
|
||||
import { For, Show, createContext, createSignal, onCleanup, onMount, splitProps, useContext } from 'solid-js';
|
||||
import { mergeRefs } from '@solid-primitives/refs';
|
||||
import { createStore } from 'solid-js/store';
|
||||
import { Transition } from 'solid-transition-group';
|
||||
import type { MakeOptional } from '@onelauncher/client';
|
||||
import Button from '../base/Button';
|
||||
import FullscreenOverlay from './FullscreenOverlay';
|
||||
|
||||
|
|
@ -68,20 +68,20 @@ export function ModalRenderer() {
|
|||
|
||||
return (
|
||||
<FullscreenOverlay
|
||||
visible={() => controller.modals().length > 0}
|
||||
setVisible={(value) => {
|
||||
if (value === false)
|
||||
controller.closeModal();
|
||||
}}
|
||||
visible={() => controller.modals().length > 0}
|
||||
>
|
||||
<Transition
|
||||
mode="outin"
|
||||
enterClass="modal-animation-enter"
|
||||
enterActiveClass="modal-animation-enter-active"
|
||||
enterClass="modal-animation-enter"
|
||||
enterToClass="modal-animation-enter-to"
|
||||
exitClass="modal-animation-leave"
|
||||
exitActiveClass="modal-animation-leave-active"
|
||||
exitClass="modal-animation-leave"
|
||||
exitToClass="modal-animation-leave-to"
|
||||
mode="outin"
|
||||
>
|
||||
<Show when={controller.modals().length > 0}>
|
||||
{controller.modals()[controller.modals().length - 1]!()}
|
||||
|
|
@ -127,7 +127,7 @@ export type ModalProps = {
|
|||
|
||||
function Modal(props: ModalProps) {
|
||||
return (
|
||||
<div ref={mergeRefs(props.ref)} class="min-w-xs flex flex-col gap-y-2 border border-white/5 rounded-lg bg-page p-4 text-center">
|
||||
<div class="min-w-xs flex flex-col gap-y-2 border border-white/5 rounded-lg bg-page p-4 text-center" ref={mergeRefs(props.ref)}>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
|
|
@ -174,7 +174,6 @@ Modal.Error = function (props: ModalErrorProps) {
|
|||
return (
|
||||
<Modal.Simple
|
||||
{...rest}
|
||||
title={split.title || 'Error'}
|
||||
buttons={split.buttons || [
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
|
|
@ -182,6 +181,7 @@ Modal.Error = function (props: ModalErrorProps) {
|
|||
onClick={props.hide}
|
||||
/>,
|
||||
]}
|
||||
title={split.title || 'Error'}
|
||||
>
|
||||
<div class="flex flex-col items-center gap-y-2">
|
||||
{split.children || (
|
||||
|
|
@ -265,7 +265,6 @@ Modal.Delete = function (props: ModalDeleteProps) {
|
|||
return (
|
||||
<Modal.Simple
|
||||
{...rest}
|
||||
title={split.title || 'Confirm Delete'}
|
||||
buttons={split.buttons || [
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
|
|
@ -279,6 +278,7 @@ Modal.Delete = function (props: ModalDeleteProps) {
|
|||
onClick={onDelete}
|
||||
/>,
|
||||
]}
|
||||
title={split.title || 'Confirm Delete'}
|
||||
>
|
||||
{split.children || (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { mergeRefs } from '@solid-primitives/refs';
|
||||
import { createEffect } from 'solid-js';
|
||||
import { Portal } from 'solid-js/web';
|
||||
import type {
|
||||
Accessor,
|
||||
JSX,
|
||||
ParentProps,
|
||||
Setter,
|
||||
} from 'solid-js';
|
||||
import { Portal } from 'solid-js/web';
|
||||
|
||||
export type PopupProps = Omit<Parameters<typeof Portal>[0], 'children'> & ParentProps & {
|
||||
visible: Accessor<boolean>;
|
||||
|
|
@ -44,7 +44,7 @@ function Popup(props: PopupProps) {
|
|||
return el;
|
||||
}, props.ref)}
|
||||
>
|
||||
<div ref={popupRef} style={props.style || ''} class={`transition-opacity ${props.visible() ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'} ${props.class || ''}`}>
|
||||
<div class={`transition-opacity ${props.visible() ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'} ${props.class || ''}`} ref={popupRef} style={props.style || ''}>
|
||||
{props.children}
|
||||
</div>
|
||||
</Portal>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { For, Show } from 'solid-js';
|
||||
import { PlusIcon, Settings01Icon } from '@untitled-theme/icons-solid';
|
||||
import { useNavigate } from '@solidjs/router';
|
||||
import { PlusIcon, Settings01Icon } from '@untitled-theme/icons-solid';
|
||||
import { For, Show } from 'solid-js';
|
||||
import type { MinecraftCredentials } from '@onelauncher/client/bindings';
|
||||
import Button from '../../base/Button';
|
||||
import PlayerHead from '../../game/PlayerHead';
|
||||
|
|
@ -26,8 +26,8 @@ function AccountComponent(props: AccountComponentProps) {
|
|||
return (
|
||||
<Show when={props.account}>
|
||||
<div
|
||||
onClick={login}
|
||||
class={`flex flex-row justify-between p-2 rounded-lg ${props.loggedIn !== true && 'hover:bg-gray-05 active:bg-gray-10 hover:text-fg-primary-hover'}`}
|
||||
onClick={login}
|
||||
>
|
||||
<div class="flex flex-1 flex-row justify-start gap-x-3">
|
||||
<PlayerHead class="h-8 w-8 rounded-md" uuid={props.account!.id} />
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { type Context, Match, type ParentProps, type Resource, Switch, createContext, createSignal, useContext } from 'solid-js';
|
||||
import { LinkExternal01Icon } from '@untitled-theme/icons-solid';
|
||||
import type { MinecraftCredentials } from '@onelauncher/client/bindings';
|
||||
import Modal, { type ModalProps, createModal } from '../Modal';
|
||||
import { bridge } from '~imports';
|
||||
import useCommand, { tryResult } from '~ui/hooks/useCommand';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import useCommand, { tryResult } from '~ui/hooks/useCommand';
|
||||
import { type Context, createContext, createSignal, Match, type ParentProps, type Resource, Switch, useContext } from 'solid-js';
|
||||
import type { MinecraftCredentials } from '@onelauncher/client/bindings';
|
||||
import Modal, { createModal, type ModalProps } from '../Modal';
|
||||
|
||||
interface AccountControllerContextFunc {
|
||||
displayAddAccount: () => void;
|
||||
|
|
@ -106,7 +106,6 @@ function AddAccountModal(p: AddAccountModalProps) {
|
|||
return (
|
||||
<Modal.Simple
|
||||
{...modalProps}
|
||||
title="Add Account"
|
||||
buttons={[
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
|
|
@ -116,11 +115,12 @@ function AddAccountModal(p: AddAccountModalProps) {
|
|||
<Button
|
||||
buttonStyle="primary"
|
||||
children="Add"
|
||||
disabled={stage() !== 0}
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
onClick={start}
|
||||
disabled={stage() !== 0}
|
||||
/>,
|
||||
]}
|
||||
title="Add Account"
|
||||
>
|
||||
<div class="max-w-120 flex flex-col gap-y-3 line-height-normal">
|
||||
<Switch>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { type Accessor, type Context, type JSX, type ParentProps, type Setter, Show, createContext, createSignal, untrack, useContext } from 'solid-js';
|
||||
import { ArrowRightIcon, Server01Icon } from '@untitled-theme/icons-solid';
|
||||
import { bridge } from '~imports';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import { type Accessor, type Context, createContext, createSignal, type JSX, type ParentProps, type Setter, Show, untrack, useContext } from 'solid-js';
|
||||
import { createStore } from 'solid-js/store';
|
||||
import type { CreateCluster } from '@onelauncher/client/bindings';
|
||||
import HeaderImage from '../../../../assets/images/header.png';
|
||||
import { createModal } from '../Modal';
|
||||
import ClusterGameSetup from './ClusterGameSetup';
|
||||
import ClusterProviderSelection from './ClusterProviderSelection';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import { bridge } from '~imports';
|
||||
|
||||
export enum CreationStage {
|
||||
PROVIDER_SELECTION = 0,
|
||||
|
|
@ -176,7 +176,7 @@ export function createClusterStep(props: CreateClusterStepType): () => JSX.Eleme
|
|||
<div class="min-w-sm flex flex-col rounded-lg bg-page text-center">
|
||||
<div class="relative h-25 flex">
|
||||
<div class="absolute left-0 top-0 h-full w-full">
|
||||
<img class="h-full w-full rounded-t-lg" src={HeaderImage} alt="Header Image" />
|
||||
<img alt="Header Image" class="h-full w-full rounded-t-lg" src={HeaderImage} />
|
||||
</div>
|
||||
<div
|
||||
class="absolute left-0 top-0 h-full flex flex-row items-center justify-start gap-x-4 bg-[radial-gradient(at_center,#00000077,transparent)] px-10"
|
||||
|
|
@ -199,16 +199,16 @@ export function createClusterStep(props: CreateClusterStepType): () => JSX.Eleme
|
|||
|
||||
<div class="flex flex-row justify-end gap-x-2 p-3 pt-0">
|
||||
<Button
|
||||
class="capitalize"
|
||||
children={previousButtonText()}
|
||||
buttonStyle="ghost"
|
||||
children={previousButtonText()}
|
||||
class="capitalize"
|
||||
onClick={previousBtnClick}
|
||||
/>
|
||||
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
children={props.buttonType}
|
||||
class="capitalize"
|
||||
buttonStyle="primary"
|
||||
disabled={canGoForward() !== true}
|
||||
iconRight={<ArrowRightIcon />}
|
||||
onClick={btnClick}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
import { TextInputIcon } from '@untitled-theme/icons-solid';
|
||||
import { For, Index, type JSX, Show, createEffect, createSignal, onMount, splitProps, untrack } from 'solid-js';
|
||||
import { bridge } from '~imports';
|
||||
import Checkbox from '~ui/components/base/Checkbox';
|
||||
import Dropdown from '~ui/components/base/Dropdown';
|
||||
import SelectList from '~ui/components/base/SelectList';
|
||||
import TextField from '~ui/components/base/TextField';
|
||||
import LoaderIcon from '~ui/components/game/LoaderIcon';
|
||||
import useCommand from '~ui/hooks/useCommand';
|
||||
import { formatVersionRelease, LOADERS } from '~utils';
|
||||
import { createEffect, createSignal, For, Index, type JSX, onMount, Show, splitProps, untrack } from 'solid-js';
|
||||
import type { Loader, VersionType } from '@onelauncher/client/bindings';
|
||||
import { type ClusterStepProps, createClusterStep } from './ClusterCreationModal';
|
||||
import Dropdown from '~ui/components/base/Dropdown';
|
||||
import TextField from '~ui/components/base/TextField';
|
||||
import useCommand from '~ui/hooks/useCommand';
|
||||
import { bridge } from '~imports';
|
||||
import SelectList from '~ui/components/base/SelectList';
|
||||
import Checkbox from '~ui/components/base/Checkbox';
|
||||
import { LOADERS, formatVersionRelease } from '~utils';
|
||||
import LoaderIcon from '~ui/components/game/LoaderIcon';
|
||||
|
||||
export default createClusterStep({
|
||||
message: 'Game Setup',
|
||||
|
|
@ -40,9 +40,9 @@ function ClusterGameSetup(props: ClusterStepProps) {
|
|||
<div class="flex flex-col gap-y-4">
|
||||
<Option header="Name">
|
||||
<TextField
|
||||
iconLeft={<TextInputIcon />}
|
||||
onInput={e => setName(e.target.value)}
|
||||
placeholder="Name"
|
||||
iconLeft={<TextInputIcon />}
|
||||
/>
|
||||
</Option>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Upload01Icon, User03Icon } from '@untitled-theme/icons-solid';
|
||||
import { Index, type JSX, createEffect, createSignal } from 'solid-js';
|
||||
import { type ClusterStepProps, CreationStage, createClusterStep } from './ClusterCreationModal';
|
||||
import ModrinthIcon from '~assets/logos/modrinth.svg?component-solid';
|
||||
import CurseforgeIcon from '~assets/logos/curseforge.svg?component-solid';
|
||||
import ModrinthIcon from '~assets/logos/modrinth.svg?component-solid';
|
||||
import { createEffect, createSignal, Index, type JSX } from 'solid-js';
|
||||
import { type ClusterStepProps, createClusterStep, CreationStage } from './ClusterCreationModal';
|
||||
|
||||
const providers: Omit<ProviderCardProps, 'selected' | 'setSelected'>[] = [
|
||||
{
|
||||
|
|
@ -70,8 +70,8 @@ interface ProviderCardProps {
|
|||
function ProviderCard(props: ProviderCardProps) {
|
||||
return (
|
||||
<div
|
||||
onClick={() => props.setSelected()}
|
||||
class={`flex flex-col justify-center items-center gap-y-2 py-2 px-4 hover:bg-component-bg-hover active:bg-component-bg-pressed rounded-lg ${props.selected ? 'bg-component-bg' : ''}`}
|
||||
onClick={() => props.setSelected()}
|
||||
>
|
||||
<div class="[&>svg]:(h-8 w-8)">
|
||||
{props.icon}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { type ComponentProps, type JSX, Match, Show, Switch, createEffect, createSignal } from 'solid-js';
|
||||
import { InfoCircleIcon } from '@untitled-theme/icons-solid';
|
||||
import { PausableTimer } from '@onelauncher/client';
|
||||
import { InfoCircleIcon } from '@untitled-theme/icons-solid';
|
||||
import { type ComponentProps, createEffect, createSignal, type JSX, Match, Show, Switch } from 'solid-js';
|
||||
import type { IngressPayload, IngressType } from '@onelauncher/client/bindings';
|
||||
|
||||
type NotificationComponentProps = IngressPayload & {
|
||||
|
|
@ -103,9 +103,9 @@ function NotificationOverlayComponent(props: NotificationComponentProps) {
|
|||
// >
|
||||
<Show when={visible()}>
|
||||
<div
|
||||
class="flex flex-col overflow-hidden rounded-lg bg-component-bg"
|
||||
onMouseEnter={() => onEnter()}
|
||||
onMouseLeave={() => onLeave()}
|
||||
class="flex flex-col overflow-hidden rounded-lg bg-component-bg"
|
||||
>
|
||||
<div class="px-2">
|
||||
<NotificationPopupComponent {...props} />
|
||||
|
|
@ -114,10 +114,10 @@ function NotificationOverlayComponent(props: NotificationComponentProps) {
|
|||
<Show when={disappearing() === true && props.fraction === undefined}>
|
||||
<div class="h-1.5 w-full bg-brand-disabled">
|
||||
<div
|
||||
class="h-1.5 rounded-lg bg-brand transition-width"
|
||||
style={{
|
||||
width: `${(secondsLeft() / TOTAL_SECONDS) * 100}%`,
|
||||
}}
|
||||
class="h-1.5 rounded-lg bg-brand transition-width"
|
||||
/>
|
||||
</div>
|
||||
</Show>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
import useIngress from '~ui/hooks/useIngress';
|
||||
import { For } from 'solid-js';
|
||||
import Popup from '../Popup';
|
||||
import NotificationComponent from './NotificationComponent';
|
||||
import useIngress from '~ui/hooks/useIngress';
|
||||
|
||||
export default function NotificationOverlay() {
|
||||
const [ingress] = useIngress();
|
||||
|
||||
return (
|
||||
<Popup
|
||||
setVisible={() => {}}
|
||||
visible={() => true}
|
||||
mount={document.body}
|
||||
ref={ref => ref.classList.add('fixed', 'bottom-8', 'right-8')}
|
||||
setVisible={() => {}}
|
||||
visible={() => true}
|
||||
>
|
||||
<div class="flex flex-col-reverse gap-2">
|
||||
<For each={ingress()}>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { For, Match, Switch } from 'solid-js';
|
||||
import { Settings01Icon, Trash01Icon } from '@untitled-theme/icons-solid';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-solid';
|
||||
import Popup, { type PopupProps } from '../Popup';
|
||||
import Button from '../../base/Button';
|
||||
import NotificationComponent from './NotificationComponent';
|
||||
import useIngress from '~ui/hooks/useIngress';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-solid';
|
||||
import { For, Match, Switch } from 'solid-js';
|
||||
import Button from '../../base/Button';
|
||||
import Popup, { type PopupProps } from '../Popup';
|
||||
import NotificationComponent from './NotificationComponent';
|
||||
|
||||
function NotificationPopup(props: PopupProps) {
|
||||
const [ingress] = useIngress(updateSize);
|
||||
|
|
@ -61,7 +61,7 @@ function NotificationPopup(props: PopupProps) {
|
|||
</Switch>
|
||||
|
||||
<div class="flex flex-row items-end justify-between">
|
||||
<Button onClick={() => {}} buttonStyle="ghost" iconLeft={<Trash01Icon />}>
|
||||
<Button buttonStyle="ghost" iconLeft={<Trash01Icon />} onClick={() => {}}>
|
||||
Clear Notifications
|
||||
</Button>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { useNavigate } from '@solidjs/router';
|
||||
import { type Accessor, type Context, For, type ParentProps, type Setter, Show, createContext, createEffect, createSignal, on, onMount, untrack, useContext } from 'solid-js';
|
||||
import type { Cluster, ManagedPackage, PackageType, ProviderSearchQuery, ProviderSearchResults, Providers } from '@onelauncher/client/bindings';
|
||||
import useCommand, { tryResult } from './useCommand';
|
||||
import { useRecentCluster } from './useCluster';
|
||||
import { bridge } from '~imports';
|
||||
import BrowserPackage from '~ui/pages/browser/BrowserPackage';
|
||||
import type { ModalProps } from '~ui/components/overlay/Modal';
|
||||
import Modal, { createModal } from '~ui/components/overlay/Modal';
|
||||
import Dropdown from '~ui/components/base/Dropdown';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import Dropdown from '~ui/components/base/Dropdown';
|
||||
import Modal, { createModal } from '~ui/components/overlay/Modal';
|
||||
import BrowserPackage from '~ui/pages/browser/BrowserPackage';
|
||||
import { type Accessor, type Context, createContext, createEffect, createSignal, For, on, onMount, type ParentProps, type Setter, Show, untrack, useContext } from 'solid-js';
|
||||
import type { Cluster, ManagedPackage, PackageType, Providers, ProviderSearchQuery, ProviderSearchResults } from '@onelauncher/client/bindings';
|
||||
import type { ModalProps } from '~ui/components/overlay/Modal';
|
||||
import { useRecentCluster } from './useCluster';
|
||||
import useCommand, { tryResult } from './useCommand';
|
||||
|
||||
export type ProviderSearchOptions = ProviderSearchQuery & { provider: Providers };
|
||||
|
||||
|
|
@ -191,11 +191,21 @@ function ChooseClusterModal(props: ModalProps) {
|
|||
return (
|
||||
<Modal.Simple
|
||||
{...props}
|
||||
title="Choose a cluster"
|
||||
buttons={[
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
children="Close"
|
||||
onClick={props.hide}
|
||||
/>,
|
||||
<Button
|
||||
children="Save"
|
||||
onClick={chooseCluster}
|
||||
/>,
|
||||
]}
|
||||
children={(
|
||||
<Show
|
||||
when={clusters !== undefined}
|
||||
fallback={<div>Loading...</div>}
|
||||
when={clusters !== undefined}
|
||||
>
|
||||
<Dropdown
|
||||
onChange={setSelected}
|
||||
|
|
@ -209,17 +219,7 @@ function ChooseClusterModal(props: ModalProps) {
|
|||
</Dropdown>
|
||||
</Show>
|
||||
)}
|
||||
buttons={[
|
||||
<Button
|
||||
children="Close"
|
||||
onClick={props.hide}
|
||||
buttonStyle="secondary"
|
||||
/>,
|
||||
<Button
|
||||
children="Save"
|
||||
onClick={chooseCluster}
|
||||
/>,
|
||||
]}
|
||||
title="Choose a cluster"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { type Accessor, type Context, type ParentProps, type ResourceReturn, Show, createContext, createEffect, createSignal, useContext } from 'solid-js';
|
||||
import { useNavigate } from '@solidjs/router';
|
||||
import { bridge } from '~imports';
|
||||
import Modal, { createModal } from '~ui/components/overlay/Modal';
|
||||
import ClusterGame from '~ui/pages/cluster/ClusterGame';
|
||||
import { type Accessor, type Context, createContext, createEffect, createSignal, type ParentProps, type ResourceReturn, Show, useContext } from 'solid-js';
|
||||
import type { Cluster } from '@onelauncher/client/bindings';
|
||||
import useCommand, { tryResult } from './useCommand';
|
||||
import { bridge } from '~imports';
|
||||
import ClusterGame from '~ui/pages/cluster/ClusterGame';
|
||||
import Modal, { createModal } from '~ui/components/overlay/Modal';
|
||||
|
||||
const ClusterContext = createContext() as Context<ResourceReturn<Cluster>>;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type ResourceOptions, type ResourceReturn, type ResourceSource, createResource } from 'solid-js';
|
||||
import { createResource, type ResourceOptions, type ResourceReturn, type ResourceSource } from 'solid-js';
|
||||
import type { Result } from '@onelauncher/client/bindings';
|
||||
|
||||
type Command<R, E> = () => Promise<Result<R, E>>;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { type IngressPayload, type IngressType, events } from '@onelauncher/client/bindings';
|
||||
import { type Signal, createSignal, onMount } from 'solid-js';
|
||||
import { events, type IngressPayload, type IngressType } from '@onelauncher/client/bindings';
|
||||
import { createSignal, onMount, type Signal } from 'solid-js';
|
||||
|
||||
type Ingresses = IngressPayload[];
|
||||
type OnUpdateFn = (event: IngressType['type']) => unknown;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { ChevronLeftIcon, ChevronRightIcon } from '@untitled-theme/icons-solid';
|
||||
import { For, Show, createSignal } from 'solid-js';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import { createSignal, For, Show } from 'solid-js';
|
||||
|
||||
export interface PaginationOptions {
|
||||
itemsCount: () => number;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { BeforeLeaveEventArgs } from '@solidjs/router';
|
||||
import { useBeforeLeave } from '@solidjs/router';
|
||||
import { createSignal } from 'solid-js';
|
||||
import type { BeforeLeaveEventArgs } from '@solidjs/router';
|
||||
|
||||
interface PreventLeaveContext {
|
||||
continue: () => void;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-solid';
|
||||
import { createSignal } from 'solid-js';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import Modal, { createModal } from '~ui/components/overlay/Modal';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-solid';
|
||||
import { createSignal } from 'solid-js';
|
||||
|
||||
function usePromptOpener() {
|
||||
const [url, setUrl] = createSignal<string | null>(null);
|
||||
|
|
@ -10,18 +10,6 @@ function usePromptOpener() {
|
|||
const modal = createModal(props => (
|
||||
<Modal.Simple
|
||||
{...props}
|
||||
title="Third Party Link"
|
||||
children={(
|
||||
<div class="flex flex-col items-center gap-y-4">
|
||||
<span class="max-w-58">You are about to visit an external website that may malicious.</span>
|
||||
<span>Do you wish to proceed?</span>
|
||||
<OverlayScrollbarsComponent class="max-w-100">
|
||||
<div class="h-8 flex flex-row">
|
||||
<code>{url()}</code>
|
||||
</div>
|
||||
</OverlayScrollbarsComponent>
|
||||
</div>
|
||||
)}
|
||||
buttons={[
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
|
|
@ -34,6 +22,18 @@ function usePromptOpener() {
|
|||
onClick={proceed}
|
||||
/>,
|
||||
]}
|
||||
children={(
|
||||
<div class="flex flex-col items-center gap-y-4">
|
||||
<span class="max-w-58">You are about to visit an external website that may malicious.</span>
|
||||
<span>Do you wish to proceed?</span>
|
||||
<OverlayScrollbarsComponent class="max-w-100">
|
||||
<div class="h-8 flex flex-row">
|
||||
<code>{url()}</code>
|
||||
</div>
|
||||
</OverlayScrollbarsComponent>
|
||||
</div>
|
||||
)}
|
||||
title="Third Party Link"
|
||||
/>
|
||||
));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { type Context, type ParentProps, Show, createContext, createEffect, useContext } from 'solid-js';
|
||||
import { useBeforeLeave } from '@solidjs/router';
|
||||
import { bridge } from '~imports';
|
||||
import { type Context, createContext, createEffect, type ParentProps, Show, useContext } from 'solid-js';
|
||||
import type { Settings } from '@onelauncher/client/bindings';
|
||||
import useCommand from './useCommand';
|
||||
import { bridge } from '~imports';
|
||||
|
||||
/**
|
||||
* Sync the launcher state (CSS, text etc) with the current settings
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { useNavigate } from '@solidjs/router';
|
||||
import {
|
||||
DotsVerticalIcon,
|
||||
PlayIcon,
|
||||
|
|
@ -5,20 +6,19 @@ import {
|
|||
RefreshCw01Icon,
|
||||
SearchMdIcon,
|
||||
} from '@untitled-theme/icons-solid';
|
||||
import { For, Show, onMount } from 'solid-js';
|
||||
import { useNavigate } from '@solidjs/router';
|
||||
import { bridge } from '~imports';
|
||||
|
||||
import ClusterCover from '~ui/components/game/ClusterCover';
|
||||
import { useClusterCreator } from '~ui/components/overlay/cluster/ClusterCreationModal';
|
||||
import { useLaunchCluster, useRecentCluster } from '~ui/hooks/useCluster';
|
||||
import useCommand from '~ui/hooks/useCommand';
|
||||
import { formatAsDuration, upperFirst } from '~utils';
|
||||
import { For, onMount, Show } from 'solid-js';
|
||||
import type { Cluster } from '@onelauncher/client/bindings';
|
||||
import BannerBackground from '../../assets/images/header.png';
|
||||
import Button from '../components/base/Button';
|
||||
import TextField from '../components/base/TextField';
|
||||
import ClusterRoot from './cluster/ClusterRoot';
|
||||
import ClusterCover from '~ui/components/game/ClusterCover';
|
||||
import useCommand from '~ui/hooks/useCommand';
|
||||
import { bridge } from '~imports';
|
||||
import { formatAsDuration, upperFirst } from '~utils';
|
||||
import { useClusterCreator } from '~ui/components/overlay/cluster/ClusterCreationModal';
|
||||
import { useLaunchCluster, useRecentCluster } from '~ui/hooks/useCluster';
|
||||
|
||||
type GroupedClusters = Record<string, Cluster[]>;
|
||||
|
||||
|
|
@ -63,19 +63,18 @@ function HomePage() {
|
|||
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
iconLeft={<PlusIcon class="stroke-[2.2] !w-5" />}
|
||||
children="New Cluster"
|
||||
iconLeft={<PlusIcon class="stroke-[2.2] !w-5" />}
|
||||
onClick={newCluster}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Show
|
||||
when={containerIds(clusters()).length > 0}
|
||||
children={(
|
||||
<For each={Object.entries(clusters() ?? {})}>
|
||||
{([group, clusters]) => (
|
||||
<ClusterGroup title={group} clusters={clusters} />
|
||||
<ClusterGroup clusters={clusters} title={group} />
|
||||
)}
|
||||
</For>
|
||||
)}
|
||||
|
|
@ -85,6 +84,7 @@ function HomePage() {
|
|||
<span class="text-xl font-bold">Create one now with the New Cluster button.</span>
|
||||
</div>
|
||||
)}
|
||||
when={containerIds(clusters()).length > 0}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -109,13 +109,13 @@ function Banner() {
|
|||
<div class="relative h-52 min-h-52 w-full overflow-hidden rounded-xl">
|
||||
<ClusterCover
|
||||
class="absolute h-52 w-full rounded-xl object-cover"
|
||||
cluster={cluster()}
|
||||
fallback={BannerBackground}
|
||||
linearBlur={{
|
||||
degrees: 270,
|
||||
blur: 30,
|
||||
class: 'after:right-1/3!',
|
||||
}}
|
||||
cluster={cluster()}
|
||||
fallback={BannerBackground}
|
||||
/>
|
||||
|
||||
<div class="relative z-10 h-full flex flex-col items-start justify-between px-8 py-6 text-fg-primary">
|
||||
|
|
@ -141,23 +141,23 @@ function Banner() {
|
|||
<div class="w-full flex flex-row items-end justify-between">
|
||||
<div class="flex flex-row items-center gap-x-4">
|
||||
<Show
|
||||
when={cluster() !== undefined}
|
||||
children={(
|
||||
<>
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
iconLeft={<PlayIcon />}
|
||||
children={`Launch ${cluster()!.meta.mc_version}`}
|
||||
iconLeft={<PlayIcon />}
|
||||
onClick={launch}
|
||||
/>
|
||||
<Button
|
||||
buttonStyle="iconSecondary"
|
||||
class="bg-op-10!"
|
||||
children={<DotsVerticalIcon />}
|
||||
class="bg-op-10!"
|
||||
onClick={() => ClusterRoot.open(navigate, cluster()!.uuid)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
when={cluster() !== undefined}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-row gap-x-2">
|
||||
|
|
@ -183,8 +183,8 @@ function ClusterCard(props: Cluster) {
|
|||
return (
|
||||
<>
|
||||
<div
|
||||
onClick={e => openClusterPage(e)}
|
||||
class="group relative h-[152px] flex flex-col border border-gray-05 rounded-xl bg-component-bg active:bg-component-bg-pressed hover:bg-component-bg-hover"
|
||||
onClick={e => openClusterPage(e)}
|
||||
>
|
||||
<div class="relative flex-1 overflow-hidden rounded-t-xl">
|
||||
<div
|
||||
|
|
@ -192,8 +192,8 @@ function ClusterCard(props: Cluster) {
|
|||
style={{ '-webkit-transform': 'translateZ(0)' }}
|
||||
>
|
||||
<ClusterCover
|
||||
cluster={props}
|
||||
class="h-full w-full object-cover"
|
||||
cluster={props}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { ChevronRightIcon } from '@untitled-theme/icons-solid';
|
||||
import { Show, onMount } from 'solid-js';
|
||||
import type { ManagedPackage } from '@onelauncher/client/bindings';
|
||||
import { BrowserContent } from './BrowserRoot';
|
||||
import useBrowser from '~ui/hooks/useBrowser';
|
||||
import OneConfigLogo from '~assets/logos/oneconfig.svg?component-solid';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import SearchResultsContainer from '~ui/components/content/SearchResults';
|
||||
import useBrowser from '~ui/hooks/useBrowser';
|
||||
import { onMount, Show } from 'solid-js';
|
||||
import type { ManagedPackage } from '@onelauncher/client/bindings';
|
||||
import { BrowserContent } from './BrowserRoot';
|
||||
|
||||
function BrowserMain() {
|
||||
const browser = useBrowser();
|
||||
|
|
@ -24,9 +24,9 @@ function BrowserMain() {
|
|||
<Featured package={browser.featured()!} />
|
||||
|
||||
<SearchResultsContainer
|
||||
header="Modrinth"
|
||||
category="modrinth"
|
||||
collapsable
|
||||
header="Modrinth"
|
||||
{...browser.cache()!}
|
||||
/>
|
||||
</Show>
|
||||
|
|
@ -51,7 +51,7 @@ function Featured(props: FeaturedProps) {
|
|||
<h5 class="ml-2">Featured</h5>
|
||||
<div class="w-full flex flex-row overflow-hidden rounded-lg bg-page-elevated">
|
||||
<div class="w-full p-1">
|
||||
<img class="aspect-ratio-video w-full rounded-md object-cover object-center" src="" alt="" />
|
||||
<img alt="" class="aspect-ratio-video w-full rounded-md object-cover object-center" src="" />
|
||||
</div>
|
||||
<div class="max-w-84 min-w-52 flex flex-col gap-y-1 p-4">
|
||||
<h2>{props.package.title}</h2>
|
||||
|
|
@ -66,8 +66,8 @@ function Featured(props: FeaturedProps) {
|
|||
<div class="flex flex-row justify-end">
|
||||
<Button
|
||||
buttonStyle="ghost"
|
||||
iconRight={<ChevronRightIcon />}
|
||||
children="View Package"
|
||||
iconRight={<ChevronRightIcon />}
|
||||
onClick={open}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
import { For, Match, type ParentProps, Show, Switch, createContext, createEffect, createSignal, on, useContext } from 'solid-js';
|
||||
import { A, type Params, Route, useSearchParams } from '@solidjs/router';
|
||||
import { CalendarIcon, ChevronDownIcon, ClockRewindIcon, Download01Icon, File02Icon, HeartIcon, LinkExternal01Icon } from '@untitled-theme/icons-solid';
|
||||
import type { Cluster, ManagedPackage, ManagedUser, ManagedVersion, Providers } from '@onelauncher/client/bindings';
|
||||
import { getLicenseUrl, getPackageUrl, upperFirst } from '../../../utils';
|
||||
import SteveHead from '~assets/images/steve.png';
|
||||
import { bridge } from '~imports';
|
||||
import useCommand from '~ui/hooks/useCommand';
|
||||
import { abbreviateNumber, formatAsRelative } from '~utils';
|
||||
import Tooltip from '~ui/components/base/Tooltip';
|
||||
import Markdown from '~ui/components/content/Markdown';
|
||||
import AnimatedRoutes from '~ui/components/AnimatedRoutes';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import Dropdown from '~ui/components/base/Dropdown';
|
||||
import useBrowser from '~ui/hooks/useBrowser';
|
||||
import SteveHead from '~assets/images/steve.png';
|
||||
import usePromptOpener from '~ui/hooks/usePromptOpener';
|
||||
import Link from '~ui/components/base/Link';
|
||||
import usePagination from '~ui/hooks/usePagination';
|
||||
import Tooltip from '~ui/components/base/Tooltip';
|
||||
import Markdown from '~ui/components/content/Markdown';
|
||||
import Spinner from '~ui/components/Spinner';
|
||||
import AnimatedRoutes from '~ui/components/AnimatedRoutes';
|
||||
import useBrowser from '~ui/hooks/useBrowser';
|
||||
import useCommand from '~ui/hooks/useCommand';
|
||||
import usePagination from '~ui/hooks/usePagination';
|
||||
import usePromptOpener from '~ui/hooks/usePromptOpener';
|
||||
import { abbreviateNumber, formatAsRelative } from '~utils';
|
||||
import { createContext, createEffect, createSignal, For, Match, on, type ParentProps, Show, Switch, useContext } from 'solid-js';
|
||||
import type { Cluster, ManagedPackage, ManagedUser, ManagedVersion, Providers } from '@onelauncher/client/bindings';
|
||||
import { getLicenseUrl, getPackageUrl, upperFirst } from '../../../utils';
|
||||
|
||||
interface BrowserModParams extends Params {
|
||||
id: string;
|
||||
|
|
@ -39,9 +39,9 @@ function BrowserPackageProvider(props: ParentProps & { pkg: ManagedPackage }) {
|
|||
function BrowserPackageRoutes() {
|
||||
return (
|
||||
<>
|
||||
<Route path="/" component={BrowserPackageBody} />
|
||||
<Route component={BrowserPackageBody} path="/" />
|
||||
{/* <Route path="/gallery" component={BrowserPackageGallery} /> */}
|
||||
<Route path="/versions" component={BrowserPackageVersions} />
|
||||
<Route component={BrowserPackageVersions} path="/versions" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -56,10 +56,10 @@ function NavLink(props: ParentProps & { href: string }) {
|
|||
|
||||
return (
|
||||
<A
|
||||
class="rounded-md px-4 py-2 text-sm text-fg-primary font-semibold uppercase active:bg-component-bg-pressed hover:bg-component-bg-hover"
|
||||
activeClass="bg-component-bg-pressed hover:bg-component-bg-pressed"
|
||||
href={url()}
|
||||
children={props.children}
|
||||
class="rounded-md px-4 py-2 text-sm text-fg-primary font-semibold uppercase active:bg-component-bg-pressed hover:bg-component-bg-hover"
|
||||
href={url()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -79,10 +79,9 @@ function BrowserPackage(props: ParentProps) {
|
|||
<Spinner.Suspense>
|
||||
<div class="h-full flex flex-1 flex-row items-start gap-x-4">
|
||||
<Show
|
||||
when={pkg() !== undefined && authors() !== undefined}
|
||||
children={(
|
||||
<>
|
||||
<BrowserSidebar package={pkg()!} authors={authors()!} />
|
||||
<BrowserSidebar authors={authors()!} package={pkg()!} />
|
||||
|
||||
<div class="min-h-full flex flex-1 flex-col items-start gap-y-4 pb-8">
|
||||
<div class="flex flex-none flex-row gap-x-1 rounded-lg bg-component-bg p-1">
|
||||
|
|
@ -109,6 +108,7 @@ function BrowserPackage(props: ParentProps) {
|
|||
</div>
|
||||
</>
|
||||
)}
|
||||
when={pkg() !== undefined && authors() !== undefined}
|
||||
/>
|
||||
</div>
|
||||
</Spinner.Suspense>
|
||||
|
|
@ -132,8 +132,8 @@ function BrowserSidebar(props: { package: ManagedPackage; authors: ManagedUser[]
|
|||
<div class="sticky top-0 z-1 max-w-60 min-w-54 flex flex-col gap-y-4">
|
||||
<div class="min-h-72 flex flex-col overflow-hidden rounded-lg bg-component-bg">
|
||||
<div class="relative h-28 flex items-center justify-center overflow-hidden">
|
||||
<img class="absolute z-0 max-w-none w-7/6 filter-blur-xl" src={props.package.icon_url || ''} alt={`Icon for ${props.package.title}`} />
|
||||
<img class="relative z-1 aspect-ratio-square w-2/5 rounded-md image-render-auto" src={props.package.icon_url || ''} alt={`Icon for ${props.package.title}`} />
|
||||
<img alt={`Icon for ${props.package.title}`} class="absolute z-0 max-w-none w-7/6 filter-blur-xl" src={props.package.icon_url || ''} />
|
||||
<img alt={`Icon for ${props.package.title}`} class="relative z-1 aspect-ratio-square w-2/5 rounded-md image-render-auto" src={props.package.icon_url || ''} />
|
||||
</div>
|
||||
<div class="flex flex-1 flex-col gap-2 p-3">
|
||||
<div class="flex flex-col gap-2">
|
||||
|
|
@ -170,7 +170,7 @@ function BrowserSidebar(props: { package: ManagedPackage; authors: ManagedUser[]
|
|||
|
||||
<div class="flex flex-col gap-2 rounded-lg bg-component-bg p-3">
|
||||
<h4 class="text-fg-primary font-bold">Links</h4>
|
||||
<Link includeIcon href={getPackageUrl(props.package.provider, props.package.id, props.package.package_type)}>
|
||||
<Link href={getPackageUrl(props.package.provider, props.package.id, props.package.package_type)} includeIcon>
|
||||
{props.package.provider}
|
||||
{' '}
|
||||
Page
|
||||
|
|
@ -186,7 +186,7 @@ function BrowserSidebar(props: { package: ManagedPackage; authors: ManagedUser[]
|
|||
class="flex flex-row items-center gap-x-1 rounded-md p-1 active:bg-component-bg-pressed hover:bg-component-bg-hover"
|
||||
onClick={() => promptOpen(author.url)}
|
||||
>
|
||||
<img class="h-8 min-h-8 min-w-8 w-8 rounded-md" src={author.avatar_url || SteveHead} alt={`${author.username}'s avatar`} />
|
||||
<img alt={`${author.username}'s avatar`} class="h-8 min-h-8 min-w-8 w-8 rounded-md" src={author.avatar_url || SteveHead} />
|
||||
<div class="flex flex-1 flex-col justify-center gap-y-1">
|
||||
<span>{author.username}</span>
|
||||
|
||||
|
|
@ -214,7 +214,7 @@ function BrowserSidebar(props: { package: ManagedPackage; authors: ManagedUser[]
|
|||
<div class="flex flex-row items-start gap-x-1">
|
||||
<File02Icon class="h-3 min-w-3 w-3" />
|
||||
License
|
||||
<Link includeIcon href={getLicenseUrl(props.package.license)}>
|
||||
<Link href={getLicenseUrl(props.package.license)} includeIcon>
|
||||
{props.package.license?.name || props.package.license?.id || 'Unknown'}
|
||||
</Link>
|
||||
</div>
|
||||
|
|
@ -303,32 +303,32 @@ function InstallButton(props: ManagedPackage) {
|
|||
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
iconLeft={<Download01Icon />}
|
||||
class="max-w-full flex-1 rounded-r-none!"
|
||||
disabled={filtered()?.length === 0}
|
||||
onClick={download}
|
||||
children={(
|
||||
<div class="flex flex-1 flex-col items-center justify-center">
|
||||
<p class="text-xs">Download latest to</p>
|
||||
<span class="mt-0.5 h-3.5 max-w-38 overflow-x-hidden text-sm font-bold">{filtered?.()?.[selected?.()]?.meta.name || 'Unknown'}</span>
|
||||
</div>
|
||||
)}
|
||||
class="max-w-full flex-1 rounded-r-none!"
|
||||
disabled={filtered()?.length === 0}
|
||||
iconLeft={<Download01Icon />}
|
||||
onClick={download}
|
||||
/>
|
||||
|
||||
<Dropdown
|
||||
class="w-8"
|
||||
dropdownClass="w-58! right-0"
|
||||
disabled={filtered()?.length === 0}
|
||||
selected={selected}
|
||||
onChange={setSelected}
|
||||
component={props => (
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
iconLeft={<ChevronDownIcon />}
|
||||
class="h-full w-full border-l border-white/5 rounded-l-none! px-0!"
|
||||
iconLeft={<ChevronDownIcon />}
|
||||
onClick={() => props.setVisible(true)}
|
||||
/>
|
||||
)}
|
||||
disabled={filtered()?.length === 0}
|
||||
dropdownClass="w-58! right-0"
|
||||
onChange={setSelected}
|
||||
selected={selected}
|
||||
>
|
||||
<For each={filtered()}>
|
||||
{cluster => (
|
||||
|
|
@ -403,7 +403,7 @@ function BrowserPackageVersions() {
|
|||
}));
|
||||
|
||||
return (
|
||||
<div ref={container} class="h-full w-full flex flex-1 flex-col gap-y-1">
|
||||
<div class="h-full w-full flex flex-1 flex-col gap-y-1" ref={container}>
|
||||
<div class="flex flex-row justify-between">
|
||||
<h1>
|
||||
Versions - Page
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
import { Route, useLocation } from '@solidjs/router';
|
||||
import { For, type JSX, type ParentProps } from 'solid-js';
|
||||
import { SearchMdIcon, Settings01Icon } from '@untitled-theme/icons-solid';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import Dropdown from '~ui/components/base/Dropdown';
|
||||
import TextField from '~ui/components/base/TextField';
|
||||
import useBrowser from '~ui/hooks/useBrowser';
|
||||
import { PROVIDERS } from '~utils';
|
||||
import { browserCategories } from '~utils/browser';
|
||||
import { For, type JSX, type ParentProps } from 'solid-js';
|
||||
import BrowserMain from './BrowserMain';
|
||||
import BrowserPackage from './BrowserPackage';
|
||||
import BrowserSearch from './BrowserSearch';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import TextField from '~ui/components/base/TextField';
|
||||
import useBrowser from '~ui/hooks/useBrowser';
|
||||
import { browserCategories } from '~utils/browser';
|
||||
import Dropdown from '~ui/components/base/Dropdown';
|
||||
import { PROVIDERS } from '~utils';
|
||||
|
||||
function BrowserRoutes() {
|
||||
return (
|
||||
<>
|
||||
<Route path="/" component={BrowserMain} />
|
||||
<Route path="/package" component={BrowserPackage} children={<BrowserPackage.Routes />} />
|
||||
<Route path="/search" component={BrowserSearch} />
|
||||
<Route component={BrowserMain} path="/" />
|
||||
<Route children={<BrowserPackage.Routes />} component={BrowserPackage} path="/package" />
|
||||
<Route component={BrowserSearch} path="/search" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -50,9 +50,9 @@ function BrowserToolbar() {
|
|||
<div class="flex flex-row gap-2">
|
||||
<TextField
|
||||
iconLeft={<SearchMdIcon />}
|
||||
value={browser.searchQuery().query || ''}
|
||||
placeholder="Search for content"
|
||||
onKeyPress={onKeyPress}
|
||||
placeholder="Search for content"
|
||||
value={browser.searchQuery().query || ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -126,11 +126,11 @@ function BrowserSidebar() {
|
|||
<div class="flex flex-col gap-y-1">
|
||||
<h6 class="my-1">Provider</h6>
|
||||
<Dropdown
|
||||
selected={() => PROVIDERS.indexOf(controller.searchQuery().provider)}
|
||||
onChange={index => controller.setSearchQuery(prev => ({
|
||||
...prev,
|
||||
provider: PROVIDERS[index] || 'Modrinth',
|
||||
}))}
|
||||
selected={() => PROVIDERS.indexOf(controller.searchQuery().provider)}
|
||||
>
|
||||
<For each={PROVIDERS}>
|
||||
{provider => (
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { Show, createEffect, on } from 'solid-js';
|
||||
import { BrowserContent } from './BrowserRoot';
|
||||
import { bridge } from '~imports';
|
||||
import SearchResultsContainer from '~ui/components/content/SearchResults';
|
||||
import Spinner from '~ui/components/Spinner';
|
||||
import useBrowser from '~ui/hooks/useBrowser';
|
||||
import useCommand from '~ui/hooks/useCommand';
|
||||
import usePagination, { type PaginationOptions } from '~ui/hooks/usePagination';
|
||||
import { createEffect, on, Show } from 'solid-js';
|
||||
import { BrowserContent } from './BrowserRoot';
|
||||
|
||||
function BrowserSearch() {
|
||||
const browser = useBrowser();
|
||||
|
|
@ -40,14 +40,14 @@ function BrowserSearch() {
|
|||
<Show when={results() !== undefined}>
|
||||
<SearchResultsContainer
|
||||
category="test"
|
||||
provider="Modrinth"
|
||||
results={results()!.results}
|
||||
header={(
|
||||
<div class="w-full flex flex-row items-end justify-between">
|
||||
<h5 class="ml-2">Results</h5>
|
||||
<pagination.Navigation />
|
||||
</div>
|
||||
)}
|
||||
provider="Modrinth"
|
||||
results={results()!.results}
|
||||
/>
|
||||
</Show>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
import { type Params, useSearchParams } from '@solidjs/router';
|
||||
import { createSignal, onCleanup, onMount } from 'solid-js';
|
||||
import type { UnlistenFn } from '@tauri-apps/api/event';
|
||||
import { SlashOctagonIcon } from '@untitled-theme/icons-solid';
|
||||
import { render } from 'solid-js/web';
|
||||
import type { DetailedProcess } from '@onelauncher/client/bindings';
|
||||
import { bridge } from '~imports';
|
||||
import Sidebar from '~ui/components/Sidebar';
|
||||
import useClusterContext from '~ui/hooks/useCluster';
|
||||
import { TimeAgo } from '~ui/components/DynamicTime';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import Tooltip from '~ui/components/base/Tooltip';
|
||||
import FormattedLog, { Line } from '~ui/components/content/FormattedLog';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import { TimeAgo } from '~ui/components/DynamicTime';
|
||||
import Modal, { createModal } from '~ui/components/overlay/Modal';
|
||||
import Sidebar from '~ui/components/Sidebar';
|
||||
import useClusterContext from '~ui/hooks/useCluster';
|
||||
import useCommand from '~ui/hooks/useCommand';
|
||||
import { createSignal, onCleanup, onMount } from 'solid-js';
|
||||
import { render } from 'solid-js/web';
|
||||
import type { DetailedProcess } from '@onelauncher/client/bindings';
|
||||
import type { UnlistenFn } from '@tauri-apps/api/event';
|
||||
|
||||
interface ClusterGameParams extends Params {
|
||||
process_uuid: string;
|
||||
|
|
@ -51,11 +51,11 @@ function ClusterGame() {
|
|||
const killModal = createModal(props => (
|
||||
<Modal.Delete
|
||||
{...props}
|
||||
title="Kill Game"
|
||||
children="Are you sure you want to kill the game?"
|
||||
onDelete={() => killProcess(true)}
|
||||
deleteBtnText="Kill $1"
|
||||
onDelete={() => killProcess(true)}
|
||||
timeLeft={1}
|
||||
title="Kill Game"
|
||||
/>
|
||||
));
|
||||
|
||||
|
|
@ -98,17 +98,17 @@ function ClusterGame() {
|
|||
|
||||
<FormattedLog
|
||||
codeRef={el => codeRef = el}
|
||||
log={log()?.trim()}
|
||||
enableAutoScroll={true}
|
||||
log={log()?.trim()}
|
||||
/>
|
||||
|
||||
<div class="flex flex-row items-center justify-end gap-x-2">
|
||||
<Button
|
||||
buttonStyle="danger"
|
||||
children="Kill"
|
||||
disabled={!isRunning()}
|
||||
iconLeft={<SlashOctagonIcon />}
|
||||
onClick={() => killProcess(false)}
|
||||
disabled={!isRunning()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { For, Show, createEffect, createSignal, untrack } from 'solid-js';
|
||||
import { LinkExternal01Icon, Upload01Icon } from '@untitled-theme/icons-solid';
|
||||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import { join } from 'pathe';
|
||||
import useCommand, { tryResult } from '~ui/hooks/useCommand';
|
||||
import { LinkExternal01Icon, Upload01Icon } from '@untitled-theme/icons-solid';
|
||||
import { bridge } from '~imports';
|
||||
import useClusterContext from '~ui/hooks/useCluster';
|
||||
import Dropdown from '~ui/components/base/Dropdown';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import Dropdown from '~ui/components/base/Dropdown';
|
||||
import FormattedLog from '~ui/components/content/FormattedLog';
|
||||
import useClusterContext from '~ui/hooks/useCluster';
|
||||
import useCommand, { tryResult } from '~ui/hooks/useCommand';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import { join } from 'pathe';
|
||||
import { createEffect, createSignal, For, Show, untrack } from 'solid-js';
|
||||
|
||||
function ClusterLogs() {
|
||||
const [cluster] = useClusterContext();
|
||||
|
|
@ -71,16 +71,16 @@ function ClusterLogs() {
|
|||
<div class="flex flex-row gap-x-2">
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
onClick={uploadAndOpenLog}
|
||||
children="Upload"
|
||||
iconLeft={<Upload01Icon />}
|
||||
disabled={missingLogs()}
|
||||
iconLeft={<Upload01Icon />}
|
||||
onClick={uploadAndOpenLog}
|
||||
/>
|
||||
|
||||
<Dropdown
|
||||
onChange={changeLog}
|
||||
class="min-w-50"
|
||||
disabled={missingLogs()}
|
||||
onChange={changeLog}
|
||||
>
|
||||
<For each={logs() || ['None']}>
|
||||
{(log) => {
|
||||
|
|
@ -98,14 +98,14 @@ function ClusterLogs() {
|
|||
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
onClick={openFolder}
|
||||
children="Open Folder"
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
onClick={openFolder}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Show when={logContent() !== null} fallback={<span>No logs were found.</span>}>
|
||||
<Show fallback={<span>No logs were found.</span>} when={logContent() !== null}>
|
||||
<FormattedLog log={logContent()!} />
|
||||
</Show>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
import { FilterFunnel01Icon, SearchMdIcon, Trash03Icon } from '@untitled-theme/icons-solid';
|
||||
import { For, Match, Show, Switch, createEffect, createResource, createSignal } from 'solid-js';
|
||||
import UFuzzy from '@leeoniya/ufuzzy';
|
||||
import type { ManagedPackage, Package, Providers } from '@onelauncher/client/bindings';
|
||||
import { FilterFunnel01Icon, SearchMdIcon, Trash03Icon } from '@untitled-theme/icons-solid';
|
||||
import { bridge } from '~imports';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import TextField from '~ui/components/base/TextField';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
import Sidebar from '~ui/components/Sidebar';
|
||||
import useClusterContext from '~ui/hooks/useCluster';
|
||||
import useCommand, { tryResult } from '~ui/hooks/useCommand';
|
||||
import { bridge } from '~imports';
|
||||
import Spinner from '~ui/components/Spinner';
|
||||
import useBrowser from '~ui/hooks/useBrowser';
|
||||
import useClusterContext from '~ui/hooks/useCluster';
|
||||
import useCommand, { tryResult } from '~ui/hooks/useCommand';
|
||||
import { createEffect, createResource, createSignal, For, Match, Show, Switch } from 'solid-js';
|
||||
import type { ManagedPackage, Package, Providers } from '@onelauncher/client/bindings';
|
||||
|
||||
// TODO: Possibly optimise this as it has 2 cloned lists, and another containing only the names
|
||||
function ClusterMods() {
|
||||
|
|
@ -114,12 +114,12 @@ function ClusterMods() {
|
|||
<div class="flex flex-row items-stretch justify-end gap-x-2">
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
onClick={() => toggleNameSort()}
|
||||
children={sortingAtoZ() ? 'A-Z' : 'Z-A'}
|
||||
iconLeft={<FilterFunnel01Icon />}
|
||||
onClick={() => toggleNameSort()}
|
||||
/>
|
||||
|
||||
<TextField iconLeft={<SearchMdIcon />} placeholder="Search..." onInput={e => search(e.target.value)} />
|
||||
<TextField iconLeft={<SearchMdIcon />} onInput={e => search(e.target.value)} placeholder="Search..." />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -132,7 +132,7 @@ function ClusterMods() {
|
|||
<For each={displayedMods()}>
|
||||
{(mod) => {
|
||||
const managed = getManagedData(mod);
|
||||
return <ModEntry pkg={mod} managed={managed} refetch={refetch} />;
|
||||
return <ModEntry managed={managed} pkg={mod} refetch={refetch} />;
|
||||
}}
|
||||
</For>
|
||||
</Match>
|
||||
|
|
@ -224,9 +224,9 @@ function ModEntry(props: ModEntryProps) {
|
|||
>
|
||||
<div>
|
||||
<Show
|
||||
when={icon()}
|
||||
children={<img alt={name()} class="aspect-ratio-square h-10 rounded-lg" src={icon()!} />}
|
||||
fallback={<div class="aspect-ratio-square h-10 rounded-lg bg-gray-05" />}
|
||||
children={<img src={icon()!} alt={name()} class="aspect-ratio-square h-10 rounded-lg" />}
|
||||
when={icon()}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-1 flex-col">
|
||||
|
|
|
|||
|
|
@ -1,23 +1,23 @@
|
|||
import { Edit02Icon, FolderIcon, ImagePlusIcon, LinkExternal01Icon, PlayIcon, Save01Icon, Share07Icon, Trash01Icon } from '@untitled-theme/icons-solid';
|
||||
import { type Accessor, type Setter, Show, createSignal, untrack } from 'solid-js';
|
||||
import { useNavigate } from '@solidjs/router';
|
||||
import * as dialog from '@tauri-apps/plugin-dialog';
|
||||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import { join } from 'pathe';
|
||||
import type { Cluster } from '@onelauncher/client/bindings';
|
||||
import ClusterCover from '../../components/game/ClusterCover';
|
||||
import LoaderIcon from '../../components/game/LoaderIcon';
|
||||
import Button from '../../components/base/Button';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
import Sidebar from '~ui/components/Sidebar';
|
||||
import { formatAsDuration, upperFirst } from '~utils';
|
||||
import useClusterContext, { useLaunchCluster } from '~ui/hooks/useCluster';
|
||||
import { Edit02Icon, FolderIcon, ImagePlusIcon, LinkExternal01Icon, PlayIcon, Save01Icon, Share07Icon, Trash01Icon } from '@untitled-theme/icons-solid';
|
||||
import { bridge } from '~imports';
|
||||
import TextField from '~ui/components/base/TextField';
|
||||
import Modal, { createModal, type ModalProps } from '~ui/components/overlay/Modal';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
import SettingsRow from '~ui/components/SettingsRow';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import Modal, { type ModalProps, createModal } from '~ui/components/overlay/Modal';
|
||||
import Sidebar from '~ui/components/Sidebar';
|
||||
import useClusterContext, { useLaunchCluster } from '~ui/hooks/useCluster';
|
||||
import usePreventLeave from '~ui/hooks/usePreventLeave';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import { formatAsDuration, upperFirst } from '~utils';
|
||||
import { join } from 'pathe';
|
||||
import { type Accessor, createSignal, type Setter, Show, untrack } from 'solid-js';
|
||||
import type { Cluster } from '@onelauncher/client/bindings';
|
||||
import Button from '../../components/base/Button';
|
||||
import ClusterCover from '../../components/game/ClusterCover';
|
||||
import LoaderIcon from '../../components/game/LoaderIcon';
|
||||
|
||||
function ClusterOverview() {
|
||||
const { settings } = useSettings();
|
||||
|
|
@ -32,8 +32,8 @@ function ClusterOverview() {
|
|||
const saveModal = createModal(props => (
|
||||
<SaveModal
|
||||
{...props}
|
||||
save={save}
|
||||
dontSave={dontSave}
|
||||
save={save}
|
||||
/>
|
||||
));
|
||||
|
||||
|
|
@ -133,67 +133,67 @@ function ClusterOverview() {
|
|||
<ScrollableContainer>
|
||||
<Banner
|
||||
cluster={cluster()!}
|
||||
refetch={refetch}
|
||||
|
||||
editMode={editMode}
|
||||
newName={newName}
|
||||
setNewName={setNewName}
|
||||
|
||||
newCover={newCover}
|
||||
newName={newName}
|
||||
refetch={refetch}
|
||||
setNewCover={setNewCover}
|
||||
setNewName={setNewName}
|
||||
/>
|
||||
|
||||
<SettingsRow.Header>Folders and Files</SettingsRow.Header>
|
||||
<SettingsRow
|
||||
title="Cluster Folder"
|
||||
description={getPath()}
|
||||
icon={<FolderIcon />}
|
||||
disabled={editMode()}
|
||||
children={(
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
children="Open"
|
||||
disabled={editMode()}
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
onClick={openPath}
|
||||
disabled={editMode()}
|
||||
/>
|
||||
)}
|
||||
description={getPath()}
|
||||
disabled={editMode()}
|
||||
icon={<FolderIcon />}
|
||||
title="Cluster Folder"
|
||||
/>
|
||||
|
||||
<SettingsRow.Header>Cluster Actions</SettingsRow.Header>
|
||||
<SettingsRow
|
||||
title="Edit Cluster"
|
||||
description="Edit the cluster name and cover image."
|
||||
icon={<Edit02Icon />}
|
||||
children={(
|
||||
<Button.Toggle
|
||||
buttonStyle={editMode() === false ? 'secondary' : 'primary'}
|
||||
checked={editMode}
|
||||
children={editMode() ? 'Save' : 'Edit'}
|
||||
iconLeft={(
|
||||
<Show
|
||||
when={editMode() === false}
|
||||
fallback={<Save01Icon />}
|
||||
children={<Edit02Icon />}
|
||||
fallback={<Save01Icon />}
|
||||
when={editMode() === false}
|
||||
/>
|
||||
)}
|
||||
children={editMode() ? 'Save' : 'Edit'}
|
||||
checked={editMode}
|
||||
onChecked={toggleEditMode}
|
||||
/>
|
||||
)}
|
||||
description="Edit the cluster name and cover image."
|
||||
icon={<Edit02Icon />}
|
||||
title="Edit Cluster"
|
||||
/>
|
||||
<SettingsRow
|
||||
title="Delete Cluster"
|
||||
description="Delete this cluster and all its data."
|
||||
icon={<Trash01Icon />}
|
||||
disabled={editMode()}
|
||||
children={(
|
||||
<Button
|
||||
buttonStyle="danger"
|
||||
children="Delete"
|
||||
disabled={editMode()}
|
||||
iconLeft={<Trash01Icon />}
|
||||
onClick={() => deleteModal.show()}
|
||||
disabled={editMode()}
|
||||
/>
|
||||
)}
|
||||
description="Delete this cluster and all its data."
|
||||
disabled={editMode()}
|
||||
icon={<Trash01Icon />}
|
||||
title="Delete Cluster"
|
||||
/>
|
||||
</ScrollableContainer>
|
||||
</Sidebar.Page>
|
||||
|
|
@ -211,8 +211,6 @@ function SaveModal(p: SaveModalProps) {
|
|||
return (
|
||||
<Modal.Simple
|
||||
{...modalProps}
|
||||
title="Save Changes?"
|
||||
children="Do you want to save your changes?"
|
||||
buttons={[
|
||||
<Button
|
||||
buttonStyle="secondary"
|
||||
|
|
@ -230,6 +228,8 @@ function SaveModal(p: SaveModalProps) {
|
|||
onClick={props.save}
|
||||
/>,
|
||||
]}
|
||||
children="Do you want to save your changes?"
|
||||
title="Save Changes?"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -275,29 +275,29 @@ function Banner(props: BannerProps) {
|
|||
<div class="relative aspect-ratio-video h-full min-w-57 w-57 overflow-hidden border border-gray-10 rounded-lg">
|
||||
<Show when={props.editMode()}>
|
||||
<div
|
||||
onClick={launchFilePicker}
|
||||
class="absolute z-1 h-full w-full flex items-center justify-center bg-black/50 opacity-50 hover:opacity-100"
|
||||
onClick={launchFilePicker}
|
||||
>
|
||||
<ImagePlusIcon class="h-12 w-12" />
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<ClusterCover override={props.newCover()} cluster={props.cluster} class="h-full w-full object-cover" />
|
||||
<ClusterCover class="h-full w-full object-cover" cluster={props.cluster} override={props.newCover()} />
|
||||
</div>
|
||||
|
||||
<div class="w-full flex flex-col justify-between gap-y-.5 overflow-hidden text-fg-primary">
|
||||
<div>
|
||||
<Show
|
||||
when={props.editMode()}
|
||||
fallback={
|
||||
<h2 class="break-words text-wrap text-2xl">{props.cluster.meta.name}</h2>
|
||||
}
|
||||
when={props.editMode()}
|
||||
>
|
||||
<TextField
|
||||
placeholder={props.cluster.meta.name}
|
||||
labelClass="h-10"
|
||||
class="text-xl font-bold"
|
||||
labelClass="h-10"
|
||||
onChange={e => updateName(e.target.value)}
|
||||
placeholder={props.cluster.meta.name}
|
||||
/>
|
||||
</Show>
|
||||
</div>
|
||||
|
|
@ -311,11 +311,11 @@ function Banner(props: BannerProps) {
|
|||
>
|
||||
<span class="flex flex-row items-center gap-x-1">
|
||||
<LoaderIcon
|
||||
loader={props.cluster.meta.loader}
|
||||
class="w-5"
|
||||
classList={{
|
||||
'opacity-50': props.editMode(),
|
||||
}}
|
||||
loader={props.cluster.meta.loader}
|
||||
/>
|
||||
<span>{props.cluster.meta.mc_version}</span>
|
||||
<span>{upperFirst(props.cluster.meta.loader || 'unknown')}</span>
|
||||
|
|
@ -343,11 +343,11 @@ function Banner(props: BannerProps) {
|
|||
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
iconLeft={<PlayIcon />}
|
||||
children="Launch"
|
||||
class="!w-auto"
|
||||
onClick={launch}
|
||||
disabled={props.editMode()}
|
||||
iconLeft={<PlayIcon />}
|
||||
onClick={launch}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,34 +1,33 @@
|
|||
import { type Navigator, Route, useIsRouting, useSearchParams } from '@solidjs/router';
|
||||
import { type ParentProps, Show, createEffect, createResource, createSignal, onCleanup, onMount } from 'solid-js';
|
||||
import { EyeIcon, File06Icon, Globe04Icon, Image03Icon, PackagePlusIcon, Settings04Icon } from '@untitled-theme/icons-solid';
|
||||
import type { UnlistenFn } from '@tauri-apps/api/event';
|
||||
import Sidebar from '../../components/Sidebar';
|
||||
import AnimatedRoutes from '../../components/AnimatedRoutes';
|
||||
import ErrorBoundary from '../../components/ErrorBoundary';
|
||||
import ClusterOverview from './ClusterOverview';
|
||||
import ClusterLogs from './ClusterLogs';
|
||||
import ClusterMods from './ClusterMods';
|
||||
import ClusterScreenshots from './ClusterScreenshots';
|
||||
import ClusterSettings from './ClusterSettings';
|
||||
import ClusterGame from './ClusterGame';
|
||||
import ClusterWorlds from './ClusterWorlds';
|
||||
import useClusterContext, { ClusterProvider } from '~ui/hooks/useCluster';
|
||||
import { supportsMods } from '~utils';
|
||||
import { tryResult } from '~ui/hooks/useCommand';
|
||||
import { bridge } from '~imports';
|
||||
import PlayerHead from '~ui/components/game/PlayerHead';
|
||||
import useClusterContext, { ClusterProvider } from '~ui/hooks/useCluster';
|
||||
import { tryResult } from '~ui/hooks/useCommand';
|
||||
import { supportsMods } from '~utils';
|
||||
import { createEffect, createResource, createSignal, onCleanup, onMount, type ParentProps, Show } from 'solid-js';
|
||||
import type { UnlistenFn } from '@tauri-apps/api/event';
|
||||
import AnimatedRoutes from '../../components/AnimatedRoutes';
|
||||
import ErrorBoundary from '../../components/ErrorBoundary';
|
||||
import Sidebar from '../../components/Sidebar';
|
||||
import ClusterGame from './ClusterGame';
|
||||
import ClusterLogs from './ClusterLogs';
|
||||
import ClusterMods from './ClusterMods';
|
||||
import ClusterOverview from './ClusterOverview';
|
||||
import ClusterScreenshots from './ClusterScreenshots';
|
||||
import ClusterSettings from './ClusterSettings';
|
||||
import ClusterWorlds from './ClusterWorlds';
|
||||
|
||||
function ClusterRoutes() {
|
||||
return (
|
||||
<>
|
||||
<Route path="/" component={ClusterOverview} />
|
||||
<Route path="/logs" component={ClusterLogs} />
|
||||
<Route path="/mods" component={ClusterMods} />
|
||||
<Route path="/screenshots" component={ClusterScreenshots} />
|
||||
<Route path="/worlds" component={ClusterWorlds} />
|
||||
<Route path="/settings" component={ClusterSettings} />
|
||||
<Route component={ClusterOverview} path="/" />
|
||||
<Route component={ClusterLogs} path="/logs" />
|
||||
<Route component={ClusterMods} path="/mods" />
|
||||
<Route component={ClusterScreenshots} path="/screenshots" />
|
||||
<Route component={ClusterWorlds} path="/worlds" />
|
||||
<Route component={ClusterSettings} path="/settings" />
|
||||
<Route
|
||||
path="/game"
|
||||
component={() => {
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
|
|
@ -38,6 +37,7 @@ function ClusterRoutes() {
|
|||
</Show>
|
||||
);
|
||||
}}
|
||||
path="/game"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { convertFileSrc } from '@tauri-apps/api/core';
|
||||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import { LinkExternal01Icon } from '@untitled-theme/icons-solid';
|
||||
import { join } from 'pathe';
|
||||
import { For, Show } from 'solid-js';
|
||||
import { bridge } from '~imports';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
|
|
@ -10,6 +8,8 @@ import Sidebar from '~ui/components/Sidebar';
|
|||
import useClusterContext from '~ui/hooks/useCluster';
|
||||
import useCommand from '~ui/hooks/useCommand';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import { join } from 'pathe';
|
||||
import { For, Show } from 'solid-js';
|
||||
|
||||
function ClusterScreenshots() {
|
||||
const { settings } = useSettings();
|
||||
|
|
@ -31,7 +31,7 @@ function ClusterScreenshots() {
|
|||
<div class="grid grid-cols-[repeat(auto-fill,minmax(350px,1fr))] w-full transform-gpu gap-2">
|
||||
<For each={list()!}>
|
||||
{screenshot => (
|
||||
<ScreenshotEntry path={screenshot} cluster_path={cluster()?.path || ''} />
|
||||
<ScreenshotEntry cluster_path={cluster()?.path || ''} path={screenshot} />
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
|
|
@ -41,8 +41,8 @@ function ClusterScreenshots() {
|
|||
<div class="mt-2 flex flex-row items-end justify-end">
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
children="Open Folder"
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
onClick={openFolder}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -68,7 +68,7 @@ function ScreenshotEntry(props: { path: string; cluster_path: string }) {
|
|||
class="flex flex-col items-center gap-3 rounded-xl bg-component-bg p-3 active:bg-component-bg-pressed hover:bg-component-bg-hover hover:opacity-80"
|
||||
onClick={onClick}
|
||||
>
|
||||
<img src={pathSrc()} alt={props.path} class="aspect-ratio-video w-full rounded-lg" />
|
||||
<img alt={props.path} class="aspect-ratio-video w-full rounded-lg" src={pathSrc()} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { useBeforeLeave } from '@solidjs/router';
|
||||
import { type Accessor, Show } from 'solid-js';
|
||||
import type { Cluster } from '@onelauncher/client/bindings';
|
||||
import { GameSettings, JvmSettings, LauncherSettings, ProcessSettings, createSetting } from '../settings/game/SettingsMinecraft';
|
||||
import { bridge } from '~imports';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
import Sidebar from '~ui/components/Sidebar';
|
||||
import useClusterContext from '~ui/hooks/useCluster';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import { tryResult } from '~ui/hooks/useCommand';
|
||||
import { bridge } from '~imports';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import { type Accessor, Show } from 'solid-js';
|
||||
import type { Cluster } from '@onelauncher/client/bindings';
|
||||
import { createSetting, GameSettings, JvmSettings, LauncherSettings, ProcessSettings } from '../settings/game/SettingsMinecraft';
|
||||
|
||||
function ClusterSettings() {
|
||||
const [cluster] = useClusterContext();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import { LinkExternal01Icon, Trash01Icon } from '@untitled-theme/icons-solid';
|
||||
import { join } from 'pathe';
|
||||
import { For, Show } from 'solid-js';
|
||||
import { bridge } from '~imports';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import WorldIcon from '~ui/components/game/WorldIcon';
|
||||
|
|
@ -11,6 +9,8 @@ import Sidebar from '~ui/components/Sidebar';
|
|||
import useClusterContext from '~ui/hooks/useCluster';
|
||||
import useCommand from '~ui/hooks/useCommand';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import { join } from 'pathe';
|
||||
import { For, Show } from 'solid-js';
|
||||
|
||||
function ClusterWorlds() {
|
||||
const { settings } = useSettings();
|
||||
|
|
@ -32,7 +32,7 @@ function ClusterWorlds() {
|
|||
<div class="flex flex-col gap-2">
|
||||
<For each={list()!}>
|
||||
{world_name => (
|
||||
<WorldEntry name={world_name} cluster_path={cluster()?.path || ''} />
|
||||
<WorldEntry cluster_path={cluster()?.path || ''} name={world_name} />
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
|
|
@ -42,8 +42,8 @@ function ClusterWorlds() {
|
|||
<div class="mt-2 flex flex-row items-end justify-end">
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
children="Open Folder"
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
onClick={openFolder}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -61,11 +61,11 @@ function WorldEntry(props: { name: string; cluster_path: string }) {
|
|||
const deleteModal = createModal(self => (
|
||||
<Modal.Delete
|
||||
{...self}
|
||||
title={`Delete '${props.name}'`}
|
||||
onDelete={() => {
|
||||
// bridge.commands.deleteWorld(props.name);
|
||||
self.hide();
|
||||
}}
|
||||
title={`Delete '${props.name}'`}
|
||||
/>
|
||||
));
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ function WorldEntry(props: { name: string; cluster_path: string }) {
|
|||
onClick={onClick}
|
||||
>
|
||||
<div class="flex flex-row items-center gap-x-3">
|
||||
<WorldIcon cluster_name={props.cluster_path} world_name={props.name} class="aspect-ratio-square h-16 w-16" />
|
||||
<WorldIcon class="aspect-ratio-square h-16 w-16" cluster_name={props.cluster_path} world_name={props.name} />
|
||||
<div class="flex flex-col gap-y-2">
|
||||
<h3>{props.name}</h3>
|
||||
<p>Todo</p>
|
||||
|
|
|
|||
|
|
@ -1,35 +1,35 @@
|
|||
import { type ParentProps, createSignal } from 'solid-js';
|
||||
import { Brush01Icon, CodeSnippet02Icon, MessageTextSquare01Icon, RefreshCcw02Icon, Rocket02Icon, Sliders04Icon, Users01Icon } from '@untitled-theme/icons-solid';
|
||||
import { PROGRAM_INFO } from '@onelauncher/client/bindings';
|
||||
import { Route } from '@solidjs/router';
|
||||
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
|
||||
import { PROGRAM_INFO } from '@onelauncher/client/bindings';
|
||||
import { Brush01Icon, CodeSnippet02Icon, MessageTextSquare01Icon, RefreshCcw02Icon, Rocket02Icon, Sliders04Icon, Users01Icon } from '@untitled-theme/icons-solid';
|
||||
import AnimatedRoutes from '~ui/components/AnimatedRoutes';
|
||||
import Tooltip from '~ui/components/base/Tooltip';
|
||||
import ErrorBoundary from '~ui/components/ErrorBoundary';
|
||||
import { createSignal, type ParentProps } from 'solid-js';
|
||||
import Sidebar from '../../components/Sidebar';
|
||||
import SettingsGeneral from './launcher/SettingsGeneral';
|
||||
import SettingsAppearance from './launcher/SettingsAppearance';
|
||||
import SettingsAccounts from './game/SettingsAccounts';
|
||||
import SettingsMinecraft from './game/SettingsMinecraft';
|
||||
import SettingsChangelog from './about/SettingsChangelog';
|
||||
import SettingsDeveloper from './about/SettingsDeveloper';
|
||||
import SettingsFeedback from './about/SettingsFeedback';
|
||||
import SettingsChangelog from './about/SettingsChangelog';
|
||||
import AnimatedRoutes from '~ui/components/AnimatedRoutes';
|
||||
import ErrorBoundary from '~ui/components/ErrorBoundary';
|
||||
import Tooltip from '~ui/components/base/Tooltip';
|
||||
import SettingsAccounts from './game/SettingsAccounts';
|
||||
import SettingsMinecraft from './game/SettingsMinecraft';
|
||||
import SettingsAppearance from './launcher/SettingsAppearance';
|
||||
import SettingsGeneral from './launcher/SettingsGeneral';
|
||||
|
||||
function SettingsRoutes() {
|
||||
return (
|
||||
<>
|
||||
{/* Launcher Settings */}
|
||||
<Route path="/" component={SettingsGeneral} />
|
||||
<Route path="/appearance" component={SettingsAppearance} />
|
||||
<Route component={SettingsGeneral} path="/" />
|
||||
<Route component={SettingsAppearance} path="/appearance" />
|
||||
|
||||
{/* Game Settings */}
|
||||
<Route path="/minecraft" component={SettingsMinecraft} />
|
||||
<Route path="/accounts" component={SettingsAccounts} />
|
||||
<Route component={SettingsMinecraft} path="/minecraft" />
|
||||
<Route component={SettingsAccounts} path="/accounts" />
|
||||
|
||||
{/* About */}
|
||||
<Route path="/feedback" component={SettingsFeedback} />
|
||||
<Route path="/changelog" component={SettingsChangelog} />
|
||||
<Route path="/developer" component={SettingsDeveloper} />
|
||||
<Route component={SettingsFeedback} path="/feedback" />
|
||||
<Route component={SettingsChangelog} path="/changelog" />
|
||||
<Route component={SettingsDeveloper} path="/developer" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,20 +15,20 @@ function SettingsDeveloper() {
|
|||
<p class="mb-2">You probably shouldn't mess with any of these if you don't know what you're doing!</p>
|
||||
<ScrollableContainer>
|
||||
<SettingsRow
|
||||
title="Open Dev Tools"
|
||||
description="Opens the browser developer tools."
|
||||
icon={<CodeBrowserIcon />}
|
||||
title="Open Dev Tools"
|
||||
>
|
||||
<Button
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
children="Open"
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
/>
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title="Debug mode"
|
||||
description="Enables debug mode."
|
||||
icon={<GitMergeIcon />}
|
||||
title="Debug mode"
|
||||
>
|
||||
<Toggle
|
||||
checked={() => settings().debug_mode ?? false}
|
||||
|
|
@ -37,14 +37,14 @@ function SettingsDeveloper() {
|
|||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title="Reload"
|
||||
description="Reloads the launcher frontend."
|
||||
icon={<RefreshCcw05Icon />}
|
||||
title="Reload"
|
||||
>
|
||||
<Button
|
||||
children="Reload"
|
||||
iconLeft={<RefreshCcw05Icon />}
|
||||
onClick={() => location.href = '/'}
|
||||
children="Reload"
|
||||
/>
|
||||
</SettingsRow>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { InfoCircleIcon, Trash01Icon, UserPlus02Icon } from '@untitled-theme/icons-solid';
|
||||
import { For, Match, Show, Switch, createSignal, mergeProps } from 'solid-js';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import Tooltip from '~ui/components/base/Tooltip';
|
||||
import PlayerHead from '~ui/components/game/PlayerHead';
|
||||
import useAccountController from '~ui/components/overlay/account/AddAccountModal';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
import Sidebar from '~ui/components/Sidebar';
|
||||
import { createSignal, For, Match, mergeProps, Show, Switch } from 'solid-js';
|
||||
|
||||
function SettingsAccounts() {
|
||||
const controller = useAccountController();
|
||||
|
|
@ -38,11 +38,11 @@ function SettingsAccounts() {
|
|||
<For each={controller.accounts()}>
|
||||
{account => (
|
||||
<AccountRow
|
||||
username={account.username}
|
||||
uuid={account.id}
|
||||
current={controller.defaultAccount()?.id === account.id}
|
||||
onClick={setCurrent}
|
||||
onDelete={onDelete}
|
||||
username={account.username}
|
||||
uuid={account.id}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
|
|
@ -53,8 +53,8 @@ function SettingsAccounts() {
|
|||
<div class="mt-2 flex flex-row items-end justify-end">
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
iconLeft={<UserPlus02Icon />}
|
||||
children="Add Account"
|
||||
iconLeft={<UserPlus02Icon />}
|
||||
onClick={showModal}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -76,14 +76,14 @@ function AccountRow(props: AccountRowProps) {
|
|||
|
||||
return (
|
||||
<div
|
||||
onClick={() => props.onClick(props.uuid)}
|
||||
class={`flex flex-row bg-component-bg hover:bg-component-bg-hover active:bg-component-bg-pressed rounded-xl gap-3.5 p-4 items-center box-border border ${defaultProps.current ? 'border-brand' : 'border-transparent'}`}
|
||||
onClick={() => props.onClick(props.uuid)}
|
||||
>
|
||||
<div class="h-12 w-12 flex items-center justify-center">
|
||||
<PlayerHead
|
||||
class="h-12 w-12 rounded-md"
|
||||
uuid={props.uuid}
|
||||
onError={() => setErrored(true)}
|
||||
uuid={props.uuid}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import { ActivityIcon, CpuChip01Icon, Database01Icon, EyeIcon, FilePlus02Icon, FileX02Icon, LayoutTopIcon, Maximize01Icon, ParagraphWrapIcon, VariableIcon, XIcon } from '@untitled-theme/icons-solid';
|
||||
import { type Accessor, type Setter, Show, createSignal, onMount, splitProps, untrack } from 'solid-js';
|
||||
import type { Memory, Resolution } from '@onelauncher/client/bindings';
|
||||
import TextField from '~ui/components/base/TextField';
|
||||
import Toggle from '~ui/components/base/Toggle';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
|
|
@ -8,6 +6,8 @@ import BaseSettingsRow, { type SettingsRowProps } from '~ui/components/SettingsR
|
|||
import Sidebar from '~ui/components/Sidebar';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import { asEnvVariables } from '~utils';
|
||||
import { type Accessor, createSignal, onMount, type Setter, Show, splitProps, untrack } from 'solid-js';
|
||||
import type { Memory, Resolution } from '@onelauncher/client/bindings';
|
||||
|
||||
function SettingsMinecraft() {
|
||||
return (
|
||||
|
|
@ -108,11 +108,11 @@ export function GameSettings(props: {
|
|||
<BaseSettingsRow.Header>Game</BaseSettingsRow.Header>
|
||||
|
||||
<SettingsRow
|
||||
title="Force Fullscreen"
|
||||
description="Force Minecraft to start in fullscreen mode."
|
||||
icon={<Maximize01Icon />}
|
||||
isGlobal={props.fullscreen.isGlobal}
|
||||
reset={props.fullscreen.resetToFallback}
|
||||
title="Force Fullscreen"
|
||||
>
|
||||
<Toggle
|
||||
checked={props.fullscreen.get}
|
||||
|
|
@ -121,38 +121,38 @@ export function GameSettings(props: {
|
|||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title="Resolution"
|
||||
description="The game window resolution in pixels."
|
||||
icon={<LayoutTopIcon />}
|
||||
isGlobal={props.resolution.isGlobal}
|
||||
reset={props.resolution.resetToFallback}
|
||||
title="Resolution"
|
||||
>
|
||||
<div class="grid grid-cols-[70px_16px_70px] gap-2 grid-justify-center grid-items-center">
|
||||
<TextField.Number
|
||||
class="text-center"
|
||||
value={props.resolution.get()[0]}
|
||||
onValidSubmit={(value) => {
|
||||
props.resolution.set([Number.parseInt(value), props.resolution.get()[1]]);
|
||||
}}
|
||||
value={props.resolution.get()[0]}
|
||||
/>
|
||||
<XIcon class="h-4 w-4" />
|
||||
<TextField.Number
|
||||
class="text-center"
|
||||
value={props.resolution.get()[1]}
|
||||
onValidSubmit={(value) => {
|
||||
props.resolution.set([props.resolution.get()[0], Number.parseInt(value)]);
|
||||
}}
|
||||
value={props.resolution.get()[1]}
|
||||
/>
|
||||
</div>
|
||||
</SettingsRow>
|
||||
|
||||
{/* TODO: make this a memory slider */}
|
||||
<SettingsRow
|
||||
title="Memory"
|
||||
description="The amount of memory in megabytes allocated for the game."
|
||||
icon={<Database01Icon />}
|
||||
isGlobal={props.memory.isGlobal}
|
||||
reset={props.memory.resetToFallback}
|
||||
title="Memory"
|
||||
>
|
||||
<div class="flex items-center gap-x-4 flex-justify-center">
|
||||
<div class="flex flex-row items-center gap-x-2">
|
||||
|
|
@ -160,12 +160,12 @@ export function GameSettings(props: {
|
|||
<TextField.Number
|
||||
class="text-center"
|
||||
labelClass="w-[70px]!"
|
||||
value={props.memory.get().minimum}
|
||||
min={1}
|
||||
max={props.memory.get().maximum}
|
||||
min={1}
|
||||
onValidSubmit={(value) => {
|
||||
props.memory.set({ minimum: Number.parseInt(value), maximum: props.memory.get().maximum });
|
||||
}}
|
||||
value={props.memory.get().minimum}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -174,12 +174,12 @@ export function GameSettings(props: {
|
|||
<TextField.Number
|
||||
class="text-center"
|
||||
labelClass="w-[70px]!"
|
||||
value={props.memory.get().maximum}
|
||||
min={props.memory.get().minimum}
|
||||
max={Number.MAX_SAFE_INTEGER}
|
||||
min={props.memory.get().minimum}
|
||||
onValidSubmit={(value) => {
|
||||
props.memory.set({ minimum: props.memory.get().minimum, maximum: Number.parseInt(value) });
|
||||
}}
|
||||
value={props.memory.get().maximum}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -202,11 +202,11 @@ export function LauncherSettings(props: {
|
|||
|
||||
<Show when={props.hideOnLaunch !== undefined}>
|
||||
<SettingsRow
|
||||
title="Hide On Launch"
|
||||
description="Hide the launcher whenever you start a game."
|
||||
icon={<EyeIcon />}
|
||||
isGlobal={props.hideOnLaunch!.isGlobal}
|
||||
reset={props.hideOnLaunch!.resetToFallback}
|
||||
title="Hide On Launch"
|
||||
>
|
||||
<Toggle
|
||||
checked={props.hideOnLaunch!.get}
|
||||
|
|
@ -217,11 +217,11 @@ export function LauncherSettings(props: {
|
|||
|
||||
<Show when={props.allowParallelClusters !== undefined}>
|
||||
<SettingsRow
|
||||
title="Allow Parallel Clusters"
|
||||
description="Allow running the same cluster with the same account."
|
||||
icon={<ActivityIcon />}
|
||||
isGlobal={props.allowParallelClusters!.isGlobal}
|
||||
reset={props.allowParallelClusters!.resetToFallback}
|
||||
title="Allow Parallel Clusters"
|
||||
>
|
||||
<Toggle
|
||||
checked={props.allowParallelClusters!.get}
|
||||
|
|
@ -243,47 +243,47 @@ export function ProcessSettings(props: {
|
|||
<BaseSettingsRow.Header>Process</BaseSettingsRow.Header>
|
||||
|
||||
<SettingsRow
|
||||
title="Pre-Launch Command"
|
||||
description="Command to run before launching the game."
|
||||
icon={<FilePlus02Icon />}
|
||||
isGlobal={props.preCommand.isGlobal}
|
||||
reset={props.preCommand.resetToFallback}
|
||||
title="Pre-Launch Command"
|
||||
>
|
||||
<TextField
|
||||
labelClass="w-full! min-w-[260px]!"
|
||||
onValidSubmit={props.preCommand.set}
|
||||
placeholder="echo 'Game started'"
|
||||
value={props.preCommand.get()}
|
||||
onValidSubmit={props.preCommand.set}
|
||||
/>
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title="Wrapper Command"
|
||||
description="Command to run when launching the game."
|
||||
icon={<ParagraphWrapIcon />}
|
||||
isGlobal={props.wrapperCommand.isGlobal}
|
||||
reset={props.wrapperCommand.resetToFallback}
|
||||
title="Wrapper Command"
|
||||
>
|
||||
<TextField
|
||||
labelClass="w-full! min-w-[260px]!"
|
||||
onValidSubmit={props.wrapperCommand.set}
|
||||
placeholder="gamescope"
|
||||
value={props.wrapperCommand.get()}
|
||||
onValidSubmit={props.wrapperCommand.set}
|
||||
/>
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title="Post-Exit Command"
|
||||
description="Command to run after exiting the game."
|
||||
icon={<FileX02Icon />}
|
||||
isGlobal={props.postCommand.isGlobal}
|
||||
reset={props.postCommand.resetToFallback}
|
||||
title="Post-Exit Command"
|
||||
>
|
||||
<TextField
|
||||
labelClass="w-full! min-w-[260px]!"
|
||||
onValidSubmit={props.postCommand.set}
|
||||
placeholder="echo 'Game exited'"
|
||||
value={props.postCommand.get()}
|
||||
onValidSubmit={props.postCommand.set}
|
||||
/>
|
||||
</SettingsRow>
|
||||
</>
|
||||
|
|
@ -299,44 +299,44 @@ export function JvmSettings(props: {
|
|||
<BaseSettingsRow.Header>Java</BaseSettingsRow.Header>
|
||||
|
||||
<SettingsRow
|
||||
title="Version"
|
||||
description="Choose the JRE (Java Runtime Environment) used for the game."
|
||||
icon={<CpuChip01Icon />}
|
||||
isGlobal={() => true}
|
||||
reset={() => {}}
|
||||
title="Version"
|
||||
/>
|
||||
|
||||
<SettingsRow
|
||||
title="Arguments"
|
||||
description="Additional arguments passed to the JVM (Java Virtual Machine)."
|
||||
icon={<FilePlus02Icon />}
|
||||
isGlobal={props.javaArgs.isGlobal}
|
||||
reset={props.javaArgs.resetToFallback}
|
||||
title="Arguments"
|
||||
>
|
||||
<TextField
|
||||
labelClass="w-full! min-w-[260px]!"
|
||||
placeholder='"-Xmx3G"'
|
||||
value={props.javaArgs.get().join(' ')}
|
||||
onValidSubmit={(value) => {
|
||||
props.javaArgs.set(value.split(' '));
|
||||
}}
|
||||
placeholder='"-Xmx3G"'
|
||||
value={props.javaArgs.get().join(' ')}
|
||||
/>
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title="Environment Variables"
|
||||
description="Additional environment variables passed to the JVM (Java Virtual Machine)."
|
||||
icon={<VariableIcon />}
|
||||
isGlobal={props.envVars.isGlobal}
|
||||
reset={props.envVars.resetToFallback}
|
||||
title="Environment Variables"
|
||||
>
|
||||
<TextField
|
||||
labelClass="w-full! min-w-[260px]!"
|
||||
placeholder='"JAVA_HOME=/path/to/java"'
|
||||
value={props.envVars.get().join(' ')}
|
||||
onValidSubmit={(value) => {
|
||||
props.envVars.set(asEnvVariables(value));
|
||||
}}
|
||||
placeholder='"JAVA_HOME=/path/to/java"'
|
||||
value={props.envVars.get().join(' ')}
|
||||
/>
|
||||
</SettingsRow>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { ColorsIcon, PackageIcon, PaintPourIcon, Speedometer04Icon } from '@untitled-theme/icons-solid';
|
||||
import { useBeforeLeave } from '@solidjs/router';
|
||||
import { For, createSignal } from 'solid-js';
|
||||
import SettingsRow from '../../../components/SettingsRow';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
import { ColorsIcon, PackageIcon, PaintPourIcon, Speedometer04Icon } from '@untitled-theme/icons-solid';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import Dropdown from '~ui/components/base/Dropdown';
|
||||
import Toggle from '~ui/components/base/Toggle';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
import Sidebar from '~ui/components/Sidebar';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import Dropdown from '~ui/components/base/Dropdown';
|
||||
import { BROWSER_VIEWS } from '~utils/browser';
|
||||
import { createSignal, For } from 'solid-js';
|
||||
import SettingsRow from '../../../components/SettingsRow';
|
||||
|
||||
function SettingsAppearance() {
|
||||
const { settings, saveOnLeave } = useSettings();
|
||||
|
|
@ -35,21 +35,21 @@ function SettingsAppearance() {
|
|||
</div>
|
||||
|
||||
<SettingsRow
|
||||
title="Accent Color"
|
||||
description="The main color used across the launcher. This doesn't edit your theme."
|
||||
icon={<PaintPourIcon />}
|
||||
title="Accent Color"
|
||||
>
|
||||
<Button iconLeft={<ColorsIcon />}>#ff0000</Button>
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title="Package List Style"
|
||||
description="Change the look of the package list."
|
||||
icon={<PackageIcon />}
|
||||
title="Package List Style"
|
||||
>
|
||||
<Dropdown
|
||||
selected={() => BROWSER_VIEWS.indexOf(settings().browser_list_view ?? 'grid')}
|
||||
onChange={value => settings().browser_list_view = BROWSER_VIEWS[value] ?? 'grid'}
|
||||
selected={() => BROWSER_VIEWS.indexOf(settings().browser_list_view ?? 'grid')}
|
||||
>
|
||||
<For each={BROWSER_VIEWS}>
|
||||
{view => (
|
||||
|
|
@ -60,9 +60,9 @@ function SettingsAppearance() {
|
|||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title="Disable Animations"
|
||||
description="Disables all animations in the launcher."
|
||||
icon={<Speedometer04Icon />}
|
||||
title="Disable Animations"
|
||||
>
|
||||
<Toggle
|
||||
checked={() => settings().disable_animations ?? false}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { AlertSquareIcon, FolderIcon, LinkExternal01Icon, XIcon } from '@untitled-theme/icons-solid';
|
||||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import SettingsRow from '../../../components/SettingsRow';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
import { AlertSquareIcon, FolderIcon, LinkExternal01Icon, XIcon } from '@untitled-theme/icons-solid';
|
||||
import DiscordIcon from '~assets/logos/discord.svg?component-solid';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import Toggle from '~ui/components/base/Toggle';
|
||||
import ScrollableContainer from '~ui/components/ScrollableContainer';
|
||||
import Sidebar from '~ui/components/Sidebar';
|
||||
import useSettings from '~ui/hooks/useSettings';
|
||||
import Button from '~ui/components/base/Button';
|
||||
import DiscordIcon from '~assets/logos/discord.svg?component-solid';
|
||||
import SettingsRow from '../../../components/SettingsRow';
|
||||
|
||||
function SettingsGeneral() {
|
||||
const { settings, saveOnLeave } = useSettings();
|
||||
|
|
@ -23,9 +23,9 @@ function SettingsGeneral() {
|
|||
<ScrollableContainer>
|
||||
|
||||
<SettingsRow
|
||||
title="Discord RPC"
|
||||
description="Enable Discord Rich Presence."
|
||||
icon={<DiscordIcon class="w-6" />}
|
||||
title="Discord RPC"
|
||||
>
|
||||
<Toggle
|
||||
checked={() => !(settings().disable_discord ?? false)}
|
||||
|
|
@ -34,9 +34,9 @@ function SettingsGeneral() {
|
|||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title="Hide Close Dialog"
|
||||
description="Hide the confirmation dialog when closing the launcher."
|
||||
icon={<XIcon />}
|
||||
title="Hide Close Dialog"
|
||||
>
|
||||
<Toggle
|
||||
checked={() => settings().hide_close_prompt ?? true}
|
||||
|
|
@ -45,9 +45,9 @@ function SettingsGeneral() {
|
|||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title="Error Analytics"
|
||||
description="Sends errors and crash logs using Sentry to help developers fix issues. (// TODO)"
|
||||
icon={<AlertSquareIcon />}
|
||||
title="Error Analytics"
|
||||
>
|
||||
<Toggle
|
||||
checked={() => !(settings().disable_analytics ?? false)}
|
||||
|
|
@ -57,13 +57,13 @@ function SettingsGeneral() {
|
|||
|
||||
<SettingsRow.Header>Folders and Files</SettingsRow.Header>
|
||||
<SettingsRow
|
||||
title="Launcher Folder"
|
||||
description={settings().config_dir || 'Unknown'}
|
||||
icon={<FolderIcon />}
|
||||
title="Launcher Folder"
|
||||
>
|
||||
<Button
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
children="Open"
|
||||
iconLeft={<LinkExternal01Icon />}
|
||||
onClick={() => {
|
||||
if (settings().config_dir)
|
||||
open(settings().config_dir!);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { DurationFormat } from '@formatjs/intl-durationformat';
|
||||
import { open } from '@tauri-apps/plugin-shell';
|
||||
import type { Cluster, License, Loader, PackageType, Providers, VersionType } from '@onelauncher/client/bindings';
|
||||
import { DurationFormat } from '@formatjs/intl-durationformat';
|
||||
|
||||
export function supportsMods(loader?: Cluster | Loader): boolean {
|
||||
if (loader === undefined)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { listen } from '@tauri-apps/api/event';
|
||||
import { commands } from '@onelauncher/client/bindings';
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import process from 'node:process';
|
||||
import type { UserConfig } from 'vite';
|
||||
import { defineConfig, loadEnv } from 'vite';
|
||||
import { sentryVitePlugin as sentry } from '@sentry/vite-plugin';
|
||||
import unocss from 'unocss/vite';
|
||||
|
||||
import { defineConfig, loadEnv } from 'vite';
|
||||
import solid from 'vite-plugin-solid';
|
||||
import solidSvg from 'vite-plugin-solid-svg';
|
||||
import paths from 'vite-tsconfig-paths';
|
||||
import unocss from 'unocss/vite';
|
||||
import { sentryVitePlugin as sentry } from '@sentry/vite-plugin';
|
||||
import type { UserConfig } from 'vite';
|
||||
|
||||
export default defineConfig(async ({ mode }) => {
|
||||
process.env = { ...process.env, ...loadEnv(mode, process.cwd(), '') };
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ async fn main() -> Result<()> {
|
|||
&cluster.cluster_path(),
|
||||
&package_path,
|
||||
PackageType::Mod,
|
||||
).await?;
|
||||
)
|
||||
.await?;
|
||||
cluster::content::package::sync_packages_by_type(&cluster.cluster_path(), PackageType::Mod)
|
||||
.await?;
|
||||
|
||||
|
|
@ -83,7 +84,12 @@ async fn create_cluster() -> Result<Cluster> {
|
|||
Ok(cluster)
|
||||
}
|
||||
|
||||
async fn download_mod(cluster: &mut Cluster, pkg: &str, ver: &str, add: bool) -> Result<PackagePath> {
|
||||
async fn download_mod(
|
||||
cluster: &mut Cluster,
|
||||
pkg: &str,
|
||||
ver: &str,
|
||||
add: bool,
|
||||
) -> Result<PackagePath> {
|
||||
let package = Providers::Modrinth.get(pkg).await?;
|
||||
|
||||
let (package_path, package) = cluster::content::package::download_package(
|
||||
|
|
|
|||
|
|
@ -1,20 +1,24 @@
|
|||
use onelauncher::{data::PackageType, package::content, Result, State};
|
||||
use onelauncher::data::PackageType;
|
||||
use onelauncher::package::content;
|
||||
use onelauncher::{Result, State};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let _ = State::get().await?;
|
||||
|
||||
let provider = content::Providers::Modrinth;
|
||||
let results = provider.search(
|
||||
Some("chatting".to_string()),
|
||||
Some(5),
|
||||
Some(0),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Some(vec![PackageType::Mod]),
|
||||
None
|
||||
).await?;
|
||||
let results = provider
|
||||
.search(
|
||||
Some("chatting".to_string()),
|
||||
Some(5),
|
||||
Some(0),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Some(vec![PackageType::Mod]),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
println!("{:#?}", results);
|
||||
|
||||
|
|
|
|||
12
package.json
12
package.json
|
|
@ -57,20 +57,20 @@
|
|||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@flowr/eslint-config": "^4.0.0",
|
||||
"@types/node": "^22.5.1",
|
||||
"@flowr/eslint-config": "^4.1.0",
|
||||
"@types/node": "^22.5.4",
|
||||
"@unocss/eslint-plugin": "^0.62.3",
|
||||
"@vitest/ui": "^2.0.5",
|
||||
"bumpp": "^9.5.2",
|
||||
"eslint": "^9.9.1",
|
||||
"eslint-plugin-solid": "^0.14.2",
|
||||
"eslint": "^9.10.0",
|
||||
"eslint-plugin-solid": "^0.14.3",
|
||||
"jiti": "^1.21.6",
|
||||
"prisma": "^5.19.0",
|
||||
"prisma": "^5.19.1",
|
||||
"rimraf": "^6.0.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "^5.5.4",
|
||||
"vite": "^5.4.2",
|
||||
"vite": "^5.4.3",
|
||||
"vitest": "^2.0.5"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@solid-primitives/deep": "^0.2.9",
|
||||
"@tanstack/solid-query": "^5.53.1",
|
||||
"@tauri-apps/api": "=2.0.0-rc.1",
|
||||
"@tanstack/solid-query": "^5.55.2",
|
||||
"@tauri-apps/api": "=2.0.0-rc.4",
|
||||
"highlight.js": "^11.10.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
"plausible-tracker": "^0.3.9",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
export * from './usePlausible';
|
||||
export * from './useDebug';
|
||||
export * from './usePlausible';
|
||||
export * from './useQuery';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { createMutable } from 'solid-js/store';
|
||||
import { createEffect, createSignal } from 'solid-js';
|
||||
import { createMutable } from 'solid-js/store';
|
||||
import { createPersistedMutable, useSolidStore } from '../library';
|
||||
|
||||
export interface DebugState {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import type { PlausibleOptions as PlausibleTrackerOptions } from 'plausible-tracker';
|
||||
import Plausible from 'plausible-tracker';
|
||||
import { createEffect, createSignal } from 'solid-js';
|
||||
|
||||
import { createMutable } from 'solid-js/store';
|
||||
import { createEffect, createSignal } from 'solid-js';
|
||||
import { createPersistedMutable, useSolidStore } from '../library';
|
||||
import type { ProgramInfo } from '../types';
|
||||
import type { PlausibleOptions as PlausibleTrackerOptions } from 'plausible-tracker';
|
||||
import { PROGRAM_INFO } from '../bindings';
|
||||
import { createPersistedMutable, useSolidStore } from '../library';
|
||||
import { useDebugState } from './useDebug';
|
||||
import type { ProgramInfo } from '../types';
|
||||
|
||||
/**
|
||||
* Possible platform types for Plausible.
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ declare global {
|
|||
}
|
||||
|
||||
export * from './constants';
|
||||
export * from './library';
|
||||
export * from './hooks';
|
||||
export * from './utils';
|
||||
export * from './library';
|
||||
export type * from './types';
|
||||
export * from './utils';
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
export * from './createPersistedMutable';
|
||||
export * from './useSolidStore';
|
||||
export * from './useObserver';
|
||||
export * from './useSolidStore';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Owner } from 'solid-js';
|
||||
import { createEffect, createReaction, createRoot, createSignal, onCleanup, runWithOwner } from 'solid-js';
|
||||
import type { Owner } from 'solid-js';
|
||||
|
||||
export interface Observer {
|
||||
dispose: () => void;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import MarkdownIt, { type Options as MarkdownOptions } from 'markdown-it';
|
||||
import { FilterXSS, escapeAttrValue, safeAttrValue, whiteList } from 'xss';
|
||||
import { escapeAttrValue, FilterXSS, safeAttrValue, whiteList } from 'xss';
|
||||
|
||||
// from https://github.com/modrinth/code/blob/main/packages/utils/parse.ts for parsing modrinth style markdown
|
||||
export const configuredXss: FilterXSS = new FilterXSS({
|
||||
|
|
@ -73,7 +73,7 @@ export const configuredXss: FilterXSS = new FilterXSS({
|
|||
}
|
||||
}
|
||||
|
||||
if (name === 'class' && ['pre', 'code', 'span'].includes(tag)) {
|
||||
if (name === 'class' && ['code', 'pre', 'span'].includes(tag)) {
|
||||
const allowedClasses: string[] = [];
|
||||
for (const className of value.split(/\s/g))
|
||||
if (className.startsWith('hljs-') || className.startsWith('language-'))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type Accessor, type Setter, createSignal } from 'solid-js';
|
||||
import { type Accessor, createSignal, type Setter } from 'solid-js';
|
||||
|
||||
export type SortingFunction<T> = (a: T, b: T) => number;
|
||||
export type Sortables<T> = Record<string, SortingFunction<T>>;
|
||||
|
|
|
|||
|
|
@ -20,11 +20,13 @@ pub async fn find_managed_version(
|
|||
) -> Result<ManagedVersion> {
|
||||
let provider = package.provider.clone();
|
||||
|
||||
let versions = provider.get_all_versions(
|
||||
&package.id,
|
||||
game_version.as_ref().map(|v| vec![v.to_owned()]).to_owned(),
|
||||
loader.map(|l| vec![l]).clone(),
|
||||
).await?;
|
||||
let versions = provider
|
||||
.get_all_versions(
|
||||
&package.id,
|
||||
game_version.as_ref().map(|v| vec![v.to_owned()]).to_owned(),
|
||||
loader.map(|l| vec![l]).clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(versions
|
||||
.iter()
|
||||
|
|
@ -242,7 +244,9 @@ pub async fn sync_packages_by_type(
|
|||
.get_mut(cluster_path)
|
||||
.ok_or(anyhow::anyhow!("cluster not found in packages map"))?;
|
||||
|
||||
manager.sync_packages_by_type(&state.directories, package_type).await?;
|
||||
manager
|
||||
.sync_packages_by_type(&state.directories, package_type)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,10 +138,11 @@ impl Providers {
|
|||
.collect())
|
||||
}
|
||||
|
||||
pub async fn get_all_versions(&self,
|
||||
pub async fn get_all_versions(
|
||||
&self,
|
||||
project_id: &str,
|
||||
game_versions: Option<Vec<String>>,
|
||||
loaders: Option<Vec<Loader>>
|
||||
loaders: Option<Vec<Loader>>,
|
||||
) -> Result<Vec<ManagedVersion>> {
|
||||
Ok(match self {
|
||||
Providers::Modrinth => modrinth::get_all_versions(project_id, game_versions, loaders),
|
||||
|
|
|
|||
|
|
@ -290,7 +290,14 @@ pub async fn get(id: &str) -> Result<ModrinthPackage> {
|
|||
pub async fn get_multiple(ids: &[String]) -> Result<Vec<ModrinthPackage>> {
|
||||
Ok(serde_json::from_slice(
|
||||
&fetch(
|
||||
format_url!("/projects?ids=[{}]", ids.iter().map(|id| format!("\"{}\"", id)).collect::<Vec<String>>().join(",")).as_str(),
|
||||
format_url!(
|
||||
"/projects?ids=[{}]",
|
||||
ids.iter()
|
||||
.map(|id| format!("\"{}\"", id))
|
||||
.collect::<Vec<String>>()
|
||||
.join(",")
|
||||
)
|
||||
.as_str(),
|
||||
None,
|
||||
&State::get().await?.fetch_semaphore,
|
||||
)
|
||||
|
|
@ -445,20 +452,34 @@ pub async fn get_all_versions(
|
|||
) -> Result<Vec<ModrinthVersion>> {
|
||||
let mut url = url::Url::parse(format_url!("/project/{}/version", project_id).as_str())?;
|
||||
if let Some(game_versions) = game_versions {
|
||||
url.query_pairs_mut()
|
||||
.append_pair("game_versions", &game_versions.iter().map(|v| format!("\"{}\"", v.to_string())).collect::<Vec<String>>().join(","));
|
||||
url.query_pairs_mut().append_pair(
|
||||
"game_versions",
|
||||
&game_versions
|
||||
.iter()
|
||||
.map(|v| format!("\"{}\"", v.to_string()))
|
||||
.collect::<Vec<String>>()
|
||||
.join(","),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(loaders) = loaders {
|
||||
url.query_pairs_mut()
|
||||
.append_pair("loaders", format!("[{}]", &loaders.iter().map(|l| format!("\"{}\"", l.to_string())).collect::<Vec<String>>().join(",")).as_str());
|
||||
url.query_pairs_mut().append_pair(
|
||||
"loaders",
|
||||
format!(
|
||||
"[{}]",
|
||||
&loaders
|
||||
.iter()
|
||||
.map(|l| format!("\"{}\"", l.to_string()))
|
||||
.collect::<Vec<String>>()
|
||||
.join(",")
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(serde_json::from_slice(
|
||||
&fetch(
|
||||
format_url!(
|
||||
"/project/{}/version",
|
||||
project_id).as_str(),
|
||||
format_url!("/project/{}/version", project_id).as_str(),
|
||||
None,
|
||||
&State::get().await?.fetch_semaphore,
|
||||
)
|
||||
|
|
@ -469,7 +490,15 @@ pub async fn get_all_versions(
|
|||
pub async fn get_versions(versions: Vec<String>) -> Result<Vec<ModrinthVersion>> {
|
||||
Ok(serde_json::from_slice(
|
||||
&fetch(
|
||||
format_url!("/versions?ids=[{}]", versions.iter().map(|v| format!("\"{}\"", v)).collect::<Vec<String>>().join(",")).as_str(),
|
||||
format_url!(
|
||||
"/versions?ids=[{}]",
|
||||
versions
|
||||
.iter()
|
||||
.map(|v| format!("\"{}\"", v))
|
||||
.collect::<Vec<String>>()
|
||||
.join(",")
|
||||
)
|
||||
.as_str(),
|
||||
None,
|
||||
&State::get().await?.fetch_semaphore,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -354,7 +354,13 @@ impl PackageManager {
|
|||
package_path: &PackagePath,
|
||||
package_type: PackageType,
|
||||
) -> crate::Result<()> {
|
||||
let full_path = self.cluster_path.clone().full_path().await?.join(package_type.get_folder()).join(package_path.0.clone());
|
||||
let full_path = self
|
||||
.cluster_path
|
||||
.clone()
|
||||
.full_path()
|
||||
.await?
|
||||
.join(package_type.get_folder())
|
||||
.join(package_path.0.clone());
|
||||
io::remove_file(full_path).await?;
|
||||
|
||||
let packages = &mut self.get_mut(package_type).packages;
|
||||
|
|
@ -441,7 +447,8 @@ impl PackageManager {
|
|||
|
||||
while let Some(file) = files.next_entry().await? {
|
||||
// Skip .packages.json meta file
|
||||
if file.file_name()
|
||||
if file
|
||||
.file_name()
|
||||
.to_string_lossy()
|
||||
.eq(&package_type.get_meta_file_name())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import fs from 'node:fs';
|
||||
import { readFile, writeFile } from 'node:fs/promises';
|
||||
import { join, resolve } from 'pathe';
|
||||
import mustache from 'mustache';
|
||||
import { consola } from 'consola';
|
||||
import mustache from 'mustache';
|
||||
import { join, resolve } from 'pathe';
|
||||
import { checkEnvironment, which } from './utils';
|
||||
import { getTriple } from './utils/triple';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import process from 'node:process';
|
||||
import fs from 'node:fs/promises';
|
||||
import process from 'node:process';
|
||||
import { setTimeout } from 'node:timers/promises';
|
||||
import pathe from 'pathe';
|
||||
import { execa } from 'execa';
|
||||
import { consola } from 'consola';
|
||||
import { execa } from 'execa';
|
||||
import pathe from 'pathe';
|
||||
import { awaitLock, checkEnvironment } from './utils';
|
||||
import { patchTauri } from './utils/patch';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import process from 'node:process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { setTimeout } from 'node:timers/promises';
|
||||
|
||||
import { type } from 'node:os';
|
||||
import fs from 'node:fs/promises';
|
||||
import { dirname, join, resolve } from 'pathe';
|
||||
import { execa } from 'execa';
|
||||
import { type } from 'node:os';
|
||||
import process from 'node:process';
|
||||
|
||||
import { setTimeout } from 'node:timers/promises';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { consola } from 'consola';
|
||||
import { execa } from 'execa';
|
||||
import { dirname, join, resolve } from 'pathe';
|
||||
|
||||
export type CheckedEnvironment = ReturnType<typeof checkEnvironment>;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import process from 'node:process';
|
||||
import { existsSync, readFileSync } from 'node:fs';
|
||||
import fs from 'node:fs/promises';
|
||||
import { type } from 'node:os';
|
||||
import { existsSync, readFileSync } from 'node:fs';
|
||||
import { join, resolve } from 'pathe';
|
||||
import { execa } from 'execa';
|
||||
import semver from 'semver';
|
||||
import process from 'node:process';
|
||||
import { consola } from 'consola';
|
||||
import { execa } from 'execa';
|
||||
import { join, resolve } from 'pathe';
|
||||
import semver from 'semver';
|
||||
import type { CheckedEnvironment } from '.';
|
||||
|
||||
const UPDATEKEY_LOCK_VERSION = '1';
|
||||
|
|
@ -53,7 +53,7 @@ export async function tauriUpdateKey(env: CheckedEnvironment): Promise<string |
|
|||
}
|
||||
|
||||
export async function patchTauri(env: CheckedEnvironment, targets: string[], args: string[]): Promise<string[]> {
|
||||
if (args.findIndex(a => ['-c', '--config'].includes(a)) !== -1)
|
||||
if (args.findIndex(a => ['--config', '-c'].includes(a)) !== -1)
|
||||
throw new Error('custom tauri build configuration is not supported!');
|
||||
|
||||
const osType = type();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { env } from 'node:process';
|
||||
import { machine, type } from 'node:os';
|
||||
import { execaCommand } from 'execa';
|
||||
import { env } from 'node:process';
|
||||
import { consola } from 'consola';
|
||||
import { execaCommand } from 'execa';
|
||||
|
||||
const state: { __debug: boolean; libc: 'musl' | 'glibc' } = {
|
||||
__debug: env.NODE_ENV === 'debug',
|
||||
|
|
|
|||
1067
pnpm-lock.yaml
generated
1067
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue