From 20597e6e8888efba059f02cf1393032c30a1553f Mon Sep 17 00:00:00 2001
From: cdricms <36056008+cdricms@users.noreply.github.com>
Date: Fri, 24 Jul 2026 13:19:26 +0200
Subject: [PATCH] fix(apple): enforce a single window on macOS and iPadOS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
macOS uses a single-instance `Window` scene instead of `WindowGroup`, which
otherwise lets the app open multiple windows (via ⌘N). iPadOS sets
`UIApplicationSupportsMultipleScenes = false` to block a second scene via Stage
Manager / split view. (`LSMultipleInstancesProhibited` only blocks a second
process, not a second window.)
---
apple/VniDrop/App/VniDropApp.swift | 15 ++++++++++++++-
apple/VniDrop/Resources/Info.plist | 4 ++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/apple/VniDrop/App/VniDropApp.swift b/apple/VniDrop/App/VniDropApp.swift
index 0119980..3882b17 100644
--- a/apple/VniDrop/App/VniDropApp.swift
+++ b/apple/VniDrop/App/VniDropApp.swift
@@ -1,5 +1,8 @@
import SwiftUI
+/// Scene identifier for the single main window.
+private let mainWindowId = "main"
+
/// Native app entry point for iOS, iPadOS, and macOS.
/// Opens `.vnd` invitations via `onOpenURL` and routes them to the receive flow.
@main
@@ -7,11 +10,21 @@ struct VniDropApp: App {
@StateObject private var externalInvitations = ExternalInvitationController()
var body: some Scene {
- WindowGroup {
+ #if os(macOS)
+ // A single-instance `Window` (not `WindowGroup`): the app must never open a
+ // second window. `Window` also drops the ⌘N "New Window" command.
+ Window(Text(verbatim: "VniDrop"), id: mainWindowId) {
RootView(dependencies: makeAppDependencies(externalInvitations: externalInvitations))
.ignoresSafeArea()
.onOpenURL(perform: openInvitation)
}
+ #else
+ WindowGroup(id: mainWindowId) {
+ RootView(dependencies: makeAppDependencies(externalInvitations: externalInvitations))
+ .ignoresSafeArea()
+ .onOpenURL(perform: openInvitation)
+ }
+ #endif
}
/// Reads a `.vnd` invitation document under a security scope, enforcing the
diff --git a/apple/VniDrop/Resources/Info.plist b/apple/VniDrop/Resources/Info.plist
index 9ef9fc8..a2613e4 100644
--- a/apple/VniDrop/Resources/Info.plist
+++ b/apple/VniDrop/Resources/Info.plist
@@ -67,6 +67,10 @@
VniDrop uses the camera to scan transfer QR codes.
NSLocalNetworkUsageDescription
VniDrop needs local network access to send to other local devices if needed.
+
+ UIApplicationSupportsMultipleScenes
+
UIBackgroundModes
fetch