-
Notifications
You must be signed in to change notification settings - Fork 1
Fix/code review issues #44
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
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
cfee3b8
fix: StartTime should use DateTimeOffset.UtcNow instead of DateTime.U…
NeverMorewd 5bcaeac
fix: FrontShowAsync window overload discarded close task causing unob…
NeverMorewd d64740e
fix: ObserveCloseTask silently swallowed dialog close exceptions
NeverMorewd 21e5537
fix: rename GoForward/GoBack to GoForwardAsync/GoBackAsync in IRegion…
NeverMorewd d1d3118
fix: add [Obsolete] attribute to MaxCachedViews to enforce documented…
NeverMorewd ff7374b
fix: correct spelling of AddSingletonWitAllMembers/AddTransientWitAll…
NeverMorewd fd97b4d
fix: correct typo OnResovleViewAsync -> OnResolveViewAsync in RegionN…
NeverMorewd c0f35b0
fix: WeakAsyncEventHandler use generic WeakReference<T> and fix TOCTO…
NeverMorewd 00dc5b1
fix: AsyncJobProcessor CancelCurrent strategy must await job completi…
NeverMorewd 19d5283
fix: NavigationResult factory methods should not mutate NavigationCon…
NeverMorewd b1793f5
fix: NavigationOptions.MergeFrom compared against Default.X causing s…
NeverMorewd ab6173e
feat: add NavigationAwareBase abstract base class to reduce INavigati…
NeverMorewd cfda239
feat: add INavigationGuard to support blocking navigation (e.g. unsav…
NeverMorewd d608ac0
feat: add INavigationInterceptor for global navigation hooks (auth, l…
NeverMorewd cc7e5ac
feat: extract FrontShowAsync from core IDialogService to platform-spe…
NeverMorewd c445293
fix: remove spurious 'new' keyword and add missing 'where TWindow : c…
NeverMorewd 01d7d7e
ignore local settings
NeverMorewd File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| using AsyncNavigation; | ||
| using AsyncNavigation.Abstractions; | ||
| using AsyncNavigation.Core; | ||
|
|
||
| namespace AsyncNavigation.Avalonia; | ||
|
|
||
| /// <summary> | ||
| /// Avalonia-specific dialog service. Extends <see cref="DialogService"/> with | ||
| /// <see cref="IAvaloniaDialogService"/> which exposes the front-show pattern under | ||
| /// the clearer <c>FrontShowViewAsync</c> / <c>FrontShowWindowAsync</c> names. | ||
| /// </summary> | ||
| internal sealed class AvaloniaDialogService : DialogService, IAvaloniaDialogService | ||
| { | ||
| public AvaloniaDialogService(IServiceProvider serviceProvider, IPlatformService platformService) | ||
| : base(serviceProvider, platformService) | ||
| { | ||
| } | ||
|
|
||
| Task IAvaloniaDialogService.FrontShowViewAsync<TWindow>( | ||
| string viewName, | ||
| Func<IDialogResult, TWindow?> mainWindowBuilder, | ||
| string? containerName, | ||
| IDialogParameters? parameters, | ||
| CancellationToken cancellationToken) where TWindow : class | ||
| => FrontShowAsync(viewName, mainWindowBuilder, containerName, parameters, cancellationToken); | ||
|
|
||
| Task IAvaloniaDialogService.FrontShowWindowAsync<TWindow>( | ||
| string windowName, | ||
| Func<IDialogResult, TWindow?> mainWindowBuilder, | ||
| IDialogParameters? parameters, | ||
| CancellationToken cancellationToken) where TWindow : class | ||
| => FrontShowAsync(windowName, mainWindowBuilder, parameters, cancellationToken); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| using AsyncNavigation.Abstractions; | ||
| using AsyncNavigation.Core; | ||
|
|
||
| namespace AsyncNavigation.Avalonia; | ||
|
|
||
| /// <summary> | ||
| /// Avalonia-specific dialog service that extends <see cref="IDialogService"/> with | ||
| /// the <c>FrontShowAsync</c> pattern for showing a dialog (e.g. splash screen or | ||
| /// login window) before the main application window is displayed. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// Register and resolve this interface instead of <see cref="IDialogService"/> in | ||
| /// Avalonia applications when you need the front-show functionality at startup. | ||
| /// The underlying <see cref="AsyncNavigation.DialogService"/> implements both | ||
| /// interfaces, so resolving <see cref="IAvaloniaDialogService"/> will return the | ||
| /// same service instance. | ||
| /// </remarks> | ||
| public interface IAvaloniaDialogService : IDialogService | ||
| { | ||
| /// <summary> | ||
| /// Displays a dialog view (e.g., a splash screen or login form hosted inside a | ||
| /// container window) before showing the main application window. | ||
| /// </summary> | ||
| /// <typeparam name="TWindow">The main window type to create after the dialog closes.</typeparam> | ||
| /// <param name="viewName">The registered name of the dialog view content.</param> | ||
| /// <param name="mainWindowBuilder"> | ||
| /// A factory that receives the dialog result and returns the main window instance, | ||
| /// or <see langword="null"/> to suppress main window creation. | ||
| /// </param> | ||
| /// <param name="containerName">Optional container window name; uses the default container if omitted.</param> | ||
| /// <param name="parameters">Optional parameters passed to the dialog view model.</param> | ||
| /// <param name="cancellationToken">Token to cancel the operation.</param> | ||
| Task FrontShowViewAsync<TWindow>( | ||
| string viewName, | ||
| Func<IDialogResult, TWindow?> mainWindowBuilder, | ||
| string? containerName = null, | ||
| IDialogParameters? parameters = null, | ||
| CancellationToken cancellationToken = default) where TWindow : class; | ||
|
|
||
| /// <summary> | ||
| /// Displays a dialog window (e.g., a splash screen or login window) before showing | ||
| /// the main application window. | ||
| /// </summary> | ||
| /// <typeparam name="TWindow">The main window type to create after the dialog closes.</typeparam> | ||
| /// <param name="windowName">The registered name of the dialog window.</param> | ||
| /// <param name="mainWindowBuilder"> | ||
| /// A factory that receives the dialog result and returns the main window instance, | ||
| /// or <see langword="null"/> to suppress main window creation. | ||
| /// </param> | ||
| /// <param name="parameters">Optional parameters passed to the dialog window view model.</param> | ||
| /// <param name="cancellationToken">Token to cancel the operation.</param> | ||
| Task FrontShowWindowAsync<TWindow>( | ||
| string windowName, | ||
| Func<IDialogResult, TWindow?> mainWindowBuilder, | ||
| IDialogParameters? parameters = null, | ||
| CancellationToken cancellationToken = default) where TWindow : class; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| namespace AsyncNavigation.Abstractions; | ||
|
|
||
| /// <summary> | ||
| /// Allows a view model to block or confirm a navigation request before it proceeds. | ||
| /// Implement this interface alongside <see cref="INavigationAware"/> to intercept | ||
| /// navigations away from the current view (e.g., unsaved-changes confirmation). | ||
| /// </summary> | ||
| /// <example> | ||
| /// <code> | ||
| /// public class EditViewModel : NavigationAwareBase, INavigationGuard | ||
| /// { | ||
| /// public async Task<bool> CanNavigateAsync(NavigationContext context, CancellationToken ct) | ||
| /// { | ||
| /// if (!HasUnsavedChanges) return true; | ||
| /// return await _dialogService.ConfirmAsync("Discard unsaved changes?", ct); | ||
| /// } | ||
| /// } | ||
| /// </code> | ||
| /// </example> | ||
| public interface INavigationGuard | ||
| { | ||
| /// <summary> | ||
| /// Called before navigating away from the current view. | ||
| /// Return <see langword="true"/> to allow the navigation to proceed, | ||
| /// or <see langword="false"/> to cancel it. | ||
| /// </summary> | ||
| /// <param name="context">The navigation context for the incoming navigation request.</param> | ||
| /// <param name="cancellationToken">Token to cancel the guard check itself.</param> | ||
| Task<bool> CanNavigateAsync(NavigationContext context, CancellationToken cancellationToken); | ||
| } |
43 changes: 43 additions & 0 deletions
43
src/AsyncNavigation/Abstractions/INavigationInterceptor.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| namespace AsyncNavigation.Abstractions; | ||
|
|
||
| /// <summary> | ||
| /// Globally intercepts navigation requests across all regions. | ||
| /// Register an implementation via <c>RegisterNavigationInterceptor<T>()</c>. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// Interceptors run in registration order and are invoked for every navigation request | ||
| /// regardless of region or view. Common uses: authentication checks, analytics/logging, | ||
| /// global error handling, or A/B redirect logic. | ||
| /// </remarks> | ||
| /// <example> | ||
| /// <code> | ||
| /// public class AuthInterceptor : INavigationInterceptor | ||
| /// { | ||
| /// public Task OnNavigatingAsync(NavigationContext context) | ||
| /// { | ||
| /// if (!_auth.IsLoggedIn) | ||
| /// throw new OperationCanceledException("Not authenticated."); | ||
| /// return Task.CompletedTask; | ||
| /// } | ||
| /// | ||
| /// public Task OnNavigatedAsync(NavigationContext context) => Task.CompletedTask; | ||
| /// } | ||
| /// | ||
| /// // Registration: | ||
| /// services.RegisterNavigationInterceptor<AuthInterceptor>(); | ||
| /// </code> | ||
| /// </example> | ||
| public interface INavigationInterceptor | ||
| { | ||
| /// <summary> | ||
| /// Called before navigation begins (before the pipeline runs). | ||
| /// Throw <see cref="OperationCanceledException"/> to abort the navigation. | ||
| /// </summary> | ||
| Task OnNavigatingAsync(NavigationContext context); | ||
|
|
||
| /// <summary> | ||
| /// Called after navigation completes successfully. | ||
| /// Exceptions thrown here are logged but do not affect the navigation result. | ||
| /// </summary> | ||
| Task OnNavigatedAsync(NavigationContext context); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In
HandleExistingJobs, theCancelCurrentbranch now doesawait WaitAllAsync()immediately after cancellation, butWaitAllAsync()propagatesTaskCanceledException/OperationCanceledExceptionfrom the jobs that were just canceled. When a running job correctly throws on cancellation (e.g.,Task.Delay(..., ct)), this exception escapesRunJobAsyncbefore the new job is added, so the replacement navigation never starts. This breaks the coreCancelCurrentbehavior under normal cancellable workloads.Useful? React with 👍 / 👎.