Skip to content

Commit

Permalink
breaking changes: regions are now async (added init async, loaded asy…
Browse files Browse the repository at this point in the history
…nc awares), added ILoaded aware and async version
  • Loading branch information
Alex-Dobrynin committed Oct 18, 2024
1 parent 4560af2 commit d818e66
Show file tree
Hide file tree
Showing 21 changed files with 176 additions and 47 deletions.
13 changes: 13 additions & 0 deletions MPowerKit.Navigation.Core/Awares/ILoadedAware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using MPowerKit.Navigation.Interfaces;

namespace MPowerKit.Navigation.Awares;

public interface ILoadedAware
{
void OnLoaded(INavigationParameters navigationParameters);
}

public interface ILoadedAsyncAware
{
Task OnLoadedAsync(INavigationParameters navigationParameters);
}
6 changes: 3 additions & 3 deletions MPowerKit.Navigation.Core/Interfaces/IRegion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

public interface IRegion
{
NavigationResult ReplaceAll(string viewName, INavigationParameters? parameters);
NavigationResult Push(string viewName, INavigationParameters? parameters);
NavigationResult PushBackwards(string viewName, INavigationParameters? parameters);
ValueTask<NavigationResult> ReplaceAll(string viewName, INavigationParameters? parameters);
ValueTask<NavigationResult> Push(string viewName, INavigationParameters? parameters);
ValueTask<NavigationResult> PushBackwards(string viewName, INavigationParameters? parameters);
NavigationResult GoBack(INavigationParameters? parameters);
NavigationResult GoForward(INavigationParameters? parameters);
NavigationResult GoByName(string viewName, INavigationParameters? parameters);
Expand Down
2 changes: 1 addition & 1 deletion MPowerKit.Navigation.Core/Interfaces/IRegionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

public interface IRegionManager
{
NavigationResult NavigateTo(string regionName, string viewName, INavigationParameters? parameters = null);
ValueTask<NavigationResult> NavigateTo(string regionName, string viewName, INavigationParameters? parameters = null);
IEnumerable<IRegion> GetRegions(VisualElement? regionHolder);
}
2 changes: 1 addition & 1 deletion MPowerKit.Navigation.Core/MPowerKit.Navigation.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>MPowerKit.Navigation.Core</Title>
<Version>1.2.1</Version>
<Version>1.3.0</Version>
<Authors>MPowerKit,Alex Dobrynin</Authors>
<Description>.NET MAUI MVVM navigation framework. It supports regular/modal navigation, opening/closing windows, regions</Description>
<Copyright>MPowerKit</Copyright>
Expand Down
33 changes: 33 additions & 0 deletions MPowerKit.Navigation.Core/Utilities/MvvmHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,39 @@ public static bool IsParentRegionHolder(Element? initialView, Element? regionHol
return false;
}

public static async Task OnPageLoadedRecursively(Page target, INavigationParameters parameters)
{
OnLoaded(target, parameters);
await OnLoadedAsync(target, parameters);

if (target is NavigationPage np)
{
await OnPageLoadedRecursively(np.CurrentPage, parameters);
}
else if (target is TabbedPage tp)
{
foreach (var item in tp.Children)
{
await OnPageLoadedRecursively(item, parameters);
}
}
else if (target is FlyoutPage fp)
{
await OnPageLoadedRecursively(fp.Flyout, parameters);
await OnPageLoadedRecursively(fp.Detail, parameters);
}
}

public static void OnLoaded(VisualElement target, INavigationParameters parameters)
{
InvokeViewAndViewModelAction<ILoadedAware>(target, v => v.OnLoaded(parameters));
}

public static Task OnLoadedAsync(VisualElement target, INavigationParameters parameters)
{
return InvokeViewAndViewModelActionAsync<ILoadedAsyncAware>(target, v => v.OnLoadedAsync(parameters));
}

public static void PageNavigatedRecursively(Page target, INavigationParameters parameters, bool to)
{
var child = target switch
Expand Down
2 changes: 1 addition & 1 deletion MPowerKit.Navigation.Popups/Awares/IPopupDialogAware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ namespace MPowerKit.Navigation.Awares;

public interface IPopupDialogAware
{
public Action<(Confirmation Confirmation, bool Animated)> RequestClose { get; set; }
public Action<(Confirmation Confirmation, bool Animated)>? RequestClose { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace MPowerKit.Navigation.Interfaces;
public interface IPopupNavigationService
{
ValueTask<PopupResult> ShowAwaitablePopupAsync(string popupName, INavigationParameters? parameters = null, bool animated = true);
ValueTask<NavigationResult> ShowPopupAsync(string popupName, INavigationParameters? parameters = null, bool animated = true, Action<Confirmation>? closeAction = null);
ValueTask<NavigationResult> ShowPopupAsync(string popupName, INavigationParameters? parameters = null, bool animated = true, Action<Confirmation?>? closeAction = null);
ValueTask<NavigationResult> HidePopupAsync(bool animated = true);
ValueTask<NavigationResult> HidePopupAsync(PopupPage page, bool animated = true);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>MPowerKit.Navigation.Popups</Title>
<Version>1.2.1.4</Version>
<Version>1.3.0</Version>
<Authors>MPowerKit,Alex Dobrynin</Authors>
<Description>.NET MAUI MVVM navigation framework. It supports regular/modal navigation, opening/closing windows, regions, popups</Description>
<Copyright>MPowerKit</Copyright>
Expand Down
2 changes: 1 addition & 1 deletion MPowerKit.Navigation.Popups/MPowerKitPopupsWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public MPowerKitPopupsWindow(IPopupNavigationService popupNavigationService)

protected override bool OnBackButtonClicked()
{
var navigationPopupService = this.Handler.MauiContext.Services.GetRequiredService<INavigationPopupService>();
var navigationPopupService = this.Handler.MauiContext!.Services.GetRequiredService<INavigationPopupService>();

var popup = navigationPopupService.PopupStack.FirstOrDefault(p => p.Window == this);

Expand Down
2 changes: 1 addition & 1 deletion MPowerKit.Navigation/MPowerKit.Navigation.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>MPowerKit.Navigation</Title>
<Version>1.2.1</Version>
<Version>1.3.0</Version>
<Authors>MPowerKit,Alex Dobrynin</Authors>
<Description>.NET MAUI MVVM navigation framework. It supports regular/modal navigation, opening/closing windows, regions</Description>
<Copyright>MPowerKit</Copyright>
Expand Down
5 changes: 5 additions & 0 deletions MPowerKit.Navigation/NavigationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ protected virtual async ValueTask GoBackModally(INavigationParameters parameters

public virtual async ValueTask<NavigationResult> NavigateAsync(string stringUri, INavigationParameters? parameters = null, bool modal = false, bool animated = true)
{
// need to be here to wait until ui finish its important work
await Task.Delay(1);

parameters ??= new NavigationParameters();

try
Expand Down Expand Up @@ -299,6 +302,8 @@ public virtual async ValueTask<NavigationResult> NavigateAsync(string stringUri,
await DoRelativeNavigation(pages, parameters, animated);
}

if (pages?.Count > 0) await MvvmHelpers.OnPageLoadedRecursively(pages[0]!, parameters);

return new NavigationResult(true, null);
}
catch (Exception ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ public override void ViewDidLoad()
{
base.ViewDidLoad();

this.InteractivePopGestureRecognizer.Delegate = new SwipeBackDelegate(this);
InteractivePopGestureRecognizer.Delegate = new SwipeBackDelegate(this);
}

public override void ViewWillDisappear(bool animated)
{
this.InteractivePopGestureRecognizer.Delegate = null;
InteractivePopGestureRecognizer.Delegate = null;

base.ViewWillDisappear(animated);
}
Expand Down
2 changes: 1 addition & 1 deletion MPowerKit.Regions/MPowerKit.Regions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>MPowerKit.Regions</Title>
<Version>1.2.1</Version>
<Version>1.3.0</Version>
<Authors>MPowerKit,Alex Dobrynin</Authors>
<Description>.NET MAUI MVVM navigation framework. It supports regular/modal navigation, opening/closing windows, regions</Description>
<Copyright>MPowerKit</Copyright>
Expand Down
55 changes: 40 additions & 15 deletions MPowerKit.Regions/Region.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,19 @@ public Region(IServiceProvider serviceProvider,
RegionManager = regionManager;
RegionAccessor = regionAccessor;

RegionHolder.Content = StackContainer;
RegionHolder!.Content = StackContainer;
}

public virtual NavigationResult ReplaceAll(string viewName, INavigationParameters? parameters)
public virtual async ValueTask<NavigationResult> ReplaceAll(string viewName, INavigationParameters? parameters)
{
// need to be here to wait until ui finish its important work
await Task.Delay(1);

parameters ??= new NavigationParameters();

try
{
var view = InitView(viewName, parameters);
var view = await InitView(viewName, parameters);

var viewsToRemove = RegionStack.Reverse().ToList();

Expand All @@ -67,6 +70,8 @@ public virtual NavigationResult ReplaceAll(string viewName, INavigationParameter
DestroyRecursively(item);
}

await OnLoadded(parameters);

return new NavigationResult(true, null);
}
catch (Exception ex)
Expand All @@ -75,13 +80,16 @@ public virtual NavigationResult ReplaceAll(string viewName, INavigationParameter
}
}

public virtual NavigationResult Push(string viewName, INavigationParameters? parameters)
public virtual async ValueTask<NavigationResult> Push(string viewName, INavigationParameters? parameters)
{
// need to be here to wait until ui finish its important work
await Task.Delay(1);

parameters ??= new NavigationParameters();

try
{
var view = InitView(viewName, parameters);
var view = await InitView(viewName, parameters);

var index = RegionStack.Count - 1;

Expand All @@ -105,6 +113,8 @@ public virtual NavigationResult Push(string viewName, INavigationParameters? par
DestroyRecursively(item);
}

await OnLoadded(parameters);

return new NavigationResult(true, null);
}
catch (Exception ex)
Expand All @@ -113,13 +123,16 @@ public virtual NavigationResult Push(string viewName, INavigationParameters? par
}
}

public virtual NavigationResult PushBackwards(string viewName, INavigationParameters? parameters)
public virtual async ValueTask<NavigationResult> PushBackwards(string viewName, INavigationParameters? parameters)
{
// need to be here to wait until ui finish its important work
await Task.Delay(1);

parameters ??= new NavigationParameters();

try
{
var view = InitView(viewName, parameters);
var view = await InitView(viewName, parameters);

var index = 0;

Expand All @@ -143,6 +156,8 @@ public virtual NavigationResult PushBackwards(string viewName, INavigationParame
DestroyRecursively(item);
}

await OnLoadded(parameters);

return new NavigationResult(true, null);
}
catch (Exception ex)
Expand All @@ -151,13 +166,20 @@ public virtual NavigationResult PushBackwards(string viewName, INavigationParame
}
}

protected virtual View InitView(string viewName, INavigationParameters parameters)
protected virtual async ValueTask OnLoadded(INavigationParameters parameters)
{
MvvmHelpers.OnLoaded(CurrentView!, parameters);
await MvvmHelpers.OnLoadedAsync(CurrentView!, parameters);
}

protected virtual async ValueTask<View> InitView(string viewName, INavigationParameters parameters)
{
var view = (ServiceProvider.GetViewAndViewModel(viewName) as View)!;

ViewRegionViewNameAttached.SetRegionViewName(view, viewName);

MvvmHelpers.OnInitialized(view, parameters);
await MvvmHelpers.OnInitializedAsync(view, parameters);

BehaviorExtensions.ApplyBehaviors(ServiceProvider, view);

Expand All @@ -176,7 +198,7 @@ public virtual bool CanGoForward()

public virtual bool CanGoByName(string viewName)
{
return (RegionStack as List<VisualElement>).Exists(v => ViewRegionViewNameAttached.GetRegionViewName(v) == viewName);
return RegionStack.Any(v => ViewRegionViewNameAttached.GetRegionViewName(v) == viewName);
}

public virtual NavigationResult GoBack(INavigationParameters? parameters)
Expand Down Expand Up @@ -249,7 +271,7 @@ public virtual NavigationResult GoByName(string viewName, INavigationParameters?
throw new InvalidOperationException("Cannot go by view name");
}

var viewNavigateTo = (RegionStack as List<VisualElement>).Find(v => ViewRegionViewNameAttached.GetRegionViewName(v) == viewName);
var viewNavigateTo = RegionStack.FirstOrDefault(v => ViewRegionViewNameAttached.GetRegionViewName(v) == viewName);

if (viewNavigateTo == CurrentView)
{
Expand All @@ -258,7 +280,7 @@ public virtual NavigationResult GoByName(string viewName, INavigationParameters?

var index = RegionStack.IndexOf(CurrentView!);

var indexNavigateTo = RegionStack.IndexOf(viewNavigateTo);
var indexNavigateTo = RegionStack.IndexOf(viewNavigateTo!);

parameters[KnownNavigationParameters.NavigationDirection] = index > indexNavigateTo ? NavigationDirection.Back : NavigationDirection.Forward;

Expand All @@ -283,9 +305,12 @@ public virtual void NavigatedRecursively(INavigationParameters parameters, bool
MvvmHelpers.Navigated(CurrentView, parameters, to);
}

foreach (var region in RegionManager.GetRegions(RegionHolder))
if (parameters.GetNavigationDirection() != NavigationDirection.New)
{
region.NavigatedRecursively(parameters, to);
foreach (var region in RegionManager.GetRegions(CurrentView))
{
region.NavigatedRecursively(parameters, to);
}
}

if (!to)
Expand Down Expand Up @@ -333,7 +358,7 @@ public virtual void OnWindowLifecycleRecursively(bool resume)
MvvmHelpers.WindowLifecycle(view, resume);
}

foreach (var region in RegionManager.GetRegions(RegionHolder))
foreach (var region in RegionManager.GetRegions(StackContainer))
{
region.OnWindowLifecycleRecursively(resume);
}
Expand All @@ -349,7 +374,7 @@ public virtual void OnPageLifecycleRecursively(bool appearing)
}
}

foreach (var region in RegionManager.GetRegions(RegionHolder))
foreach (var region in RegionManager.GetRegions(StackContainer))
{
region.OnPageLifecycleRecursively(appearing);
}
Expand Down
8 changes: 4 additions & 4 deletions MPowerKit.Regions/RegionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ public RegionManager(IServiceProvider serviceProvider)
ServiceProvider = serviceProvider;
}

public virtual NavigationResult NavigateTo(string regionName, string viewName, INavigationParameters? parameters = null)
public virtual async ValueTask<NavigationResult> NavigateTo(string regionName, string viewName, INavigationParameters? parameters = null)
{
parameters ??= new NavigationParameters();

try
{
if (!_regionHolders.ContainsKey(regionName))
if (!_regionHolders.TryGetValue(regionName, out WeakReference<ContentView>? value))
{
throw new ArgumentNullException($"There is not registered region with name {regionName}");
}

var regionHolder = (_regionHolders[regionName].TryGetTarget(out var target) ? target : null)
var regionHolder = (value.TryGetTarget(out var target) ? target : null)
?? throw new NullReferenceException("Region was disposed");

var scope = ViewServiceProviderAttached.GetServiceScope(regionHolder);
Expand Down Expand Up @@ -57,7 +57,7 @@ public virtual NavigationResult NavigateTo(string regionName, string viewName, I

var region = scope.ServiceProvider.GetRequiredService<IRegion>();

return region.ReplaceAll(viewName, parameters);
return await region.ReplaceAll(viewName, parameters);
}
catch (Exception ex)
{
Expand Down
1 change: 1 addition & 0 deletions Sample/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public static MauiApp CreateMauiApp()
s.RegisterForNavigation<MainPage>();
s.RegisterForNavigation<NewPage1>();
s.RegisterForNavigation<NewContent1>();
s.RegisterForNavigation<NewContent2>();
s.RegisterForNavigation<PopupPageTest>();
s.RegisterForNavigation<FlyPage>();
})
Expand Down
4 changes: 3 additions & 1 deletion Sample/NewContent1.xaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentView x:Class="Sample.NewContent1"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mpk="clr-namespace:MPowerKit.Regions;assembly=MPowerKit.Regions">
<VerticalStackLayout>
<Label HorizontalOptions="Center"
Text="Welcome to .NET MAUI!"
VerticalOptions="Center" />
<ContentView mpk:RegionManager.RegionName="NewRegion" />
</VerticalStackLayout>
</ContentView>
Loading

0 comments on commit d818e66

Please sign in to comment.