feat: add sound system (LS.sfx) — synthesized Web Audio API sounds for classroom, gamification, quiz

- New js/sound.js: shared LS.sfx module with 21 synthesized sounds (ADSR envelope, sequences, sweeps, noise)
- Classroom: lesson_start/end, user_joined/left, hand_raise, chat_message, muted, draw_permitted
- Dashboard: achievement, level_up, xp_gain, coin via SSE events
- Live quiz: quiz_start, quiz_end on question launch and results
- Settings panel: global enable toggle + volume slider + localStorage persistence
- Replaces old _crBeep() in classroom.html

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-04-14 19:43:13 +03:00
parent d2bf3aba47
commit 29aa985504
4 changed files with 391 additions and 17 deletions
+3
View File
@@ -449,6 +449,7 @@
</div>
<script src="/js/api.js"></script>
<script src="/js/sound.js"></script>
<script src="/js/sidebar.js"></script>
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"></script>
@@ -795,6 +796,7 @@
updateStudentCounter(0);
renderActiveQuestion(currentQuestion);
renderQuestionList();
if (window.LS && LS.sfx) LS.sfx.play('quiz_start');
} catch (e) {
LS.toast(e.message || 'Ошибка запуска вопроса', 'error');
}
@@ -860,6 +862,7 @@
try {
const data = await LS.api('/api/live/' + activeSession.id + '/results');
renderResults(data, resultsArea);
if (window.LS && LS.sfx) LS.sfx.play('quiz_end');
} catch (e) {
resultsArea.innerHTML = `<div style="padding:20px;text-align:center;color:#8898AA;font-size:0.84rem">${esc(e.message || 'Ошибка загрузки результатов')}</div>`;
}