// // OnboardPathEnvironmentKey.swift // // Copyright 2026 Brendan Szymanski // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // SPDX-License-Identifier: GPL-3.0-or-later // import Logging import LuminateCore import Portico private let logger = Logger(label: "\(AppInfo.identifier).onboarding") /// The environment slot that carries `OnboardWindow`'s navigation path down the onboarding tree. /// /// The slot holds the `Binding` itself, not the path value: Portico's `@Environment` is a read-only /// view of a slot, so a consumer can only push by writing through a binding that the injecting /// window owns. Onboarding-specific by design -- a future main-window stack gets its own slot /// rather than sharing this one. package enum OnboardPathEnvironmentKey: EnvironmentKey { /// The inert binding used when nothing injected a path. /// /// Reads yield an empty stack and writes are logged and dropped, so a page mounted outside /// `OnboardWindow` (a unit test, a preview harness) reports the mistake instead of silently /// appearing to navigate. package static var defaultValue: Binding<[OnboardDestination]> { Binding( get: { [] }, set: { _ in logger.error("Dropped an onboarding navigation push: no OnboardWindow injected \\.onboardPath") } ) } } extension EnvironmentValues { /// The onboarding navigation path visible to this subtree. /// /// ```swift /// // Injection, once, on OnboardWindow's NavigationView: /// NavigationView(path: $onboardPath) { ... }.environment(\.onboardPath, $onboardPath) /// /// // Consumption in any onboarding page: /// @Environment(\.onboardPath) private var onboardPath /// onboardPath.wrappedValue.append(.manualLogin) /// ``` /// /// The accessors deliberately route through `self[OnboardPathEnvironmentKey.self]`: Portico /// resolves a key path by reading it with a probe installed and capturing the box the subscript /// hands over, so a computed property that bypassed the subscript would leave the slot /// unresolvable. package var onboardPath: Binding<[OnboardDestination]> { get { self[OnboardPathEnvironmentKey.self] } set { self[OnboardPathEnvironmentKey.self] = newValue } } }