From 140520fc5e21fb188ca2c83ea4dc06e7641f1434 Mon Sep 17 00:00:00 2001 From: sk1982 Date: Mon, 22 Apr 2024 00:28:52 -0400 Subject: [PATCH] fix: chuni: errors from null userbox values when items not in database --- src/actions/chuni/profile.ts | 9 +++-- .../(with-header)/chuni/userbox/userbox.tsx | 38 +++++++++---------- src/components/chuni/avatar.tsx | 12 +++--- src/components/chuni/nameplate.tsx | 8 ++-- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/actions/chuni/profile.ts b/src/actions/chuni/profile.ts index cdc3a42..8c12189 100644 --- a/src/actions/chuni/profile.ts +++ b/src/actions/chuni/profile.ts @@ -58,14 +58,17 @@ export async function getUserData(user: { id: number }) { [`${name}.name as ${name}Name`, `${name}.iconPath as ${name}Icon`, `${name}.texturePath as ${name}Texture`] as const) ]) - .where(({ and, eb, selectFrom }) => and([ + .where(({ and, eb, selectFrom, or }) => and([ eb('p.user', '=', user.id), eb('p.version', '=', selectFrom('chuni_static_music') .select(({ fn }) => fn.max('version').as('latest')) ), - ...avatarNames.map(name => eb(`${name}.version`, '=', selectFrom('chuni_static_music') - .select(({ fn }) => fn.max('version').as('latest')))) + ...avatarNames.map(name => or([ + eb(`${name}.version`, '=', selectFrom('chuni_static_avatar') + .select(({ fn }) => fn.max('version').as('latest'))), + eb(`${name}.version`, 'is', null) + ])) ])) .executeTakeFirst(); diff --git a/src/app/(with-header)/chuni/userbox/userbox.tsx b/src/app/(with-header)/chuni/userbox/userbox.tsx index d86feb6..ab6ddd9 100644 --- a/src/app/(with-header)/chuni/userbox/userbox.tsx +++ b/src/app/(with-header)/chuni/userbox/userbox.tsx @@ -43,7 +43,7 @@ const ITEM_KEYS: Record> = const AVATAR_KEYS = ['avatarWear', 'avatarHead', 'avatarFace', 'avatarSkin', 'avatarItem', 'avatarFront', 'avatarBack'] as const; type RequiredUserbox = NonNullable; -type EquippedItem = { [K in keyof RequiredUserbox]: RequiredUserbox[K][number] }; +type EquippedItem = { [K in keyof RequiredUserbox]: RequiredUserbox[K][number] | null }; type SavedItem = { [K in keyof RequiredUserbox]: boolean } & { username: boolean }; export const ChuniUserbox = ({ profile, userboxItems }: ChuniUserboxProps) => { @@ -92,7 +92,7 @@ export const ChuniUserbox = ({ profile, userboxItems }: ChuniUserboxProps) => { const update: Partial = Object.fromEntries((Object.entries(equipped) as Entries) .filter(([k]) => items.includes(k as any)) - .map(([k, v]) => [ITEM_KEYS[k], v.id])); + .map(([k, v]) => [ITEM_KEYS[k], v?.id])); if ((items as string[]).includes('username')) update.userName = username; @@ -129,13 +129,13 @@ export const ChuniUserbox = ({ profile, userboxItems }: ChuniUserboxProps) => { selectedKeys={selectedLine} onSelectionChange={s => { if (typeof s === 'string' || !s.size) return; setSelectedLine(s as any); - play(getAudioUrl(`chuni/system-voice/${selectingVoice?.cuePath ?? equipped.systemVoice.cuePath}_${[...s][0]}`)) + play(getAudioUrl(`chuni/system-voice/${selectingVoice?.cuePath ?? equipped.systemVoice?.cuePath}_${[...s][0]}`)) }}> {CHUNI_VOICE_LINES.map(([line, id]) => {line})} ); @@ -171,14 +171,14 @@ export const ChuniUserbox = ({ profile, userboxItems }: ChuniUserboxProps) => { - setEditingUsername(false)} setUsername={u => { setSaved(s => ({ ...s, username: false })); @@ -225,12 +225,12 @@ export const ChuniUserbox = ({ profile, userboxItems }: ChuniUserboxProps) => {
+ wear={equipped.avatarWear?.texturePath} + head={equipped.avatarHead?.texturePath} + face={equipped.avatarFace?.texturePath} + skin={equipped.avatarSkin?.texturePath} + item={equipped.avatarItem?.texturePath} + back={equipped.avatarBack?.texturePath}/>
{(['avatarHead', 'avatarFace', 'avatarWear', 'avatarSkin', 'avatarItem', 'avatarBack'] as const).map(k => ((k !== 'avatarSkin' || userboxItems.avatarSkin.length > 1) && {
{equipped.systemVoice.name - { equipped.systemVoice.name } + alt={equipped.systemVoice?.name ?? ''} src={getImageUrl(`chuni/system-voice-icon/${equipped.systemVoice?.imagePath}`)} /> + { equipped.systemVoice?.name }
@@ -324,8 +324,8 @@ export const ChuniUserbox = ({ profile, userboxItems }: ChuniUserboxProps) => { {equipped.mapIcon.name - { equipped.mapIcon.name } + alt={equipped.mapIcon?.name ?? ''} src={getImageUrl(`chuni/map-icon/${equipped.mapIcon?.imagePath}`)} /> + { equipped.mapIcon?.name }
i && equipItem('mapIcon', i)} selectedItem={equipped.mapIcon} displayMode="grid" modalSize="full" rowSize={210} colSize={175} items={userboxItems.mapIcon} gap={6} diff --git a/src/components/chuni/avatar.tsx b/src/components/chuni/avatar.tsx index 301e19c..5d8b697 100644 --- a/src/components/chuni/avatar.tsx +++ b/src/components/chuni/avatar.tsx @@ -2,12 +2,12 @@ import { getImageUrl } from '@/helpers/assets'; import Image from 'next/image'; export type ChuniAvatarProps = { - wear: string | null, - head: string | null, - face: string | null, - skin: string | null, - item: string | null, - back: string | null, + wear: string | null | undefined, + head: string | null | undefined, + face: string | null | undefined, + skin: string | null | undefined, + item: string | null | undefined, + back: string | null | undefined, className?: string }; diff --git a/src/components/chuni/nameplate.tsx b/src/components/chuni/nameplate.tsx index 700e2c8..b5bb7fa 100644 --- a/src/components/chuni/nameplate.tsx +++ b/src/components/chuni/nameplate.tsx @@ -15,7 +15,7 @@ export type Profile = PickNullable, }; export const ChuniNameplate = ({ className, profile }: ChuniNameplateProps) => { @@ -36,7 +36,7 @@ export const ChuniNameplate = ({ className, profile }: ChuniNameplateProps) => {
- +
@@ -65,8 +65,8 @@ export const ChuniNameplate = ({ className, profile }: ChuniNameplateProps) => {
Character + `chuni/character/CHU_UI_Character_${Math.floor(profile.characterId! / 10).toString() + .padStart(4, '0')}_${(profile.characterId! % 10).toString().padStart(2, '0')}_02`) : ''}/>