feat(panel): improve header update loop and animations

This commit is contained in:
Simon
2025-10-21 17:51:51 +08:00
parent 89c065d5c5
commit 73b4b301a4

View File

@@ -27,6 +27,9 @@ export class Panel {
#pageAgent: PageAgent #pageAgent: PageAgent
#userAnswerResolver: ((input: string) => void) | null = null #userAnswerResolver: ((input: string) => void) | null = null
#isWaitingForUserAnswer: boolean = false #isWaitingForUserAnswer: boolean = false
#headerUpdateTimer: ReturnType<typeof setInterval> | null = null
#pendingHeaderText: string | null = null
#isAnimating = false
get wrapper(): HTMLElement { get wrapper(): HTMLElement {
return this.#wrapper return this.#wrapper
@@ -46,6 +49,7 @@ export class Panel {
this.#taskInput = this.#wrapper.querySelector(`.${styles.taskInput}`)! this.#taskInput = this.#wrapper.querySelector(`.${styles.taskInput}`)!
this.#setupEventListeners() this.#setupEventListeners()
this.#startHeaderUpdateLoop()
// this.#expand() // debug // this.#expand() // debug
this.#showInputArea() this.#showInputArea()
@@ -85,20 +89,19 @@ export class Panel {
*/ */
dispose(): void { dispose(): void {
this.#isWaitingForUserAnswer = false this.#isWaitingForUserAnswer = false
this.#stopHeaderUpdateLoop()
this.wrapper.remove() this.wrapper.remove()
} }
/** /**
* Update status * Update status
*/ */
async #update(stepData: Omit<Step, 'id' | 'stepNumber' | 'timestamp'>): Promise<void> { #update(stepData: Omit<Step, 'id' | 'stepNumber' | 'timestamp'>): void {
const step = this.#state.addStep(stepData) const step = this.#state.addStep(stepData)
// Show animation if text changes // Queue header text update (will be processed by periodic check)
const headerText = truncate(step.displayText, 20) const headerText = truncate(step.displayText, 20)
if (this.#statusText.textContent !== headerText) { this.#pendingHeaderText = headerText
await this.#animateTextChange(headerText)
}
this.#updateStatusIndicator(step.type) this.#updateStatusIndicator(step.type)
this.#updateHistory() this.#updateHistory()
@@ -394,25 +397,69 @@ export class Panel {
this.#expandButton.textContent = '▼' this.#expandButton.textContent = '▼'
} }
async #animateTextChange(newText: string): Promise<void> { /**
return new Promise((resolve) => { * Start periodic header update loop
// Fade out current text */
this.#statusText.classList.add(styles.fadeOut) #startHeaderUpdateLoop(): void {
// Check every 450ms (same as total animation duration)
this.#headerUpdateTimer = setInterval(() => {
this.#checkAndUpdateHeader()
}, 450)
}
/**
* Stop periodic header update loop
*/
#stopHeaderUpdateLoop(): void {
if (this.#headerUpdateTimer) {
clearInterval(this.#headerUpdateTimer)
this.#headerUpdateTimer = null
}
}
/**
* Check if header needs update and trigger animation if not currently animating
*/
#checkAndUpdateHeader(): void {
// If no pending text or currently animating, skip
if (!this.#pendingHeaderText || this.#isAnimating) {
return
}
// If text is already displayed, clear pending and skip
if (this.#statusText.textContent === this.#pendingHeaderText) {
this.#pendingHeaderText = null
return
}
// Start animation
const textToShow = this.#pendingHeaderText
this.#pendingHeaderText = null
this.#animateTextChange(textToShow)
}
/**
* Animate text change with fade out/in effect
*/
#animateTextChange(newText: string): void {
this.#isAnimating = true
// Fade out current text
this.#statusText.classList.add(styles.fadeOut)
setTimeout(() => {
// Update text content
this.#statusText.textContent = newText
// Fade in new text
this.#statusText.classList.remove(styles.fadeOut)
this.#statusText.classList.add(styles.fadeIn)
setTimeout(() => { setTimeout(() => {
// Update text content this.#statusText.classList.remove(styles.fadeIn)
this.#statusText.textContent = newText this.#isAnimating = false
}, 300)
// Fade in new text }, 150) // Half the duration of fade out animation
this.#statusText.classList.remove(styles.fadeOut)
this.#statusText.classList.add(styles.fadeIn)
setTimeout(() => {
this.#statusText.classList.remove(styles.fadeIn)
resolve()
}, 300)
}, 150) // Half the duration of fade out animation
})
} }
#updateStatusIndicator(type: Step['type']): void { #updateStatusIndicator(type: Step['type']): void {