All Platforms: Modally presented popover server driven components.
bradleysmaskell opened this issue · 4 comments
Use case
For context our BFF is written in Kotlin using Quarkus, client apps are written in Kotlin/Swift/reactJS.
In one of our server-driven screens we have a ListView
component. One of the Template
s has a Touchable
component. When pressed we want to modally present a popover ViewController/Dialog which contains a ServerDrivenComponent
and a Context
so that selections made in the popover update the parent Activity/ViewControllers context.
Issues
- there is no
Navigate.PresentModalView
action onNavigate
in Beagle andNavigate
is not extendable. - While you can create a custom action that stores a
ServerDrivenComponent
, there's no way to render the component.- on iOS in
func execute(controller: BeagleController, origin: UIView)
the renderer onBeagleController
isprivate
and theBeagleEnvironment.renderer
is internal. - on Android in
fun execute(rootView: RootView, origin: View)
it's not clear what we need to call onRootView
to render aServerDrivenComponent
- on iOS in
Because of these issues, we had to just create a custom action that presents/shows a preexisting client-driven view and have our custom action listen for events so that we can execute/handle cancellation/apply actions. After those actions are completed, to update the parent Activity/ViewController we had to do the following on both platforms.
Android
- Cast the RootView to a FragmentRootView/ActivityRootView and cast the
fragment.activity
oractivity
toBeagleActivity
- Since fetch is
internal
toBeagleActivity
and there's no way to refresh the screens content from the BFF or context we had to callfinish()
andstartActivity()
to get the updates from the popover screen, which causes the screen to disappear and be recreated which isn't the best user experience.
iOS
- Cast the
BeagleController
to aBeagleScreenViewController
- Since there is no obvious way to refresh the
BeagleScreenViewController
we have to callreloadScreen(with screenType: ScreenType)
which doesn't deallocate and recreate the VC as it does on Android, but still causes the parent VC to flicker while it fetches it's data and presents it again.
There's not really a lot of helpful documentation around this use case, so any advice would be really helpful.
Proposal
- Provide a path to extend Navigate in the BFF and client SDKs and add documentation.
- Provide renderers that are publicly available so integrators can render ServerDrivenComponents both from a custom action as well as a custom widget.
- Provide a way to refresh the data of an activity/VC, or a way to update the ServerDrivenComponents context from a custom widget/action.
Hello @bradleysmaskell
This is a very interesting feature request. Implementing this is indeed harder than we'd like and it would be in our interest to create something to make it easier. Having said this, I think there might be an easier way to achieve this result.
Have you tried the following?
- Create a native modal view in Android and iOS that loads a server driven view with a given URL;
- Create a custom action that receives the URL as parameter and opens up the modal;
- Use a global context to store the data that must be shared between the screen with the ListView and the modal screen.
By using the Global Context, when you update it from the modal, it should automatically update the other view.
A native support in Beagle
To implement a native support for this in Beagle, we need:
- A modal view in the navigator and actions to open and close it;
- A way for updating the state (context) of the screen from the modal.
We're developing a "version of Beagle" for SwiftUI and Compose called "Nimbus". We do have this feature there. Can you take a look at the implementation in Nimbus and tell us if it would work for you? If it does work for you, we can consider bringing it to Beagle.
Link to this feature in nimbus: https://github.com/ZupIT/nimbus-docs/blob/main/specification/default-actions/navigation.md#more-on-states-and-events
The example above navigates to a new screen. But, in Nimbus, we have the action "present", that works the same way, but opens a modal view instead.
Summary
- I think there's a simpler way to implement this in Beagle without any update to the library. It consists on using the global context to share a state between the screens and custom actions to open a modal. Can you check if this works for you?
- In the long term, I propose a native implementation that works just like Nimbus. What do you think about this?
Hi, I'm passing here just to let you know that the Beagle team is taking some vacation time.
We'll take 2 weeks off and be back at Feb 06. Feel free to keep commenting in this issue and we'll address it as soon as we're back.
Thanks @Tiagoperes. We will try this approach and report back.
Closing this due to inactivity.