From bb0faaa847bb27a3727b5bf035e683a2a0bb8264 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 28 Nov 2024 16:29:39 +0000 Subject: [PATCH] Use EventAggregator to decouple exception handler and UI --- .../Bindings/ArcGISSelectionBinding.cs | 5 +- .../Bindings/ArcGISSendBinding.cs | 9 +- .../Bindings/BasicConnectorBinding.cs | 4 +- .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../Bindings/AutocadBasicConnectorBinding.cs | 3 +- .../Bindings/AutocadSelectionBinding.cs | 4 +- .../Bindings/AutocadSendBaseBinding.cs | 3 +- .../Bindings/AutocadSendBinding.cs | 2 + .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../Bindings/Civil3dSendBinding.cs | 2 + .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../Bindings/BasicConnectorBindingRevit.cs | 5 +- .../Bindings/RevitSendBinding.cs | 4 +- .../Bindings/SelectionBinding.cs | 3 +- .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../Bindings/RhinoBasicConnectorBinding.cs | 5 +- .../Bindings/RhinoSendBinding.cs | 5 +- .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../Bindings/TeklaBasicConnectorBinding.cs | 3 +- .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../packages.lock.json | 6 + .../Bridge/TopLevelExceptionHandlerTests.cs | 49 ++++---- .../packages.lock.json | 6 + .../packages.lock.json | 12 ++ .../Bindings/OperationProgressManager.cs | 4 +- .../TopLevelExceptionHandlerBinding.cs | 4 - .../Bridge/BrowserBridge.cs | 20 +++- .../Bridge/IBrowserBridge.cs | 2 - .../Bridge/TopLevelExceptionHandler.cs | 109 +++++++++++++----- .../ContainerRegistration.cs | 5 +- .../Speckle.Connectors.DUI.csproj | 1 + .../Speckle.Connectors.DUI/packages.lock.json | 6 + Directory.Packages.props | 3 +- 46 files changed, 299 insertions(+), 99 deletions(-) diff --git a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/ArcGISSelectionBinding.cs b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/ArcGISSelectionBinding.cs index d243d12b7..239ea1115 100644 --- a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/ArcGISSelectionBinding.cs +++ b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/ArcGISSelectionBinding.cs @@ -12,15 +12,14 @@ public class ArcGISSelectionBinding : ISelectionBinding public string Name => "selectionBinding"; public IBrowserBridge Parent { get; } - public ArcGISSelectionBinding(IBrowserBridge parent, MapMembersUtils mapMemberUtils) + public ArcGISSelectionBinding(IBrowserBridge parent, MapMembersUtils mapMemberUtils, ITopLevelExceptionHandler topLevelExceptionHandler) { _mapMemberUtils = mapMemberUtils; Parent = parent; - var topLevelHandler = parent.TopLevelExceptionHandler; // example: https://github.com/Esri/arcgis-pro-sdk-community-samples/blob/master/Map-Authoring/QueryBuilderControl/DefinitionQueryDockPaneViewModel.cs // MapViewEventArgs args = new(MapView.Active); - TOCSelectionChangedEvent.Subscribe(_ => topLevelHandler.CatchUnhandled(OnSelectionChanged), true); + TOCSelectionChangedEvent.Subscribe(_ => topLevelExceptionHandler.CatchUnhandled(OnSelectionChanged), true); } private void OnSelectionChanged() diff --git a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/ArcGISSendBinding.cs b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/ArcGISSendBinding.cs index 7082ee687..288b90c9d 100644 --- a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/ArcGISSendBinding.cs +++ b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/ArcGISSendBinding.cs @@ -66,6 +66,7 @@ public ArcGISSendBinding( IOperationProgressManager operationProgressManager, ILogger logger, IArcGISConversionSettingsFactory arcGisConversionSettingsFactory, + ITopLevelExceptionHandler topLevelExceptionHandler, MapMembersUtils mapMemberUtils ) { @@ -76,7 +77,7 @@ MapMembersUtils mapMemberUtils _sendConversionCache = sendConversionCache; _operationProgressManager = operationProgressManager; _logger = logger; - _topLevelExceptionHandler = parent.TopLevelExceptionHandler; + _topLevelExceptionHandler = topLevelExceptionHandler; _arcGISConversionSettingsFactory = arcGisConversionSettingsFactory; _mapMemberUtils = mapMemberUtils; @@ -190,7 +191,7 @@ private void SubscribeToAnyDataSourceChange(Table layerTable) { RowCreatedEvent.Subscribe( (args) => - Parent.TopLevelExceptionHandler.FireAndForget(async () => + _topLevelExceptionHandler.FireAndForget(async () => { await OnRowChanged(args).ConfigureAwait(false); }), @@ -198,7 +199,7 @@ private void SubscribeToAnyDataSourceChange(Table layerTable) ); RowChangedEvent.Subscribe( (args) => - Parent.TopLevelExceptionHandler.FireAndForget(async () => + _topLevelExceptionHandler.FireAndForget(async () => { await OnRowChanged(args).ConfigureAwait(false); }), @@ -206,7 +207,7 @@ private void SubscribeToAnyDataSourceChange(Table layerTable) ); RowDeletedEvent.Subscribe( (args) => - Parent.TopLevelExceptionHandler.FireAndForget(async () => + _topLevelExceptionHandler.FireAndForget(async () => { await OnRowChanged(args).ConfigureAwait(false); }), diff --git a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/BasicConnectorBinding.cs b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/BasicConnectorBinding.cs index 89f04d1f6..5744735a9 100644 --- a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/BasicConnectorBinding.cs +++ b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/BasicConnectorBinding.cs @@ -21,7 +21,7 @@ public class BasicConnectorBinding : IBasicConnectorBinding private readonly DocumentModelStore _store; private readonly ISpeckleApplication _speckleApplication; - public BasicConnectorBinding(DocumentModelStore store, IBrowserBridge parent, ISpeckleApplication speckleApplication) + public BasicConnectorBinding(DocumentModelStore store, IBrowserBridge parent, ISpeckleApplication speckleApplication, ITopLevelExceptionHandler topLevelExceptionHandler) { _store = store; _speckleApplication = speckleApplication; @@ -29,7 +29,7 @@ public BasicConnectorBinding(DocumentModelStore store, IBrowserBridge parent, IS Commands = new BasicConnectorBindingCommands(parent); _store.DocumentChanged += (_, _) => - parent.TopLevelExceptionHandler.FireAndForget(async () => + topLevelExceptionHandler.FireAndForget(async () => { await Commands.NotifyDocumentChanged().ConfigureAwait(false); }); diff --git a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/packages.lock.json b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/packages.lock.json index 5f273fe0c..f04d83729 100644 --- a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/packages.lock.json +++ b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/packages.lock.json @@ -166,6 +166,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -240,6 +245,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Autocad/Speckle.Connectors.Autocad2022/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Autocad2022/packages.lock.json index 90cb7fe9a..4927a144b 100644 --- a/Connectors/Autocad/Speckle.Connectors.Autocad2022/packages.lock.json +++ b/Connectors/Autocad/Speckle.Connectors.Autocad2022/packages.lock.json @@ -164,6 +164,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -273,6 +278,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Autocad/Speckle.Connectors.Autocad2023/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Autocad2023/packages.lock.json index 5ce5caae0..61597c899 100644 --- a/Connectors/Autocad/Speckle.Connectors.Autocad2023/packages.lock.json +++ b/Connectors/Autocad/Speckle.Connectors.Autocad2023/packages.lock.json @@ -164,6 +164,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -273,6 +278,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Autocad/Speckle.Connectors.Autocad2024/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Autocad2024/packages.lock.json index c12eb3cba..9cc4fdf0f 100644 --- a/Connectors/Autocad/Speckle.Connectors.Autocad2024/packages.lock.json +++ b/Connectors/Autocad/Speckle.Connectors.Autocad2024/packages.lock.json @@ -164,6 +164,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -273,6 +278,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Autocad/Speckle.Connectors.Autocad2025/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Autocad2025/packages.lock.json index 94d9d3057..3b2f4305a 100644 --- a/Connectors/Autocad/Speckle.Connectors.Autocad2025/packages.lock.json +++ b/Connectors/Autocad/Speckle.Connectors.Autocad2025/packages.lock.json @@ -155,6 +155,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -229,6 +234,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadBasicConnectorBinding.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadBasicConnectorBinding.cs index 552c43aaf..12d69566e 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadBasicConnectorBinding.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadBasicConnectorBinding.cs @@ -31,6 +31,7 @@ public AutocadBasicConnectorBinding( IAccountManager accountManager, ISpeckleApplication speckleApplication, ILogger logger, + ITopLevelExceptionHandler topLevelExceptionHandler, IThreadContext threadContext ) { @@ -40,7 +41,7 @@ IThreadContext threadContext _speckleApplication = speckleApplication; Commands = new BasicConnectorBindingCommands(parent); _store.DocumentChanged += (_, _) => - parent.TopLevelExceptionHandler.FireAndForget(async () => + topLevelExceptionHandler.FireAndForget(async () => { await Commands.NotifyDocumentChanged().ConfigureAwait(false); }); diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSelectionBinding.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSelectionBinding.cs index 0af057595..d323156f0 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSelectionBinding.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSelectionBinding.cs @@ -18,9 +18,9 @@ public class AutocadSelectionBinding : ISelectionBinding public IBrowserBridge Parent { get; } - public AutocadSelectionBinding(IBrowserBridge parent, IThreadContext threadContext) + public AutocadSelectionBinding(IBrowserBridge parent, IThreadContext threadContext, ITopLevelExceptionHandler topLevelExceptionHandler) { - _topLevelExceptionHandler = parent.TopLevelExceptionHandler; + _topLevelExceptionHandler = topLevelExceptionHandler; Parent = parent; _threadContext = threadContext; diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSendBaseBinding.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSendBaseBinding.cs index cf2a9b659..6aa6756b0 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSendBaseBinding.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSendBaseBinding.cs @@ -60,6 +60,7 @@ protected AutocadSendBaseBinding( IOperationProgressManager operationProgressManager, ILogger logger, ISpeckleApplication speckleApplication, + ITopLevelExceptionHandler topLevelExceptionHandler, IThreadContext threadContext ) { @@ -73,7 +74,7 @@ IThreadContext threadContext _logger = logger; _speckleApplication = speckleApplication; _threadContext = threadContext; - _topLevelExceptionHandler = parent.TopLevelExceptionHandler; + _topLevelExceptionHandler =topLevelExceptionHandler; Parent = parent; Commands = new SendBindingUICommands(parent); diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSendBinding.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSendBinding.cs index ddd5c223c..65b14ab1a 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSendBinding.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSendBinding.cs @@ -30,6 +30,7 @@ public AutocadSendBinding( ILogger logger, IAutocadConversionSettingsFactory autocadConversionSettingsFactory, ISpeckleApplication speckleApplication, + ITopLevelExceptionHandler topLevelExceptionHandler, IThreadContext threadContext ) : base( @@ -43,6 +44,7 @@ IThreadContext threadContext operationProgressManager, logger, speckleApplication, + topLevelExceptionHandler, threadContext ) { diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3d2022/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Civil3d2022/packages.lock.json index f32ba4a78..6d44b1c6b 100644 --- a/Connectors/Autocad/Speckle.Connectors.Civil3d2022/packages.lock.json +++ b/Connectors/Autocad/Speckle.Connectors.Civil3d2022/packages.lock.json @@ -173,6 +173,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -282,6 +287,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3d2023/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Civil3d2023/packages.lock.json index 26e3bfefb..d30ee8ee2 100644 --- a/Connectors/Autocad/Speckle.Connectors.Civil3d2023/packages.lock.json +++ b/Connectors/Autocad/Speckle.Connectors.Civil3d2023/packages.lock.json @@ -173,6 +173,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -282,6 +287,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3d2024/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Civil3d2024/packages.lock.json index e3fa8c79f..5474ff59a 100644 --- a/Connectors/Autocad/Speckle.Connectors.Civil3d2024/packages.lock.json +++ b/Connectors/Autocad/Speckle.Connectors.Civil3d2024/packages.lock.json @@ -173,6 +173,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -282,6 +287,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3d2025/packages.lock.json b/Connectors/Autocad/Speckle.Connectors.Civil3d2025/packages.lock.json index 7f9f5b453..bc67aa30d 100644 --- a/Connectors/Autocad/Speckle.Connectors.Civil3d2025/packages.lock.json +++ b/Connectors/Autocad/Speckle.Connectors.Civil3d2025/packages.lock.json @@ -164,6 +164,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -238,6 +243,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Bindings/Civil3dSendBinding.cs b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Bindings/Civil3dSendBinding.cs index 4b26c74ef..57a120595 100644 --- a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Bindings/Civil3dSendBinding.cs +++ b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Bindings/Civil3dSendBinding.cs @@ -34,6 +34,7 @@ public Civil3dSendBinding( ICivil3dConversionSettingsFactory civil3dConversionSettingsFactory, IAutocadConversionSettingsFactory autocadConversionSettingsFactory, ISpeckleApplication speckleApplication, + ITopLevelExceptionHandler topLevelExceptionHandler, IThreadContext threadContext ) : base( @@ -47,6 +48,7 @@ IThreadContext threadContext operationProgressManager, logger, speckleApplication, + topLevelExceptionHandler, threadContext ) { diff --git a/Connectors/Revit/Speckle.Connectors.Revit2022/packages.lock.json b/Connectors/Revit/Speckle.Connectors.Revit2022/packages.lock.json index 647bacc38..9e9b70a59 100644 --- a/Connectors/Revit/Speckle.Connectors.Revit2022/packages.lock.json +++ b/Connectors/Revit/Speckle.Connectors.Revit2022/packages.lock.json @@ -192,6 +192,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -301,6 +306,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Revit/Speckle.Connectors.Revit2023/packages.lock.json b/Connectors/Revit/Speckle.Connectors.Revit2023/packages.lock.json index d7f833c1e..07db1b489 100644 --- a/Connectors/Revit/Speckle.Connectors.Revit2023/packages.lock.json +++ b/Connectors/Revit/Speckle.Connectors.Revit2023/packages.lock.json @@ -192,6 +192,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -301,6 +306,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Revit/Speckle.Connectors.Revit2024/packages.lock.json b/Connectors/Revit/Speckle.Connectors.Revit2024/packages.lock.json index 6e34d1d52..720697d9d 100644 --- a/Connectors/Revit/Speckle.Connectors.Revit2024/packages.lock.json +++ b/Connectors/Revit/Speckle.Connectors.Revit2024/packages.lock.json @@ -192,6 +192,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -301,6 +306,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Revit/Speckle.Connectors.Revit2025/packages.lock.json b/Connectors/Revit/Speckle.Connectors.Revit2025/packages.lock.json index 023ab26c3..c595be280 100644 --- a/Connectors/Revit/Speckle.Connectors.Revit2025/packages.lock.json +++ b/Connectors/Revit/Speckle.Connectors.Revit2025/packages.lock.json @@ -177,6 +177,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -251,6 +256,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/BasicConnectorBindingRevit.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/BasicConnectorBindingRevit.cs index 6691eb77b..0e7805b76 100644 --- a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/BasicConnectorBindingRevit.cs +++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/BasicConnectorBindingRevit.cs @@ -26,7 +26,8 @@ public BasicConnectorBindingRevit( DocumentModelStore store, IBrowserBridge parent, RevitContext revitContext, - ISpeckleApplication speckleApplication + ISpeckleApplication speckleApplication, + ITopLevelExceptionHandler topLevelExceptionHandler ) { Name = "baseBinding"; @@ -38,7 +39,7 @@ ISpeckleApplication speckleApplication // POC: event binding? _store.DocumentChanged += (_, _) => - parent.TopLevelExceptionHandler.FireAndForget(async () => + topLevelExceptionHandler.FireAndForget(async () => { await Commands.NotifyDocumentChanged().ConfigureAwait(false); }); diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitSendBinding.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitSendBinding.cs index 48cd80243..d36a240af 100644 --- a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitSendBinding.cs +++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitSendBinding.cs @@ -59,7 +59,8 @@ public RevitSendBinding( ILogger logger, ElementUnpacker elementUnpacker, IRevitConversionSettingsFactory revitConversionSettingsFactory, - ISpeckleApplication speckleApplication + ISpeckleApplication speckleApplication, + ITopLevelExceptionHandler topLevelExceptionHandler ) : base("sendBinding", store, bridge, revitContext) { @@ -73,7 +74,6 @@ ISpeckleApplication speckleApplication _elementUnpacker = elementUnpacker; _revitConversionSettingsFactory = revitConversionSettingsFactory; _speckleApplication = speckleApplication; - var topLevelExceptionHandler = Parent.TopLevelExceptionHandler; Commands = new SendBindingUICommands(bridge); // TODO expiry events diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/SelectionBinding.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/SelectionBinding.cs index eabb03f7f..a5903928f 100644 --- a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/SelectionBinding.cs +++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/SelectionBinding.cs @@ -17,6 +17,7 @@ public SelectionBinding( RevitContext revitContext, DocumentModelStore store, IAppIdleManager revitIdleManager, + ITopLevelExceptionHandler topLevelExceptionHandler, IBrowserBridge parent ) : base("selectionBinding", store, parent, revitContext) @@ -24,7 +25,7 @@ IBrowserBridge parent #if REVIT2022 // NOTE: getting the selection data should be a fast function all, even for '000s of elements - and having a timer hitting it every 1s is ok. _selectionTimer = new System.Timers.Timer(1000); - _selectionTimer.Elapsed += (_, _) => parent.TopLevelExceptionHandler.CatchUnhandled(OnSelectionChanged); + _selectionTimer.Elapsed += (_, _) => topLevelExceptionHandler.CatchUnhandled(OnSelectionChanged); _selectionTimer.Start(); #else diff --git a/Connectors/Rhino/Speckle.Connectors.Rhino7/packages.lock.json b/Connectors/Rhino/Speckle.Connectors.Rhino7/packages.lock.json index 4ad0873ae..fcb6d4454 100644 --- a/Connectors/Rhino/Speckle.Connectors.Rhino7/packages.lock.json +++ b/Connectors/Rhino/Speckle.Connectors.Rhino7/packages.lock.json @@ -173,6 +173,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -282,6 +287,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Rhino/Speckle.Connectors.Rhino8/packages.lock.json b/Connectors/Rhino/Speckle.Connectors.Rhino8/packages.lock.json index 5c61db061..493e3f93c 100644 --- a/Connectors/Rhino/Speckle.Connectors.Rhino8/packages.lock.json +++ b/Connectors/Rhino/Speckle.Connectors.Rhino8/packages.lock.json @@ -173,6 +173,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -282,6 +287,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Bindings/RhinoBasicConnectorBinding.cs b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Bindings/RhinoBasicConnectorBinding.cs index 432c2c81f..0cf61e606 100644 --- a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Bindings/RhinoBasicConnectorBinding.cs +++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Bindings/RhinoBasicConnectorBinding.cs @@ -26,7 +26,8 @@ public RhinoBasicConnectorBinding( DocumentModelStore store, IBrowserBridge parent, ISendConversionCache sendConversionCache, - ISpeckleApplication speckleApplication + ISpeckleApplication speckleApplication, + ITopLevelExceptionHandler topLevelExceptionHandler ) { _store = store; @@ -36,7 +37,7 @@ ISpeckleApplication speckleApplication Commands = new BasicConnectorBindingCommands(parent); _store.DocumentChanged += (_, _) => - parent.TopLevelExceptionHandler.FireAndForget(async () => + topLevelExceptionHandler.FireAndForget(async () => { await Commands.NotifyDocumentChanged().ConfigureAwait(false); // Note: this prevents scaling issues when copy-pasting from one rhino doc to another in the same session. diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Bindings/RhinoSendBinding.cs b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Bindings/RhinoSendBinding.cs index 1d4e454b8..36a90a8c2 100644 --- a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Bindings/RhinoSendBinding.cs +++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Bindings/RhinoSendBinding.cs @@ -64,7 +64,8 @@ public RhinoSendBinding( ILogger logger, IRhinoConversionSettingsFactory rhinoConversionSettingsFactory, ISpeckleApplication speckleApplication, - ISdkActivityFactory activityFactory + ISdkActivityFactory activityFactory, + ITopLevelExceptionHandler topLevelExceptionHandler ) { _store = store; @@ -77,7 +78,7 @@ ISdkActivityFactory activityFactory _logger = logger; _rhinoConversionSettingsFactory = rhinoConversionSettingsFactory; _speckleApplication = speckleApplication; - _topLevelExceptionHandler = parent.TopLevelExceptionHandler.Parent.TopLevelExceptionHandler; + _topLevelExceptionHandler = topLevelExceptionHandler; Parent = parent; Commands = new SendBindingUICommands(parent); // POC: Commands are tightly coupled with their bindings, at least for now, saves us injecting a factory. _activityFactory = activityFactory; diff --git a/Connectors/Tekla/Speckle.Connector.Tekla2023/packages.lock.json b/Connectors/Tekla/Speckle.Connector.Tekla2023/packages.lock.json index 26ec29612..a895c9f4a 100644 --- a/Connectors/Tekla/Speckle.Connector.Tekla2023/packages.lock.json +++ b/Connectors/Tekla/Speckle.Connector.Tekla2023/packages.lock.json @@ -212,6 +212,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -341,6 +346,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Tekla/Speckle.Connector.Tekla2024/packages.lock.json b/Connectors/Tekla/Speckle.Connector.Tekla2024/packages.lock.json index 3225e90b7..63ac3df21 100644 --- a/Connectors/Tekla/Speckle.Connector.Tekla2024/packages.lock.json +++ b/Connectors/Tekla/Speckle.Connector.Tekla2024/packages.lock.json @@ -231,6 +231,11 @@ "resolved": "0.11.4", "contentHash": "IC1h5g0NeJGHIUgzM1P82ld57knhP0IcQfrYITDPXlNpMYGUrsG5TxuaWTjaeqDNQMBDNZkB8L0rBnwsY6JHuQ==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -422,6 +427,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Connectors/Tekla/Speckle.Connector.TeklaShared/Bindings/TeklaBasicConnectorBinding.cs b/Connectors/Tekla/Speckle.Connector.TeklaShared/Bindings/TeklaBasicConnectorBinding.cs index bc1449c7c..60f3f13a9 100644 --- a/Connectors/Tekla/Speckle.Connector.TeklaShared/Bindings/TeklaBasicConnectorBinding.cs +++ b/Connectors/Tekla/Speckle.Connector.TeklaShared/Bindings/TeklaBasicConnectorBinding.cs @@ -25,6 +25,7 @@ public TeklaBasicConnectorBinding( ISpeckleApplication speckleApplication, DocumentModelStore store, ILogger logger, + ITopLevelExceptionHandler topLevelExceptionHandler, TSM.Model model ) { @@ -35,7 +36,7 @@ TSM.Model model _model = model; Commands = new BasicConnectorBindingCommands(parent); _store.DocumentChanged += (_, _) => - parent.TopLevelExceptionHandler.FireAndForget(async () => + topLevelExceptionHandler.FireAndForget(async () => { await Commands.NotifyDocumentChanged().ConfigureAwait(false); }); diff --git a/Converters/Autocad/Speckle.Converters.Autocad2024/packages.lock.json b/Converters/Autocad/Speckle.Converters.Autocad2024/packages.lock.json index 77afeebe8..cfd016d4a 100644 --- a/Converters/Autocad/Speckle.Converters.Autocad2024/packages.lock.json +++ b/Converters/Autocad/Speckle.Converters.Autocad2024/packages.lock.json @@ -164,6 +164,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -273,6 +278,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Converters/Autocad/Speckle.Converters.Autocad2025/packages.lock.json b/Converters/Autocad/Speckle.Converters.Autocad2025/packages.lock.json index 08ccad09b..2c553583f 100644 --- a/Converters/Autocad/Speckle.Converters.Autocad2025/packages.lock.json +++ b/Converters/Autocad/Speckle.Converters.Autocad2025/packages.lock.json @@ -155,6 +155,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -229,6 +234,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/Converters/Civil3d/Speckle.Converters.Civil3d2025/packages.lock.json b/Converters/Civil3d/Speckle.Converters.Civil3d2025/packages.lock.json index 247926a4a..3bc6b830d 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3d2025/packages.lock.json +++ b/Converters/Civil3d/Speckle.Converters.Civil3d2025/packages.lock.json @@ -164,6 +164,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -238,6 +243,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/DUI3/Speckle.Connectors.DUI.Tests/Bridge/TopLevelExceptionHandlerTests.cs b/DUI3/Speckle.Connectors.DUI.Tests/Bridge/TopLevelExceptionHandlerTests.cs index 8ba16dc14..674dbd850 100644 --- a/DUI3/Speckle.Connectors.DUI.Tests/Bridge/TopLevelExceptionHandlerTests.cs +++ b/DUI3/Speckle.Connectors.DUI.Tests/Bridge/TopLevelExceptionHandlerTests.cs @@ -2,7 +2,7 @@ using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; -using Speckle.Connectors.DUI.Bindings; +using Speckle.Connectors.Common.Threading; using Speckle.Connectors.DUI.Bridge; using Speckle.Testing; @@ -14,8 +14,8 @@ public class TopLevelExceptionHandlerTests : MoqTest public void CatchUnhandledAction_Happy() { var logger = Create>(MockBehavior.Loose); - var bridge = Create(); - var sut = new TopLevelExceptionHandler(logger.Object, bridge.Object); + var eventAggregator = Create(); + var sut = new TopLevelExceptionHandler(logger.Object, eventAggregator.Object); sut.CatchUnhandled(() => { }); } @@ -24,13 +24,12 @@ public void CatchUnhandledAction_Happy() public void CatchUnhandledAction_Exception() { var logger = Create>(MockBehavior.Loose); - var bridge = Create(); + var eventAggregator = Create(); - bridge - .Setup(x => x.Send(BasicConnectorBindingCommands.SET_GLOBAL_NOTIFICATION, It.IsAny(), default)) - .Returns(Task.CompletedTask); + eventAggregator.Setup(x => x.GetEvent()) + .Returns(new ExceptionEvent(Create().Object)); - var sut = new TopLevelExceptionHandler(logger.Object, bridge.Object); + var sut = new TopLevelExceptionHandler(logger.Object, eventAggregator.Object); sut.CatchUnhandled(() => throw new InvalidOperationException()); } @@ -40,8 +39,8 @@ public void CatchUnhandledFunc_Happy() { var val = 2; var logger = Create>(MockBehavior.Loose); - var bridge = Create(); - var sut = new TopLevelExceptionHandler(logger.Object, bridge.Object); + var eventAggregator = Create(); + var sut = new TopLevelExceptionHandler(logger.Object, eventAggregator.Object); var returnVal = sut.CatchUnhandled(() => val); returnVal.Value.Should().Be(val); @@ -53,13 +52,12 @@ public void CatchUnhandledFunc_Happy() public void CatchUnhandledFunc_Exception() { var logger = Create>(MockBehavior.Loose); - var bridge = Create(); + var eventAggregator = Create(); - bridge - .Setup(x => x.Send(BasicConnectorBindingCommands.SET_GLOBAL_NOTIFICATION, It.IsAny(), default)) - .Returns(Task.CompletedTask); + eventAggregator.Setup(x => x.GetEvent()) + .Returns(new ExceptionEvent(Create().Object)); - var sut = new TopLevelExceptionHandler(logger.Object, bridge.Object); + var sut = new TopLevelExceptionHandler(logger.Object, eventAggregator.Object); var returnVal = sut.CatchUnhandled((Func)(() => throw new InvalidOperationException())); returnVal.Value.Should().BeNull(); @@ -71,8 +69,8 @@ public void CatchUnhandledFunc_Exception() public void CatchUnhandledFunc_Exception_Fatal() { var logger = Create>(MockBehavior.Loose); - var bridge = Create(); - var sut = new TopLevelExceptionHandler(logger.Object, bridge.Object); + var eventAggregator = Create(); + var sut = new TopLevelExceptionHandler(logger.Object, eventAggregator.Object); var exception = Assert.Throws( () => sut.CatchUnhandled(new Func(() => throw new AppDomainUnloadedException())) @@ -85,8 +83,8 @@ public async Task CatchUnhandledFuncAsync_Happy() { var val = 2; var logger = Create>(MockBehavior.Loose); - var bridge = Create(); - var sut = new TopLevelExceptionHandler(logger.Object, bridge.Object); + var eventAggregator = Create(); + var sut = new TopLevelExceptionHandler(logger.Object, eventAggregator.Object); var returnVal = await sut.CatchUnhandledAsync(() => Task.FromResult(val)); returnVal.Value.Should().Be(val); @@ -98,13 +96,12 @@ public async Task CatchUnhandledFuncAsync_Happy() public async Task CatchUnhandledFuncAsync_Exception() { var logger = Create>(MockBehavior.Loose); - var bridge = Create(); + var eventAggregator = Create(); - bridge - .Setup(x => x.Send(BasicConnectorBindingCommands.SET_GLOBAL_NOTIFICATION, It.IsAny(), default)) - .Returns(Task.CompletedTask); + eventAggregator.Setup(x => x.GetEvent()) + .Returns(new ExceptionEvent(Create().Object)); - var sut = new TopLevelExceptionHandler(logger.Object, bridge.Object); + var sut = new TopLevelExceptionHandler(logger.Object, eventAggregator.Object); var returnVal = await sut.CatchUnhandledAsync(new Func>(() => throw new InvalidOperationException())); returnVal.Value.Should().BeNull(); @@ -116,8 +113,8 @@ public async Task CatchUnhandledFuncAsync_Exception() public void CatchUnhandledFuncAsync_Exception_Fatal() { var logger = Create>(MockBehavior.Loose); - var bridge = Create(); - var sut = new TopLevelExceptionHandler(logger.Object, bridge.Object); + var eventAggregator = Create(); + var sut = new TopLevelExceptionHandler(logger.Object, eventAggregator.Object); var exception = Assert.ThrowsAsync( async () => await sut.CatchUnhandledAsync(new Func>(() => throw new AppDomainUnloadedException())) diff --git a/DUI3/Speckle.Connectors.DUI.Tests/packages.lock.json b/DUI3/Speckle.Connectors.DUI.Tests/packages.lock.json index 0b906a217..9b95cfa6d 100644 --- a/DUI3/Speckle.Connectors.DUI.Tests/packages.lock.json +++ b/DUI3/Speckle.Connectors.DUI.Tests/packages.lock.json @@ -236,6 +236,11 @@ "resolved": "13.0.1", "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -333,6 +338,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/DUI3/Speckle.Connectors.DUI.WebView/packages.lock.json b/DUI3/Speckle.Connectors.DUI.WebView/packages.lock.json index 73b4c347b..5466b56da 100644 --- a/DUI3/Speckle.Connectors.DUI.WebView/packages.lock.json +++ b/DUI3/Speckle.Connectors.DUI.WebView/packages.lock.json @@ -164,6 +164,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -273,6 +278,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" @@ -500,6 +506,11 @@ "resolved": "8.0.0", "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" }, + "Prism.Events": { + "type": "Transitive", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.DoubleNumerics": { "type": "Transitive", "resolved": "4.0.1", @@ -574,6 +585,7 @@ "type": "Project", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, )", + "Prism.Events": "[9.0.537, )", "Speckle.Connectors.Common": "[1.0.0, )", "Speckle.Sdk": "[3.1.0-dev.200, )", "Speckle.Sdk.Dependencies": "[3.1.0-dev.200, )" diff --git a/DUI3/Speckle.Connectors.DUI/Bindings/OperationProgressManager.cs b/DUI3/Speckle.Connectors.DUI/Bindings/OperationProgressManager.cs index 992aaf669..a0da34e8b 100644 --- a/DUI3/Speckle.Connectors.DUI/Bindings/OperationProgressManager.cs +++ b/DUI3/Speckle.Connectors.DUI/Bindings/OperationProgressManager.cs @@ -11,7 +11,7 @@ namespace Speckle.Connectors.DUI.Bindings; /// This class requires a specific bridge in its binding, so registering it will create random bridge which we don't want to. /// [GenerateAutoInterface] -public class OperationProgressManager : IOperationProgressManager +public class OperationProgressManager(ITopLevelExceptionHandler topLevelExceptionHandler) : IOperationProgressManager { private class NonUIThreadProgress(Action handler) : IProgress { @@ -30,7 +30,7 @@ CancellationToken cancellationToken ) { var progress = new NonUIThreadProgress(args => - bridge.TopLevelExceptionHandler.FireAndForget( + topLevelExceptionHandler.FireAndForget( () => SetModelProgress( bridge, diff --git a/DUI3/Speckle.Connectors.DUI/Bindings/TopLevelExceptionHandlerBinding.cs b/DUI3/Speckle.Connectors.DUI/Bindings/TopLevelExceptionHandlerBinding.cs index 617722d69..2fec4a7ca 100644 --- a/DUI3/Speckle.Connectors.DUI/Bindings/TopLevelExceptionHandlerBinding.cs +++ b/DUI3/Speckle.Connectors.DUI/Bindings/TopLevelExceptionHandlerBinding.cs @@ -2,10 +2,6 @@ namespace Speckle.Connectors.DUI.Bindings; -/// -/// Simple binding that can be injected into non- services to get access to the -/// -/// public sealed class TopLevelExceptionHandlerBinding(IBrowserBridge parent) : IBinding { public string Name => "topLevelExceptionHandlerBinding"; diff --git a/DUI3/Speckle.Connectors.DUI/Bridge/BrowserBridge.cs b/DUI3/Speckle.Connectors.DUI/Bridge/BrowserBridge.cs index 9249aa255..f7514e281 100644 --- a/DUI3/Speckle.Connectors.DUI/Bridge/BrowserBridge.cs +++ b/DUI3/Speckle.Connectors.DUI/Bridge/BrowserBridge.cs @@ -27,7 +27,9 @@ public sealed class BrowserBridge : IBrowserBridge /// private readonly ConcurrentDictionary _resultsStore = new(); - public ITopLevelExceptionHandler TopLevelExceptionHandler { get; } + + private readonly ITopLevelExceptionHandler _topLevelExceptionHandler; + private readonly ISpeckleEventAggregator _eventAggregator; private readonly IThreadContext _threadContext; private readonly IThreadOptions _threadOptions; @@ -60,18 +62,24 @@ public BrowserBridge( IThreadContext threadContext, IJsonSerializer jsonSerializer, ILogger logger, - ILogger topLogger, IBrowserScriptExecutor browserScriptExecutor, - IThreadOptions threadOptions - ) + IThreadOptions threadOptions, ISpeckleEventAggregator eventAggregator, ITopLevelExceptionHandler topLevelExceptionHandler) { _threadContext = threadContext; _jsonSerializer = jsonSerializer; _logger = logger; - TopLevelExceptionHandler = new TopLevelExceptionHandler(topLogger, this); // Capture the main thread's SynchronizationContext _browserScriptExecutor = browserScriptExecutor; _threadOptions = threadOptions; + _eventAggregator = eventAggregator; + _topLevelExceptionHandler = topLevelExceptionHandler; + eventAggregator.GetEvent().Subscribe(ex => + { + Send(BasicConnectorBindingCommands.SET_GLOBAL_NOTIFICATION, + new { type = ToastNotificationType.DANGER, title = "Unhandled Exception Occurred", description = ex.ToFormattedString(), autoClose = false } + ) + .ConfigureAwait(false); + }, ThreadOption.UIThread); } public void AssociateWithBinding(IBinding binding) @@ -108,7 +116,7 @@ public void RunMethod(string methodName, string requestId, string methodArgs) => _threadContext.RunOnThreadAsync( async () => { - var task = await TopLevelExceptionHandler + var task = await _topLevelExceptionHandler .CatchUnhandledAsync(async () => { var result = await ExecuteMethod(methodName, methodArgs).ConfigureAwait(false); diff --git a/DUI3/Speckle.Connectors.DUI/Bridge/IBrowserBridge.cs b/DUI3/Speckle.Connectors.DUI/Bridge/IBrowserBridge.cs index f968bf3ef..b4232f766 100644 --- a/DUI3/Speckle.Connectors.DUI/Bridge/IBrowserBridge.cs +++ b/DUI3/Speckle.Connectors.DUI/Bridge/IBrowserBridge.cs @@ -39,6 +39,4 @@ public interface IBrowserBridge /// Bridge was not initialized with a binding public Task Send(string eventName, T data, CancellationToken cancellationToken = default) where T : class; - - public ITopLevelExceptionHandler TopLevelExceptionHandler { get; } } diff --git a/DUI3/Speckle.Connectors.DUI/Bridge/TopLevelExceptionHandler.cs b/DUI3/Speckle.Connectors.DUI/Bridge/TopLevelExceptionHandler.cs index 569440a4e..1c5fb6397 100644 --- a/DUI3/Speckle.Connectors.DUI/Bridge/TopLevelExceptionHandler.cs +++ b/DUI3/Speckle.Connectors.DUI/Bridge/TopLevelExceptionHandler.cs @@ -1,8 +1,7 @@ using Microsoft.Extensions.Logging; -using Speckle.Connectors.DUI.Bindings; +using Speckle.Connectors.Common.Threading; using Speckle.InterfaceGenerator; using Speckle.Sdk; -using Speckle.Sdk.Models.Extensions; namespace Speckle.Connectors.DUI.Bridge; @@ -23,15 +22,15 @@ namespace Speckle.Connectors.DUI.Bridge; public sealed class TopLevelExceptionHandler : ITopLevelExceptionHandler { private readonly ILogger _logger; - public IBrowserBridge Parent { get; } + private readonly ISpeckleEventAggregator _eventAggregator; public string Name => nameof(TopLevelExceptionHandler); private const string UNHANDLED_LOGGER_TEMPLATE = "An unhandled Exception occured"; - internal TopLevelExceptionHandler(ILogger logger, IBrowserBridge bridge) + internal TopLevelExceptionHandler(ILogger logger, ISpeckleEventAggregator eventAggregator) { _logger = logger; - Parent = bridge; + _eventAggregator = eventAggregator; } /// @@ -70,13 +69,7 @@ public async Task CatchUnhandledAsync(Func function) catch (Exception ex) when (!ex.IsFatal()) { _logger.LogError(ex, UNHANDLED_LOGGER_TEMPLATE); - await SetGlobalNotification( - ToastNotificationType.DANGER, - "Unhandled Exception Occured", - ex.ToFormattedString(), - false - ) - .ConfigureAwait(false); + _eventAggregator.GetEvent().Publish(ex); return new(ex); } } @@ -99,13 +92,7 @@ public async Task> CatchUnhandledAsync(Func> function) catch (Exception ex) when (!ex.IsFatal()) { _logger.LogError(ex, UNHANDLED_LOGGER_TEMPLATE); - await SetGlobalNotification( - ToastNotificationType.DANGER, - "Unhandled Exception Occured", - ex.ToFormattedString(), - false - ) - .ConfigureAwait(false); + _eventAggregator.GetEvent().Publish(ex); return new(ex); } } @@ -126,18 +113,76 @@ await SetGlobalNotification( /// /// public async void FireAndForget(Func function) => await CatchUnhandledAsync(function).ConfigureAwait(false); +} + +public interface ISpeckleEventAggregator +{ + TEventType GetEvent() where TEventType : EventBase; +} +public class SpeckleEventAggregator : ISpeckleEventAggregator +{ + private readonly IServiceProvider _serviceProvider; + + + private readonly Dictionary _events = new(); + + public SpeckleEventAggregator(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public TEventType GetEvent() where TEventType : EventBase + { + lock (_events) + { + if (!_events.TryGetValue(typeof(TEventType), out var existingEvent)) + { + existingEvent = (TEventType)_serviceProvider.GetService(typeof(TEventType)); + _events[typeof(TEventType)] = existingEvent; + } + return (TEventType)existingEvent; + } + } +} + +public class ExceptionEvent(IThreadContext threadContext) : SpeckleEvent(threadContext); + +public class SpeckleEvent(IThreadContext threadContext) : PubSubEvent +{ + public override SubscriptionToken Subscribe(Action action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, + Predicate filter) + { + IDelegateReference actionReference = new DelegateReference(action, keepSubscriberReferenceAlive); + + EventSubscription subscription; + switch (threadOption) + { + case ThreadOption.PublisherThread: + subscription = new EventSubscription(actionReference); + break; + case ThreadOption.BackgroundThread: + subscription = new BackgroundEventSubscription(actionReference); + break; + case ThreadOption.UIThread: + subscription = new ThreadContextEventSubscription(actionReference, threadContext); + break; + default: + subscription = new EventSubscription(actionReference); + break; + } + + return InternalSubscribe(subscription); + + } +} + +public class ThreadContextEventSubscription : EventSubscription +{ + private readonly IThreadContext _threadContext; + public ThreadContextEventSubscription(IDelegateReference actionReference, IThreadContext threadContext) : base(actionReference) + { + _threadContext = threadContext; + } - private async Task SetGlobalNotification(ToastNotificationType type, string title, string message, bool autoClose) => - await Parent - .Send( - BasicConnectorBindingCommands.SET_GLOBAL_NOTIFICATION, //TODO: We could move these constants into a DUI3 constants static class - new - { - type, - title, - description = message, - autoClose - } - ) - .ConfigureAwait(false); + public override void InvokeAction(Action action) => _threadContext.RunOnMain(action); } diff --git a/DUI3/Speckle.Connectors.DUI/ContainerRegistration.cs b/DUI3/Speckle.Connectors.DUI/ContainerRegistration.cs index f922d234f..8b64a90b3 100644 --- a/DUI3/Speckle.Connectors.DUI/ContainerRegistration.cs +++ b/DUI3/Speckle.Connectors.DUI/ContainerRegistration.cs @@ -23,6 +23,7 @@ public static void AddDUI(this IServiceCollectio serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetAssembly(typeof(IdleCallManager))); serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetAssembly(typeof(IServerTransportFactory))); + serviceCollection.AddSingleton(sp => new SpeckleEventAggregator(sp)); } public static void RegisterTopLevelExceptionHandler(this IServiceCollection serviceCollection) @@ -31,8 +32,6 @@ public static void RegisterTopLevelExceptionHandler(this IServiceCollection serv sp.GetRequiredService() ); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(c => - c.GetRequiredService().Parent.TopLevelExceptionHandler - ); + serviceCollection.AddSingleton(); } } diff --git a/DUI3/Speckle.Connectors.DUI/Speckle.Connectors.DUI.csproj b/DUI3/Speckle.Connectors.DUI/Speckle.Connectors.DUI.csproj index e2909423f..2b842c1d7 100644 --- a/DUI3/Speckle.Connectors.DUI/Speckle.Connectors.DUI.csproj +++ b/DUI3/Speckle.Connectors.DUI/Speckle.Connectors.DUI.csproj @@ -12,6 +12,7 @@ + diff --git a/DUI3/Speckle.Connectors.DUI/packages.lock.json b/DUI3/Speckle.Connectors.DUI/packages.lock.json index c3cb0647e..79ffe1039 100644 --- a/DUI3/Speckle.Connectors.DUI/packages.lock.json +++ b/DUI3/Speckle.Connectors.DUI/packages.lock.json @@ -42,6 +42,12 @@ "resolved": "1.14.1", "contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ==" }, + "Prism.Events": { + "type": "Direct", + "requested": "[9.0.537, )", + "resolved": "9.0.537", + "contentHash": "Pzp5MGUuhAyKXZUbHVYNWLGF/eA3sScqDN6VrzbWlKj85R0IS0q+JXe99umynso2xhXAe+1jrQCCkgqmEFCBng==" + }, "Speckle.InterfaceGenerator": { "type": "Direct", "requested": "[0.9.6, )", diff --git a/Directory.Packages.props b/Directory.Packages.props index 04a20fc9d..9d668aa6a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -17,6 +17,7 @@ + @@ -48,4 +49,4 @@ - + \ No newline at end of file