Skip to content

Add option to show fullscreen notifications on all screens#907

Open
JonathanGuberman wants to merge 1 commit intoleits:masterfrom
JonathanGuberman:JonathanGuberman/fullscreen-notif-docs
Open

Add option to show fullscreen notifications on all screens#907
JonathanGuberman wants to merge 1 commit intoleits:masterfrom
JonathanGuberman:JonathanGuberman/fullscreen-notif-docs

Conversation

@JonathanGuberman
Copy link
Copy Markdown

@JonathanGuberman JonathanGuberman commented Mar 24, 2026

Summary

  • Adds a new "Show on all screens" toggle under the fullscreen notification setting in Preferences → General → Event Notifications
  • When enabled, creates a notification window on every connected display instead of just the main screen
  • Dismissing or joining from any screen closes all notification windows simultaneously
  • Includes localized strings for all 22 supported languages and unit tests for the new setting

Test plan

  • Enable fullscreen notifications and the new "Show on all screens" toggle
  • Create a calendar event with a meeting link (Zoom, Google Meet, etc.) starting within the configured notification window
  • Verify notification appears on all connected displays
  • Click Close or Join on any screen — verify all windows dismiss together
  • Disable "Show on all screens" and verify notification only appears on the main screen
  • Verify the toggle is disabled when fullscreen notifications are turned off

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added an option to display fullscreen notifications on all connected screens instead of just the primary screen.
  • Localization

    • Added full multi-language support for the new multi-screen notification feature across 20+ languages, including English, German, French, Spanish, Chinese, Japanese, Korean, and others.

Users with multiple displays only see the fullscreen meeting notification
on their main screen, making it easy to miss. This adds a toggleable
"Show on all screens" setting that creates a notification window on every
connected display with synchronized dismissal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Mar 24, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 24, 2026

Walkthrough

The PR adds multi-screen support for fullscreen notifications. When the new fullscreenNotificationAllScreens preference is enabled, notifications display on all attached screens instead of just the primary screen. Changes include preference storage, multi-window handling, UI toggle, and localization across 19 languages.

Changes

