Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
JaggerJo committed Sep 8, 2024
2 parents 7458f16 + e8e1553 commit 4eef8c9
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/Avalonia.FuncUI.Elmish/Avalonia.FuncUI.Elmish.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,8 @@
<ItemGroup>
<ProjectReference Include="..\Avalonia.FuncUI\Avalonia.FuncUI.fsproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Update="FSharp.Core" Version="6.0.0" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="System.Reactive" Version="6.0.1" />
<PackageReference Include="xunit" Version="2.9.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PrivateAssets>all</PrivateAssets>
Expand Down
24 changes: 22 additions & 2 deletions src/Avalonia.FuncUI.UnitTests/LibTests.fs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
namespace Avalonia.FuncUI.UnitTests

open System.Reactive.Subjects
open Avalonia.FuncUI.Library
open Xunit

module Library =

[<Fact>]
let ``function equality`` () =

let view () =
let add = fun (count: int) -> count + 1
let sub = fun (count: int) -> count - 1
Expand All @@ -19,4 +20,23 @@ module Library =
Assert.Equal(add'.GetType(), add''.GetType())
Assert.Equal(sub'.GetType(), sub''.GetType())
Assert.NotEqual(add'.GetType(), sub'.GetType())
Assert.NotEqual(add''.GetType(), sub''.GetType())
Assert.NotEqual(add''.GetType(), sub''.GetType())


[<Fact>]
let ``IObservable<T>.SkipFirst`` () =
let observable = new Subject<int>()
let seenItems = ResizeArray<int>()

let _ =
observable
.SkipFirst()
.Subscribe(fun n -> seenItems.Add(n))

observable.OnNext(1)
observable.OnNext(2)
observable.OnNext(3)

Assert.Equal(2, seenItems.Count)
Assert.Equal(2, seenItems.[0])
Assert.Equal(3, seenItems.[1])
4 changes: 4 additions & 0 deletions src/Avalonia.FuncUI/Avalonia.FuncUI.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,8 @@
<Compile Include="Experimental\Experimental.Hooks.fs" />
</ItemGroup>

<ItemGroup>
<PackageReference Update="FSharp.Core" Version="6.0.0" />
</ItemGroup>

</Project>
4 changes: 4 additions & 0 deletions src/Avalonia.FuncUI/DSL/AttrBuilder.fs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ type AttrBuilder<'view>() =
let cts = new CancellationTokenSource()
control
.GetObservable(property)
// GetObservable immediately emits the current value. We're not interested in that, so we skip the first value.
.SkipFirst()
.Subscribe(func, cts.Token)
cts

Expand All @@ -261,6 +263,8 @@ type AttrBuilder<'view>() =
let cts = new CancellationTokenSource()
control
.GetObservable(property)
// GetObservable immediately emits the current value. We're not interested in that, so we skip the first value.
.SkipFirst()
.Subscribe(func, cts.Token)
cts

Expand Down
27 changes: 25 additions & 2 deletions src/Avalonia.FuncUI/Library.fs
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,40 @@ module internal Extensions =
let disposable = Observable.subscribe callback this
token.Register(fun () -> disposable.Dispose()) |> ignore

member this.SkipFirst() =
{ new IObservable<'a> with
member __.Subscribe(observer: IObserver<'a>) =
let skipFirstObserver =
let mutable isFirst = true

{ new IObserver<'a> with
member __.OnNext(value) =
if isFirst then
isFirst <- false
else
observer.OnNext(value)

member __.OnError(error) =
observer.OnError(error)

member __.OnCompleted() =
observer.OnCompleted()
}

this.Subscribe(skipFirstObserver)
}

type Interactive with
member this.GetObservable<'args when 'args :> RoutedEventArgs>(routedEvent: RoutedEvent<'args>) : IObservable<'args> =
let sub = Func<IObserver<'args>, IDisposable>(fun observer ->
// push new update to subscribers
let handler = EventHandler<'args>(fun _ e ->
observer.OnNext e
)

// subscribe to event changes so they can be pushed to subscribers
this.AddDisposableHandler(routedEvent, handler, routedEvent.RoutingStrategies)
)

{ new IObservable<'args>
with member this.Subscribe(observer: IObserver<'args>) = sub.Invoke(observer) }
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<AvaloniaVersion>11.1.0</AvaloniaVersion>
<FuncUIVersion>1.5.0</FuncUIVersion>
<FuncUIVersion>1.5.1</FuncUIVersion>
</PropertyGroup>
</Project>

0 comments on commit 4eef8c9

Please sign in to comment.