万圣节&圣诞节皮肤
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
/* ============================================================
|
||||
Festival skin gating — date-driven, URL-overridable.
|
||||
Only Christmas is implemented today; add more festivals by
|
||||
extending FESTIVAL_WINDOWS plus the matching components under
|
||||
components/festival/.
|
||||
============================================================ */
|
||||
import { useMemo } from "react";
|
||||
|
||||
export type FestivalId = "christmas" | "halloween";
|
||||
|
||||
/** Inclusive [month, day] windows. Christmas: Dec 20 – Dec 26; Halloween: Oct 26 – Nov 1. */
|
||||
const FESTIVAL_WINDOWS: Record<
|
||||
FestivalId,
|
||||
{ from: [number, number]; to: [number, number] }
|
||||
> = {
|
||||
christmas: { from: [12, 20], to: [12, 26] },
|
||||
halloween: { from: [10, 26], to: [11, 1] },
|
||||
};
|
||||
|
||||
function inWindow(
|
||||
month: number,
|
||||
day: number,
|
||||
w: { from: [number, number]; to: [number, number] },
|
||||
) {
|
||||
const cur = month * 100 + day;
|
||||
const from = w.from[0] * 100 + w.from[1];
|
||||
const to = w.to[0] * 100 + w.to[1];
|
||||
// Support windows that wrap the new year (from > to).
|
||||
return from <= to ? cur >= from && cur <= to : cur >= from || cur <= to;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the active festival skin.
|
||||
* `?festival=christmas` forces it on and `?festival=off` forces it off (QA hook,
|
||||
* so the skin can be verified without waiting for the real date window).
|
||||
* Otherwise falls back to the system-date window.
|
||||
*/
|
||||
export function getFestival(
|
||||
now: Date = new Date(),
|
||||
search: string = typeof location !== "undefined" ? location.search : "",
|
||||
): FestivalId | null {
|
||||
const override = new URLSearchParams(search).get("festival");
|
||||
if (override === "off" || override === "none") return null;
|
||||
if (override && Object.prototype.hasOwnProperty.call(FESTIVAL_WINDOWS, override)) {
|
||||
return override as FestivalId;
|
||||
}
|
||||
for (const id of Object.keys(FESTIVAL_WINDOWS) as FestivalId[]) {
|
||||
if (inWindow(now.getMonth() + 1, now.getDate(), FESTIVAL_WINDOWS[id])) return id;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Stable per-mount festival resolution (the date won't matter mid-session). */
|
||||
export function useFestival(): FestivalId | null {
|
||||
return useMemo(() => getFestival(), []);
|
||||
}
|
||||
|
||||
/** 首页 VU 区的节日问候语,键与 FestivalId 对应。 */
|
||||
export const FESTIVAL_GREETINGS: Record<FestivalId, string> = {
|
||||
christmas: "Merry Christmas",
|
||||
halloween: "Happy Halloween",
|
||||
};
|
||||
Reference in New Issue
Block a user