diff --git a/.env.local.example b/.env.local.example index e8d18ae..fc4448a 100644 --- a/.env.local.example +++ b/.env.local.example @@ -4,4 +4,5 @@ NEXT_PUBLIC_DISCORD_LINK= # Optional: URL to your community's Discord server. NEXT_PUBLIC_OSU_SERVER_LIST_LINK= # Optional: Link to your osu! osu server list page. NEXT_PUBLIC_KOFI_LINK= # Optional: Your Ko-fi donation page URL. NEXT_PUBLIC_BOOSTY_LINK= # Optional: Your Boosty.to page URL. -NEXT_PUBLIC_STATUS_PAGE_LINK= # Optional: Link to your status page. \ No newline at end of file +NEXT_PUBLIC_STATUS_PAGE_LINK= # Optional: Link to your status page. +NEXT_PUBLIC_PATCHER_PAGE_ENABLED= # Optional: Set to "true" to show the Sunrise Patcher page in the help section. \ No newline at end of file diff --git a/app/(website)/patcher/layout.tsx b/app/(website)/patcher/layout.tsx new file mode 100644 index 0000000..9df7504 --- /dev/null +++ b/app/(website)/patcher/layout.tsx @@ -0,0 +1,17 @@ +import type { Metadata } from "next"; + +import { getT } from "@/lib/i18n/utils"; + +import Page from "./page"; + +export async function generateMetadata(): Promise { + const t = await getT("pages.patcher.meta"); + return { + title: t("title"), + openGraph: { + title: t("title"), + }, + }; +} + +export default Page; diff --git a/app/(website)/patcher/page.tsx b/app/(website)/patcher/page.tsx new file mode 100644 index 0000000..48f4a77 --- /dev/null +++ b/app/(website)/patcher/page.tsx @@ -0,0 +1,156 @@ +"use client"; + +import { + Download, + Eye, + Gauge, + Puzzle, + Settings, + TriangleAlert, +} from "lucide-react"; +import Image from "next/image"; +import Link from "next/link"; + +import PrettyHeader from "@/components/General/PrettyHeader"; +import RoundedContent from "@/components/General/RoundedContent"; +import { Button } from "@/components/ui/button"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { + Carousel, + CarouselContent, + CarouselItem, + CarouselNext, + CarouselPrevious, +} from "@/components/ui/carousel"; +import { useT } from "@/lib/i18n/utils"; + +const PATCHER_DOWNLOAD_URL + = "https://github.com/SunriseCommunity/osu-patcher/releases/latest/download/osu-patcher-for-sunrise-based-server.rar"; + +const ORIGINAL_REPO_URL = "https://github.com/rushiiMachine/osu-patcher"; + +const featureCategories = [ + { key: "relax", icon: }, + { key: "pp", icon: }, + { key: "mods", icon: }, + { key: "ui", icon: }, +] as const; + +const previews = [ + { + key: "settings", + src: "/images/patcher/patcher-settings.png", + }, + { + key: "relaxRanking", + src: "/images/patcher/patcher-relax-ranking.png", + }, + { + key: "ppCounter", + src: "/images/patcher/patcher-pp-counter.png", + }, +] as const; + +export default function Patcher() { + const t = useT("pages.patcher"); + + return ( +
+ } + roundBottom={true} + /> + +
+ } /> + +
+ + + {previews.map(({ key, src }) => ( + +
+ +
+ {t(`previews.${key}.alt`)} +
+ +

+ {t(`previews.${key}.title`)} +

+

+ {t(`previews.${key}.description`)} +

+
+
+
+
+ ))} +
+ + +
+ +

+ {t.rich("description", { + a: chunks => ( + + {chunks} + + ), + })} +

