fix(avatar): 移除并行工具轮播,头像固定显示当前工具,文字过渡与SVG切换同步

This commit is contained in:
JOJO 2026-08-12 23:41:34 +08:00
parent 56c067b710
commit 4f940e9a86
2 changed files with 21 additions and 28 deletions

View File

@ -101,7 +101,6 @@ const props = withDefaults(
} }
); );
const emit = defineEmits<{ const emit = defineEmits<{
(event: 'active-index', index: number): void;
(event: 'poke'): void; (event: 'poke'): void;
}>(); }>();
@ -314,18 +313,12 @@ function trackEyes() {
trackRaf = requestAnimationFrame(trackEyes); trackRaf = requestAnimationFrame(trackEyes);
} }
// ---- ---- // ---- face ----
let carouselTimer: number | null = null;
let faceSwitchTimer: number | null = null; let faceSwitchTimer: number | null = null;
let blinkTimer: number | null = null; let blinkTimer: number | null = null;
let nervousTimer: number | null = null; let nervousTimer: number | null = null;
let isBlinking = false; let isBlinking = false;
let carouselIdx = 0;
const internalMode = ref<string | null>(null); const internalMode = ref<string | null>(null);
function stopCarousel() {
if (carouselTimer) clearInterval(carouselTimer);
carouselTimer = null;
}
function stopFaceSwitchTimer() { function stopFaceSwitchTimer() {
if (faceSwitchTimer) clearTimeout(faceSwitchTimer); if (faceSwitchTimer) clearTimeout(faceSwitchTimer);
faceSwitchTimer = null; faceSwitchTimer = null;
@ -375,7 +368,6 @@ function triggerNervous() {
stopAutoBlink(); stopAutoBlink();
stopNervousTimer(); stopNervousTimer();
stopTracking(); stopTracking();
stopCarousel();
stopFaceSwitchTimer(); stopFaceSwitchTimer();
activeFaceKey.value = null; activeFaceKey.value = null;
sharedVisible.value = true; sharedVisible.value = true;
@ -424,20 +416,6 @@ function setIconFace(key: string, animated = true) {
faceSwitchTimer = null; faceSwitchTimer = null;
}, 160); }, 160);
} }
function startCarousel(keys: string[]) {
stopCarousel();
stopFaceSwitchTimer();
carouselIdx = 0;
setIconFace(keys[0]);
emit('active-index', carouselIdx);
if (keys.length < 2) return;
carouselTimer = window.setInterval(() => {
carouselIdx = (carouselIdx + 1) % keys.length;
setIconFace(keys[carouselIdx]);
emit('active-index', carouselIdx);
}, 1450);
}
// ---- ---- // ---- ----
function applyState() { function applyState() {
if (props.mode !== 'idle' && internalMode.value) { if (props.mode !== 'idle' && internalMode.value) {
@ -449,10 +427,11 @@ function applyState() {
if (mode === 'tool') { if (mode === 'tool') {
stopTracking(); stopTracking();
const keys = (props.toolKeys || []).filter(Boolean); const keys = (props.toolKeys || []).filter(Boolean);
startCarousel(keys.length ? keys : ['command']); //
// toolKeys
setIconFace(keys.length ? keys[0] : 'command');
return; return;
} }
stopCarousel();
stopFaceSwitchTimer(); stopFaceSwitchTimer();
if (mode === 'think') { if (mode === 'think') {
stopTracking(); stopTracking();
@ -493,7 +472,13 @@ function applyState() {
} }
} }
watch(() => [props.mode, props.toolKeys, props.tracking, internalMode.value], () => applyState(), { deep: true }); // toolKeys join avatarStatus computed
// intent applyState
// face
watch(
() => [props.mode, (props.toolKeys || []).join('\u001f'), props.tracking, internalMode.value],
() => applyState()
);
onMounted(() => { onMounted(() => {
// SVG // SVG
@ -504,7 +489,6 @@ onMounted(() => {
onBeforeUnmount(() => { onBeforeUnmount(() => {
document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mousemove', onMouseMove);
stopTracking(); stopTracking();
stopCarousel();
stopFaceSwitchTimer(); stopFaceSwitchTimer();
stopAutoBlink(); stopAutoBlink();
stopNervousTimer(); stopNervousTimer();

View File

@ -106,7 +106,7 @@
</span> </span>
<span <span
v-else-if="composerAvatarText" v-else-if="composerAvatarText"
:key="`tool-${props.avatarStatus?.mode}`" :key="composerAvatarTextKey"
class="composer-avatar__text" class="composer-avatar__text"
:class="{ :class="{
'composer-avatar__text--right': !floatingStatusVisible, 'composer-avatar__text--right': !floatingStatusVisible,
@ -975,6 +975,15 @@ const composerAvatarText = computed(() => {
return ''; return '';
}); });
// key running tool
// 12 out-in SVG
const composerAvatarTextKey = computed(() => {
const s = props.avatarStatus;
if (!s) return 'avatar-none';
if (s.mode === 'tool') return `avatar-tool-${s.toolKeys?.[0] || ''}`;
return `avatar-${s.mode}`;
});
const projectGitMenuOpen = ref<null | 'project' | 'branch'>(null); const projectGitMenuOpen = ref<null | 'project' | 'branch'>(null);
const closeProjectGitMenu = () => { const closeProjectGitMenu = () => {