Cohort / File(s) Summary
Core logic
MeetingBar/App/AppDelegate.swift, MeetingBar/UI/Views/FullscreenNotification.swift
Modified notification window creation to support multiple screens. AppDelegate now creates one window per selected screen (all or main based on preference) and passes windows array to FullscreenNotification. Changed from single optional window property to non-optional windows array.
Preferences and UI
MeetingBar/Extensions/DefaultsKeys.swift, MeetingBar/UI/Views/Shared.swift
Added new boolean preference fullscreenNotificationAllScreens (default: false) and corresponding UI toggle in FullscreenNotificationPicker with conditional enabling based on main fullscreen notification toggle.
Localization
MeetingBar/Resources/Localization/*.lproj/Localizable.strings
Added shared_fullscreen_notification_all_screens_toggle string key across 19 language files (English, German, Spanish, French, Czech, Croatian, Hungarian, Italian, Japanese, Korean, Norwegian, Dutch, Polish, Portuguese, Slovak, Tamil, Turkish, Ukrainian, Simplified Chinese).
Tests
MeetingBarTests/FullscreenNotificationTests.swift
New test file validating that the fullscreenNotificationAllScreens preference defaults to false, can be toggled to true, and persists independently of the main fullscreen notification toggle.

Sequence Diagram

sequenceDiagram
    participant AppDelegate
    participant Defaults
    participant NSScreen
    participant NSWindow
    participant FullscreenNotification

    AppDelegate->>Defaults: Check fullscreenNotificationAllScreens
    Defaults-->>AppDelegate: Setting value

    alt Setting enabled
        AppDelegate->>NSScreen: Get NSScreen.screens
    else Setting disabled
        AppDelegate->>NSScreen: Get NSScreen.main
    end
    NSScreen-->>AppDelegate: Selected screens list

    loop For each screen
        AppDelegate->>NSWindow: Create new NSWindow
        AppDelegate->>NSWindow: Configure (appearance, collectionBehavior, etc.)
        AppDelegate->>FullscreenNotification: Initialize with event and windows array
        AppDelegate->>NSWindow: Order front and show
    end

    FullscreenNotification-->>AppDelegate: Notification UI displayed
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Suggested labels

lgtm

Suggested reviewers

  • leits
  • mskopp

Poem

🐰 Multi-screen magic, a hop and a bound,
Notifications now dancing all screens around,
Windows align in harmonious cheer,
Every display sees the meeting appear! 📺✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding a new option to display fullscreen notifications on all screens instead of just the main screen. This is the core objective reflected throughout the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dosubot dosubot Bot added the feature New feature or request label Mar 24, 2026

class FullscreenNotificationTests: BaseTestCase {

func test_fullscreenNotificationAllScreens_defaultsToFalse() {

Check warning

Code scanning / Tailor (reported by Codacy)

Function names should be lowerCamelCase Warning

Function names should be lowerCamelCase
XCTAssertFalse(Defaults[.fullscreenNotificationAllScreens])
}

func test_fullscreenNotificationAllScreens_canBeEnabled() {

Check warning

Code scanning / Tailor (reported by Codacy)

Function names should be lowerCamelCase Warning

Function names should be lowerCamelCase
XCTAssertTrue(Defaults[.fullscreenNotificationAllScreens])
}

func test_fullscreenNotificationAllScreens_independentOfMainToggle() {

Check warning

Code scanning / Tailor (reported by Codacy)

Function names should be lowerCamelCase Warning

Function names should be lowerCamelCase

XCTAssertFalse(Defaults[.fullscreenNotification])
XCTAssertTrue(Defaults[.fullscreenNotificationAllScreens])
}

Check warning

Code scanning / Tailor (reported by Codacy)

Function should have at least one blank line after it Warning

Function should have at least one blank line after it
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 24, 2026

Codecov Report

❌ Patch coverage is 23.25581% with 33 lines in your changes missing coverage. Please review.
✅ Project coverage is 36.49%. Comparing base (84e0a9f) to head (477279b).
⚠️ Report is 15 commits behind head on master.

Files with missing lines Patch % Lines
MeetingBar/App/AppDelegate.swift 0.00% 28 Missing ⚠️
MeetingBar/UI/Views/Shared.swift 0.00% 3 Missing ⚠️
MeetingBar/UI/Views/FullscreenNotification.swift 0.00% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           master     #907       +/-   ##
===========================================
+ Coverage   26.30%   36.49%   +10.19%     
===========================================
  Files          36       49       +13     
  Lines        5645     5121      -524     
  Branches     2210     1740      -470     
===========================================
+ Hits         1485     1869      +384     
+ Misses       4103     3196      -907     
+ Partials       57       56        -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@MeetingBar/App/AppDelegate.swift`:
- Around line 260-261: The second assignment to window.collectionBehavior
overwrites the first, dropping .canJoinAllSpaces; change the code that sets
window.collectionBehavior (in AppDelegate.swift where window.collectionBehavior
is assigned) to combine the options instead of replacing them—use the OptionSet
union (e.g., set both flags together or call insert on
window.collectionBehavior) so the window keeps both .canJoinAllSpaces and
.moveToActiveSpace.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0352fd25-4093-4fc6-85c6-61d09fc7cd27

📥 Commits

Reviewing files that changed from the base of the PR and between 48373d7 and 477279b.

📒 Files selected for processing (26)
  • MeetingBar/App/AppDelegate.swift
  • MeetingBar/Extensions/DefaultsKeys.swift
  • MeetingBar/Resources /Localization /cs.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /de.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /en.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /es.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /fr.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /he.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /hr.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /hu.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /it.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /ja.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /ko.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /nb-NO.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /nl.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /pl.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /pt-BR.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /pt.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /sk.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /ta.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /tr.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /uk.lproj/Localizable.strings
  • MeetingBar/Resources /Localization /zh-Hans.lproj/Localizable.strings
  • MeetingBar/UI/Views/FullscreenNotification.swift
  • MeetingBar/UI/Views/Shared.swift
  • MeetingBarTests/FullscreenNotificationTests.swift

Comment on lines +260 to +261
window.collectionBehavior = .canJoinAllSpaces
window.collectionBehavior = .moveToActiveSpace
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In AppKit, is NSWindow.collectionBehavioranOptionSet, and does assigning it twice replace previously set flags? What is the correct way to combine .canJoinAllSpacesand.moveToActiveSpace?

💡 Result:

Yes, NSWindow.collectionBehavior is an NSWindow.CollectionBehavior type, which is a Swift OptionSet (struct with OptionSet conformance, supporting bitwise operations). Assigning it multiple times replaces the previous value entirely, as it is a simple property setter (var collectionBehavior: NSWindow.CollectionBehavior { get set }). The correct way to combine .canJoinAllSpaces and .moveToActiveSpace is to use the bitwise OR operator: window.collectionBehavior = [.canJoinAllSpaces, .moveToActiveSpace]. This creates a single value with both flags set. Note that some behaviors are mutually exclusive (e.g., within Spaces group), but .canJoinAllSpaces and .moveToActiveSpace can be combined as they are distinct options, though their effects may interact (window appears in all spaces but moves when activated). Example: window.collectionBehavior = [.canJoinAllSpaces, .moveToActiveSpace]

Citations:


Combine the collection behavior flags instead of overwriting them.

The second assignment replaces the first one, so these windows lose .canJoinAllSpaces. That can keep fullscreen notifications from following the same Spaces/fullscreen behavior as before.

Suggested fix
-            window.collectionBehavior = .canJoinAllSpaces
-            window.collectionBehavior = .moveToActiveSpace
+            window.collectionBehavior = [.canJoinAllSpaces, .moveToActiveSpace]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
window.collectionBehavior = .canJoinAllSpaces
window.collectionBehavior = .moveToActiveSpace
window.collectionBehavior = [.canJoinAllSpaces, .moveToActiveSpace]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MeetingBar/App/AppDelegate.swift` around lines 260 - 261, The second
assignment to window.collectionBehavior overwrites the first, dropping
.canJoinAllSpaces; change the code that sets window.collectionBehavior (in
AppDelegate.swift where window.collectionBehavior is assigned) to combine the
options instead of replacing them—use the OptionSet union (e.g., set both flags
together or call insert on window.collectionBehavior) so the window keeps both
.canJoinAllSpaces and .moveToActiveSpace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants