@@ -22,6 +22,18 @@ struct ContentView: View {
2222 /// non-blocking state (.none, .unlocked, .lockNowAcknowledged).
2323 private var isLockdownGateActive : Bool { lockdown. isBlockingSession }
2424
25+ /// Plain view-state mirror of `isLockdownGateActive`, kept in sync from the
26+ /// coordinator via `.onChange`. Presenting the lockdown `fullScreenCover`
27+ /// through a *computed* `Binding` — getter reading the `lockdown`
28+ /// `@EnvironmentObject`, setter a no-op — produced a presentation binding that
29+ /// could never converge, which iOS 17's SwiftUI resolved by re-entering the
30+ /// attribute graph until it tripped `_assertionFailure` at first layout (a
31+ /// launch crash unique to iOS 17; iOS 18+ tolerated it). Driving the cover
32+ /// from real `@State` breaks that cycle. `LockdownSheet` has no dismiss
33+ /// affordance, so this stays non-dismissable — only the coordinator leaving a
34+ /// blocking state clears it.
35+ @State private var isShowingLockdownGate : Bool = false
36+
2537 init ( appState: AppState , router: Router ) {
2638 self . appState = appState
2739 self . router = router
@@ -38,16 +50,23 @@ struct ContentView: View {
3850 DeviceOnboarding ( )
3951 }
4052 )
41- . fullScreenCover ( isPresented: Binding (
42- get: { isLockdownGateActive } ,
43- set: { _ in /* non-dismissable; coordinator state controls visibility */ }
44- ) ) {
53+ . fullScreenCover ( isPresented: $isShowingLockdownGate) {
4554 LockdownSheet ( )
4655 }
4756 . onAppear {
4857 if UserDefaults . firstLaunch {
4958 isShowingDeviceOnboardingFlow = true
5059 }
60+ // Present the gate if the device is already in a blocking state when
61+ // this view appears.
62+ isShowingLockdownGate = isLockdownGateActive
63+ }
64+ . onChange ( of: isLockdownGateActive) { _, active in
65+ // Follow the coordinator's blocking state. The gate never closes from
66+ // user interaction (fullScreenCover has no interactive dismiss and
67+ // LockdownSheet exposes no dismiss control), so this is the only path
68+ // that shows or hides it.
69+ isShowingLockdownGate = active
5170 }
5271 . onChange ( of: UserDefaults . showDeviceOnboarding) { _, newValue in
5372 isShowingDeviceOnboardingFlow = newValue
0 commit comments