portico/Sources/Portico/App/EitherScene.swift

47 lines
1.5 KiB
Swift

import Adw
/// The scene produced by an `if`/`else` inside ``SceneBuilder``.
///
/// Carries whichever branch the condition selected. A scene branch change
/// replaces the whole window - top-level windows cannot be swapped without
/// rebuilding them.
public struct EitherScene<First: Scene, Second: Scene>: Scene {
enum Branch {
case first(First)
case second(Second)
}
let branch: Branch
init(_ branch: Branch) { self.branch = branch }
public var body: Never { fatalError() }
}
@_spi(Portico) extension EitherScene: MountableScene {
@_spi(Portico) public var identity: SceneIdentity {
switch branch {
case .first(let s): return .first(Self.mountable(s).identity)
case .second(let s): return .second(Self.mountable(s).identity)
}
}
@_spi(Portico) public func attach(to app: Adw.Application) -> SceneHandle? {
switch branch {
case .first(let s): return Self.mountable(s).attach(to: app)
case .second(let s): return Self.mountable(s).attach(to: app)
}
}
/// Runtime-casts a branch to ``MountableScene``, matching the dispatch
/// ``PorticoRuntime`` uses for the root scene.
private static func mountable<S: Scene>(_ scene: S) -> MountableScene {
guard let m = scene as? MountableScene else {
fatalError(
"Portico: every branch of a conditional Scene must conform to "
+ "MountableScene (use ApplicationWindow)"
)
}
return m
}
}