fix: derive the colophon's credits from the feed
It still thanked only Game8 and hardcoded the studio list, so wiki.gg went uncredited and unmentioned in the disclaimer after being added as a source. Sources and studios are now read from the feed and the game registry, so adding either credits the right people automatically. A hardcoded credit goes stale the moment someone adds a source, and out of date is the one thing a credit must not be. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6fad016f66
commit
25c32dbe62
@@ -3,12 +3,28 @@ import type { SourceHealth } from "../../shared/feed.ts";
|
|||||||
|
|
||||||
export const REPO_URL = "https://github.com/StereotypicalCat/gacha-event-tracker";
|
export const REPO_URL = "https://github.com/StereotypicalCat/gacha-event-tracker";
|
||||||
|
|
||||||
|
/** Display name and homepage for a source host. */
|
||||||
|
const SITES: Record<string, { name: string; url: string }> = {
|
||||||
|
"game8.co": { name: "Game8", url: "https://game8.co" },
|
||||||
|
"endfield.wiki.gg": { name: "wiki.gg", url: "https://wiki.gg" },
|
||||||
|
};
|
||||||
|
|
||||||
|
function siteFor(url: string): { name: string; url: string } {
|
||||||
|
try {
|
||||||
|
const host = new URL(url).host;
|
||||||
|
return SITES[host] ?? { name: host, url: `https://${host}` };
|
||||||
|
} catch {
|
||||||
|
return { name: url, url };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Credit, disclaimer, and where the code lives.
|
* Credit, disclaimer, and where the code lives.
|
||||||
*
|
*
|
||||||
* This sits at the foot of the page rather than behind an "About" link: the
|
* Everything here is derived from the feed rather than written down, so adding
|
||||||
* people whose work this depends on should be visible on the same screen as
|
* a source or a game credits the right people automatically. A hardcoded list
|
||||||
* the data, not one navigation step away from it.
|
* silently goes stale the moment someone adds the seventh source, and the one
|
||||||
|
* thing a credit must not be is out of date.
|
||||||
*/
|
*/
|
||||||
export function Colophon({
|
export function Colophon({
|
||||||
sources,
|
sources,
|
||||||
@@ -17,7 +33,15 @@ export function Colophon({
|
|||||||
sources: SourceHealth[];
|
sources: SourceHealth[];
|
||||||
staleCount: number;
|
staleCount: number;
|
||||||
}) {
|
}) {
|
||||||
const games = [...new Set(sources.map((s) => s.game))];
|
const games = [...new Set(sources.map((s) => s.game))].map(gameMeta);
|
||||||
|
const studios = [...new Set(games.map((g) => g.studio))];
|
||||||
|
|
||||||
|
const sites = [...new Map(sources.map((s) => {
|
||||||
|
const site = siteFor(s.url);
|
||||||
|
return [site.name, site] as const;
|
||||||
|
})).values()];
|
||||||
|
|
||||||
|
const named = [...sites.map((s) => s.name), ...studios];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="border-t border-hairline px-4 pb-12 pt-6 text-xs leading-relaxed text-faint">
|
<footer className="border-t border-hairline px-4 pb-12 pt-6 text-xs leading-relaxed text-faint">
|
||||||
@@ -36,23 +60,34 @@ export function Colophon({
|
|||||||
<div className="mt-5">
|
<div className="mt-5">
|
||||||
<p className="eyebrow">With thanks to</p>
|
<p className="eyebrow">With thanks to</p>
|
||||||
<p className="mt-1.5">
|
<p className="mt-1.5">
|
||||||
|
{sites.map((site, i) => (
|
||||||
|
<span key={site.name}>
|
||||||
|
{i > 0 && (i === sites.length - 1 ? " and " : ", ")}
|
||||||
<a
|
<a
|
||||||
href="https://game8.co"
|
href={site.url}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
className="text-muted underline decoration-hairline underline-offset-2 transition-colors duration-150 hover:text-ink hover:decoration-near"
|
className="text-muted underline decoration-hairline underline-offset-2 transition-colors duration-150 hover:text-ink hover:decoration-near"
|
||||||
>
|
>
|
||||||
Game8
|
{site.name}
|
||||||
</a>
|
</a>
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
{", whose editors compile and maintain the event calendars this reads from. The schedules are their work; this page only rearranges them."}
|
{", whose editors compile and maintain the event calendars this reads from. The schedules are their work; this page only rearranges them."}
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-2">
|
<p className="mt-2">
|
||||||
And to HoYoverse, Kuro Games, Hypergryph and Hotta Studio, who make the
|
And to{" "}
|
||||||
games worth keeping track of —{" "}
|
{studios.map((studio, i) => (
|
||||||
{games.map((g, i) => (
|
<span key={studio}>
|
||||||
<span key={g}>
|
{i > 0 && (i === studios.length - 1 ? " and " : ", ")}
|
||||||
|
{studio}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
, who make the games worth keeping track of —{" "}
|
||||||
|
{games.map((game, i) => (
|
||||||
|
<span key={game.id}>
|
||||||
{i > 0 && ", "}
|
{i > 0 && ", "}
|
||||||
<span style={{ color: gameMeta(g).hue }}>{gameMeta(g).name}</span>
|
<span style={{ color: game.hue }}>{game.name}</span>
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
{"."}
|
{"."}
|
||||||
@@ -62,10 +97,10 @@ export function Colophon({
|
|||||||
<div className="mt-5 border-t border-hairline pt-4">
|
<div className="mt-5 border-t border-hairline pt-4">
|
||||||
<p>
|
<p>
|
||||||
<strong className="font-semibold text-muted">Not affiliated</strong>{" "}
|
<strong className="font-semibold text-muted">Not affiliated</strong>{" "}
|
||||||
with Game8, HoYoverse, Kuro Games, Hypergryph, Hotta Studio, or any
|
with {named.join(", ")}, or any other publisher or source named here.
|
||||||
other publisher or source named here. This is an unofficial fan-made
|
This is an unofficial fan-made tool, not endorsed by or connected to
|
||||||
tool, not endorsed by or connected to any of them. All game names,
|
any of them. All game names, event names and trademarks belong to their
|
||||||
event names and trademarks belong to their respective owners.
|
respective owners.
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-2">
|
<p className="mt-2">
|
||||||
Event dates can be wrong or go out of date. Treat the source page as
|
Event dates can be wrong or go out of date. Treat the source page as
|
||||||
|
|||||||
+9
-7
@@ -11,16 +11,18 @@ export interface GameMeta {
|
|||||||
* "whose event is this?" and "how long have I got?" at the same time.
|
* "whose event is this?" and "how long have I got?" at the same time.
|
||||||
*/
|
*/
|
||||||
hue: string;
|
hue: string;
|
||||||
|
/** Who makes it. Credited in the colophon, derived rather than hardcoded. */
|
||||||
|
studio: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GAMES: Record<GameId, GameMeta> = {
|
export const GAMES: Record<GameId, GameMeta> = {
|
||||||
genshin: { id: "genshin", name: "Genshin Impact", short: "Genshin", hue: "#4EA8DE" },
|
genshin: { id: "genshin", name: "Genshin Impact", short: "Genshin", hue: "#4EA8DE" , studio: "HoYoverse" },
|
||||||
hsr: { id: "hsr", name: "Honkai: Star Rail", short: "Star Rail", hue: "#7B8CFF" },
|
hsr: { id: "hsr", name: "Honkai: Star Rail", short: "Star Rail", hue: "#7B8CFF" , studio: "HoYoverse" },
|
||||||
zzz: { id: "zzz", name: "Zenless Zone Zero", short: "ZZZ", hue: "#F2A03D" },
|
zzz: { id: "zzz", name: "Zenless Zone Zero", short: "ZZZ", hue: "#F2A03D" , studio: "HoYoverse" },
|
||||||
wuwa: { id: "wuwa", name: "Wuthering Waves", short: "Wuwa", hue: "#3DD6A0" },
|
wuwa: { id: "wuwa", name: "Wuthering Waves", short: "Wuwa", hue: "#3DD6A0" , studio: "Kuro Games" },
|
||||||
arknights: { id: "arknights", name: "Arknights", short: "Arknights", hue: "#9AA3B8" },
|
arknights: { id: "arknights", name: "Arknights", short: "Arknights", hue: "#9AA3B8" , studio: "Hypergryph" },
|
||||||
endfield: { id: "endfield", name: "Arknights: Endfield", short: "Endfield", hue: "#E8635A" },
|
endfield: { id: "endfield", name: "Arknights: Endfield", short: "Endfield", hue: "#E8635A" , studio: "Hypergryph" },
|
||||||
nte: { id: "nte", name: "Neverness to Everness", short: "NTE", hue: "#C77DFF" },
|
nte: { id: "nte", name: "Neverness to Everness", short: "NTE", hue: "#C77DFF" , studio: "Hotta Studio" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GAME_LIST: GameMeta[] = Object.values(GAMES);
|
export const GAME_LIST: GameMeta[] = Object.values(GAMES);
|
||||||
|
|||||||
Reference in New Issue
Block a user