UPDATE: Replace lodash clone deep to structuredClone
All checks were successful
Gitea Auto Deploy / Deploy-Container (push) Successful in 1m47s

This commit is contained in:
2025-11-03 12:22:10 +07:00
parent 35095c19d5
commit 189002cf44
13 changed files with 78 additions and 91 deletions

View File

@@ -10,7 +10,6 @@
"fast-average-color": "^9.5.0", "fast-average-color": "^9.5.0",
"framer-motion": "^12.12.1", "framer-motion": "^12.12.1",
"html2canvas-pro": "^1.5.11", "html2canvas-pro": "^1.5.11",
"lodash": "^4.17.21",
"lucide-react": "^0.536.0", "lucide-react": "^0.536.0",
"next": "15.3.2", "next": "15.3.2",
"next-intl": "^4.1.0", "next-intl": "^4.1.0",
@@ -27,7 +26,6 @@
"@eslint/eslintrc": "^3", "@eslint/eslintrc": "^3",
"@tailwindcss/postcss": "^4", "@tailwindcss/postcss": "^4",
"@types/jest": "^29.5.14", "@types/jest": "^29.5.14",
"@types/lodash": "^4.17.20",
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^19", "@types/react": "^19",
"@types/react-dom": "^19", "@types/react-dom": "^19",
@@ -302,8 +300,6 @@
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
"@types/lodash": ["@types/lodash@4.17.20", "", {}, "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA=="],
"@types/node": ["@types/node@20.19.9", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw=="], "@types/node": ["@types/node@20.19.9", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw=="],
"@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="], "@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="],

View File

@@ -15,7 +15,6 @@
"fast-average-color": "^9.5.0", "fast-average-color": "^9.5.0",
"framer-motion": "^12.12.1", "framer-motion": "^12.12.1",
"html2canvas-pro": "^1.5.11", "html2canvas-pro": "^1.5.11",
"lodash": "^4.17.21",
"lucide-react": "^0.536.0", "lucide-react": "^0.536.0",
"next": "15.3.2", "next": "15.3.2",
"next-intl": "^4.1.0", "next-intl": "^4.1.0",
@@ -32,7 +31,6 @@
"@eslint/eslintrc": "^3", "@eslint/eslintrc": "^3",
"@tailwindcss/postcss": "^4", "@tailwindcss/postcss": "^4",
"@types/jest": "^29.5.14", "@types/jest": "^29.5.14",
"@types/lodash": "^4.17.20",
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^19", "@types/react": "^19",
"@types/react-dom": "^19", "@types/react-dom": "^19",

View File

@@ -425,6 +425,7 @@ export default function AvatarInfo() {
<Image <Image
width={904} width={904}
height={1260} height={1260}
priority
src={`https://api.hakush.in/hsr/UI/lightconemaxfigures/${lightconeDetail.id}.webp`} src={`https://api.hakush.in/hsr/UI/lightconemaxfigures/${lightconeDetail.id}.webp`}
className="w-full h-full rounded-lg object-cover shadow-lg" className="w-full h-full rounded-lg object-cover shadow-lg"
alt="Lightcone" alt="Lightcone"

View File

@@ -46,14 +46,14 @@ export default function EidolonsInfo() {
}} }}
> >
<Image <Image
className={`w-60 object-contain mb-2 ${Number(key) <= avatars[avatarSelected?.id || ""]?.data?.rank ? "" : "grayscale"}`}
loading="lazy"
className={`w-60 h-60 mb-2 ${Number(key) <= avatars[avatarSelected?.id || ""]?.data?.rank ? "" : "grayscale"}`}
src={`https://api.hakush.in/hsr/UI/rank/_dependencies/textures/${avatarSelected?.id}/${avatarSelected?.id}_Rank_${key}.webp`} src={`https://api.hakush.in/hsr/UI/rank/_dependencies/textures/${avatarSelected?.id}/${avatarSelected?.id}_Rank_${key}.webp`}
alt={`Rank ${key}`} alt={`Rank ${key}`}
priority
width={240} width={240}
height={240} height={240}
/> />
<div className="text-lg pb-1 flex items-center justify-items-center gap-2"> <div className="text-lg pb-1 flex items-center justify-items-center gap-2">
<span className="inline-block text-indigo-500">{key}.</span> <span className="inline-block text-indigo-500">{key}.</span>
<ParseText <ParseText

