From f4611aa53f0493a6d3f4f9852f85efd852a875ad Mon Sep 17 00:00:00 2001 From: Ronan Burke Date: Sat, 11 Nov 2023 20:47:37 +0000 Subject: [PATCH] Back button source generator --- README.md | 38 ++++---- samples/DemoApp/Views/ChangeUsernamePage.xaml | 4 +- .../DemoApp/Views/ChangeUsernamePage.xaml.cs | 2 +- .../DemoApp/Views/Flyouts/ContactsPage.xaml | 4 +- .../Views/Flyouts/ContactsPage.xaml.cs | 2 +- .../DemoApp/Views/Flyouts/DemoFlyoutPage.xaml | 4 +- .../Views/Flyouts/DemoFlyoutPage.xaml.cs | 3 +- .../Views/Flyouts/FlyoutMenuPage.xaml.cs | 1 + .../DemoApp/Views/Flyouts/RemindersPage.xaml | 4 +- .../Views/Flyouts/RemindersPage.xaml.cs | 2 +- samples/DemoApp/Views/Flyouts/TodoPage.xaml | 4 +- .../DemoApp/Views/Flyouts/TodoPage.xaml.cs | 2 +- samples/DemoApp/Views/HomePage.xaml | 4 +- samples/DemoApp/Views/HomePage.xaml.cs | 2 +- samples/DemoApp/Views/LoginPage.xaml | 4 +- samples/DemoApp/Views/LoginPage.xaml.cs | 2 +- samples/DemoApp/Views/RegisterPage.xaml | 4 +- samples/DemoApp/Views/RegisterPage.xaml.cs | 2 +- samples/DemoApp/Views/Tabs/AlphaTabPage.xaml | 4 +- .../DemoApp/Views/Tabs/AlphaTabPage.xaml.cs | 2 +- samples/DemoApp/Views/Tabs/BetaTabPage.xaml | 4 +- .../DemoApp/Views/Tabs/BetaTabPage.xaml.cs | 2 +- .../DemoApp/Views/Tabs/CharlieTabPage.xaml | 4 +- .../DemoApp/Views/Tabs/CharlieTabPage.xaml.cs | 2 +- samples/DemoApp/Views/Tabs/DemoTabsPage.xaml | 4 +- .../DemoApp/Views/Tabs/DemoTabsPage.xaml.cs | 2 +- samples/DemoApp/Views/UriTestPage.xaml | 4 +- samples/DemoApp/Views/UriTestPage.xaml.cs | 2 +- .../AppSourceGenerator.cs | 5 +- .../Burkus.Mvvm.Maui.SourceGenerators.csproj | 1 + .../PageSourceGenerator.cs | 87 +++++++++++++++++++ .../DisableBackButtonNavigatorAttribute.cs | 11 +++ .../Models/Pages/BackButtonNavigator.cs | 4 +- .../Models/Pages/BurkusContentPage.cs | 9 -- .../Models/Pages/BurkusFlyoutPage.cs | 9 -- .../Models/Pages/BurkusNavigationPage.cs | 9 -- .../Models/Pages/BurkusTabbedPage.cs | 9 -- 37 files changed, 161 insertions(+), 101 deletions(-) create mode 100644 src/Burkus.Mvvm.Maui.SourceGenerators/PageSourceGenerator.cs create mode 100644 src/Burkus.Mvvm.Maui/Annotations/DisableBackButtonNavigatorAttribute.cs delete mode 100644 src/Burkus.Mvvm.Maui/Models/Pages/BurkusContentPage.cs delete mode 100644 src/Burkus.Mvvm.Maui/Models/Pages/BurkusFlyoutPage.cs delete mode 100644 src/Burkus.Mvvm.Maui/Models/Pages/BurkusNavigationPage.cs delete mode 100644 src/Burkus.Mvvm.Maui/Models/Pages/BurkusTabbedPage.cs diff --git a/README.md b/README.md index 0a6a772..a644cce 100644 --- a/README.md +++ b/README.md @@ -355,26 +355,6 @@ Several parameter keys have been pre-defined and are using by the `Burkus.Mvvm.M The `NavigationParameters` object exposes some handy properties `.UseAnimatedNavigation` and `.UseModalNavigation` so you can easily set or check the value of these properties. -### Handling back button presses -By default, back button presses on Android/Windows will bypass `Burkus.Mvvm.Maui` which would mean lifecycle events and parameter passing may not happen when you expect them to. You can allow `Burkus.Mvvm.Maui` to handle the back button navigation for a page by turning it into a `Burkus...Page`. For example, below a `ContentPage` is turned into a `BurkusContentPage`. - -``` xml - -``` - -``` csharp -public partial class HomePage : BurkusContentPage -``` - -The page types available are: -- `BurkusContentPage` -- `BurkusNavigationPage` -- `BurkusTabbedPage` -- `BurkusFlyoutPage` - ## Dialog service `IDialogService` is automatically registered by `.UseBurkusMvvm(...)`. It is a testable service that is an abstraction over [the MAUI alerts/pop-ups/prompts/action sheets](https://learn.microsoft.com/en-us/dotnet/maui/user-interface/pop-ups). @@ -401,7 +381,7 @@ dialogService.DisplayAlert( See the [IDialogService interface in the repository](https://github.com/BurkusCat/Burkus.Mvvm.Maui/blob/main/src/Abstractions/IDialogService.cs) for all the possible method options. ## Advanced / complexities -The below are some things of note that may help prevent issues from arising: +Below are some things of note that may help prevent issues from arising: - The `MainPage` of the app will be automatically set to a `NavigationPage`. This means the first page you push can be a `ContentPage` rather than needing to push a `NavigationPage`. This may change in the future. - A source generator will automatically add code overriding `Window CreateWindow(IActivationState? activationState)` in your `App.xaml.cs` class. - Adding this package to a project will automatically import the `Burkus.Mvvm.Maui` namespace globally if you have [`ImplicitUsings`](https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/#implicit-usings) enabled in your project. You can opt out of this by including the following in your `.csproj` file: @@ -409,6 +389,22 @@ The below are some things of note that may help prevent issues from arising: ``` +### Handling back button presses +A source generator will automatically override `bool OnBackButtonPressed()` for every `ContentPage`, `FlyoutPage`, `TabbedPage`, and `NavigationPage`. This generated source code allows `Burkus.Mvvm.Maui` to handle back button presses on Android & Windows. + +To disable this for a particular page, annotate the page with the `[DisableBackButtonNavigator]` attribute like this: +```csharp +[DisableBackButtonNavigator] +public partial class FlyoutMenuPage : ContentPage +{ + ... +``` + +The source generator calls the following code, which may be useful if you need to create some custom `OnBackButtonPressed` logic: +``` csharp +return BackButtonNavigator.HandleBackButtonPressed(); +``` + # Roadmap 🛣️ - [View and viewmodel auto-registration](https://github.com/BurkusCat/Burkus.Mvvm.Maui/issues/4) - [Popup pages](https://github.com/BurkusCat/Burkus.Mvvm.Maui/issues/2) diff --git a/samples/DemoApp/Views/ChangeUsernamePage.xaml b/samples/DemoApp/Views/ChangeUsernamePage.xaml index 0c98f5e..2cffa91 100644 --- a/samples/DemoApp/Views/ChangeUsernamePage.xaml +++ b/samples/DemoApp/Views/ChangeUsernamePage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/ChangeUsernamePage.xaml.cs b/samples/DemoApp/Views/ChangeUsernamePage.xaml.cs index bc53544..f16e9bb 100644 --- a/samples/DemoApp/Views/ChangeUsernamePage.xaml.cs +++ b/samples/DemoApp/Views/ChangeUsernamePage.xaml.cs @@ -1,6 +1,6 @@ namespace DemoApp.Views; -public partial class ChangeUsernamePage : BurkusContentPage +public partial class ChangeUsernamePage : ContentPage { public ChangeUsernamePage() { diff --git a/samples/DemoApp/Views/Flyouts/ContactsPage.xaml b/samples/DemoApp/Views/Flyouts/ContactsPage.xaml index be7179d..aa9b348 100644 --- a/samples/DemoApp/Views/Flyouts/ContactsPage.xaml +++ b/samples/DemoApp/Views/Flyouts/ContactsPage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/Flyouts/ContactsPage.xaml.cs b/samples/DemoApp/Views/Flyouts/ContactsPage.xaml.cs index 02393ca..785430e 100644 --- a/samples/DemoApp/Views/Flyouts/ContactsPage.xaml.cs +++ b/samples/DemoApp/Views/Flyouts/ContactsPage.xaml.cs @@ -1,6 +1,6 @@ namespace DemoApp.Views; -public partial class ContactsPage : BurkusContentPage +public partial class ContactsPage : ContentPage { public ContactsPage() { diff --git a/samples/DemoApp/Views/Flyouts/DemoFlyoutPage.xaml b/samples/DemoApp/Views/Flyouts/DemoFlyoutPage.xaml index 7654f95..4508591 100644 --- a/samples/DemoApp/Views/Flyouts/DemoFlyoutPage.xaml +++ b/samples/DemoApp/Views/Flyouts/DemoFlyoutPage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/Flyouts/DemoFlyoutPage.xaml.cs b/samples/DemoApp/Views/Flyouts/DemoFlyoutPage.xaml.cs index acc80ee..9b76956 100644 --- a/samples/DemoApp/Views/Flyouts/DemoFlyoutPage.xaml.cs +++ b/samples/DemoApp/Views/Flyouts/DemoFlyoutPage.xaml.cs @@ -1,6 +1,7 @@ namespace DemoApp.Views; -public partial class DemoFlyoutPage : BurkusFlyoutPage +[DisableBackButtonNavigator] +public partial class DemoFlyoutPage : FlyoutPage { public DemoFlyoutPage() { diff --git a/samples/DemoApp/Views/Flyouts/FlyoutMenuPage.xaml.cs b/samples/DemoApp/Views/Flyouts/FlyoutMenuPage.xaml.cs index 089bd99..a14461f 100644 --- a/samples/DemoApp/Views/Flyouts/FlyoutMenuPage.xaml.cs +++ b/samples/DemoApp/Views/Flyouts/FlyoutMenuPage.xaml.cs @@ -1,5 +1,6 @@ namespace DemoApp.Views; +[DisableBackButtonNavigator] public partial class FlyoutMenuPage : ContentPage { public FlyoutMenuPage() diff --git a/samples/DemoApp/Views/Flyouts/RemindersPage.xaml b/samples/DemoApp/Views/Flyouts/RemindersPage.xaml index 8547986..9ec250f 100644 --- a/samples/DemoApp/Views/Flyouts/RemindersPage.xaml +++ b/samples/DemoApp/Views/Flyouts/RemindersPage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/Flyouts/RemindersPage.xaml.cs b/samples/DemoApp/Views/Flyouts/RemindersPage.xaml.cs index 638fce2..5e3f4a5 100644 --- a/samples/DemoApp/Views/Flyouts/RemindersPage.xaml.cs +++ b/samples/DemoApp/Views/Flyouts/RemindersPage.xaml.cs @@ -1,6 +1,6 @@ namespace DemoApp.Views; -public partial class RemindersPage : BurkusContentPage +public partial class RemindersPage : ContentPage { public RemindersPage() { diff --git a/samples/DemoApp/Views/Flyouts/TodoPage.xaml b/samples/DemoApp/Views/Flyouts/TodoPage.xaml index d7dd56b..8fbf2a7 100644 --- a/samples/DemoApp/Views/Flyouts/TodoPage.xaml +++ b/samples/DemoApp/Views/Flyouts/TodoPage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/Flyouts/TodoPage.xaml.cs b/samples/DemoApp/Views/Flyouts/TodoPage.xaml.cs index 3a8376d..1610e7f 100644 --- a/samples/DemoApp/Views/Flyouts/TodoPage.xaml.cs +++ b/samples/DemoApp/Views/Flyouts/TodoPage.xaml.cs @@ -1,6 +1,6 @@ namespace DemoApp.Views; -public partial class TodoPage : BurkusContentPage +public partial class TodoPage : ContentPage { public TodoPage() { diff --git a/samples/DemoApp/Views/HomePage.xaml b/samples/DemoApp/Views/HomePage.xaml index 25c6353..bb351cf 100644 --- a/samples/DemoApp/Views/HomePage.xaml +++ b/samples/DemoApp/Views/HomePage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/HomePage.xaml.cs b/samples/DemoApp/Views/HomePage.xaml.cs index 022df21..db77768 100644 --- a/samples/DemoApp/Views/HomePage.xaml.cs +++ b/samples/DemoApp/Views/HomePage.xaml.cs @@ -1,6 +1,6 @@ namespace DemoApp.Views; -public partial class HomePage : BurkusContentPage +public partial class HomePage : ContentPage { public HomePage() { diff --git a/samples/DemoApp/Views/LoginPage.xaml b/samples/DemoApp/Views/LoginPage.xaml index cb5c31a..8830c48 100644 --- a/samples/DemoApp/Views/LoginPage.xaml +++ b/samples/DemoApp/Views/LoginPage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/LoginPage.xaml.cs b/samples/DemoApp/Views/LoginPage.xaml.cs index c7ea61f..e75867b 100644 --- a/samples/DemoApp/Views/LoginPage.xaml.cs +++ b/samples/DemoApp/Views/LoginPage.xaml.cs @@ -1,6 +1,6 @@ namespace DemoApp.Views; -public partial class LoginPage : BurkusContentPage +public partial class LoginPage : ContentPage { public LoginPage() { diff --git a/samples/DemoApp/Views/RegisterPage.xaml b/samples/DemoApp/Views/RegisterPage.xaml index bd88f4e..0015bdd 100644 --- a/samples/DemoApp/Views/RegisterPage.xaml +++ b/samples/DemoApp/Views/RegisterPage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/RegisterPage.xaml.cs b/samples/DemoApp/Views/RegisterPage.xaml.cs index 8975a6a..de98860 100644 --- a/samples/DemoApp/Views/RegisterPage.xaml.cs +++ b/samples/DemoApp/Views/RegisterPage.xaml.cs @@ -1,6 +1,6 @@ namespace DemoApp.Views; -public partial class RegisterPage : BurkusContentPage +public partial class RegisterPage : ContentPage { public RegisterPage() { diff --git a/samples/DemoApp/Views/Tabs/AlphaTabPage.xaml b/samples/DemoApp/Views/Tabs/AlphaTabPage.xaml index 9d3e314..4848faf 100644 --- a/samples/DemoApp/Views/Tabs/AlphaTabPage.xaml +++ b/samples/DemoApp/Views/Tabs/AlphaTabPage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/Tabs/AlphaTabPage.xaml.cs b/samples/DemoApp/Views/Tabs/AlphaTabPage.xaml.cs index 3d9e54b..d6a98bb 100644 --- a/samples/DemoApp/Views/Tabs/AlphaTabPage.xaml.cs +++ b/samples/DemoApp/Views/Tabs/AlphaTabPage.xaml.cs @@ -1,6 +1,6 @@ namespace DemoApp.Views; -public partial class AlphaTabPage : BurkusContentPage +public partial class AlphaTabPage : ContentPage { public AlphaTabPage() { diff --git a/samples/DemoApp/Views/Tabs/BetaTabPage.xaml b/samples/DemoApp/Views/Tabs/BetaTabPage.xaml index f1f2f94..ba4f6bb 100644 --- a/samples/DemoApp/Views/Tabs/BetaTabPage.xaml +++ b/samples/DemoApp/Views/Tabs/BetaTabPage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/Tabs/BetaTabPage.xaml.cs b/samples/DemoApp/Views/Tabs/BetaTabPage.xaml.cs index e6e3509..8d20b37 100644 --- a/samples/DemoApp/Views/Tabs/BetaTabPage.xaml.cs +++ b/samples/DemoApp/Views/Tabs/BetaTabPage.xaml.cs @@ -1,6 +1,6 @@ namespace DemoApp.Views; -public partial class BetaTabPage : BurkusContentPage +public partial class BetaTabPage : ContentPage { public BetaTabPage() { diff --git a/samples/DemoApp/Views/Tabs/CharlieTabPage.xaml b/samples/DemoApp/Views/Tabs/CharlieTabPage.xaml index 17acc7d..885d9e4 100644 --- a/samples/DemoApp/Views/Tabs/CharlieTabPage.xaml +++ b/samples/DemoApp/Views/Tabs/CharlieTabPage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/Tabs/CharlieTabPage.xaml.cs b/samples/DemoApp/Views/Tabs/CharlieTabPage.xaml.cs index 0ea12a6..d69082f 100644 --- a/samples/DemoApp/Views/Tabs/CharlieTabPage.xaml.cs +++ b/samples/DemoApp/Views/Tabs/CharlieTabPage.xaml.cs @@ -1,6 +1,6 @@ namespace DemoApp.Views; -public partial class CharlieTabPage : BurkusContentPage +public partial class CharlieTabPage : ContentPage { public CharlieTabPage() { diff --git a/samples/DemoApp/Views/Tabs/DemoTabsPage.xaml b/samples/DemoApp/Views/Tabs/DemoTabsPage.xaml index 9a31142..b4a6315 100644 --- a/samples/DemoApp/Views/Tabs/DemoTabsPage.xaml +++ b/samples/DemoApp/Views/Tabs/DemoTabsPage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/Tabs/DemoTabsPage.xaml.cs b/samples/DemoApp/Views/Tabs/DemoTabsPage.xaml.cs index 26c2156..aded198 100644 --- a/samples/DemoApp/Views/Tabs/DemoTabsPage.xaml.cs +++ b/samples/DemoApp/Views/Tabs/DemoTabsPage.xaml.cs @@ -1,6 +1,6 @@ namespace DemoApp.Views; -public partial class DemoTabsPage : BurkusTabbedPage +public partial class DemoTabsPage : TabbedPage { public DemoTabsPage() { diff --git a/samples/DemoApp/Views/UriTestPage.xaml b/samples/DemoApp/Views/UriTestPage.xaml index 39e95ca..87a6aba 100644 --- a/samples/DemoApp/Views/UriTestPage.xaml +++ b/samples/DemoApp/Views/UriTestPage.xaml @@ -1,5 +1,5 @@  - - \ No newline at end of file + \ No newline at end of file diff --git a/samples/DemoApp/Views/UriTestPage.xaml.cs b/samples/DemoApp/Views/UriTestPage.xaml.cs index 5873420..3896f1e 100644 --- a/samples/DemoApp/Views/UriTestPage.xaml.cs +++ b/samples/DemoApp/Views/UriTestPage.xaml.cs @@ -1,6 +1,6 @@ namespace DemoApp.Views; -public partial class UriTestPage : BurkusContentPage +public partial class UriTestPage : ContentPage { public UriTestPage() { diff --git a/src/Burkus.Mvvm.Maui.SourceGenerators/AppSourceGenerator.cs b/src/Burkus.Mvvm.Maui.SourceGenerators/AppSourceGenerator.cs index 39309c5..a4c4a3b 100644 --- a/src/Burkus.Mvvm.Maui.SourceGenerators/AppSourceGenerator.cs +++ b/src/Burkus.Mvvm.Maui.SourceGenerators/AppSourceGenerator.cs @@ -8,7 +8,7 @@ namespace Burkus.Mvvm.Maui; [Generator] -public class AppSourceGenerator : ISourceGenerator +internal class AppSourceGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { @@ -33,7 +33,6 @@ public void Execute(GeneratorExecutionContext context) } // get the MAUI program we are running in - var assembly = context.Compilation.Assembly; var mauiProgramName = $"{assembly.Name}.MauiProgram"; var mauiProgram = context.Compilation @@ -54,7 +53,7 @@ public void Execute(GeneratorExecutionContext context) namespace {mauiProgram.ContainingNamespace.ToDisplayString()}; -public partial class App : Application +partial class App {{ protected override Window CreateWindow(IActivationState? activationState) {{ diff --git a/src/Burkus.Mvvm.Maui.SourceGenerators/Burkus.Mvvm.Maui.SourceGenerators.csproj b/src/Burkus.Mvvm.Maui.SourceGenerators/Burkus.Mvvm.Maui.SourceGenerators.csproj index d2c7fc6..dca7623 100644 --- a/src/Burkus.Mvvm.Maui.SourceGenerators/Burkus.Mvvm.Maui.SourceGenerators.csproj +++ b/src/Burkus.Mvvm.Maui.SourceGenerators/Burkus.Mvvm.Maui.SourceGenerators.csproj @@ -12,6 +12,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Burkus.Mvvm.Maui.SourceGenerators/PageSourceGenerator.cs b/src/Burkus.Mvvm.Maui.SourceGenerators/PageSourceGenerator.cs new file mode 100644 index 0000000..0d90a00 --- /dev/null +++ b/src/Burkus.Mvvm.Maui.SourceGenerators/PageSourceGenerator.cs @@ -0,0 +1,87 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using System.Linq; +using System.Text; + +namespace Burkus.Mvvm.Maui; + +[Generator] +public class PageSourceGenerator : ISourceGenerator +{ + public void Initialize(GeneratorInitializationContext context) + { + // No initialization required + } + + public void Execute(GeneratorExecutionContext context) + { + // Get the compilation object that represents the user code + var compilation = context.Compilation; + + // Get the symbols for the base types + var contentPageSymbol = compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.ContentPage"); + var flyoutPageSymbol = compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.FlyoutPage"); + var navigationPageSymbol = compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.NavigationPage"); + var tabbedPageSymbol = compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.TabbedPage"); + + var skipBackButtonGenerationSymbol = compilation.GetTypeByMetadataName("Burkus.Mvvm.Maui.DisableBackButtonNavigatorAttribute"); + + // for each syntax tree, find the class declarations that derive from the base types + foreach (var syntaxTree in compilation.SyntaxTrees) + { + var root = syntaxTree.GetRoot(); + var semanticModel = compilation.GetSemanticModel(syntaxTree); + var classDeclarations = root.DescendantNodes().OfType(); + + // for each class declaration, check if it derives from any of the base types + foreach (var classDeclaration in classDeclarations) + { + // get the symbol for the class declaration + var classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration); + + var attributes = classSymbol.GetAttributes(); + var hasAttribute = attributes.Any(a => a.AttributeClass.Equals(skipBackButtonGenerationSymbol, SymbolEqualityComparer.Default)); + + if (hasAttribute) + { + // don't generate back button handling for this class + continue; + } + + // check if the class symbol inherits from any of the base type symbols + if (classSymbol.BaseType.Equals(contentPageSymbol, SymbolEqualityComparer.Default) || + classSymbol.BaseType.Equals(flyoutPageSymbol, SymbolEqualityComparer.Default) || + classSymbol.BaseType.Equals(navigationPageSymbol, SymbolEqualityComparer.Default) || + classSymbol.BaseType.Equals(tabbedPageSymbol, SymbolEqualityComparer.Default)) + { + // get the name and namespace of the class symbol + var typeName = classSymbol.Name; + var namespaceName = classSymbol.ContainingNamespace.ToDisplayString(); + + // generate the source code for the HandleBackButtonPressed method + var sourceBuilder = $@"// +// This code was generated by a tool. Burkus.Mvvm.Maui generated this. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// + +namespace {namespaceName}; + +partial class {typeName} +{{ + protected override bool OnBackButtonPressed() + {{ + return BackButtonNavigator.HandleBackButtonPressed(); + }} +}}"; + + // Add the source file to the generator output + context.AddSource($"{typeName}-HandleBackButton.g.cs", SourceText.From(sourceBuilder, Encoding.UTF8)); + } + } + } + } +} diff --git a/src/Burkus.Mvvm.Maui/Annotations/DisableBackButtonNavigatorAttribute.cs b/src/Burkus.Mvvm.Maui/Annotations/DisableBackButtonNavigatorAttribute.cs new file mode 100644 index 0000000..3994059 --- /dev/null +++ b/src/Burkus.Mvvm.Maui/Annotations/DisableBackButtonNavigatorAttribute.cs @@ -0,0 +1,11 @@ +namespace Burkus.Mvvm.Maui; + +/// +/// Any , , , +/// or marked with this attribute will be excluded from having +/// being overrided by . +/// +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] +public class DisableBackButtonNavigatorAttribute : Attribute +{ +} \ No newline at end of file diff --git a/src/Burkus.Mvvm.Maui/Models/Pages/BackButtonNavigator.cs b/src/Burkus.Mvvm.Maui/Models/Pages/BackButtonNavigator.cs index 6cd06d1..077c73e 100644 --- a/src/Burkus.Mvvm.Maui/Models/Pages/BackButtonNavigator.cs +++ b/src/Burkus.Mvvm.Maui/Models/Pages/BackButtonNavigator.cs @@ -1,8 +1,8 @@ namespace Burkus.Mvvm.Maui; -internal static class BackButtonNavigator +public static class BackButtonNavigator { - internal static bool HandleBackButtonPressed() + public static bool HandleBackButtonPressed() { var navigationService = ServiceResolver.Resolve(); diff --git a/src/Burkus.Mvvm.Maui/Models/Pages/BurkusContentPage.cs b/src/Burkus.Mvvm.Maui/Models/Pages/BurkusContentPage.cs deleted file mode 100644 index cff98f1..0000000 --- a/src/Burkus.Mvvm.Maui/Models/Pages/BurkusContentPage.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Burkus.Mvvm.Maui; - -public class BurkusContentPage : ContentPage -{ - protected override bool OnBackButtonPressed() - { - return BackButtonNavigator.HandleBackButtonPressed(); - } -} diff --git a/src/Burkus.Mvvm.Maui/Models/Pages/BurkusFlyoutPage.cs b/src/Burkus.Mvvm.Maui/Models/Pages/BurkusFlyoutPage.cs deleted file mode 100644 index c3a9ce3..0000000 --- a/src/Burkus.Mvvm.Maui/Models/Pages/BurkusFlyoutPage.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Burkus.Mvvm.Maui; - -public class BurkusFlyoutPage : FlyoutPage -{ - protected override bool OnBackButtonPressed() - { - return BackButtonNavigator.HandleBackButtonPressed(); - } -} diff --git a/src/Burkus.Mvvm.Maui/Models/Pages/BurkusNavigationPage.cs b/src/Burkus.Mvvm.Maui/Models/Pages/BurkusNavigationPage.cs deleted file mode 100644 index cb4c451..0000000 --- a/src/Burkus.Mvvm.Maui/Models/Pages/BurkusNavigationPage.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Burkus.Mvvm.Maui; - -public class BurkusNavigationPage : NavigationPage -{ - protected override bool OnBackButtonPressed() - { - return BackButtonNavigator.HandleBackButtonPressed(); - } -} diff --git a/src/Burkus.Mvvm.Maui/Models/Pages/BurkusTabbedPage.cs b/src/Burkus.Mvvm.Maui/Models/Pages/BurkusTabbedPage.cs deleted file mode 100644 index 898ff3e..0000000 --- a/src/Burkus.Mvvm.Maui/Models/Pages/BurkusTabbedPage.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Burkus.Mvvm.Maui; - -public class BurkusTabbedPage : TabbedPage -{ - protected override bool OnBackButtonPressed() - { - return BackButtonNavigator.HandleBackButtonPressed(); - } -}