From eb820e45ff714523dcc6a3171829c47d1be88014 Mon Sep 17 00:00:00 2001 From: LynithDev <61880709+LynithDev@users.noreply.github.com> Date: Sun, 15 Jun 2025 20:27:44 +0200 Subject: [PATCH 1/2] feat: finished home page and did lots of stuff --- apps/oneclient/desktop/src/lib.rs | 9 ++ .../src/components/GameBackground.tsx | 8 +- .../frontend/src/components/Loader.tsx | 68 ++++++++++ .../frontend/src/components/Navbar.tsx | 2 +- .../frontend/src/components/Spinner.tsx | 32 +++++ .../frontend/src/components/index.ts | 2 + apps/oneclient/frontend/src/routes/__root.tsx | 3 - .../frontend/src/routes/app/index.tsx | 126 +++++++++++++++++- .../frontend/src/routes/app/route.tsx | 40 +++--- .../stores/{appFrameStore.ts => appStore.ts} | 18 ++- .../frontend/src/styles/animations.css | 18 +++ apps/oneclient/frontend/src/styles/global.css | 14 ++ apps/oneclient/frontend/src/types/global.d.ts | 9 ++ apps/oneclient/frontend/src/utils/motion.ts | 44 ++++++ .../frontend/src/utils/versionMap.ts | 40 ++++++ apps/onelauncher/desktop/src/lib.rs | 9 ++ .../frontend/src/styles/global.css | 11 ++ .../core/src/api/proxy/impl/proxy_tauri.rs | 3 + packages/core/src/api/tauri/commands.rs | 31 +++-- packages/core/src/logger.rs | 22 ++- packages/core/src/store/core_options.rs | 6 +- packages/web_common/package.json | 1 + .../src/components/AnimatedOutlet.tsx | 2 +- packages/web_common/src/components/Button.tsx | 3 +- packages/web_common/src/hooks/useCommand.ts | 63 ++++++--- packages/web_common/src/theme.css | 14 +- packages/web_common/vite.config.ts | 5 +- 27 files changed, 519 insertions(+), 84 deletions(-) create mode 100644 apps/oneclient/frontend/src/components/Loader.tsx create mode 100644 apps/oneclient/frontend/src/components/Spinner.tsx rename apps/oneclient/frontend/src/stores/{appFrameStore.ts => appStore.ts} (51%) create mode 100644 apps/oneclient/frontend/src/styles/animations.css create mode 100644 apps/oneclient/frontend/src/types/global.d.ts create mode 100644 apps/oneclient/frontend/src/utils/motion.ts create mode 100644 apps/oneclient/frontend/src/utils/versionMap.ts diff --git a/apps/oneclient/desktop/src/lib.rs b/apps/oneclient/desktop/src/lib.rs index d46bfc5c..4e8f7c21 100644 --- a/apps/oneclient/desktop/src/lib.rs +++ b/apps/oneclient/desktop/src/lib.rs @@ -20,6 +20,12 @@ pub struct SingleInstancePayload { #[tracing::instrument] async fn initialize_core() -> LauncherResult<()> { + let level = if cfg!(debug_assertions) { + tracing::Level::DEBUG + } else { + tracing::Level::INFO + }; + let opts = CoreOptions { curseforge_api_key: Some(constants::CURSEFORGE_API_KEY.to_string()), launcher_name: "OneClient".to_string(), @@ -27,6 +33,9 @@ async fn initialize_core() -> LauncherResult<()> { launcher_website: "https://polyfrost.org/".to_string(), discord_client_id: None, //Some(constants::DISCORD_CLIENT_ID.to_string()), // disabled for now fetch_attempts: 3, + logger_filter: Some( + format!("{}={level},onelauncher_core={level}", env!("CARGO_PKG_NAME")), + ), ..Default::default() }; diff --git a/apps/oneclient/frontend/src/components/GameBackground.tsx b/apps/oneclient/frontend/src/components/GameBackground.tsx index aea2413d..ef7cebd1 100644 --- a/apps/oneclient/frontend/src/components/GameBackground.tsx +++ b/apps/oneclient/frontend/src/components/GameBackground.tsx @@ -1,3 +1,4 @@ +import type { CSSProperties } from 'react'; import { twMerge } from 'tailwind-merge'; import HypixelSkyblockHub from '../assets/backgrounds/HypixelSkyblockHub.png'; @@ -5,20 +6,21 @@ const GameBackgrounds = { HypixelSkyblockHub, }; -type GameBackgroundName = keyof typeof GameBackgrounds; +export type GameBackgroundName = keyof typeof GameBackgrounds; interface GameBackgroundProps { name: GameBackgroundName; className?: string; + style?: CSSProperties; } -export function GameBackground({ name, className = '' }: GameBackgroundProps) { +export function GameBackground({ name, className = '', style = undefined }: GameBackgroundProps) { const BackgroundImage = GameBackgrounds[name]; return (
); } diff --git a/apps/oneclient/frontend/src/components/Loader.tsx b/apps/oneclient/frontend/src/components/Loader.tsx new file mode 100644 index 00000000..5c273593 --- /dev/null +++ b/apps/oneclient/frontend/src/components/Loader.tsx @@ -0,0 +1,68 @@ +import type { HTMLAttributes, ReactNode } from 'react'; +import type { SpinnerProps } from './Spinner'; +import { motion } from 'motion/react'; +import { Suspense } from 'react'; +import { twMerge } from 'tailwind-merge'; +import { Spinner } from './Spinner'; + +interface LoaderProps extends HTMLAttributes { + children?: ReactNode; + spinner?: SpinnerProps; +} + +export function LoaderContainer({ + loading = false, + children, + spinner, + className, +}: LoaderProps & { + loading?: boolean; +}) { + return loading ? : {children}; +} + +export function LoaderSuspense({ + children, + spinner, + className, +}: LoaderProps) { + return ( + }> + + {children} + + + ); +} + +function Fallback({ + spinner, + className, +}: { + spinner?: SpinnerProps; + className?: string; +}) { + return ( +
+ +
+ ); +} + +function LoadedChildren({ + children, + className, +}: { + children: ReactNode; + className?: string; +}) { + return ( + + {children} + + ); +} diff --git a/apps/oneclient/frontend/src/components/Navbar.tsx b/apps/oneclient/frontend/src/components/Navbar.tsx index ee07e236..505ad7a7 100644 --- a/apps/oneclient/frontend/src/components/Navbar.tsx +++ b/apps/oneclient/frontend/src/components/Navbar.tsx @@ -24,7 +24,7 @@ export function Navbar() { Accounts
-
+
} onClick={onMinimize} diff --git a/apps/oneclient/frontend/src/components/Spinner.tsx b/apps/oneclient/frontend/src/components/Spinner.tsx new file mode 100644 index 00000000..af8794e7 --- /dev/null +++ b/apps/oneclient/frontend/src/components/Spinner.tsx @@ -0,0 +1,32 @@ +import type { HTMLAttributes } from 'react'; +import type { VariantProps } from 'tailwind-variants'; +import { tv } from 'tailwind-variants'; + +const spinnerVariants = tv({ + base: 'inline-block relative opacity-0 animate-delay-1000 animate-fade animate-fill-forwards', + variants: { + size: { + small: 'w-8 h-8', + medium: 'w-12 h-12', + large: 'w-16 h-16', + }, + }, +}); + +type SpinnerVariantsProps = VariantProps; + +export interface SpinnerProps extends HTMLAttributes { + size?: SpinnerVariantsProps['size']; +}; + +export function Spinner({ + size = 'medium', + className, +}: SpinnerProps) { + return ( +
+
+
+
+ ); +} diff --git a/apps/oneclient/frontend/src/components/index.ts b/apps/oneclient/frontend/src/components/index.ts index b50eb89f..9ca292a7 100644 --- a/apps/oneclient/frontend/src/components/index.ts +++ b/apps/oneclient/frontend/src/components/index.ts @@ -1,2 +1,4 @@ export * from './GameBackground'; +export * from './Loader'; export * from './Navbar'; +export * from './Spinner'; diff --git a/apps/oneclient/frontend/src/routes/__root.tsx b/apps/oneclient/frontend/src/routes/__root.tsx index 87e628bd..e014e607 100644 --- a/apps/oneclient/frontend/src/routes/__root.tsx +++ b/apps/oneclient/frontend/src/routes/__root.tsx @@ -1,6 +1,5 @@ import type { QueryClient } from '@tanstack/react-query'; import type { NavigateOptions, ToOptions } from '@tanstack/react-router'; -import { Navbar } from '@/components'; import { AnimatedOutletProvider } from '@onelauncher/common/components'; import { createRootRouteWithContext, Outlet, useRouter } from '@tanstack/react-router'; import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'; @@ -30,8 +29,6 @@ function RootRoute() { useHref={to => router.buildLocation({ to }).href} >
- - diff --git a/apps/oneclient/frontend/src/routes/app/index.tsx b/apps/oneclient/frontend/src/routes/app/index.tsx index b74e6a66..bce289b7 100644 --- a/apps/oneclient/frontend/src/routes/app/index.tsx +++ b/apps/oneclient/frontend/src/routes/app/index.tsx @@ -1,21 +1,133 @@ +import type { ClusterModel } from '@/bindings.gen'; +import type { HTMLAttributes } from 'react'; +import { GameBackground } from '@/components'; +import { bindings } from '@/main'; +import { animations, transitions } from '@/utils/motion'; +import { getVersionInfo } from '@/utils/versionMap'; +import { useCommandSuspense } from '@onelauncher/common'; +import { Button } from '@onelauncher/common/components'; import { createFileRoute } from '@tanstack/react-router'; +import { DotsGridIcon, Settings04Icon } from '@untitled-theme/icons-react'; +import { motion } from 'motion/react'; +import { twMerge } from 'tailwind-merge'; export const Route = createFileRoute('/app/')({ component: RouteComponent, }); function RouteComponent() { + const { data: clusters } = useCommandSuspense>( + 'getClusters', + async () => { + await new Promise(resolve => setTimeout(resolve, 3000)); // Simulate loading delay + return bindings.core.getClusters(); + }, + { + select: ((data: Array) => { + const sorted = data.sort((a, b) => { + if (a.last_played && b.last_played) + return new Date(b.last_played).getTime() - new Date(a.last_played).getTime(); + else if (a.last_played) + return -1; // a has last_played, b does not + else if (b.last_played) + return 1; // b has last_played, a does not + + const aVersion = a.mc_version.replaceAll('.', ''); + const bVersion = b.mc_version.replaceAll('.', ''); + return Number.parseInt(bVersion) - Number.parseInt(aVersion); + }); + + return [ + sorted[0], + sorted[1], + undefined, + ]; + }) as (data: Array) => Array, + }, + ); + return (
-
-

1.8.9

-
- -
-
+ +

1.8.9

+

The Bountiful Update

+
+ +
-
+ + + + {clusters.map(cluster => ( + + ))} + + + + + +
+ ); +} + +interface RecentsCardProps { + version: string | undefined; +} + +const BLUR = '30px'; +function RecentsCard({ version }: RecentsCardProps) { + const versionInfo = getVersionInfo(version); + + return ( + + {versionInfo && ( +
+ + +
+
+ +

{version}

+
+ )} +
+ ); +} + +function Card({ + blur = true, + children, + className, + style, +}: { + blur?: boolean; + children?: React.ReactNode; +} & HTMLAttributes) { + return ( +
+ {children}
); } diff --git a/apps/oneclient/frontend/src/routes/app/route.tsx b/apps/oneclient/frontend/src/routes/app/route.tsx index 1dfeeb3b..e4cf6791 100644 --- a/apps/oneclient/frontend/src/routes/app/route.tsx +++ b/apps/oneclient/frontend/src/routes/app/route.tsx @@ -1,6 +1,7 @@ +import { LoaderSuspense, Navbar } from '@/components'; import { GameBackground } from '@/components/GameBackground'; import { AnimatedOutlet } from '@onelauncher/common/components'; -import { createFileRoute } from '@tanstack/react-router'; +import { createFileRoute, Outlet } from '@tanstack/react-router'; export const Route = createFileRoute('/app')({ component: RouteComponent, @@ -8,24 +9,29 @@ export const Route = createFileRoute('/app')({ function RouteComponent() { return ( -
- + +
+ -
- + + +
+ {/* */} + +
-
+
); } diff --git a/apps/oneclient/frontend/src/stores/appFrameStore.ts b/apps/oneclient/frontend/src/stores/appStore.ts similarity index 51% rename from apps/oneclient/frontend/src/stores/appFrameStore.ts rename to apps/oneclient/frontend/src/stores/appStore.ts index 6bbcb87d..f91847fc 100644 --- a/apps/oneclient/frontend/src/stores/appFrameStore.ts +++ b/apps/oneclient/frontend/src/stores/appStore.ts @@ -2,17 +2,27 @@ import type { ClusterModel } from '@/bindings.gen'; import type { FileRoutesByFullPath } from '@/routeTree.gen'; import { create } from 'zustand'; -interface AppFrameStore { - previousPage: FileRoutesByFullPath | null; +interface AppStore { activeCluster: ClusterModel | null; + previousPage: FileRoutesByFullPath | null; } -const useAppFrameStore = create()(set => ({ +interface AppStoreActions { + setInitialData: (data: AppStore) => void; + setActiveCluster: (cluster: ClusterModel | null) => void; + setPreviousPage: (page: FileRoutesByFullPath) => void; +} + +const useAppStore = create()(set => ({ activeCluster: null, previousPage: null, + setInitialData: (data: AppStore) => set({ + activeCluster: data.activeCluster, + previousPage: data.previousPage, + }), setPreviousPage: (page: FileRoutesByFullPath) => set({ previousPage: page }), setActiveCluster: (cluster: ClusterModel | null) => set({ activeCluster: cluster }), })); -export default useAppFrameStore; +export default useAppStore; diff --git a/apps/oneclient/frontend/src/styles/animations.css b/apps/oneclient/frontend/src/styles/animations.css new file mode 100644 index 00000000..1fd64fb9 --- /dev/null +++ b/apps/oneclient/frontend/src/styles/animations.css @@ -0,0 +1,18 @@ +@layer utilities { + @keyframes custom-anim-fade-scale { + 0% { + transform: scale(0); + opacity: 1; + } + 100% { + transform: scale(1); + opacity: 0; + } + } +} + +@utility animate-fade-scale { + transform: scale(0); + opacity: 1; + animation: custom-anim-fade-scale var(--default-animation-duration, 1s) var(--default-animation-timing-function, cubic-bezier(0, 0, 0.2, 1)) var(--default-animation-delay, 0s) forwards; +} diff --git a/apps/oneclient/frontend/src/styles/global.css b/apps/oneclient/frontend/src/styles/global.css index 113e4de1..d0f8814a 100644 --- a/apps/oneclient/frontend/src/styles/global.css +++ b/apps/oneclient/frontend/src/styles/global.css @@ -2,6 +2,7 @@ @plugin "tailwindcss-react-aria-components"; @plugin "tailwindcss-animated"; @import "../../node_modules/@onelauncher/common/dist/theme.css"; +@import "./animations.css"; @utility partial-underline-* { position: relative; @@ -18,3 +19,16 @@ border-radius: 10px; } } + +@theme { + /** border */ + --color-component-border: #ffffff1A; + + /** rounding */ + --radius-sm: 0.25rem; + --radius-md: 0.438rem; + --radius-lg: 0.625rem; + --radius-xl: 1rem; + --radius-2xl: 1.5rem; + --radius-3xl: 2rem; +} diff --git a/apps/oneclient/frontend/src/types/global.d.ts b/apps/oneclient/frontend/src/types/global.d.ts new file mode 100644 index 00000000..871e7fd1 --- /dev/null +++ b/apps/oneclient/frontend/src/types/global.d.ts @@ -0,0 +1,9 @@ +import type { bindings } from '@/main'; + +export type BindingCommands = (keyof typeof bindings.core) | (keyof typeof bindings.oneclient); + +declare module '@onelauncher/common' { + interface Register { + commands: Array; + } +} diff --git a/apps/oneclient/frontend/src/utils/motion.ts b/apps/oneclient/frontend/src/utils/motion.ts new file mode 100644 index 00000000..44ceedac --- /dev/null +++ b/apps/oneclient/frontend/src/utils/motion.ts @@ -0,0 +1,44 @@ +import type { MotionProps } from 'motion/react'; + +export const transitions = { + spring: { + duration: 0.3, + bounce: 0.1, + power: 0.2, + type: 'spring', + }, +} as const satisfies Record; + +export const animations = { + slideInRight: { + initial: { + right: '-100%', + }, + animate: { + right: '0', + }, + transition: transitions.spring, + }, + + slideInLeft: { + initial: { + position: 'relative', + left: '-100%', + }, + animate: { + position: 'relative', + left: '0', + }, + }, + + slideInUp: { + initial: { + position: 'relative', + bottom: '-100%', + }, + animate: { + position: 'relative', + bottom: '0', + }, + }, +} as const satisfies Record; diff --git a/apps/oneclient/frontend/src/utils/versionMap.ts b/apps/oneclient/frontend/src/utils/versionMap.ts new file mode 100644 index 00000000..e232f3db --- /dev/null +++ b/apps/oneclient/frontend/src/utils/versionMap.ts @@ -0,0 +1,40 @@ +import type { GameBackgroundName } from '@/components'; + +export interface VersionInfo { + backgroundName: GameBackgroundName; + description: string; +} + +const VERSION_MAP: Record = { + [-1]: { + backgroundName: 'HypixelSkyblockHub', + description: 'Unknown Version', + }, + 8: { + backgroundName: 'HypixelSkyblockHub', + description: 'The Bountiful Update', + }, +} as const; + +export function getVersionInfo(version: number | string | null | undefined): VersionInfo | undefined { + if (version === undefined || version === null) + return undefined; + + let majorVersion; + + if (typeof version === 'string') { + const parts = version.split('.'); + if (parts.length >= 2) + majorVersion = Number.parseInt(parts[1], 10); + } + + if (majorVersion) + return VERSION_MAP[majorVersion]; + else + return undefined; +} + +export function getVersionInfoOrDefault(version: number | string): VersionInfo { + const info = getVersionInfo(version); + return info ?? VERSION_MAP[-1]; +} diff --git a/apps/onelauncher/desktop/src/lib.rs b/apps/onelauncher/desktop/src/lib.rs index fee5c801..7bc4dad5 100644 --- a/apps/onelauncher/desktop/src/lib.rs +++ b/apps/onelauncher/desktop/src/lib.rs @@ -20,6 +20,12 @@ pub struct SingleInstancePayload { #[tracing::instrument] async fn initialize_core() -> LauncherResult<()> { + let level = if cfg!(debug_assertions) { + tracing::Level::DEBUG + } else { + tracing::Level::INFO + }; + let opts = CoreOptions { curseforge_api_key: Some(constants::CURSEFORGE_API_KEY.to_string()), launcher_name: "OneLauncher".to_string(), @@ -27,6 +33,9 @@ async fn initialize_core() -> LauncherResult<()> { launcher_website: "https://polyfrost.org/".to_string(), discord_client_id: Some(constants::DISCORD_CLIENT_ID.to_string()), fetch_attempts: 3, + logger_filter: Some( + format!("{}={level},onelauncher_core={level}", env!("CARGO_PKG_NAME")), + ), ..Default::default() }; diff --git a/apps/onelauncher/frontend/src/styles/global.css b/apps/onelauncher/frontend/src/styles/global.css index 4b3b8ec7..34cfceb8 100644 --- a/apps/onelauncher/frontend/src/styles/global.css +++ b/apps/onelauncher/frontend/src/styles/global.css @@ -2,3 +2,14 @@ @plugin "tailwindcss-react-aria-components"; @plugin "tailwindcss-animated"; @import "../../node_modules/@onelauncher/common/dist/theme.css"; + +@theme { + --radius-xs: 0.125rem; + --radius-sm: 0.25rem; + --radius-md: 0.375rem; + --radius-lg: 0.5rem; + --radius-xl: 0.75rem; + --radius-2xl: 1rem; + --radius-3xl: 1.5rem; + --radius-4xl: 2rem; +} diff --git a/packages/core/src/api/proxy/impl/proxy_tauri.rs b/packages/core/src/api/proxy/impl/proxy_tauri.rs index f38d0558..46d89fe1 100644 --- a/packages/core/src/api/proxy/impl/proxy_tauri.rs +++ b/packages/core/src/api/proxy/impl/proxy_tauri.rs @@ -12,6 +12,9 @@ pub struct ProxyTauri { impl ProxyTauri { #[must_use] pub fn new(handle: AppHandle) -> Self { + tracing::debug!("using tauri bridge"); + tracing::debug!("webview version: {}", tauri::webview_version().unwrap_or("unknown".into())); + Self { emitter: LauncherEventEmitter::new(handle.clone()), handle, diff --git a/packages/core/src/api/tauri/commands.rs b/packages/core/src/api/tauri/commands.rs index e7444efe..6959941e 100644 --- a/packages/core/src/api/tauri/commands.rs +++ b/packages/core/src/api/tauri/commands.rs @@ -1,6 +1,5 @@ use interpulse::api::minecraft::Version; -use onelauncher_entity::{clusters, icon::Icon, loader::GameLoader, prelude::entity}; -use sea_orm::ActiveValue::Set; +use onelauncher_entity::{icon::Icon, loader::GameLoader}; use tauri::{AppHandle, Runtime}; use crate::{api::{self, cluster::dao::ClusterId}, error::LauncherResult, store::{credentials::MinecraftCredentials, Core}}; @@ -26,8 +25,8 @@ pub trait TauriLauncherApi { #[taurpc(alias = "launchCluster")] async fn launch_cluster(id: ClusterId, uuid: Option) -> LauncherResult<()>; - #[taurpc(alias = "updateClusterById")] - async fn update_cluster_by_id(id: ClusterId, request: Cluster) -> LauncherResult<()>; + // #[taurpc(alias = "updateClusterById")] + // async fn update_cluster_by_id(id: ClusterId, request: Cluster) -> LauncherResult<()>; // Setting Profiles @@ -120,21 +119,21 @@ impl TauriLauncherApi for TauriLauncherApiImpl { Ok(()) } - async fn update_cluster_by_id(id: ClusterId, request: clusters::ActiveModel) -> LauncherResult<()> { - let updated_cluster = api::cluster::dao::update_cluster_by_id(id, |mut active_model| async move { - if let Some(name) = request.name { - active_model.name = Set(name); - } + // async fn update_cluster_by_id(self, id: ClusterId, request: clusters::ActiveModel) -> LauncherResult<()> { + // // let updated_cluster = api::cluster::dao::update_cluster_by_id(id, |mut active_model| async move { + // // if let Some(name) = request.name { + // // active_model.name = Set(name); + // // } - active_model.updated_at = Set(chrono::Utc::now().naive_utc()); + // // active_model.updated_at = Set(chrono::Utc::now().naive_utc()); - Ok(active_model) - }) - .await - .map_err(|e| e.to_string())?; + // // Ok(active_model) + // // }) + // // .await + // // .map_err(|e| e.to_string())?; - Ok(()) - } + // Ok(()) + // } // Setting Profiles diff --git a/packages/core/src/logger.rs b/packages/core/src/logger.rs index e7740b80..fd0b74e2 100644 --- a/packages/core/src/logger.rs +++ b/packages/core/src/logger.rs @@ -6,7 +6,15 @@ use crate::store::Core; #[cfg(debug_assertions)] pub async fn start_logger() { let filter = tracing_subscriber::EnvFilter::try_from_default_env() - .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(format!("{}=info", env!("CARGO_PKG_NAME")))); + .unwrap_or_else(|_| { + tracing_subscriber::EnvFilter::new( + Core::get().logger_filter + .as_ref() + .unwrap_or( + &format!("{}=info", env!("CARGO_PKG_NAME")) + ) + ) + }); let mut fmt_layer = tracing_subscriber::fmt::layer() .with_ansi(true) @@ -16,7 +24,7 @@ pub async fn start_logger() { .with_thread_names(true) .pretty(); - if let Some(span) = Core::get().span_formatting.clone() { + if let Some(span) = Core::get().logger_span_formatting.clone() { fmt_layer = fmt_layer.with_span_events(span); } @@ -62,7 +70,15 @@ pub async fn start_logger() { }; let filter = tracing_subscriber::EnvFilter::try_from_default_env() - .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(format!("{}=info", env!("CARGO_PKG_NAME")))); + .unwrap_or_else(|_| { + tracing_subscriber::EnvFilter::new( + Core::get().logger_filter + .as_ref() + .unwrap_or( + &format!("{}=info", env!("CARGO_PKG_NAME")) + ) + ) + }); let mut fmt_layer = tracing_subscriber::fmt::layer() .compact() diff --git a/packages/core/src/store/core_options.rs b/packages/core/src/store/core_options.rs index 2df8568c..e44c23a5 100644 --- a/packages/core/src/store/core_options.rs +++ b/packages/core/src/store/core_options.rs @@ -16,11 +16,12 @@ pub struct CoreOptions { pub launcher_version: String, pub launcher_website: String, pub fetch_attempts: usize, - pub span_formatting: Option, /// Default client id is the same as the one used by the official launcher pub msa_client_id: String, pub msa_redirect_uri: String, pub curseforge_api_key: Option, + pub logger_span_formatting: Option, + pub logger_filter: Option, } impl Default for CoreOptions { @@ -31,10 +32,11 @@ impl Default for CoreOptions { launcher_version: String::from(env!("CARGO_PKG_VERSION")), launcher_website: String::from("https://polyfrost.org/"), fetch_attempts: 3, - span_formatting: None, msa_client_id: String::from("00000000402b5328"), msa_redirect_uri: String::from("https://login.live.com/oauth20_desktop.srf"), curseforge_api_key: None, + logger_span_formatting: None, + logger_filter: None, } } } diff --git a/packages/web_common/package.json b/packages/web_common/package.json index 52c8abd4..18c0cf6d 100644 --- a/packages/web_common/package.json +++ b/packages/web_common/package.json @@ -24,6 +24,7 @@ "peerDependencies": { "@tanstack/react-query": "^5.66.5", "@tanstack/react-router": "^1.114.3", + "@untitled-theme/icons-react": "^0.14.0", "motion": "^12.10.5", "react": "^19.0.0", "react-aria-components": "^1.8.0", diff --git a/packages/web_common/src/components/AnimatedOutlet.tsx b/packages/web_common/src/components/AnimatedOutlet.tsx index 2c6cecc5..bfa4801b 100644 --- a/packages/web_common/src/components/AnimatedOutlet.tsx +++ b/packages/web_common/src/components/AnimatedOutlet.tsx @@ -7,7 +7,7 @@ import type { AnyRoute } from '@tanstack/react-router'; import type { MotionProps } from 'motion/react'; import { Outlet, useMatch, useRouter } from '@tanstack/react-router'; -import { motion } from 'motion/react'; +import { AnimatePresence, motion } from 'motion/react'; import { createContext, useContext, useEffect, useRef, useState } from 'react'; interface TransitionProps { diff --git a/packages/web_common/src/components/Button.tsx b/packages/web_common/src/components/Button.tsx index c6c72b1e..1fefb9c7 100644 --- a/packages/web_common/src/components/Button.tsx +++ b/packages/web_common/src/components/Button.tsx @@ -29,8 +29,9 @@ export const buttonVariants = tv({ }, size: { normal: 'py-1.5 px-3', + large: 'py-2 px-6 text-lg', icon: 'p-1.5 aspect-square box-border w-8 h-8', - iconLarge: 'w-9 h-9 [&>*]:p-0.5', + iconLarge: 'w-10 h-10 [&>*]:p-0.5', }, }, }); diff --git a/packages/web_common/src/hooks/useCommand.ts b/packages/web_common/src/hooks/useCommand.ts index 752218db..a9322841 100644 --- a/packages/web_common/src/hooks/useCommand.ts +++ b/packages/web_common/src/hooks/useCommand.ts @@ -1,5 +1,6 @@ -import type { UndefinedInitialDataOptions, UseQueryResult } from '@tanstack/react-query'; -import { useQuery } from '@tanstack/react-query'; +/* eslint-disable query/exhaustive-deps -- False */ +import type { UndefinedInitialDataOptions, UseMutationOptions, UseMutationResult, UseQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult } from '@tanstack/react-query'; +import { useMutation, useQuery, useSuspenseQuery } from '@tanstack/react-query'; // this gets overwritten by the consumer project export interface Register { @@ -10,24 +11,52 @@ type RegisterConfig = Register extends { commands: infer Keys; } ? Keys : never; -export function useCommand(cacheKey: RegisterConfig[number] | (string & {}) | false, command: () => Promise, options?: Omit, 'queryKey' | 'queryFn'>): UseQueryResult { +async function fetchCommand(command: () => Promise): Promise { + try { + const result = await command(); + return result; + } + // TODO: (lynith) handle errors better (requires modifications to TauRPC) + catch (e) { + console.error(e); + if (e instanceof Error) + return Promise.reject(e); + else + return Promise.reject(new Error('Unknown error')); + } +} + +export function useCommand( + cacheKey: RegisterConfig[number] | (string & {}) | false, + command: () => Promise, + options?: Omit, 'queryKey' | 'queryFn'>, +): UseQueryResult { return useQuery({ queryKey: cacheKey === false ? [] : [cacheKey], - queryFn: async () => { - try { - const result = await command(); - return result; - } - // TODO: (lynith) handle errors better (requires modifications to TauRPC) - catch (e) { - console.error(e); - if (e instanceof Error) - return Promise.reject(e); - else - return Promise.reject(new Error('Unknown error')); - } - }, + queryFn: () => fetchCommand(command), enabled: true, ...options, }); } + +export function useCommandSuspense( + cacheKey: RegisterConfig[number] | (string & {}) | false, + command: () => Promise, + options?: Omit, 'queryKey' | 'queryFn'>, +): UseSuspenseQueryResult { + return useSuspenseQuery({ + queryKey: cacheKey === false ? [] : [cacheKey], + queryFn: () => fetchCommand(command), + ...options, + }); +} + +export function useCommandMut( + command: () => Promise, + options?: Omit, 'mutationFn'>, +): UseMutationResult { + return useMutation({ + mutationFn: () => fetchCommand(command), + ...options, + }); +} diff --git a/packages/web_common/src/theme.css b/packages/web_common/src/theme.css index c1631c37..74ee89cc 100644 --- a/packages/web_common/src/theme.css +++ b/packages/web_common/src/theme.css @@ -3,7 +3,7 @@ @plugin "tailwindcss-animated"; @theme { - /* foreground colors */ + /** foreground colors */ --color-fg-primary: #d5dbff; --color-fg-primary-hover: #dae0ff; --color-fg-primary-pressed: #e1e5ff; @@ -19,7 +19,7 @@ --color-link-pressed: #72afff; --color-link-disabled: #7597b3; - /* background colors */ + /** background colors */ --color-brand: #2b4bff; --color-brand-hover: #2843dd; --color-brand-pressed: #3957ff; @@ -35,7 +35,7 @@ --color-page-overlay: #ffffff1a; --color-window-frame: #151b20; - /* general colors */ + /** general colors */ --color-danger: #ff4444; --color-danger-hover: #d63434; --color-danger-pressed: #ff5656; @@ -52,12 +52,12 @@ --color-code-debug: #2b4bff; --color-code-trace: #fdfdfd; - /* border */ + /** border */ --color-component-border: rgba(255, 255, 255, 0.05); --color-component-border-hover: rgba(255, 255, 255, 0.10); --color-component-border-pressed: rgba(255, 255, 255, 0.15); - /* overlay */ + /** overlay */ --color-ghost-overlay: rgba(255, 255, 255, 0.05); --color-ghost-overlay-hover: rgba(255, 255, 255, 0.10); --color-ghost-overlay-pressed: rgba(255, 255, 255, 0.15); @@ -66,11 +66,11 @@ --color-scrollbar-bg-hover: rgba(255, 255, 255, 0.10); --color-scrollbar-bg-pressed: rgba(255, 255, 255, 0.15); - /* other */ + /** other */ --font-sans: "Poppins", sans-serif; --text-xs: 0.688rem; --text-sm: 0.75rem; - --text-base: 0.875rem; + --text-base: 0.875rem; /** body text is 14px */ --text-lg: 1rem; --text-2lg: 1.125rem; --text-xl: 1.25rem; diff --git a/packages/web_common/vite.config.ts b/packages/web_common/vite.config.ts index 926b3f73..c4962b2c 100644 --- a/packages/web_common/vite.config.ts +++ b/packages/web_common/vite.config.ts @@ -25,8 +25,8 @@ export default defineConfig({ minify: false, lib: { entry: { - 'index': path.resolve(__dirname, 'src/index.ts'), - 'components': path.resolve(__dirname, 'src/components/index.ts'), + index: path.resolve(__dirname, 'src/index.ts'), + components: path.resolve(__dirname, 'src/components/index.ts'), }, formats: ['es'], fileName: (_, entryName) => `${entryName}.js`, @@ -44,6 +44,7 @@ export default defineConfig({ 'tailwindcss', 'tailwind-merge', 'tailwind-variants', + '@untitled-theme/icons-react', // 'tailwindcss-animated', // 'tailwindcss-react-aria-components', ], From 4e8b03f86b4ec9454268d1b3f5d32a8ceaf4fce9 Mon Sep 17 00:00:00 2001 From: LynithDev <61880709+LynithDev@users.noreply.github.com> Date: Tue, 17 Jun 2025 21:42:42 +0200 Subject: [PATCH 2/2] temp: cluster pages --- .../frontend/src/components/Navbar.tsx | 2 +- .../app/{test.tsx => clusters/index.tsx} | 4 +- .../src/routes/app/clusters/route.tsx | 57 +++++++++++++++++ .../frontend/src/routes/app/index.tsx | 61 +++++++++++-------- .../frontend/src/routes/app/route.tsx | 15 +++-- packages/web_common/src/theme.css | 1 + 6 files changed, 102 insertions(+), 38 deletions(-) rename apps/oneclient/frontend/src/routes/app/{test.tsx => clusters/index.tsx} (54%) create mode 100644 apps/oneclient/frontend/src/routes/app/clusters/route.tsx diff --git a/apps/oneclient/frontend/src/components/Navbar.tsx b/apps/oneclient/frontend/src/components/Navbar.tsx index 505ad7a7..74913b2c 100644 --- a/apps/oneclient/frontend/src/components/Navbar.tsx +++ b/apps/oneclient/frontend/src/components/Navbar.tsx @@ -20,7 +20,7 @@ export function Navbar() {
Home - Clusters + Clusters Accounts
diff --git a/apps/oneclient/frontend/src/routes/app/test.tsx b/apps/oneclient/frontend/src/routes/app/clusters/index.tsx similarity index 54% rename from apps/oneclient/frontend/src/routes/app/test.tsx rename to apps/oneclient/frontend/src/routes/app/clusters/index.tsx index 9f1b1495..08b49803 100644 --- a/apps/oneclient/frontend/src/routes/app/test.tsx +++ b/apps/oneclient/frontend/src/routes/app/clusters/index.tsx @@ -1,9 +1,9 @@ import { createFileRoute } from '@tanstack/react-router'; -export const Route = createFileRoute('/app/test')({ +export const Route = createFileRoute('/app/clusters/')({ component: RouteComponent, }); function RouteComponent() { - return
Hello "/app/test"!
; + return
Hello "/app/clusters/"!
; } diff --git a/apps/oneclient/frontend/src/routes/app/clusters/route.tsx b/apps/oneclient/frontend/src/routes/app/clusters/route.tsx new file mode 100644 index 00000000..66b2e11f --- /dev/null +++ b/apps/oneclient/frontend/src/routes/app/clusters/route.tsx @@ -0,0 +1,57 @@ +import { AnimatedOutlet, AnimatedOutletProvider } from '@onelauncher/common/components'; +import { createFileRoute } from '@tanstack/react-router'; + +export const Route = createFileRoute('/app/clusters')({ + component: RouteComponent, +}); + +function RouteComponent() { + return ( +
+ + + + + +
+ ); +} + +function BackgroundGradients() { + return ( +
+
+
+
+
+
+ ); +} diff --git a/apps/oneclient/frontend/src/routes/app/index.tsx b/apps/oneclient/frontend/src/routes/app/index.tsx index bce289b7..6d36a199 100644 --- a/apps/oneclient/frontend/src/routes/app/index.tsx +++ b/apps/oneclient/frontend/src/routes/app/index.tsx @@ -15,36 +15,43 @@ export const Route = createFileRoute('/app/')({ component: RouteComponent, }); +const clusters = [ + { + mc_version: '1.8.9', + }, + undefined, + { + mc_version: '1.21.4', + }, +]; + function RouteComponent() { - const { data: clusters } = useCommandSuspense>( - 'getClusters', - async () => { - await new Promise(resolve => setTimeout(resolve, 3000)); // Simulate loading delay - return bindings.core.getClusters(); - }, - { - select: ((data: Array) => { - const sorted = data.sort((a, b) => { - if (a.last_played && b.last_played) - return new Date(b.last_played).getTime() - new Date(a.last_played).getTime(); - else if (a.last_played) - return -1; // a has last_played, b does not - else if (b.last_played) - return 1; // b has last_played, a does not + // const { data: clusters } = useCommandSuspense>( + // 'getClusters', + // bindings.core.getClusters, + // { + // select: ((data: Array) => { + // const sorted = data.sort((a, b) => { + // if (a.last_played && b.last_played) + // return new Date(b.last_played).getTime() - new Date(a.last_played).getTime(); + // else if (a.last_played) + // return -1; // a has last_played, b does not + // else if (b.last_played) + // return 1; // b has last_played, a does not - const aVersion = a.mc_version.replaceAll('.', ''); - const bVersion = b.mc_version.replaceAll('.', ''); - return Number.parseInt(bVersion) - Number.parseInt(aVersion); - }); + // const aVersion = a.mc_version.replaceAll('.', ''); + // const bVersion = b.mc_version.replaceAll('.', ''); + // return Number.parseInt(bVersion) - Number.parseInt(aVersion); + // }); - return [ - sorted[0], - sorted[1], - undefined, - ]; - }) as (data: Array) => Array, - }, - ); + // return [ + // sorted[0], + // sorted[1], + // undefined, + // ]; + // }) as (data: Array) => Array, + // }, + // ); return (
diff --git a/apps/oneclient/frontend/src/routes/app/route.tsx b/apps/oneclient/frontend/src/routes/app/route.tsx index e4cf6791..269c75ad 100644 --- a/apps/oneclient/frontend/src/routes/app/route.tsx +++ b/apps/oneclient/frontend/src/routes/app/route.tsx @@ -1,7 +1,7 @@ import { LoaderSuspense, Navbar } from '@/components'; import { GameBackground } from '@/components/GameBackground'; import { AnimatedOutlet } from '@onelauncher/common/components'; -import { createFileRoute, Outlet } from '@tanstack/react-router'; +import { createFileRoute } from '@tanstack/react-router'; export const Route = createFileRoute('/app')({ component: RouteComponent, @@ -16,19 +16,18 @@ function RouteComponent() {
- {/* */} - + />
diff --git a/packages/web_common/src/theme.css b/packages/web_common/src/theme.css index 74ee89cc..f0be6864 100644 --- a/packages/web_common/src/theme.css +++ b/packages/web_common/src/theme.css @@ -83,6 +83,7 @@ * { user-select: none !important; -webkit-user-select: none !important; + -webkit-user-drag: none !important; cursor: default !important; }