Skip to content

Commit

Permalink
Merge branch 'main' into release/2.5
Browse files Browse the repository at this point in the history
  • Loading branch information
Timothé Larivière committed Jan 30, 2024
2 parents 1933f98 + 4a93b2f commit 6de97c0
Show file tree
Hide file tree
Showing 15 changed files with 502 additions and 210 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

_No unreleased changes_

## [2.5.0-pre8] - 2024-01-30

### Changed
- Dispose properly ViewNode and Component when Widget is removed from tree by @TimLariviere (https://github.com/fabulous-dev/Fabulous/pull/1066)

## [2.5.0-pre7] - 2024-01-30

### Added
Expand Down Expand Up @@ -90,7 +95,8 @@ _No unreleased changes_
### Changed
- Fabulous.XamarinForms & Fabulous.MauiControls have been moved been out of the Fabulous repository. Find them in their own repositories: [https://github.com/fabulous-dev/Fabulous.XamarinForms](https://github.com/fabulous-dev/Fabulous.XamarinForms) / [https://github.com/fabulous-dev/Fabulous.MauiControls](https://github.com/fabulous-dev/Fabulous.MauiControls)

[unreleased]: https://github.com/fabulous-dev/Fabulous/compare/2.5.0-pre7...HEAD
[unreleased]: https://github.com/fabulous-dev/Fabulous/compare/2.5.0-pre8...HEAD
[2.5.0-pre8]: https://github.com/fabulous-dev/Fabulous/releases/tag/2.5.0-pre8
[2.5.0-pre7]: https://github.com/fabulous-dev/Fabulous/releases/tag/2.5.0-pre7
[2.5.0-pre6]: https://github.com/fabulous-dev/Fabulous/releases/tag/2.5.0-pre6
[2.5.0-pre5]: https://github.com/fabulous-dev/Fabulous/releases/tag/2.5.0-pre5
Expand Down
56 changes: 36 additions & 20 deletions src/Fabulous.Tests/APISketchTests/TestUI.Attributes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,22 @@ module TestUI_Attributes =

let btn = node.Target :?> IButton

match node.TryGetHandler<int>(name) with
match node.TryGetHandler(name) with
| ValueNone -> ()
| ValueSome handlerId -> btn.RemovePressListener handlerId
| ValueSome handler -> handler.Dispose()

match newValueOpt with
| ValueNone -> node.SetHandler(name, ValueNone)
| ValueNone -> node.RemoveHandler(name)

| ValueSome msg ->
let handler () = Dispatcher.dispatch node msg

let handlerId = btn.AddPressListener handler
node.SetHandler<int>(name, ValueSome handlerId))

let disposable =
{ new IDisposable with
member _.Dispose() = btn.RemovePressListener handlerId }

node.SetHandler(name, disposable))
)
|> AttributeDefinitionStore.registerScalar

Expand All @@ -44,18 +48,22 @@ module TestUI_Attributes =

let btn = node.Target :?> IButton

match node.TryGetHandler<int>(name) with
match node.TryGetHandler(name) with
| ValueNone -> ()
| ValueSome handlerId -> btn.RemoveTapListener handlerId
| ValueSome handler -> handler.Dispose()

match newValueOpt with
| ValueNone -> node.SetHandler(name, ValueNone)
| ValueNone -> node.RemoveHandler(name)

| ValueSome msg ->
let handler () = Dispatcher.dispatch node msg

let handlerId = btn.AddTapListener handler
node.SetHandler<int>(name, ValueSome handlerId))

let disposable =
{ new IDisposable with
member _.Dispose() = btn.RemoveTapListener handlerId }

node.SetHandler(name, disposable))
)
|> AttributeDefinitionStore.registerScalar

Expand All @@ -70,18 +78,22 @@ module TestUI_Attributes =

let btn = node.Target :?> IButton

match node.TryGetHandler<int>(name) with
match node.TryGetHandler(name) with
| ValueNone -> ()
| ValueSome handlerId -> btn.RemoveTap2Listener handlerId
| ValueSome handler -> handler.Dispose()

match newValueOpt with
| ValueNone -> node.SetHandler(name, ValueNone)
| ValueNone -> node.RemoveHandler(name)

| ValueSome msg ->
let handler () = Dispatcher.dispatch node msg

let handlerId = btn.AddTap2Listener handler
node.SetHandler<int>(name, ValueSome handlerId))

let disposable =
{ new IDisposable with
member _.Dispose() = btn.RemoveTap2Listener handlerId }

node.SetHandler(name, disposable))
)
|> AttributeDefinitionStore.registerScalar

Expand All @@ -96,18 +108,22 @@ module TestUI_Attributes =

let btn = node.Target :?> IContainer

match node.TryGetHandler<int>(name) with
match node.TryGetHandler(name) with
| ValueNone -> ()
| ValueSome handlerId -> btn.RemoveTapListener handlerId
| ValueSome handler -> handler.Dispose()

match newValueOpt with
| ValueNone -> node.SetHandler(name, ValueNone)
| ValueNone -> node.RemoveHandler(name)

| ValueSome msg ->
let handler () = Dispatcher.dispatch node msg

let handlerId = btn.AddTapListener handler
node.SetHandler<int>(name, ValueSome handlerId))

let disposable =
{ new IDisposable with
member _.Dispose() = btn.RemoveTapListener handlerId }

