How Meetily's Notification System Respects User Preferences Across macOS, Windows, and Linux

Meetily uses a cross-platform notification layer built on Tauri's notification plugin that checks user consent, Do-Not-Disturb status, and notification priority before displaying any system toast, ensuring native OS behavior is combined with consistent preference enforcement.

Meetily's open-source meeting assistant takes a careful approach to notifications. According to the Zackriya-Solutions/meetily source code, the app implements a three-layer architecture that separates data modeling, system delivery, and user-controlled settings to guarantee preferences are honored identically across all supported operating systems.

Architecture Overview: Three Concerns, One Goal

The notification system in frontend/src-tauri/src/notifications/ cleanly separates responsibilities:

Concern Primary File Purpose
Data model types.rs Defines notification types, priorities, and timeouts
System delivery system.rs Wraps Tauri's NotificationExt with DND checks
User preferences settings.rs Persists consent and DND state per-platform

This separation ensures that Meetily respects user preferences by validating them at multiple checkpoints before any native notification appears.

Notification Data Model with Priority Levels

In frontend/src-tauri/src/notifications/types.rs, Meetily defines a discriminated priority system:

  • Critical – Always shown, even during DND
  • High – Shown unless DND is active
  • Normal – Shown unless DND is active
  • Low – Often suppressed by DND or batching

The Notification struct carries a NotificationPriority field and an optional NotificationTimeout. This lets the app tag time-sensitive alerts (like meeting starts) differently from background status updates.

// Creating a high-priority meeting reminder
let reminder = Notification::meeting_reminder(5, Some("Team Sync".into()));

Critical notifications bypass all suppression logic. Lower priorities are evaluated against the current system and user state.

System-Level Delivery with Do-Not-Disturb Awareness

The SystemNotificationHandler in frontend/src-tauri/src/notifications/system.rs performs the actual platform integration. Before calling Tauri's builder().title().body().show(), it runs two checks:

  1. is_dnd_active() – Queries whether Do-Not-Disturb mode is currently enabled
  2. should_respect_dnd(priority) – Determines if this notification's priority requires DND obedience
// Simplified flow inside SystemNotificationHandler::show_notification
if self.is_dnd_active() && self.should_respect_dnd(notification.priority) {
    log::debug!("Notification suppressed due to DND");
    return Ok(()); // Early return — user sees nothing
}
// Proceed to native notification via Tauri

Because Tauri's notification plugin renders native toasts—Notification Center on macOS, Action Center on Windows, and FreeDesktop notifications on Linux—the visual appearance follows each OS convention while the pre-display filtering remains under Meetily's unified control.

Persistent User Preferences Per Operating System

User settings live in frontend/src-tauri/src/notifications/settings.rs, implemented through NotificationSettings and NotificationPreferences structs. The ConsentManager handles persistence using the dirs crate to locate OS-appropriate config directories:

OS Config Path
macOS ~/Library/Application Support/Meetily/notifications.json
Windows %APPDATA%\Meetily\notifications.json
Linux $HOME/.config/meetily/notifications.json

The settings file tracks four key flags:

  • consent_given – Explicit user opt-in to notifications
  • system_permission_granted – OS-level permission recorded
  • manual_dnd_mode – User-enabled Do-Not-Disturb
  • respect_do_not_disturb – Whether to honor system DND state

The ConsentManager::should_show_notifications() method returns true only when all conditions align:

pub fn should_show_notifications(&self) -> bool {
    self.settings.consent_given 
        && self.settings.system_permission_granted 
        && !self.settings.manual_dnd_mode
}

Every notification path in NotificationManager calls this method before delegating to SystemNotificationHandler.

Complete Notification Flow

The typical lifecycle demonstrates how Meetily respects user preferences across operating systems:

1. First Launch Initialization

ConsentManager::initialize_on_first_launch() creates the default settings file if absent:

let settings = consent_manager.initialize_on_first_launch().await?;
log::info!("Notification consent: {}", settings.consent_given);

2. User Toggles Do-Not-Disturb

The UI binds to set_dnd_mode, which immediately persists to disk:

let _ = consent_manager.set_dnd_mode(true).await;

3. App Attempts Notification

The NotificationManager orchestrates the full permission stack:

// NotificationManager::show_notification implementation pattern
pub async fn show_notification(&self, notification: Notification) -> Result<()> {
    // Gate 1: User consent and manual DND
    if !self.consent_manager.should_show_notifications() {
        return Ok(());
    }
    
    // Gate 2: System DND and priority evaluation
    self.system_handler.show_notification(notification).await
}

Only after passing both gates does Tauri's plugin render the native OS notification.

How Cross-Platform Consistency Is Achieved

Meetily's approach to respecting user preferences works uniformly because:

  • Same code path runs on all platforms—the Rust logic is compiled for each target
  • Divergence only at presentation—Tauri abstracts the final native rendering
  • Identity-based persistence—settings live in the user's profile, tied to their OS account

The notification plugin auto-grants permissions on all platforms (logged via SystemNotificationHandler::request_permission), but Meetily still records this in system_permission_granted to maintain explicit state tracking.

Summary

  • Typed priorities in types.rs let Meetily distinguish critical alerts from optional updates
  • Dual DND checking in system.rs respects both system and user-controlled Do-Not-Disturb modes
  • OS-native config paths in settings.rs ensure preferences persist per-user, per-platform
  • Unified ConsentManager provides a single source of truth for whether any notification should display
  • Tauri abstraction guarantees native appearance without sacrificing consistent preference enforcement

Frequently Asked Questions

How does Meetily handle notification permissions on different operating systems?

Tauri's notification plugin grants permissions automatically on macOS, Windows, and Linux, so SystemNotificationHandler::request_permission primarily records this state in system_permission_granted. Meetily treats this as a prerequisite rather than a runtime check, ensuring the app knows whether the OS layer is available before attempting delivery.

Can users completely disable Meetily notifications?

Yes. Setting consent_given to false or enabling manual_dnd_mode in the settings file (or via the UI that calls set_dnd_mode) causes ConsentManager::should_show_notifications() to return false. All notification paths check this method first, so no native toasts will appear regardless of priority or system DND state.

Where does Meetily store notification settings on macOS versus Linux?

On macOS, settings live at ~/Library/Application Support/Meetily/notifications.json. On Linux, the path resolves to $HOME/.config/meetily/notifications.json. Both use the dirs::config_dir() crate function with platform-specific suffixes, ensuring XDG compliance on Linux and standard macOS application support directories.

What happens to notifications when Do-Not-Disturb is active?

Non-critical notifications are suppressed entirely—SystemNotificationHandler::show_notification returns early without calling Tauri's display methods. Critical-priority notifications bypass this check and display regardless of DND state. The user can also enable manual_dnd_mode to suppress even critical notifications at the consent layer.

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 →