GraniteNavigation.Passthrough | Screen
public struct NavigationPassthroughComponent<Component: GraniteComponent, Payload: GranitePayload>: View {
class Screen<Component: GraniteComponent, Payload: GranitePayload> {
...
}
@Environment(\.graniteRouter) var router
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@Environment(\.graniteNavigationStyle) var style
@Environment(\.graniteNavigationDestinationStyle) var destinationStyle
@Environment(\.graniteNavigationWindowDestinationStyle) var windowStyle
fileprivate var screen: Screen<Component, Payload>
@State var loaded: Bool = false
//Simulate slide in nav stack anim
//should be customizable via destination style
@State var isShowing: Bool = false
init(screen: Screen<Component, Payload>)
var destinationStyleFinal: GraniteNavigationDestinationStyle {
self.screen.style ?? destinationStyle
}
func dismiss()
var leadingItem: some View
var navBar : some View
public var body: some View {
Group {
#if os(iOS)
SlideAnimationContainerView($isShowing,
loaded: $loaded) {
mainView
}
#else
mainView
#endif
}
.onDisappear {
self.screen.clean()
self.loaded = false
GraniteLog("Navigation Stack Window released", level: .debug)
}
.onAppear {
self.screen.build {
loaded = true
GraniteLog("Navigation Stack Window loaded, isPresented: \(presentationMode.wrappedValue.isPresented)", level: .debug)
}
}
.onChange(of: isShowing) { state in
guard !state else { return }
GraniteLog("Navigated view dismissed via sliding")
dismiss()
}
}
}This is the final wrapper that GraniteNavigation's set function creates around a pushed component. When the screen builds, a wrapper is used around the mainView to add the familiar native slide/swipe animation. Entering from the trailing end of the view, it will move inwards as a normal push. This setup will also allow further customization on the developer's end, when choosing what type of animation to use for entry and dismissal.
For macOS on the other hand, it simply appears on top. Will be thinking about bringing it to macOS, but it didn't feel very natural of an experience at the time of creation.
self.screen.clean()
self.screen.build { }This simply allows us to remove the instances of the Views and re-build them upon appear. As they are all contained in handlers such as () -> View. Since GraniteComponent sets up listeners for events on appear, we'd like to remove and re-add them whenever they are necessary to prevent memory leaks or simply to avoid memory-usage overall. GraniteNavigation.Router shows where this screen is created and keyed into the stack.