From f08507c0924e67316cc2a38b7f8acf50b81c0980 Mon Sep 17 00:00:00 2001 From: Promansis Date: Fri, 22 May 2026 22:23:57 +0800 Subject: [PATCH 1/4] avatar crop scaling --- .../components/CharacterAvatarImage.tsx | 48 +++++++++++++++++++ .../components/CharacterLibraryView.tsx | 21 +++----- .../characters/components/CharactersPanel.tsx | 18 ++----- 3 files changed, 60 insertions(+), 27 deletions(-) create mode 100644 src/features/characters/components/CharacterAvatarImage.tsx diff --git a/src/features/characters/components/CharacterAvatarImage.tsx b/src/features/characters/components/CharacterAvatarImage.tsx new file mode 100644 index 0000000..5cc593e --- /dev/null +++ b/src/features/characters/components/CharacterAvatarImage.tsx @@ -0,0 +1,48 @@ +import type { AvatarCrop } from "../../../shared/lib/utils"; +import { cn, getAvatarCropStyle, parseAvatarCropJson } from "../../../shared/lib/utils"; + +function isAvatarCrop(value: unknown): value is AvatarCrop { + return ( + !!value && + typeof value === "object" && + Number.isFinite((value as AvatarCrop).srcX) && + Number.isFinite((value as AvatarCrop).srcY) && + Number.isFinite((value as AvatarCrop).srcWidth) && + Number.isFinite((value as AvatarCrop).srcHeight) && + (value as AvatarCrop).srcWidth > 0 && + (value as AvatarCrop).srcHeight > 0 && + (value as AvatarCrop).srcX >= 0 && + (value as AvatarCrop).srcY >= 0 && + (value as AvatarCrop).srcX + (value as AvatarCrop).srcWidth <= 1.001 && + (value as AvatarCrop).srcY + (value as AvatarCrop).srcHeight <= 1.001 + ); +} + +function resolveAvatarCrop(crop: unknown): AvatarCrop | null { + if (!crop) return null; + if (typeof crop === "string") return parseAvatarCropJson(crop); + return isAvatarCrop(crop) ? crop : null; +} + +export function CharacterAvatarImage({ + src, + alt, + crop, + className, +}: { + src: string; + alt: string; + crop?: unknown; + className?: string; +}) { + return ( + {alt} + ); +} diff --git a/src/features/characters/components/CharacterLibraryView.tsx b/src/features/characters/components/CharacterLibraryView.tsx index bf9d721..eb4b2fe 100644 --- a/src/features/characters/components/CharacterLibraryView.tsx +++ b/src/features/characters/components/CharacterLibraryView.tsx @@ -3,8 +3,9 @@ import { ArrowLeft, ArrowUpDown, Download, MessageCircle, Pencil, Plus, Search, import { useCharacters } from "../hooks/use-characters"; import { useStartChatFromCharacter } from "../hooks/use-start-chat-from-character"; import { getCharacterTitle } from "../../../shared/lib/character-display"; -import { cn, getAvatarCropStyle, type AvatarCrop } from "../../../shared/lib/utils"; +import { cn } from "../../../shared/lib/utils"; import { useUIStore } from "../../../shared/stores/ui.store"; +import { CharacterAvatarImage } from "./CharacterAvatarImage"; type CharacterData = Record & { name?: string; @@ -106,14 +107,10 @@ function CharacterLibraryDetailCard({
{character.avatarPath ? ( - {characterName ) : (
@@ -428,15 +425,11 @@ export function CharacterLibraryView() { >
{char.avatarPath ? ( - {charName} ) : (
diff --git a/src/features/characters/components/CharactersPanel.tsx b/src/features/characters/components/CharactersPanel.tsx index cf5d5d4..692944f 100644 --- a/src/features/characters/components/CharactersPanel.tsx +++ b/src/features/characters/components/CharactersPanel.tsx @@ -48,8 +48,9 @@ import { } from "lucide-react"; import { getCharacterTitle } from "../../../shared/lib/character-display"; import { useUIStore } from "../../../shared/stores/ui.store"; -import { cn, getAvatarCropStyle, type AvatarCrop } from "../../../shared/lib/utils"; +import { cn } from "../../../shared/lib/utils"; import { ExportFormatDialog, type ExportFormatChoice } from "../../../shared/components/ui/ExportFormatDialog"; +import { CharacterAvatarImage } from "./CharacterAvatarImage"; type CharacterRow = { id: string; @@ -946,12 +947,7 @@ export function CharactersPanel() { >
{member.avatarPath ? ( - {member.name} + ) : ( )} @@ -1120,14 +1116,10 @@ export function CharactersPanel() {
{avatarUrl ? (
- {charName}
) : ( From 3ff0db4e0f92ab6ce1115309c3d794ac1f960ab7 Mon Sep 17 00:00:00 2001 From: Promansis Date: Sat, 23 May 2026 21:25:33 +0800 Subject: [PATCH 2/4] fix character group avatar crops --- .../characters/components/CharactersPanel.tsx | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/features/characters/components/CharactersPanel.tsx b/src/features/characters/components/CharactersPanel.tsx index 692944f..149eb44 100644 --- a/src/features/characters/components/CharactersPanel.tsx +++ b/src/features/characters/components/CharactersPanel.tsx @@ -182,9 +182,17 @@ export function CharactersPanel() { }, [characters]) as ParsedCharacterRow[]; const charMap = useMemo(() => { - const map = new Map(); + const map = new Map< + string, + { name: string; comment?: string | null; avatarPath: string | null; avatarCrop?: unknown } + >(); for (const c of parsedCharacters) { - map.set(c.id, { name: c.parsed.name ?? "Unknown", comment: c.comment, avatarPath: c.avatarPath }); + map.set(c.id, { + name: c.parsed.name ?? "Unknown", + comment: c.comment, + avatarPath: c.avatarPath, + avatarCrop: c.parsed.extensions?.avatarCrop, + }); } return map; }, [parsedCharacters]); @@ -945,9 +953,13 @@ export function CharactersPanel() { }} className="group/member flex cursor-pointer items-center gap-2 rounded-lg p-1.5 transition-all hover:bg-[var(--sidebar-accent)]" > -
+
{member.avatarPath ? ( - + ) : ( )} From 29967b10773e8ad4d475af650ef6c53b2a8c7d78 Mon Sep 17 00:00:00 2001 From: Promansis Date: Sat, 23 May 2026 21:31:46 +0800 Subject: [PATCH 3/4] show full images in character library cards --- .../characters/components/CharacterLibraryView.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/features/characters/components/CharacterLibraryView.tsx b/src/features/characters/components/CharacterLibraryView.tsx index eb4b2fe..2e803dd 100644 --- a/src/features/characters/components/CharacterLibraryView.tsx +++ b/src/features/characters/components/CharacterLibraryView.tsx @@ -5,7 +5,6 @@ import { useStartChatFromCharacter } from "../hooks/use-start-chat-from-characte import { getCharacterTitle } from "../../../shared/lib/character-display"; import { cn } from "../../../shared/lib/utils"; import { useUIStore } from "../../../shared/stores/ui.store"; -import { CharacterAvatarImage } from "./CharacterAvatarImage"; type CharacterData = Record & { name?: string; @@ -107,10 +106,12 @@ function CharacterLibraryDetailCard({
{character.avatarPath ? ( - ) : (
@@ -425,11 +426,12 @@ export function CharacterLibraryView() { >
{char.avatarPath ? ( - ) : (
From fbedf0a50caa93062e8fce83073ed6b3e0c11ddb Mon Sep 17 00:00:00 2001 From: Promansis Date: Sat, 23 May 2026 21:38:43 +0800 Subject: [PATCH 4/4] Revert "show full images in character library cards" This reverts commit 29967b10773e8ad4d475af650ef6c53b2a8c7d78. --- .../characters/components/CharacterLibraryView.tsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/features/characters/components/CharacterLibraryView.tsx b/src/features/characters/components/CharacterLibraryView.tsx index 2e803dd..eb4b2fe 100644 --- a/src/features/characters/components/CharacterLibraryView.tsx +++ b/src/features/characters/components/CharacterLibraryView.tsx @@ -5,6 +5,7 @@ import { useStartChatFromCharacter } from "../hooks/use-start-chat-from-characte import { getCharacterTitle } from "../../../shared/lib/character-display"; import { cn } from "../../../shared/lib/utils"; import { useUIStore } from "../../../shared/stores/ui.store"; +import { CharacterAvatarImage } from "./CharacterAvatarImage"; type CharacterData = Record & { name?: string; @@ -106,12 +107,10 @@ function CharacterLibraryDetailCard({
{character.avatarPath ? ( - {characterName ) : (
@@ -426,12 +425,11 @@ export function CharacterLibraryView() { >
{char.avatarPath ? ( - {charName} ) : (