+ +
+ {featureCategories.map(({ key, icon }) => ( + + + + {icon} + {t(`featureSummary.${key}.title`)} + + + + + {t(`featureSummary.${key}.description`)} + + + + ))} +
+ + + +
+ + {t("banchoWarning")} +
+
+
+
+
+ ); +} diff --git a/components/Header/Header.tsx b/components/Header/Header.tsx index 3868cf1..f31a9f6 100644 --- a/components/Header/Header.tsx +++ b/components/Header/Header.tsx @@ -86,6 +86,12 @@ export default function Header() { )} + {process.env.NEXT_PUBLIC_PATCHER_PAGE_ENABLED === "true" && ( + + {t("links.patcher")} + + )} + {(process.env.NEXT_PUBLIC_KOFI_LINK || process.env.NEXT_PUBLIC_BOOSTY_LINK) && ( diff --git a/components/Header/HeaderMobileDrawer.tsx b/components/Header/HeaderMobileDrawer.tsx index 4592d47..61db1ee 100644 --- a/components/Header/HeaderMobileDrawer.tsx +++ b/components/Header/HeaderMobileDrawer.tsx @@ -8,6 +8,7 @@ import { LucideHistory, Menu, MonitorCog, + Puzzle, Search, UserIcon, Users2, @@ -96,6 +97,14 @@ export default function HeaderMobileDrawer() { }, ]; + if (process.env.NEXT_PUBLIC_PATCHER_PAGE_ENABLED === "true") { + list.push({ + icon: , + title: t("navigation.patcher"), + url: "/patcher", + }); + } + if (process.env.NEXT_PUBLIC_DISCORD_LINK) { list.push({ icon: , diff --git a/lib/i18n/messages/en.json b/lib/i18n/messages/en.json index 1271011..16d2f23 100644 --- a/lib/i18n/messages/en.json +++ b/lib/i18n/messages/en.json @@ -105,6 +105,10 @@ "supportUs": { "text": "support us", "context": "Help dropdown menu item for support page" + }, + "patcher": { + "text": "osu! patcher", + "context": "Help dropdown menu item for Sunrise Patcher page" } } }, @@ -315,6 +319,10 @@ "supportUs": { "text": "Support Us", "context": "Mobile drawer navigation item for support page" + }, + "patcher": { + "text": "osu! Patcher", + "context": "Mobile drawer navigation item for Sunrise Patcher page" } }, "yourProfile": { @@ -1072,6 +1080,218 @@ } } }, + "patcher": { + "meta": { + "title": { + "text": "Sunrise Patcher | {appName}", + "context": "The title for the Sunrise Patcher page" + } + }, + "header": { + "text": "Sunrise Patcher", + "context": "The main header text for the patcher page" + }, + "description": { + "text": "Sunrise Patcher is a community fork of rushiiMachine/osu-patcher focused on Relax improvements, live PP tools, and practical osu! quality-of-life fixes.", + "context": "Concise summary of what Sunrise Patcher does with original project credit" + }, + "warning": { + "text": "This is for use in offline play or private servers that allow modifications only. Use at your own risk! Modifications are disallowed on most servers, even though this project does not provide an unfair advantage.", + "context": "Warning about patcher usage restrictions" + }, + "banchoWarning": { + "text": "Using this on official Bancho servers WILL get you banned.", + "context": "Strong warning about using patcher on official servers" + }, + "features": { + "title": { + "text": "Features", + "context": "Section header for the features list" + }, + "relax": { + "title": { + "text": "Relax", + "context": "Feature category title for Relax-related features" + }, + "showMisses": { + "text": "Show misses on hit objects while playing Relax", + "context": "Feature: showing misses during Relax gameplay" + }, + "combobreak": { + "text": "Re-enable combobreak sounds with Relax enabled", + "context": "Feature: combobreak sounds in Relax mode" + }, + "saveScores": { + "text": "Save all Relax scores to local leaderboards automatically", + "context": "Feature: automatic local score saving for Relax" + }, + "allowFailing": { + "text": "Allow failing with Relax enabled (toggleable)", + "context": "Feature: toggleable failing in Relax mode" + }, + "lowHpGlow": { + "text": "Re-enable the low hp glow (with shaders on)", + "context": "Feature: low HP glow effect in Relax mode" + }, + "note": { + "text": "Note: Relax refers to Relax or Autopilot", + "context": "Clarification that Relax features apply to both Relax and Autopilot" + } + }, + "pp": { + "title": { + "text": "PP", + "context": "Feature category title for PP-related features" + }, + "liveCounter": { + "text": "Show a live pp counter during gameplay and replays", + "context": "Feature: live PP counter" + }, + "switchCalculators": { + "text": "Switch between Bancho and Sunrise pp calculators", + "context": "Feature: switchable PP calculators" + } + }, + "mods": { + "title": { + "text": "Mods", + "context": "Feature category title for mod-related features" + }, + "showActiveMods": { + "text": "Always faintly show active mods during gameplay", + "context": "Feature: visible active mods during gameplay" + }, + "autoRestart": { + "text": "Auto restart when failed due to Sudden Death mod", + "context": "Feature: auto restart on Sudden Death failure" + } + }, + "ui": { + "title": { + "text": "UI", + "context": "Feature category title for UI-related features" + }, + "thumbnailOpacity": { + "text": "Increase the thumbnail opacity in song select", + "context": "Feature: increased thumbnail opacity" + }, + "settingsInGameplay": { + "text": "Allow opening settings during gameplay with Ctrl+O", + "context": "Feature: open settings during gameplay" + } + }, + "other": { + "title": { + "text": "Other", + "context": "Feature category title for miscellaneous features" + }, + "miscFixes": { + "text": "Other miscellaneous fixes", + "context": "Feature: various other fixes" + } + } + }, + "featureSummary": { + "relax": { + "title": { + "text": "Relax Gameplay", + "context": "Short summary title for Relax-related patcher features" + }, + "description": { + "text": "Improves Relax/Autopilot feel with miss visibility, combobreak audio, fail toggle, local score saving, and low HP glow.", + "context": "Condensed summary of Relax category features" + } + }, + "pp": { + "title": { + "text": "PP Tools", + "context": "Short summary title for PP-related patcher features" + }, + "description": { + "text": "Adds a live pp counter and lets you switch between Bancho and Sunrise pp calculators.", + "context": "Condensed summary of PP category features" + } + }, + "mods": { + "title": { + "text": "Mods Awareness", + "context": "Short summary title for mod-related patcher features" + }, + "description": { + "text": "Keeps active mods visible in-game and can auto-restart runs failed by Sudden Death.", + "context": "Condensed summary of mod category features" + } + }, + "ui": { + "title": { + "text": "Interface QoL", + "context": "Short summary title for UI-related patcher features" + }, + "description": { + "text": "Improves song select thumbnail readability and allows opening settings mid-game with Ctrl+O.", + "context": "Condensed summary of UI category features" + } + }, + "other": { + "title": { + "text": "Extra Fixes", + "context": "Short summary title for miscellaneous patcher fixes" + }, + "description": { + "text": "Includes additional small fixes that polish gameplay behavior.", + "context": "Condensed summary of miscellaneous fixes" + } + } + }, + "download": { + "text": "Download Patcher", + "context": "Button text to download the Sunrise Patcher" + }, + "previews": { + "settings": { + "title": { + "text": "Feature Toggle Panel", + "context": "Title for the settings preview slide" + }, + "description": { + "text": "Enable or disable individual patches quickly from one settings panel.", + "context": "Description for the settings preview slide" + }, + "alt": { + "text": "Patcher settings preview", + "context": "Alt text for the patcher settings screenshot" + } + }, + "relaxRanking": { + "title": { + "text": "Relax Ranking View", + "context": "Title for the relax ranking preview slide" + }, + "description": { + "text": "Track and review Relax scores through a dedicated local ranking display.", + "context": "Description for the relax ranking preview slide" + }, + "alt": { + "text": "Relax ranking panel preview", + "context": "Alt text for the relax ranking panel screenshot" + } + }, + "ppCounter": { + "title": { + "text": "In-Game PP Overlay", + "context": "Title for the PP counter preview slide" + }, + "description": { + "text": "Monitor PP changes in real time while playing or watching replays.", + "context": "Description for the PP counter preview slide" + }, + "alt": { + "text": "Live PP counter preview", + "context": "Alt text for the live PP counter screenshot" + } + } + } + }, "topplays": { "meta": { "title": { diff --git a/public/images/patcher/patcher-pp-counter.png b/public/images/patcher/patcher-pp-counter.png new file mode 100644 index 0000000..a0da39e Binary files /dev/null and b/public/images/patcher/patcher-pp-counter.png differ diff --git a/public/images/patcher/patcher-relax-ranking.png b/public/images/patcher/patcher-relax-ranking.png new file mode 100644 index 0000000..6d3f8fa Binary files /dev/null and b/public/images/patcher/patcher-relax-ranking.png differ diff --git a/public/images/patcher/patcher-settings.png b/public/images/patcher/patcher-settings.png new file mode 100644 index 0000000..b6dfaec Binary files /dev/null and b/public/images/patcher/patcher-settings.png differ