Voice audio (Bug 2):
- Guard _playAudio against duplicate Web Audio graph creation
- Prevents multiple GainNodes competing for the same stream
Talking indicator (Bug 3):
- Already fixed: 300ms hysteresis hold timer in both local and remote
talk detection (prevents flicker from micro-pauses between syllables)
Screen share (Bug 4):
- Add SDP rollback in voice-offer handler for renegotiation glare
- Guard voice-answer handler against stale answers after rollback
- Use event.streams[0] in ontrack for proper stream association
- Add track.onunmute to re-trigger screen display when data arrives
- Mute all screen share video tiles (prevents browser autoplay block)
- Explicit vid.play() call as autoplay backup
GIF search (Bug 1):
- Tenor API key can now be set from the admin GIF picker UI
- Stored in server_settings DB table (no .env editing needed)
- Server checks DB first, falls back to TENOR_API_KEY env var
- Shows step-by-step setup guide when key is missing
- Non-admins see a clear 'ask your admin' message
- GIF button next to emoji picker opens search/browse panel
- Server-side proxy keeps Tenor API key hidden from clients
- Trending GIFs shown by default, live search with debounce
- Click a GIF to send it as an inline image in chat
- Tenor URLs auto-detected and rendered as inline images
- CSP updated to allow media.tenor.com images
- TENOR_API_KEY added to .env.example (optional, free)
- Full CSS theming for GIF picker panel
- Database, .env, certs, and uploads now stored outside the code directory
- Auto-migration moves existing data from old locations on first launch
- SSL certs auto-detected in data dir (no .env config needed)
- New src/paths.js module as single source of truth for all data paths
- HAVEN_DATA_DIR env var for custom data location override
- Updated Start Haven.bat, start.sh, README, GUIDE, .env.example
- Bumped version to 1.1.0