public SectionsNavigatorState( SectionsNavigatorState state, NavigatorRequestState lastRequestState, SectionsNavigatorRequest lastRequest) : this(state.Sections, state.ActiveSection, state.Modals, lastRequestState, lastRequest) { }
private async void OnModalClosedNatively(object sender, ModalClosedEventArgs e) { try { if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug($"Processing native close modal."); } // We schedule on a background thread because most of the work doesn't require any work on the UI thread. await Task.Run(async() => await CloseModal(CancellationToken.None, SectionsNavigatorRequest.GetCloseModalRequest(e.ModalName, transitionInfo: e.TransitionInfo))); } catch (Exception exception) { if (_logger.IsEnabled(LogLevel.Error)) { _logger.LogError($"Failed to process native close modal.", exception); } } finally { if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug($"Processed native close modal."); } } }
/// <summary> /// Opens a new modal. /// </summary> /// <typeparam name="TViewModel">The type of the view model.</typeparam> /// <param name="sectionsNavigator">The sections navigator.</param> /// <param name="ct"></param> /// <param name="viewModelProvider">The method invoked to instanciate the new ViewModel.</param> /// <param name="priority">The modal's priority.</param> /// <param name="name">The modal's name.</param> /// <returns>The newly created ViewModel instance.</returns> public static async Task <TViewModel> OpenModal <TViewModel>(this ISectionsNavigator sectionsNavigator, CancellationToken ct, Func <TViewModel> viewModelProvider, int?priority = null, string name = null) where TViewModel : INavigableViewModel { var modalNavigator = await sectionsNavigator.OpenModal(ct, SectionsNavigatorRequest.GetOpenModalRequest(StackNavigatorRequest.GetNavigateRequest(viewModelProvider, suppressTransition: true), name, priority)); // Note that modalNavigator can be null if the OpenModal gets cancelled. return((TViewModel)modalNavigator?.GetActiveViewModel()); }
/// <summary> /// Sets the active section using the provided section name and navigates. /// </summary> /// <typeparam name="TViewModel">The type of the view model.</typeparam> /// <param name="sectionsNavigator">The sections navigator.</param> /// <param name="ct">The cancellation token.</param> /// <param name="sectionName">The name of the section to set as active.</param> /// <param name="viewModelProvider">The method to make the view model instance. It will be invoked only if necessary.</param> /// <param name="returnToRoot">When this is true, the navigator will navigate back to the view model matching the type <typeparamref name="TViewModel"/>.</param> /// <returns>The stack navigator of the active section.</returns> public static async Task <ISectionStackNavigator> SetActiveSection <TViewModel>(this ISectionsNavigator sectionsNavigator, CancellationToken ct, string sectionName, Func <TViewModel> viewModelProvider, bool returnToRoot = false) where TViewModel : INavigableViewModel { if (ct.IsCancellationRequested) { typeof(SectionsNavigatorExtensions).Log().LogWarning($"Canceled 'SetActiveSection' operation to '{typeof(TViewModel).Name}' because of cancellation token."); return(null); } // No cancellation beyond this point. ct = CancellationToken.None; var sectionNavigator = sectionsNavigator.State.Sections[sectionName]; if (sectionNavigator.State.Stack.LastOrDefault() == null) { // Create the default page if there's nothing in the section. await sectionNavigator.Navigate(ct, StackNavigatorRequest.GetNavigateRequest(viewModelProvider, suppressTransition: true)); } else if (returnToRoot && sectionNavigator.State.Stack.Last().ViewModel.GetType() != typeof(TViewModel)) { if (sectionNavigator.State.Stack.Any(e => e.ViewModel.GetType() == typeof(TViewModel))) { // If the stack contains the root page of the section, remove all other entries and navigate back to it. var indexesToRemove = sectionNavigator.State.Stack .Select((entry, index) => (entry, index)) .Where(t => t.entry.ViewModel.GetType() != typeof(TViewModel) && t.index < sectionNavigator.State.Stack.Count - 1) .Select(t => t.index) .ToList(); await sectionNavigator.RemoveEntries(ct, indexesToRemove); await sectionNavigator.NavigateBack(ct); } else { // If the section root page isn't in the stack, clear everything and navigate to it. await sectionNavigator.Navigate(ct, StackNavigatorRequest.GetNavigateRequest(viewModelProvider, suppressTransition: true, clearBackStack: true)); } } return(await sectionsNavigator.SetActiveSection(ct, SectionsNavigatorRequest.GetSetActiveSectionRequest(sectionName))); }
public SectionsNavigatorState( IReadOnlyDictionary <string, ISectionStackNavigator> sections, ISectionStackNavigator activeSection, IReadOnlyList <IModalStackNavigator> modals, NavigatorRequestState lastRequestState, SectionsNavigatorRequest lastRequest) { Sections = sections; ActiveSection = activeSection; Modals = modals; ActiveModal = modals?.LastOrDefault(); LastRequestState = lastRequestState; LastRequest = lastRequest; }
/// <summary> /// Closes the top-most modal. /// </summary> /// <param name="sectionsNavigator">The sections navigator.</param> /// <param name="ct">The cancellation token.</param> public static async Task CloseModal(this ISectionsNavigator sectionsNavigator, CancellationToken ct) { await sectionsNavigator.CloseModal(ct, SectionsNavigatorRequest.GetCloseModalRequest(modalPriority: null)); }
/// <summary> /// Sets the active section using the provided section name. /// </summary> /// <param name="sectionsNavigator">The sections navigator.</param> /// <param name="ct">The cancellation token.</param> /// <param name="sectionName">The name of the section to set as active.</param> /// <returns>The stack navigator of the active section.</returns> public static Task <ISectionStackNavigator> SetActiveSection(this ISectionsNavigator sectionsNavigator, CancellationToken ct, string sectionName) { return(sectionsNavigator.SetActiveSection(ct, SectionsNavigatorRequest.GetSetActiveSectionRequest(sectionName))); }