Feature: Notifications and Sounds
Relevant source files
The following files were used as context for generating this wiki page:
The Notifications and Sounds feature provides essential user feedback for key events within the Pomodoro timer lifecycle. It uses the browser's native Web Audio API to generate simple sound effects and the Notification API for desktop alerts. This system is designed to be configurable, allowing users to enable or disable audio feedback, adjust volume, and manage notification permissions directly through the application's settings interface.
The core functionality is centralized but consumed by specific components like the Pomodoro timer. When a work or break session completes, the system triggers a sound and, if enabled, sends a desktop notification to alert the user, even if the application window is not in focus. This ensures a non-intrusive yet effective way to keep the user on track with their Pomodoro cycles.
System Architecture and Data Flow
The feature's architecture is driven by the central App component, which manages all user settings. These settings are passed down as props to the Pomodoro component, which in turn uses the useSound hook and a sendNotification function to produce feedback at the appropriate moments.
The following diagram illustrates the data and control flow from user settings to the final output.
Configuration
Users can configure notifications and sounds via the "SYSTEM CONFIG" view. These settings are defined in the Settings interface and managed within the App component's state.
| Setting | Type | Description | Default Value | Source File |
|---|---|---|---|---|
soundEnabled | boolean | Toggles all timer-related sound effects on or off. | true | src/types.ts:68 |
soundVolume | number | Sets the volume for sound effects (0.0 to 1.0). | 0.5 | src/types.ts:69 |
notificationsEnabled | boolean | Toggles desktop notifications for timer completion events. | false | src/types.ts:70 |
These settings are persisted in localStorage under the key origin_terminal_settings.
Sources: src/App.tsx:23-38, 211-215, src/types.ts:63-75, src/constants.ts:8
Sound Effects
Sound effects are generated programmatically using the Web Audio API to avoid loading external audio files. The SoundManager.tsx module provides a useSound hook for easy consumption within React components.
useSound Hook
The useSound hook takes enabled and volume as arguments and returns a memoized callback function to play a sound. This function accepts a type argument ('start', 'end', or 'tick') to play the corresponding sound effect.
Sources: src/components/SoundManager.tsx:47-53
playBeep Function
This is the core function that creates and plays a sound. It initializes an AudioContext, creates an OscillatorNode for the tone and a GainNode for volume control, and connects them to the audio output. Different sound characteristics are applied based on the type parameter.
The following diagram shows the sequence of playing a sound.
Sources: src/components/SoundManager.tsx:5-45
Sound Types
The system supports three distinct sound types for different timer events.
| Type | Frequency | Duration | Description |
|---|---|---|---|
start | 600Hz -> 1200Hz | SOUND_START_DURATION (0.3s) | An upward-ramping tone played when a timer starts. |
end | 800Hz -> 300Hz | SOUND_END_DURATION (0.5s) | A downward-ramping tone played when a timer completes. |
tick | 1000Hz | SOUND_TICK_DURATION (0.05s) | A short, high-frequency click. (Note: The tick sound is defined but not currently used by the Pomodoro component). |
Sources: src/components/SoundManager.tsx:21-44, src/constants.ts:80-82
Desktop Notifications
Desktop notifications are handled by the sendNotification function within the Pomodoro.tsx component. They are triggered upon the completion of a work or break session.
Notification Logic
When handleComplete is called in Pomodoro.tsx, it invokes sendNotification with a title and body. The sendNotification function first checks if notifications are enabled in settings and if the browser permission has been granted.
The notification is configured to require user interaction and will bring the application window into focus when clicked.
// src/components/Pomodoro.tsx:201-211
const sendNotification = (title: string, body: string) => {
if (!settingsRef.current.notificationsEnabled) return;
if ('Notification' in window && Notification.permission === 'granted') {
try {
const n = new Notification(title, {
body,
icon: '/pwa-192x192.png',
requireInteraction: true,
silent: false
});
n.onclick = () => { window.focus(); n.close(); };
} catch (e) {
console.error('Notification error:', e);
}
}
};
Notification Content
The content for the notifications is sourced from the internationalization module (i18n.ts) to support multiple languages.
| Event | Notification Title Key | Notification Body Key |
|---|---|---|
| Work cycle complete | NOTIFICATION_WORK_COMPLETE_TITLE | NOTIFICATION_WORK_COMPLETE_BODY |
| Break cycle complete | NOTIFICATION_BREAK_COMPLETE_TITLE | NOTIFICATION_BREAK_COMPLETE_BODY |
Sources: src/components/Pomodoro.tsx:214, 225, src/utils/i18n.ts:67-70, 161-164
Permission Handling
Notification permission is requested in the App.tsx component when the user checks the "DESKTOP NOTIFICATIONS" checkbox in the settings.
- The
onChangehandler for the checkbox is triggered. - It checks if the
NotificationAPI is available in the browser. - If permission is
'default', it callsNotification.requestPermission(). - The
notificationsEnabledsetting is updated totrueonly if the final permission is'granted'. - If permission is
'denied', analertis shown to the user.
The following diagram illustrates this user-driven permission request flow.
Sources: src/App.tsx:550-571