feat : merge mat
CI / Verify (push) Successful in 1m31s
CI / Build immutable images and deploy (push) Successful in 4m0s

This commit is contained in:
2026-09-06 18:05:48 +07:00 Unverified
parent 770c60c4a2
commit 6dc8e3afaa
3 changed files with 60 additions and 8 deletions
+4 -8
View File
@@ -7,16 +7,10 @@ import type {
CatalogAscensionGroup, CatalogAscensionGroup,
CatalogBaseStat, CatalogBaseStat,
} from "@/lib/catalog/lunaris"; } from "@/lib/catalog/lunaris";
import { mergePosterMaterials, type PosterMaterial } from "@/lib/material-poster";
import { accentGradient } from "@/lib/overview-image"; import { accentGradient } from "@/lib/overview-image";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
type PosterMaterial = {
key: string;
amount: number;
name: string;
imageUrl: string | null;
};
export type PosterBlendMode = "normal" | "multiply" | "screen" | "overlay" | "darken" | "lighten" | "color-dodge" | "color-burn" | "hard-light" | "soft-light" | "difference" | "exclusion" | "hue" | "saturation" | "color" | "luminosity"; export type PosterBlendMode = "normal" | "multiply" | "screen" | "overlay" | "darken" | "lighten" | "color-dodge" | "color-burn" | "hard-light" | "soft-light" | "difference" | "exclusion" | "hue" | "saturation" | "color" | "luminosity";
type PosterCharacter = { type PosterCharacter = {
@@ -80,7 +74,9 @@ export function MaterialPoster({
}) { }) {
const dragStart = useRef<{ pointerId: number; x: number; y: number; offsetX: number; offsetY: number } | null>(null); const dragStart = useRef<{ pointerId: number; x: number; y: number; offsetX: number; offsetY: number } | null>(null);
const stats = character.baseStats.slice(0, 4); const stats = character.baseStats.slice(0, 4);
const materials = [...character.ascension, ...character.leveling].flatMap((group) => group.items); const materials = mergePosterMaterials(
[...character.ascension, ...character.leveling].flatMap((group) => group.items),
);
const background = `linear-gradient(180deg, ${topColors[0]} 0%, ${topColors[1]} 22%, rgba(0,0,0,0) 42%, rgba(0,0,0,0) 62%, ${bottomColors[0]} 88%, ${bottomColors[1]} 100%)`; const background = `linear-gradient(180deg, ${topColors[0]} 0%, ${topColors[1]} 22%, rgba(0,0,0,0) 42%, rgba(0,0,0,0) 62%, ${bottomColors[0]} 88%, ${bottomColors[1]} 100%)`;
function handlePointerDown(event: PointerEvent<HTMLDivElement>) { function handlePointerDown(event: PointerEvent<HTMLDivElement>) {
+23
View File
@@ -0,0 +1,23 @@
import { describe, expect, it } from "vitest";
import { mergePosterMaterials } from "@/lib/material-poster";
describe("mergePosterMaterials", () => {
it("combines amounts when leveling and talent materials use the same image", () => {
expect(mergePosterMaterials([
{ key: "talent", amount: 9, name: "Talent", imageUrl: "/shared.webp" },
{ key: "leveling", amount: 18, name: "Leveling", imageUrl: "/shared.webp" },
])).toEqual([
{ key: "talent", amount: 27, name: "Talent", imageUrl: "/shared.webp" },
]);
});
it("keeps materials without images separate", () => {
const materials = [
{ key: "first", amount: 1, name: "First", imageUrl: null },
{ key: "second", amount: 2, name: "Second", imageUrl: null },
];
expect(mergePosterMaterials(materials)).toEqual(materials);
});
});
+33
View File
@@ -0,0 +1,33 @@
export type PosterMaterial = {
key: string;
amount: number;
name: string;
imageUrl: string | null;
};
export function mergePosterMaterials(materials: PosterMaterial[]): PosterMaterial[] {
const merged: PosterMaterial[] = [];
const indexByImageUrl = new Map<string, number>();
for (const material of materials) {
if (!material.imageUrl) {
merged.push(material);
continue;
}
const existingIndex = indexByImageUrl.get(material.imageUrl);
if (existingIndex === undefined) {
indexByImageUrl.set(material.imageUrl, merged.length);
merged.push(material);
continue;
}
const existing = merged[existingIndex];
merged[existingIndex] = {
...existing,
amount: existing.amount + material.amount,
};
}
return merged;
}