From 2e13669655a7c3027ad1c94921ad4d2e07406c28 Mon Sep 17 00:00:00 2001 From: Avinash-yadav103 Date: Tue, 3 Feb 2026 06:54:17 +0530 Subject: [PATCH] feat: add audio notification for user joins with mute/unmute toggle --- CHANGELOG.md | 53 +++++++ CONTRIBUTORS.md | 53 +++++++ README.md | 8 + client/app.ts | 95 ++++++++++++ client/index.html | 8 + docker/Dockerfile | 4 +- docs/AUDIO_NOTIFICATION_FEATURE.md | 137 +++++++++++++++++ docs/IMPLEMENTATION_SUMMARY.md | 226 +++++++++++++++++++++++++++++ 8 files changed, 582 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTORS.md create mode 100644 docs/AUDIO_NOTIFICATION_FEATURE.md create mode 100644 docs/IMPLEMENTATION_SUMMARY.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c235c7c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,53 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added +- Audio notification feature when peer joins chat [@Avinash-yadav103](https://github.com/Avinash-yadav103) + - Pleasant beep sound using Web Audio API + - Toggle button to mute/unmute notifications + - Persistent settings using localStorage + - Fully accessible and keyboard navigable + - Mobile-friendly implementation +- Comprehensive documentation for audio notification feature +- CONTRIBUTORS.md file for proper contributor recognition +- Feature documentation in docs/AUDIO_NOTIFICATION_FEATURE.md + +### Changed +- Updated README.md with new audio notification feature +- Enhanced contributors section in README.md + +### Technical Details +- Implemented Web Audio API for client-side sound generation +- Added localStorage persistence for user preferences +- SVG icon updates for visual feedback +- No external dependencies added + +--- + +## How to Update This Changelog + +When contributing, please add your changes under the `[Unreleased]` section following this format: + +### Added +- New features + +### Changed +- Changes to existing functionality + +### Deprecated +- Soon-to-be removed features + +### Removed +- Removed features + +### Fixed +- Bug fixes + +### Security +- Security improvements diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 0000000..5f1d807 --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,53 @@ +# Contributors + +Thank you to all the amazing people who have contributed to chat-e2ee! 🎉 + +This project exists because of the contributions from developers around the world. Below is a list of contributors who have helped make this project better. + +## How to Contribute + +We welcome contributions! Please see our [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on how to contribute to this project. + +## Feature Contributors + +### Audio Notification Feature +**Feature**: Audio notification when peer joins chat with mute/unmute option +**Contributors**: +- [@Avinash-yadav103](https://github.com/Avinash-yadav103) - Implemented user join audio notifications with localStorage persistence and toggle controls (February 2026) + +## All Contributors + +This project follows the [all-contributors](https://allcontributors.org) specification. + + + + + + +
+ + +
+ Avinash Yadav +
+
+ + 💻 +
+ + +## Legend + +- ✨ Features +- 💻 Code +- 🐛 Bug fixes +- 📖 Documentation +- 🎨 Design +- 💡 Ideas & Planning +- 🚧 Maintenance +- ⚠️ Tests +- 🔧 Tools + +--- + +*Want to see your name here? Check out our [contribution guidelines](CONTRIBUTING.md) and start contributing today!* diff --git a/README.md b/README.md index 9967f12..4244352 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Demo: https://chat-e2ee-2.azurewebsites.net 1. :negative_squared_cross_mark: No login/signup - the end users **don't identify** themselves. 2. :closed_lock_with_key: End-to-end encrypted Audio-Call (Experimental - added on [19th September, 2024](https://github.com/muke1908/chat-e2ee/commit/efae545c4c378dd7cae3c133843c1d58fded8a56)). :warning: Note that Audio encryption in webrtc call is done diffrently, please refer [Wiki](https://github.com/muke1908/chat-e2ee/wiki/End%E2%80%90to%E2%80%90end-encryption-in-Webrtc-audio-call). It internally uses RTCRtpSender API: `createEncodedStreams` that has [limited Support](https://caniuse.com/mdn-api_rtcrtpsender_createencodedstreams) +3. :bell: Audio notification when a peer joins the chat - with option to mute/unmute notifications. 4. :no_entry_sign: Data is **not** stored on any remote server, encrypted data is just relayed to other users, the data can't be decrypted by any man in the middle. **No history** i.e. once chat is closed the data is not recoverable, however encrypted data can be found on memory trace. [Read More](https://github.com/muke1908/chat-e2ee/wiki/How-and-when-your-data-can-be-compromised%3F) ## :star: JS SDK @@ -112,8 +113,15 @@ Example: ## ✨ Contributors +We thank all contributors who have helped improve chat-e2ee! + +### Recent Contributors +- **[@Avinash-yadav103](https://github.com/Avinash-yadav103)** - Added audio notification feature for user joins with mute/unmute controls + +See [CONTRIBUTORS.md](CONTRIBUTORS.md) for detailed contribution history. + --- ## :closed_lock_with_key: Cryptographic notice This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See http://www.wassenaar.org/ for more information. diff --git a/client/app.ts b/client/app.ts index 92b1176..ae19771 100644 --- a/client/app.ts +++ b/client/app.ts @@ -6,6 +6,10 @@ let userId: string = ''; let channelHash: string = ''; let privateKey: string = ''; +// Audio notification settings +let audioNotificationsEnabled: boolean = true; +const AUDIO_SETTINGS_KEY = 'chat-e2ee-audio-notifications'; + // DOM Elements // DOM Elements const setupOverlay = document.getElementById('setup-overlay')!; @@ -34,6 +38,7 @@ const participantInfo = document.getElementById('participant-info')!; const headerHashDisplay = document.getElementById('channel-hash-display')!; const headerHashText = document.getElementById('header-hash')!; const copyHeaderHashBtn = document.getElementById('copy-header-hash') as HTMLButtonElement; +const audioToggleBtn = document.getElementById('audio-toggle-btn') as HTMLButtonElement; // Call Elements const callOverlay = document.getElementById('call-overlay')!; @@ -41,6 +46,71 @@ const callStatusText = document.getElementById('call-status')!; const endCallBtn = document.getElementById('end-call-btn') as HTMLButtonElement; const callDuration = document.getElementById('call-duration')!; +// Audio Notification Functions +function loadAudioSettings() { + const saved = localStorage.getItem(AUDIO_SETTINGS_KEY); + audioNotificationsEnabled = saved === null ? true : saved === 'true'; + updateAudioToggleButton(); +} + +function saveAudioSettings() { + localStorage.setItem(AUDIO_SETTINGS_KEY, audioNotificationsEnabled.toString()); +} + +function updateAudioToggleButton() { + if (audioToggleBtn) { + const icon = audioToggleBtn.querySelector('svg'); + if (audioNotificationsEnabled) { + audioToggleBtn.title = 'Mute join notifications'; + if (icon) { + icon.innerHTML = ``; + } + } else { + audioToggleBtn.title = 'Unmute join notifications'; + if (icon) { + icon.innerHTML = ``; + } + } + } +} + +function playJoinBeep() { + if (!audioNotificationsEnabled) return; + + try { + // Create AudioContext + const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)(); + + // Create oscillator for beep sound + const oscillator = audioContext.createOscillator(); + const gainNode = audioContext.createGain(); + + // Configure beep: pleasant notification sound + oscillator.type = 'sine'; + oscillator.frequency.setValueAtTime(800, audioContext.currentTime); // 800Hz + + // Envelope for smooth sound + gainNode.gain.setValueAtTime(0, audioContext.currentTime); + gainNode.gain.linearRampToValueAtTime(0.15, audioContext.currentTime + 0.02); + gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.2); + + // Connect nodes + oscillator.connect(gainNode); + gainNode.connect(audioContext.destination); + + // Play beep + oscillator.start(audioContext.currentTime); + oscillator.stop(audioContext.currentTime + 0.2); + + // Cleanup + oscillator.onended = () => { + audioContext.close(); + }; + } catch (err) { + console.error('Audio notification error:', err); + } +} + // Initialize Chat async function initChat() { try { @@ -52,6 +122,9 @@ async function initChat() { privateKey = keys.privateKey; setupStatus.textContent = ''; + // Load audio settings + loadAudioSettings(); + // Check for URL hash on load handleUrlHash(); } catch (err) { @@ -183,6 +256,7 @@ function setupChatListeners() { chat.on('on-alice-join', () => { chatHeader.classList.add('active'); participantInfo.textContent = 'Peer joined. Communication is encrypted.'; + playJoinBeep(); // Play notification sound }); chat.on('on-alice-disconnect', () => { @@ -299,5 +373,26 @@ function hideCallOverlay() { callOverlay.classList.add('hidden'); } +// Audio Toggle Button Handler +if (audioToggleBtn) { + audioToggleBtn.addEventListener('click', () => { + audioNotificationsEnabled = !audioNotificationsEnabled; + saveAudioSettings(); + updateAudioToggleButton(); + + // Show feedback + const originalText = participantInfo.textContent; + participantInfo.textContent = audioNotificationsEnabled + ? 'Join notifications enabled' + : 'Join notifications muted'; + setTimeout(() => { + if (participantInfo.textContent === 'Join notifications enabled' || + participantInfo.textContent === 'Join notifications muted') { + participantInfo.textContent = originalText || 'Waiting for someone to join...'; + } + }, 2000); + }); +} + // Start initChat(); diff --git a/client/index.html b/client/index.html index 191ff71..059d050 100644 --- a/client/index.html +++ b/client/index.html @@ -80,6 +80,14 @@

Secure Channel

Waiting for someone to join...

+