View File

@@ -8,7 +8,6 @@ import useUserDataStore from "@/stores/userDataStore";
import useMonsterStore from "@/stores/monsterStore"; import useMonsterStore from "@/stores/monsterStore";
import Image from "next/image"; import Image from "next/image";
import { MonsterStore } from "@/types"; import { MonsterStore } from "@/types";
import cloneDeep from 'lodash/cloneDeep'
import useMazeStore from "@/stores/mazeStore"; import useMazeStore from "@/stores/mazeStore";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { listCurrentLanguageApi } from "@/constant/constant"; import { listCurrentLanguageApi } from "@/constant/constant";
@@ -55,7 +54,7 @@ export default function AsBar() {
useEffect(() => { useEffect(() => {
if (!challengeSelected || as_config.event_id === 0 || as_config.challenge_id === 0) return if (!challengeSelected || as_config.event_id === 0 || as_config.challenge_id === 0) return
const newBattleConfig = cloneDeep(as_config) const newBattleConfig = structuredClone(as_config)
newBattleConfig.cycle_count = 0 newBattleConfig.cycle_count = 0
newBattleConfig.blessings = [] newBattleConfig.blessings = []

View File

@@ -17,7 +17,6 @@ import useLocaleStore from "@/stores/localeStore";
import { getLocaleName } from "@/helper"; import { getLocaleName } from "@/helper";
import Image from "next/image"; import Image from "next/image";
import { MonsterBasic } from "@/types"; import { MonsterBasic } from "@/types";
import cloneDeep from 'lodash/cloneDeep'
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { listCurrentLanguageApi } from "@/constant/constant"; import { listCurrentLanguageApi } from "@/constant/constant";
import useGlobalStore from "@/stores/globalStore"; import useGlobalStore from "@/stores/globalStore";
@@ -117,7 +116,7 @@ export default function CeBar() {
if (!ce_config) return if (!ce_config) return
if (!extraData || !extraData.theory_craft?.mode) return if (!extraData || !extraData.theory_craft?.mode) return
const newExtraData = cloneDeep(extraData) const newExtraData = structuredClone(extraData)
if (!newExtraData.theory_craft.hp) { if (!newExtraData.theory_craft.hp) {
newExtraData.theory_craft.hp = {} newExtraData.theory_craft.hp = {}
} }
@@ -253,7 +252,7 @@ export default function CeBar() {
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()
const newCeConfig = cloneDeep(ce_config) const newCeConfig = structuredClone(ce_config)
const waves = newCeConfig.monsters const waves = newCeConfig.monsters
const temp = waves[waveIndex - 1] const temp = waves[waveIndex - 1]
waves[waveIndex - 1] = waves[waveIndex] waves[waveIndex - 1] = waves[waveIndex]
@@ -270,7 +269,7 @@ export default function CeBar() {
disabled={waveIndex === ce_config.monsters.length - 1} disabled={waveIndex === ce_config.monsters.length - 1}
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()
const newCeConfig = cloneDeep(ce_config) const newCeConfig = structuredClone(ce_config)
const waves = newCeConfig.monsters const waves = newCeConfig.monsters
const temp = waves[waveIndex + 1] const temp = waves[waveIndex + 1]
waves[waveIndex + 1] = waves[waveIndex] waves[waveIndex + 1] = waves[waveIndex]
@@ -285,7 +284,7 @@ export default function CeBar() {
<button <button
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()
const newCeConfig = cloneDeep(ce_config) const newCeConfig = structuredClone(ce_config)
const waves = newCeConfig.monsters const waves = newCeConfig.monsters
const temp = waves[waveIndex] const temp = waves[waveIndex]
newCeConfig.monsters.push([...temp]) newCeConfig.monsters.push([...temp])
@@ -298,7 +297,7 @@ export default function CeBar() {
<button <button
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()
const newCeConfig = cloneDeep(ce_config) const newCeConfig = structuredClone(ce_config)
newCeConfig.monsters.splice(waveIndex, 1) newCeConfig.monsters.splice(waveIndex, 1)
setCeConfig(newCeConfig) setCeConfig(newCeConfig)
}} }}
@@ -316,7 +315,7 @@ export default function CeBar() {
<button <button
className="btn btn-xs btn-success absolute -top-2 right-12 opacity-50 group-hover:opacity-100 transition-opacity" className="btn btn-xs btn-success absolute -top-2 right-12 opacity-50 group-hover:opacity-100 transition-opacity"
onClick={() => { onClick={() => {
const newCeConfig = cloneDeep(ce_config) const newCeConfig = structuredClone(ce_config)
newCeConfig.monsters[waveIndex].push({ newCeConfig.monsters[waveIndex].push({
monster_id: Number(member.monster_id), monster_id: Number(member.monster_id),
@@ -331,7 +330,7 @@ export default function CeBar() {
<button <button
className="btn btn-xs btn-error absolute -top-2 right-2 opacity-50 group-hover:opacity-100 transition-opacity" className="btn btn-xs btn-error absolute -top-2 right-2 opacity-50 group-hover:opacity-100 transition-opacity"
onClick={() => { onClick={() => {
const newCeConfig = cloneDeep(ce_config) const newCeConfig = structuredClone(ce_config)
newCeConfig.monsters[waveIndex].splice(memberIndex, 1) newCeConfig.monsters[waveIndex].splice(memberIndex, 1)
setCeConfig(newCeConfig) setCeConfig(newCeConfig)
}} }}
@@ -379,7 +378,7 @@ export default function CeBar() {
if (isNaN(val) || val < 1 || val > 95) return if (isNaN(val) || val < 1 || val > 95) return
if (ce_config.monsters[waveIndex][memberIndex].level === val) return if (ce_config.monsters[waveIndex][memberIndex].level === val) return
const newCeConfig = cloneDeep(ce_config) const newCeConfig = structuredClone(ce_config)
newCeConfig.monsters[waveIndex][memberIndex].level = val newCeConfig.monsters[waveIndex][memberIndex].level = val
setCeConfig(newCeConfig) setCeConfig(newCeConfig)
}} }}
@@ -397,7 +396,7 @@ export default function CeBar() {
const val = Number(e.target.value) const val = Number(e.target.value)
if (isNaN(val) || val < 0) return if (isNaN(val) || val < 0) return
const newData = cloneDeep(extraData) const newData = structuredClone(extraData)
if (!newData?.theory_craft?.hp?.[(waveIndex + 1).toString()]) { if (!newData?.theory_craft?.hp?.[(waveIndex + 1).toString()]) {
newData.theory_craft.hp[(waveIndex + 1).toString()] = [] newData.theory_craft.hp[(waveIndex + 1).toString()] = []
@@ -473,7 +472,7 @@ export default function CeBar() {
key={monster.id} key={monster.id}
className="flex items-center gap-2 p-2 hover:bg-success/40 rounded cursor-pointer" className="flex items-center gap-2 p-2 hover:bg-success/40 rounded cursor-pointer"
onClick={() => { onClick={() => {
const newCeConfig = cloneDeep(ce_config) const newCeConfig = structuredClone(ce_config)
newCeConfig.monsters[waveIndex].push({ newCeConfig.monsters[waveIndex].push({
monster_id: Number(monster.id), monster_id: Number(monster.id),
level: 95, level: 95,
@@ -543,7 +542,7 @@ export default function CeBar() {
<div className="card-body p-8"> <div className="card-body p-8">
<button <button
onClick={() => { onClick={() => {
const newCeConfig = cloneDeep(ce_config) const newCeConfig = structuredClone(ce_config)
newCeConfig.monsters.push([]) newCeConfig.monsters.push([])
setCeConfig(newCeConfig) setCeConfig(newCeConfig)
}} }}

View File

@@ -8,10 +8,9 @@ import useLocaleStore from "@/stores/localeStore";
import useUserDataStore from "@/stores/userDataStore"; import useUserDataStore from "@/stores/userDataStore";
import useMonsterStore from "@/stores/monsterStore"; import useMonsterStore from "@/stores/monsterStore";
import Image from "next/image"; import Image from "next/image";
import { MonsterStore } from "@/types";
import cloneDeep from 'lodash/cloneDeep'
import useMazeStore from "@/stores/mazeStore"; import useMazeStore from "@/stores/mazeStore";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { MonsterStore } from "@/types";
export default function MocBar() { export default function MocBar() {
const { MOCEvent, mapMOCInfo } = useEventStore() const { MOCEvent, mapMOCInfo } = useEventStore()
@@ -32,7 +31,7 @@ export default function MocBar() {
useEffect(() => { useEffect(() => {
const challenge = mapMOCInfo[moc_config.event_id.toString()]?.find((moc) => moc.Id === moc_config.challenge_id) const challenge = mapMOCInfo[moc_config.event_id.toString()]?.find((moc) => moc.Id === moc_config.challenge_id)
if (moc_config.event_id !== 0 && moc_config.challenge_id !== 0 && challenge) { if (moc_config.event_id !== 0 && moc_config.challenge_id !== 0 && challenge) {
const newBattleConfig = cloneDeep(moc_config) const newBattleConfig = structuredClone(moc_config)
newBattleConfig.cycle_count = 0 newBattleConfig.cycle_count = 0
if (moc_config.use_cycle_count) { if (moc_config.use_cycle_count) {
newBattleConfig.cycle_count = challenge.Countdown newBattleConfig.cycle_count = challenge.Countdown

View File

@@ -7,7 +7,6 @@ import useLocaleStore from "@/stores/localeStore";
import useUserDataStore from "@/stores/userDataStore"; import useUserDataStore from "@/stores/userDataStore";
import useMonsterStore from "@/stores/monsterStore"; import useMonsterStore from "@/stores/monsterStore";
import Image from "next/image"; import Image from "next/image";
import cloneDeep from 'lodash/cloneDeep'
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { MonsterStore } from "@/types"; import { MonsterStore } from "@/types";
@@ -39,7 +38,7 @@ export default function PeakBar() {
}, [peak_config, mapPEAKInfo]) }, [peak_config, mapPEAKInfo])
const challengeSelected = useMemo(() => { const challengeSelected = useMemo(() => {
const challenge = cloneDeep(listFloor.find((peak) => peak.Id === peak_config.challenge_id)) const challenge = structuredClone(listFloor.find((peak) => peak.Id === peak_config.challenge_id))
if ( if (
challenge challenge
&& challenge.Id === mapPEAKInfo?.[peak_config?.event_id?.toString()]?.BossLevel?.Id && challenge.Id === mapPEAKInfo?.[peak_config?.event_id?.toString()]?.BossLevel?.Id
@@ -57,7 +56,7 @@ export default function PeakBar() {
useEffect(() => { useEffect(() => {
if (!challengeSelected) return if (!challengeSelected) return
if (peak_config.event_id !== 0 && peak_config.challenge_id !== 0 && challengeSelected) { if (peak_config.event_id !== 0 && peak_config.challenge_id !== 0 && challengeSelected) {
const newBattleConfig = cloneDeep(peak_config) const newBattleConfig = structuredClone(peak_config)
newBattleConfig.cycle_count = 6 newBattleConfig.cycle_count = 6
newBattleConfig.blessings = [] newBattleConfig.blessings = []
for (const value of challengeSelected.TagList) { for (const value of challengeSelected.TagList) {

View File

@@ -8,7 +8,6 @@ import useUserDataStore from "@/stores/userDataStore";
import useMonsterStore from "@/stores/monsterStore"; import useMonsterStore from "@/stores/monsterStore";
import Image from "next/image"; import Image from "next/image";
import { MonsterStore } from "@/types"; import { MonsterStore } from "@/types";
import cloneDeep from 'lodash/cloneDeep'
import useMazeStore from "@/stores/mazeStore"; import useMazeStore from "@/stores/mazeStore";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
@@ -35,7 +34,7 @@ export default function PfBar() {
if (!challengeSelected || pf_config.event_id === 0 || pf_config.challenge_id === 0) { if (!challengeSelected || pf_config.event_id === 0 || pf_config.challenge_id === 0) {
return return
} }
const newBattleConfig = cloneDeep(pf_config) const newBattleConfig = structuredClone(pf_config)
newBattleConfig.cycle_count = 4 newBattleConfig.cycle_count = 4
newBattleConfig.blessings = [] newBattleConfig.blessings = []
if (pf_config.buff_id !== 0) { if (pf_config.buff_id !== 0) {

View File

@@ -11,8 +11,7 @@ import useAvatarStore from '@/stores/avatarStore';
import useModelStore from '@/stores/modelStore'; import useModelStore from '@/stores/modelStore';
import useRelicMakerStore from '@/stores/relicMakerStore'; import useRelicMakerStore from '@/stores/relicMakerStore';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl'
import cloneDeep from 'lodash/cloneDeep'
import { ChevronDown, ChevronUp } from 'lucide-react'; import { ChevronDown, ChevronUp } from 'lucide-react';
import { AnimatePresence, motion } from 'framer-motion'; import { AnimatePresence, motion } from 'framer-motion';
@@ -81,7 +80,7 @@ export default function RelicMaker() {
const mainProp = mainAffixMap[selectedMainStat]?.property; const mainProp = mainAffixMap[selectedMainStat]?.property;
if (!mainProp) return; if (!mainProp) return;
const newSubAffixes = cloneDeep(listSelectedSubStats); const newSubAffixes = structuredClone(listSelectedSubStats);
let updated = false; let updated = false;
for (let i = 0; i < newSubAffixes.length; i++) { for (let i = 0; i < newSubAffixes.length; i++) {
@@ -126,7 +125,7 @@ export default function RelicMaker() {
const handleSubStatChange = (key: string, index: number, rollCount: number, stepCount: number) => { const handleSubStatChange = (key: string, index: number, rollCount: number, stepCount: number) => {
setError(""); setError("");
const newSubAffixes = cloneDeep(listSelectedSubStats); const newSubAffixes = structuredClone(listSelectedSubStats);
if (!subAffixOptions[key]) { if (!subAffixOptions[key]) {
newSubAffixes[index].affixId = ""; newSubAffixes[index].affixId = "";
newSubAffixes[index].property = ""; newSubAffixes[index].property = "";
@@ -151,8 +150,8 @@ export default function RelicMaker() {
const keys = Object.keys(preSelectedSubStats[index]); const keys = Object.keys(preSelectedSubStats[index]);
if (keys.length <= 1) return; if (keys.length <= 1) return;
const newSubAffixes = cloneDeep(listSelectedSubStats); const newSubAffixes = structuredClone(listSelectedSubStats);
const listHistory = cloneDeep(preSelectedSubStats[index]); const listHistory = structuredClone(preSelectedSubStats[index]);
const secondLastKey = listHistory.length - 2; const secondLastKey = listHistory.length - 2;
const preSubAffixes = { ...listHistory[secondLastKey] }; const preSubAffixes = { ...listHistory[secondLastKey] };
newSubAffixes[index].rollCount = preSubAffixes.rollCount; newSubAffixes[index].rollCount = preSubAffixes.rollCount;
@@ -162,7 +161,7 @@ export default function RelicMaker() {
}; };
const resetSubStat = (index: number) => { const resetSubStat = (index: number) => {
const newSubAffixes = cloneDeep(listSelectedSubStats); const newSubAffixes = structuredClone(listSelectedSubStats);
resetHistory(index); resetHistory(index);
newSubAffixes[index].affixId = ""; newSubAffixes[index].affixId = "";
newSubAffixes[index].property = ""; newSubAffixes[index].property = "";
@@ -172,7 +171,7 @@ export default function RelicMaker() {
}; };
const randomizeStats = () => { const randomizeStats = () => {
const newSubAffixes = cloneDeep(listSelectedSubStats); const newSubAffixes = structuredClone(listSelectedSubStats);
const exKeys = Object.keys(exSubAffixOptions); const exKeys = Object.keys(exSubAffixOptions);
for (let i = 0; i < newSubAffixes.length; i++) { for (let i = 0; i < newSubAffixes.length; i++) {
const keys = Object.keys(subAffixOptions).filter((key) => !exKeys.includes(key)); const keys = Object.keys(subAffixOptions).filter((key) => !exKeys.includes(key));
@@ -192,7 +191,7 @@ export default function RelicMaker() {
}; };
const randomizeRolls = () => { const randomizeRolls = () => {
const newSubAffixes = cloneDeep(listSelectedSubStats); const newSubAffixes = structuredClone(listSelectedSubStats);
const randomRolls = randomPartition(9, listSelectedSubStats.length); const randomRolls = randomPartition(9, listSelectedSubStats.length);
for (let i = 0; i < listSelectedSubStats.length; i++) { for (let i = 0; i < listSelectedSubStats.length; i++) {
newSubAffixes[i].rollCount = randomRolls[i]; newSubAffixes[i].rollCount = randomRolls[i];

View File

@@ -739,6 +739,7 @@ export default function ShowCaseInfo() {
alt="Lightcone Image" alt="Lightcone Image"
width={904} width={904}
height={1206} height={1206}
priority
style={{ style={{
top: '0px', top: '0px',
left: '6px', left: '6px',

View File

@@ -10,7 +10,6 @@ import Image from "next/image";
import { replaceByParam } from "@/helper"; import { replaceByParam } from "@/helper";
import { mappingStats } from "@/constant/constant"; import { mappingStats } from "@/constant/constant";
import { StatusAddType } from "@/types"; import { StatusAddType } from "@/types";
import cloneDeep from "lodash/cloneDeep";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
export default function SkillsInfo() { export default function SkillsInfo() {
@@ -115,7 +114,7 @@ export default function SkillsInfo() {
toast.error(transI18n("maxAllFailed")) toast.error(transI18n("maxAllFailed"))
return return
} }
const newData = cloneDeep(avatarData) const newData = structuredClone(avatarData)
newData.data.skills = Object.values(avatarSkillTree).reduce((acc, dataPointEntry) => { newData.data.skills = Object.values(avatarSkillTree).reduce((acc, dataPointEntry) => {
const firstEntry = Object.values(dataPointEntry)[0]; const firstEntry = Object.values(dataPointEntry)[0];
if (firstEntry) { if (firstEntry) {
@@ -129,7 +128,7 @@ export default function SkillsInfo() {
const handlerChangeStatusTrace = (status: boolean) => { const handlerChangeStatusTrace = (status: boolean) => {
if (!avatarData || !skillInfo) return if (!avatarData || !skillInfo) return
const newData = cloneDeep(avatarData) const newData = structuredClone(avatarData)
newData.data.skills[skillInfo?.PointID] = status ? 1 : 0 newData.data.skills[skillInfo?.PointID] = status ? 1 : 0
if (!status && traceLink?.[avatarSelected?.baseType || ""]?.[skillSelected || ""]) { if (!status && traceLink?.[avatarSelected?.baseType || ""]?.[skillSelected || ""]) {
@@ -286,7 +285,7 @@ export default function SkillsInfo() {
max={skillInfo?.MaxLevel || 1} max={skillInfo?.MaxLevel || 1}
value={avatarData?.data.skills?.[skillInfo?.PointID] || 1} value={avatarData?.data.skills?.[skillInfo?.PointID] || 1}
onChange={(e) => { onChange={(e) => {
const newData = cloneDeep(avatarData) const newData = structuredClone(avatarData)
newData.data.skills[skillInfo?.PointID] = parseInt(e.target.value) newData.data.skills[skillInfo?.PointID] = parseInt(e.target.value)
setAvatar(newData) setAvatar(newData)
}} }}
@@ -308,12 +307,12 @@ export default function SkillsInfo() {
onChange={(e) => { onChange={(e) => {
if (traceButtons?.find((btn) => btn.id === skillSelected)?.size === "special") { if (traceButtons?.find((btn) => btn.id === skillSelected)?.size === "special") {
if (e.target.checked) { if (e.target.checked) {
const newData = cloneDeep(avatarData) const newData = structuredClone(avatarData)
newData.data.skills[skillInfo?.PointID] = 1 newData.data.skills[skillInfo?.PointID] = 1
setAvatar(newData) setAvatar(newData)
return return
} }
const newData = cloneDeep(avatarData) const newData = structuredClone(avatarData)
delete newData.data.skills[skillInfo?.PointID] delete newData.data.skills[skillInfo?.PointID]
setAvatar(newData) setAvatar(newData)
return return

View File

@@ -1,6 +1,4 @@
import { create } from 'zustand' import { create } from 'zustand'
import cloneDeep from 'lodash/cloneDeep'
interface RelicMakerState { interface RelicMakerState {
selectedRelicSlot: string; selectedRelicSlot: string;
selectedMainStat: string; selectedMainStat: string;
@@ -185,14 +183,14 @@ const useRelicMakerStore = create<RelicMakerState>((set) => ({
return {} return {}
}), }),
popHistory: (index: number) => set((state) => { popHistory: (index: number) => set((state) => {
const newPreSelectedSubStats = cloneDeep(state.preSelectedSubStats); const newPreSelectedSubStats = structuredClone(state.preSelectedSubStats);
const copied = state.preSelectedSubStats[index].map(item => ({ ...item })); const copied = state.preSelectedSubStats[index].map(item => ({ ...item }));
copied.pop(); copied.pop();
newPreSelectedSubStats[index] = copied; newPreSelectedSubStats[index] = copied;
return { preSelectedSubStats: newPreSelectedSubStats }; return { preSelectedSubStats: newPreSelectedSubStats };
}), }),
addHistory: (index, affix) => set((state) => { addHistory: (index, affix) => set((state) => {
const newPreSelectedSubStats = cloneDeep(state.preSelectedSubStats); const newPreSelectedSubStats = structuredClone(state.preSelectedSubStats);
const currentList = state.preSelectedSubStats[index]; const currentList = state.preSelectedSubStats[index];
const copied = currentList ? currentList.map(item => ({ ...item })) : [ const copied = currentList ? currentList.map(item => ({ ...item })) : [
@@ -203,7 +201,7 @@ const useRelicMakerStore = create<RelicMakerState>((set) => ({
]; ];
if (copied) { if (copied) {
const newAffix = cloneDeep(affix); const newAffix = structuredClone(affix);
copied.push(newAffix); copied.push(newAffix);
newPreSelectedSubStats[index] = copied; newPreSelectedSubStats[index] = copied;
return { preSelectedSubStats: newPreSelectedSubStats }; return { preSelectedSubStats: newPreSelectedSubStats };