Skip to content

Commit 6441b5d

Browse files
authored
Merge pull request #1063 from fabulous-dev/debounce-cmd
Debounce cmd
2 parents 203440e + 13aa015 commit 6441b5d

File tree

6 files changed

+73
-5
lines changed

6 files changed

+73
-5
lines changed

.config/dotnet-tools.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"isRoot": true,
44
"tools": {
55
"fantomas": {
6-
"version": "5.2.0",
6+
"version": "6.2.3",
77
"commands": [
88
"fantomas"
99
]

.github/workflows/pull_request.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: Check code formatting
1919
run: |
2020
dotnet tool restore
21-
dotnet fantomas --check -r src
21+
dotnet fantomas --check src
2222
- name: Restore
2323
run: dotnet restore ${SLN_FILE}
2424
- name: Build

src/Fabulous.Tests/CmdTests.fs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
namespace Fabulous.Tests
2+
3+
open Fabulous
4+
open NUnit.Framework
5+
6+
type CmdTestsMsg = NewValue of int
7+
8+
module CmdTestsHelper =
9+
let execute dispatch (cmd: Cmd<'msg>) =
10+
for sub in cmd do
11+
sub dispatch
12+
13+
[<TestFixture>]
14+
type ``Cmd tests``() =
15+
[<Test>]
16+
member _.``Cmd.debounce only dispatch the last message``() =
17+
async {
18+
let mutable actualValue = None
19+
20+
let dispatch msg =
21+
if actualValue.IsNone then
22+
actualValue <- Some msg
23+
24+
let triggerCmd = Cmd.debounce 100 NewValue
25+
26+
triggerCmd 1 |> CmdTestsHelper.execute dispatch
27+
do! Async.Sleep 50
28+
triggerCmd 2 |> CmdTestsHelper.execute dispatch
29+
do! Async.Sleep 75
30+
triggerCmd 3 |> CmdTestsHelper.execute dispatch
31+
do! Async.Sleep 125
32+
33+
Assert.AreEqual(Some(NewValue 3), actualValue)
34+
35+
actualValue <- None
36+
37+
triggerCmd 4 |> CmdTestsHelper.execute dispatch
38+
do! Async.Sleep 75
39+
triggerCmd 5 |> CmdTestsHelper.execute dispatch
40+
do! Async.Sleep 125
41+
42+
Assert.AreEqual(Some(NewValue 5), actualValue)
43+
}

src/Fabulous.Tests/Fabulous.Tests.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<Compile Include="AttributesTests.fs" />
1616
<Compile Include="ViewTests.fs" />
1717
<Compile Include="ArrayTests.fs" />
18+
<Compile Include="CmdTests.fs" />
1819
</ItemGroup>
1920
<ItemGroup>
2021
<PackageReference Include="BenchmarkDotNet" />

src/Fabulous/Builders.fs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ type WidgetBuilder<'msg, 'marker> =
3838
DebugName = $"{typeof<'marker>.Name}<{typeof<'msg>.Name}>"
3939
#endif
4040
ScalarAttributes =
41-
match StackList.length &scalarAttributes with
42-
| 0us -> ValueNone
43-
| _ -> ValueSome(Array.sortInPlace (fun a -> a.Key) (StackList.toArray &scalarAttributes))
41+
match StackList.length &scalarAttributes with
42+
| 0us -> ValueNone
43+
| _ -> ValueSome(Array.sortInPlace (fun a -> a.Key) (StackList.toArray &scalarAttributes))
4444

4545
WidgetAttributes = ValueOption.map (Array.sortInPlace(fun a -> a.Key)) widgetAttributes
4646

src/Fabulous/Cmd.fs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace Fabulous
22

3+
open System.Threading
34
open System.Threading.Tasks
45

56
/// Dispatch - feed new message into the processing loop
@@ -104,3 +105,26 @@ module Cmd =
104105
dispatch(failure ex)
105106
}
106107
|> ignore ]
108+
109+
/// Command to issue a message if no other message has been issued within the specified timeout
110+
let debounce (timeout: int) (fn: 'value -> 'msg) : 'value -> Cmd<'msg> =
111+
let mutable cts: CancellationTokenSource = null
112+
113+
fun (value: 'value) ->
114+
[ fun dispatch ->
115+
if cts <> null then
116+
cts.Cancel()
117+
cts.Dispose()
118+
119+
cts <- new CancellationTokenSource()
120+
121+
Async.Start(
122+
async {
123+
do! Async.Sleep(timeout)
124+
dispatch(fn value)
125+
126+
cts.Dispose()
127+
cts <- null
128+
},
129+
cts.Token
130+
) ]

0 commit comments

Comments
 (0)