Here's a video demo of using custom async proc's with Fidget to animate a UI: 
<https://youtu.be/nRFoflV3MI0> and the [example 
code](https://github.com/elcritch/fidget/blob/devel/tests/progressbar/progressbar.nim).

It turns out the required user code is as simple as creating an async proc:
    
    
    var progressBar: float = 0.02
    var ticks: Future[void] = emptyFuture() ## Create an completed "empty" 
future
    
    proc ticker() {.async.} =
      ## Every tick will increment the progress bar 10% until its done.
      for i in 1..10:
        await sleepAsync(1_000)
        progressBar = 0.1 * i.toFloat()
        echo fmt"tick {bar}"
        refresh()
    
    
    Run

Then trigger it in the UI:
    
    
    rectangle "run animation button":
              box barW-80, 0, 40, 40
              onClick:
                if ticks.finished():
                  echo "setup new ticker"
                  ticks = ticker()
                else:
                  echo "ticker already running!"
    
    
    Run

Enabling that use case required tweaking Fidget and Nim's async/ioselectors on 
MacOSX. The Fidget changes were just adding an AsyncEvent callback on 
keyboard/mouse inputs.

Unfortunately on MacOSX it was painfully slow. That's because Nim's AsyncEvent 
relies on user events in `selectors`. On MacOSX and BSD user events in the 
`selectors` module are emulated using pipes. This cause me headaches before so 
I created a [PR](https://github.com/nim-lang/Nim/pull/19587) to enable using 
kqueues's `EVFILT_USER`. Though it'll need some testing/work the latency is 
much better at about ~1ms.

Reply via email to