using System; using System.ComponentModel; using Marechai.App.Presentation.ViewModels; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; namespace Marechai.App.Presentation.Views; public sealed partial class MainPage : Page { private PropertyChangedEventHandler _sidebarPropertyChangedHandler; public MainPage() { InitializeComponent(); DataContextChanged += MainPage_DataContextChanged; Loaded += MainPage_Loaded; } private void MainPage_Loaded(object sender, RoutedEventArgs e) { if(DataContext is not MainViewModel viewModel) return; SidebarWrapper.Width = viewModel.IsSidebarOpen ? 280 : 60; if(_sidebarPropertyChangedHandler != null) return; _sidebarPropertyChangedHandler = (_, propArgs) => { if(propArgs.PropertyName != nameof(MainViewModel.IsSidebarOpen)) return; AnimateSidebarWidth(((MainViewModel)DataContext).IsSidebarOpen); }; ((INotifyPropertyChanged)viewModel).PropertyChanged += _sidebarPropertyChangedHandler; } void AnimateSidebarWidth(bool isOpen) { double start = SidebarColumn.Width.Value; double end = isOpen ? 280 : 60; if(Math.Abs(start - end) < 0.1) return; // If expanding, show content immediately if(isOpen && DataContext is MainViewModel vm) vm.SidebarContentVisible = true; const int durationMs = 250; const int fps = 60; var steps = (int)(durationMs / (1000.0 / fps)); var currentStep = 0; var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(1000.0 / fps) }; timer.Tick += (_, _) => { currentStep++; double t = (double)currentStep / steps; // Ease in-out cubic double eased = t < 0.5 ? 4 * t * t * t : 1 - Math.Pow(-2 * t + 2, 3) / 2; double value = start + (end - start) * eased; SidebarColumn.Width = new GridLength(value, GridUnitType.Pixel); SidebarWrapper.Width = value; if(currentStep >= steps) { SidebarColumn.Width = new GridLength(end, GridUnitType.Pixel); SidebarWrapper.Width = end; timer.Stop(); // After collapse animation completes, hide sidebar content if(!isOpen && DataContext is MainViewModel vm) vm.SidebarContentVisible = false; } }; timer.Start(); } private void MainPage_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args) { if(args.NewValue is MainViewModel vm && _sidebarPropertyChangedHandler == null) { SidebarWrapper.Width = vm.IsSidebarOpen ? 280 : 60; _sidebarPropertyChangedHandler = (_, propArgs) => { if(propArgs.PropertyName != nameof(MainViewModel.IsSidebarOpen)) return; AnimateSidebarWidth(vm.IsSidebarOpen); }; ((INotifyPropertyChanged)vm).PropertyChanged += _sidebarPropertyChangedHandler; } } }