From 9eadef559c30cbbac209f72c0982151ef42410c9 Mon Sep 17 00:00:00 2001 From: LynithDev <61880709+LynithDev@users.noreply.github.com> Date: Fri, 6 Jun 2025 13:41:04 +0200 Subject: [PATCH] chore: created a common package for frontend code --- .vscode/settings.json | 5 +- apps/oneclient/frontend/.gitignore | 2 + apps/oneclient/frontend/src/bindings.gen.ts | 6 +- apps/oneclient/frontend/src/routes/index.tsx | 2 +- apps/onelauncher/frontend/.gitignore | 2 + apps/onelauncher/frontend/src/bindings.gen.ts | 4 +- .../frontend/src/components/Navbar.tsx | 6 +- .../frontend/src/components/SettingsRow.tsx | 60 +++++++------- .../src/components/content/LauncherIcon.tsx | 6 +- .../src/components/launcher/LoaderIcon.tsx | 22 +++-- .../frontend/src/components/overlay/Modal.tsx | 22 ++--- .../overlay/popups/AccountPopup.tsx | 15 ++-- .../frontend/src/hooks/useCluster.ts | 4 +- .../frontend/src/routes/app/browser/index.tsx | 2 +- .../frontend/src/routes/app/cluster/index.tsx | 35 ++++---- .../frontend/src/routes/app/cluster/route.tsx | 82 +++++++++---------- .../src/routes/app/cluster/screenshots.tsx | 79 +++++++++--------- .../src/routes/app/cluster/settings.tsx | 50 ++++++----- .../src/routes/app/cluster/worlds.tsx | 30 +++---- .../frontend/src/routes/app/index.tsx | 34 +++++--- .../src/routes/app/settings/accounts.tsx | 10 +-- .../src/routes/app/settings/appearance.tsx | 7 +- .../src/routes/app/settings/index.tsx | 2 +- .../src/routes/app/settings/minecraft.tsx | 4 +- .../src/routes/app/settings/route.tsx | 3 +- .../src/routes/onboarding/complete.tsx | 8 +- .../frontend/src/routes/onboarding/index.tsx | 26 +++--- .../frontend/src/routes/onboarding/login.tsx | 2 +- .../frontend/src/routes/onboarding/route.tsx | 15 ++-- .../frontend/src/types/global.d.ts | 10 ++- apps/onelauncher/frontend/tsconfig.json | 2 +- eslint.config.js | 7 +- packages/core/src/api/tauri/commands.rs | 26 +++++- .../src/components/AnimatedOutlet.tsx | 3 +- packages/web_common/src/hooks/useCommand.ts | 15 ++-- packages/web_common/src/index.ts | 1 + 36 files changed, 336 insertions(+), 273 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index b7be1aee..e539bbb3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,8 +4,7 @@ }, "files.readonlyInclude": { "**/node_modules/**": true, - "**/routeTree.gen.ts": true, - "**/bindings.gen.ts": true + "**/*.gen.ts": true }, "files.watcherExclude": { "**/_build": true, @@ -21,7 +20,7 @@ "**/.rustup": true, "**/.cargo": true, "**/.crates": true, - "**/routeTree.gen.ts": true + "**/*.gen.ts": true }, "rust-analyzer.procMacro.enable": true, "rust-analyzer.procMacro.attributes.enable": true, diff --git a/apps/oneclient/frontend/.gitignore b/apps/oneclient/frontend/.gitignore index d451ff16..d195a4a0 100644 --- a/apps/oneclient/frontend/.gitignore +++ b/apps/oneclient/frontend/.gitignore @@ -3,3 +3,5 @@ node_modules dist dist-ssr *.local + +*.gen.ts diff --git a/apps/oneclient/frontend/src/bindings.gen.ts b/apps/oneclient/frontend/src/bindings.gen.ts index 6b4f2cd0..88ad8162 100644 --- a/apps/oneclient/frontend/src/bindings.gen.ts +++ b/apps/oneclient/frontend/src/bindings.gen.ts @@ -103,11 +103,11 @@ export interface SettingProfileModel { name: string; java_id: bigint | null; res export interface SettingsOsExtra { enable_gamemode: boolean | null } -const ARGS_MAP = { 'core': '{"get_cluster":["id"],"remove_cluster":["id"],"get_profile_or_default":["name"],"get_clusters":[],"remove_user":["uuid"],"get_global_profile":[],"get_users":[],"get_default_user":["fallback"],"create_cluster":["options"],"open_msa_login":[],"get_user":["uuid"],"set_default_user":["uuid"]}', 'oneclient': '{"open_dev_tools":[],"return_error":[]}', '': '{"send_event":["event"]}' }; +const ARGS_MAP = { 'core': '{"openMsaLogin":[],"getClusters":[],"getClusterById":["id"],"getUsers":[],"removeUser":["uuid"],"removeCluster":["id"],"getGlobalProfile":[],"getUser":["uuid"],"setDefaultUser":["uuid"],"createCluster":["options"],"getDefaultUser":["fallback"],"getProfileOrDefault":["name"]}', 'oneclient': '{"return_error":[],"open_dev_tools":[]}', '': '{"send_event":["event"]}' }; export interface Router { - 'core': { get_clusters: () => Promise>; get_cluster: (id: bigint) => Promise; remove_cluster: (id: bigint) => Promise; create_cluster: (options: CreateCluster) => Promise; get_profile_or_default: (name: string | null) => Promise; get_global_profile: () => Promise; get_users: () => Promise>; get_user: (uuid: string) => Promise; remove_user: (uuid: string) => Promise; get_default_user: (fallback: boolean | null) => Promise; set_default_user: (uuid: string | null) => Promise; open_msa_login: () => Promise }; - 'oneclient': { return_error: () => Promise; open_dev_tools: () => Promise }; '': { send_event: (event: LauncherEvent) => Promise }; + 'core': { getClusters: () => Promise>; getClusterById: (id: bigint) => Promise; removeCluster: (id: bigint) => Promise; createCluster: (options: CreateCluster) => Promise; getProfileOrDefault: (name: string | null) => Promise; getGlobalProfile: () => Promise; getUsers: () => Promise>; getUser: (uuid: string) => Promise; removeUser: (uuid: string) => Promise; getDefaultUser: (fallback: boolean | null) => Promise; setDefaultUser: (uuid: string | null) => Promise; openMsaLogin: () => Promise }; + 'oneclient': { return_error: () => Promise; open_dev_tools: () => Promise }; } export type { InferCommandOutput }; diff --git a/apps/oneclient/frontend/src/routes/index.tsx b/apps/oneclient/frontend/src/routes/index.tsx index 90519972..06960add 100644 --- a/apps/oneclient/frontend/src/routes/index.tsx +++ b/apps/oneclient/frontend/src/routes/index.tsx @@ -1,5 +1,5 @@ +import { Button } from '@onelauncher/common/components'; import { createFileRoute } from '@tanstack/react-router'; -import { Button } from "@onelauncher/common/components"; export const Route = createFileRoute('/')({ component: App, diff --git a/apps/onelauncher/frontend/.gitignore b/apps/onelauncher/frontend/.gitignore index d451ff16..d195a4a0 100644 --- a/apps/onelauncher/frontend/.gitignore +++ b/apps/onelauncher/frontend/.gitignore @@ -3,3 +3,5 @@ node_modules dist dist-ssr *.local + +*.gen.ts diff --git a/apps/onelauncher/frontend/src/bindings.gen.ts b/apps/onelauncher/frontend/src/bindings.gen.ts index 9b6eccee..6da474ae 100644 --- a/apps/onelauncher/frontend/src/bindings.gen.ts +++ b/apps/onelauncher/frontend/src/bindings.gen.ts @@ -103,11 +103,11 @@ export interface SettingProfileModel { name: string; java_id: bigint | null; res export interface SettingsOsExtra { enable_gamemode: boolean | null } -const ARGS_MAP = { '': '{"send_event":["event"]}', 'onelauncher': '{"return_error":[],"open_dev_tools":[]}', 'core': '{"get_user":["uuid"],"get_default_user":["fallback"],"set_default_user":["uuid"],"get_global_profile":[],"get_clusters":[],"remove_cluster":["id"],"get_profile_or_default":["name"],"get_users":[],"remove_user":["uuid"],"open_msa_login":[],"create_cluster":["options"],"get_cluster":["id"]}' }; +const ARGS_MAP = { 'core': '{"getGlobalProfile":[],"getUsers":[],"removeUser":["uuid"],"getDefaultUser":["fallback"],"getUser":["uuid"],"getClusterById":["id"],"setDefaultUser":["uuid"],"openMsaLogin":[],"removeCluster":["id"],"getProfileOrDefault":["name"],"getClusters":[],"createCluster":["options"]}', 'onelauncher': '{"open_dev_tools":[],"return_error":[]}', '': '{"send_event":["event"]}' }; export interface Router { 'onelauncher': { return_error: () => Promise; open_dev_tools: () => Promise }; - 'core': { get_clusters: () => Promise>; get_cluster: (id: bigint) => Promise; remove_cluster: (id: bigint) => Promise; create_cluster: (options: CreateCluster) => Promise; get_profile_or_default: (name: string | null) => Promise; get_global_profile: () => Promise; get_users: () => Promise>; get_user: (uuid: string) => Promise; remove_user: (uuid: string) => Promise; get_default_user: (fallback: boolean | null) => Promise; set_default_user: (uuid: string | null) => Promise; open_msa_login: () => Promise }; '': { send_event: (event: LauncherEvent) => Promise }; + 'core': { getClusters: () => Promise>; getClusterById: (id: bigint) => Promise; removeCluster: (id: bigint) => Promise; createCluster: (options: CreateCluster) => Promise; getProfileOrDefault: (name: string | null) => Promise; getGlobalProfile: () => Promise; getUsers: () => Promise>; getUser: (uuid: string) => Promise; removeUser: (uuid: string) => Promise; getDefaultUser: (fallback: boolean | null) => Promise; setDefaultUser: (uuid: string | null) => Promise; openMsaLogin: () => Promise }; } export type { InferCommandOutput }; diff --git a/apps/onelauncher/frontend/src/components/Navbar.tsx b/apps/onelauncher/frontend/src/components/Navbar.tsx index d37dc4ca..f84e01f6 100644 --- a/apps/onelauncher/frontend/src/components/Navbar.tsx +++ b/apps/onelauncher/frontend/src/components/Navbar.tsx @@ -1,15 +1,15 @@ import type { ToOptions } from '@tanstack/react-router'; -import {useCommand} from '@onelauncher/common'; import { bindings } from '@/main'; +import { useCommand } from '@onelauncher/common'; +import { Button, Menu } from '@onelauncher/common/components'; import { Link } from '@tanstack/react-router'; import { Bell01Icon, Cloud01Icon, TerminalBrowserIcon } from '@untitled-theme/icons-react'; import { MenuTrigger } from 'react-aria-components'; -import { Button, Menu } from '@onelauncher/common/components'; import PlayerHead from './content/PlayerHead'; import AccountPopup from './overlay/popups/AccountPopup'; function Navbar() { - const defaultUser = useCommand('getDefaultUser', () => bindings.core.get_default_user(false)); + const defaultUser = useCommand('getDefaultUser', () => bindings.core.getDefaultUser(false)); return (
diff --git a/apps/onelauncher/frontend/src/components/SettingsRow.tsx b/apps/onelauncher/frontend/src/components/SettingsRow.tsx index b5cd826a..ce336cae 100644 --- a/apps/onelauncher/frontend/src/components/SettingsRow.tsx +++ b/apps/onelauncher/frontend/src/components/SettingsRow.tsx @@ -1,45 +1,45 @@ -import type { JSX } from "react"; +import type { JSX } from 'react'; -export type SettingsRowProps = { - title: JSX.Element | string; - description: JSX.Element | string; - icon: JSX.Element; - disabled?: boolean; - children?: JSX.Element; -}; +export interface SettingsRowProps { + title: JSX.Element | string; + description: JSX.Element | string; + icon: JSX.Element; + disabled?: boolean; + children?: JSX.Element; +} -function SettingsRow(props: SettingsRowProps) { - return ( -
-
- {props.icon} -
+ > +
+ {icon} +
-
-

{props.title}

-

{props.description}

-
+
+

{title}

+

{description}

+
-
- {props.children} -
-
- ); +
+ {children} +
+
+ ); } interface SettingsRowHeaderProps { - className?: string; - children?: React.ReactNode; + className?: string; + children?: React.ReactNode; } SettingsRow.Header = ({ className, children }: SettingsRowHeaderProps) => { - const headerClasses = `mt-4 mb-1 ml-2 text-md text-fg-secondary uppercase ${className || ''}`; - return

{children}

; + const headerClasses = `mt-4 mb-1 ml-2 text-md text-fg-secondary uppercase ${className || ''}`; + return

{children}

; }; export default SettingsRow; diff --git a/apps/onelauncher/frontend/src/components/content/LauncherIcon.tsx b/apps/onelauncher/frontend/src/components/content/LauncherIcon.tsx index 1acae0c1..5536ab92 100644 --- a/apps/onelauncher/frontend/src/components/content/LauncherIcon.tsx +++ b/apps/onelauncher/frontend/src/components/content/LauncherIcon.tsx @@ -1,4 +1,5 @@ import type { ImgHTMLAttributes, JSX } from 'react'; +import { Show } from '@onelauncher/common/components'; import CurseforgeIcon from '../../assets/logos/curseforge.svg'; import AtLauncherIcon from '../../assets/logos/launchers/atlauncher.svg'; import FTBIcon from '../../assets/logos/launchers/ftb.svg'; @@ -9,7 +10,6 @@ import TechnicImage from '../../assets/logos/launchers/technic.png'; import TLauncherImage from '../../assets/logos/launchers/tlauncher.png'; import UnknownImage from '../../assets/logos/minecraft.png'; import ModrinthIcon from '../../assets/logos/modrinth.svg'; -import { Show } from '../base/Show'; type ElementType = (props: any) => JSX.Element; @@ -45,8 +45,8 @@ type LauncherIconProps = ImgHTMLAttributes & { }; function LauncherIcon({ - launcher, - ...props + launcher, + ...props }: LauncherIconProps) { return ( = { vanilla: VanillaImage, @@ -21,17 +21,21 @@ export function getLoaderLogoSrc(loader: Model | GameLoader): string { return mapping[loaderName]; } -type LoaderIconProp = RefAttributes & { +type LoaderIconProp = ImgHTMLAttributes & RefAttributes & { loader: GameLoader | undefined; - className?: string; }; -function LoaderIcon(props: LoaderIconProp) { +function LoaderIcon({ + loader, + src: _src, + alt: _alt, + ...rest +}: LoaderIconProp) { return ( {`${props.loader}'s ); } diff --git a/apps/onelauncher/frontend/src/components/overlay/Modal.tsx b/apps/onelauncher/frontend/src/components/overlay/Modal.tsx index 728cd4da..cc32aa79 100644 --- a/apps/onelauncher/frontend/src/components/overlay/Modal.tsx +++ b/apps/onelauncher/frontend/src/components/overlay/Modal.tsx @@ -1,19 +1,19 @@ -import type { ClassNameString } from '@/types/global'; -import { - Dialog as AriaDialog, - DialogTrigger, - Modal as ModalOverlay -} from 'react-aria-components'; +import type { ClassNameString } from '@onelauncher/common'; import type { DialogProps } from 'react-aria-components'; +import { + Dialog as AriaDialog, + DialogTrigger, + Modal as ModalOverlay, +} from 'react-aria-components'; interface ModalProps extends DialogProps, ClassNameString { } function Modal({ className, ...props }: ModalProps) { - return ( - - - - ); + return ( + + + + ); } Modal.Trigger = DialogTrigger; diff --git a/apps/onelauncher/frontend/src/components/overlay/popups/AccountPopup.tsx b/apps/onelauncher/frontend/src/components/overlay/popups/AccountPopup.tsx index 7af01da0..8caaafc3 100644 --- a/apps/onelauncher/frontend/src/components/overlay/popups/AccountPopup.tsx +++ b/apps/onelauncher/frontend/src/components/overlay/popups/AccountPopup.tsx @@ -1,17 +1,18 @@ +import type { MinecraftCredentials } from '@/bindings.gen'; import PlayerHead from '@/components/content/PlayerHead'; -import {useCommand} from '@onelauncher/common'; -import { Button, Menu } from '@onelauncher/common/components'; import { bindings } from '@/main'; +import { useCommand } from '@onelauncher/common'; +import { Button, Menu } from '@onelauncher/common/components'; import { PlusIcon, Settings01Icon } from '@untitled-theme/icons-react'; import { Separator } from 'react-aria-components'; import { twMerge } from 'tailwind-merge'; function AccountPopup() { - const users = useCommand('getUsers', bindings.commands.getUsers); - const defaultUser = useCommand('getDefaultUser', () => bindings.commands.getDefaultUser(false)); + const users = useCommand('getUsers', bindings.core.getUsers); + const defaultUser = useCommand('getDefaultUser', () => bindings.core.getDefaultUser(false)); - const setDefaultUser = (user: bindings.MinecraftCredentials) => { - bindings.commands.setDefaultUser(user.id); + const setDefaultUser = (user: MinecraftCredentials) => { + bindings.core.setDefaultUser(user.id); }; return ( @@ -64,7 +65,7 @@ function AccountEntry({ loggedIn = false, }: { onClick: () => void; - user: bindings.MinecraftCredentials; + user: MinecraftCredentials; loggedIn?: boolean; }) { return ( diff --git a/apps/onelauncher/frontend/src/hooks/useCluster.ts b/apps/onelauncher/frontend/src/hooks/useCluster.ts index 634b1346..eb8e44e7 100644 --- a/apps/onelauncher/frontend/src/hooks/useCluster.ts +++ b/apps/onelauncher/frontend/src/hooks/useCluster.ts @@ -1,10 +1,10 @@ import type { Model } from '@/bindings.gen'; import { bindings } from '@/main'; +import { useCommand } from '@onelauncher/common'; import { useEffect, useState } from 'react'; -import useCommand from './useCommand'; function useRecentCluster() { - const result = useCommand('getClusters', bindings.core.get_clusters); + const result = useCommand('getClusters', bindings.core.getClusters); const [cluster, setCluster] = useState(); useEffect(() => { diff --git a/apps/onelauncher/frontend/src/routes/app/browser/index.tsx b/apps/onelauncher/frontend/src/routes/app/browser/index.tsx index d5a45078..19fb84ef 100644 --- a/apps/onelauncher/frontend/src/routes/app/browser/index.tsx +++ b/apps/onelauncher/frontend/src/routes/app/browser/index.tsx @@ -1,5 +1,5 @@ -import { Button, TextField } from '@onelauncher/common/components'; import Modal from '@/components/overlay/Modal'; +import { Button, TextField } from '@onelauncher/common/components'; import { createFileRoute } from '@tanstack/react-router'; export const Route = createFileRoute('/app/browser/')({ diff --git a/apps/onelauncher/frontend/src/routes/app/cluster/index.tsx b/apps/onelauncher/frontend/src/routes/app/cluster/index.tsx index efe0e46e..cfeadd8b 100644 --- a/apps/onelauncher/frontend/src/routes/app/cluster/index.tsx +++ b/apps/onelauncher/frontend/src/routes/app/cluster/index.tsx @@ -3,12 +3,13 @@ import type { Dispatch, SetStateAction } from 'react'; import LoaderIcon from '@/components/launcher/LoaderIcon'; import ScrollableContainer from '@/components/ScrollableContainer'; import SettingsRow from '@/components/SettingsRow'; -import useCommand from '@/hooks/useCommand'; import { bindings } from '@/main'; +import { useCommand } from '@onelauncher/common'; import { Button, Show, TextField } from '@onelauncher/common/components'; import { createFileRoute } from '@tanstack/react-router'; import { Edit02Icon, FolderIcon, ImagePlusIcon, Share07Icon, Tool02Icon, Trash01Icon } from '@untitled-theme/icons-react'; import { useState } from 'react'; +import { twMerge } from 'tailwind-merge'; import Sidebar from '../settings/route'; export const Route = createFileRoute('/app/cluster/')({ @@ -21,7 +22,7 @@ function RouteComponent() { const [newName, setNewName] = useState(''); // dumbass fix ik - const cluster = useCommand('getClusterById', () => bindings.commands.getClusterById(Number(id.toString()) as unknown as bigint)); + const cluster = useCommand('getClusterById', () => bindings.core.getClusterById(Number(id.toString()) as unknown as bigint)); return ( @@ -102,7 +103,11 @@ interface BannerProps { refetch: () => void; } -function Banner(props: BannerProps) { +function Banner({ + cluster, + editMode, + setNewName, +}: BannerProps) { // async function launchFilePicker() { // const selected = await dialog.open({ // multiple: false, @@ -123,13 +128,13 @@ function Banner(props: BannerProps) { if (name.length > 30 || name.length <= 0) return; - props.setNewName(name); + setNewName(name); } return (
- +
{props.cluster?.name} +

{cluster?.name}

} - when={props.editMode} + when={editMode} > updateName(e.target.value)} - placeholder={props.cluster?.name} + placeholder={cluster?.name} />
- {props.cluster?.mc_version} - {props.cluster?.mc_loader || 'unknown'} - {props.cluster?.mc_loader_version && {props.cluster.mc_loader_version}} + {cluster?.mc_version} + {cluster?.mc_loader || 'unknown'} + {cluster?.mc_loader_version && {cluster.mc_loader_version}} Played for {' '} - {props.cluster?.overall_played || 0} + {cluster?.overall_played || 0} .
diff --git a/apps/onelauncher/frontend/src/routes/app/cluster/route.tsx b/apps/onelauncher/frontend/src/routes/app/cluster/route.tsx index 9a5c0515..3596750c 100644 --- a/apps/onelauncher/frontend/src/routes/app/cluster/route.tsx +++ b/apps/onelauncher/frontend/src/routes/app/cluster/route.tsx @@ -1,52 +1,52 @@ -import { createFileRoute, Outlet } from '@tanstack/react-router' -import Sidebar from '../settings/route' -import { EyeIcon, File06Icon, Globe04Icon, Image03Icon, PackagePlusIcon, Settings04Icon } from '@untitled-theme/icons-react' -import useCommand from '@/hooks/useCommand' -import { bindings } from '@/main' +import { bindings } from '@/main'; +import { useCommand } from '@onelauncher/common'; +import { createFileRoute, Outlet } from '@tanstack/react-router'; +import { EyeIcon, File06Icon, Globe04Icon, Image03Icon, PackagePlusIcon, Settings04Icon } from '@untitled-theme/icons-react'; +import Sidebar from '../settings/route'; -type ClusterSearch = { - id: bigint +interface ClusterSearch { + id: bigint; } export const Route = createFileRoute('/app/cluster')({ - component: RouteComponent, - validateSearch: (search: Record): ClusterSearch => { - return { - id: BigInt(search.id as string), - } - }, -}) + component: RouteComponent, + validateSearch: (search: Record): ClusterSearch => { + return { + id: BigInt(search.id as string), + }; + }, +}); function RouteComponent() { - const { id } = Route.useSearch() + const { id } = Route.useSearch(); - const cluster = useCommand("getClusterById", () => bindings.commands.getClusterById(Number(id.toString()) as unknown as bigint)) + const cluster = useCommand('getClusterById', () => bindings.core.getClusterById(Number(id.toString()) as unknown as bigint)); - const isModded = cluster.data?.mc_loader != "vanilla" + const isModded = cluster.data?.mc_loader != 'vanilla'; - return ( -
-
- , 'Overview', '/?id=' + id], - (isModded ? [, 'Mods', '/mods?id=' + id] : undefined), - [, 'Screenshots', '/screenshots?id=' + id], - [, 'Worlds', '/worlds?id=' + id], - [, 'Logs', '/logs?id=' + id], - [, 'Game Settings', '/settings?id=' + id], - ], - }} - /> - {/* */} -
+ return ( +
+
+ , 'Overview', `/?id=${id}`], + (isModded ? [, 'Mods', `/mods?id=${id}`] : undefined), + [, 'Screenshots', `/screenshots?id=${id}`], + [, 'Worlds', `/worlds?id=${id}`], + [, 'Logs', `/logs?id=${id}`], + [, 'Game Settings', `/settings?id=${id}`], + ], + }} + /> + {/* */} +
-
- -
-
- ) +
+ +
+
+ ); } diff --git a/apps/onelauncher/frontend/src/routes/app/cluster/screenshots.tsx b/apps/onelauncher/frontend/src/routes/app/cluster/screenshots.tsx index b1da46fc..9353c645 100644 --- a/apps/onelauncher/frontend/src/routes/app/cluster/screenshots.tsx +++ b/apps/onelauncher/frontend/src/routes/app/cluster/screenshots.tsx @@ -1,46 +1,51 @@ -import { createFileRoute } from '@tanstack/react-router' -import Sidebar from '../settings/route'; import ScrollableContainer from '@/components/ScrollableContainer'; -import { Show } from '@/components/base/Show'; +import { Show } from '@onelauncher/common/components'; +import { createFileRoute } from '@tanstack/react-router'; +import Sidebar from '../settings/route'; export const Route = createFileRoute('/app/cluster/screenshots')({ - component: RouteComponent, -}) + component: RouteComponent, +}); function RouteComponent() { - const arr = [1, 2, 3, 4, 5, 6] - return ( - -

Screenshots

- -
- No screenshots found. Press F2 in game to take a screenshot!
} - when={true} - > -
- {arr.map((data) => ( - - ))} -
- -
- - - ) + const arr = [1, 2, 3, 4, 5, 6]; + return ( + +

Screenshots

+ +
+ No screenshots found. Press F2 in game to take a screenshot!
} + when + > +
+ {arr.map(data => ( + + ))} +
+
+
+ + + ); } -function ScreenshotEntry(props: { path: string; cluster_path: string }) { - function onClick() { - //screen shot viewer overlay - } +function ScreenshotEntry({ + path, +}: { + path: string; + cluster_path: string; +}) { + function onClick() { + // screen shot viewer overlay + } - return ( -
- {props.path} -
- ); + return ( +
+ {path} +
+ ); } diff --git a/apps/onelauncher/frontend/src/routes/app/cluster/settings.tsx b/apps/onelauncher/frontend/src/routes/app/cluster/settings.tsx index dabbeaa3..82b98d12 100644 --- a/apps/onelauncher/frontend/src/routes/app/cluster/settings.tsx +++ b/apps/onelauncher/frontend/src/routes/app/cluster/settings.tsx @@ -1,35 +1,33 @@ -import { createFileRoute } from '@tanstack/react-router' -import Sidebar from '../settings/route' -import ScrollableContainer from '@/components/ScrollableContainer' -import useCommand from '@/hooks/useCommand' -import { bindings } from '@/main' -import { GameSettings, ProcessSettings } from '../settings/minecraft' +import ScrollableContainer from '@/components/ScrollableContainer'; +import { bindings } from '@/main'; +import { useCommand } from '@onelauncher/common'; +import { createFileRoute } from '@tanstack/react-router'; +import { GameSettings, ProcessSettings } from '../settings/minecraft'; +import Sidebar from '../settings/route'; export const Route = createFileRoute('/app/cluster/settings')({ - component: RouteComponent, -}) + component: RouteComponent, +}); function RouteComponent() { - const { id } = Route.useSearch() + const { id } = Route.useSearch(); - const cluster = useCommand("getClusterById", () => bindings.commands.getClusterById(Number(id.toString()) as unknown as bigint)) - const result = useCommand("getProfileOrDefault", () => bindings.commands.getProfileOrDefault(cluster.data?.name as string), { - enabled: !!cluster.data?.name - }) + const cluster = useCommand('getClusterById', () => bindings.core.getClusterById(Number(id.toString()) as unknown as bigint)); + const result = useCommand('getProfileOrDefault', () => bindings.core.getProfileOrDefault(cluster.data?.name as string), { + enabled: !!cluster.data?.name, + }); - console.log(result.data) + return ( + + +
+

Minecraft Settings

- return ( - - -
-

Minecraft Settings

+ - - - -
-
-
- ) + +
+
+
+ ); } diff --git a/apps/onelauncher/frontend/src/routes/app/cluster/worlds.tsx b/apps/onelauncher/frontend/src/routes/app/cluster/worlds.tsx index df186f95..c1ea46be 100644 --- a/apps/onelauncher/frontend/src/routes/app/cluster/worlds.tsx +++ b/apps/onelauncher/frontend/src/routes/app/cluster/worlds.tsx @@ -1,20 +1,20 @@ -import { createFileRoute } from '@tanstack/react-router' -import Sidebar from '../settings/route' -import ScrollableContainer from '@/components/ScrollableContainer' +import ScrollableContainer from '@/components/ScrollableContainer'; +import { createFileRoute } from '@tanstack/react-router'; +import Sidebar from '../settings/route'; export const Route = createFileRoute('/app/cluster/worlds')({ - component: RouteComponent, -}) + component: RouteComponent, +}); function RouteComponent() { - return ( - -

Worlds

- -
- -
-
-
- ) + return ( + +

Worlds

+ +
+ +
+
+
+ ); } diff --git a/apps/onelauncher/frontend/src/routes/app/index.tsx b/apps/onelauncher/frontend/src/routes/app/index.tsx index 2f18576c..b46af92d 100644 --- a/apps/onelauncher/frontend/src/routes/app/index.tsx +++ b/apps/onelauncher/frontend/src/routes/app/index.tsx @@ -6,7 +6,7 @@ import Modal from '@/components/overlay/Modal'; import { bindings } from '@/main'; import { useCommand } from '@onelauncher/common'; import { Button, TextField } from '@onelauncher/common/components'; -import { createFileRoute, Link, useNavigate } from '@tanstack/react-router'; +import { createFileRoute, Link } from '@tanstack/react-router'; import { Server01Icon } from '@untitled-theme/icons-react'; import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'; @@ -19,7 +19,7 @@ Please note this route has a very big issue related to scrolling and i am very angry rn so i will not be fixing it rn */ function RouteComponent() { - const result = useCommand('getClusters', bindings.core.get_clusters); + const result = useCommand('getClusters', bindings.core.getClusters); return (
@@ -49,7 +49,7 @@ function Banner() { */ // const cluster = useRecentCluster(); // const launch = useLaunchCluster(() => cluster()?.uuid); - const navigate = useNavigate(); + // const navigate = useNavigate(); return (
@@ -110,8 +110,8 @@ function Banner() { } function ClusterCreate() { - const result = useCommand('createCluster', () => bindings.commands.createCluster({ - icon_url: 'asd', + const result = useCommand('createCluster', () => bindings.core.createCluster({ + icon: 'asd', mc_loader: 'vanilla', mc_version: '1.20.1', name: 'Test Cluster', @@ -177,8 +177,11 @@ interface ClusterGroupProps { isFetching?: boolean; } -function ClusterGroup(props: ClusterGroupProps) { - if (props.isFetching) +function ClusterGroup({ + isFetching, + clusters, +}: ClusterGroupProps) { + if (isFetching) return (
@@ -191,7 +194,7 @@ function ClusterGroup(props: ClusterGroupProps) { className="h-full w-full" >
- {props.clusters?.map(data => ( + {clusters?.map(data => ( ))}
@@ -200,11 +203,16 @@ function ClusterGroup(props: ClusterGroupProps) { ); } -function ClusterCard(props: Model) { +function ClusterCard({ + id, + name, + mc_loader, + mc_version, +}: Model) { return (
-

{props.name}

+

{name}

- {props.mc_loader} + {mc_loader} {' '} - {props.mc_version} + {mc_version} {/* {' '} {props.packages.mods && `• ${props.mods} mods`} */}

diff --git a/apps/onelauncher/frontend/src/routes/app/settings/accounts.tsx b/apps/onelauncher/frontend/src/routes/app/settings/accounts.tsx index 5cb86bcf..21056bd4 100644 --- a/apps/onelauncher/frontend/src/routes/app/settings/accounts.tsx +++ b/apps/onelauncher/frontend/src/routes/app/settings/accounts.tsx @@ -1,7 +1,7 @@ import PlayerHead from '@/components/content/PlayerHead'; import ScrollableContainer from '@/components/ScrollableContainer'; -import useCommand from '@/hooks/useCommand'; import { bindings } from '@/main'; +import { useCommand } from '@onelauncher/common'; import { Button, Show, Tooltip } from '@onelauncher/common/components'; import { createFileRoute } from '@tanstack/react-router'; import { InfoCircleIcon, Trash01Icon, UserPlus02Icon } from '@untitled-theme/icons-react'; @@ -18,8 +18,8 @@ interface Account { } function RouteComponent() { - const { data: usersData, isLoading: usersLoading } = useCommand('getUsers', bindings.commands.getUsers); - const { data: defaultUserData, isLoading: defaultUserLoading } = useCommand('getDefaultUser', () => bindings.commands.getDefaultUser(false)); + const { data: usersData, isLoading: usersLoading } = useCommand('getUsers', bindings.core.getUsers); + const { data: defaultUserData, isLoading: defaultUserLoading } = useCommand('getDefaultUser', () => bindings.core.getDefaultUser(false)); if (usersLoading || defaultUserLoading) return ( @@ -67,7 +67,7 @@ function AccountRow({ account, isCurrent }: AccountRowProps) { const setDefaultUserCommand = useCommand( 'setDefaultUser', - () => bindings.commands.setDefaultUser(account.id), + () => bindings.core.setDefaultUser(account.id), { enabled: false, subscribed: false, @@ -76,7 +76,7 @@ function AccountRow({ account, isCurrent }: AccountRowProps) { const removeUserCommand = useCommand( 'removeUser', - () => bindings.commands.removeUser(account.id), + () => bindings.core.removeUser(account.id), { enabled: false, subscribed: false, diff --git a/apps/onelauncher/frontend/src/routes/app/settings/appearance.tsx b/apps/onelauncher/frontend/src/routes/app/settings/appearance.tsx index e3ad63ed..784ee6f1 100644 --- a/apps/onelauncher/frontend/src/routes/app/settings/appearance.tsx +++ b/apps/onelauncher/frontend/src/routes/app/settings/appearance.tsx @@ -77,9 +77,12 @@ interface ThemeCardProps { setTheme: (merged: string) => void; }; -function ThemeCard(props: ThemeCardProps) { +function ThemeCard({ + themeSelector, + setTheme, +}: ThemeCardProps) { return ( -
props.setTheme(props.themeSelector)}> +
setTheme(themeSelector)}> diff --git a/apps/onelauncher/frontend/src/routes/app/settings/minecraft.tsx b/apps/onelauncher/frontend/src/routes/app/settings/minecraft.tsx index 5ee5bef8..9e4e1e8e 100644 --- a/apps/onelauncher/frontend/src/routes/app/settings/minecraft.tsx +++ b/apps/onelauncher/frontend/src/routes/app/settings/minecraft.tsx @@ -1,8 +1,8 @@ import ScrollableContainer from '@/components/ScrollableContainer'; import SettingsRow from '@/components/SettingsRow'; -import { Switch, TextField, ToggleButton } from '@onelauncher/common/components'; +import { Switch, TextField } from '@onelauncher/common/components'; import { createFileRoute } from '@tanstack/react-router'; -import { Database01Icon, EyeIcon, FilePlus02Icon, FileX02Icon, LayoutTopIcon, Maximize01Icon, ParagraphWrapIcon, XIcon } from '@untitled-theme/icons-react'; +import { Database01Icon, FilePlus02Icon, FileX02Icon, LayoutTopIcon, Maximize01Icon, ParagraphWrapIcon, XIcon } from '@untitled-theme/icons-react'; import Sidebar from './route'; export const Route = createFileRoute('/app/settings/minecraft')({ diff --git a/apps/onelauncher/frontend/src/routes/app/settings/route.tsx b/apps/onelauncher/frontend/src/routes/app/settings/route.tsx index 3db5530e..48d9c438 100644 --- a/apps/onelauncher/frontend/src/routes/app/settings/route.tsx +++ b/apps/onelauncher/frontend/src/routes/app/settings/route.tsx @@ -100,8 +100,7 @@ function Sidebar(props: SidebarProps) {
- ), - )} + ))}
); } diff --git a/apps/onelauncher/frontend/src/routes/onboarding/complete.tsx b/apps/onelauncher/frontend/src/routes/onboarding/complete.tsx index 264e3687..1ce8de61 100644 --- a/apps/onelauncher/frontend/src/routes/onboarding/complete.tsx +++ b/apps/onelauncher/frontend/src/routes/onboarding/complete.tsx @@ -1,9 +1,9 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from '@tanstack/react-router'; export const Route = createFileRoute('/onboarding/complete')({ - component: RouteComponent, -}) + component: RouteComponent, +}); function RouteComponent() { - return
Hello "/onboarding/complete"!
+ return
Hello "/onboarding/complete"!
; } diff --git a/apps/onelauncher/frontend/src/routes/onboarding/index.tsx b/apps/onelauncher/frontend/src/routes/onboarding/index.tsx index e600c137..88ec7cf2 100644 --- a/apps/onelauncher/frontend/src/routes/onboarding/index.tsx +++ b/apps/onelauncher/frontend/src/routes/onboarding/index.tsx @@ -1,19 +1,19 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from '@tanstack/react-router'; export const Route = createFileRoute('/onboarding/')({ - component: RouteComponent, -}) + component: RouteComponent, +}); function RouteComponent() { - return ( -
-

- Welcome to - {' '} - OneLauncher -

+ return ( +
+

+ Welcome to + {' '} + OneLauncher +

-

A powerful yet easy to use launcher for Minecraft.

-
- ) +

A powerful yet easy to use launcher for Minecraft.

+
+ ); } diff --git a/apps/onelauncher/frontend/src/routes/onboarding/login.tsx b/apps/onelauncher/frontend/src/routes/onboarding/login.tsx index 54604a14..1e1d96fc 100644 --- a/apps/onelauncher/frontend/src/routes/onboarding/login.tsx +++ b/apps/onelauncher/frontend/src/routes/onboarding/login.tsx @@ -13,7 +13,7 @@ export const Route = createFileRoute('/onboarding/login')({ function RouteComponent() { const [profile, setProfile] = useState(); const [errorMessage, setErrorMessage] = useState(''); - const result = useCommand('beginMsFlow', bindings.commands.beginMsFlow, { + const result = useCommand('openMsaLogin', bindings.core.openMsaLogin, { enabled: false, subscribed: false, }); diff --git a/apps/onelauncher/frontend/src/routes/onboarding/route.tsx b/apps/onelauncher/frontend/src/routes/onboarding/route.tsx index 3152ba5c..c0825491 100644 --- a/apps/onelauncher/frontend/src/routes/onboarding/route.tsx +++ b/apps/onelauncher/frontend/src/routes/onboarding/route.tsx @@ -120,21 +120,26 @@ export interface OnboardingStepProps { children: JSX.Element; } -export function OnboardingStep(props: OnboardingStepProps) { +export function OnboardingStep({ + title, + paragraph, + illustration, + children, +}: OnboardingStepProps) { return (
- {props.illustration} + {illustration}
-

{props.title}

-

{props.paragraph}

+

{title}

+

{paragraph}

- {props.children} + {children}
diff --git a/apps/onelauncher/frontend/src/types/global.d.ts b/apps/onelauncher/frontend/src/types/global.d.ts index d5d4d0a1..bdc8303c 100644 --- a/apps/onelauncher/frontend/src/types/global.d.ts +++ b/apps/onelauncher/frontend/src/types/global.d.ts @@ -1,3 +1,9 @@ -export interface ClassNameString { - className?: string; +import type { bindings } from '@/main'; + +export type BindingCommands = (keyof typeof bindings.core) | (keyof typeof bindings.onelauncher); + +declare module '@onelauncher/common' { + interface Register { + commands: Array; + } } diff --git a/apps/onelauncher/frontend/tsconfig.json b/apps/onelauncher/frontend/tsconfig.json index 6e96a58a..6325fbce 100644 --- a/apps/onelauncher/frontend/tsconfig.json +++ b/apps/onelauncher/frontend/tsconfig.json @@ -27,5 +27,5 @@ "skipLibCheck": true, "noUncheckedSideEffectImports": true }, - "include": ["**/*.ts", "**/*.tsx", "prettier.config.js", "vite.config.js"] + "include": ["**/*.ts", "**/*.tsx", "vite.config.js"] } diff --git a/eslint.config.js b/eslint.config.js index c6dd7afc..5e70391c 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -8,9 +8,6 @@ export default defineConfig( react: true, query: true, ignores: ['*.rs', '**/migrations/**'], - rules: { - 'ts/no-use-before-define': 'off', - }, toml: { overrides: { 'toml/array-element-newline': ['error', 'always'], @@ -30,7 +27,9 @@ export default defineConfig( rules: { 'sort-imports': 'off', // Replaced by perfectionist/sort-named-imports', 'import/order': 'off', // Replaced by perfectionist/sort-named-imports', - 'style/jsx-max-props-per-line': ['error', { maximum: 3}] + 'style/jsx-max-props-per-line': ['error', { maximum: 3}], + 'ts/no-use-before-define': 'off', + 'style/function-paren-newline': ['error', 'consistent'] }, }, ); diff --git a/packages/core/src/api/tauri/commands.rs b/packages/core/src/api/tauri/commands.rs index a05aca35..8e8ef1a3 100644 --- a/packages/core/src/api/tauri/commands.rs +++ b/packages/core/src/api/tauri/commands.rs @@ -9,21 +9,43 @@ use onelauncher_entity::prelude::model::*; pub trait TauriLauncherApi { // Clusters + #[taurpc(alias = "getClusters")] async fn get_clusters() -> LauncherResult>; - async fn get_cluster(id: ClusterId) -> LauncherResult>; + + #[taurpc(alias = "getClusterById")] + async fn get_cluster_by_id(id: ClusterId) -> LauncherResult>; + + #[taurpc(alias = "removeCluster")] async fn remove_cluster(id: ClusterId) -> LauncherResult<()>; + + #[taurpc(alias = "createCluster")] async fn create_cluster(options: CreateCluster) -> LauncherResult; // Setting Profiles + #[taurpc(alias = "getProfileOrDefault")] async fn get_profile_or_default(name: Option) -> LauncherResult; + + #[taurpc(alias = "getGlobalProfile")] async fn get_global_profile() -> SettingsProfile; + // Users + #[taurpc(alias = "getUsers")] async fn get_users() -> LauncherResult>; + + #[taurpc(alias = "getUser")] async fn get_user(uuid: uuid::Uuid) -> LauncherResult>; + + #[taurpc(alias = "removeUser")] async fn remove_user(uuid: uuid::Uuid) -> LauncherResult<()>; + + #[taurpc(alias = "getDefaultUser")] async fn get_default_user(fallback: Option) -> LauncherResult>; + + #[taurpc(alias = "setDefaultUser")] async fn set_default_user(uuid: Option) -> LauncherResult<()>; + + #[taurpc(alias = "openMsaLogin")] async fn open_msa_login(app_handle: AppHandle) -> LauncherResult>; } @@ -48,7 +70,7 @@ impl TauriLauncherApi for TauriLauncherApiImpl { api::cluster::dao::get_all_clusters().await } - async fn get_cluster(self, id: ClusterId) -> LauncherResult> { + async fn get_cluster_by_id(self, id: ClusterId) -> LauncherResult> { api::cluster::dao::get_cluster_by_id(id).await } diff --git a/packages/web_common/src/components/AnimatedOutlet.tsx b/packages/web_common/src/components/AnimatedOutlet.tsx index 3a28c690..2c6cecc5 100644 --- a/packages/web_common/src/components/AnimatedOutlet.tsx +++ b/packages/web_common/src/components/AnimatedOutlet.tsx @@ -116,8 +116,7 @@ export function AnimatedOutlet({ const handleAnimationComplete = (id: number) => { setSnapshots(prevSnapshots => - prevSnapshots.filter(snapshot => snapshot.id !== id), - ); + prevSnapshots.filter(snapshot => snapshot.id !== id)); }; return ( diff --git a/packages/web_common/src/hooks/useCommand.ts b/packages/web_common/src/hooks/useCommand.ts index 01c5d0a7..752218db 100644 --- a/packages/web_common/src/hooks/useCommand.ts +++ b/packages/web_common/src/hooks/useCommand.ts @@ -1,11 +1,18 @@ import type { UndefinedInitialDataOptions, UseQueryResult } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query'; -type CacheKey = string; +// this gets overwritten by the consumer project +export interface Register { + // commands +} -export function useCommand(cacheKey: CacheKey | (string & {}), command: () => Promise, options?: Omit, 'queryKey' | 'queryFn'>): UseQueryResult { +type RegisterConfig = Register extends { + commands: infer Keys; +} ? Keys : never; + +export function useCommand(cacheKey: RegisterConfig[number] | (string & {}) | false, command: () => Promise, options?: Omit, 'queryKey' | 'queryFn'>): UseQueryResult { return useQuery({ - queryKey: [cacheKey], + queryKey: cacheKey === false ? [] : [cacheKey], queryFn: async () => { try { const result = await command(); @@ -24,5 +31,3 @@ export function useCommand(cacheKey: CacheKey | (string & {}), command: () => ...options, }); } - -// export useCommand; diff --git a/packages/web_common/src/index.ts b/packages/web_common/src/index.ts index fd70c425..10b7a1b5 100644 --- a/packages/web_common/src/index.ts +++ b/packages/web_common/src/index.ts @@ -1,2 +1,3 @@ export * from './hooks'; +export type * from './types/global'; export * from './utils';