feat: 又一大波改动

This commit is contained in:
claude-code-best
2026-04-23 11:20:24 +08:00
parent 1a910ed639
commit ecf2dbde44
7 changed files with 147 additions and 56 deletions

View File

@@ -13,6 +13,7 @@ import {
getCreatureName,
getXpProgress,
loadSprite,
fetchAndCacheSprite,
getFallbackSprite,
renderAnimatedSprite,
getIdleAnimMode,
@@ -165,10 +166,19 @@ export function CompanionSprite(): React.ReactNode {
const xpInfo = useAppState(s => s.companionXpInfo);
const focused = useAppState(s => s.footerSelection === 'companion');
// Subscribe to creature changes so we re-render immediately after switch
const _creatureChangedAt = useAppState(s => s.companionCreatureChangedAt);
const creatureChangedAt = useAppState(s => s.companionCreatureChangedAt);
const setAppState = useSetAppState();
const { columns } = useTerminalSize();
const [tick, setTick] = useState(0);
const [spriteTick, setSpriteTick] = useState(0);
// Prefetch sprite when creature changes
useEffect(() => {
const c = getPokemonCreature();
if (!c || loadSprite(c.speciesId)) return;
fetchAndCacheSprite(c.speciesId).then(s => { if (s) setSpriteTick(t => t + 1) });
}, [creatureChangedAt]);
void spriteTick;
const lastSpokeTick = useRef(0);
const [{ petStartTick, forPetAt }, setPetStart] = useState({
petStartTick: 0,

View File

@@ -19,7 +19,7 @@ import { calculateStats, getCreatureName, getTotalEV, getActiveCreature, saveBud
import { getXpProgress } from '@claude-code-best/pokemon';
import { getGenderSymbol } from '@claude-code-best/pokemon';
import { StatBar, SpriteAnimator, getFallbackSprite, loadSprite, SpeciesPicker } from '@claude-code-best/pokemon';
import { StatBar, SpriteAnimator, getFallbackSprite, loadSprite, fetchAndCacheSprite, SpeciesPicker } from '@claude-code-best/pokemon';
import type { LocalJSXCommandOnDone } from '../../types/command.js';
const CYAN: Color = 'ansi:cyan';
@@ -136,6 +136,7 @@ function PartyView({
const [focusedSlot, setFocusedSlot] = useState(0);
const [statusMsg, setStatusMsg] = useState<string | null>(null);
const [tick, setTick] = useState(0); // force re-render on navigation
const [spriteTick, setSpriteTick] = useState(0); // force re-render after sprite fetch
useInput((_input, key) => {
if (!isActive) return;
@@ -171,6 +172,31 @@ function PartyView({
? data.creatures.find(c => c.id === focusedCreatureId) ?? null
: null;
// Async-fetch sprite for focused creature if not cached
React.useEffect(() => {
if (!focusedCreature) return;
if (loadSprite(focusedCreature.speciesId)) return;
fetchAndCacheSprite(focusedCreature.speciesId).then((sprite) => {
if (sprite) setSpriteTick(t => t + 1);
});
}, [focusedCreature?.speciesId]);
// Also prefetch sprites for all party members on mount
React.useEffect(() => {
for (const id of data.party) {
if (!id) continue;
const c = data.creatures.find(cr => cr.id === id);
if (c && !loadSprite(c.speciesId)) {
fetchAndCacheSprite(c.speciesId).then((sprite) => {
if (sprite) setSpriteTick(t => t + 1);
});
}
}
}, []);
// Consume spriteTick to avoid unused warning
void spriteTick;
// Load sprite for focused creature (not just active)
const focusedSprite = focusedCreature
? (loadSprite(focusedCreature.speciesId)?.lines ?? getFallbackSprite(focusedCreature.speciesId))
@@ -417,6 +443,15 @@ function DexTab({
const [focusedId, setFocusedId] = useState<SpeciesId>(buddyData.dex[0]?.speciesId ?? 'bulbasaur');
const [dexCursor, setDexCursor] = useState(0);
const [statusMsg, setStatusMsg] = useState<string | null>(null);
const [dexSpriteTick, setDexSpriteTick] = useState(0);
// Prefetch sprite for focused dex species
React.useEffect(() => {
if (!loadSprite(focusedId)) {
fetchAndCacheSprite(focusedId).then(s => { if (s) setDexSpriteTick(t => t + 1) });
}
}, [focusedId]);
void dexSpriteTick;
// Sorted discovered species
const discovered = buddyData.dex