wwt / SwiftCurrent

A library for managing complex workflows in Swift

Home Page:https://wwt.github.io/SwiftCurrent/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SwiftUI: Abandon from outside `FlowRepresentable`

Tyler-Keith-Thompson opened this issue · comments

Is your feature request related to a problem? Please describe.

I've got multiple workflows in SwiftUI being presented at the same time. I'd like to abandon them all if a user is logged out. This is achievable in UIKit because you can just extract and use the data model. For example, I could've created multiple workflows and stored them somewhere, then just called abandon on them. However, because SwiftUI does not use the data model, that trick doesn't work.

Describe the solution you'd like

Realistically this is yet another example in my head of why we should allow the data model to be used in SwiftUI however this feature request is different. I'd like some way of abandoning a workflow from outside a FlowRepresentable think something like this:

WorkflowLauncher(isLaunched: .constant(true))
                .thenProceed(with: WorkflowItem(LoginView.self))
                .thenProceed(with: WorkflowItem(QRScannerFeatureOnboardingView.self))
                .thenProceed(with: WorkflowItem(QRScannerFeatureView.self))
                .abandonOn(user.isLoggedIn == false) // Version 1, Autoclosure
                .abandonOn { !user.isLoggedIn } // Version 2, for reals closure
                .tabItem {
                    Label("QR Scanner", systemImage: "camera")
                }
                .tag(Tab.qr)

That exact solution may not actually be possible, but you can see the advantage of describing this here.

Describe alternatives you've considered

Allow me to use data models:

This solution is a huge request, but it carries some very reasonable possibilities for me outside this one use-case, for example:

@State var workflow = Workflow(LoginView.self)
                                        .thenProceed(with: QRScannerFeatureOnboardingView.self)
                                        .thenProceed(with: QRScannerFeatureView.self)
                                        
// In the view
WorkflowLauncher(isLaunched: .constant(true))
                .launchInto(workflow)
                .tabItem {
                    Label("QR Scanner", systemImage: "camera")
                }
                .tag(Tab.qr)
                .onChange(of: user.isLoggedIn) { if !$0 { workflow.abandon() } } // abandons and relaunches, yay!

With how things are now:

The current alternative is for me to go to literally every FlowRepresentable view and add an onChange modifier that abandons the workflow if the user is not logged in anymore. This is highly unfortunate because then every view has to know about the user, even if it would otherwise not need to.

Additional context

There may be completely new options or patterns I have not yet thought through. I'm happy to have a discussion about that if my premise is incorrect.

Other ideas occurred to me that wouldn't require any change:

  • You could have all the workflows use the same state variable for isLaunched so when one abandons it abandons the others
  • You could put the entire WorkflowLauncher in an if user.isLoggedIn and basically have 2 workflows, one for logging in, one when that state changes for the part that's after login. This isn't quite as seamless as describing a linear flow but it's not a bad option in SwiftUI land where state is so crucial