FlowStacks icon indicating copy to clipboard operation
FlowStacks copied to clipboard

SwiftUI's native dismiss environment value does not work from fullscreen modal with navigation

Open CorbinMontague opened this issue 4 months ago • 3 comments

There is a bug where attempting to use SwiftUI's native dismiss environment value does not work from a fullscreen modal presented with navigation: foo.presentCover(Screen.modalView, withNavigation: true). This bug is present in both the 0.8.1 and 0.8.2 versions (I haven't checked any other versions). Workaround is to use FlowPathNavigator or a reference to the FlowPath associated with the FlowStack because FlowStacks dismiss APIs still work as expected. See code example below:

import Foundation
import FlowStacks
import SwiftUI

public enum Screen {
    case modalView
}
extension Screen: Identifiable, Hashable {
    public var id: String {
        return String(reflecting: self)
    }
    
    public func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
    
    public static func == (lhs: Screen, rhs: Screen) -> Bool {
        lhs.id == rhs.id
    }
}

struct ScreenViewBuilder {
    static func view(for screen: Screen) -> some View {
        switch screen {
        case .modalView:
            return ModalView()
        }
    }
}

struct ContentView: View {
    
    @State var path = FlowPath()
    var body: some View {
        FlowStack($path, withNavigation: true) {
            makeRootView()
                .flowDestination(for: Screen.self) { screen in
                    ScreenViewBuilder.view(for: screen)
                }
        }
    }
    
    @ViewBuilder private func makeRootView() -> some View {
        Button("Present ModalView with navigation") {
            path.presentCover(Screen.modalView, withNavigation: true)
        }
    }
}

struct ModalView: View {
    @Environment(\.dismiss) private var dismiss
    @EnvironmentObject var navigator: FlowPathNavigator
    
    var body: some View {
        Text("Modal View")
            .toolbar {
                ToolbarItem(placement: .topBarLeading) {
                    Button("Native Dismiss") {
                        dismiss() // does not work
                    }
                }
                
                ToolbarItem(placement: .topBarTrailing) {
                    Button("FlowStacks Dismiss") {
                        navigator.dismiss() // works
                        // navigator.goBack() // works
                    }
                }
            }
    }
}

CorbinMontague avatar Oct 07 '24 14:10 CorbinMontague