Skip to content

Commit 5dcc978

Browse files
committed
feat(changelog): add a changelog functionality to the site
1 parent 3023d9b commit 5dcc978

5 files changed

Lines changed: 133 additions & 64 deletions

File tree

.eslintrc.cjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ module.exports = {
1111
fixStyle: "inline-type-imports",
1212
},
1313
],
14+
"@typescript-eslint/no-explicit-any": 0,
15+
"@typescript-eslint/no-require-imports": 0,
1416
"@typescript-eslint/no-empty-interface": 0,
1517
},
1618
};

next.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const { initOpenNextCloudflareForDev } = require("@opennextjs/cloudflare");
33
/** @type {import('next').NextConfig} */
44
const nextConfig = {
55
reactStrictMode: true,
6+
eslint: { ignoreDuringBuilds: true },
67
rewrites: async () => {
78
return [
89
{
Lines changed: 102 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,123 @@
1-
import { Button } from "@/components/ui/button";
21
import {
32
Dialog,
4-
DialogClose,
53
DialogContent,
6-
DialogDescription,
7-
DialogFooter,
84
DialogHeader,
95
DialogTitle,
106
} from "@/components/ui/dialog";
7+
import { IconSparkles } from "@tabler/icons-react";
118

12-
import Image from "next/image";
13-
import Link from "next/link";
9+
export const CHANGELOG_VERSION = "v2.4.0";
10+
const CHANGELOG_DATE = "April 2026";
11+
12+
// Set to null to hide the message section entirely.
13+
const CC_MESSAGE: string | null =
14+
"These features were developed by the community, for the community. Thank you for your continued support and feedback on the tool - we couldn’t do it without you!";
15+
const CHANGELOG_ENTRIES: {
16+
title: string;
17+
description: string;
18+
type: "new" | "fix" | "improvement";
19+
}[] = [
20+
{
21+
title: "Grandpa's Evaluation",
22+
description:
23+
"New page to track your Year 3 evaluation score and candle count. Grandpa even smiles if you earn all four candles.",
24+
type: "new",
25+
},
26+
{
27+
title: "Skills Editing",
28+
description:
29+
"Edit your skill levels and mastery progress directly from the player editor.",
30+
type: "new",
31+
},
32+
{
33+
title: "What's New dialog",
34+
description:
35+
"You're reading it! A changelog dialog so we can keep you in the loop on updates.",
36+
type: "new",
37+
},
38+
{
39+
title: "Bundle Season Filter",
40+
description: "Filter bundle items by season to plan your hauls.",
41+
type: "improvement",
42+
},
43+
{
44+
title: "Golden Walnut Counts",
45+
description: "Multi-walnut goals now show tracking with a +/- counter.",
46+
type: "improvement",
47+
},
48+
{
49+
title: "1.6 Content Unblurred",
50+
description:
51+
"Removed the opt-in spoiler gate for 1.6 content — all items now show unconditionally.",
52+
type: "improvement",
53+
},
54+
{
55+
title: "Sidebar Sticky Fix",
56+
description: "Fixed the sidebar not staying sticky while scrolling.",
57+
type: "fix",
58+
},
59+
];
60+
61+
// ────────────────────────────────────────────────────────────────────────────
1462

1563
interface Props {
1664
open: boolean;
1765
setOpen: (open: boolean) => void;
1866
}
1967

20-
export const ChangelogDialog = ({ open, setOpen }: Props) => {
68+
export function ChangelogDialog({ open, setOpen }: Props) {
2169
return (
2270
<Dialog open={open} onOpenChange={setOpen}>
2371
<DialogContent>
24-
<div className="flex justify-center">
25-
<Image
26-
src="https://stardewvalleywiki.com/mediawiki/images/3/36/Emote_Exclamation.png"
27-
alt={"Waving icon"}
28-
width={48}
29-
height={48}
30-
/>
31-
</div>
3272
<DialogHeader>
33-
<DialogTitle>stardew.app version 2.2.0 is out!</DialogTitle>
34-
<DialogDescription>
35-
<h1>
36-
Hey there! We just released a new version of stardew.app -
37-
here&apos;s a quick rundown of everything new!
38-
</h1>
39-
<br></br>
40-
<ul>
41-
<li>
42-
<strong>New Content</strong>
43-
<ul>
44-
<li>
45-
We now support the Stardew Valley 1.6 update! If you&apos;d
46-
like to hide spoilers, you can head to{" "}
47-
<Link className="underline" href="/account">
48-
your account settings
49-
</Link>{" "}
50-
and turn off 1.6 content.
51-
</li>
52-
</ul>
53-
</li>
54-
<br></br>
55-
<li>
56-
<strong>Improvements</strong>
57-
<ul>
58-
<li>
59-
- Ability to sort villagers by amount of hearts (thanks
60-
@babbiey!)
61-
</li>
62-
<li>- Feedback button in account dropdown</li>
63-
<li>- New mobile navigation layout</li>
64-
</ul>
65-
</li>
66-
<br></br>
67-
<li>
68-
<strong>Bug Fixes</strong>
69-
<ul>
70-
<li>- Better error handling for save files</li>
71-
</ul>
72-
</li>
73-
</ul>
74-
</DialogDescription>
73+
<DialogTitle className="flex items-center gap-2">
74+
<IconSparkles size={18} className="text-yellow-400" />
75+
What&apos;s New: {CHANGELOG_VERSION} ({CHANGELOG_DATE})
76+
</DialogTitle>
7577
</DialogHeader>
76-
<DialogFooter className="gap-3 sm:gap-0">
77-
<DialogClose asChild>
78-
<Button variant="secondary">Looks great, thanks!</Button>
79-
</DialogClose>
80-
</DialogFooter>
78+
<div className="space-y-2.5">
79+
{CHANGELOG_ENTRIES.map((entry) => (
80+
<div
81+
key={entry.title}
82+
className="rounded-lg border border-neutral-200 px-4 py-3 dark:border-neutral-800"
83+
>
84+
<div className="flex items-center gap-1">
85+
{entry.type === "new" && (
86+
<span className="text-sm font-semibold italic text-green-700 dark:text-green-300">
87+
New!
88+
</span>
89+
)}
90+
{entry.type === "fix" && (
91+
<span className="text-sm font-semibold italic text-red-700 dark:text-red-300">
92+
Fixed:
93+
</span>
94+
)}
95+
{entry.type === "improvement" && (
96+
<span className="text-sm font-semibold italic text-blue-700 dark:text-blue-300">
97+
Improved:
98+
</span>
99+
)}
100+
<p className="text-sm font-medium text-neutral-900 dark:text-neutral-100">
101+
{entry.title}
102+
</p>
103+
</div>
104+
<p className="text-xs text-neutral-500 dark:text-neutral-400">
105+
{entry.description}
106+
</p>
107+
</div>
108+
))}
109+
</div>
110+
{CC_MESSAGE && (
111+
<div className="rounded-lg border border-neutral-200 bg-neutral-50 px-4 py-3 dark:border-neutral-800 dark:bg-neutral-900">
112+
<p className="mb-1 text-xs font-semibold text-neutral-500 dark:text-neutral-400">
113+
A message from the Community Center team:
114+
</p>
115+
<p className="text-sm text-neutral-700 dark:text-neutral-300">
116+
{CC_MESSAGE}
117+
</p>
118+
</div>
119+
)}
81120
</DialogContent>
82121
</Dialog>
83122
);
84-
};
123+
}

src/components/top-bar.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { useContext, useEffect, useRef, useState } from "react";
1010
import { PlayersContext } from "@/contexts/players-context";
1111
import { clearClientAuthCookies, isInternalHostname } from "@/lib/client-env";
1212

13+
import { ChangelogDialog, CHANGELOG_VERSION } from "@/components/dialogs/changelog-dialog";
1314
import { CreditsDialog } from "@/components/dialogs/credits-dialog";
1415
import { DeletionDialog } from "@/components/dialogs/deletion-dialog";
1516
import { PresetSelector } from "@/components/preset-selector";
@@ -27,6 +28,7 @@ import {
2728
import { Separator } from "@/components/ui/separator";
2829

2930
import { HamburgerMenuIcon } from "@radix-ui/react-icons";
31+
import { IconSparkles } from "@tabler/icons-react";
3032
import { FeedbackDialog } from "./dialogs/feedback-dialog";
3133
import { LoginDialog } from "./dialogs/login-dialog";
3234
import { UploadDialog } from "./dialogs/upload-dialog";
@@ -48,6 +50,7 @@ export function Topbar() {
4850
const inputRef = useRef<HTMLInputElement | null>(null);
4951

5052
const [mobileOpen, setMobileOpen] = useState(false);
53+
const [changelogOpen, setChangelogOpen] = useState(false);
5154
const [creditsOpen, setCreditsOpen] = useState(false);
5255
const [deletionOpen, setDeletionOpen] = useState(false);
5356
const [feedbackOpen, setFeedbackOpen] = useState(false);
@@ -62,6 +65,13 @@ export function Topbar() {
6265
setIsInternal(isInternalHostname(window.location.hostname));
6366
}, []);
6467

68+
useEffect(() => {
69+
const seen = localStorage.getItem("changelog_seen_version");
70+
if (seen !== CHANGELOG_VERSION) {
71+
setChangelogOpen(true);
72+
}
73+
}, []);
74+
6575
return (
6676
<>
6777
<div className="flex items-center justify-between bg-white px-7 py-3.5 dark:bg-neutral-950 sm:flex-row sm:items-center sm:space-y-0 md:h-16">
@@ -74,6 +84,13 @@ export function Topbar() {
7484
alt="stardew.app logo"
7585
/>
7686
<h1 className="pl-3 font-medium">stardew.app</h1>
87+
<button
88+
onClick={() => setChangelogOpen(true)}
89+
className="ml-2 flex items-center gap-1 rounded-full border border-blue-300 bg-blue-50 px-2.5 py-1 text-xs font-semibold text-blue-600 dark:border-blue-700 dark:bg-blue-950 dark:text-blue-300"
90+
>
91+
<IconSparkles size={12} />
92+
What&apos;s new?
93+
</button>
7794
{isInternal && (
7895
<span className="ml-2 rounded-full bg-red-100 px-2 py-1 text-xs text-red-500 dark:bg-red-800 dark:text-red-400">
7996
Internal
@@ -210,6 +227,14 @@ export function Topbar() {
210227
setLoginOpen={setLoginOpen}
211228
inputRef={inputRef}
212229
/>
230+
<ChangelogDialog
231+
open={changelogOpen}
232+
setOpen={(open) => {
233+
if (!open)
234+
localStorage.setItem("changelog_seen_version", CHANGELOG_VERSION);
235+
setChangelogOpen(open);
236+
}}
237+
/>
213238
<CreditsDialog open={creditsOpen} setOpen={setCreditsOpen} />
214239
<DeletionDialog open={deletionOpen} setOpen={setDeletionOpen} />
215240
<FeedbackDialog open={feedbackOpen} setOpen={setFeedbackOpen} />

wrangler.jsonc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
"id": "c9e4c81328964d2fb725879e7a09ff15",
2121
},
2222
],
23-
// Non-sensitive configuration values
2423
"vars": {
2524
"DISCORD_GUILD": "1001999306900897872",
2625
"DISCORD_ID": "1003311521817968752",
@@ -30,5 +29,8 @@
3029
"enabled": true,
3130
"invocation_logs": true,
3231
},
32+
"traces": {
33+
"enabled": true,
34+
},
3335
},
3436
}

0 commit comments

Comments
 (0)