diff --git a/Cargo.lock b/Cargo.lock index 11d3abcc..bd59fa95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -971,6 +971,26 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "const_format" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -1275,7 +1295,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2041,6 +2061,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "git2" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fda788993cc341f69012feba8bf45c0ba4f3291fcc08e214b4d5a7332d88aff" +dependencies = [ + "bitflags 2.6.0", + "libc", + "libgit2-sys", + "log", + "url", +] + [[package]] name = "glib" version = "0.18.5" @@ -2561,6 +2594,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "is_debug" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fe266d2e243c931d8190177f20bf7f24eed45e96f39e87dc49a27b32d12d407" + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -2742,6 +2781,18 @@ version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +[[package]] +name = "libgit2-sys" +version = "0.18.3+1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9b3acc4b91781bb0b3386669d325163746af5f6e4f73e6d2d630e09a35f3487" +dependencies = [ + "cc", + "libc", + "libz-sys", + "pkg-config", +] + [[package]] name = "libloading" version = "0.7.4" @@ -2800,6 +2851,18 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libz-sys" +version = "1.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -3176,6 +3239,15 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "number_prefix" version = "0.4.0" @@ -3527,6 +3599,7 @@ dependencies = [ "serde_with", "sha1", "sha2", + "shadow-rs", "specta", "sysinfo", "tauri", @@ -5262,6 +5335,19 @@ dependencies = [ "digest", ] +[[package]] +name = "shadow-rs" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d18183cef626bce22836103349c7050d73db799be0171386b80947d157ae32" +dependencies = [ + "const_format", + "git2", + "is_debug", + "time", + "tzdb", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -6504,7 +6590,9 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa 1.0.11", + "libc", "num-conv", + "num_threads", "powerfmt", "serde", "time-core", @@ -6830,6 +6918,32 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "tz-rs" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14eff19b8dc1ace5bf7e4d920b2628ae3837f422ff42210cb1567cbf68b5accf" + +[[package]] +name = "tzdb" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0be2ea5956f295449f47c0b825c5e109022ff1a6a53bb4f77682a87c2341fbf5" +dependencies = [ + "iana-time-zone", + "tz-rs", + "tzdb_data", +] + +[[package]] +name = "tzdb_data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c4c81d75033770e40fbd3643ce7472a1a9fd301f90b7139038228daf8af03ec" +dependencies = [ + "tz-rs", +] + [[package]] name = "uds_windows" version = "1.1.0" @@ -6930,6 +7044,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index fb99741e..ac04216b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -173,6 +173,7 @@ sysinfo = { version = "=0.34.2", features = [ "serde" ] } thiserror = { version = "2" } whoami = { version = "=1.6.0" } opener = { version = "=0.8.2" } +shadow-rs = { version = "1.4.0", default-features = false } # macro paste = { version = "1" } diff --git a/apps/oneclient/desktop/build.rs b/apps/oneclient/desktop/build.rs index 9f7658d7..106b7123 100644 --- a/apps/oneclient/desktop/build.rs +++ b/apps/oneclient/desktop/build.rs @@ -1,20 +1,3 @@ -use std::process::Command; -use std::time::{SystemTime, UNIX_EPOCH}; - fn main() { - let output = Command::new("git") - .args(&["rev-parse", "HEAD"]) - .output() - .unwrap(); - let git_hash = String::from_utf8(output.stdout).unwrap(); - println!("cargo:rustc-env=GIT_HASH={}", git_hash); - - let start = SystemTime::now(); - let timestamp = start - .duration_since(UNIX_EPOCH) - .expect("Time went backwards") - .as_secs(); - println!("cargo:rustc-env=BUILD_TIMESTAMP={}", timestamp); - tauri_build::build(); } diff --git a/apps/oneclient/desktop/capabilities/default.json b/apps/oneclient/desktop/capabilities/default.json index 97bca373..79db1d31 100644 --- a/apps/oneclient/desktop/capabilities/default.json +++ b/apps/oneclient/desktop/capabilities/default.json @@ -38,6 +38,13 @@ "fs:allow-data-read-recursive", "fs:allow-data-write-recursive", - "os:default" + "os:allow-arch", + "os:deny-exe-extension", + "os:allow-family", + "os:deny-hostname", + "os:allow-locale", + "os:allow-os-type", + "os:allow-platform", + "os:allow-version" ] } diff --git a/apps/oneclient/desktop/src/constants.rs b/apps/oneclient/desktop/src/constants.rs index 8a278c20..75cec7c2 100644 --- a/apps/oneclient/desktop/src/constants.rs +++ b/apps/oneclient/desktop/src/constants.rs @@ -1,7 +1,7 @@ // === API === pub const CURSEFORGE_API_KEY: &'static str = "$2a$10$6utA1UNSmFPrE/Lh7b7ndeeGmiOkjKNY8kpFB0fsmE/d42ZAfFgCe"; -pub const DISCORD_CLIENT_ID: &'static str = "1274084193193955408"; +pub const DISCORD_CLIENT_ID: &'static str = "1426999264633946334"; // === Meta === // Cannot contain trailing slash diff --git a/apps/oneclient/desktop/src/lib.rs b/apps/oneclient/desktop/src/lib.rs index 3f329ac2..399747f1 100644 --- a/apps/oneclient/desktop/src/lib.rs +++ b/apps/oneclient/desktop/src/lib.rs @@ -33,7 +33,7 @@ async fn initialize_core() -> LauncherResult<()> { launcher_name: "OneClient".to_string(), launcher_version: env!("CARGO_PKG_VERSION").to_string(), launcher_website: "https://polyfrost.org/".to_string(), - discord_client_id: None, //Some(constants::DISCORD_CLIENT_ID.to_string()), // disabled for now + discord_client_id: Some(constants::DISCORD_CLIENT_ID.to_string()), fetch_attempts: 3, logger_filter: Some(format!( "{}={level},onelauncher_core={level}", diff --git a/apps/oneclient/frontend/src/bindings.gen.ts b/apps/oneclient/frontend/src/bindings.gen.ts index 6583fad1..2ffe3630 100644 --- a/apps/oneclient/frontend/src/bindings.gen.ts +++ b/apps/oneclient/frontend/src/bindings.gen.ts @@ -301,22 +301,10 @@ export type VersionType = */ "old_beta" -const ARGS_MAP = { 'debug':'{"getFamily":[],"getPlatform":[],"getCommitHash":[],"getArch":[],"openDevTools":[],"getVersion":[],"isInDev":[],"getType":[],"getLocale":[],"getBuildTimestamp":[]}', 'oneclient':'{"getVersions":[],"getClustersGroupedByMajor":[],"getBundlesFor":["cluster_id"]}', 'core':'{"getPackageBody":["provider","body"],"createSettingsProfile":["name"],"getProfileOrDefault":["name"],"setDefaultUser":["uuid"],"getUsersFromAuthor":["provider","author"],"removeCluster":["id"],"writeSettings":["setting"],"getUser":["uuid"],"readSettings":[],"uploadSkinBytes":["access_token","skin_data","image_format","skin_variant"],"updateClusterProfile":["name","profile"],"convertUsernameUUID":["username_uuid"],"open":["input"],"getRunningProcesses":[],"installModpack":["modpack","cluster_id"],"searchPackages":["provider","query"],"changeSkin":["access_token","skin_url","skin_variant"],"launchCluster":["id","uuid"],"changeCape":["access_token","cape_uuid"],"getGlobalProfile":[],"getClusters":[],"getWorlds":["id"],"getMultiplePackages":["provider","slugs"],"removeUser":["uuid"],"removeCape":["access_token"],"getUsers":[],"getPackage":["provider","slug"],"downloadExternalPackage":["package","cluster_id","force","skip_compatibility"],"getRunningProcessesByClusterId":["cluster_id"],"fetchMinecraftProfile":["uuid"],"getClusterById":["id"],"getGameVersions":[],"getDefaultUser":["fallback"],"getLogs":["id"],"getLogByName":["id","name"],"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"],"getLoadersForVersion":["mc_version"],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"],"fetchLoggedInProfile":["access_token"],"openMsaLogin":[],"getScreenshots":["id"],"isClusterRunning":["cluster_id"],"killProcess":["pid"],"createCluster":["options"],"updateClusterById":["id","request"]}', 'events':'{"process":["event"],"message":["event"],"ingress":["event"]}', 'folders':'{"openCluster":["folder_name"],"fromCluster":["folder_name"]}' } +const ARGS_MAP = { 'debug':'{"getType":[],"getGitCommitHash":[],"getBuildTimestamp":[],"getPlatform":[],"getOsVersion":[],"getArch":[],"getPackageVersion":[],"openDevTools":[],"getFamily":[],"isInDev":[],"getLocale":[]}', 'oneclient':'{"getClustersGroupedByMajor":[],"getVersions":[],"getBundlesFor":["cluster_id"]}', 'events':'{"message":["event"],"process":["event"],"ingress":["event"]}', 'core':'{"getScreenshots":["id"],"getPackageBody":["provider","body"],"convertUsernameUUID":["username_uuid"],"writeSettings":["setting"],"createCluster":["options"],"createSettingsProfile":["name"],"getMultiplePackages":["provider","slugs"],"updateClusterProfile":["name","profile"],"downloadExternalPackage":["package","cluster_id","force","skip_compatibility"],"openMsaLogin":[],"getClusters":[],"installModpack":["modpack","cluster_id"],"fetchMinecraftProfile":["uuid"],"killProcess":["pid"],"getUsers":[],"searchPackages":["provider","query"],"readSettings":[],"getLoadersForVersion":["mc_version"],"getRunningProcessesByClusterId":["cluster_id"],"getProfileOrDefault":["name"],"uploadSkinBytes":["access_token","skin_data","image_format","skin_variant"],"getUser":["uuid"],"getRunningProcesses":[],"fetchLoggedInProfile":["access_token"],"getLogs":["id"],"isClusterRunning":["cluster_id"],"getWorlds":["id"],"removeCape":["access_token"],"updateClusterById":["id","request"],"getGameVersions":[],"launchCluster":["id","uuid"],"removeCluster":["id"],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"],"getLinkedPackages":["cluster_id"],"getClusterById":["id"],"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"],"removeUser":["uuid"],"changeSkin":["access_token","skin_url","skin_variant"],"getUsersFromAuthor":["provider","author"],"getGlobalProfile":[],"changeCape":["access_token","cape_uuid"],"getLogByName":["id","name"],"getDefaultUser":["fallback"],"setDiscordRPCMessage":["message"],"getPackage":["provider","slug"],"open":["input"],"setDefaultUser":["uuid"]}', 'folders':'{"openCluster":["folder_name"],"fromCluster":["folder_name"]}' } export type Router = { 'events': { ingress: (event: IngressPayload) => Promise, message: (event: MessagePayload) => Promise, process: (event: ProcessPayload) => Promise }, -'folders': { fromCluster: (folderName: string) => Promise, -openCluster: (folderName: string) => Promise }, -'debug': { openDevTools: () => Promise, -isInDev: () => Promise, -getPlatform: () => Promise, -getArch: () => Promise, -getFamily: () => Promise, -getLocale: () => Promise, -getType: () => Promise, -getVersion: () => Promise, -getCommitHash: () => Promise, -getBuildTimestamp: () => Promise }, 'oneclient': { getClustersGroupedByMajor: () => Promise>, getBundlesFor: (clusterId: number) => Promise, getVersions: () => Promise }, @@ -356,6 +344,7 @@ getPackageVersions: (provider: Provider, slug: string, mcVersion: string | null, downloadPackage: (provider: Provider, packageId: string, versionId: string, clusterId: number, skipCompatibility: boolean | null) => Promise, downloadExternalPackage: (package: ExternalPackage, clusterId: number, force: boolean | null, skipCompatibility: boolean | null) => Promise, getUsersFromAuthor: (provider: Provider, author: PackageAuthor) => Promise, +getLinkedPackages: (clusterId: number) => Promise, installModpack: (modpack: ModpackArchive, clusterId: number) => Promise, fetchMinecraftProfile: (uuid: string) => Promise, fetchLoggedInProfile: (accessToken: string) => Promise, @@ -364,7 +353,21 @@ changeSkin: (accessToken: string, skinUrl: string, skinVariant: SkinVariant) => changeCape: (accessToken: string, capeUuid: string) => Promise, removeCape: (accessToken: string) => Promise, convertUsernameUUID: (usernameUuid: string) => Promise, -open: (input: string) => Promise } }; +setDiscordRPCMessage: (message: string) => Promise, +open: (input: string) => Promise }, +'debug': { openDevTools: () => Promise, +isInDev: () => Promise, +getArch: () => Promise, +getFamily: () => Promise, +getLocale: () => Promise, +getType: () => Promise, +getPlatform: () => Promise, +getOsVersion: () => Promise, +getGitCommitHash: () => Promise, +getBuildTimestamp: () => Promise, +getPackageVersion: () => Promise }, +'folders': { fromCluster: (folderName: string) => Promise, +openCluster: (folderName: string) => Promise } }; export type { InferCommandOutput } diff --git a/apps/oneclient/frontend/src/components/Bundle/Bundle.tsx b/apps/oneclient/frontend/src/components/Bundle/Bundle.tsx index 3fe522a2..d076496f 100644 --- a/apps/oneclient/frontend/src/components/Bundle/Bundle.tsx +++ b/apps/oneclient/frontend/src/components/Bundle/Bundle.tsx @@ -1,8 +1,8 @@ import type { ClusterModel, ModpackFile } from '@/bindings.gen'; +import { ModCard, useModCardContext } from '@/components'; import { useSettings } from '@/hooks/useSettings'; import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'; import { twMerge } from 'tailwind-merge'; -import { ModCard, useModCardContext } from '.'; interface BundleProps { files: Array; diff --git a/apps/oneclient/frontend/src/components/Bundle/ModCard.tsx b/apps/oneclient/frontend/src/components/Bundle/ModCard.tsx index 7230488e..f8d628f5 100644 --- a/apps/oneclient/frontend/src/components/Bundle/ModCard.tsx +++ b/apps/oneclient/frontend/src/components/Bundle/ModCard.tsx @@ -1,10 +1,10 @@ import type { ClusterModel, ModpackFile, ModpackFileKind } from '@/bindings.gen'; import MissingLogo from '@/assets/misc/missingLogo.svg'; +import { DownloadModButton, ModTag } from '@/components'; import { useSettings } from '@/hooks/useSettings'; import { bindings } from '@/main'; import { createContext, useContext, useEffect, useState } from 'react'; import { twMerge } from 'tailwind-merge'; -import { DownloadModButton, ModTag } from '.'; export interface ModInfo { name: string; diff --git a/apps/oneclient/frontend/src/components/Bundle/ModList.tsx b/apps/oneclient/frontend/src/components/Bundle/ModList.tsx index f78b7efe..56b23aae 100644 --- a/apps/oneclient/frontend/src/components/Bundle/ModList.tsx +++ b/apps/oneclient/frontend/src/components/Bundle/ModList.tsx @@ -1,7 +1,7 @@ import type { ClusterModel, ModpackArchive } from '@/bindings.gen'; +import { Bundle, useModCardContext } from '@/components'; import { useSettings } from '@/hooks/useSettings'; import { Button, Tab, TabContent, TabList, TabPanel, Tabs } from '@onelauncher/common/components'; -import { Bundle, useModCardContext } from '.'; function getBundleName(name: string): string { return (name.match(/\[(.*?)\]/)?.[1]) ?? 'Loading...'; diff --git a/apps/oneclient/frontend/src/components/Bundle/ModTag.tsx b/apps/oneclient/frontend/src/components/Bundle/ModTag.tsx index fe2a5be7..1f17496e 100644 --- a/apps/oneclient/frontend/src/components/Bundle/ModTag.tsx +++ b/apps/oneclient/frontend/src/components/Bundle/ModTag.tsx @@ -1,5 +1,5 @@ import type { ClusterModel } from '@/bindings.gen'; -import type { ModInfo } from '.'; +import type { ModInfo } from '@/components'; import { useSettings } from '@/hooks/useSettings'; import { Link } from '@tanstack/react-router'; import { twMerge } from 'tailwind-merge'; diff --git a/apps/oneclient/frontend/src/components/DeleteAccountButton.tsx b/apps/oneclient/frontend/src/components/DeleteAccountButton.tsx index 7aace1e0..c21e0a13 100644 --- a/apps/oneclient/frontend/src/components/DeleteAccountButton.tsx +++ b/apps/oneclient/frontend/src/components/DeleteAccountButton.tsx @@ -1,12 +1,11 @@ import type { MinecraftCredentials } from '@/bindings.gen'; +import { Overlay, RemoveAccountModal } from '@/components'; import { Button } from '@onelauncher/common/components'; import { Trash01Icon } from '@untitled-theme/icons-react'; -import { DialogTrigger } from 'react-aria-components'; -import { Overlay, RemoveAccountModal } from './overlay'; export function DeleteAccountButton({ profile, onPress }: { profile: MinecraftCredentials; onPress: () => void }) { return ( - + @@ -14,6 +13,6 @@ export function DeleteAccountButton({ profile, onPress }: { profile: MinecraftCr - + ); } diff --git a/apps/oneclient/frontend/src/components/DownloadMods.tsx b/apps/oneclient/frontend/src/components/DownloadMods.tsx index a8145e14..ac6ae984 100644 --- a/apps/oneclient/frontend/src/components/DownloadMods.tsx +++ b/apps/oneclient/frontend/src/components/DownloadMods.tsx @@ -1,4 +1,5 @@ import type { ExternalPackage, ManagedVersionDependency, ModpackFile, Provider } from '@/bindings.gen'; +import { getModMetaDataName, Overlay } from '@/components'; import { useSettings } from '@/hooks/useSettings'; import { bindings } from '@/main'; import { useCommandMut } from '@onelauncher/common'; @@ -6,8 +7,6 @@ import { Button } from '@onelauncher/common/components'; import { useNavigate } from '@tanstack/react-router'; import { useEffect, useImperativeHandle, useState } from 'react'; import { DialogTrigger } from 'react-aria-components'; -import { getModMetaDataName } from './Bundle'; -import { Overlay } from './overlay'; export interface DownloadModsRef { openDownloadDialog: (nextPath?: string) => void; diff --git a/apps/oneclient/frontend/src/components/ExternalLink.tsx b/apps/oneclient/frontend/src/components/ExternalLink.tsx index 3f81d7cb..ae5dd23c 100644 --- a/apps/oneclient/frontend/src/components/ExternalLink.tsx +++ b/apps/oneclient/frontend/src/components/ExternalLink.tsx @@ -1,11 +1,11 @@ import type React from 'react'; import type { HTMLProps } from 'react'; +import { Overlay } from '@/components'; import { bindings } from '@/main'; import { writeText } from '@tauri-apps/plugin-clipboard-manager'; import { LinkExternal01Icon } from '@untitled-theme/icons-react'; import { useState } from 'react'; import { twMerge } from 'tailwind-merge'; -import { Overlay } from './overlay'; export interface ExternalLinkProps extends HTMLProps { href?: string | undefined; diff --git a/apps/oneclient/frontend/src/components/LaunchButton.tsx b/apps/oneclient/frontend/src/components/LaunchButton.tsx index 0129d552..e064d23b 100644 --- a/apps/oneclient/frontend/src/components/LaunchButton.tsx +++ b/apps/oneclient/frontend/src/components/LaunchButton.tsx @@ -1,16 +1,17 @@ +import type { ClusterModel } from '@/bindings.gen'; import type { ButtonProps } from '@onelauncher/common/components'; +import { KillMinecraft, NoAccountPopup, Overlay } from '@/components'; import { useIsRunning } from '@/hooks/useClusters'; import { useLaunchCluster } from '@/hooks/useLaunchCluster'; import { bindings } from '@/main'; import { useCommandSuspense } from '@onelauncher/common'; import { Button } from '@onelauncher/common/components'; +import { useNavigate } from '@tanstack/react-router'; import { useState } from 'react'; -import { DialogTrigger } from 'react-aria-components'; import { tv } from 'tailwind-variants'; -import { NoAccountPopup, Overlay } from './overlay'; export type LaunchButtonProps = Omit & { - clusterId: number | undefined | null; + cluster: ClusterModel; }; const launchButtonVariants = tv({ @@ -21,32 +22,73 @@ const launchButtonVariants = tv({ }, }); +function PromptForOnboarding({ launch, setSkipPackagesCheck, cluster }: { launch: () => void; setSkipPackagesCheck: React.Dispatch>; cluster: ClusterModel }) { + const navigate = useNavigate(); + const onClickYes = () => { + localStorage.setItem('selectedClusters', JSON.stringify([{ mc_version: cluster.mc_version, mc_loader: cluster.mc_loader }])); + navigate({ to: `/onboarding/preferences/versionCategory` }); + }; + + const onClickLaunch = () => { + setSkipPackagesCheck(true); + launch(); + }; + + return ( + + Not Setup +
+

It seems like you haven't setup this version

+

Do you want to setup this version?

+
+ +
+ ); +} + export function LaunchButton({ - clusterId, + cluster, isDisabled, className, ...rest }: LaunchButtonProps) { const { data: currentAccount } = useCommandSuspense(['getDefaultUser'], () => bindings.core.getDefaultUser(true)); - const launchCluster = useLaunchCluster(clusterId); - const isRunning = useIsRunning(clusterId); - const [open, setOpen] = useState(false); + const { data: installedPackages } = useCommandSuspense(['getLinkedPackages', cluster.id], () => bindings.core.getLinkedPackages(cluster.id)); + const launchCluster = useLaunchCluster(cluster.id); + const isRunning = useIsRunning(cluster.id); + + const [reason, setReason] = useState<'account' | 'packages' | 'kill' | null>(null); + const [skipPackagesCheck, setSkipPackagesCheck] = useState(false); const launch = () => { - if (currentAccount === null) { - setOpen(true); - } - else { - launchCluster(); - setOpen(false); - } + if (isRunning) + return setReason('kill'); + if (!currentAccount) + return setReason('account'); + if (installedPackages.length === 0 && !skipPackagesCheck) + return setReason('packages'); + + launchCluster(); + setSkipPackagesCheck(false); + setReason(null); }; return ( - + !open && setReason(null)}> - + {reason === 'kill' && setReason(null)} />} + {reason === 'packages' && } + {reason === 'account' && } - + ); } diff --git a/apps/oneclient/frontend/src/components/Loader.tsx b/apps/oneclient/frontend/src/components/Loader.tsx index 5c273593..2d32295b 100644 --- a/apps/oneclient/frontend/src/components/Loader.tsx +++ b/apps/oneclient/frontend/src/components/Loader.tsx @@ -1,9 +1,9 @@ +import type { SpinnerProps } from '@/components'; import type { HTMLAttributes, ReactNode } from 'react'; -import type { SpinnerProps } from './Spinner'; +import { Spinner } from '@/components'; import { motion } from 'motion/react'; import { Suspense } from 'react'; import { twMerge } from 'tailwind-merge'; -import { Spinner } from './Spinner'; interface LoaderProps extends HTMLAttributes { children?: ReactNode; diff --git a/apps/oneclient/frontend/src/components/Markdown.tsx b/apps/oneclient/frontend/src/components/Markdown.tsx index 6b598756..cefbea63 100644 --- a/apps/oneclient/frontend/src/components/Markdown.tsx +++ b/apps/oneclient/frontend/src/components/Markdown.tsx @@ -1,8 +1,8 @@ +import { ExternalLink } from '@/components'; import ReactMarkdown from 'react-markdown'; import rehypeRaw from 'rehype-raw'; import remarkGfm from 'remark-gfm'; import { twMerge } from 'tailwind-merge'; -import { ExternalLink } from './ExternalLink'; import styles from './Markdown.module.css'; export function Markdown({ diff --git a/apps/oneclient/frontend/src/components/Navbar.tsx b/apps/oneclient/frontend/src/components/Navbar.tsx index 607f98f0..2ff3a787 100644 --- a/apps/oneclient/frontend/src/components/Navbar.tsx +++ b/apps/oneclient/frontend/src/components/Navbar.tsx @@ -1,6 +1,7 @@ import type { ButtonProps } from '@onelauncher/common/components'; import type { LinkProps, RegisteredRouter } from '@tanstack/react-router'; import LauncherLogo from '@/assets/logos/oneclient.svg?react'; +import { AccountAvatar, AccountPopup, Overlay, SuperSecretDevOptions } from '@/components'; import { bindings } from '@/main'; import { useCommand } from '@onelauncher/common'; import { Button, Popup } from '@onelauncher/common/components'; @@ -8,9 +9,6 @@ import { Link, useNavigate } from '@tanstack/react-router'; import { Window } from '@tauri-apps/api/window'; import { MinusIcon, Settings02Icon, SquareIcon, XCloseIcon } from '@untitled-theme/icons-react'; import { twMerge } from 'tailwind-merge'; -import { AccountAvatar } from './AccountAvatar'; -import { Overlay, SuperSecretDevOptions } from './overlay'; -import { AccountPopup } from './overlay/AccountPopup'; export function Navbar() { const { data: currentAccount } = useCommand(['getDefaultUser'], () => bindings.core.getDefaultUser(true)); diff --git a/apps/oneclient/frontend/src/components/SettingSwitch.tsx b/apps/oneclient/frontend/src/components/SettingSwitch.tsx index 7c3c82e1..5d4c22c7 100644 --- a/apps/oneclient/frontend/src/components/SettingSwitch.tsx +++ b/apps/oneclient/frontend/src/components/SettingSwitch.tsx @@ -5,7 +5,7 @@ type BooleanSetting = [ (value: boolean) => void, ]; -export default function SettingsSwitch({ setting }: { setting: BooleanSetting }) { +export function SettingsSwitch({ setting }: { setting: BooleanSetting }) { return ( ); -function GoBackButton() { +export function GoBackButton() { const router = useRouter(); const canGoBack = useCanGoBack(); diff --git a/apps/oneclient/frontend/src/components/Stepper.tsx b/apps/oneclient/frontend/src/components/Stepper.tsx index 68e04bab..05ddd090 100644 --- a/apps/oneclient/frontend/src/components/Stepper.tsx +++ b/apps/oneclient/frontend/src/components/Stepper.tsx @@ -11,7 +11,7 @@ export function Stepper({ steps, currentStepIndex }: VerticalStepperProps) {
{steps.map((step, index) => (
{defaultUser.data && ( -
- { }} - onDelete={() => deleteUser(defaultUser.data as MinecraftCredentials)} - user={defaultUser.data} - /> -
+ { }} + onDelete={() => deleteUser(defaultUser.data as MinecraftCredentials)} + user={defaultUser.data} + /> )} {users.data?.filter(user => user.id !== defaultUser.data?.id).map(user => ( -
- setDefaultUser(user)} - onDelete={() => deleteUser(user)} - user={user} - /> -
+ setDefaultUser(user)} + onDelete={() => deleteUser(user)} + user={user} + /> ))}
-
+ + - - + + + + - - - - -
-
- - - -
+ + +
@@ -89,23 +76,9 @@ export function AccountPopup() { export default AccountPopup; -function AccountEntry({ - onClick, - onDelete, - user, - loggedIn = false, -}: { - onClick: () => void; - onDelete: () => void; - user: MinecraftCredentials; - loggedIn?: boolean; -}) { +function AccountEntry({ onClick, onDelete, user, loggedIn = false }: { onClick: () => void; onDelete: () => void; user: MinecraftCredentials; loggedIn?: boolean }) { return ( - - - ) - : ( - - )} - + profile + ? ( + <> + + + + ) + : ); } -function AccountRow({ - profile, -}: { - profile: MinecraftCredentials; -}) { +function AccountRow({ profile }: { profile: MinecraftCredentials }) { return (
diff --git a/apps/oneclient/frontend/src/components/overlay/BundleModListModal.tsx b/apps/oneclient/frontend/src/components/overlay/BundleModListModal.tsx index e1aac7bc..29d79ce4 100644 --- a/apps/oneclient/frontend/src/components/overlay/BundleModListModal.tsx +++ b/apps/oneclient/frontend/src/components/overlay/BundleModListModal.tsx @@ -1,9 +1,8 @@ +import { ModList, Overlay, useModCardContext } from '@/components'; import { bindings } from '@/main'; import { useCommandSuspense } from '@onelauncher/common'; import { Button } from '@onelauncher/common/components'; import { useState } from 'react'; -import { ModList, useModCardContext } from '../Bundle'; -import { Overlay } from './Overlay'; export function BundleModListModal({ clusterId, name }: { clusterId: number; name: string }) { const { data: cluster } = useCommandSuspense(['getClusterById'], () => bindings.core.getClusterById(clusterId)); diff --git a/apps/oneclient/frontend/src/components/overlay/DebugInfo.tsx b/apps/oneclient/frontend/src/components/overlay/DebugInfo.tsx index 4d940ec2..54a5882b 100644 --- a/apps/oneclient/frontend/src/components/overlay/DebugInfo.tsx +++ b/apps/oneclient/frontend/src/components/overlay/DebugInfo.tsx @@ -1,8 +1,8 @@ +import { Overlay } from '@/components'; import { bindings } from '@/main'; import { Button } from '@onelauncher/common/components'; import { writeText } from '@tauri-apps/plugin-clipboard-manager'; import { useEffect, useState } from 'react'; -import { Overlay } from './Overlay'; export type DebugInfoArray = Array<{ title: string; value: string }>; export interface DebugInfoData { @@ -12,9 +12,10 @@ export interface DebugInfoData { family: string; locale: string; type: string; - version: string; + osVersion: string; commitHash: string; buildTimestamp: string; + buildVersion: string; } export function useDebugInfo(): DebugInfoArray { @@ -25,9 +26,10 @@ export function useDebugInfo(): DebugInfoArray { family: 'UNKNOWN', locale: 'UNKNOWN', type: 'UNKNOWN', - version: 'UNKNOWN', + osVersion: 'UNKNOWN', commitHash: 'UNKNOWN', buildTimestamp: 'UNKNOWN', + buildVersion: 'UNKNOWN', }); useEffect(() => { @@ -39,9 +41,10 @@ export function useDebugInfo(): DebugInfoArray { family, locale, type, - version, + osVersion, commitHash, buildTimestamp, + buildVersion, ] = await Promise.all([ bindings.debug.isInDev(), bindings.debug.getPlatform(), @@ -49,9 +52,10 @@ export function useDebugInfo(): DebugInfoArray { bindings.debug.getFamily(), bindings.debug.getLocale(), bindings.debug.getType(), - bindings.debug.getVersion(), - bindings.debug.getCommitHash(), + bindings.debug.getOsVersion(), + bindings.debug.getGitCommitHash(), bindings.debug.getBuildTimestamp(), + bindings.debug.getPackageVersion(), ]); setDevInfo({ @@ -61,9 +65,10 @@ export function useDebugInfo(): DebugInfoArray { family, locale: locale ?? 'UNKNOWN', type, - version, + osVersion, commitHash, - buildTimestamp, + buildTimestamp: new Date(buildTimestamp).getTime().toString(), + buildVersion, }); }; @@ -77,9 +82,10 @@ export function useDebugInfo(): DebugInfoArray { { title: 'Family', value: devInfo.family }, { title: 'Locale', value: devInfo.locale }, { title: 'Type', value: devInfo.type }, - { title: 'Version', value: devInfo.version }, + { title: 'Os Version', value: devInfo.osVersion }, { title: 'Commit Hash', value: devInfo.commitHash }, { title: 'Build Timestamp', value: devInfo.buildTimestamp }, + { title: 'Version', value: devInfo.buildVersion }, ]; } @@ -87,7 +93,7 @@ export function copyDebugInfo(debugInfo: DebugInfoArray) { const timestamp = Math.floor(new Date().getTime() / 1000); const lines = [`**Data exported at:** (\`${timestamp}\`)`, ...debugInfo.map((lineData) => { if (lineData.title === 'Build Timestamp') - return `**${lineData.title}:** (\`${lineData.value}\`)`; + return `**${lineData.title}:** (\`${Math.floor(Number(lineData.value) / 1000)}\`)`; return `**${lineData.title}:** \`${lineData.value}\``; })]; writeText(lines.join('\n')); @@ -111,7 +117,7 @@ export function RawDebugInfo({ debugInfo }: { debugInfo: DebugInfoArray }) { {debugInfo.map((lineData) => { let line = ''; if (lineData.title === 'Build Timestamp') - line = `${lineData.title}: ${new Date(Number(lineData.value) * 1000)}`; + line = `${lineData.title}: ${new Date(Number(lineData.value))}`; else line = `${lineData.title}: ${lineData.value}`; return

{line}

; diff --git a/apps/oneclient/frontend/src/components/overlay/ImportSkinModal.tsx b/apps/oneclient/frontend/src/components/overlay/ImportSkinModal.tsx index aa55a0dd..1854edfc 100644 --- a/apps/oneclient/frontend/src/components/overlay/ImportSkinModal.tsx +++ b/apps/oneclient/frontend/src/components/overlay/ImportSkinModal.tsx @@ -1,6 +1,6 @@ +import { Overlay } from '@/components'; import { Button, TextField } from '@onelauncher/common/components'; import { useState } from 'react'; -import { Overlay } from './Overlay'; export function ImportSkinModal({ importFromURL, importFromUsername }: { importFromURL: (url: string) => void; importFromUsername: (username: string) => void }) { const [input, setInput] = useState(''); diff --git a/apps/oneclient/frontend/src/components/overlay/KillMinecraft.tsx b/apps/oneclient/frontend/src/components/overlay/KillMinecraft.tsx new file mode 100644 index 00000000..d85f14c0 --- /dev/null +++ b/apps/oneclient/frontend/src/components/overlay/KillMinecraft.tsx @@ -0,0 +1,19 @@ +import { Overlay } from '@/components'; +import { bindings } from '@/main'; +import { useCommandSuspense } from '@onelauncher/common'; + +export function KillMinecraft({ setOpen }: { setOpen: React.Dispatch> }) { + const { data: foundAllProcess } = useCommandSuspense(['getRunningProcesses'], () => bindings.core.getRunningProcesses()); + const kill = () => { + foundAllProcess.forEach(process => bindings.core.killProcess(process.pid)); + setOpen(false); + }; + + return ( + + Minecraft is running +

Do you want to kill minecraft?

+ +
+ ); +} diff --git a/apps/oneclient/frontend/src/components/overlay/NoAccountPopup.tsx b/apps/oneclient/frontend/src/components/overlay/NoAccountPopup.tsx index 9459202d..7bb814e9 100644 --- a/apps/oneclient/frontend/src/components/overlay/NoAccountPopup.tsx +++ b/apps/oneclient/frontend/src/components/overlay/NoAccountPopup.tsx @@ -1,23 +1,11 @@ -import { Button } from '@onelauncher/common/components'; -import { DialogTrigger } from 'react-aria-components'; -import { AddAccountModal } from './AddAccountModal'; -import { Overlay } from './Overlay'; +import { AddAccountModalButton, Overlay } from '@/components'; export function NoAccountPopup() { return ( No Account

Please add an account before you start minecraft

- - - - - - - - +
); } diff --git a/apps/oneclient/frontend/src/components/overlay/PolyBundleModal.tsx b/apps/oneclient/frontend/src/components/overlay/PolyBundleModal.tsx deleted file mode 100644 index f4d55e1c..00000000 --- a/apps/oneclient/frontend/src/components/overlay/PolyBundleModal.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import type { OverlayProps } from './Overlay'; -import { Overlay } from './Overlay'; - -export interface PolyBundleModalProps extends OverlayProps { - -} - -export function PolyBundleModal() { - return ( - - test - - ); -} diff --git a/apps/oneclient/frontend/src/components/overlay/RemoveAccountModal.tsx b/apps/oneclient/frontend/src/components/overlay/RemoveAccountModal.tsx index 9b81a1d3..7bffc7bd 100644 --- a/apps/oneclient/frontend/src/components/overlay/RemoveAccountModal.tsx +++ b/apps/oneclient/frontend/src/components/overlay/RemoveAccountModal.tsx @@ -1,7 +1,6 @@ import type { MinecraftCredentials } from '@/bindings.gen'; -import { AccountAvatar } from '@/components/AccountAvatar'; +import { AccountAvatar, Overlay } from '@/components'; import { Button } from '@onelauncher/common/components'; -import { Overlay } from './Overlay'; export function RemoveAccountModal({ profile, diff --git a/apps/oneclient/frontend/src/components/overlay/RemoveSkinCapeModal.tsx b/apps/oneclient/frontend/src/components/overlay/RemoveSkinCapeModal.tsx index cdd04b03..d677a837 100644 --- a/apps/oneclient/frontend/src/components/overlay/RemoveSkinCapeModal.tsx +++ b/apps/oneclient/frontend/src/components/overlay/RemoveSkinCapeModal.tsx @@ -1,5 +1,5 @@ +import { Overlay } from '@/components'; import { Button } from '@onelauncher/common/components'; -import { Overlay } from './Overlay'; export function RemoveSkinCapeModal({ onPress }: { onPress: () => void }) { return ( diff --git a/apps/oneclient/frontend/src/components/overlay/SuperSecretDevOptions.tsx b/apps/oneclient/frontend/src/components/overlay/SuperSecretDevOptions.tsx index bd5379f5..ee0eb6e5 100644 --- a/apps/oneclient/frontend/src/components/overlay/SuperSecretDevOptions.tsx +++ b/apps/oneclient/frontend/src/components/overlay/SuperSecretDevOptions.tsx @@ -1,3 +1,4 @@ +import { Overlay, RawDebugInfo, SettingsRow, SettingsSwitch, useDebugInfo } from '@/components'; import { useSettings } from '@/hooks/useSettings'; import { bindings } from '@/main'; import { Button } from '@onelauncher/common/components'; @@ -5,10 +6,6 @@ import { Link } from '@tanstack/react-router'; import { dataDir, join } from '@tauri-apps/api/path'; import { BatteryEmptyIcon, Code02Icon, FolderIcon, LinkExternal01Icon, Truck01Icon } from '@untitled-theme/icons-react'; import { useEffect, useState } from 'react'; -import SettingsRow from '../SettingsRow'; -import SettingsSwitch from '../SettingSwitch'; -import { RawDebugInfo, useDebugInfo } from './DebugInfo'; -import { Overlay } from './Overlay'; export function SuperSecretDevOptions() { const { createSetting } = useSettings(); diff --git a/apps/oneclient/frontend/src/components/overlay/Toasts.tsx b/apps/oneclient/frontend/src/components/overlay/Toasts.tsx index 7adc0483..d4b485e5 100644 --- a/apps/oneclient/frontend/src/components/overlay/Toasts.tsx +++ b/apps/oneclient/frontend/src/components/overlay/Toasts.tsx @@ -2,6 +2,7 @@ import type { IngressType } from '@/bindings.gen'; import type { ToastData, ToastId } from '@/utils/toast'; import type { HTMLAttributes } from 'react'; import type { ToastContentProps, ToastOptions } from 'react-toastify'; +import { Spinner } from '@/components'; import { bindings } from '@/main'; import { toast, toastUpdate } from '@/utils/toast'; import { Button } from '@onelauncher/common/components'; @@ -9,7 +10,6 @@ import { AlertCircleIcon, AlertTriangleIcon, CheckCircleIcon, InfoCircleIcon, XC import { useEffect, useRef } from 'react'; import { cssTransition, ToastContainer } from 'react-toastify'; import { tv } from 'tailwind-variants'; -import { Spinner } from '../Spinner'; import styles from './Toasts.module.css'; const toastVariants = tv({ diff --git a/apps/oneclient/frontend/src/components/overlay/index.ts b/apps/oneclient/frontend/src/components/overlay/index.ts index 8032c167..3865c7a2 100644 --- a/apps/oneclient/frontend/src/components/overlay/index.ts +++ b/apps/oneclient/frontend/src/components/overlay/index.ts @@ -3,6 +3,7 @@ export * from './AddAccountModal'; export * from './BundleModListModal'; export * from './DebugInfo'; export * from './ImportSkinModal'; +export * from './KillMinecraft'; export * from './NoAccountPopup'; export * from './Overlay'; export * from './Popup'; diff --git a/apps/oneclient/frontend/src/hooks/useClusters.ts b/apps/oneclient/frontend/src/hooks/useClusters.ts index 6a718850..ce09f056 100644 --- a/apps/oneclient/frontend/src/hooks/useClusters.ts +++ b/apps/oneclient/frontend/src/hooks/useClusters.ts @@ -31,7 +31,7 @@ export function useActiveCluster() { const { data: clusters } = useLastPlayedClusters(); - return clusters.find(c => c.id === clusterId) ?? clusters.at(0); + return clusters.find(c => c.id === clusterId) ?? clusters[0]; } export function useIsRunning(clusterId: number | undefined | null) { diff --git a/apps/oneclient/frontend/src/routes/__root.tsx b/apps/oneclient/frontend/src/routes/__root.tsx index 25d1f372..b8b64372 100644 --- a/apps/oneclient/frontend/src/routes/__root.tsx +++ b/apps/oneclient/frontend/src/routes/__root.tsx @@ -1,11 +1,14 @@ import type { QueryClient } from '@tanstack/react-query'; import type { NavigateOptions, ToOptions } from '@tanstack/react-router'; -import { Toasts } from '@/components/overlay'; +import { Toasts } from '@/components'; import { useSettings } from '@/hooks/useSettings'; +import { bindings } from '@/main'; +import { useCommand } from '@onelauncher/common'; import { TanStackDevtools } from '@tanstack/react-devtools'; import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'; -import { createRootRouteWithContext, Outlet, useRouter } from '@tanstack/react-router'; +import { createRootRouteWithContext, Outlet, useLocation, useRouter } from '@tanstack/react-router'; import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'; +import { useEffect } from 'react'; import { RouterProvider } from 'react-aria-components'; interface AppRouterContext { @@ -23,9 +26,58 @@ export const Route = createRootRouteWithContext()({ component: RootRoute, }); +type URLPath = Exclude; +const ResolvedPathNames: Record = { + '.': 'UNKNOWN', + '..': 'UNKNOWN', + '/': 'Viewing Home', + '/app': 'Viewing Homepage', + '/app/account': 'Viewing Account', + '/app/account/skins': 'Viewing Skin Manager', + '/app/cluster': 'Viewing Clusters', + '/app/cluster/browser': 'Viewing {clusterName}\'s mods', + '/app/cluster/browser/package': 'Browsing {packageName}', + '/app/cluster/logs': 'Viewing {clusterName}\'s logs', + '/app/cluster/mods': 'Viewing {clusterName}\'s mods', + '/app/cluster/overview': 'Viewing {clusterName}', + '/app/cluster/process': 'Viewing {clusterName}', + '/app/cluster/settings': 'Viewing {clusterName}\'s settings', + '/app/settings': 'Viewing Settings', + '/app/settings/appearance': 'Viewing Settings', + '/app/settings/developer': 'Viewing Settings', + '/app/settings/minecraft': 'Viewing Settings', + '/app/accounts': 'Viewing Accounts', + '/app/clusters': 'Viewing Clusters', + '/onboarding': 'Preparing OneClient', + '/onboarding/account': 'Preparing OneClient', + '/onboarding/finished': 'Preparing OneClient', + '/onboarding/language': 'Preparing OneClient', + '/onboarding/preferences/version': 'Preparing OneClient', + '/onboarding/preferences/versionCategory': 'Preparing OneClient', + '/onboarding/preferences': 'Preparing OneClient', +}; + +// Credit - https://github.com/DuckySoLucky/hypixel-discord-chat-bridge/blob/d3ea84a26ebf094c8191d50b4954549e2dd4dc7f/src/contracts/helperFunctions.js#L216-L225 +function ReplaceVariables(template: string, variables: Record) { + return template.replace(/\{(\w+)\}/g, (match: any, name: string | number) => variables[name] ?? match); +} + +function useDiscordRPC() { + const location = useLocation(); + const clusterId = location.search.clusterId ?? 0; + const provider = location.search.provider ?? 'Modrinth'; + const packageId = location.search.packageId ?? '8pJYUDNi'; + const { data: cluster } = useCommand(['getClusterById', clusterId], () => bindings.core.getClusterById(clusterId)); + const { data: managedPackage } = useCommand(['getPackage', provider, packageId], () => bindings.core.getPackage(provider, packageId)); + useEffect(() => { + bindings.core.setDiscordRPCMessage(ReplaceVariables(ResolvedPathNames[location.pathname as URLPath], { clusterName: cluster?.name ?? 'UNKNOWN', packageName: managedPackage?.name ?? 'UNKNOWN' })); + }, [location.pathname, location.search.clusterId, cluster?.name, managedPackage?.name]); +} + function RootRoute() { const router = useRouter(); const { setting } = useSettings(); + useDiscordRPC(); return ( router.navigate({ to, ...options })} @@ -46,7 +98,7 @@ function DevTools() { return (
- + @@ -366,7 +363,7 @@ function RenderSkin({ skin, selected, animation, setSelectedSkin, setSkins, cape setSkins(prev => prev.filter(skinData => skinData.skin_url !== skin.skin_url))} /> - + )} @@ -174,6 +172,6 @@ function AddAccountButton({ - + ); } diff --git a/apps/oneclient/frontend/src/routes/app/cluster/browser/package.tsx b/apps/oneclient/frontend/src/routes/app/cluster/browser/package.tsx index 3a1957e6..2310da71 100644 --- a/apps/oneclient/frontend/src/routes/app/cluster/browser/package.tsx +++ b/apps/oneclient/frontend/src/routes/app/cluster/browser/package.tsx @@ -1,7 +1,5 @@ import type { ManagedPackage, ManagedUser, ManagedVersion, PackageDonationUrl } from '@/bindings.gen'; -import { LoaderSuspense } from '@/components'; -import { ExternalLink } from '@/components/ExternalLink'; -import { Markdown } from '@/components/Markdown'; +import { ExternalLink, LoaderSuspense, Markdown } from '@/components'; import { bindings } from '@/main'; import { abbreviateNumber, formatAsRelative, upperFirst, useCommand, useCommandMut, useCommandSuspense } from '@onelauncher/common'; import { Button, Show, Tooltip } from '@onelauncher/common/components'; diff --git a/apps/oneclient/frontend/src/routes/app/cluster/logs.tsx b/apps/oneclient/frontend/src/routes/app/cluster/logs.tsx index cd4aa639..8f3d8a5f 100644 --- a/apps/oneclient/frontend/src/routes/app/cluster/logs.tsx +++ b/apps/oneclient/frontend/src/routes/app/cluster/logs.tsx @@ -1,6 +1,5 @@ import type { Key } from 'react-aria-components'; -import { LoaderContainer, SheetPage, useSheetPageContext } from '@/components'; -import { LogViewer } from '@/components/LogViewer'; +import { LoaderContainer, LogViewer, SheetPage, useSheetPageContext } from '@/components'; import { bindings } from '@/main'; import { getMessageFromError, useCommand, useCommandSuspense } from '@onelauncher/common'; import { Dropdown } from '@onelauncher/common/components'; @@ -17,7 +16,7 @@ function RouteComponent() { const { data: fileNames } = useCommandSuspense(['getLogs', cluster.id], () => bindings.core.getLogs(cluster.id)); - const [activeFileName, setActiveFileName] = useState(fileNames[0] || undefined); + const [activeFileName, setActiveFileName] = useState(fileNames[0] || null); return ( diff --git a/apps/oneclient/frontend/src/routes/app/cluster/mods.tsx b/apps/oneclient/frontend/src/routes/app/cluster/mods.tsx index ebfb1d29..351f5440 100644 --- a/apps/oneclient/frontend/src/routes/app/cluster/mods.tsx +++ b/apps/oneclient/frontend/src/routes/app/cluster/mods.tsx @@ -1,5 +1,5 @@ -import type { ModCardContextApi } from '@/components/Bundle'; -import { ModCardContext, ModList } from '@/components/Bundle'; +import type { ModCardContextApi } from '@/components'; +import { ModCardContext, ModList } from '@/components'; import { bindings } from '@/main'; import { useCommandSuspense } from '@onelauncher/common'; import { createFileRoute } from '@tanstack/react-router'; diff --git a/apps/oneclient/frontend/src/routes/app/cluster/overview.tsx b/apps/oneclient/frontend/src/routes/app/cluster/overview.tsx index d4b04ac8..02d60b6f 100644 --- a/apps/oneclient/frontend/src/routes/app/cluster/overview.tsx +++ b/apps/oneclient/frontend/src/routes/app/cluster/overview.tsx @@ -1,4 +1,4 @@ -import { SheetPage } from '@/components/SheetPage'; +import { SheetPage } from '@/components'; import { createFileRoute } from '@tanstack/react-router'; export const Route = createFileRoute('/app/cluster/overview')({ diff --git a/apps/oneclient/frontend/src/routes/app/cluster/process.tsx b/apps/oneclient/frontend/src/routes/app/cluster/process.tsx index 02a3563e..16e45a6d 100644 --- a/apps/oneclient/frontend/src/routes/app/cluster/process.tsx +++ b/apps/oneclient/frontend/src/routes/app/cluster/process.tsx @@ -1,6 +1,5 @@ -import type { LogViewerRef } from '@/components/LogViewer'; -import { LoaderContainer, SheetPage, useSheetPageContext } from '@/components'; -import { LogViewer } from '@/components/LogViewer'; +import type { LogViewerRef } from '@/components'; +import { LoaderContainer, LogViewer, SheetPage, useSheetPageContext } from '@/components'; import { bindings } from '@/main'; import { getMessageFromError, useAsyncEffect, useCommand } from '@onelauncher/common'; import { createFileRoute } from '@tanstack/react-router'; diff --git a/apps/oneclient/frontend/src/routes/app/cluster/route.tsx b/apps/oneclient/frontend/src/routes/app/cluster/route.tsx index 65d037c3..0d658601 100644 --- a/apps/oneclient/frontend/src/routes/app/cluster/route.tsx +++ b/apps/oneclient/frontend/src/routes/app/cluster/route.tsx @@ -1,6 +1,4 @@ -import { LoaderSuspense, Tab, TabList } from '@/components'; -import { LaunchButton } from '@/components/LaunchButton'; -import { SheetPage } from '@/components/SheetPage'; +import { LaunchButton, LoaderSuspense, SheetPage, Tab, TabList } from '@/components'; import { useIsRunning } from '@/hooks/useClusters'; import { bindings } from '@/main'; import { prettifyLoader } from '@/utils/loaders'; @@ -128,7 +126,7 @@ function HeaderLarge() {
@@ -155,7 +153,7 @@ function HeaderSmall() {
diff --git a/apps/oneclient/frontend/src/routes/app/cluster/settings.tsx b/apps/oneclient/frontend/src/routes/app/cluster/settings.tsx index f04ac848..9cc0692e 100644 --- a/apps/oneclient/frontend/src/routes/app/cluster/settings.tsx +++ b/apps/oneclient/frontend/src/routes/app/cluster/settings.tsx @@ -1,5 +1,4 @@ -import { SheetPage } from '@/components'; -import SettingsRow from '@/components/SettingsRow'; +import { SettingsRow, SheetPage } from '@/components'; import { useClusterProfile } from '@/hooks/useSettings'; import { Switch, TextField } from '@onelauncher/common/components'; import { createFileRoute } from '@tanstack/react-router'; diff --git a/apps/oneclient/frontend/src/routes/app/clusters.tsx b/apps/oneclient/frontend/src/routes/app/clusters.tsx index eb415ce1..ae132e16 100644 --- a/apps/oneclient/frontend/src/routes/app/clusters.tsx +++ b/apps/oneclient/frontend/src/routes/app/clusters.tsx @@ -1,7 +1,5 @@ import type { GameLoader } from '@/bindings.gen'; -import { GameBackground } from '@/components'; -import { LaunchButton } from '@/components/LaunchButton'; -import { SheetPage } from '@/components/SheetPage'; +import { GameBackground, LaunchButton, SheetPage } from '@/components'; import { bindings } from '@/main'; import useClusterStore from '@/stores/clusterStore'; import { prettifyLoader } from '@/utils/loaders'; @@ -105,6 +103,21 @@ function RouteComponent() { }); }, [cluster, navigate]); + if (!cluster) + return ( + } + headerSmall={} + > +
+ +

Something wen't wrong while getting a cluster

+

Please reload and if this does not work please contact support

+
+
+
+ ); + return ( } @@ -139,7 +152,7 @@ function RouteComponent() {
-

Version {cluster?.mc_version}

+

Version {cluster.mc_version}

{versionInfo.longDescription}

{minorVersions.length > 1 && ( @@ -196,7 +209,7 @@ function RouteComponent() { )}
- +