From 228deefa2441df4da702fc3ca0a4462be6aa5d94 Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Thu, 17 Apr 2025 10:21:02 -0400 Subject: [PATCH 01/14] Create MauiGestureRecognizerEventsBinder.cs --- .../MauiGestureRecognizerEventsBinder.cs | 210 ++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs diff --git a/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs b/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs new file mode 100644 index 0000000000..cc2a00e35a --- /dev/null +++ b/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs @@ -0,0 +1,210 @@ +namespace Sentry.Maui.Internal; + +/// +/// Binds to +/// +public class MauiGestureRecognizerEventsBinder : IMauiElementEventBinder +{ + private Action _addBreadcrumb = null!; + + /// + /// Searches VisualElement for gesture recognizers to bind to + /// + public void Bind(VisualElement element, Action addBreadcrumb) + { + _addBreadcrumb ??= addBreadcrumb; + if (element is IGestureRecognizers recognizers) + { + foreach (var recognizer in recognizers.GestureRecognizers) + { + SetHooks(recognizer, true); + } + } + } + + + /// + /// Searches VisualElement for gesture recognizers to unbind from + /// + /// + public void UnBind(VisualElement element) + { + if (element is IGestureRecognizers recognizers) + { + foreach (var recognizer in recognizers.GestureRecognizers) + { + SetHooks(recognizer, false); + } + } + } + + + void SetHooks(IGestureRecognizer recognizer, bool add) + { + switch (recognizer) + { + case TapGestureRecognizer tap: + if (add) + { + tap.Tapped += OnTapGesture; + } + else + { + tap.Tapped -= OnTapGesture; + } + break; + + case SwipeGestureRecognizer swipe: + if (add) + { + swipe.Swiped += OnSwipeGesture; + } + else + { + swipe.Swiped -= OnSwipeGesture; + } + break; + + case PinchGestureRecognizer pinch: + if (add) + { + pinch.PinchUpdated += OnPinchGesture; + } + else + { + pinch.PinchUpdated -= OnPinchGesture; + } + break; + + case DragGestureRecognizer drag: + if (add) + { + drag.DragStarting += OnDragStartingGesture; + drag.DropCompleted += OnDropCompletedGesture; + } + else + { + drag.DragStarting -= OnDragStartingGesture; + drag.DropCompleted -= OnDropCompletedGesture; + } + break; + + case PanGestureRecognizer pan: + if (add) + { + pan.PanUpdated += OnPanGesture; + } + else + { + pan.PanUpdated -= OnPanGesture; + } + break; + + case PointerGestureRecognizer pointer: + if (add) + { + pointer.PointerEntered += OnPointerEnteredGesture; + pointer.PointerExited += OnPointerExitedGesture; + pointer.PointerMoved += OnPointerMovedGesture; + pointer.PointerPressed += OnPointerPressedGesture; + pointer.PointerReleased += OnPointerReleasedGesture; + } + else + { + pointer.PointerEntered -= OnPointerEnteredGesture; + pointer.PointerExited -= OnPointerExitedGesture; + pointer.PointerMoved -= OnPointerMovedGesture; + pointer.PointerPressed -= OnPointerPressedGesture; + pointer.PointerReleased -= OnPointerReleasedGesture; + } + break; + } + } + + private void OnPointerReleasedGesture(object? sender, PointerEventArgs e) => _addBreadcrumb.Invoke(new( + sender, + nameof(PointerGestureRecognizer.PointerReleased), + ToPointerData(e) + )); + + private void OnPointerPressedGesture(object? sender, PointerEventArgs e) => _addBreadcrumb.Invoke(new( + sender, + nameof(PointerGestureRecognizer.PointerPressed), + ToPointerData(e) + )); + + private void OnPointerMovedGesture(object? sender, PointerEventArgs e) => _addBreadcrumb.Invoke(new( + sender, + nameof(PointerGestureRecognizer.PointerMoved), + ToPointerData(e) + )); + + private void OnPointerExitedGesture(object? sender, PointerEventArgs e) => _addBreadcrumb.Invoke(new( + sender, + nameof(PointerGestureRecognizer.PointerExited), + ToPointerData(e) + )); + + private void OnPointerEnteredGesture(object? sender, PointerEventArgs e) => _addBreadcrumb.Invoke(new( + sender, + nameof(PointerGestureRecognizer.PointerEntered), + ToPointerData(e) + )); + + + static IEnumerable<(string Key, string Value)> ToPointerData(PointerEventArgs e) => + [ + // some of the data here may have some challenges being pulled out + #if ANDROID + ("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? String.Empty) + //("MotionEventActionButton", e.PlatformArgs?.MotionEvent.ActionButton.ToString() ?? String.Empty) + #elif IOS + ("State", e.PlatformArgs?.GestureRecognizer.State.ToString() ?? String.Empty) + //("ButtonMask", e.PlatformArgs?.GestureRecognizer.ButtonMask.ToString() ?? String.Empty) + #endif + ]; + + private void OnPanGesture(object? sender, PanUpdatedEventArgs e) => _addBreadcrumb.Invoke(new( + sender, + nameof(PanGestureRecognizer.PanUpdated), + [ + ("GestureId", e.GestureId.ToString()), + ("StatusType", e.StatusType.ToString()), + ("TotalX", e.TotalX.ToString()), + ("TotalY", e.TotalY.ToString()) + ] + )); + + private void OnDropCompletedGesture(object? sender, DropCompletedEventArgs e) => _addBreadcrumb.Invoke(new( + sender, + nameof(DragGestureRecognizer.DropCompleted) + )); + + private void OnDragStartingGesture(object? sender, DragStartingEventArgs e) => _addBreadcrumb.Invoke(new( + sender, + nameof(DragGestureRecognizer.DragStarting) + )); + + + private void OnPinchGesture(object? sender, PinchGestureUpdatedEventArgs e) => _addBreadcrumb.Invoke(new( + sender, + nameof(PinchGestureRecognizer.PinchUpdated), + [ + ("GestureStatus", e.Status.ToString()), + ("Scale", e.Scale.ToString()), + ("ScaleOrigin", e.ScaleOrigin.ToString()) + ] + )); + + private void OnSwipeGesture(object? sender, SwipedEventArgs e) => _addBreadcrumb.Invoke(new( + sender, + nameof(SwipeGestureRecognizer.Swiped), + [("Direction", e.Direction.ToString())] + )); + + private void OnTapGesture(object? sender, TappedEventArgs e) => _addBreadcrumb.Invoke(new( + sender, + nameof(TapGestureRecognizer.Tapped), + [("ButtonMask", e.Buttons.ToString())] + )); +} From e66308c6aef98fedbb34f70680f9ff20cba99a5a Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Thu, 17 Apr 2025 10:28:51 -0400 Subject: [PATCH 02/14] Wireup --- src/Sentry.Maui/SentryMauiAppBuilderExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Sentry.Maui/SentryMauiAppBuilderExtensions.cs b/src/Sentry.Maui/SentryMauiAppBuilderExtensions.cs index b10eab38d7..87385641d9 100644 --- a/src/Sentry.Maui/SentryMauiAppBuilderExtensions.cs +++ b/src/Sentry.Maui/SentryMauiAppBuilderExtensions.cs @@ -57,8 +57,8 @@ public static MauiAppBuilder UseSentry(this MauiAppBuilder builder, services.AddSingleton(); services.AddSingleton(); - services.TryAddSingleton(); - + services.AddSingleton(); + services.AddSingleton(); services.AddSentry(); builder.RegisterMauiEventsBinder(); From d2cb84fb892b2efbb0eaba5db661a5ed0e10293d Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Thu, 17 Apr 2025 14:40:02 +0000 Subject: [PATCH 03/14] Format code --- .../MauiGestureRecognizerEventsBinder.cs | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs b/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs index cc2a00e35a..b4677b7198 100644 --- a/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs +++ b/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs @@ -39,7 +39,7 @@ public void UnBind(VisualElement element) } - void SetHooks(IGestureRecognizer recognizer, bool add) + private void SetHooks(IGestureRecognizer recognizer, bool add) { switch (recognizer) { @@ -152,7 +152,41 @@ private void OnPointerEnteredGesture(object? sender, PointerEventArgs e) => _add )); + +<<<<<<< TODO: Unmerged change from project 'Sentry.Maui(net8.0-android34.0)', Before: + static IEnumerable<(string Key, string Value)> ToPointerData(PointerEventArgs e) => + [ + // some of the data here may have some challenges being pulled out + #if ANDROID + ("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? String.Empty) +======= + private static IEnumerable<(string Key, string Value)> ToPointerData(PointerEventArgs e) => + [ + // some of the data here may have some challenges being pulled out + #if ANDROID + ("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? string.Empty) +>>>>>>> After + +<<<<<<< TODO: Unmerged change from project 'Sentry.Maui(net8.0-ios17.0)', Before: static IEnumerable<(string Key, string Value)> ToPointerData(PointerEventArgs e) => + [ + // some of the data here may have some challenges being pulled out + #if ANDROID + ("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? String.Empty) + //("MotionEventActionButton", e.PlatformArgs?.MotionEvent.ActionButton.ToString() ?? String.Empty) + #elif IOS + ("State", e.PlatformArgs?.GestureRecognizer.State.ToString() ?? String.Empty) +======= + private static IEnumerable<(string Key, string Value)> ToPointerData(PointerEventArgs e) => + [ + // some of the data here may have some challenges being pulled out + #if ANDROID + ("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? String.Empty) + //("MotionEventActionButton", e.PlatformArgs?.MotionEvent.ActionButton.ToString() ?? String.Empty) + #elif IOS + ("State", e.PlatformArgs?.GestureRecognizer.State.ToString() ?? string.Empty) +>>>>>>> After + private static IEnumerable<(string Key, string Value)> ToPointerData(PointerEventArgs e) => [ // some of the data here may have some challenges being pulled out #if ANDROID From 24248daa9f24aab3a061db9d31c4261ad45ea304 Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Thu, 17 Apr 2025 11:03:42 -0400 Subject: [PATCH 04/14] Cleanup and fix code due stupid bot --- .../MauiGestureRecognizerEventsBinder.cs | 70 ++++--------------- 1 file changed, 13 insertions(+), 57 deletions(-) diff --git a/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs b/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs index b4677b7198..ef48ad6ec4 100644 --- a/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs +++ b/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs @@ -10,41 +10,32 @@ public class MauiGestureRecognizerEventsBinder : IMauiElementEventBinder /// /// Searches VisualElement for gesture recognizers to bind to /// - public void Bind(VisualElement element, Action addBreadcrumb) - { - _addBreadcrumb ??= addBreadcrumb; - if (element is IGestureRecognizers recognizers) - { - foreach (var recognizer in recognizers.GestureRecognizers) - { - SetHooks(recognizer, true); - } - } - } - + public void Bind(VisualElement element, Action addBreadcrumb) => TryBind(element, true); /// /// Searches VisualElement for gesture recognizers to unbind from /// /// - public void UnBind(VisualElement element) + public void UnBind(VisualElement element) => TryBind(element, false); + + private void TryBind(VisualElement element, bool bind) { if (element is IGestureRecognizers recognizers) { foreach (var recognizer in recognizers.GestureRecognizers) { - SetHooks(recognizer, false); + SetHooks(recognizer, bind); } } } - private void SetHooks(IGestureRecognizer recognizer, bool add) + private void SetHooks(IGestureRecognizer recognizer, bool bind) { switch (recognizer) { case TapGestureRecognizer tap: - if (add) + if (bind) { tap.Tapped += OnTapGesture; } @@ -55,7 +46,7 @@ private void SetHooks(IGestureRecognizer recognizer, bool add) break; case SwipeGestureRecognizer swipe: - if (add) + if (bind) { swipe.Swiped += OnSwipeGesture; } @@ -66,7 +57,7 @@ private void SetHooks(IGestureRecognizer recognizer, bool add) break; case PinchGestureRecognizer pinch: - if (add) + if (bind) { pinch.PinchUpdated += OnPinchGesture; } @@ -77,7 +68,7 @@ private void SetHooks(IGestureRecognizer recognizer, bool add) break; case DragGestureRecognizer drag: - if (add) + if (bind) { drag.DragStarting += OnDragStartingGesture; drag.DropCompleted += OnDropCompletedGesture; @@ -90,7 +81,7 @@ private void SetHooks(IGestureRecognizer recognizer, bool add) break; case PanGestureRecognizer pan: - if (add) + if (bind) { pan.PanUpdated += OnPanGesture; } @@ -101,7 +92,7 @@ private void SetHooks(IGestureRecognizer recognizer, bool add) break; case PointerGestureRecognizer pointer: - if (add) + if (bind) { pointer.PointerEntered += OnPointerEnteredGesture; pointer.PointerExited += OnPointerExitedGesture; @@ -151,41 +142,6 @@ private void OnPointerEnteredGesture(object? sender, PointerEventArgs e) => _add ToPointerData(e) )); - - -<<<<<<< TODO: Unmerged change from project 'Sentry.Maui(net8.0-android34.0)', Before: - static IEnumerable<(string Key, string Value)> ToPointerData(PointerEventArgs e) => - [ - // some of the data here may have some challenges being pulled out - #if ANDROID - ("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? String.Empty) -======= - private static IEnumerable<(string Key, string Value)> ToPointerData(PointerEventArgs e) => - [ - // some of the data here may have some challenges being pulled out - #if ANDROID - ("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? string.Empty) ->>>>>>> After - -<<<<<<< TODO: Unmerged change from project 'Sentry.Maui(net8.0-ios17.0)', Before: - static IEnumerable<(string Key, string Value)> ToPointerData(PointerEventArgs e) => - [ - // some of the data here may have some challenges being pulled out - #if ANDROID - ("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? String.Empty) - //("MotionEventActionButton", e.PlatformArgs?.MotionEvent.ActionButton.ToString() ?? String.Empty) - #elif IOS - ("State", e.PlatformArgs?.GestureRecognizer.State.ToString() ?? String.Empty) -======= - private static IEnumerable<(string Key, string Value)> ToPointerData(PointerEventArgs e) => - [ - // some of the data here may have some challenges being pulled out - #if ANDROID - ("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? String.Empty) - //("MotionEventActionButton", e.PlatformArgs?.MotionEvent.ActionButton.ToString() ?? String.Empty) - #elif IOS - ("State", e.PlatformArgs?.GestureRecognizer.State.ToString() ?? string.Empty) ->>>>>>> After private static IEnumerable<(string Key, string Value)> ToPointerData(PointerEventArgs e) => [ // some of the data here may have some challenges being pulled out @@ -193,7 +149,7 @@ private void OnPointerEnteredGesture(object? sender, PointerEventArgs e) => _add ("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? String.Empty) //("MotionEventActionButton", e.PlatformArgs?.MotionEvent.ActionButton.ToString() ?? String.Empty) #elif IOS - ("State", e.PlatformArgs?.GestureRecognizer.State.ToString() ?? String.Empty) + ("State", e.PlatformArgs?.GestureRecognizer.State.ToString() ?? String.Empty), //("ButtonMask", e.PlatformArgs?.GestureRecognizer.ButtonMask.ToString() ?? String.Empty) #endif ]; From 98a97892406c5f481dcdf47a0e9ac4b063e96f9f Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Thu, 17 Apr 2025 11:07:05 -0400 Subject: [PATCH 05/14] I'm not an animal - I can save mem --- .../MauiGestureRecognizerEventsBinder.cs | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs b/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs index ef48ad6ec4..82a52aed9d 100644 --- a/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs +++ b/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs @@ -5,20 +5,29 @@ namespace Sentry.Maui.Internal; /// public class MauiGestureRecognizerEventsBinder : IMauiElementEventBinder { - private Action _addBreadcrumb = null!; + private static Action? _addBreadcrumb = null!; /// /// Searches VisualElement for gesture recognizers to bind to /// - public void Bind(VisualElement element, Action addBreadcrumb) => TryBind(element, true); + public void Bind(VisualElement element, Action addBreadcrumb) + { + _addBreadcrumb ??= addBreadcrumb; // this is fine... it's the same callback for everyone and it never changes + TryBind(element, true); + } + /// /// Searches VisualElement for gesture recognizers to unbind from /// /// - public void UnBind(VisualElement element) => TryBind(element, false); + public void UnBind(VisualElement element) + { + _addBreadcrumb = null; + TryBind(element, false); + } - private void TryBind(VisualElement element, bool bind) + private static void TryBind(VisualElement element, bool bind) { if (element is IGestureRecognizers recognizers) { @@ -30,7 +39,7 @@ private void TryBind(VisualElement element, bool bind) } - private void SetHooks(IGestureRecognizer recognizer, bool bind) + private static void SetHooks(IGestureRecognizer recognizer, bool bind) { switch (recognizer) { @@ -112,31 +121,31 @@ private void SetHooks(IGestureRecognizer recognizer, bool bind) } } - private void OnPointerReleasedGesture(object? sender, PointerEventArgs e) => _addBreadcrumb.Invoke(new( + private static void OnPointerReleasedGesture(object? sender, PointerEventArgs e) => _addBreadcrumb?.Invoke(new( sender, nameof(PointerGestureRecognizer.PointerReleased), ToPointerData(e) )); - private void OnPointerPressedGesture(object? sender, PointerEventArgs e) => _addBreadcrumb.Invoke(new( + private static void OnPointerPressedGesture(object? sender, PointerEventArgs e) => _addBreadcrumb?.Invoke(new( sender, nameof(PointerGestureRecognizer.PointerPressed), ToPointerData(e) )); - private void OnPointerMovedGesture(object? sender, PointerEventArgs e) => _addBreadcrumb.Invoke(new( + private static void OnPointerMovedGesture(object? sender, PointerEventArgs e) => _addBreadcrumb?.Invoke(new( sender, nameof(PointerGestureRecognizer.PointerMoved), ToPointerData(e) )); - private void OnPointerExitedGesture(object? sender, PointerEventArgs e) => _addBreadcrumb.Invoke(new( + private static void OnPointerExitedGesture(object? sender, PointerEventArgs e) => _addBreadcrumb?.Invoke(new( sender, nameof(PointerGestureRecognizer.PointerExited), ToPointerData(e) )); - private void OnPointerEnteredGesture(object? sender, PointerEventArgs e) => _addBreadcrumb.Invoke(new( + private static void OnPointerEnteredGesture(object? sender, PointerEventArgs e) => _addBreadcrumb?.Invoke(new( sender, nameof(PointerGestureRecognizer.PointerEntered), ToPointerData(e) @@ -154,7 +163,7 @@ private void OnPointerEnteredGesture(object? sender, PointerEventArgs e) => _add #endif ]; - private void OnPanGesture(object? sender, PanUpdatedEventArgs e) => _addBreadcrumb.Invoke(new( + private static void OnPanGesture(object? sender, PanUpdatedEventArgs e) => _addBreadcrumb?.Invoke(new( sender, nameof(PanGestureRecognizer.PanUpdated), [ @@ -165,18 +174,18 @@ private void OnPanGesture(object? sender, PanUpdatedEventArgs e) => _addBreadcru ] )); - private void OnDropCompletedGesture(object? sender, DropCompletedEventArgs e) => _addBreadcrumb.Invoke(new( + private static void OnDropCompletedGesture(object? sender, DropCompletedEventArgs e) => _addBreadcrumb?.Invoke(new( sender, nameof(DragGestureRecognizer.DropCompleted) )); - private void OnDragStartingGesture(object? sender, DragStartingEventArgs e) => _addBreadcrumb.Invoke(new( + private static void OnDragStartingGesture(object? sender, DragStartingEventArgs e) => _addBreadcrumb?.Invoke(new( sender, nameof(DragGestureRecognizer.DragStarting) )); - private void OnPinchGesture(object? sender, PinchGestureUpdatedEventArgs e) => _addBreadcrumb.Invoke(new( + private static void OnPinchGesture(object? sender, PinchGestureUpdatedEventArgs e) => _addBreadcrumb?.Invoke(new( sender, nameof(PinchGestureRecognizer.PinchUpdated), [ @@ -186,13 +195,13 @@ private void OnPinchGesture(object? sender, PinchGestureUpdatedEventArgs e) => _ ] )); - private void OnSwipeGesture(object? sender, SwipedEventArgs e) => _addBreadcrumb.Invoke(new( + private static void OnSwipeGesture(object? sender, SwipedEventArgs e) => _addBreadcrumb?.Invoke(new( sender, nameof(SwipeGestureRecognizer.Swiped), [("Direction", e.Direction.ToString())] )); - private void OnTapGesture(object? sender, TappedEventArgs e) => _addBreadcrumb.Invoke(new( + private static void OnTapGesture(object? sender, TappedEventArgs e) => _addBreadcrumb?.Invoke(new( sender, nameof(TapGestureRecognizer.Tapped), [("ButtonMask", e.Buttons.ToString())] From 35e769c02fee840f4aec8099e96b8fff44ef594d Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Thu, 17 Apr 2025 15:19:24 +0000 Subject: [PATCH 06/14] Format code --- src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs b/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs index 82a52aed9d..9a4c654927 100644 --- a/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs +++ b/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs @@ -155,10 +155,10 @@ private static void OnPointerEnteredGesture(object? sender, PointerEventArgs e) [ // some of the data here may have some challenges being pulled out #if ANDROID - ("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? String.Empty) + ("MotionEventAction", e.PlatformArgs?.MotionEvent.Action.ToString() ?? string.Empty) //("MotionEventActionButton", e.PlatformArgs?.MotionEvent.ActionButton.ToString() ?? String.Empty) #elif IOS - ("State", e.PlatformArgs?.GestureRecognizer.State.ToString() ?? String.Empty), + ("State", e.PlatformArgs?.GestureRecognizer.State.ToString() ?? string.Empty), //("ButtonMask", e.PlatformArgs?.GestureRecognizer.ButtonMask.ToString() ?? String.Empty) #endif ]; From 658605027bab280f186a0c4b42e881683cba44e3 Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Wed, 30 Apr 2025 10:59:47 -0400 Subject: [PATCH 07/14] Update MauiGestureRecognizerEventsBinder.cs --- .../MauiGestureRecognizerEventsBinder.cs | 48 +++++++------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs b/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs index 9a4c654927..f0f2e53d1f 100644 --- a/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs +++ b/src/Sentry.Maui/Internal/MauiGestureRecognizerEventsBinder.cs @@ -1,7 +1,7 @@ namespace Sentry.Maui.Internal; /// -/// Binds to +/// Detects and breadcrumbs any gesture recognizers attached to the visual element /// public class MauiGestureRecognizerEventsBinder : IMauiElementEventBinder { @@ -44,63 +44,59 @@ private static void SetHooks(IGestureRecognizer recognizer, bool bind) switch (recognizer) { case TapGestureRecognizer tap: + tap.Tapped -= OnTapGesture; + if (bind) { tap.Tapped += OnTapGesture; } - else - { - tap.Tapped -= OnTapGesture; - } break; case SwipeGestureRecognizer swipe: + swipe.Swiped -= OnSwipeGesture; + if (bind) { swipe.Swiped += OnSwipeGesture; } - else - { - swipe.Swiped -= OnSwipeGesture; - } break; case PinchGestureRecognizer pinch: + pinch.PinchUpdated -= OnPinchGesture; + if (bind) { pinch.PinchUpdated += OnPinchGesture; } - else - { - pinch.PinchUpdated -= OnPinchGesture; - } break; case DragGestureRecognizer drag: + drag.DragStarting -= OnDragStartingGesture; + drag.DropCompleted -= OnDropCompletedGesture; + if (bind) { drag.DragStarting += OnDragStartingGesture; drag.DropCompleted += OnDropCompletedGesture; } - else - { - drag.DragStarting -= OnDragStartingGesture; - drag.DropCompleted -= OnDropCompletedGesture; - } break; case PanGestureRecognizer pan: + pan.PanUpdated -= OnPanGesture; + if (bind) { pan.PanUpdated += OnPanGesture; } - else - { - pan.PanUpdated -= OnPanGesture; - } break; case PointerGestureRecognizer pointer: + pointer.PointerEntered -= OnPointerEnteredGesture; + pointer.PointerExited -= OnPointerExitedGesture; + pointer.PointerMoved -= OnPointerMovedGesture; + pointer.PointerPressed -= OnPointerPressedGesture; + pointer.PointerReleased -= OnPointerReleasedGesture; + if (bind) { pointer.PointerEntered += OnPointerEnteredGesture; @@ -109,14 +105,6 @@ private static void SetHooks(IGestureRecognizer recognizer, bool bind) pointer.PointerPressed += OnPointerPressedGesture; pointer.PointerReleased += OnPointerReleasedGesture; } - else - { - pointer.PointerEntered -= OnPointerEnteredGesture; - pointer.PointerExited -= OnPointerExitedGesture; - pointer.PointerMoved -= OnPointerMovedGesture; - pointer.PointerPressed -= OnPointerPressedGesture; - pointer.PointerReleased -= OnPointerReleasedGesture; - } break; } } From d1d5089e7a1de5b996b5b45310ec07633be1492f Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Wed, 30 Apr 2025 14:57:03 -0400 Subject: [PATCH 08/14] Create MauiEventsBinderTests.GestureRecognizers.cs --- ...auiEventsBinderTests.GestureRecognizers.cs | 284 ++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 test/Sentry.Maui.Tests/MauiEventsBinderTests.GestureRecognizers.cs diff --git a/test/Sentry.Maui.Tests/MauiEventsBinderTests.GestureRecognizers.cs b/test/Sentry.Maui.Tests/MauiEventsBinderTests.GestureRecognizers.cs new file mode 100644 index 0000000000..30ff56e5a6 --- /dev/null +++ b/test/Sentry.Maui.Tests/MauiEventsBinderTests.GestureRecognizers.cs @@ -0,0 +1,284 @@ +using Sentry.Maui.Internal; + +namespace Sentry.Maui.Tests; + +public partial class MauiEventsBinderTests +{ + [Fact] + public void TapGestureRecognizer_LifecycleEvents_AddsBreadcrumb() + { + // Arrange + var image = new Image(); + var gesture = new TapGestureRecognizer(); + image.GestureRecognizers.Add(gesture); + + _fixture.Binder.HandleElementEvents(image); + + // Act + gesture.RaiseEvent(nameof(TapGestureRecognizer.Tapped), EventArgs.Empty); + + // Assert + var crumb = Assert.Single(_fixture.Scope.Breadcrumbs); + Assert.Equal($"{nameof(Window)}.{nameof(TapGestureRecognizer.Tapped)}", crumb.Message); + Assert.Equal(BreadcrumbLevel.Info, crumb.Level); + Assert.Equal(MauiEventsBinder.SystemType, crumb.Type); + Assert.Equal(MauiEventsBinder.LifecycleCategory, crumb.Category); + crumb.Data.Should().Contain($"{nameof(TapGestureRecognizer)}.Name", "tapgesturerecognizer"); + } + + // [Theory] + // [InlineData(nameof(Window.Activated))] + // [InlineData(nameof(Window.Deactivated))] + // [InlineData(nameof(Window.Stopped))] + // [InlineData(nameof(Window.Resumed))] + // [InlineData(nameof(Window.Created))] + // [InlineData(nameof(Window.Destroying))] + // public void Window_UnbindLifecycleEvents_DoesNotAddBreadcrumb(string eventName) + // { + // // Arrange + // var window = new Window + // { + // StyleId = "window" + // }; + // _fixture.Binder.HandleWindowEvents(window); + // + // window.RaiseEvent(eventName, EventArgs.Empty); + // Assert.Single(_fixture.Scope.Breadcrumbs); // Sanity check + // + // _fixture.Binder.HandleWindowEvents(window, bind: false); + // + // // Act + // window.RaiseEvent(eventName, EventArgs.Empty); + // + // // Assert + // Assert.Single(_fixture.Scope.Breadcrumbs); + // } + // + // [Theory] + // [InlineData(true)] + // [InlineData(false)] + // public void Window_Backgrounding_AddsBreadcrumb(bool includeStateInBreadcrumb) + // { + // // Arrange + // var window = new Window + // { + // StyleId = "window" + // }; + // _fixture.Binder.HandleWindowEvents(window); + // _fixture.Options.IncludeBackgroundingStateInBreadcrumbs = includeStateInBreadcrumb; + // + // var state = new PersistedState + // { + // ["Foo"] = "123", + // ["Bar"] = "", + // ["Baz"] = null + // }; + // + // // Act + // window.RaiseEvent(nameof(Window.Backgrounding), new BackgroundingEventArgs(state)); + // + // // Assert + // var crumb = Assert.Single(_fixture.Scope.Breadcrumbs); + // Assert.Equal($"{nameof(Window)}.{nameof(Window.Backgrounding)}", crumb.Message); + // Assert.Equal(BreadcrumbLevel.Info, crumb.Level); + // Assert.Equal(MauiEventsBinder.SystemType, crumb.Type); + // Assert.Equal(MauiEventsBinder.LifecycleCategory, crumb.Category); + // crumb.Data.Should().Contain($"{nameof(Window)}.Name", "window"); + // + // if (includeStateInBreadcrumb) + // { + // crumb.Data.Should().Contain("State.Foo", "123"); + // crumb.Data.Should().Contain("State.Bar", ""); + // crumb.Data.Should().Contain("State.Baz", ""); + // } + // else + // { + // crumb.Data.Should().NotContain(kvp => kvp.Key.StartsWith("State.")); + // } + // } + // + // [Fact] + // public void Window_UnbindBackgrounding_DoesNotAddBreadcrumb() + // { + // // Arrange + // var window = new Window + // { + // StyleId = "window" + // }; + // _fixture.Binder.HandleWindowEvents(window); + // _fixture.Options.IncludeBackgroundingStateInBreadcrumbs = true; + // + // var state = new PersistedState + // { + // ["Foo"] = "123", + // ["Bar"] = "", + // ["Baz"] = null + // }; + // + // window.RaiseEvent(nameof(Window.Backgrounding), new BackgroundingEventArgs(state)); + // Assert.Single(_fixture.Scope.Breadcrumbs); // Sanity check + // + // _fixture.Binder.HandleWindowEvents(window, bind: false); + // + // // Act + // window.RaiseEvent(nameof(Window.Backgrounding), new BackgroundingEventArgs(state)); + // + // // Assert + // Assert.Single(_fixture.Scope.Breadcrumbs); + // } + // + // [Fact] + // public void Window_DisplayDensityChanged_AddsBreadcrumb() + // { + // // Arrange + // var window = new Window + // { + // StyleId = "window" + // }; + // _fixture.Binder.HandleWindowEvents(window); + // + // // Act + // window.RaiseEvent(nameof(Window.DisplayDensityChanged), new DisplayDensityChangedEventArgs(1.25f)); + // + // // Assert + // var crumb = Assert.Single(_fixture.Scope.Breadcrumbs); + // Assert.Equal($"{nameof(Window)}.{nameof(Window.DisplayDensityChanged)}", crumb.Message); + // Assert.Equal(BreadcrumbLevel.Info, crumb.Level); + // Assert.Equal(MauiEventsBinder.SystemType, crumb.Type); + // Assert.Equal(MauiEventsBinder.LifecycleCategory, crumb.Category); + // crumb.Data.Should().Contain($"{nameof(Window)}.Name", "window"); + // crumb.Data.Should().Contain("DisplayDensity", "1.25"); + // } + // + // [Fact] + // public void Window_UnbindDisplayDensityChanged_DoesNotAddBreadcrumb() + // { + // // Arrange + // var window = new Window + // { + // StyleId = "window" + // }; + // _fixture.Binder.HandleWindowEvents(window); + // + // window.RaiseEvent(nameof(Window.DisplayDensityChanged), new DisplayDensityChangedEventArgs(1.25f)); + // Assert.Single(_fixture.Scope.Breadcrumbs); // Sanity check + // + // _fixture.Binder.HandleWindowEvents(window, bind: false); + // + // // Act + // window.RaiseEvent(nameof(Window.DisplayDensityChanged), new DisplayDensityChangedEventArgs(1.0f)); + // + // // Assert + // Assert.Single(_fixture.Scope.Breadcrumbs); + // } + // + // [Fact] + // public void Window_PopCanceled_AddsBreadcrumb() + // { + // // Arrange + // var window = new Window + // { + // StyleId = "window" + // }; + // _fixture.Binder.HandleWindowEvents(window); + // + // // Act + // window.RaiseEvent(nameof(Window.PopCanceled), EventArgs.Empty); + // + // // Assert + // var crumb = Assert.Single(_fixture.Scope.Breadcrumbs); + // Assert.Equal($"{nameof(Window)}.{nameof(Window.PopCanceled)}", crumb.Message); + // Assert.Equal(BreadcrumbLevel.Info, crumb.Level); + // Assert.Equal(MauiEventsBinder.NavigationType, crumb.Type); + // Assert.Equal(MauiEventsBinder.NavigationCategory, crumb.Category); + // crumb.Data.Should().Contain($"{nameof(Window)}.Name", "window"); + // } + // + // [Fact] + // public void Window_UnbindPopCanceled_DoesNotAddBreadcrumb() + // { + // // Arrange + // var window = new Window + // { + // StyleId = "window" + // }; + // _fixture.Binder.HandleWindowEvents(window); + // + // window.RaiseEvent(nameof(Window.PopCanceled), EventArgs.Empty); + // Assert.Single(_fixture.Scope.Breadcrumbs); // Sanity check + // + // _fixture.Binder.HandleWindowEvents(window, bind: false); + // + // // Act + // window.RaiseEvent(nameof(Window.PopCanceled), EventArgs.Empty); + // + // // Assert + // Assert.Single(_fixture.Scope.Breadcrumbs); + // } + // + // [Theory] + // [MemberData(nameof(WindowModalEventsData))] + // public void Window_ModalEvents_AddsBreadcrumb(string eventName, object eventArgs) + // { + // // Arrange + // var window = new Window + // { + // StyleId = "window" + // }; + // _fixture.Binder.HandleWindowEvents(window); + // + // // Act + // window.RaiseEvent(eventName, eventArgs); + // + // // Assert + // var crumb = Assert.Single(_fixture.Scope.Breadcrumbs); + // Assert.Equal($"{nameof(Window)}.{eventName}", crumb.Message); + // Assert.Equal(BreadcrumbLevel.Info, crumb.Level); + // Assert.Equal(MauiEventsBinder.NavigationType, crumb.Type); + // Assert.Equal(MauiEventsBinder.NavigationCategory, crumb.Category); + // crumb.Data.Should().Contain($"{nameof(Window)}.Name", "window"); + // crumb.Data.Should().Contain("Modal", nameof(ContentPage)); + // crumb.Data.Should().Contain("Modal.Name", "TestModalPage"); + // } + // + // [Theory] + // [MemberData(nameof(WindowModalEventsData))] + // public void Window_UnbindModalEvents_DoesNotAddBreadcrumb(string eventName, object eventArgs) + // { + // // Arrange + // var window = new Window + // { + // StyleId = "window" + // }; + // _fixture.Binder.HandleWindowEvents(window); + // + // window.RaiseEvent(eventName, eventArgs); + // Assert.Single(_fixture.Scope.Breadcrumbs); // Sanity check + // + // _fixture.Binder.HandleWindowEvents(window, bind: false); + // + // // Act + // window.RaiseEvent(eventName, eventArgs); + // + // // Assert + // Assert.Single(_fixture.Scope.Breadcrumbs); + // } + // + // public static IEnumerable WindowModalEventsData + // { + // get + // { + // var modelPage = new ContentPage + // { + // StyleId = "TestModalPage" + // }; + // + // return new List + // { + // // Note, these are distinct from the Application events with the same names. + // new object[] {nameof(Window.ModalPushed), new ModalPushedEventArgs(modelPage)}, + // new object[] {nameof(Window.ModalPopped), new ModalPoppedEventArgs(modelPage)} + // }; + // } + // } +} From efcd6735871450ac0973a819295f39db39032cf3 Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Wed, 30 Apr 2025 16:16:41 -0400 Subject: [PATCH 09/14] Update MauiEventsBinderTests.GestureRecognizers.cs --- ...auiEventsBinderTests.GestureRecognizers.cs | 334 ++++-------------- 1 file changed, 73 insertions(+), 261 deletions(-) diff --git a/test/Sentry.Maui.Tests/MauiEventsBinderTests.GestureRecognizers.cs b/test/Sentry.Maui.Tests/MauiEventsBinderTests.GestureRecognizers.cs index 30ff56e5a6..48ba343e95 100644 --- a/test/Sentry.Maui.Tests/MauiEventsBinderTests.GestureRecognizers.cs +++ b/test/Sentry.Maui.Tests/MauiEventsBinderTests.GestureRecognizers.cs @@ -7,278 +7,90 @@ public partial class MauiEventsBinderTests [Fact] public void TapGestureRecognizer_LifecycleEvents_AddsBreadcrumb() { - // Arrange - var image = new Image(); var gesture = new TapGestureRecognizer(); + TestGestureRecognizer( + gesture, + nameof(TapGestureRecognizer.Tapped), + new TappedEventArgs(gesture) + ); + } + + + [Fact] + public void SwipeGestureRecognizer_LifecycleEvents_AddsBreadcrumb() + { + var gesture = new SwipeGestureRecognizer(); + TestGestureRecognizer( + gesture, + nameof(SwipeGestureRecognizer.Swiped), + new SwipedEventArgs(gesture, SwipeDirection.Down) + ); + } + + [Fact] + public void PinchGestureRecognizer_LifecycleEvents_AddsBreadcrumb() + { + TestGestureRecognizer( + new PinchGestureRecognizer(), + nameof(PinchGestureRecognizer.PinchUpdated), + new PinchGestureUpdatedEventArgs(GestureStatus.Completed, 0, Point.Zero) + ); + } + + [Theory] + [InlineData(nameof(DragGestureRecognizer.DragStarting))] + [InlineData(nameof(DragGestureRecognizer.DropCompleted))] + public void DragGestureRecognizer_LifecycleEvents_AddsBreadcrumb(string eventName) + { + TestGestureRecognizer( + new DragGestureRecognizer(), + eventName, + DragStartingEventArgs.Empty + ); + } + + [Fact] + public void PanGestureRecognizer_LifecycleEvents_AddsBreadcrumb() + { + TestGestureRecognizer( + new PanGestureRecognizer(), + nameof(PanGestureRecognizer.PanUpdated), + new PanUpdatedEventArgs(GestureStatus.Completed, 1, 0, 0) + ); + } + + [Theory] + [InlineData(nameof(PointerGestureRecognizer.PointerEntered))] + [InlineData(nameof(PointerGestureRecognizer.PointerExited))] + [InlineData(nameof(PointerGestureRecognizer.PointerMoved))] + [InlineData(nameof(PointerGestureRecognizer.PointerPressed))] + [InlineData(nameof(PointerGestureRecognizer.PointerReleased))] + public void PointerGestureRecognizer_LifecycleEvents_AddsBreadcrumb(string eventName) + { + TestGestureRecognizer( + new PointerGestureRecognizer(), + eventName, + PointerEventArgs.Empty + ); + } + + + void TestGestureRecognizer(GestureRecognizer gesture, string eventName, object eventArgs) + { + var image = new Image(); image.GestureRecognizers.Add(gesture); _fixture.Binder.HandleElementEvents(image); // Act - gesture.RaiseEvent(nameof(TapGestureRecognizer.Tapped), EventArgs.Empty); + gesture.RaiseEvent(eventName, eventArgs); // Assert var crumb = Assert.Single(_fixture.Scope.Breadcrumbs); - Assert.Equal($"{nameof(Window)}.{nameof(TapGestureRecognizer.Tapped)}", crumb.Message); + Assert.Equal($"{gesture.GetType().Name}.{eventName}", crumb.Message); Assert.Equal(BreadcrumbLevel.Info, crumb.Level); Assert.Equal(MauiEventsBinder.SystemType, crumb.Type); Assert.Equal(MauiEventsBinder.LifecycleCategory, crumb.Category); - crumb.Data.Should().Contain($"{nameof(TapGestureRecognizer)}.Name", "tapgesturerecognizer"); + crumb.Data.Should().Contain($"{gesture.GetType().Name}.Name", "tapgesturerecognizer"); } - - // [Theory] - // [InlineData(nameof(Window.Activated))] - // [InlineData(nameof(Window.Deactivated))] - // [InlineData(nameof(Window.Stopped))] - // [InlineData(nameof(Window.Resumed))] - // [InlineData(nameof(Window.Created))] - // [InlineData(nameof(Window.Destroying))] - // public void Window_UnbindLifecycleEvents_DoesNotAddBreadcrumb(string eventName) - // { - // // Arrange - // var window = new Window - // { - // StyleId = "window" - // }; - // _fixture.Binder.HandleWindowEvents(window); - // - // window.RaiseEvent(eventName, EventArgs.Empty); - // Assert.Single(_fixture.Scope.Breadcrumbs); // Sanity check - // - // _fixture.Binder.HandleWindowEvents(window, bind: false); - // - // // Act - // window.RaiseEvent(eventName, EventArgs.Empty); - // - // // Assert - // Assert.Single(_fixture.Scope.Breadcrumbs); - // } - // - // [Theory] - // [InlineData(true)] - // [InlineData(false)] - // public void Window_Backgrounding_AddsBreadcrumb(bool includeStateInBreadcrumb) - // { - // // Arrange - // var window = new Window - // { - // StyleId = "window" - // }; - // _fixture.Binder.HandleWindowEvents(window); - // _fixture.Options.IncludeBackgroundingStateInBreadcrumbs = includeStateInBreadcrumb; - // - // var state = new PersistedState - // { - // ["Foo"] = "123", - // ["Bar"] = "", - // ["Baz"] = null - // }; - // - // // Act - // window.RaiseEvent(nameof(Window.Backgrounding), new BackgroundingEventArgs(state)); - // - // // Assert - // var crumb = Assert.Single(_fixture.Scope.Breadcrumbs); - // Assert.Equal($"{nameof(Window)}.{nameof(Window.Backgrounding)}", crumb.Message); - // Assert.Equal(BreadcrumbLevel.Info, crumb.Level); - // Assert.Equal(MauiEventsBinder.SystemType, crumb.Type); - // Assert.Equal(MauiEventsBinder.LifecycleCategory, crumb.Category); - // crumb.Data.Should().Contain($"{nameof(Window)}.Name", "window"); - // - // if (includeStateInBreadcrumb) - // { - // crumb.Data.Should().Contain("State.Foo", "123"); - // crumb.Data.Should().Contain("State.Bar", ""); - // crumb.Data.Should().Contain("State.Baz", ""); - // } - // else - // { - // crumb.Data.Should().NotContain(kvp => kvp.Key.StartsWith("State.")); - // } - // } - // - // [Fact] - // public void Window_UnbindBackgrounding_DoesNotAddBreadcrumb() - // { - // // Arrange - // var window = new Window - // { - // StyleId = "window" - // }; - // _fixture.Binder.HandleWindowEvents(window); - // _fixture.Options.IncludeBackgroundingStateInBreadcrumbs = true; - // - // var state = new PersistedState - // { - // ["Foo"] = "123", - // ["Bar"] = "", - // ["Baz"] = null - // }; - // - // window.RaiseEvent(nameof(Window.Backgrounding), new BackgroundingEventArgs(state)); - // Assert.Single(_fixture.Scope.Breadcrumbs); // Sanity check - // - // _fixture.Binder.HandleWindowEvents(window, bind: false); - // - // // Act - // window.RaiseEvent(nameof(Window.Backgrounding), new BackgroundingEventArgs(state)); - // - // // Assert - // Assert.Single(_fixture.Scope.Breadcrumbs); - // } - // - // [Fact] - // public void Window_DisplayDensityChanged_AddsBreadcrumb() - // { - // // Arrange - // var window = new Window - // { - // StyleId = "window" - // }; - // _fixture.Binder.HandleWindowEvents(window); - // - // // Act - // window.RaiseEvent(nameof(Window.DisplayDensityChanged), new DisplayDensityChangedEventArgs(1.25f)); - // - // // Assert - // var crumb = Assert.Single(_fixture.Scope.Breadcrumbs); - // Assert.Equal($"{nameof(Window)}.{nameof(Window.DisplayDensityChanged)}", crumb.Message); - // Assert.Equal(BreadcrumbLevel.Info, crumb.Level); - // Assert.Equal(MauiEventsBinder.SystemType, crumb.Type); - // Assert.Equal(MauiEventsBinder.LifecycleCategory, crumb.Category); - // crumb.Data.Should().Contain($"{nameof(Window)}.Name", "window"); - // crumb.Data.Should().Contain("DisplayDensity", "1.25"); - // } - // - // [Fact] - // public void Window_UnbindDisplayDensityChanged_DoesNotAddBreadcrumb() - // { - // // Arrange - // var window = new Window - // { - // StyleId = "window" - // }; - // _fixture.Binder.HandleWindowEvents(window); - // - // window.RaiseEvent(nameof(Window.DisplayDensityChanged), new DisplayDensityChangedEventArgs(1.25f)); - // Assert.Single(_fixture.Scope.Breadcrumbs); // Sanity check - // - // _fixture.Binder.HandleWindowEvents(window, bind: false); - // - // // Act - // window.RaiseEvent(nameof(Window.DisplayDensityChanged), new DisplayDensityChangedEventArgs(1.0f)); - // - // // Assert - // Assert.Single(_fixture.Scope.Breadcrumbs); - // } - // - // [Fact] - // public void Window_PopCanceled_AddsBreadcrumb() - // { - // // Arrange - // var window = new Window - // { - // StyleId = "window" - // }; - // _fixture.Binder.HandleWindowEvents(window); - // - // // Act - // window.RaiseEvent(nameof(Window.PopCanceled), EventArgs.Empty); - // - // // Assert - // var crumb = Assert.Single(_fixture.Scope.Breadcrumbs); - // Assert.Equal($"{nameof(Window)}.{nameof(Window.PopCanceled)}", crumb.Message); - // Assert.Equal(BreadcrumbLevel.Info, crumb.Level); - // Assert.Equal(MauiEventsBinder.NavigationType, crumb.Type); - // Assert.Equal(MauiEventsBinder.NavigationCategory, crumb.Category); - // crumb.Data.Should().Contain($"{nameof(Window)}.Name", "window"); - // } - // - // [Fact] - // public void Window_UnbindPopCanceled_DoesNotAddBreadcrumb() - // { - // // Arrange - // var window = new Window - // { - // StyleId = "window" - // }; - // _fixture.Binder.HandleWindowEvents(window); - // - // window.RaiseEvent(nameof(Window.PopCanceled), EventArgs.Empty); - // Assert.Single(_fixture.Scope.Breadcrumbs); // Sanity check - // - // _fixture.Binder.HandleWindowEvents(window, bind: false); - // - // // Act - // window.RaiseEvent(nameof(Window.PopCanceled), EventArgs.Empty); - // - // // Assert - // Assert.Single(_fixture.Scope.Breadcrumbs); - // } - // - // [Theory] - // [MemberData(nameof(WindowModalEventsData))] - // public void Window_ModalEvents_AddsBreadcrumb(string eventName, object eventArgs) - // { - // // Arrange - // var window = new Window - // { - // StyleId = "window" - // }; - // _fixture.Binder.HandleWindowEvents(window); - // - // // Act - // window.RaiseEvent(eventName, eventArgs); - // - // // Assert - // var crumb = Assert.Single(_fixture.Scope.Breadcrumbs); - // Assert.Equal($"{nameof(Window)}.{eventName}", crumb.Message); - // Assert.Equal(BreadcrumbLevel.Info, crumb.Level); - // Assert.Equal(MauiEventsBinder.NavigationType, crumb.Type); - // Assert.Equal(MauiEventsBinder.NavigationCategory, crumb.Category); - // crumb.Data.Should().Contain($"{nameof(Window)}.Name", "window"); - // crumb.Data.Should().Contain("Modal", nameof(ContentPage)); - // crumb.Data.Should().Contain("Modal.Name", "TestModalPage"); - // } - // - // [Theory] - // [MemberData(nameof(WindowModalEventsData))] - // public void Window_UnbindModalEvents_DoesNotAddBreadcrumb(string eventName, object eventArgs) - // { - // // Arrange - // var window = new Window - // { - // StyleId = "window" - // }; - // _fixture.Binder.HandleWindowEvents(window); - // - // window.RaiseEvent(eventName, eventArgs); - // Assert.Single(_fixture.Scope.Breadcrumbs); // Sanity check - // - // _fixture.Binder.HandleWindowEvents(window, bind: false); - // - // // Act - // window.RaiseEvent(eventName, eventArgs); - // - // // Assert - // Assert.Single(_fixture.Scope.Breadcrumbs); - // } - // - // public static IEnumerable WindowModalEventsData - // { - // get - // { - // var modelPage = new ContentPage - // { - // StyleId = "TestModalPage" - // }; - // - // return new List - // { - // // Note, these are distinct from the Application events with the same names. - // new object[] {nameof(Window.ModalPushed), new ModalPushedEventArgs(modelPage)}, - // new object[] {nameof(Window.ModalPopped), new ModalPoppedEventArgs(modelPage)} - // }; - // } - // } } From 1fba474ff7ff1093e2dd37ab6ae71976e1786cb4 Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Thu, 1 May 2025 11:08:53 -0400 Subject: [PATCH 10/14] Update MauiEventsBinderTests.cs --- test/Sentry.Maui.Tests/MauiEventsBinderTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Sentry.Maui.Tests/MauiEventsBinderTests.cs b/test/Sentry.Maui.Tests/MauiEventsBinderTests.cs index 484b0d445d..8871b74fe9 100644 --- a/test/Sentry.Maui.Tests/MauiEventsBinderTests.cs +++ b/test/Sentry.Maui.Tests/MauiEventsBinderTests.cs @@ -28,7 +28,8 @@ public Fixture() options, [ new MauiButtonEventsBinder(), - new MauiImageButtonEventsBinder() + new MauiImageButtonEventsBinder(), + new MauiGestureRecognizerEventsBinder() ] ); } From 8ef9aca849e472cace82601df55389d1ce0aa13b Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Thu, 1 May 2025 11:19:29 -0400 Subject: [PATCH 11/14] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb8c957329..fb7579b89c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Added `CaptureFeedback` overload with `configureScope` parameter ([#4073](https://github.com/getsentry/sentry-dotnet/pull/4073)) - Custom SessionReplay masks in MAUI Android apps ([#4121](https://github.com/getsentry/sentry-dotnet/pull/4121)) +- Auto breadcrumbs now include all .NET MAUI gesture recognizer events ### Fixes From 559c8e0ddd1e78489432d5a2a1fdc6c1e2f772a1 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Thu, 1 May 2025 15:25:39 +0000 Subject: [PATCH 12/14] Format code --- .../MauiEventsBinderTests.GestureRecognizers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Sentry.Maui.Tests/MauiEventsBinderTests.GestureRecognizers.cs b/test/Sentry.Maui.Tests/MauiEventsBinderTests.GestureRecognizers.cs index 48ba343e95..c9d30833b0 100644 --- a/test/Sentry.Maui.Tests/MauiEventsBinderTests.GestureRecognizers.cs +++ b/test/Sentry.Maui.Tests/MauiEventsBinderTests.GestureRecognizers.cs @@ -75,7 +75,7 @@ public void PointerGestureRecognizer_LifecycleEvents_AddsBreadcrumb(string event } - void TestGestureRecognizer(GestureRecognizer gesture, string eventName, object eventArgs) + private void TestGestureRecognizer(GestureRecognizer gesture, string eventName, object eventArgs) { var image = new Image(); image.GestureRecognizers.Add(gesture); From a71375a6f2441ea2b9c27882752dc73111e1a43c Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Thu, 1 May 2025 12:01:16 -0400 Subject: [PATCH 13/14] WIP --- samples/Sentry.Samples.Maui/MainPage.xaml | 6 +++++- samples/Sentry.Samples.Maui/MainPage.xaml.cs | 4 ++++ .../MauiEventsBinderTests.GestureRecognizers.cs | 5 +++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/samples/Sentry.Samples.Maui/MainPage.xaml b/samples/Sentry.Samples.Maui/MainPage.xaml index 276176d175..a8bf13e5ba 100644 --- a/samples/Sentry.Samples.Maui/MainPage.xaml +++ b/samples/Sentry.Samples.Maui/MainPage.xaml @@ -15,7 +15,11 @@ sentry:SessionReplay.Mask="Unmask" SemanticProperties.Description="Cute dot net bot waving hi to you!" HeightRequest="200" - HorizontalOptions="Center" /> + HorizontalOptions="Center"> + + + +