Using AddTimeout in Subscription
AlexanderLindsay opened this issue · comments
Description
I am trying to add a subscription to a program to use the AddTimeout method on the MainLoop of Terminal.Gui Application. However, it only runs once when I am expecting it to rerun since I am returning true
in the AddTimeout callback. I have a feeling that I just don't understand how the dispatch works, or maybe how it interacts with the Application.MainLoop.
Repro steps
Program.mkProgram init update view
|> Program.withSubscription (fun m ->
let sub dispatch =
Application
.MainLoop
.AddTimeout(
System.TimeSpan(0, 0, 1),
(fun _ ->
dispatch Tick
true
)
)
|> ignore
Cmd.ofSub sub
)
|> Program.run
Expected behavior
I expected the Tick msg to be dispatched every second
Actual behavior
The Tick msg is dispatched only once
Known workarounds
none
Related information
- Windows 10
- master
dotnet --version
: 2.2.401
Full Sample Program
open Terminal.Gui
open Terminal.Gui.Elmish
type Model =
{ Count : int }
type Msg =
| Tick
| Inc
| Dec
let init() = { Count = 1 }, Cmd.none
let update (msg : Msg) (model : Model) =
match msg with
| Tick -> { model with Count = model.Count + 1 }, Cmd.none
| Inc -> { model with Count = model.Count + 1 }, Cmd.none
| Dec -> { model with Count = model.Count - 1 }, Cmd.none
let view (model : Model) (dispatch : Msg -> unit) =
page [
window [
Styles [
Pos(AbsPos 0, AbsPos 1)
Dim(Fill, Fill)
]
Title "Terminal/Console Elmish"
] [
button [
Styles [
Pos (AbsPos 1, AbsPos 1)
]
Text "Counter Up"
OnClicked (fun () -> dispatch Inc)
]
label [
Styles [
Pos (AbsPos 1, AbsPos 2)
]
Text <| sprintf "%d" model.Count
]
button [
Styles [
Pos (AbsPos 1, AbsPos 3)
]
Text "Counter Down"
OnClicked (fun () -> dispatch Dec)
]
]
]
[<EntryPoint>]
let main argv =
Program.mkProgram init update view
|> Program.withSubscription (fun m ->
let sub dispatch =
Application
.MainLoop
.AddTimeout(
System.TimeSpan(0, 0, 1),
(fun _ ->
dispatch Tick
true
)
)
|> ignore
Cmd.ofSub sub
)
|> Program.run
0 // return an integer exit code
I think I found a workaround at least:
let wait dispatch =
Application.MainLoop.AddTimeout(
System.TimeSpan(0, 0, 1),
(fun _ ->
dispatch Tick
false
)
) |> ignore
let init() = { Count = 1 }, Cmd.ofSub wait
let update (msg : Msg) (model : Model) =
match msg with
| Tick -> { model with Count = model.Count + 1 }, Cmd.ofSub wait
| Inc -> { model with Count = model.Count + 1 }, Cmd.none
| Dec -> { model with Count = model.Count - 1 }, Cmd.none
I will look into it. Thank you :)
Hi. So i fixed that issue and commit the fix into the master branch. I have to add some additional bugfixes, bacause the subscription, especially the kind of sending messages in intervals, cause some issues.
I added a subscription into the demo application.
Awesome, thanks!
I will take a look at the sample and try it out.
Hi. So I published a new nuget version.
https://www.nuget.org/packages/Terminal.Gui.Elmish/0.1.4
feel free to report further issues. :)