Skip to content

UI: fix pause in task audio playing (with glm-5.1 model help)#2893

Merged
lifeart merged 5 commits intomasterfrom
fix-audio-pause
May 6, 2026
Merged

UI: fix pause in task audio playing (with glm-5.1 model help)#2893
lifeart merged 5 commits intomasterfrom
fix-audio-pause

Conversation

@ElenaSpb
Copy link
Copy Markdown
Contributor

@ElenaSpb ElenaSpb commented May 4, 2026

##GithubTaskNumber

Исправлено: аудио останавливается после ~5 воспроизведений из-за idle-таймера

Корневая причина

Библиотека idle-js (конфиг idleTimeout: 10000 = 10 сек) определяла «бездействие» пользователя (нет движений мыши) и ставила упражнение на паузу через studyingTimer.pause(). Это вызывало audio.stop(), и упражнение зависало до следующего движения мыши.

Изменённые файлы (4 файла)

1. frontend/app/services/studying-timer.ts — добавлен метод resetIdle():

  • Снимает isPaused, если таймер на паузе
  • Перезапускает idle-watcher (stop + start) для сброса внутреннего таймера

2. frontend/app/services/audio.ts — инжекция studying-timer + вызов resetIdle():

  • Добавлен @service('studying-timer') studyingTimer
  • В startPlayTask() вызывается this.studyingTimer.resetIdle() перед воспроизведением

3. frontend/app/components/task-player/index.gts — защита аудио от idle-прерывания:

  • onPauseStateChanged(): теперь НЕ останавливает аудио, если оно сейчас играет (!this.audio.isPlaying)
  • listenModeTask: добавлен this.studyingTimer.resetIdle() перед каждым воспроизведением слова
  • interactModeTask: добавлен this.studyingTimer.resetIdle() перед воспроизведением

4. frontend/tests/unit/components/task-player/component-test.js — обновлены тесты:

  • Добавлен параметр isPlaying в мок createComponent
  • Обновлена логика onPauseStateChanged в тестах
  • Добавлен новый тест: «does not stop audio when isPaused is true but audio is playing»

Как это работает теперь

  1. Перед каждым воспроизведением аудио → idle-таймер сбрасывается (ещё 10 сек до следующего idle)
  2. Если idle всё же сработал во время воспроизведения → аудио НЕ останавливается (защита по isPlaying)
  3. Упражнение продолжает работать без необходимости двигать мышью

@ElenaSpb ElenaSpb requested a review from lifeart as a code owner May 4, 2026 12:33
@ElenaSpb ElenaSpb changed the title fix pause in task audio playing UI: fix pause in task audio playing (with glm-5.1 model help) May 4, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Frontend test coverage: 72.32% (-0.13% compared to 72.45% on base)

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Frontend test coverage: 72.31% (-0.14% compared to 72.45% on base)

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Gradle Unit and Integration Test Results

0 tests   - 523   0 ✔️  - 521   0s ⏱️ -38s
0 suites  - 116   0 💤  -     2 
0 files    - 116   0 ±    0 

Results for commit 96363f0. ± Comparison against base commit 92b150e.

♻️ This comment has been updated with latest results.

Copy link
Copy Markdown
Collaborator

@lifeart lifeart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few concerns with the approach:

Fix the root cause in onIdle, not at every call site. The simpler fix is in studying-timer.ts:

onIdle() {
  if (player.audio?.isPlaying) return;
  player.pause();
}

That removes the need for resetIdle(), the three scattered call sites in task-player, and the guard in onPauseStateChanged. Every new audio site won't have to remember to call resetIdle().

Silent catch in resetIdle(). idle-js is pinned to a specific version, so the "may not support stop/start cycle" justification doesn't hold. Drop the try/catch or at least console.error(_e).

onPauseStateChanged change breaks user-initiated pause. studyingTimer.isPaused is shared between idle-pause and user-clicked-pause. With && !this.audio.isPlaying, clicking the pause button while audio is playing no longer stops audio. If the root-cause fix above is applied, this guard goes away and user-pause keeps working.

resetIdle() is misnamed. It also force-resumes a paused timer and calls relaunchStartedTimer(). The name suggests a passive idle-watcher refresh. Either split or rename (e.g. keepActive()).

Redundant calls. audio.startPlayTask() calls resetIdle(), and the component calls it again before setAudioElements/playAudio in listen/interact modes. Pick one layer.

Tests:

  • The new unit test reimplements the component logic inline ("Reproduce the logic from TaskPlayerComponent") — it passes whether or not the real component matches. Not a regression guard.
  • resetIdle() itself is untested.
  • No test for the actual reported scenario: 5+ playbacks without mouse movement. Without it this can silently regress.

Minor:

  • audio.ts:37 — use import type for StudyingTimerService.
  • index.gts:295 — restored blank line is unnecessary diff churn.
  • Comments on the new calls describe what, not why. Drop or shorten.

@lifeart
Copy link
Copy Markdown
Collaborator

lifeart commented May 4, 2026

Two corrections to my earlier review:

  1. idle-js version — it's "^1.2.0" (caret), not strictly pinned. The try/catch is still bad style (silent, no console.error) but my framing was off — the comment isn't strictly false, just over-defensive.

  2. resetIdle() calls are not redundant. listenModeTask and interactModeTask call audio.setAudioElements() + audio.playAudio() directly, bypassing startPlayTask(). So the resetIdle() in audio.ts:130 doesn't cover those paths — the component-level calls are doing real work. Disregard the "pick one layer" point.

The other points stand: user-pause UX regression (timer/index.gts:142 wires togglePause to a button), silent catch, misnamed resetIdle, test reimplements logic, no regression test, root-cause fix in onIdle is cleaner.

lifeart and others added 2 commits May 5, 2026 19:00
Move the audio-vs-idle reconciliation into studying-timer's onIdle
handler instead of resetting the idle watcher around every playback.
StudyingTimer now skips pause via maybeIdlePause() when audio is
playing, so user-initiated pause still stops audio immediately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

Frontend test coverage: 72.49% (+0.09% compared to 72.4% on base)

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

Frontend test coverage: 72.42% (+1.16% compared to 71.26% on base)

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 5, 2026

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

Frontend test coverage: 71.26% (-1.21% compared to 72.47% on base)

@lifeart lifeart merged commit 6322d5a into master May 6, 2026
6 of 8 checks passed
@lifeart lifeart deleted the fix-audio-pause branch May 6, 2026 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants