Skip to content

Fix missing MAUI Shell navigation breadcrumbs on iOS #4006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Fixes

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

## 5.3.0

Expand Down
11 changes: 10 additions & 1 deletion src/Sentry.Maui/Internal/MauiEventsBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,16 @@ public void HandleApplicationEvents(Application application, bool bind = true)
{
if (bind)
{
// Attach element events to all descendents as they are added to the application.
// Attach element events to all existing descendants (skip the application itself)
foreach (var descendant in application.GetVisualTreeDescendants().Skip(1))
{
if (descendant is VisualElement element)
{
OnApplicationOnDescendantAdded(application, new ElementEventArgs(element));
}
}

// Attach element events to all descendants as they are added to the application.
application.DescendantAdded += OnApplicationOnDescendantAdded;
application.DescendantRemoved += OnApplicationOnDescendantRemoved;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Sentry.EntityFramework.Tests;
public class IntegrationTests
{
// needs to be a variable to stop EF from inlining it as a constant
static string shouldNotAppearInPayload = "SHOULD NOT APPEAR IN PAYLOAD";
private static string shouldNotAppearInPayload = "SHOULD NOT APPEAR IN PAYLOAD";

[SkippableFact]
public async Task Simple()
Expand Down
30 changes: 30 additions & 0 deletions test/Sentry.Maui.Tests/MauiEventsBinderTests.Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,36 @@ public void Application_UnbindModalEvents_DoesNotAddBreadcrumb(string eventName,
Assert.Single(_fixture.Scope.Breadcrumbs);
}

[Fact]
public void Application_HandleApplicationEvents_TracksExistingDescendants()
{
// Arrange
var application = MockApplication.Create();
var element = new MockVisualElement("element");
var mainPage = new ContentPage
{
Content = new VerticalStackLayout
{
element
}
};

application.AddWindow(mainPage);

_fixture.Binder.HandleApplicationEvents(application);

// Act
element.RaiseEvent(nameof(VisualElement.Focused), new FocusEventArgs(element, true));

// Assert
var crumb = Assert.Single(_fixture.Scope.Breadcrumbs);
Assert.Equal($"{nameof(MockVisualElement)}.{nameof(VisualElement.Focused)}", crumb.Message);
Assert.Equal(BreadcrumbLevel.Info, crumb.Level);
Assert.Equal(MauiEventsBinder.SystemType, crumb.Type);
Assert.Equal(MauiEventsBinder.RenderingCategory, crumb.Category);
crumb.Data.Should().Contain($"{nameof(MockVisualElement)}.Name", "element");
}

public static IEnumerable<object[]> ApplicationModalEventsData
{
get
Expand Down
18 changes: 18 additions & 0 deletions test/Sentry.Maui.Tests/Mocks/MockApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace Sentry.Maui.Tests.Mocks;
public class MockApplication : Application
{
private static readonly object LockObj = new();
private Page _mainPage;

static MockApplication()
{
Expand All @@ -18,6 +19,23 @@ private MockApplication()
{
}

public void AddWindow(Page mainPage)
{
_mainPage = mainPage;
((IApplication)this).CreateWindow(null);
_mainPage = null;
}

protected override Window CreateWindow(IActivationState activationState)
{
if (_mainPage != null)
{
return new Window(_mainPage);
}

return base.CreateWindow(activationState);
}

public static MockApplication Create()
{
// The base constructor will try to set the mock as the current application, which we don't want in tests.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using Foundation;
using Foundation;

namespace Sentry.MauiTrimTest;

[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
14 changes: 7 additions & 7 deletions test/Sentry.MauiTrimTest/Platforms/MacCatalyst/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ namespace Sentry.MauiTrimTest;

public class Program
{
// This is the main entry point of the application.
static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, typeof(AppDelegate));
}
// This is the main entry point of the application.
private static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, typeof(AppDelegate));
}
}
14 changes: 7 additions & 7 deletions test/Sentry.MauiTrimTest/Platforms/Tizen/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

namespace Sentry.MauiTrimTest;

class Program : MauiApplication
public class Program : MauiApplication
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();

static void Main(string[] args)
{
var app = new Program();
app.Run(args);
}
private static void Main(string[] args)
{
var app = new Program();
app.Run(args);
}
}
20 changes: 10 additions & 10 deletions test/Sentry.MauiTrimTest/Platforms/Windows/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml;

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

protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}

Loading