using System; using System.Diagnostics; using CommunityToolkit.Mvvm.Messaging; using Microsoft.Extensions.DependencyInjection; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using Wino.Core.ViewModels; using Wino.Messaging.Client.Shell; using WinoNavigationMode = Wino.Core.Domain.Models.Navigation.NavigationMode; namespace Wino.Mail.WinUI; public partial class BasePage : Page, IRecipient { private bool _isPreparedForClose; public void Receive(LanguageChanged message) { OnLanguageChanged(); } public virtual void OnLanguageChanged() { } /// /// Register message recipients for this page. Override to register specific message types. /// protected virtual void RegisterRecipients() { } /// /// Unregister message recipients for this page. Override to unregister specific message types. /// protected virtual void UnregisterRecipients() { } public virtual CoreBaseViewModel? AssociatedViewModel => null; public virtual void PrepareForClose() { if (_isPreparedForClose) return; _isPreparedForClose = true; WeakReferenceMessenger.Default.Unregister(this); UnregisterRecipients(); } protected void ResetPreparedForCloseState() { _isPreparedForClose = false; } protected bool IsPreparedForClose => _isPreparedForClose; } public abstract class BasePage : BasePage where T : CoreBaseViewModel { public T ViewModel { get; } = WinoApplication.Current.Services.GetService() ?? throw new ArgumentException($"Can't resolve '{typeof(T)}' as view model."); public override CoreBaseViewModel AssociatedViewModel => ViewModel; protected BasePage() { ViewModel.Dispatcher = new WinUIDispatcher(DispatcherQueue); Loaded += PageLoaded; Unloaded += PageUnloaded; } private void PageUnloaded(object sender, RoutedEventArgs e) { Loaded -= PageLoaded; Unloaded -= PageUnloaded; } private void PageLoaded(object sender, RoutedEventArgs e) => ViewModel.OnPageLoaded(); ~BasePage() { Debug.WriteLine($"Disposed {GetType().Name}"); } protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); var mode = GetNavigationMode(e.NavigationMode); var parameter = e.Parameter; ResetPreparedForCloseState(); WeakReferenceMessenger.Default.Register(this); RegisterRecipients(); ViewModel.OnNavigatedTo(mode, parameter); } protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) { base.OnNavigatingFrom(e); var mode = GetNavigationMode(e.NavigationMode); var parameter = e.Parameter; PrepareForClose(mode, parameter); GC.Collect(); } public override void PrepareForClose() { PrepareForClose(WinoNavigationMode.New, null); } private void PrepareForClose(WinoNavigationMode mode, object? parameter) { if (IsPreparedForClose) return; base.PrepareForClose(); ViewModel.OnNavigatedFrom(mode, parameter!); } private WinoNavigationMode GetNavigationMode(NavigationMode mode) { return (WinoNavigationMode)mode; } }