Skip to content

Commit ac4f837

Browse files
Fix missing MAUI Shell navigation breadcrumbs on iOS (#4006)
--------- Co-authored-by: James Crosswell <[email protected]>
1 parent a59729f commit ac4f837

File tree

9 files changed

+86
-28
lines changed

9 files changed

+86
-28
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
### Fixes
2222

2323
- Unknown stack frames in profiles on .NET 8+ ([#3967](https://github.com/getsentry/sentry-dotnet/pull/3967))
24+
- Missing MAUI `Shell` navigation breadcrumbs on iOS ([#4006](https://github.com/getsentry/sentry-dotnet/pull/4006))
2425

2526
## 5.3.0
2627

src/Sentry.Maui/Internal/MauiEventsBinder.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,16 @@ public void HandleApplicationEvents(Application application, bool bind = true)
3434
{
3535
if (bind)
3636
{
37-
// Attach element events to all descendents as they are added to the application.
37+
// Attach element events to all existing descendants (skip the application itself)
38+
foreach (var descendant in application.GetVisualTreeDescendants().Skip(1))
39+
{
40+
if (descendant is VisualElement element)
41+
{
42+
OnApplicationOnDescendantAdded(application, new ElementEventArgs(element));
43+
}
44+
}
45+
46+
// Attach element events to all descendants as they are added to the application.
3847
application.DescendantAdded += OnApplicationOnDescendantAdded;
3948
application.DescendantRemoved += OnApplicationOnDescendantRemoved;
4049

test/Sentry.EntityFramework.Tests/IntegrationTests.verify.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace Sentry.EntityFramework.Tests;
55
public class IntegrationTests
66
{
77
// needs to be a variable to stop EF from inlining it as a constant
8-
static string shouldNotAppearInPayload = "SHOULD NOT APPEAR IN PAYLOAD";
8+
private static string shouldNotAppearInPayload = "SHOULD NOT APPEAR IN PAYLOAD";
99

1010
[SkippableFact]
1111
public async Task Simple()

test/Sentry.Maui.Tests/MauiEventsBinderTests.Application.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,36 @@ public void Application_UnbindModalEvents_DoesNotAddBreadcrumb(string eventName,
145145
Assert.Single(_fixture.Scope.Breadcrumbs);
146146
}
147147

148+
[Fact]
149+
public void Application_HandleApplicationEvents_TracksExistingDescendants()
150+
{
151+
// Arrange
152+
var application = MockApplication.Create();
153+
var element = new MockVisualElement("element");
154+
var mainPage = new ContentPage
155+
{
156+
Content = new VerticalStackLayout
157+
{
158+
element
159+
}
160+
};
161+
162+
application.AddWindow(mainPage);
163+
164+
_fixture.Binder.HandleApplicationEvents(application);
165+
166+
// Act
167+
element.RaiseEvent(nameof(VisualElement.Focused), new FocusEventArgs(element, true));
168+
169+
// Assert
170+
var crumb = Assert.Single(_fixture.Scope.Breadcrumbs);
171+
Assert.Equal($"{nameof(MockVisualElement)}.{nameof(VisualElement.Focused)}", crumb.Message);
172+
Assert.Equal(BreadcrumbLevel.Info, crumb.Level);
173+
Assert.Equal(MauiEventsBinder.SystemType, crumb.Type);
174+
Assert.Equal(MauiEventsBinder.RenderingCategory, crumb.Category);
175+
crumb.Data.Should().Contain($"{nameof(MockVisualElement)}.Name", "element");
176+
}
177+
148178
public static IEnumerable<object[]> ApplicationModalEventsData
149179
{
150180
get

test/Sentry.Maui.Tests/Mocks/MockApplication.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace Sentry.Maui.Tests.Mocks;
55
public class MockApplication : Application
66
{
77
private static readonly object LockObj = new();
8+
private Page _mainPage;
89

910
static MockApplication()
1011
{
@@ -18,6 +19,23 @@ private MockApplication()
1819
{
1920
}
2021

22+
public void AddWindow(Page mainPage)
23+
{
24+
_mainPage = mainPage;
25+
((IApplication)this).CreateWindow(null);
26+
_mainPage = null;
27+
}
28+
29+
protected override Window CreateWindow(IActivationState activationState)
30+
{
31+
if (_mainPage != null)
32+
{
33+
return new Window(_mainPage);
34+
}
35+
36+
return base.CreateWindow(activationState);
37+
}
38+
2139
public static MockApplication Create()
2240
{
2341
// The base constructor will try to set the mock as the current application, which we don't want in tests.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
using Foundation;
1+
using Foundation;
22

33
namespace Sentry.MauiTrimTest;
44

55
[Register("AppDelegate")]
66
public class AppDelegate : MauiUIApplicationDelegate
77
{
8-
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
8+
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
99
}

test/Sentry.MauiTrimTest/Platforms/MacCatalyst/Program.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ namespace Sentry.MauiTrimTest;
55

66
public class Program
77
{
8-
// This is the main entry point of the application.
9-
static void Main(string[] args)
10-
{
11-
// if you want to use a different Application Delegate class from "AppDelegate"
12-
// you can specify it here.
13-
UIApplication.Main(args, null, typeof(AppDelegate));
14-
}
8+
// This is the main entry point of the application.
9+
private static void Main(string[] args)
10+
{
11+
// if you want to use a different Application Delegate class from "AppDelegate"
12+
// you can specify it here.
13+
UIApplication.Main(args, null, typeof(AppDelegate));
14+
}
1515
}

test/Sentry.MauiTrimTest/Platforms/Tizen/Main.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55
namespace Sentry.MauiTrimTest;
66

7-
class Program : MauiApplication
7+
public class Program : MauiApplication
88
{
9-
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
9+
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
1010

11-
static void Main(string[] args)
12-
{
13-
var app = new Program();
14-
app.Run(args);
15-
}
11+
private static void Main(string[] args)
12+
{
13+
var app = new Program();
14+
app.Run(args);
15+
}
1616
}
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Microsoft.UI.Xaml;
1+
using Microsoft.UI.Xaml;
22

33
// To learn more about WinUI, the WinUI project structure,
44
// and more about our project templates, see: http://aka.ms/winui-project-info.
@@ -10,15 +10,15 @@ namespace Sentry.MauiTrimTest.WinUI;
1010
/// </summary>
1111
public partial class App : MauiWinUIApplication
1212
{
13-
/// <summary>
14-
/// Initializes the singleton application object. This is the first line of authored code
15-
/// executed, and as such is the logical equivalent of main() or WinMain().
16-
/// </summary>
17-
public App()
18-
{
19-
this.InitializeComponent();
20-
}
13+
/// <summary>
14+
/// Initializes the singleton application object. This is the first line of authored code
15+
/// executed, and as such is the logical equivalent of main() or WinMain().
16+
/// </summary>
17+
public App()
18+
{
19+
this.InitializeComponent();
20+
}
2121

22-
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
22+
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
2323
}
2424

0 commit comments

Comments
 (0)