Commit Graph

2 Commits

Author SHA1 Message Date
Maxim Dolgolyov c0f20ef020 fix: classroom review — 11 исправлений из code review
- sessions.js: endSession закрывает classroom_attendance (left_at), чистит classroom_muted
- sessions.js: joinSession восстанавливает mute-состояние при реконнекте
- strokes.js: updateStroke проверяет авторство штриха (не только canDraw)
- strokes.js: clearPage валидирует page_num как положительное целое
- strokes.js: postStrokes ограничивает массив 500 штрихами
- pages.js: duplicatePage сохраняет user_id при копировании штрихов
- pages.js: changePage валидирует page_num
- pages.js: updatePageTemplate делает INSERT OR IGNORE перед UPDATE
- permissions.js: mutePeer сохраняет в classroom_muted; добавлен unmutePeer
- permissions.js: getOnlineStudents не возвращает email
- chat.js: exportChat экранирует переводы строк в именах и сообщениях
- guestClassroom.js: санитизация имени гостя (убираем HTML-символы)
- ws-server.js: mute_peer сохраняет в БД; добавлен обработчик unmute_peer
- routes/classroom.js: rate-limit для cursor/preview/signal/strokes; маршрут DELETE /mute
- migrations/001_classroom_muted.sql: новая таблица classroom_muted
2026-05-07 14:26:19 +03:00
Maxim Dolgolyov fd29acbbdd feat: WebSocket real-time + rAF render gate + guest board + screen picker
Classroom performance:
- WebSocket server (ws-server.js) for low-latency cursor & stroke preview
  Replaces HTTP POST per event → eliminates per-message auth overhead
  Session member cache (30s TTL) avoids SQLite query per WS message
  Fallback to HTTP POST when WS not connected
- Cursor throttle reduced 100ms → 33ms (~30fps)
- Stroke preview throttle reduced 50ms → 20ms
- whiteboard.js: render() is now rAF-gated (_doRender/_rafPending)
  Multiple render() calls within one frame collapse into one repaint
  document.hidden check — zero CPU when tab is in background
  visibilitychange listener restores canvas on tab focus

Guest board:
- guestClassroom.js route: public token-based read-only access
- guest-board.html: name entry + read-only whiteboard + SSE
- SSE: addGuestClient/removeGuestClient/emitToGuests

Screen share picker:
- Discord-style modal with tab switching (screen/window/tab)
- Live video preview before confirming share
- useExistingScreenStream() in ClassroomRTC

Fullscreen exit overlay:
- #cr-fs-exit-overlay button inside cr-board-wrap
- Visible only via CSS :fullscreen selector (touchpad users)

File sharing from library:
- Teacher picks file from library, sends as styled card in chat
- crDownloadLibraryFile() fetches with Bearer auth

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 18:04:59 +03:00