node.SetHandler(name, disposable))
)
|> AttributeDefinitionStore.registerScalar

Expand Down
7 changes: 6 additions & 1 deletion src/Fabulous.Tests/APISketchTests/TestUI.Component.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@ module TestUI_Component =
let ComponentProperty = "ComponentProperty"

let getComponent (target: obj) =
(target :?> TestViewElement).PropertyBag.Item ComponentProperty
match (target :?> TestViewElement).PropertyBag.TryGetValue(ComponentProperty) with
| true, comp -> comp
| _ -> null

let setComponent (comp: obj) (target: obj) =
(target :?> TestViewElement).PropertyBag.Add(ComponentProperty, comp)
3 changes: 2 additions & 1 deletion src/Fabulous.Tests/APISketchTests/TestUI.Widgets.fs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ module TestUI_Widgets =
| ValueNone -> None
| ValueSome parent -> Some parent

let viewNode = ViewNode(parentNode, context, weakReference)
let viewNode = new ViewNode(parentNode, context, weakReference)

view.PropertyBag.Add(ViewNode.ViewNodeProperty, viewNode)

Expand Down Expand Up @@ -214,6 +214,7 @@ module TestUI_Widgets =
MinLogLevel = LogLevel.Fatal }
Dispatch = fun msg -> unbox<'msg> msg |> x.ProcessMessage
GetComponent = Component.getComponent
SetComponent = Component.setComponent
SyncAction = fun fn -> fn() }

member x.ProcessMessage(msg: 'msg) =
Expand Down
45 changes: 17 additions & 28 deletions src/Fabulous/Attributes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ module Attributes =

// Trigger the unmounted event
Dispatcher.dispatchEventForAllChildren itemNode widget Lifecycle.Unmounted
itemNode.Disconnect()
itemNode.Dispose()

// Remove the child from the UI tree
targetColl.RemoveAt(index)
Expand Down Expand Up @@ -247,7 +247,7 @@ module Attributes =

// Trigger the unmounted event for the old child
Dispatcher.dispatchEventForAllChildren prevItemNode oldWidget Lifecycle.Unmounted
prevItemNode.Disconnect()
prevItemNode.Dispose()

// Replace the existing child in the UI tree at the index with the new one
targetColl[index] <- unbox view
Expand Down Expand Up @@ -288,20 +288,16 @@ module Attributes =
SimpleScalarAttributeDefinition.CreateAttributeData(
ScalarAttributeComparers.noCompare,
(fun _ (newValueOpt: MsgValue voption) node ->
let event = getEvent node.Target

match node.TryGetHandler(name) with
| ValueNone -> ()
| ValueSome handler -> event.RemoveHandler handler
| ValueSome handler -> handler.Dispose()

match newValueOpt with
| ValueNone -> node.SetHandler(name, ValueNone)

| ValueNone -> node.RemoveHandler(name)
| ValueSome(MsgValue msg) ->
let handler = EventHandler(fun _ _ -> Dispatcher.dispatch node msg)

event.AddHandler handler
node.SetHandler(name, ValueSome handler))
let event = getEvent node.Target
let handler = event.Subscribe(fun _ -> Dispatcher.dispatch node msg)
node.SetHandler(name, handler))
)

|> AttributeDefinitionStore.registerScalar
Expand All @@ -317,23 +313,21 @@ module Attributes =
SimpleScalarAttributeDefinition.CreateAttributeData(
ScalarAttributeComparers.noCompare,
(fun _ (newValueOpt: ('args -> MsgValue) voption) (node: IViewNode) ->
let event = getEvent node.Target

match node.TryGetHandler(name) with
| ValueNone -> ()
| ValueSome handler -> event.RemoveHandler handler
| ValueSome handler -> handler.Dispose()

match newValueOpt with
| ValueNone -> node.SetHandler(name, ValueNone)

| ValueNone -> node.RemoveHandler(name)
| ValueSome fn ->
let event = getEvent node.Target

let handler =
EventHandler<'args>(fun _ args ->
event.Subscribe(fun args ->
let (MsgValue r) = fn args
Dispatcher.dispatch node r)

node.SetHandler(name, ValueSome handler)
event.AddHandler handler)
node.SetHandler(name, handler))
)
|> AttributeDefinitionStore.registerScalar

Expand All @@ -347,20 +341,15 @@ module Attributes =
SimpleScalarAttributeDefinition.CreateAttributeData(
ScalarAttributeComparers.noCompare,
(fun _ (newValueOpt: (unit -> unit) voption) node ->
let event = getEvent(node.Target)

match node.TryGetHandler(name) with
| ValueNone -> ()
| ValueSome handler -> event.RemoveHandler handler
| ValueSome handler -> handler.Dispose()

match newValueOpt with
| ValueNone -> node.SetHandler(name, ValueNone)

| ValueNone -> node.RemoveHandler(name)
| ValueSome(fn) ->
let handler = EventHandler(fun _ _ -> fn())

event.AddHandler handler
node.SetHandler(name, ValueSome handler))
let event = getEvent node.Target
node.SetHandler(name, event.Subscribe(fun _ -> fn())))
)

|> AttributeDefinitionStore.registerScalar
Expand Down
Loading

0 comments on commit 6de97c0

Please sign in to comment.