Skip to content

feat: add MicProlongedUsage detection event#3681

Merged
yujonglee merged 10 commits intomainfrom
devin/1770345923-mic-active-without-hyprnote
Feb 6, 2026
Merged

feat: add MicProlongedUsage detection event#3681
yujonglee merged 10 commits intomainfrom
devin/1770345923-mic-active-without-hyprnote

Conversation

@devin-ai-integration
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot commented Feb 6, 2026

feat: add MicProlongedUsage detection event

Summary

Adds a new DetectEvent::MicProlongedUsage variant that fires when an app has been using the mic for 3 minutes continuously. The frontend then decides whether to show a notification based on the current listener state and user settings. This enables prompting users to start recording when they appear to be in a meeting.

How it works:

Rust (detect plugin):

  • When MicStarted is received for an app (that passes policy + cooldown filtering), a per-app timer is spawned with a 3-minute threshold using CancellationToken
  • When the timer fires, it acquires the std::sync::Mutex state lock, calls claim() with the generation number to atomically verify and remove the entry, then emits MicProlongedUsage
  • When MicStopped is received, the timer's CancellationToken is cancelled and the entry removed
  • A 1-hour cooldown per app prevents repeated notifications for the same app. Expired cooldown entries are lazily cleaned up in is_in_cooldown() to prevent unbounded map growth.
  • The tauri-plugin-listener dependency is removed from the detect plugin — the "is listening" check is intentionally moved to the consumer side (frontend)

Frontend:

  • listener.tsx handles the new micProlongedUsage event, checking both the notification_in_meeting_reminder setting and store.getState().live.status === "active" before showing a notification
  • New MeetingReminderToggle in Settings > Lab lets users enable/disable the feature (default: enabled)
  • Notification: "Zoom has been using the mic for 3 min. Start listening?"

Race condition mitigations:

  • Generation-based claiming: Each timer gets a monotonically increasing generation number. claim() only succeeds if the generation matches, preventing stale timers from emitting after a stop+restart cycle.
  • CancellationToken: tokio::select! between sleep and cancellation ensures prompt abort on MicStopped.
  • Cooldown: After a successful claim(), the app enters a 1-hour cooldown, suppressing duplicate notifications.

Key files changed:

  • plugins/detect/src/mic_usage_tracker.rsnew module: MicUsageTracker with generation-based timers, cooldowns (with lazy expiry cleanup), and comprehensive unit tests
  • plugins/detect/src/env.rsnew module: Env trait abstracting event emission + DnD checks for testability
  • plugins/detect/src/handler.rs — refactored to use Env trait; added integration-style tests
  • plugins/detect/src/events.rs — new MicProlongedUsage variant (replaces old From impl)
  • plugins/detect/src/policy.rs — removed is_listening/skip_when_listening; added should_track_app(); user_ignored_bundle_ids changed to HashSet
  • plugins/detect/src/lib.rs — split into DetectorState + ProcessorState; std::sync::Mutex instead of tokio::sync::Mutex
  • apps/desktop/src/contexts/listener.tsx — handles micProlongedUsage with listener state + setting checks
  • apps/desktop/src/components/settings/lab/index.tsx — new MeetingReminderToggle component

Review & Testing Checklist for Human

  • TS bindings consistencybindings.gen.ts was hand-edited. Regenerate via cargo test -p tauri-plugin-detect to verify it matches.
  • Listener state check timing — Frontend checks store.getState().live.status === "active" at notification time. If user starts listening between timer fire and notification display, the notification is correctly suppressed. Verify this works as expected.
  • DnD not checked for MicProlongedUsage — The timer fires regardless of DnD state (only MicStarted/MicStopped notifications respect DnD). Confirm this is intentional behavior.
  • Manual test plan:
    1. Start a mic-using app (e.g. Zoom), wait 3+ minutes without Hyprnote listening → notification should appear
    2. Stop the mic app before 3 min → no notification
    3. Start Hyprnote listening before 3 min → no notification (frontend suppresses)
    4. Stop mic app right at ~3 min → no false notification (cancellation race)
    5. Stop then immediately restart mic app → new timer starts fresh
    6. After notification fires, stop and restart mic app → no notification for 1 hour (cooldown)
    7. Toggle off "In-Meeting Reminder" in Settings > Lab → no notifications

Notes

  • Threshold is hardcoded at 3 minutes (MIC_ACTIVE_THRESHOLD). Cooldown is 1 hour (COOLDOWN_DURATION). Could be made configurable later.
  • Timers are per-app: e.g. if Zoom and Slack are both using the mic, each gets its own independent timer.
  • Comprehensive unit tests added for MicUsageTracker and integration-style tests in handler.rs.
  • Cooldown entries are lazily cleaned up when is_in_cooldown() is called (not via periodic task), which is sufficient since the map is bounded by the number of distinct apps that have triggered timers.

Link to Devin run: https://app.devin.ai/sessions/0abeb320269b434cade8e4591a698c6e
Requested by: @yujonglee

Per-app timer that fires after 3 minutes of mic usage when Hyprnote
is not actively listening. Timers are cancelled when the app stops
using the mic.

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
@netlify
Copy link

netlify bot commented Feb 6, 2026

Deploy Preview for hyprnote-storybook canceled.

Name Link
🔨 Latest commit cde5528
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote-storybook/deploys/6985aaec8b55910008d79e46

@netlify
Copy link

netlify bot commented Feb 6, 2026

Deploy Preview for hyprnote canceled.

Name Link
🔨 Latest commit cde5528
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote/deploys/6985aaec9a106200081ec82f

@devin-ai-integration
Copy link
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Copy link
Contributor Author

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

devin-ai-integration bot and others added 2 commits February 6, 2026 03:01
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Copy link
Contributor Author

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 8 additional findings in Devin Review.

Open in Devin Review

…rt race

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Copy link
Contributor Author

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 9 additional findings in Devin Review.

Open in Devin Review

devin-ai-integration bot and others added 2 commits February 6, 2026 03:48
…state

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Copy link
Contributor Author

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 10 additional findings in Devin Review.

Open in Devin Review

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
@devin-ai-integration devin-ai-integration bot changed the title feat: add MicActiveWithoutHyprnote detection event feat: add MicProlongedUsage detection event Feb 6, 2026
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
@yujonglee yujonglee merged commit c61f11f into main Feb 6, 2026
20 checks passed
@yujonglee yujonglee deleted the devin/1770345923-mic-active-without-hyprnote branch February 6, 2026 09:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant