mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
feat: comparing achievements
This commit is contained in:
parent
694e0cd12c
commit
c24f6be1b7
2 changed files with 121 additions and 74 deletions
|
@ -6,7 +6,7 @@ import { useTranslation } from "react-i18next";
|
|||
import * as styles from "./achievements.css";
|
||||
import { formatDownloadProgress } from "@renderer/helpers";
|
||||
import { TrophyIcon } from "@primer/octicons-react";
|
||||
import { vars } from "@renderer/theme.css";
|
||||
import { SPACING_UNIT, vars } from "@renderer/theme.css";
|
||||
import { gameDetailsContext } from "@renderer/context";
|
||||
import { GameShop, UserAchievement } from "@types";
|
||||
import { average } from "color.js";
|
||||
|
@ -19,6 +19,107 @@ interface AchievementsContentProps {
|
|||
displayName: string | null;
|
||||
}
|
||||
|
||||
interface AchievementListProps {
|
||||
achievements: UserAchievement[];
|
||||
}
|
||||
|
||||
interface AchievementPanelProps {
|
||||
achievements: UserAchievement[];
|
||||
displayName: string | null;
|
||||
}
|
||||
|
||||
function AchievementPanel({
|
||||
achievements,
|
||||
displayName,
|
||||
}: AchievementPanelProps) {
|
||||
const { t } = useTranslation("achievement");
|
||||
|
||||
const unlockedAchievementCount = achievements.filter(
|
||||
(achievement) => achievement.unlocked
|
||||
).length;
|
||||
|
||||
const totalAchievementCount = achievements.length;
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
padding: `0 ${SPACING_UNIT * 2}px`,
|
||||
}}
|
||||
>
|
||||
<h1 style={{ fontSize: "1.2em", marginBottom: "8px" }}>
|
||||
{displayName
|
||||
? t("user_achievements", {
|
||||
displayName,
|
||||
})
|
||||
: t("your_achievements")}
|
||||
</h1>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
marginBottom: 8,
|
||||
width: "100%",
|
||||
color: vars.color.muted,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
}}
|
||||
>
|
||||
<TrophyIcon size={13} />
|
||||
<span>
|
||||
{unlockedAchievementCount} / {totalAchievementCount}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<span>
|
||||
{formatDownloadProgress(
|
||||
unlockedAchievementCount / totalAchievementCount
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<progress
|
||||
max={1}
|
||||
value={unlockedAchievementCount / totalAchievementCount}
|
||||
className={styles.achievementsProgressBar}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function AchievementList({ achievements }: AchievementListProps) {
|
||||
const { formatDateTime } = useDate();
|
||||
|
||||
return (
|
||||
<ul className={styles.list}>
|
||||
{achievements.map((achievement, index) => (
|
||||
<li key={index} className={styles.listItem}>
|
||||
<img
|
||||
className={styles.listItemImage({
|
||||
unlocked: achievement.unlocked,
|
||||
})}
|
||||
src={achievement.icon}
|
||||
alt={achievement.displayName}
|
||||
loading="lazy"
|
||||
/>
|
||||
<div>
|
||||
<p>{achievement.displayName}</p>
|
||||
<p>{achievement.description}</p>
|
||||
<small>
|
||||
{achievement.unlockTime && formatDateTime(achievement.unlockTime)}
|
||||
</small>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
export function AchievementsContent({
|
||||
userId,
|
||||
displayName,
|
||||
|
@ -31,13 +132,9 @@ export function AchievementsContent({
|
|||
[]
|
||||
);
|
||||
|
||||
const { t } = useTranslation("achievement");
|
||||
|
||||
const { gameTitle, objectId, shop, achievements, gameColor, setGameColor } =
|
||||
useContext(gameDetailsContext);
|
||||
|
||||
const { formatDateTime } = useDate();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -93,12 +190,6 @@ export function AchievementsContent({
|
|||
|
||||
const userAchievements = userId ? pageAchievements : achievements;
|
||||
|
||||
const unlockedAchievementCount = userAchievements.filter(
|
||||
(achievement) => achievement.unlocked
|
||||
).length;
|
||||
|
||||
const totalAchievementCount = userAchievements.length;
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<img
|
||||
|
@ -137,70 +228,26 @@ export function AchievementsContent({
|
|||
</div>
|
||||
|
||||
<div className={styles.panel({ stuck: isHeaderStuck })}>
|
||||
<h1 style={{ fontSize: "1.2em", marginBottom: "8px" }}>
|
||||
{displayName
|
||||
? t("user_achievements", {
|
||||
displayName,
|
||||
})
|
||||
: t("your_achievements")}
|
||||
</h1>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
marginBottom: 8,
|
||||
width: "100%",
|
||||
color: vars.color.muted,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
}}
|
||||
>
|
||||
<TrophyIcon size={13} />
|
||||
<span>
|
||||
{unlockedAchievementCount} / {totalAchievementCount}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<span>
|
||||
{formatDownloadProgress(
|
||||
unlockedAchievementCount / totalAchievementCount
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<progress
|
||||
max={1}
|
||||
value={unlockedAchievementCount / totalAchievementCount}
|
||||
className={styles.achievementsProgressBar}
|
||||
<AchievementPanel
|
||||
displayName={displayName}
|
||||
achievements={userAchievements}
|
||||
/>
|
||||
{pageAchievements.length > 0 && (
|
||||
<AchievementPanel displayName={null} achievements={achievements} />
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
}}
|
||||
>
|
||||
{pageAchievements.length > 0 && (
|
||||
<AchievementList achievements={pageAchievements} />
|
||||
)}
|
||||
|
||||
<ul className={styles.list}>
|
||||
{userAchievements.map((achievement, index) => (
|
||||
<li key={index} className={styles.listItem}>
|
||||
<img
|
||||
className={styles.listItemImage({
|
||||
unlocked: achievement.unlocked,
|
||||
})}
|
||||
src={achievement.icon}
|
||||
alt={achievement.displayName}
|
||||
loading="lazy"
|
||||
/>
|
||||
<div>
|
||||
<p>{achievement.displayName}</p>
|
||||
<p>{achievement.description}</p>
|
||||
<small>
|
||||
{achievement.unlockTime &&
|
||||
formatDateTime(achievement.unlockTime)}
|
||||
</small>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<AchievementList achievements={achievements} />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -66,10 +66,10 @@ export const panel = recipe({
|
|||
width: "100%",
|
||||
height: "100px",
|
||||
minHeight: "100px",
|
||||
padding: `${SPACING_UNIT * 2}px ${SPACING_UNIT * 2}px`,
|
||||
padding: `${SPACING_UNIT * 2}px 0`,
|
||||
backgroundColor: vars.color.darkBackground,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
flexDirection: "row",
|
||||
transition: "all ease 0.2s",
|
||||
borderBottom: `solid 1px ${vars.color.border}`,
|
||||
position: "sticky",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue