Meetily Notification System Architecture and DND Handling: A Technical Deep Dive

Meetily implements a three-layer Rust notification stack that filters alerts through a centralized manager, supports both manual and OS-respecting Do-Not-Disturb modes, and guarantees critical notifications bypass any suppression.

Meetily's desktop application uses Tauri to deliver native cross-platform notifications while maintaining strict user privacy controls. The notification architecture separates concerns across distinct layers to handle consent management, preference persistence, and Do-Not-Disturb (DND) logic. This analysis examines the source code in the Zackriya-Solutions/meetily repository to explain how the system processes notification requests while respecting user DND preferences stored in ~/.config/meetily/notifications.json.

Three-Layer Notification Architecture

The notification system splits responsibilities across three Rust modules, each handling specific aspects of notification delivery and preference management.

System Layer (SystemNotificationHandler)

The SystemNotificationHandler in frontend/src-tauri/src/notifications/system.rs provides the lowest-level interface to the operating system's notification APIs. This layer wraps Tauri's notification plugin and handles the actual display and clearing of native OS notifications.

The handler checks DND status before showing any notification and provides a hook for critical alerts to bypass suppression:

pub async fn show_notification(&self, notification: Notification) -> Result<()> {
    // Respect DND if it is active
    if self.is_dnd_active().await && self.should_respect_dnd(&notification) {
        log_info!("DND is active, skipping notification: {}", notification.title);
        return Ok(());
    }

    let builder = self.app_handle.notification().builder()
        .title(&notification.title)
        .body(&notification.body);
    builder.show()?;
    Ok(())
}

Currently, is_dnd_active() in this layer returns false because Meetily manages DND internally rather than querying the OS, though the structure supports future OS-level integration.

Manager Layer (NotificationManager)

The NotificationManager in frontend/src-tauri/src/notifications/manager.rs serves as the central decision engine. It holds shared references to the system handler, consent manager, and in-memory settings, coordinating whether a notification should be displayed based on user preferences and DND status.

The manager initializes by loading settings from disk and requesting system permissions if needed:

pub async fn show_notification(&self, notification: Notification) -> Result<()> {
    // Ensure the manager is initialized
    if !*self.initialized.read().await { self.initialize().await?; }

    // Decide if the notification should be shown
    if !self.should_show_notification(&notification).await {
        log_info!("Skipping notification due to settings");
        return Ok(());
    }

    // Forward to the system layer
    self.system_handler.show_notification(notification).await
}

The NotificationSettings and ConsentManager in frontend/src-tauri/src/notifications/settings.rs handle persistence. User preferences serialize to a JSON file at ~/.config/meetily/notifications.json using the dirs::config_dir crate.

The settings structure captures granular notification preferences:

pub struct NotificationSettings {
    pub recording_notifications: bool,
    pub time_based_reminders: bool,
    pub meeting_reminders: bool,
    pub respect_do_not_disturb: bool,
    pub notification_sound: bool,
    pub system_permission_granted: bool,
    pub consent_given: bool,
    pub manual_dnd_mode: bool,
    pub notification_preferences: NotificationPreferences,
}

How DND Preference Handling Works

Meetily supports two DND modes: a manual toggle controlled within the UI and an optional integration with OS-level DND settings.

Manual DND Mode

When users enable Do-Not-Disturb through the Meetily interface, the application sets the manual_dnd_mode flag to true. The set_manual_dnd method in NotificationManager updates both the in-memory state and the persistent JSON configuration:

pub async fn set_manual_dnd(&self, enabled: bool) -> Result<()> {
    self.consent_manager.set_dnd_mode(enabled).await?;
    let mut settings = self.settings.write().await;
    settings.manual_dnd_mode = enabled;
    log_info!("Manual DND mode set to: {}", enabled);
    Ok(())
}

Once enabled, the is_dnd_active method returns true immediately, causing all non-critical notifications to be suppressed until the user disables the mode.

OS DND Integration

The respect_do_not_disturb boolean flag in NotificationSettings determines whether Meetily queries the operating system's DND status. Currently, the system layer returns false for OS DND checks, but the architecture accommodates future expansion:

pub async fn is_dnd_active(&self) -> bool {
    let settings = self.settings.read().await;
    if settings.manual_dnd_mode { return true; }
    if settings.respect_do_not_disturb {
        self.system_handler.is_dnd_active().await
    } else { false }
}

Critical Notification Bypass

Critical notifications related to system errors or data loss bypass DND restrictions regardless of settings. The should_respect_dnd method returns false for any notification with NotificationPriority::Critical, ensuring urgent alerts always reach the user.

End-to-End Notification Flow

When a recording starts, the notification system processes the alert through this sequence:

  1. The UI invokes NotificationManager::show_recording_started, which checks notification_preferences.show_recording_started
  2. If enabled, the manager constructs a Notification struct and calls show_notification
  3. should_show_notification verifies user consent, system permissions, and calls is_dnd_active
  4. If manual_dnd_mode is true and the notification is Normal priority, the method returns false and drops the alert silently
  5. If the notification were Critical, should_respect_dnd would return false, allowing immediate display via the system layer

Working with the Notification API

Use these patterns to interact with Meetily's notification system from your Rust code or Tauri commands:

// Initialize the manager once at application startup
let notif_manager = NotificationManager::new(app_handle.clone()).await?;

// Request system permission (Tauri typically grants this automatically)
let permission_granted = notif_manager.request_permission().await?;
println!("Permission granted: {}", permission_granted);

// Enable manual DND to suppress non-critical notifications
notif_manager.set_manual_dnd(true).await?;

// Send a normal notification (suppressed if DND is active)
let note = Notification::new(
    "Meeting Ready".into(),
    "Your recording will start shortly".into(),
    NotificationPriority::Normal,
    NotificationType::RecordingStarted,
);
notif_manager.show_notification(note).await?;

// Send a critical notification (always displays, bypassing DND)
let urgent = Notification::new(
    "⚠️ Battery Low".into(),
    "Plug in your device to avoid data loss".into(),
    NotificationPriority::Critical,
    NotificationType::SystemError("Battery".into()),
);
notif_manager.show_notification(urgent).await?;

Summary

  • Three-layer architecture: System layer handles OS APIs, Manager layer coordinates decisions, and Settings layer persists user preferences to ~/.config/meetily/notifications.json
  • Dual DND support: Manual DND mode provides immediate user control, while respect_do_not_disturb flag prepares for future OS integration
  • Critical bypass: Notifications with Critical priority bypass all DND checks via should_respect_dnd logic
  • Granular preferences: Per-type toggles in NotificationPreferences allow fine-grained control over recording alerts, reminders, and meeting notifications
  • Tauri integration: The system leverages Tauri's notification plugin while adding a Rust-based filtering layer for privacy and customization

Frequently Asked Questions

Where does Meetily store notification and DND preferences?

Meetily persists notification settings in a JSON file located at ~/.config/meetily/notifications.json on Linux, with equivalent paths for macOS and Windows using the dirs::config_dir standard. The ConsentManager in frontend/src-tauri/src/notifications/settings.rs handles serialization and deserialization of the NotificationSettings struct, including the manual_dnd_mode and respect_do_not_disturb flags.

How does Meetily ensure critical alerts appear during Do-Not-Disturb mode?

The system checks notification priority before applying DND filters. In SystemNotificationHandler::show_notification, the code calls should_respect_dnd(&notification), which returns false for any notification carrying NotificationPriority::Critical. This allows battery warnings, system errors, and other urgent alerts to bypass both manual DND mode and OS DND settings, ensuring users receive critical information regardless of their current preference settings.

Can Meetily respect the operating system's native Do-Not-Disturb settings?

The architecture supports OS DND integration through the respect_do_not_disturb boolean flag in NotificationSettings. When enabled, NotificationManager::is_dnd_active delegates to SystemNotificationHandler::is_dnd_active. However, the current implementation in frontend/src-tauri/src/notifications/system.rs returns false for OS DND queries because Meetily manages DND internally. The flag exists to enable future cross-platform OS DND detection without requiring breaking changes to the API.

What happens when a user toggles DND mode in the Meetily interface?

When users activate DND through the UI, the application calls NotificationManager::set_manual_dnd(true). This method immediately updates the manual_dnd_mode field in the in-memory NotificationSettings struct and persists the change to disk via ConsentManager::set_dnd_mode. Subsequent notification requests check this flag in is_dnd_active, causing all non-critical notifications to be logged and dropped silently until the user disables the mode.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →