Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I implement Event Msgs from Cmd.ofAsyncMsg? #632

Closed
goldfish1974 opened this issue Dec 3, 2019 · 1 comment
Closed

How do I implement Event Msgs from Cmd.ofAsyncMsg? #632

goldfish1974 opened this issue Dec 3, 2019 · 1 comment
Labels
t/discussion A subject is being debated

Comments

@goldfish1974
Copy link

goldfish1974 commented Dec 3, 2019

Hi All,

I'm trying to implement a "PopUp" window module within my Xamarin App. The idea being that the PopUp window is used like normal popup windows/Dialog type functions but they include different layouts and Lottie animations + changing progress text.

The main feature for the Popup i want are:

  1. Uses Fabulous View (as opposed to Android popup) - I will have some Lottie Anims on the popups.
  2. Popups can open on one Process View and close on another Process view
  3. Popups appear after a specific timeout and fade in. Popups fade out when dismissed.
  4. Popups can get additional "progress" Msgs whilst it is open (e.g. progress of a longer process hasn't hung...say 10% complete, etc.)

N.B. This is somewhat modeled on the way Fabulous Contacts handles it's update and view by having external commands to jump between processes. I am planning on adding a second external command to control the reveling and dismissing of the Dialog. It needs to be handled at the top level state so that when the View is created, the current dialog view fragment can be passed in and then presented as an overlay. Effectively popups span across different processes.

I'm looking for some guidance on how I can structure my code like so:

let delayedDialog = mkDelayedDialog asyncLogon

I'm having trouble on a few fronts. My current issues are:
How can I wrap asyncShowSlowLogon such that I can dispatch a Cmd (one that is not part of this process, but another DialogMsg |> Cmd.ofMsg and therefore the 'T is different to the LOGGEDON Msg msg type show below.

The above mkDelayedDialog would need to split Cmds into 2 things.

  1. modify asyncLogon by wrapping it in an async block. when it completes, reutrn the original response as well as asyncHideDialog (below)
  2. When the initial Command is returned, return [asyncShowSlowLogon ; wrappedAsyncLogon ]

The dialog would show automatically if the AsyncLogon was taking too long and when the logon completed, the completed Msg as well as HIDEDIALOG would be returned.

One issue is that the show and hide Msgs would need to be wrapped and passed into the current process as a LOCALDIALOGMSG (i.e. I map the asyncShowSlowLogon and asyncHideDialog is a message that is directed at the current process update method, which then unpacks the DialogMsg which ultimately modifies the DialogState at the top level update function.

What I don't know is. How can I get the asyncLogon to return Cmds over time so that I could provide additional feedback to the user?

let asyncShowSlowLogon =
    async {
           do! Async.Sleep 300
           return SHOWDIALOG
    } |> Cmd.OfAsyncCmd

let asyncHideDialog =
    async {
           do! Async.Sleep 300
           return HIDEDIALOG
    } |> Cmd.OfAsyncCmd

let asyncLogon =
      async {
             <Return Additional Cmds to progressive messages>
              // How do I return multiple MSGS, e.g. Progress
              // return PROGRESSMSG("")

              // return PROGRESSMSG("")
              return LOGGEDON
      } |> Cmd.ofAsyncCmd

let update msg =
    match msg with
    | LOGONBUTTON ->
        // start logon and show dialog
        { state with LogonInProgress = true}; ShowDialog = false, [ asyncLogon;  asyncShowSlowLogon ]
    | LOGGEDON ->
        { state with LogonInProgress = false; ProgressMsg = None}. [ asyncHideDialog ]
    | PROGRESSMSG message ->
       { state with ProgressMsg = Some Msg }, []
    | SHOWDIALOG ->
       { state with ShowDialog = true}, []
    | HIDEDIALOG ->
       { state with ShowDialog = false}, []

So to progress, my questions are:

  1. How could I pass multiple Cmds back from the asyncLogon so I could provide progress messages into the DialogState, or
  2. Is there a way where I can pass a dispatch from the update function that can inject a MSG into the top level update function (There is a video about how to break up large Elmish Programs and FabulousContacts follows a similar pattern, as do I. The video talks about MSGs go into the top level Update. If I could construct a dialogDispatch that took a message that dropped the "event" Cmd into the top of the root update function, this would probably also solve many of my issues.

I can see the withSubscriber() app call but I don't understand how that works. I get the impression that is snooping on messages as opposed to originating them.

Option 2 seems like the best path because I cannot see how I can get multiple Msgs spread over time from the asyncLogon AsyncCmd.

Thanks.

@TimLariviere TimLariviere added this to To do in Fabulous for Xamarin.Forms via automation Feb 10, 2020
@TimLariviere TimLariviere added t/discussion A subject is being debated and removed proj/xamarinforms labels Feb 18, 2020
@h0lg
Copy link

h0lg commented Dec 26, 2023

@TimLariviere Is there an answer to the "returning multiple async messages" (see PROGRESSMSG above) part of this question somewhere? I am new to the MVU pattern and have a similar scenario: A long-running, cancelable async search method returning an IAsyncEnumerable<SearchResult> ( i.e. returning each search result as soon as it is available).

I'm trying to wrap my head around how to integrate

  1. the cancellation of the search
  2. displaying SearchResults (and maybe even search progress) as soon as they become available.

For 1 I found #928 and am trying to wrap my head around it - but I'm still looking for an MVU pattern that deals with async sequences.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
t/discussion A subject is being debated
Projects
No open projects
Development

No branches or pull requests

3 participants