diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..ca41cd3 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +# Ignore artifacts: +build +coverage +.gitkeep \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..bffbb1a --- /dev/null +++ b/.prettierrc @@ -0,0 +1,14 @@ +{ + "bracketSpacing": true, + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "jsxSingleQuote": false, + "printWidth": 120, + "proseWrap": "always", + "quoteProps": "as-needed", + "semi": true, + "singleQuote": false, + "tabWidth": 4, + "trailingComma": "all", + "useTabs": false +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7747450..9ec2c31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,6 @@ "react-router": "^7.13.0" }, "devDependencies": { - "@babel/core": "^7.29.0", "@chromatic-com/storybook": "^5.0.1", "@eslint/js": "^9.39.2", "@storybook/addon-a11y": "^10.2.8", @@ -46,6 +45,7 @@ "eslint": "^9.39.2", "eslint-plugin-react-compiler": "^19.1.0-rc.2", "playwright": "^1.58.2", + "prettier": "3.8.4", "storybook": "^10.2.8", "typescript": "~5.8.3", "typescript-eslint": "^8.55.0", @@ -6556,6 +6556,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.4.tgz", + "integrity": "sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", diff --git a/package.json b/package.json index 6a511a9..fadeb12 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,9 @@ "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", "lint": "eslint src/", + "lint:fix": "eslint src/ --fix", + "prettier:check": "prettier --check src/**/*", + "prettier:write": "prettier --write src/**/*", "check:react-compiler": "node tools/check-react-compiler.mjs" }, "dependencies": { @@ -56,6 +59,7 @@ "eslint": "^9.39.2", "eslint-plugin-react-compiler": "^19.1.0-rc.2", "playwright": "^1.58.2", + "prettier": "3.8.4", "storybook": "^10.2.8", "typescript": "~5.8.3", "typescript-eslint": "^8.55.0", diff --git a/src/App.tsx b/src/App.tsx index 2a08058..99ac3e3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -29,37 +29,53 @@ function App() { } /> {/* Main launcher window */} - - - - - - - - - - - - - }> - } /> - } /> - } /> - } /> - } /> - - - - - - - - - - - - } /> + + + + + + + + + + + + + }> + } /> + } + /> + } /> + } + /> + } + /> + + + + + + + + + + + + } + /> ); diff --git a/src/components/atoms/news/ChangeEntry.stories.tsx b/src/components/atoms/news/ChangeEntry.stories.tsx index 13a8aae..9f36a1b 100644 --- a/src/components/atoms/news/ChangeEntry.stories.tsx +++ b/src/components/atoms/news/ChangeEntry.stories.tsx @@ -1,9 +1,9 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import type { Meta, StoryObj } from "@storybook/react-vite"; -import ChangeEntry from './ChangeEntry'; +import ChangeEntry from "./ChangeEntry"; const meta = { - component: ChangeEntry, + component: ChangeEntry, } satisfies Meta; export default meta; @@ -11,32 +11,32 @@ export default meta; type Story = StoryObj; export const New: Story = { - "args": { - "description": "Added something super awesome!", - "author": "John Doe", - "type": "NEW" - } + args: { + description: "Added something super awesome!", + author: "John Doe", + type: "NEW", + }, }; export const Fix: Story = { - "args": { - "description": "Fixed a bug where the application would crash on startup.", - "author": "John Doe", - "type": "FIX" - } + args: { + description: "Fixed a bug where the application would crash on startup.", + author: "John Doe", + type: "FIX", + }, }; export const Improvement: Story = { - "args": { - "description": "Improved performance of the application.", - "author": "John Doe", - "type": "IMPROVEMENT" - } + args: { + description: "Improved performance of the application.", + author: "John Doe", + type: "IMPROVEMENT", + }, }; export const Balance: Story = { - "args": { - "description": "Balanced gameplay mechanics.", - "author": "John Doe", - "type": "BALANCE" - } -}; \ No newline at end of file + args: { + description: "Balanced gameplay mechanics.", + author: "John Doe", + type: "BALANCE", + }, +}; diff --git a/src/components/atoms/news/ChangeEntry.tsx b/src/components/atoms/news/ChangeEntry.tsx index e693fc5..97c9586 100644 --- a/src/components/atoms/news/ChangeEntry.tsx +++ b/src/components/atoms/news/ChangeEntry.tsx @@ -4,7 +4,6 @@ import { AutoAwesome, Balance, Build, QuestionMark, RocketLaunch } from "@mui/ic type ChangeTypeContrained = "FIX" | "NEW" | "IMPROVEMENT" | "BALANCE"; - export default function ChangeEntry(props: Change) { const { description, author, type } = props; const changeType = type as ChangeTypeContrained; @@ -31,10 +30,14 @@ export default function ChangeEntry(props: Change) { {getIconByType()} - {description} - By {author} + + {description} + + + By {author} + - + ); -} \ No newline at end of file +} diff --git a/src/components/atoms/preferences/PreferenceFieldLabel.stories.tsx b/src/components/atoms/preferences/PreferenceFieldLabel.stories.tsx index cac027d..ae91ee4 100644 --- a/src/components/atoms/preferences/PreferenceFieldLabel.stories.tsx +++ b/src/components/atoms/preferences/PreferenceFieldLabel.stories.tsx @@ -33,4 +33,3 @@ export const WithoutTooltip: Story = { label: "Installation path", }, }; - diff --git a/src/components/atoms/servers/ServerFact.tsx b/src/components/atoms/servers/ServerFact.tsx index 6c8e453..64ecc0b 100644 --- a/src/components/atoms/servers/ServerFact.tsx +++ b/src/components/atoms/servers/ServerFact.tsx @@ -10,15 +10,8 @@ export default function ServerFact(props: ServerFactProps) { const { icon, value } = props; return ( - - - {icon} - + + {icon} {value} diff --git a/src/components/atoms/update/VersionBadge.tsx b/src/components/atoms/update/VersionBadge.tsx index d40b869..e2ad610 100644 --- a/src/components/atoms/update/VersionBadge.tsx +++ b/src/components/atoms/update/VersionBadge.tsx @@ -17,10 +17,7 @@ export default function VersionBadge(props: VersionBadgeProps) { Version - + {currentVersion} ; export default meta; type Story = StoryObj; -export const Default: Story = {}; \ No newline at end of file +export const Default: Story = {}; diff --git a/src/components/demo/ThemeDemoLayout.tsx b/src/components/demo/ThemeDemoLayout.tsx index 9f3b692..224acd1 100644 --- a/src/components/demo/ThemeDemoLayout.tsx +++ b/src/components/demo/ThemeDemoLayout.tsx @@ -56,7 +56,6 @@ export default function ThemeDemoLayout() { const [snackbarOpen, setSnackbarOpen] = useState(false); const [tabValue, setTabValue] = useState(0); - return ( @@ -78,7 +77,9 @@ export default function ThemeDemoLayout() { Title Small Body Large Body Medium — The pudu is the world's smallest deer. - Body Small — Native to South American temperate rainforests. + + Body Small — Native to South American temperate rainforests. + Body Extra Small — They stand only 32–44 cm tall. @@ -96,27 +97,57 @@ export default function ThemeDemoLayout() { Soft - - - - - + + + + + Outlined - - - - - + + + + + Plain - - - - - + + + + + Sizes & States @@ -132,11 +163,21 @@ export default function ThemeDemoLayout() { {/* Icon Buttons */}
- P - S - W - D - N + + P + + + S + + + W + + + D + + + N +
@@ -217,11 +258,7 @@ export default function ThemeDemoLayout() {
Cuteness Level: {sliderValue}% - setSliderValue(v as number)} - color="primary" - /> + setSliderValue(v as number)} color="primary" /> @@ -238,10 +275,18 @@ export default function ThemeDemoLayout() { Warning - Soft Primary - Soft Success - Outlined - Outlined + + Soft Primary + + + Soft Success + + + Outlined + + + Outlined +
@@ -256,7 +301,9 @@ export default function ThemeDemoLayout() { DU - OK + + OK + A @@ -275,8 +322,12 @@ export default function ThemeDemoLayout() { Success — the pudu population is growing! Warning — habitat fragmentation detected. Danger — poachers reported in the area. - Soft variant — a gentle reminder about pudus. - Outlined variant — conservation efforts are working. + + Soft variant — a gentle reminder about pudus. + + + Outlined variant — conservation efforts are working. +
@@ -287,8 +338,8 @@ export default function ThemeDemoLayout() { Southern Pudu - Pudu puda — found in Chile and Argentina. The smallest deer in the world, - standing at just 35–45 cm tall. + Pudu puda — found in Chile and Argentina. The smallest deer in the world, standing at + just 35–45 cm tall. @@ -299,8 +350,8 @@ export default function ThemeDemoLayout() { Northern Pudu - Pudu mephistophiles — found in Colombia, Ecuador, and Peru. - Even smaller than its southern cousin. + Pudu mephistophiles — found in Colombia, Ecuador, and Peru. Even smaller than its + southern cousin. @@ -308,8 +359,8 @@ export default function ThemeDemoLayout() { Conservation - Protected areas and breeding programs help ensure the survival - of these adorable creatures. + Protected areas and breeding programs help ensure the survival of these adorable + creatures. @@ -327,7 +378,12 @@ export default function ThemeDemoLayout() { Soft Sheet A tinted container - + Solid Primary Bold and warm @@ -354,7 +410,8 @@ export default function ThemeDemoLayout() { - Pudus eat leaves, bark, seeds, and fallen fruit. They can stand on hind legs to reach branches. + Pudus eat leaves, bark, seeds, and fallen fruit. They can stand on hind legs to reach + branches. @@ -366,22 +423,22 @@ export default function ThemeDemoLayout() { What is a pudu? - The pudu is a genus of South American deer. Two species are known: the northern pudu - and the southern pudu. They are the world's smallest deer. + The pudu is a genus of South American deer. Two species are known: the northern pudu and the + southern pudu. They are the world's smallest deer. How big do they get? - Southern pudus stand 35–45 cm at the shoulder and weigh 6.4–13.4 kg. - Northern pudus are even smaller. + Southern pudus stand 35–45 cm at the shoulder and weigh 6.4–13.4 kg. Northern pudus are even + smaller. Are they endangered? - The southern pudu is classified as Near Threatened, while the northern pudu - is Vulnerable due to habitat loss and hunting. + The southern pudu is classified as Near Threatened, while the northern pudu is Vulnerable + due to habitat loss and hunting. @@ -404,25 +461,41 @@ export default function ThemeDemoLayout() { Southern Pudu Chile, Argentina 35–45 cm - Near Threatened + + + Near Threatened + + Northern Pudu Colombia, Ecuador, Peru 32–35 cm - Vulnerable + + + Vulnerable + + White-tailed Deer Americas 53–120 cm - Least Concern + + + Least Concern + + Moose North America, Europe 140–210 cm - Least Concern + + + Least Concern + + @@ -436,7 +509,9 @@ export default function ThemeDemoLayout() { - F + + F + Forest Walk @@ -447,7 +522,9 @@ export default function ThemeDemoLayout() { - C + + C + Conservation @@ -458,7 +535,9 @@ export default function ThemeDemoLayout() { - P + + P + Photo Gallery @@ -473,15 +552,27 @@ export default function ThemeDemoLayout() { {/* Breadcrumbs & Links */}
- Home - Animals - Cervidae + + Home + + + Animals + + + Cervidae + Pudu - Primary Link - Neutral Link - Danger Link + + Primary Link + + + Neutral Link + + + Danger Link +
@@ -522,8 +613,17 @@ export default function ThemeDemoLayout() { - - 16:9 + + + 16:9 + @@ -534,8 +634,17 @@ export default function ThemeDemoLayout() { - - 1:1 + + + 1:1 + @@ -566,7 +675,13 @@ export default function ThemeDemoLayout() {
- } sx={{ height: 40 }}> + } + sx={{ height: 40 }} + > Section A Section B Section C @@ -580,7 +695,9 @@ export default function ThemeDemoLayout() { {(["primary", "neutral", "danger", "success", "warning"] as const).map((color) => ( - {color} + + {color} + {[50, 100, 200, 300, 400, 500, 600, 700, 800, 900].map((shade) => ( @@ -616,5 +733,5 @@ export default function ThemeDemoLayout() { - ) -} \ No newline at end of file + ); +} diff --git a/src/components/layouts/InstallationsLayout.tsx b/src/components/layouts/InstallationsLayout.tsx index b212bc9..180340a 100644 --- a/src/components/layouts/InstallationsLayout.tsx +++ b/src/components/layouts/InstallationsLayout.tsx @@ -11,9 +11,7 @@ export default function InstallationsLayout() { - - Installations - + Installations Manage your local game installations @@ -28,16 +26,10 @@ export default function InstallationsLayout() { > Installations Folder - - diff --git a/src/components/layouts/NewsLayout.tsx b/src/components/layouts/NewsLayout.tsx index 20f97c7..106b204 100644 --- a/src/components/layouts/NewsLayout.tsx +++ b/src/components/layouts/NewsLayout.tsx @@ -52,9 +52,7 @@ export default function NewsLayout() { {showEmpty && ( - - No news is currently available. - + No news is currently available. )} @@ -108,11 +106,7 @@ export default function NewsLayout() { - + ); } diff --git a/src/components/layouts/PreferencesLayout.tsx b/src/components/layouts/PreferencesLayout.tsx index 979d76b..afa728b 100644 --- a/src/components/layouts/PreferencesLayout.tsx +++ b/src/components/layouts/PreferencesLayout.tsx @@ -1,7 +1,11 @@ import { Box, CircularProgress, Stack, Typography } from "@mui/joy"; import { preferencesSchema } from "../../pudu/generated"; import { usePreferencesContext } from "../../contextProviders/PreferencesContextProvider"; -import { themeIdToPreferenceValue, themePreferenceValueToThemeId, useThemeContext } from "../../contextProviders/ThemeProvider"; +import { + themeIdToPreferenceValue, + themePreferenceValueToThemeId, + useThemeContext, +} from "../../contextProviders/ThemeProvider"; import PreferenceCategory from "../molecules/preferences/PreferenceCategory"; export default function PreferencesLayout() { @@ -30,11 +34,9 @@ export default function PreferencesLayout() { return ( - + - - Preferences - + Preferences {isSaving ? "Saving..." : "Changes are saved automatically"} @@ -49,15 +51,16 @@ export default function PreferencesLayout() { )} - {preferences && preferencesSchema.map((category) => ( - - ))} + {preferences && + preferencesSchema.map((category) => ( + + ))} ); diff --git a/src/components/layouts/ServersLayout.tsx b/src/components/layouts/ServersLayout.tsx index b360127..f1534ca 100644 --- a/src/components/layouts/ServersLayout.tsx +++ b/src/components/layouts/ServersLayout.tsx @@ -8,9 +8,7 @@ export default function ServersLayout() { return ( - - Servers - + Servers {lastUpdatedLabel} @@ -21,26 +19,19 @@ export default function ServersLayout() { - - Refreshing server list... - + Refreshing server list... )} {isEmpty && ( - - No servers are currently available. - + No servers are currently available. )} {cards.map((card) => ( - + ))} diff --git a/src/components/layouts/SideBarLayout.tsx b/src/components/layouts/SideBarLayout.tsx index 3ba369d..cc1fec7 100644 --- a/src/components/layouts/SideBarLayout.tsx +++ b/src/components/layouts/SideBarLayout.tsx @@ -4,21 +4,22 @@ import { Outlet } from "react-router"; import { SideBarContextProvider } from "../../contextProviders/SideBarContextProvider"; export default function SideBarLayout() { - return ( - + - + - ) + ); } diff --git a/src/components/layouts/UpdateLayout.stories.tsx b/src/components/layouts/UpdateLayout.stories.tsx index 1369c71..027033c 100644 --- a/src/components/layouts/UpdateLayout.stories.tsx +++ b/src/components/layouts/UpdateLayout.stories.tsx @@ -2,7 +2,8 @@ import { Box } from "@mui/joy"; import type { Meta, StoryObj } from "@storybook/react-vite"; import UpdateLayout from "./UpdateLayout"; -const sampleReleaseNotes = "It is here! Feature parity with the old stationhub launcher, but with many extra goodies!\r\n\r\n## What's Changed\r\n* feat: first release of pudulauncher, now with 0% bugs by @corp-0 in [7](https://github.com/corp-0/PuduLauncher/pull/7)\r\n* feat: new HonkTTS and HonkTTS installer. Visually install the TTS server that powers immersive voices in Unitystation.\r\n* fix: TTS installation is no longer a side-effect of downloading a game build. You can manage your installation however you want.\r\n* feat: new onboarding system to have a friendly pudu guide you through new features and things that require your attention.\r\n* feat: new Discord rich presence functionality. If you feel like sharing, your friends on Discord can now see if you are playing and on what server.\r\n\r\n\r\n**Full Changelog**: [Here](https://github.com/corp-0/PuduLauncher/compare/v0.1.1...v1.0.0)"; +const sampleReleaseNotes = + "It is here! Feature parity with the old stationhub launcher, but with many extra goodies!\r\n\r\n## What's Changed\r\n* feat: first release of pudulauncher, now with 0% bugs by @corp-0 in [7](https://github.com/corp-0/PuduLauncher/pull/7)\r\n* feat: new HonkTTS and HonkTTS installer. Visually install the TTS server that powers immersive voices in Unitystation.\r\n* fix: TTS installation is no longer a side-effect of downloading a game build. You can manage your installation however you want.\r\n* feat: new onboarding system to have a friendly pudu guide you through new features and things that require your attention.\r\n* feat: new Discord rich presence functionality. If you feel like sharing, your friends on Discord can now see if you are playing and on what server.\r\n\r\n\r\n**Full Changelog**: [Here](https://github.com/corp-0/PuduLauncher/compare/v0.1.1...v1.0.0)"; const meta = { title: "Layouts/UpdateLayout", diff --git a/src/components/layouts/UpdateLayout.tsx b/src/components/layouts/UpdateLayout.tsx index 4400605..d8ceb95 100644 --- a/src/components/layouts/UpdateLayout.tsx +++ b/src/components/layouts/UpdateLayout.tsx @@ -58,42 +58,52 @@ export default function UpdateLayout(props: UpdateLayoutProps) { const isBusy = isDownloading || isInstalling; return ( - - - - - + + inset: 0, + background: + "radial-gradient(ellipse 80% 60% at 30% 80%, rgba(var(--joy-palette-primary-mainChannel) / 0.08) 0%, transparent 70%), radial-gradient(ellipse 60% 50% at 80% 20%, rgba(var(--joy-palette-primary-mainChannel) / 0.05) 0%, transparent 60%)", + pointerEvents: "none", + }} + /> + + + - + @@ -133,7 +145,8 @@ export default function UpdateLayout(props: UpdateLayoutProps) { sx={{ fontWeight: 800, letterSpacing: "-0.01em", - background: "linear-gradient(135deg, var(--joy-palette-primary-300), var(--joy-palette-primary-500))", + background: + "linear-gradient(135deg, var(--joy-palette-primary-300), var(--joy-palette-primary-500))", backgroundClip: "text", WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent", @@ -157,25 +170,30 @@ export default function UpdateLayout(props: UpdateLayoutProps) { )} {isInstalling && ( - - + + Installing... the app will restart shortly @@ -183,13 +201,15 @@ export default function UpdateLayout(props: UpdateLayoutProps) { )} {status === "error" && ( - + Update failed. Please download the latest version manually. @@ -224,11 +244,7 @@ export default function UpdateLayout(props: UpdateLayoutProps) { ) : ( - diff --git a/src/components/layouts/onboarding/FirstTimeLaunchLayout.stories.tsx b/src/components/layouts/onboarding/FirstTimeLaunchLayout.stories.tsx index 083e765..decfe83 100644 --- a/src/components/layouts/onboarding/FirstTimeLaunchLayout.stories.tsx +++ b/src/components/layouts/onboarding/FirstTimeLaunchLayout.stories.tsx @@ -4,39 +4,39 @@ import type { OnboardingStep } from "../../../pudu/generated"; import { MockOnboardingProvider } from "../../../storybook/mockProviders"; interface OnboardingPreviewProps { - steps: OnboardingStep[]; + steps: OnboardingStep[]; } function OnboardingPreview(props: OnboardingPreviewProps) { - const { steps } = props; + const { steps } = props; - return ( - - - - ); + return ( + + + + ); } const meta = { - title: "Layouts/Onboarding/FirstTimeLaunch", - component: OnboardingPreview, - parameters: { - layout: "fullscreen", - }, - decorators: [ - (Story) => ( - <> - - - - ), - ], + title: "Layouts/Onboarding/FirstTimeLaunch", + component: OnboardingPreview, + parameters: { + layout: "fullscreen", + }, + decorators: [ + (Story) => ( + <> + + + + ), + ], } satisfies Meta; export default meta; @@ -44,51 +44,51 @@ export default meta; type Story = StoryObj; const singleStepMock: OnboardingStep[] = [ - { - id: "welcome", - componentKey: "welcome", - title: "Welcome", - description: "Let's set up your launcher experience.", - isRequired: true, - order: 0, - } + { + id: "welcome", + componentKey: "welcome", + title: "Welcome", + description: "Let's set up your launcher experience.", + isRequired: true, + order: 0, + }, ]; const multiStepMock: OnboardingStep[] = [ - { - id: "welcome", - componentKey: "welcome", - title: "Welcome", - description: "Let's set up your launcher experience.", - isRequired: true, - order: 0, - }, - { - id: "launcher-basics", - componentKey: "launcher-basics", - title: "Launcher basics", - description: "Quick overview of launcher preferences.", - isRequired: false, - order: 1, - }, - { - id: "ready-v1", - componentKey: "all-ready", - title: "You're ready", - description: "Final confirmation step.", - isRequired: true, - order: 2, - }, + { + id: "welcome", + componentKey: "welcome", + title: "Welcome", + description: "Let's set up your launcher experience.", + isRequired: true, + order: 0, + }, + { + id: "launcher-basics", + componentKey: "launcher-basics", + title: "Launcher basics", + description: "Quick overview of launcher preferences.", + isRequired: false, + order: 1, + }, + { + id: "ready-v1", + componentKey: "all-ready", + title: "You're ready", + description: "Final confirmation step.", + isRequired: true, + order: 2, + }, ]; export const SingleStepFlow: Story = { - args: { - steps: singleStepMock, - }, -} + args: { + steps: singleStepMock, + }, +}; export const MultiStepFlow: Story = { - args: { - steps: multiStepMock, - }, + args: { + steps: multiStepMock, + }, }; diff --git a/src/components/layouts/onboarding/OnboardingProgressDots.tsx b/src/components/layouts/onboarding/OnboardingProgressDots.tsx index 2c673ab..1d60bdf 100644 --- a/src/components/layouts/onboarding/OnboardingProgressDots.tsx +++ b/src/components/layouts/onboarding/OnboardingProgressDots.tsx @@ -25,11 +25,7 @@ export default function OnboardingProgressDots(props: OnboardingProgressDotsProp width: isActive ? 24 : 8, height: 8, borderRadius: 99, - backgroundColor: isActive - ? "primary.400" - : isCompleted - ? "primary.700" - : "neutral.700", + backgroundColor: isActive ? "primary.400" : isCompleted ? "primary.700" : "neutral.700", transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)", }} /> diff --git a/src/components/layouts/onboarding/OnboardingStepShell.tsx b/src/components/layouts/onboarding/OnboardingStepShell.tsx index fb5a5a9..c0ffffc 100644 --- a/src/components/layouts/onboarding/OnboardingStepShell.tsx +++ b/src/components/layouts/onboarding/OnboardingStepShell.tsx @@ -20,12 +20,7 @@ interface OnboardingStepShellProps { } export default function OnboardingStepShell(props: OnboardingStepShellProps): JSX.Element { - const { - children, - actions, - illustration, - maxContentWidth = 720, - } = props; + const { children, actions, illustration, maxContentWidth = 720 } = props; return ( ) : ( - - {children} - + {children} )} @@ -116,11 +109,7 @@ export default function OnboardingStepShell(props: OnboardingStepShellProps): JS ); } -function ContentContainer(props: { - children: ReactNode; - maxWidth: number | string; - flex?: string; -}) { +function ContentContainer(props: { children: ReactNode; maxWidth: number | string; flex?: string }) { return ( - You are all set + + You are all set + PuduLauncher is ready to use. diff --git a/src/components/layouts/onboarding/firstTimeLaunchSteps/WelcomeLayout.tsx b/src/components/layouts/onboarding/firstTimeLaunchSteps/WelcomeLayout.tsx index 7995423..3e30d98 100644 --- a/src/components/layouts/onboarding/firstTimeLaunchSteps/WelcomeLayout.tsx +++ b/src/components/layouts/onboarding/firstTimeLaunchSteps/WelcomeLayout.tsx @@ -19,9 +19,7 @@ export default function WelcomeLayout(props: OnboardingStepComponentProps): JSX. return ( Welcome to PuduLauncher! - Thanks for being here! Pudu is the official Unitystation launcher, built to get you into - the game faster and with less hassle. Let's get you set up. + Thanks for being here! Pudu is the official Unitystation launcher, built to get you into the game faster + and with less hassle. Let's get you set up. Need help or have a question? Reach out on{" "} void openDiscord(event)}> Unitystation's Discord - . + + . ); diff --git a/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/HonkTtsSetupLayout.tsx b/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/HonkTtsSetupLayout.tsx index d2ffb6c..5f8158b 100644 --- a/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/HonkTtsSetupLayout.tsx +++ b/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/HonkTtsSetupLayout.tsx @@ -68,8 +68,8 @@ export default function HonkTtsSetupLayout(props: HonkTtsSetupLayoutProps): JSX. > Set up HonkTTS - Choose where HonkTTS should be installed and whether it should start automatically when - PuduLauncher starts. + Choose where HonkTTS should be installed and whether it should start automatically when PuduLauncher + starts. diff --git a/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/ImmersiveVoicesIntroLayout.tsx b/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/ImmersiveVoicesIntroLayout.tsx index 7345fe0..0205708 100644 --- a/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/ImmersiveVoicesIntroLayout.tsx +++ b/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/ImmersiveVoicesIntroLayout.tsx @@ -30,8 +30,8 @@ export default function ImmersiveVoicesIntroLayout(props: ImmersiveVoicesIntroLa > Immersive voices with HonkTTS - HonkTTS is the local text-to-speech server used by PuduLauncher immersive voices. - It runs on your machine and adds voices to characters in-game. + HonkTTS is the local text-to-speech server used by PuduLauncher immersive voices. It runs on your + machine and adds voices to characters in-game. You can skip for now and enable it later from Preferences. diff --git a/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/InstallationsPathLayout.tsx b/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/InstallationsPathLayout.tsx index f7285ae..879873d 100644 --- a/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/InstallationsPathLayout.tsx +++ b/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/InstallationsPathLayout.tsx @@ -50,8 +50,8 @@ export default function InstallationsPathLayout(props: InstallationsPathLayoutPr > Choose your installations folder - This is where PuduLauncher stores downloaded game builds. Whenever you join a server, - the required build is downloaded and stored here. + This is where PuduLauncher stores downloaded game builds. Whenever you join a server, the required build + is downloaded and stored here. You can change this later from Preferences. diff --git a/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/MainLayout.tsx b/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/MainLayout.tsx index f4ba953..004f9d2 100644 --- a/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/MainLayout.tsx +++ b/src/components/layouts/onboarding/firstTimeLaunchSteps/launcherBasics/MainLayout.tsx @@ -111,9 +111,8 @@ export default function MainLayout(props: OnboardingStepComponentProps) { return; } - const resolvedInstallationsPath = installationsPath.trim().length > 0 - ? installationsPath.trim() - : preferences.installations.installationPath; + const resolvedInstallationsPath = + installationsPath.trim().length > 0 ? installationsPath.trim() : preferences.installations.installationPath; const updatedPreferences: Preferences = { ...preferences, @@ -138,13 +137,10 @@ export default function MainLayout(props: OnboardingStepComponentProps) { return true; } - const resolvedInstallationsPath = installationsPath.trim().length > 0 - ? installationsPath.trim() - : preferences.installations.installationPath; + const resolvedInstallationsPath = + installationsPath.trim().length > 0 ? installationsPath.trim() : preferences.installations.installationPath; - const resolvedTtsPath = ttsInstallPath.trim().length > 0 - ? ttsInstallPath.trim() - : preferences.tts.installPath; + const resolvedTtsPath = ttsInstallPath.trim().length > 0 ? ttsInstallPath.trim() : preferences.tts.installPath; const updatedPreferences: Preferences = { ...preferences, @@ -251,8 +247,6 @@ export default function MainLayout(props: OnboardingStepComponentProps) { }; return ( - - {renderStep()} - + {renderStep()} ); } diff --git a/src/components/layouts/tts/TtsInstallerLayout.stories.tsx b/src/components/layouts/tts/TtsInstallerLayout.stories.tsx index cc23aea..aa4028a 100644 --- a/src/components/layouts/tts/TtsInstallerLayout.stories.tsx +++ b/src/components/layouts/tts/TtsInstallerLayout.stories.tsx @@ -10,15 +10,7 @@ const sampleLogs = [ "[4/6] eSpeak NG (espeak)", ]; -const installStepLabels = [ - "Prepare", - "Python", - "Environment", - "Packages", - "eSpeak-ng", - "Model", - "Server", -]; +const installStepLabels = ["Prepare", "Python", "Environment", "Packages", "eSpeak-ng", "Model", "Server"]; const meta = { title: "Layouts/Tts/TtsInstallerLayout", diff --git a/src/components/layouts/tts/TtsInstallerLayout.tsx b/src/components/layouts/tts/TtsInstallerLayout.tsx index b33d784..b1ba34d 100644 --- a/src/components/layouts/tts/TtsInstallerLayout.tsx +++ b/src/components/layouts/tts/TtsInstallerLayout.tsx @@ -1,5 +1,5 @@ -import {Alert, Box, Button, Modal, ModalDialog, Stack, Typography} from "@mui/joy"; -import {useEffect, useRef} from "react"; +import { Alert, Box, Button, Modal, ModalDialog, Stack, Typography } from "@mui/joy"; +import { useEffect, useRef } from "react"; import PuduStepper from "../../organisms/common/PuduStepper"; interface TtsInstallerLayoutProps { @@ -42,8 +42,8 @@ export default function TtsInstallerLayout(props: TtsInstallerLayoutProps) { return ( - - + + HonkTTS Installer @@ -97,12 +97,10 @@ export default function TtsInstallerLayout(props: TtsInstallerLayoutProps) { wordBreak: "break-word", }} > - {installLogs.length > 0 - ? installLogs.join("\n") - : "Waiting for installer output..."} + {installLogs.length > 0 ? installLogs.join("\n") : "Waiting for installer output..."} - + diff --git a/src/components/layouts/workInProgressLayout/WorkInProgressLayout.stories.tsx b/src/components/layouts/workInProgressLayout/WorkInProgressLayout.stories.tsx index 6c42048..8ce6b33 100644 --- a/src/components/layouts/workInProgressLayout/WorkInProgressLayout.stories.tsx +++ b/src/components/layouts/workInProgressLayout/WorkInProgressLayout.stories.tsx @@ -1,7 +1,6 @@ -import type {Meta, StoryObj} from "@storybook/react-vite"; +import type { Meta, StoryObj } from "@storybook/react-vite"; import WorkInProgressLayout from "./WorkInProgressLayout.tsx"; -import {Box, GlobalStyles} from "@mui/joy"; - +import { Box, GlobalStyles } from "@mui/joy"; const meta = { title: "Layouts/WorkInProgressLayout", @@ -12,23 +11,27 @@ const meta = { decorators: [ (Story) => ( <> - - - + + + ), - ] + ], } satisfies Meta; export default meta; type Story = StoryObj; -export const Default: Story = {}; \ No newline at end of file +export const Default: Story = {}; diff --git a/src/components/layouts/workInProgressLayout/WorkInProgressLayout.tsx b/src/components/layouts/workInProgressLayout/WorkInProgressLayout.tsx index 72c0c46..7ac7c8b 100644 --- a/src/components/layouts/workInProgressLayout/WorkInProgressLayout.tsx +++ b/src/components/layouts/workInProgressLayout/WorkInProgressLayout.tsx @@ -1,19 +1,21 @@ -import {AspectRatio, Stack, Typography} from "@mui/joy"; +import { AspectRatio, Stack, Typography } from "@mui/joy"; export default function WorkInProgressLayout() { return ( <> - - Pudu is having a nap + + Pudu is having a nap - - Work in progress... - + Work in progress... - ) + ); } diff --git a/src/components/molecules/PaginationControls.tsx b/src/components/molecules/PaginationControls.tsx index eb0af06..d7b42fa 100644 --- a/src/components/molecules/PaginationControls.tsx +++ b/src/components/molecules/PaginationControls.tsx @@ -14,23 +14,13 @@ export default function PaginationControls(props: PaginationControlsProps) { return ( - Page {currentPage} of {totalPages} - diff --git a/src/components/molecules/discord/DiscordJoinDialog.tsx b/src/components/molecules/discord/DiscordJoinDialog.tsx index 47e7786..e4c91fb 100644 --- a/src/components/molecules/discord/DiscordJoinDialog.tsx +++ b/src/components/molecules/discord/DiscordJoinDialog.tsx @@ -11,14 +11,7 @@ import { Stack, Typography, } from "@mui/joy"; -import { - Download, - Dns, - GamepadRounded, - Map as MapIcon, - People, - SportsEsports, -} from "@mui/icons-material"; +import { Download, Dns, GamepadRounded, Map as MapIcon, People, SportsEsports } from "@mui/icons-material"; import type { ReactNode } from "react"; export interface DiscordJoinDialogProps { @@ -38,9 +31,7 @@ export interface DiscordJoinDialogProps { function InfoRow(props: { icon: ReactNode; label: string; value: string }) { return ( - - {props.icon} - + {props.icon} {props.label} @@ -112,10 +103,7 @@ export default function DiscordJoinDialog(props: DiscordJoinDialogProps) { > - + Game Invite @@ -204,21 +192,13 @@ export default function DiscordJoinDialog(props: DiscordJoinDialogProps) { {/* Install notice */} - + This build is not installed yet. Install it to join the server. {/* Actions */} - + {onSeeLogs && ( ) diff --git a/src/components/molecules/installations/InstallationCard.stories.tsx b/src/components/molecules/installations/InstallationCard.stories.tsx index 3dd5fd8..7a67c84 100644 --- a/src/components/molecules/installations/InstallationCard.stories.tsx +++ b/src/components/molecules/installations/InstallationCard.stories.tsx @@ -1,53 +1,50 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; -import type { ComponentProps } from 'react'; +import type { Meta, StoryObj } from "@storybook/react-vite"; +import type { ComponentProps } from "react"; -import InstallationCard from './InstallationCard'; +import InstallationCard from "./InstallationCard"; type InstallationCardStoryArgs = ComponentProps & { - showLastPlayedChip: boolean; - lastPlayedStatus: "Recently Played" | "A while ago"; + showLastPlayedChip: boolean; + lastPlayedStatus: "Recently Played" | "A while ago"; }; const DAY_MS = 24 * 60 * 60 * 1000; const getLastPlayedDate = (status: InstallationCardStoryArgs["lastPlayedStatus"]) => { - const daysAgo = status === "Recently Played" ? 2 : 45; - return new Date(Date.now() - daysAgo * DAY_MS).toISOString(); + const daysAgo = status === "Recently Played" ? 2 : 45; + return new Date(Date.now() - daysAgo * DAY_MS).toISOString(); }; const meta = { - component: InstallationCard, - args: { - forkName: "UnitystationDevelop", - buildVersion: "26021410", - isNewest: false, - showLastPlayedChip: true, - lastPlayedStatus: "Recently Played", - }, - argTypes: { - isNewest: { - control: "boolean", - description: "Show or hide the Newest chip.", + component: InstallationCard, + args: { + forkName: "UnitystationDevelop", + buildVersion: "26021410", + isNewest: false, + showLastPlayedChip: true, + lastPlayedStatus: "Recently Played", }, - showLastPlayedChip: { - control: "boolean", - description: "Show or hide the Last Played chip.", + argTypes: { + isNewest: { + control: "boolean", + description: "Show or hide the Newest chip.", + }, + showLastPlayedChip: { + control: "boolean", + description: "Show or hide the Last Played chip.", + }, + lastPlayedStatus: { + control: { type: "inline-radio" }, + options: ["Recently Played", "A while ago"], + description: "Controls the label shown when Last Played chip is enabled.", + }, + lastPlayedAt: { + table: { disable: true }, + }, }, - lastPlayedStatus: { - control: { type: "inline-radio" }, - options: ["Recently Played", "A while ago"], - description: "Controls the label shown when Last Played chip is enabled.", - }, - lastPlayedAt: { - table: { disable: true }, - }, - }, - render: ({ showLastPlayedChip, lastPlayedStatus, ...args }) => ( - - ), + render: ({ showLastPlayedChip, lastPlayedStatus, ...args }) => ( + + ), } satisfies Meta; export default meta; @@ -57,27 +54,27 @@ type Story = StoryObj; export const Default: Story = {}; export const AWhileAgo: Story = { - args: { - lastPlayedStatus: "A while ago", - }, + args: { + lastPlayedStatus: "A while ago", + }, }; export const WithoutLastPlayed: Story = { - args: { - showLastPlayedChip: false, - }, + args: { + showLastPlayedChip: false, + }, }; export const NewestBuild: Story = { - args: { - isNewest: true, - }, + args: { + isNewest: true, + }, }; export const LongForkName: Story = { - args: { - forkName: "UnitystationDevelop-CI-Nightly-Windows-x64-Experimental", - lastPlayedStatus: "A while ago", - isNewest: true, - }, + args: { + forkName: "UnitystationDevelop-CI-Nightly-Windows-x64-Experimental", + lastPlayedStatus: "A while ago", + isNewest: true, + }, }; diff --git a/src/components/molecules/installations/InstallationCard.tsx b/src/components/molecules/installations/InstallationCard.tsx index d11f5f4..8257b7b 100644 --- a/src/components/molecules/installations/InstallationCard.tsx +++ b/src/components/molecules/installations/InstallationCard.tsx @@ -42,17 +42,15 @@ export default function InstallationCard(props: InstallationCardProps) { overflow: "hidden", padding: 2, flexShrink: 0, - }}> + }} + > - + alignItems={{ xs: "stretch", sm: "center" }} + > + + }} + > - - + + {forkName} {isNewest && ( @@ -94,30 +86,15 @@ export default function InstallationCard(props: InstallationCardProps) { - - - - ) + ); } diff --git a/src/components/molecules/installations/RegistryBuildRow.tsx b/src/components/molecules/installations/RegistryBuildRow.tsx index 028933d..38ac31f 100644 --- a/src/components/molecules/installations/RegistryBuildRow.tsx +++ b/src/components/molecules/installations/RegistryBuildRow.tsx @@ -1,13 +1,6 @@ -import {Check, CloudDownload, Refresh} from "@mui/icons-material"; -import { - Button, - Chip, - LinearProgress, - Sheet, - Stack, - Typography, -} from "@mui/joy"; -import type {RegistryDownloadSnapshot} from "../../../contextProviders/InstallationsContextProvider"; +import { Check, CloudDownload, Refresh } from "@mui/icons-material"; +import { Button, Chip, LinearProgress, Sheet, Stack, Typography } from "@mui/joy"; +import type { RegistryDownloadSnapshot } from "../../../contextProviders/InstallationsContextProvider"; const STATE_LABELS: Record = { 1: "Downloading", @@ -26,14 +19,14 @@ interface RegistryBuildRowProps { } export default function RegistryBuildRow(props: RegistryBuildRowProps) { - const {versionNumber, dateCreated, download, isInstalled, onDownload} = props; + const { versionNumber, dateCreated, download, isInstalled, onDownload } = props; const formattedDate = dateCreated ? new Date(dateCreated).toLocaleDateString(undefined, { - year: "numeric", - month: "short", - day: "numeric", - }) + year: "numeric", + month: "short", + day: "numeric", + }) : null; const isDownloading = download?.state === 1; @@ -51,22 +44,26 @@ export default function RegistryBuildRow(props: RegistryBuildRowProps) { overflow: "hidden", }} > - + - + Build {versionNumber} {isInstalled && !download && ( - }> + } + > Installed )} {formattedDate && ( - + {formattedDate} )} @@ -77,7 +74,7 @@ export default function RegistryBuildRow(props: RegistryBuildRowProps) { variant="soft" color="primary" size="sm" - startDecorator={} + startDecorator={} onClick={onDownload} > Download @@ -98,7 +95,7 @@ export default function RegistryBuildRow(props: RegistryBuildRowProps) { variant="soft" color="danger" size="sm" - startDecorator={} + startDecorator={} onClick={onDownload} > Retry @@ -113,17 +110,11 @@ export default function RegistryBuildRow(props: RegistryBuildRowProps) { variant="soft" value={download.progress} color="primary" - sx={{borderRadius: 0}} + sx={{ borderRadius: 0 }} /> )} - {isProcessing && ( - - )} + {isProcessing && } ); } diff --git a/src/components/molecules/installations/RegistryBuildsPopup.tsx b/src/components/molecules/installations/RegistryBuildsPopup.tsx index 928131e..19c7ad8 100644 --- a/src/components/molecules/installations/RegistryBuildsPopup.tsx +++ b/src/components/molecules/installations/RegistryBuildsPopup.tsx @@ -1,14 +1,5 @@ import { Close } from "@mui/icons-material"; -import { - Alert, - Box, - CircularProgress, - IconButton, - Modal, - ModalDialog, - Stack, - Typography, -} from "@mui/joy"; +import { Alert, Box, CircularProgress, IconButton, Modal, ModalDialog, Stack, Typography } from "@mui/joy"; import type { RegistryBuild } from "../../../pudu/generated"; import type { RegistryDownloadSnapshot } from "../../../contextProviders/InstallationsContextProvider"; import { usePaginatedCollection } from "../../../hooks/usePaginatedCollection"; @@ -30,14 +21,10 @@ interface RegistryBuildsPopupProps { export default function RegistryBuildsPopup(props: RegistryBuildsPopupProps) { const { open, builds, loading, downloads, installedVersions, onDownload, onClose } = props; - const { - currentPageItems, - currentPage, - totalPages, - nextPage, - previousPage, - totalItems, - } = usePaginatedCollection(builds, PAGE_SIZE); + const { currentPageItems, currentPage, totalPages, nextPage, previousPage, totalItems } = usePaginatedCollection( + builds, + PAGE_SIZE, + ); return ( @@ -59,9 +46,7 @@ export default function RegistryBuildsPopup(props: RegistryBuildsPopupProps) { - - Fetching builds from registry... - + Fetching builds from registry... )} diff --git a/src/components/molecules/news/BuildEntry.stories.tsx b/src/components/molecules/news/BuildEntry.stories.tsx index 083129d..111857e 100644 --- a/src/components/molecules/news/BuildEntry.stories.tsx +++ b/src/components/molecules/news/BuildEntry.stories.tsx @@ -1,9 +1,9 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import type { Meta, StoryObj } from "@storybook/react-vite"; -import BuildEntry from './BuildEntry'; +import BuildEntry from "./BuildEntry"; const meta = { - component: BuildEntry, + component: BuildEntry, } satisfies Meta; export default meta; @@ -11,30 +11,30 @@ export default meta; type Story = StoryObj; export const Default: Story = { - args: { - "version": "1.0.0", - "dateCreated": "2024-06-01T12:00:00Z", - "changes": [ - { - "description": "Fixed a critical bug that caused crashes on startup.", - "author": "Jane Doe", - "type": "FIX" - }, - { - "description": "Added new feature for customizing user interface.", - "author": "John Smith", - "type": "NEW" - }, - { - "description": "Improved performance of the application.", - "author": "Alice Johnson", - "type": "IMPROVEMENT" - }, - { - "description": "Balanced the game mechanics for better gameplay experience.", - "author": "Bob Brown", - "type": "BALANCE" - } - ] - } -}; \ No newline at end of file + args: { + version: "1.0.0", + dateCreated: "2024-06-01T12:00:00Z", + changes: [ + { + description: "Fixed a critical bug that caused crashes on startup.", + author: "Jane Doe", + type: "FIX", + }, + { + description: "Added new feature for customizing user interface.", + author: "John Smith", + type: "NEW", + }, + { + description: "Improved performance of the application.", + author: "Alice Johnson", + type: "IMPROVEMENT", + }, + { + description: "Balanced the game mechanics for better gameplay experience.", + author: "Bob Brown", + type: "BALANCE", + }, + ], + }, +}; diff --git a/src/components/molecules/news/ChangelogSidebar.stories.tsx b/src/components/molecules/news/ChangelogSidebar.stories.tsx index 60ca069..00c7845 100644 --- a/src/components/molecules/news/ChangelogSidebar.stories.tsx +++ b/src/components/molecules/news/ChangelogSidebar.stories.tsx @@ -1,6 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import type { Meta, StoryObj } from "@storybook/react-vite"; -import ChangelogSidebar from './ChangelogSidebar'; +import ChangelogSidebar from "./ChangelogSidebar"; const meta = { component: ChangelogSidebar, @@ -26,27 +26,67 @@ export const Default: Story = { version: "0.8.3", dateCreated: "2025-06-01T12:00:00Z", changes: [ - { description: "Fixed a critical networking bug that caused disconnections during high player counts.", author: "Jane Doe", type: "FIX" }, - { description: "Added new emote system with over 30 animations.", author: "John Smith", type: "NEW" }, + { + description: + "Fixed a critical networking bug that caused disconnections during high player counts.", + author: "Jane Doe", + type: "FIX", + }, + { + description: "Added new emote system with over 30 animations.", + author: "John Smith", + type: "NEW", + }, ], }, { version: "0.8.2", dateCreated: "2025-05-20T10:00:00Z", changes: [ - { description: "Improved server browser loading speed by caching DNS lookups and reusing HTTP connections.", author: "Alice Johnson", type: "IMPROVEMENT" }, - { description: "Balanced traitor objectives to be more achievable for new players while keeping experienced players challenged.", author: "Bob Brown", type: "BALANCE" }, - { description: "Fixed ghost players being able to interact with physical objects in certain edge cases.", author: "Jane Doe", type: "FIX" }, + { + description: + "Improved server browser loading speed by caching DNS lookups and reusing HTTP connections.", + author: "Alice Johnson", + type: "IMPROVEMENT", + }, + { + description: + "Balanced traitor objectives to be more achievable for new players while keeping experienced players challenged.", + author: "Bob Brown", + type: "BALANCE", + }, + { + description: + "Fixed ghost players being able to interact with physical objects in certain edge cases.", + author: "Jane Doe", + type: "FIX", + }, ], }, { version: "0.8.1", dateCreated: "2025-05-10T08:00:00Z", changes: [ - { description: "Added speech-to-text integration for accessibility.", author: "Charlie Wilson", type: "NEW" }, - { description: "Fixed Linux builds failing to launch on Ubuntu 24.04.", author: "Jane Doe", type: "FIX" }, - { description: "Improved character creation UI responsiveness.", author: "Alice Johnson", type: "IMPROVEMENT" }, - { description: "Fixed inventory duplication exploit when disconnecting during transfers.", author: "Bob Brown", type: "FIX" }, + { + description: "Added speech-to-text integration for accessibility.", + author: "Charlie Wilson", + type: "NEW", + }, + { + description: "Fixed Linux builds failing to launch on Ubuntu 24.04.", + author: "Jane Doe", + type: "FIX", + }, + { + description: "Improved character creation UI responsiveness.", + author: "Alice Johnson", + type: "IMPROVEMENT", + }, + { + description: "Fixed inventory duplication exploit when disconnecting during transfers.", + author: "Bob Brown", + type: "FIX", + }, ], }, ], diff --git a/src/components/molecules/news/FeaturedBlogPostPreview.stories.tsx b/src/components/molecules/news/FeaturedBlogPostPreview.stories.tsx index 5f7cea5..fef90f1 100644 --- a/src/components/molecules/news/FeaturedBlogPostPreview.stories.tsx +++ b/src/components/molecules/news/FeaturedBlogPostPreview.stories.tsx @@ -1,6 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import type { Meta, StoryObj } from "@storybook/react-vite"; -import FeaturedBlogPostPreview from './FeaturedBlogPostPreview'; +import FeaturedBlogPostPreview from "./FeaturedBlogPostPreview"; const meta = { component: FeaturedBlogPostPreview, @@ -17,7 +17,8 @@ export const Default: Story = { author: "Gilles", createDateTime: "2025-05-03T03:07:24.470778Z", imageUrl: "https://unitystationfile.b-cdn.net/WeeklyBlogUpdates/33/sillylights.webp", - summary: "New mobs use the same systems as players, simple bots are back and talky, puddles are real, traps are live, emissive lights got cooler, and Linux builds finally work. We've got a new permissions system, character voices, a flatpacking machine, speech-to-text, and a mountain of bugfixes. It's been a big one.", + summary: + "New mobs use the same systems as players, simple bots are back and talky, puddles are real, traps are live, emissive lights got cooler, and Linux builds finally work. We've got a new permissions system, character voices, a flatpacking machine, speech-to-text, and a mountain of bugfixes. It's been a big one.", }, }; @@ -28,6 +29,7 @@ export const LongSummary: Story = { author: "TeamLead", createDateTime: "2025-04-15T10:30:00Z", imageUrl: "https://unitystationfile.b-cdn.net/WeeklyBlogUpdates/33/sillylights.webp", - summary: "This update brings a complete overhaul of the core game systems including networking, physics, rendering, and AI. We have rewritten the entire networking stack to support better latency and more concurrent players. The physics engine now handles complex interactions between objects more realistically. Our rendering pipeline has been optimized for lower-end hardware while maintaining visual fidelity on high-end systems.", + summary: + "This update brings a complete overhaul of the core game systems including networking, physics, rendering, and AI. We have rewritten the entire networking stack to support better latency and more concurrent players. The physics engine now handles complex interactions between objects more realistically. Our rendering pipeline has been optimized for lower-end hardware while maintaining visual fidelity on high-end systems.", }, }; diff --git a/src/components/molecules/news/HeroBlogPost.stories.tsx b/src/components/molecules/news/HeroBlogPost.stories.tsx index 43a325d..1d27801 100644 --- a/src/components/molecules/news/HeroBlogPost.stories.tsx +++ b/src/components/molecules/news/HeroBlogPost.stories.tsx @@ -1,6 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import type { Meta, StoryObj } from "@storybook/react-vite"; -import HeroBlogPost from './HeroBlogPost'; +import HeroBlogPost from "./HeroBlogPost"; const meta = { component: HeroBlogPost, @@ -17,6 +17,7 @@ export const Default: Story = { author: "Gilles", createDateTime: "2025-05-03T03:07:24.470778Z", imageUrl: "https://unitystationfile.b-cdn.net/WeeklyBlogUpdates/33/sillylights.webp", - summary: "New mobs use the same systems as players, simple bots are back and talky, puddles are real, traps are live, emissive lights got cooler, and Linux builds finally work. We've got a new permissions system, character voices, a flatpacking machine, speech-to-text, and a mountain of bugfixes. It's been a big one.", + summary: + "New mobs use the same systems as players, simple bots are back and talky, puddles are real, traps are live, emissive lights got cooler, and Linux builds finally work. We've got a new permissions system, character voices, a flatpacking machine, speech-to-text, and a mountain of bugfixes. It's been a big one.", }, }; diff --git a/src/components/molecules/news/HeroBlogPost.tsx b/src/components/molecules/news/HeroBlogPost.tsx index 9c32684..5fdcf2c 100644 --- a/src/components/molecules/news/HeroBlogPost.tsx +++ b/src/components/molecules/news/HeroBlogPost.tsx @@ -37,7 +37,8 @@ export default function HeroBlogPost(props: BlogPost) { sx={{ position: "absolute", inset: 0, - background: "linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.4) 50%, rgba(0,0,0,0.1) 100%)", + background: + "linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.4) 50%, rgba(0,0,0,0.1) 100%)", }} /> ; export const Default: Story = { args: { - "title": "Progress #33: It's been a while!", - "slug": "progress-33-its-been-a-while", - "author": "Gilles", - "createDateTime": "2025-05-03T03:07:24.470778Z", - "type": "weekly", - "imageUrl": "https://unitystationfile.b-cdn.net/WeeklyBlogUpdates/33/sillylights.webp", - "summary": "New mobs use the same systems as players, simple bots are back and talky, puddles are real, traps are live, emissive lights got cooler, and Linux builds finally work. We’ve got a new permissions system, character voices, a flatpacking machine, speech-to-text, and a mountain of bugfixes. It's been a big one.", - "state": "published", + title: "Progress #33: It's been a while!", + slug: "progress-33-its-been-a-while", + author: "Gilles", + createDateTime: "2025-05-03T03:07:24.470778Z", + type: "weekly", + imageUrl: "https://unitystationfile.b-cdn.net/WeeklyBlogUpdates/33/sillylights.webp", + summary: + "New mobs use the same systems as players, simple bots are back and talky, puddles are real, traps are live, emissive lights got cooler, and Linux builds finally work. We’ve got a new permissions system, character voices, a flatpacking machine, speech-to-text, and a mountain of bugfixes. It's been a big one.", + state: "published", }, -}; \ No newline at end of file +}; diff --git a/src/components/molecules/news/SmallBlogPostPreview.tsx b/src/components/molecules/news/SmallBlogPostPreview.tsx index e5193cb..11c601f 100644 --- a/src/components/molecules/news/SmallBlogPostPreview.tsx +++ b/src/components/molecules/news/SmallBlogPostPreview.tsx @@ -22,18 +22,12 @@ export default function SmallBlogPostPreview(props: BlogPost) { > - {title} + {title} - - {title} - + {title} {byline} diff --git a/src/components/molecules/preferences/PreferenceCategory.tsx b/src/components/molecules/preferences/PreferenceCategory.tsx index b92316f..cddc6cf 100644 --- a/src/components/molecules/preferences/PreferenceCategory.tsx +++ b/src/components/molecules/preferences/PreferenceCategory.tsx @@ -18,13 +18,7 @@ export default function PreferenceCategory(props: PreferenceCategoryProps) { if (schema.layout) { const CustomLayout = customLayouts[schema.layout]; if (CustomLayout) { - return ( - - ); + return ; } } @@ -35,16 +29,20 @@ export default function PreferenceCategory(props: PreferenceCategoryProps) { return ( {schema.fields.map((field) => { - const value = typeof categoryData === "object" && categoryData !== null - ? (categoryData as unknown as Record)[field.key] - : undefined; + const value = + typeof categoryData === "object" && categoryData !== null + ? (categoryData as unknown as Record)[field.key] + : undefined; return ( updateField(schema.key, field.key, newValue))} + onChange={ + fieldOverrides?.[field.key] ?? + ((newValue) => updateField(schema.key, field.key, newValue)) + } /> ); })} @@ -59,9 +57,7 @@ export default function PreferenceCategory(props: PreferenceCategoryProps) { {schema.label} - - {renderFields()} - + {renderFields()} ); } diff --git a/src/components/molecules/preferences/PreferenceInputFieldRow.stories.tsx b/src/components/molecules/preferences/PreferenceInputFieldRow.stories.tsx index 303e1e6..2462471 100644 --- a/src/components/molecules/preferences/PreferenceInputFieldRow.stories.tsx +++ b/src/components/molecules/preferences/PreferenceInputFieldRow.stories.tsx @@ -41,4 +41,3 @@ export const Number: Story = { value: 60, }, }; - diff --git a/src/components/molecules/preferences/PreferencePathFieldRow.stories.tsx b/src/components/molecules/preferences/PreferencePathFieldRow.stories.tsx index d73854b..3b75377 100644 --- a/src/components/molecules/preferences/PreferencePathFieldRow.stories.tsx +++ b/src/components/molecules/preferences/PreferencePathFieldRow.stories.tsx @@ -28,4 +28,3 @@ export default meta; type Story = StoryObj; export const Default: Story = {}; - diff --git a/src/components/molecules/preferences/PreferencePathFieldRow.tsx b/src/components/molecules/preferences/PreferencePathFieldRow.tsx index 918399b..0fd8b55 100644 --- a/src/components/molecules/preferences/PreferencePathFieldRow.tsx +++ b/src/components/molecules/preferences/PreferencePathFieldRow.tsx @@ -18,11 +18,7 @@ export default function PreferencePathFieldRow(props: PreferencePathFieldRowProp - + ); } - diff --git a/src/components/molecules/preferences/PreferenceSelectFieldRow.stories.tsx b/src/components/molecules/preferences/PreferenceSelectFieldRow.stories.tsx index 885495a..6605de7 100644 --- a/src/components/molecules/preferences/PreferenceSelectFieldRow.stories.tsx +++ b/src/components/molecules/preferences/PreferenceSelectFieldRow.stories.tsx @@ -36,4 +36,3 @@ export const WithoutOptions: Story = { value: "", }, }; - diff --git a/src/components/molecules/preferences/PreferenceToggleFieldRow.stories.tsx b/src/components/molecules/preferences/PreferenceToggleFieldRow.stories.tsx index c369389..dcc7278 100644 --- a/src/components/molecules/preferences/PreferenceToggleFieldRow.stories.tsx +++ b/src/components/molecules/preferences/PreferenceToggleFieldRow.stories.tsx @@ -37,4 +37,3 @@ export const Disabled: Story = { value: false, }, }; - diff --git a/src/components/molecules/preferences/PreferenceToggleFieldRow.tsx b/src/components/molecules/preferences/PreferenceToggleFieldRow.tsx index 141a0c0..2bd56bb 100644 --- a/src/components/molecules/preferences/PreferenceToggleFieldRow.tsx +++ b/src/components/molecules/preferences/PreferenceToggleFieldRow.tsx @@ -13,15 +13,9 @@ export default function PreferenceToggleFieldRow(props: PreferenceToggleFieldRow const { label, tooltip, value, onChange } = props; return ( - + - onChange(e.target.checked)} - /> + onChange(e.target.checked)} /> ); } diff --git a/src/components/molecules/preferences/customLayouts/TtsPreferencesLayout.tsx b/src/components/molecules/preferences/customLayouts/TtsPreferencesLayout.tsx index dafe594..de0ad73 100644 --- a/src/components/molecules/preferences/customLayouts/TtsPreferencesLayout.tsx +++ b/src/components/molecules/preferences/customLayouts/TtsPreferencesLayout.tsx @@ -14,7 +14,11 @@ function getStatusChipColor(status: number | null): "neutral" | "success" | "war return "success"; } - if (status === TTS_STATUS.Downloading || status === TTS_STATUS.Installing || status === TTS_STATUS.CheckingForUpdates) { + if ( + status === TTS_STATUS.Downloading || + status === TTS_STATUS.Installing || + status === TTS_STATUS.CheckingForUpdates + ) { return "primary"; } @@ -46,9 +50,7 @@ export default function TtsPreferencesLayout(props: TtsPreferencesLayoutProps) { runCommand, } = useTtsPreferencesContext(); - const statusLabel = status !== null - ? (TTS_STATUS_LABELS[status] ?? `Status ${status}`) - : "Unknown"; + const statusLabel = status !== null ? (TTS_STATUS_LABELS[status] ?? `Status ${status}`) : "Unknown"; const installButtonLabel = isInstalled ? "Reinstall HonkTTS" : "Install HonkTTS"; @@ -114,16 +116,37 @@ export default function TtsPreferencesLayout(props: TtsPreferencesLayoutProps) { - - - - diff --git a/src/components/molecules/servers/ServerCardDetails.tsx b/src/components/molecules/servers/ServerCardDetails.tsx index 9c7d289..d6e536a 100644 --- a/src/components/molecules/servers/ServerCardDetails.tsx +++ b/src/components/molecules/servers/ServerCardDetails.tsx @@ -13,14 +13,7 @@ interface ServerCardDetailsProps { } export default function ServerCardDetails(props: ServerCardDetailsProps) { - const { - map, - build, - roundTime, - pingMs, - playersOnline, - playerCapacity, - } = props; + const { map, build, roundTime, pingMs, playersOnline, playerCapacity } = props; return ( diff --git a/src/components/molecules/servers/ServerCardHeader.tsx b/src/components/molecules/servers/ServerCardHeader.tsx index 28fc29e..87f0f9d 100644 --- a/src/components/molecules/servers/ServerCardHeader.tsx +++ b/src/components/molecules/servers/ServerCardHeader.tsx @@ -11,14 +11,9 @@ export default function ServerCardHeader(props: ServerCardHeaderProps) { return ( - - {name} - + {name} }> - + Now playing: {mode} diff --git a/src/components/molecules/servers/serverCardActions.tsx b/src/components/molecules/servers/serverCardActions.tsx index 02c92ac..cad362e 100644 --- a/src/components/molecules/servers/serverCardActions.tsx +++ b/src/components/molecules/servers/serverCardActions.tsx @@ -107,14 +107,21 @@ export function resolveServerAction( const resolvedActionState = actionState ?? inferActionState(actionLabel); const resolvedActionLabel = actionLabel ?? defaultActionLabelByState[resolvedActionState]; const actionVisual = actionVisualByState[resolvedActionState]; - const isBusyAction = resolvedActionState === "downloading" || resolvedActionState === "extracting" || resolvedActionState === "scanning" || resolvedActionState === "playing"; - const isDeterminate = resolvedActionState === "downloading" || resolvedActionState === "downloadFailed" || resolvedActionState === "scanningFailed"; + const isBusyAction = + resolvedActionState === "downloading" || + resolvedActionState === "extracting" || + resolvedActionState === "scanning" || + resolvedActionState === "playing"; + const isDeterminate = + resolvedActionState === "downloading" || + resolvedActionState === "downloadFailed" || + resolvedActionState === "scanningFailed"; return { resolvedActionState, resolvedActionLabel, actionVisual, isBusyAction, - isDeterminate + isDeterminate, }; } diff --git a/src/components/molecules/sideBar/SideBarExternalLink.stories.tsx b/src/components/molecules/sideBar/SideBarExternalLink.stories.tsx index 720155e..e23da31 100644 --- a/src/components/molecules/sideBar/SideBarExternalLink.stories.tsx +++ b/src/components/molecules/sideBar/SideBarExternalLink.stories.tsx @@ -20,8 +20,7 @@ const meta = { ), ], args: { - onClick: () => { - }, + onClick: () => {}, }, } satisfies Meta; diff --git a/src/components/molecules/sideBar/SideBarExternalLink.tsx b/src/components/molecules/sideBar/SideBarExternalLink.tsx index a5dbd50..7fc90d0 100644 --- a/src/components/molecules/sideBar/SideBarExternalLink.tsx +++ b/src/components/molecules/sideBar/SideBarExternalLink.tsx @@ -1,5 +1,5 @@ -import {Avatar, Tooltip} from "@mui/joy"; -import {type JSX} from "react"; +import { Avatar, Tooltip } from "@mui/joy"; +import { type JSX } from "react"; export interface SideBarExternalLinkProps { tooltip: string; @@ -8,7 +8,7 @@ export interface SideBarExternalLinkProps { } export default function SideBarExternalLink(props: SideBarExternalLinkProps) { - const {tooltip, icon, onClick} = props; + const { tooltip, icon, onClick } = props; return ( @@ -28,5 +28,5 @@ export default function SideBarExternalLink(props: SideBarExternalLinkProps) { {icon} - ) + ); } diff --git a/src/components/molecules/sideBar/SideBarMenuItem.stories.tsx b/src/components/molecules/sideBar/SideBarMenuItem.stories.tsx index 7873df4..1ce24d9 100644 --- a/src/components/molecules/sideBar/SideBarMenuItem.stories.tsx +++ b/src/components/molecules/sideBar/SideBarMenuItem.stories.tsx @@ -20,8 +20,7 @@ const meta = { ), ], args: { - onClick: () => { - }, + onClick: () => {}, }, } satisfies Meta; diff --git a/src/components/molecules/sideBar/SideBarMenuItem.tsx b/src/components/molecules/sideBar/SideBarMenuItem.tsx index 6fb7180..ff82386 100644 --- a/src/components/molecules/sideBar/SideBarMenuItem.tsx +++ b/src/components/molecules/sideBar/SideBarMenuItem.tsx @@ -15,10 +15,8 @@ export default function SideBarMenuItem(props: SideBarMenuItemProps) { {icon} - - {text} - + {text} - ) + ); } diff --git a/src/components/molecules/update/ReleaseNotesCard.tsx b/src/components/molecules/update/ReleaseNotesCard.tsx index 30ef69f..4f76855 100644 --- a/src/components/molecules/update/ReleaseNotesCard.tsx +++ b/src/components/molecules/update/ReleaseNotesCard.tsx @@ -27,51 +27,54 @@ export default function ReleaseNotesCard(props: ReleaseNotesCardProps) { const { content } = props; return ( - - - + bgcolor: "background.surface", + maxHeight: 220, + overflow: "auto", + position: "relative", + }} + > + + What's new - + {content} diff --git a/src/components/organisms/common/PuduStepper.tsx b/src/components/organisms/common/PuduStepper.tsx index 0772b09..88de9be 100644 --- a/src/components/organisms/common/PuduStepper.tsx +++ b/src/components/organisms/common/PuduStepper.tsx @@ -20,7 +20,7 @@ export default function PuduStepper(props: PuduStepperProps) { const steps = Array.from({ length: stepCount }, (_, index) => index + 1); return ( - + {steps.map((stepNumber) => { const isCompleted = isComplete || stepNumber < activeStep; const isCurrent = !isComplete && stepNumber === activeStep; @@ -32,10 +32,7 @@ export default function PuduStepper(props: PuduStepperProps) { key={stepNumber} orientation="vertical" indicator={ - + {isCompleted ? : stepNumber - 1 + startNumber} } @@ -45,5 +42,5 @@ export default function PuduStepper(props: PuduStepperProps) { ); })} - ) + ); } diff --git a/src/components/organisms/installations/InstallationCardList.tsx b/src/components/organisms/installations/InstallationCardList.tsx index 9a43792..24ebf65 100644 --- a/src/components/organisms/installations/InstallationCardList.tsx +++ b/src/components/organisms/installations/InstallationCardList.tsx @@ -11,9 +11,7 @@ export default function InstallationCardList() { - - Loading installations... - + Loading installations... )} diff --git a/src/components/organisms/servers/ServerCard.stories.tsx b/src/components/organisms/servers/ServerCard.stories.tsx index 88c71a3..a7b215d 100644 --- a/src/components/organisms/servers/ServerCard.stories.tsx +++ b/src/components/organisms/servers/ServerCard.stories.tsx @@ -1,6 +1,6 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import type { Meta, StoryObj } from "@storybook/react-vite"; -import ServerCard from './ServerCard'; +import ServerCard from "./ServerCard"; import { Box, GlobalStyles } from "@mui/joy"; const meta = { @@ -24,21 +24,25 @@ const meta = { decorators: [ (Story) => ( <> - - + + ), - ] + ], } satisfies Meta; export default meta; @@ -63,7 +67,6 @@ export const Downloading: Story = { }, }; - export const Scanning: Story = { args: { actionLabel: "Scanning", diff --git a/src/components/organisms/servers/ServerCard.tsx b/src/components/organisms/servers/ServerCard.tsx index a0a76a5..7f70de6 100644 --- a/src/components/organisms/servers/ServerCard.tsx +++ b/src/components/organisms/servers/ServerCard.tsx @@ -1,20 +1,11 @@ -import { - AspectRatio, - LinearProgress, - Sheet, - Stack, -} from "@mui/joy"; +import { AspectRatio, LinearProgress, Sheet, Stack } from "@mui/joy"; import ServerCardActionButton from "../../molecules/servers/ServerCardActionButton"; import ServerCardDetails from "../../molecules/servers/ServerCardDetails"; import ServerCardHeader from "../../molecules/servers/ServerCardHeader"; -import {resolveServerAction} from "../../molecules/servers/serverCardActions"; -import type {ServerCardProps} from "./serverCard.types"; +import { resolveServerAction } from "../../molecules/servers/serverCardActions"; +import type { ServerCardProps } from "./serverCard.types"; -export type { - ServerActionState, - ServerCardProgress, - ServerCardProps, -} from "./serverCard.types"; +export type { ServerActionState, ServerCardProgress, ServerCardProps } from "./serverCard.types"; export default function ServerCard(props: ServerCardProps) { const { @@ -34,13 +25,10 @@ export default function ServerCard(props: ServerCardProps) { progress = null, } = props; - const { - resolvedActionState, - resolvedActionLabel, - actionVisual, - isBusyAction, - isDeterminate - } = resolveServerAction(actionLabel, actionState); + const { resolvedActionState, resolvedActionLabel, actionVisual, isBusyAction, isDeterminate } = resolveServerAction( + actionLabel, + actionState, + ); const shouldDisableAction = isActionDisabled || isBusyAction; @@ -48,8 +36,8 @@ export default function ServerCard(props: ServerCardProps) { const progressPercent = isScanningFailed ? 100 : progress - ? Math.round(Math.max(0, Math.min(progress.value, 100))) - : 0; + ? Math.round(Math.max(0, Math.min(progress.value, 100))) + : 0; const hasProgress = isScanningFailed || (progress !== null && progress !== undefined); return ( @@ -63,8 +51,12 @@ export default function ServerCard(props: ServerCardProps) { overflow: "hidden", }} > - - + + - {`${name} + {`${name} - - + + - + ; export default meta; @@ -17,28 +17,36 @@ export default meta; type Story = StoryObj; const renderAtPath = (path: string) => ( - - - - - - - - + + + + + + + + ); export const ServersActive: Story = { - render: () => renderAtPath("/"), + render: () => renderAtPath("/"), }; export const NewsActive: Story = { - render: () => renderAtPath("/news"), + render: () => renderAtPath("/news"), }; export const InstallationsActive: Story = { - render: () => renderAtPath("/installations"), + render: () => renderAtPath("/installations"), }; export const PreferencesActive: Story = { - render: () => renderAtPath("/preferences"), + render: () => renderAtPath("/preferences"), }; diff --git a/src/components/organisms/sideBar/SideBar.tsx b/src/components/organisms/sideBar/SideBar.tsx index e66d70c..e722126 100644 --- a/src/components/organisms/sideBar/SideBar.tsx +++ b/src/components/organisms/sideBar/SideBar.tsx @@ -1,8 +1,4 @@ -import { - Divider, - List, - Stack, Typography -} from "@mui/joy"; +import { Divider, List, Stack, Typography } from "@mui/joy"; import SideBarMenuItem from "../../molecules/sideBar/SideBarMenuItem.tsx"; import SideBarExternalLink from "../../molecules/sideBar/SideBarExternalLink.tsx"; import { useSideBarContext } from "../../../contextProviders/SideBarContextProvider.tsx"; @@ -11,13 +7,19 @@ export default function SideBar() { const { menuItems, externalLinks } = useSideBarContext(); return ( - + }} + > Pudu Launcher @@ -25,7 +27,7 @@ export default function SideBar() { - + {menuItems.map((item) => ( diff --git a/src/components/pages/IpcPermissionPage.tsx b/src/components/pages/IpcPermissionPage.tsx index 3674393..3143ebc 100644 --- a/src/components/pages/IpcPermissionPage.tsx +++ b/src/components/pages/IpcPermissionPage.tsx @@ -1,15 +1,6 @@ import { useEffect, useRef, useState } from "react"; import { useSearchParams } from "react-router"; -import { - Alert, - Box, - Button, - CssBaseline, - CssVarsProvider, - GlobalStyles, - Stack, - Typography, -} from "@mui/joy"; +import { Alert, Box, Button, CssBaseline, CssVarsProvider, GlobalStyles, Stack, Typography } from "@mui/joy"; import { IpcApi } from "../../pudu/generated"; import { useThemeContext } from "../../contextProviders/ThemeProvider"; import { themeRegistry, themeScrollbarRegistry } from "../../themes"; @@ -19,16 +10,13 @@ const isTauri = "__TAURI_INTERNALS__" in window; const POPUP_WIDTH = 420; const requestTypeDescriptions: Record string> = { - "1": (domain) => - `The game wants to open the following URL in your browser: ${domain}`, - "2": (domain) => - `The game wants to send API requests to the following domain: ${domain}`, + "1": (domain) => `The game wants to open the following URL in your browser: ${domain}`, + "2": (domain) => `The game wants to send API requests to the following domain: ${domain}`, "3": () => "The game is requesting trusted mode. This automatically allows every API and URL " + "action without prompts, and enables the Variable Viewer which can modify game data " + "and could potentially perform unwanted actions on your PC.", - "4": () => - "The game wants to access your microphone while it is running.", + "4": () => "The game wants to access your microphone while it is running.", }; export default function IpcPermissionPage() { @@ -119,29 +107,27 @@ export default function IpcPermissionPage() { userSelect: "none", }} > - + Game Permission Request - - {description} - + {description} {justification && ( Justification from the game: - + {justification} @@ -149,8 +135,7 @@ export default function IpcPermissionPage() { {isDangerous && ( - The text above was provided by the game, not by PuduLauncher. - Treat it with caution. + The text above was provided by the game, not by PuduLauncher. Treat it with caution. )} diff --git a/src/components/pages/ServersPage.tsx b/src/components/pages/ServersPage.tsx index 36c74a6..54ede3d 100644 --- a/src/components/pages/ServersPage.tsx +++ b/src/components/pages/ServersPage.tsx @@ -1,7 +1,5 @@ import ServersLayout from "../layouts/ServersLayout"; export default function ServersPage() { - return ( - - ) + return ; } diff --git a/src/constants/ttsStatus.ts b/src/constants/ttsStatus.ts index 2be458d..cad8e86 100644 --- a/src/constants/ttsStatus.ts +++ b/src/constants/ttsStatus.ts @@ -26,10 +26,7 @@ export const TTS_INSTALLED_STATUSES = new Set([ TTS_STATUS.ServerStarting, ]); -export const TTS_INSTALL_SESSION_START_STATUSES = new Set([ - TTS_STATUS.Downloading, - TTS_STATUS.Installing, -]); +export const TTS_INSTALL_SESSION_START_STATUSES = new Set([TTS_STATUS.Downloading, TTS_STATUS.Installing]); export const TTS_INSTALL_SESSION_BUSY_STATUSES = new Set([ TTS_STATUS.CheckingForUpdates, diff --git a/src/contextProviders/DiscordJoinContextProvider.tsx b/src/contextProviders/DiscordJoinContextProvider.tsx index 898d151..6227af0 100644 --- a/src/contextProviders/DiscordJoinContextProvider.tsx +++ b/src/contextProviders/DiscordJoinContextProvider.tsx @@ -1,9 +1,4 @@ -import { - type PropsWithChildren, - useEffect, - useRef, - useState, -} from "react"; +import { type PropsWithChildren, useEffect, useRef, useState } from "react"; import { EventListener } from "../pudu/events/event-listener"; import type { PuduEventMap, PuduEventType } from "../pudu/generated"; import { DiscordApi, type DiscordJoinRequestEvent } from "../pudu/generated"; diff --git a/src/contextProviders/FeedbackContextProvider.tsx b/src/contextProviders/FeedbackContextProvider.tsx index 1038874..657d981 100644 --- a/src/contextProviders/FeedbackContextProvider.tsx +++ b/src/contextProviders/FeedbackContextProvider.tsx @@ -1,11 +1,4 @@ -import { - createContext, - type PropsWithChildren, - useContext, - useEffect, - useRef, - useState, -} from "react"; +import { createContext, type PropsWithChildren, useContext, useEffect, useRef, useState } from "react"; import { CircularProgress, Modal, ModalDialog, Stack, Typography } from "@mui/joy"; import FatalErrorModal from "../components/molecules/errors/FatalErrorModal"; import FeedbackSnackbar from "../components/molecules/errors/FeedbackSnackbar"; @@ -171,13 +164,7 @@ function SnackbarHost(props: { register: (push: (item: SnackbarItem) => void) => const currentSnackbar = queue[0] ?? null; - return ( - - ); + return ; } export function FeedbackContextProvider(props: PropsWithChildren) { @@ -242,31 +229,37 @@ export function FeedbackContextProvider(props: PropsWithChildren) { }; const showError = (input: ErrorReportInput) => { - pushError({ - id: createId(), - severity: "error", - source: input.source, - userMessage: input.userMessage, - code: input.code, - technicalDetails: input.technicalDetails, - correlationId: input.correlationId, - isTransient: input.isTransient ?? true, - timestamp: new Date().toISOString(), - }, input.dedupe ?? true); + pushError( + { + id: createId(), + severity: "error", + source: input.source, + userMessage: input.userMessage, + code: input.code, + technicalDetails: input.technicalDetails, + correlationId: input.correlationId, + isTransient: input.isTransient ?? true, + timestamp: new Date().toISOString(), + }, + input.dedupe ?? true, + ); }; const showFatal = (input: ErrorReportInput) => { - pushError({ - id: createId(), - severity: "fatal", - source: input.source, - userMessage: input.userMessage, - code: input.code, - technicalDetails: input.technicalDetails, - correlationId: input.correlationId, - isTransient: false, - timestamp: new Date().toISOString(), - }, input.dedupe ?? true); + pushError( + { + id: createId(), + severity: "fatal", + source: input.source, + userMessage: input.userMessage, + code: input.code, + technicalDetails: input.technicalDetails, + correlationId: input.correlationId, + isTransient: false, + timestamp: new Date().toISOString(), + }, + input.dedupe ?? true, + ); }; const showSuccess = (input: FeedbackInput) => pushSnackbar("success", input); @@ -319,9 +312,7 @@ export function FeedbackContextProvider(props: PropsWithChildren) { // Catch unhandled frontend errors globally. useEffect(() => { const onError = (event: ErrorEvent) => { - const details = event.error instanceof Error - ? event.error.stack ?? event.error.message - : event.message; + const details = event.error instanceof Error ? (event.error.stack ?? event.error.message) : event.message; showFatal({ source: "frontend.window-error", @@ -333,9 +324,7 @@ export function FeedbackContextProvider(props: PropsWithChildren) { const onUnhandledRejection = (event: PromiseRejectionEvent) => { const reason = event.reason; - const details = reason instanceof Error - ? reason.stack ?? reason.message - : String(reason); + const details = reason instanceof Error ? (reason.stack ?? reason.message) : String(reason); showFatal({ source: "frontend.unhandled-rejection", @@ -368,13 +357,20 @@ export function FeedbackContextProvider(props: PropsWithChildren) { return ( - {backendReady ? children : ( + {backendReady ? ( + children + ) : ( - - - PuduLauncher - + + PuduLauncher diff --git a/src/contextProviders/InstallationsContextProvider.tsx b/src/contextProviders/InstallationsContextProvider.tsx index 1ee679e..cb40a16 100644 --- a/src/contextProviders/InstallationsContextProvider.tsx +++ b/src/contextProviders/InstallationsContextProvider.tsx @@ -264,11 +264,7 @@ export function InstallationsContextProvider(props: PropsWithChildren) { openInstallationsFolder, }; - return ( - - {children} - - ); + return {children}; } export function useInstallationsContext() { diff --git a/src/contextProviders/IpcContextProvider.tsx b/src/contextProviders/IpcContextProvider.tsx index df65eef..80f3ba2 100644 --- a/src/contextProviders/IpcContextProvider.tsx +++ b/src/contextProviders/IpcContextProvider.tsx @@ -1,8 +1,4 @@ -import { - type PropsWithChildren, - useEffect, - useRef, -} from "react"; +import { type PropsWithChildren, useEffect, useRef } from "react"; import { EventListener } from "../pudu/events/event-listener"; import type { IpcPermissionRequestEvent } from "../pudu/generated"; import { log } from "../pudu/log"; diff --git a/src/contextProviders/NewsContextProvider.tsx b/src/contextProviders/NewsContextProvider.tsx index e863649..6abbaee 100644 --- a/src/contextProviders/NewsContextProvider.tsx +++ b/src/contextProviders/NewsContextProvider.tsx @@ -170,11 +170,7 @@ export function NewsContextProvider(props: PropsWithChildren) { setPaused: setIsPaused, }; - return ( - - {children} - - ); + return {children}; } export function useNewsContext() { diff --git a/src/contextProviders/OnboardingContextProvider.tsx b/src/contextProviders/OnboardingContextProvider.tsx index 94ed48d..5b4da3b 100644 --- a/src/contextProviders/OnboardingContextProvider.tsx +++ b/src/contextProviders/OnboardingContextProvider.tsx @@ -1,10 +1,10 @@ -import {createContext, type PropsWithChildren, useContext, useEffect, useRef, useState} from "react"; -import {Alert, Box, Modal, ModalDialog, Stack, Typography} from "@mui/joy"; -import {OnboardingApi, type OnboardingStep} from "../pudu/generated"; -import {FeedbackContext} from "./FeedbackContextProvider"; -import {onboardingStepRegistry} from "./onboardingStepRegistry"; +import { createContext, type PropsWithChildren, useContext, useEffect, useRef, useState } from "react"; +import { Alert, Box, Modal, ModalDialog, Stack, Typography } from "@mui/joy"; +import { OnboardingApi, type OnboardingStep } from "../pudu/generated"; +import { FeedbackContext } from "./FeedbackContextProvider"; +import { onboardingStepRegistry } from "./onboardingStepRegistry"; import OnboardingProgressDots from "../components/layouts/onboarding/OnboardingProgressDots"; -import {OnboardingAnimatedContent, OnboardingBackground} from "../components/layouts/onboarding/OnboardingStepShell"; +import { OnboardingAnimatedContent, OnboardingBackground } from "../components/layouts/onboarding/OnboardingStepShell"; interface OnboardingContextValue { pendingSteps: OnboardingStep[]; @@ -32,10 +32,9 @@ export interface OnboardingContextProviderProps extends PropsWithChildren { } export function OnboardingContextProvider(props: OnboardingContextProviderProps) { - const {children, createApi, errorReporter} = props; + const { children, createApi, errorReporter } = props; const errorContext = useContext(FeedbackContext); - const showError = errorReporter ?? errorContext?.showError ?? (() => { - }); + const showError = errorReporter ?? errorContext?.showError ?? (() => {}); const buildApi = createApi ?? (() => new OnboardingApi()); const seenStepIdsRef = useRef(new Set()); @@ -161,9 +160,7 @@ export function OnboardingContextProvider(props: OnboardingContextProviderProps) advanceQueue(); }; - const ActiveStepComponent = activeStep - ? onboardingStepRegistry[activeStep.componentKey] - : null; + const ActiveStepComponent = activeStep ? onboardingStepRegistry[activeStep.componentKey] : null; const value: OnboardingContextValue = { pendingSteps, @@ -172,40 +169,30 @@ export function OnboardingContextProvider(props: OnboardingContextProviderProps) }; const missingComponentReferenceWarning = () => ( - - - {activeStep?.title ?? "Onboarding step"} - + + {activeStep?.title ?? "Onboarding step"} No component is registered for onboarding key "{activeStep?.componentKey}". {activeStep?.description && ( <> - - Description was: - - - {activeStep.description} - + Description was: + {activeStep.description} )} ); const totalSteps = Math.max(allSteps.length, 1); - const activeStepIndex = activeStep - ? allSteps.findIndex((s) => s.id === activeStep.id) - : 0; + const activeStepIndex = activeStep ? allSteps.findIndex((s) => s.id === activeStep.id) : 0; return ( - {isLoading && ( - - )} + {isLoading && } {!isLoading && children} - + - + {ActiveStepComponent ? ( - ) : missingComponentReferenceWarning()} + ) : ( + missingComponentReferenceWarning() + )} {totalSteps > 1 && ( - + = 0 ? activeStepIndex : 0} diff --git a/src/contextProviders/PreferencesContextProvider.tsx b/src/contextProviders/PreferencesContextProvider.tsx index be0b5cc..2cc9e08 100644 --- a/src/contextProviders/PreferencesContextProvider.tsx +++ b/src/contextProviders/PreferencesContextProvider.tsx @@ -165,11 +165,7 @@ export function PreferencesContextProvider(props: PropsWithChildren) { moveInstallationPath, }; - return ( - - {children} - - ); + return {children}; } export function usePreferencesContext() { diff --git a/src/contextProviders/ServersContextProvider.tsx b/src/contextProviders/ServersContextProvider.tsx index c691826..46d5f87 100644 --- a/src/contextProviders/ServersContextProvider.tsx +++ b/src/contextProviders/ServersContextProvider.tsx @@ -72,11 +72,7 @@ export function ServersContextProvider(props: PropsWithChildren) { lastUpdatedLabel, }; - return ( - - {children} - - ); + return {children}; } export function useServersContext() { diff --git a/src/contextProviders/SideBarContextProvider.tsx b/src/contextProviders/SideBarContextProvider.tsx index c4690a0..899f17b 100644 --- a/src/contextProviders/SideBarContextProvider.tsx +++ b/src/contextProviders/SideBarContextProvider.tsx @@ -1,25 +1,13 @@ -import { - Favorite, - Message, - Newspaper, - Public, - Save, - Settings, - VideogameAsset -} from "@mui/icons-material"; +import { Favorite, Message, Newspaper, Public, Save, Settings, VideogameAsset } from "@mui/icons-material"; import { openUrl } from "@tauri-apps/plugin-opener"; -import { - createContext, - type PropsWithChildren, - useContext -} from "react"; +import { createContext, type PropsWithChildren, useContext } from "react"; import { useMatch, useNavigate } from "react-router"; import { SideBarMenuItemProps } from "../components/molecules/sideBar/SideBarMenuItem"; import { SideBarExternalLinkProps } from "../components/molecules/sideBar/SideBarExternalLink"; import { UNITYSTATION_DISCORD_URL, UNITYSTATION_PATREON_URL, - UNITYSTATION_WEBSITE_URL + UNITYSTATION_WEBSITE_URL, } from "../constants/externalLinks"; interface SideBarContextValue { @@ -94,11 +82,7 @@ export function SideBarContextProvider(props: PropsWithChildren) { externalLinks, }; - return ( - - {children} - - ); + return {children}; } export function useSideBarContext() { diff --git a/src/contextProviders/StepContextProvider.tsx b/src/contextProviders/StepContextProvider.tsx index 3cf2168..d2d2a7f 100644 --- a/src/contextProviders/StepContextProvider.tsx +++ b/src/contextProviders/StepContextProvider.tsx @@ -35,19 +35,19 @@ export function StepContextProvider(props: StepContextProps) { }; return ( - + {props.children} ); - } - export function useStepContext() { const context = useContext(StepContext); if (!context) { @@ -55,4 +55,4 @@ export function useStepContext() { } return context; -} \ No newline at end of file +} diff --git a/src/contextProviders/ThemeProvider.tsx b/src/contextProviders/ThemeProvider.tsx index a1bea5b..6e0ff7f 100644 --- a/src/contextProviders/ThemeProvider.tsx +++ b/src/contextProviders/ThemeProvider.tsx @@ -21,9 +21,7 @@ const THEME_ID_TO_PREFERENCE: Record = { vapor: "Vapor", }; -const normalizeThemeToken = (value: string): string => ( - value.toLowerCase().replace(/[^a-z0-9]/g, "") -); +const normalizeThemeToken = (value: string): string => value.toLowerCase().replace(/[^a-z0-9]/g, ""); const THEME_TOKEN_TO_ID: Record = Object.entries(themeRegistry).reduce( (accumulator, [themeId]) => { @@ -38,9 +36,7 @@ Object.entries(THEME_ID_TO_PREFERENCE).forEach(([themeId, preferenceValue]) => { THEME_TOKEN_TO_ID[normalizeThemeToken(preferenceValue)] = themeId as ThemeId; }); -const isThemeId = (value: unknown): value is ThemeId => ( - typeof value === "string" && value in themeRegistry -); +const isThemeId = (value: unknown): value is ThemeId => typeof value === "string" && value in themeRegistry; const parseThemeId = (value: unknown): ThemeId | null => { if (isThemeId(value)) { @@ -102,14 +98,12 @@ export function ThemeProvider(props: PropsWithChildren) { } })(); - return () => { cancelled = true; }; + return () => { + cancelled = true; + }; }, []); - return ( - - {props.children} - - ); + return {props.children}; } export function useThemeContext() { diff --git a/src/contextProviders/TtsInstallerContextProvider.tsx b/src/contextProviders/TtsInstallerContextProvider.tsx index e859972..98a0e70 100644 --- a/src/contextProviders/TtsInstallerContextProvider.tsx +++ b/src/contextProviders/TtsInstallerContextProvider.tsx @@ -1,6 +1,11 @@ import { createContext, type PropsWithChildren, useContext, useEffect, useRef, useState } from "react"; import TtsInstallerLayout from "../components/layouts/tts/TtsInstallerLayout"; -import { TTS_INSTALL_SESSION_BUSY_STATUSES, TTS_INSTALL_SESSION_START_STATUSES, TTS_STATUS, TTS_STATUS_LABELS } from "../constants/ttsStatus"; +import { + TTS_INSTALL_SESSION_BUSY_STATUSES, + TTS_INSTALL_SESSION_START_STATUSES, + TTS_STATUS, + TTS_STATUS_LABELS, +} from "../constants/ttsStatus"; import { useFeedbackContext } from "./FeedbackContextProvider"; import { useTtsState } from "./TtsStateContextProvider"; @@ -109,11 +114,10 @@ export function TtsInstallerContextProvider(props: PropsWithChildren) { setIsInstallerOpen(true); } - if (installSessionRef.current && ( - status === TTS_STATUS.Installed - || status === TTS_STATUS.NotInstalled - || status === TTS_STATUS.Error - )) { + if ( + installSessionRef.current && + (status === TTS_STATUS.Installed || status === TTS_STATUS.NotInstalled || status === TTS_STATUS.Error) + ) { setIsInstallerOpen(true); } @@ -171,9 +175,7 @@ export function TtsInstallerContextProvider(props: PropsWithChildren) { closeInstaller, }; - const statusLabel = status !== null - ? (TTS_STATUS_LABELS[status] ?? `Status ${status}`) - : "Unknown"; + const statusLabel = status !== null ? (TTS_STATUS_LABELS[status] ?? `Status ${status}`) : "Unknown"; // Derive the active step from the log contents on every render instead of // tracking it incrementally. An incremental index cursor desynced from // installLogs whenever the shared log array was cleared for a new session, @@ -184,17 +186,15 @@ export function TtsInstallerContextProvider(props: PropsWithChildren) { const parsed = inferStepFromLogLine(line); return parsed === null ? maxStep : Math.max(maxStep, parsed); }, 1); - const currentStep = Math.min( - Math.max(stepFromLogs, stepFromStatus(status)), - INSTALL_STEP_LABELS.length, - ); + const currentStep = Math.min(Math.max(stepFromLogs, stepFromStatus(status)), INSTALL_STEP_LABELS.length); const isInstallComplete = status === TTS_STATUS.Installed; const stepStatusMessage = isInstallComplete ? INSTALL_SUCCESS_MESSAGE : (INSTALL_STEP_STATUS_MESSAGES[currentStep - 1] ?? statusMessage ?? statusLabel); - const longStepWarning = isBusy && INSTALL_LONG_RUNNING_STEPS.has(currentStep) - ? "This step can take a few minutes. If it looks stuck, please wait. It's still working" - : null; + const longStepWarning = + isBusy && INSTALL_LONG_RUNNING_STEPS.has(currentStep) + ? "This step can take a few minutes. If it looks stuck, please wait. It's still working" + : null; const canRenderModal = isInstallerOpen && installSessionRef.current; diff --git a/src/contextProviders/TtsPreferencesContextProvider.tsx b/src/contextProviders/TtsPreferencesContextProvider.tsx index 9ab441c..2455faa 100644 --- a/src/contextProviders/TtsPreferencesContextProvider.tsx +++ b/src/contextProviders/TtsPreferencesContextProvider.tsx @@ -85,11 +85,7 @@ export function TtsPreferencesContextProvider(props: PropsWithChildren) { runCommand, }; - return ( - - {children} - - ); + return {children}; } export function useTtsPreferencesContext() { @@ -106,9 +102,5 @@ export interface TtsPreferencesTestProviderProps extends PropsWithChildren { } export function TtsPreferencesTestProvider(props: TtsPreferencesTestProviderProps) { - return ( - - {props.children} - - ); + return {props.children}; } diff --git a/src/contextProviders/TtsStateContextProvider.tsx b/src/contextProviders/TtsStateContextProvider.tsx index b8447da..3d94523 100644 --- a/src/contextProviders/TtsStateContextProvider.tsx +++ b/src/contextProviders/TtsStateContextProvider.tsx @@ -106,15 +106,15 @@ export function TtsStateContextProvider(props: PropsWithChildren) { return { ...previous, status: event.status, - errorMessage: event.status === TTS_STATUS.Error - ? event.message ?? previous.errorMessage - : null, + errorMessage: event.status === TTS_STATUS.Error ? (event.message ?? previous.errorMessage) : null, }; }); - if (event.status === TTS_STATUS.Installed - || event.status === TTS_STATUS.NotInstalled - || event.status === TTS_STATUS.Error) { + if ( + event.status === TTS_STATUS.Installed || + event.status === TTS_STATUS.NotInstalled || + event.status === TTS_STATUS.Error + ) { void loadStatus(); } }); @@ -187,11 +187,7 @@ export function TtsStateContextProvider(props: PropsWithChildren) { clearInstallLogs, }; - return ( - - {children} - - ); + return {children}; } export function useTtsState() { diff --git a/src/contextProviders/UpdateContextProvider.tsx b/src/contextProviders/UpdateContextProvider.tsx index 6eae7e7..dc6a0c5 100644 --- a/src/contextProviders/UpdateContextProvider.tsx +++ b/src/contextProviders/UpdateContextProvider.tsx @@ -76,7 +76,9 @@ export function UpdateContextProvider(props: PropsWithChildren) { } })(); - return () => { disposed = true; }; + return () => { + disposed = true; + }; }, []); const startUpdate = () => { @@ -145,7 +147,9 @@ export function UpdateContextProvider(props: PropsWithChildren) { onStartUpdate={startUpdate} onOpenReleasesPage={openReleasesPage} /> - ) : children} + ) : ( + children + )} ); } diff --git a/src/contextProviders/onboardingStepRegistry.tsx b/src/contextProviders/onboardingStepRegistry.tsx index ebb37f6..66702c9 100644 --- a/src/contextProviders/onboardingStepRegistry.tsx +++ b/src/contextProviders/onboardingStepRegistry.tsx @@ -13,7 +13,7 @@ export interface OnboardingStepComponentProps { export type OnboardingStepComponent = ComponentType; export const onboardingStepRegistry: Record = { - "welcome": WelcomeLayout, + welcome: WelcomeLayout, "launcher-basics": LauncherBasicsLayout, "all-ready": AllReadyLayout, }; diff --git a/src/contextProviders/servers.resolvers.ts b/src/contextProviders/servers.resolvers.ts index f19a826..b1223ee 100644 --- a/src/contextProviders/servers.resolvers.ts +++ b/src/contextProviders/servers.resolvers.ts @@ -48,9 +48,7 @@ export function resolveMapName(server: GameServer): string { return "Unknown map"; } - return rawMap - .replace(/^MainStations\//, "") - .replace(/\.json$/i, ""); + return rawMap.replace(/^MainStations\//, "").replace(/\.json$/i, ""); } function downloadStateToActionState(state: number): ServerActionState { diff --git a/src/contextProviders/useServerState.ts b/src/contextProviders/useServerState.ts index 15c4aed..22988c9 100644 --- a/src/contextProviders/useServerState.ts +++ b/src/contextProviders/useServerState.ts @@ -300,9 +300,7 @@ export function useServerState(options: UseServerStateOptions) { dedupe: false, }); } catch (error: unknown) { - const errorMessage = error instanceof Error - ? error.message - : "Failed to start download."; + const errorMessage = error instanceof Error ? error.message : "Failed to start download."; setDownloads((prev) => { const next = new Map(prev); diff --git a/src/devtools/DevToolsPage.tsx b/src/devtools/DevToolsPage.tsx index b9a7e61..077d197 100644 --- a/src/devtools/DevToolsPage.tsx +++ b/src/devtools/DevToolsPage.tsx @@ -39,11 +39,7 @@ function RequestLogRow({ entry }: { entry: RequestLogEntry }) { borderRadius: "sm", cursor: "pointer", borderLeftWidth: 3, - borderLeftColor: hasError - ? "danger.400" - : entry.wasMocked - ? "success.400" - : "neutral.400", + borderLeftColor: hasError ? "danger.400" : entry.wasMocked ? "success.400" : "neutral.400", }} onClick={() => setExpanded(!expanded)} > @@ -89,7 +85,9 @@ function RequestLogRow({ entry }: { entry: RequestLogEntry }) { {entry.requestBody !== null && ( - Request Body + + Request Body +
                                     {JSON.stringify(entry.requestBody, null, 2)}
@@ -100,7 +98,9 @@ function RequestLogRow({ entry }: { entry: RequestLogEntry }) {
                     {entry.responseBody !== null && (
                         
                             
-                                Response Body
+                                
+                                    Response Body
+                                
                                 
                         
-                        
+                        
                             
                                 {JSON.stringify(mock.response, null, 2)}
                             
@@ -271,14 +281,39 @@ const EVENT_TYPES: string[] = [ ]; const EVENT_TEMPLATES: Record = { - "discord:join-request": { eventType: "discord:join-request", timestamp: "", serverIp: "123.45.67.89", serverPort: 7777, serverName: "Test Server", forkName: "Unitystation", buildVersion: 1234, gameMode: "Secret", currentMap: "BoxStation", playerCount: 12, playerCountMax: 40, status: 0 }, + "discord:join-request": { + eventType: "discord:join-request", + timestamp: "", + serverIp: "123.45.67.89", + serverPort: 7777, + serverName: "Test Server", + forkName: "Unitystation", + buildVersion: 1234, + gameMode: "Secret", + currentMap: "BoxStation", + playerCount: 12, + playerCountMax: 40, + status: 0, + }, "tts:status-changed": { eventType: "tts:status-changed", timestamp: "", status: 0, message: "" }, - "tts:update-available": { eventType: "tts:update-available", timestamp: "", installedVersion: "1.0.0", latestVersion: "1.1.0" }, + "tts:update-available": { + eventType: "tts:update-available", + timestamp: "", + installedVersion: "1.0.0", + latestVersion: "1.1.0", + }, "tts:install-output": { eventType: "tts:install-output", timestamp: "", line: "" }, "servers:updated": { eventType: "servers:updated", timestamp: "" }, "installations:changed": { eventType: "installations:changed", timestamp: "" }, "game:state-changed": { eventType: "game:state-changed", timestamp: "" }, - "download:progress": { eventType: "download:progress", timestamp: "", downloadId: "", bytesDownloaded: 0, totalBytes: 0, speedBps: 0 }, + "download:progress": { + eventType: "download:progress", + timestamp: "", + downloadId: "", + bytesDownloaded: 0, + totalBytes: 0, + speedBps: 0, + }, "download:state-changed": { eventType: "download:state-changed", timestamp: "", downloadId: "", state: 0 }, }; @@ -295,7 +330,13 @@ interface EventsTabProps { addMock: DevToolsChannelActions["addMock"]; } -function PresetRunner({ injectEvent, addMock }: { injectEvent: DevToolsChannelActions["injectEvent"]; addMock: DevToolsChannelActions["addMock"] }) { +function PresetRunner({ + injectEvent, + addMock, +}: { + injectEvent: DevToolsChannelActions["injectEvent"]; + addMock: DevToolsChannelActions["addMock"]; +}) { const [runningLabel, setRunningLabel] = useState(null); const cancelRef = useRef(false); @@ -338,7 +379,9 @@ function PresetRunner({ injectEvent, addMock }: { injectEvent: DevToolsChannelAc return ( - TTS Presets + + TTS Presets + {ttsPresets.map((preset) => (