mobile leaderboard fixes and hide diffs that aren't standard (for now)
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
This commit is contained in:
parent
f60f34c0c2
commit
50414d848a
@ -1,11 +1,19 @@
|
||||
const diffColors: Record<string, string> = {
|
||||
easy: "#3CB371",
|
||||
normal: "#59b0f4",
|
||||
hard: "#FF6347",
|
||||
expert: "#bf2a42",
|
||||
expertplus: "#8f48db",
|
||||
type Difficulty = {
|
||||
name: DifficultyName;
|
||||
gamemode?: string;
|
||||
color: string;
|
||||
};
|
||||
|
||||
type DifficultyName = "Easy" | "Normal" | "Hard" | "Expert" | "Expert+";
|
||||
|
||||
const difficulties: Difficulty[] = [
|
||||
{ name: "Easy", color: "#59b0f4" },
|
||||
{ name: "Normal", color: "#59b0f4" },
|
||||
{ name: "Hard", color: "#FF6347" },
|
||||
{ name: "Expert", color: "#bf2a42" },
|
||||
{ name: "Expert+", color: "#8f48db" },
|
||||
];
|
||||
|
||||
export type ScoreBadge = {
|
||||
name: string;
|
||||
min: number | null;
|
||||
@ -14,11 +22,11 @@ export type ScoreBadge = {
|
||||
};
|
||||
|
||||
const scoreBadges: ScoreBadge[] = [
|
||||
{ name: "SS+", min: 95, max: null, color: diffColors.expertplus },
|
||||
{ name: "SS", min: 90, max: 95, color: diffColors.expert },
|
||||
{ name: "S+", min: 85, max: 90, color: diffColors.hard },
|
||||
{ name: "S", min: 80, max: 85, color: diffColors.normal },
|
||||
{ name: "A", min: 70, max: 80, color: diffColors.easy },
|
||||
{ name: "SS+", min: 95, max: null, color: getDifficulty("Expert+")!.color },
|
||||
{ name: "SS", min: 90, max: 95, color: getDifficulty("Expert")!.color },
|
||||
{ name: "S+", min: 85, max: 90, color: getDifficulty("Hard")!.color },
|
||||
{ name: "S", min: 80, max: 85, color: getDifficulty("Normal")!.color },
|
||||
{ name: "A", min: 70, max: 80, color: getDifficulty("Easy")!.color },
|
||||
{ name: "-", min: null, max: 70, color: "hsl(var(--accent))" },
|
||||
];
|
||||
|
||||
@ -49,6 +57,39 @@ export function getScoreBadgeFromAccuracy(acc: number): ScoreBadge {
|
||||
return scoreBadges[scoreBadges.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a raw difficulty into a {@link Difficulty}
|
||||
* Example: _Easy_SoloStandard -> { name: "Easy", type: "Standard", color: "#59b0f4" }
|
||||
*
|
||||
* @param rawDifficulty the raw difficulty to parse
|
||||
* @return the parsed difficulty
|
||||
*/
|
||||
export function getDifficultyFromRawDifficulty(rawDifficulty: string): Difficulty {
|
||||
const [name, ...type] = rawDifficulty
|
||||
.replace("Plus", "+") // Replaces Plus with + so we can match it to our difficulty names
|
||||
.replace("Solo", "") // Removes "Solo"
|
||||
.replace(/^_+|_+$/g, "") // Removes leading and trailing underscores
|
||||
.split("_");
|
||||
const difficulty = difficulties.find(d => d.name === name);
|
||||
if (!difficulty) {
|
||||
throw new Error(`Unknown difficulty: ${rawDifficulty}`);
|
||||
}
|
||||
return {
|
||||
...difficulty,
|
||||
gamemode: type.join("_"),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Difficulty} from its name
|
||||
*
|
||||
* @param diff the name of the difficulty
|
||||
* @returns the difficulty
|
||||
*/
|
||||
export function getDifficulty(diff: DifficultyName) {
|
||||
return difficulties.find(d => d.name === diff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the difficulty of a song into a color
|
||||
*
|
||||
@ -56,6 +97,5 @@ export function getScoreBadgeFromAccuracy(acc: number): ScoreBadge {
|
||||
* @returns the color for the difficulty
|
||||
*/
|
||||
export function songDifficultyToColor(diff: string) {
|
||||
diff = diff.replace("+", "Plus");
|
||||
return diffColors[diff.toLowerCase() as keyof typeof diffColors];
|
||||
return getDifficultyFromRawDifficulty(diff).color;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ export function LeaderboardInfo({ leaderboard, beatSaverMap }: LeaderboardInfoPr
|
||||
<Image
|
||||
src={leaderboard.coverImage}
|
||||
alt={`${leaderboard.songName} Cover Image`}
|
||||
className="rounded-md w-fit h-fit"
|
||||
className="rounded-md w-[96px] h-[96px]"
|
||||
width={96}
|
||||
height={96}
|
||||
/>
|
||||
|
@ -13,8 +13,8 @@ import LeaderboardScore from "./leaderboard-score";
|
||||
import { scoreAnimation } from "@/components/score/score-animation";
|
||||
import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { getDifficultyFromScoreSaberDifficulty } from "@/common/scoresaber-utils";
|
||||
import { clsx } from "clsx";
|
||||
import { getDifficultyFromRawDifficulty } from "@/common/song-utils";
|
||||
|
||||
type LeaderboardScoresProps = {
|
||||
/**
|
||||
@ -130,14 +130,14 @@ export default function LeaderboardScores({
|
||||
* scores when new scores are loaded.
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (topOfScoresRef.current) {
|
||||
if (topOfScoresRef.current && shouldFetch) {
|
||||
const topOfScoresPosition = topOfScoresRef.current.getBoundingClientRect().top + window.scrollY;
|
||||
window.scrollTo({
|
||||
top: topOfScoresPosition - 75, // Navbar height (plus some padding)
|
||||
behavior: "smooth",
|
||||
});
|
||||
}
|
||||
}, [currentPage, topOfScoresRef]);
|
||||
}, [currentPage, topOfScoresRef, shouldFetch]);
|
||||
|
||||
if (currentScores === undefined) {
|
||||
return undefined;
|
||||
@ -153,18 +153,24 @@ export default function LeaderboardScores({
|
||||
{currentScores.scores.length === 0 && <p>No scores found. Invalid Page?</p>}
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 justify-center items-center">
|
||||
<div className="flex gap-2 justify-center items-center flex-wrap">
|
||||
{showDifficulties &&
|
||||
leaderboard.difficulties.map(({ difficulty, leaderboardId }) => {
|
||||
leaderboard.difficulties.map(({ difficultyRaw, leaderboardId }) => {
|
||||
const difficulty = getDifficultyFromRawDifficulty(difficultyRaw);
|
||||
// todo: add support for other gamemodes?
|
||||
if (difficulty.gamemode !== "Standard") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
key={difficulty}
|
||||
key={difficultyRaw}
|
||||
variant={leaderboardId === selectedLeaderboardId ? "default" : "outline"}
|
||||
onClick={() => {
|
||||
handleLeaderboardChange(leaderboardId);
|
||||
}}
|
||||
>
|
||||
{getDifficultyFromScoreSaberDifficulty(difficulty)}
|
||||
{difficulty.name}
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
|
Reference in New Issue
Block a user