using System.Linq; using Avalonia; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Layout; using Avalonia.Media; using ClaudeDo.Ui.ViewModels; using ClaudeDo.Ui.ViewModels.Islands; using ClaudeDo.Ui.ViewModels.Modals; using ClaudeDo.Ui.Views.Modals; using ClaudeDo.Ui.Views.Planning; namespace ClaudeDo.Ui.Views; public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); KeyDown += OnWindowKeyDown; DataContextChanged += OnDataContextChanged; } private void OnDataContextChanged(object? sender, EventArgs e) { if (DataContext is IslandsShellViewModel vm) { vm.ShowConflictDialog = async (conflictVm) => { var modal = new ConflictResolutionView { DataContext = conflictVm }; await modal.ShowDialog(this); }; vm.ShowAboutModal = async (aboutVm) => { var dlg = new AboutModalView { DataContext = aboutVm }; var tcs = new TaskCompletionSource(); aboutVm.CloseAction = () => { dlg.Close(); tcs.TrySetResult(true); }; await dlg.ShowDialog(this); }; vm.ShowWorktreesOverviewModal = async (modal) => { var dlg = new WorktreesOverviewModalView { DataContext = modal }; modal.CloseAction = () => dlg.Close(); modal.JumpToTaskAction = (listId, taskId) => { if (DataContext is IslandsShellViewModel s) _ = JumpToTaskAsync(s, listId, taskId); }; modal.ShowDiffAction = diffVm => { var diffDlg = new WorktreeModalView { DataContext = diffVm }; diffVm.CloseAction = () => diffDlg.Close(); _ = diffVm.LoadAsync(); _ = diffDlg.ShowDialog(this); }; modal.ConfirmAction = ShowConfirmAsync; modal.ResolveMergeVm = vm.ResolveMergeVm; modal.ShowMergeAction = async mergeVm => { var mergeDlg = new MergeModalView { DataContext = mergeVm }; await mergeDlg.ShowDialog(this); }; await dlg.ShowDialog(this); }; vm.ShowRepoImportModal = async (modal) => { var dlg = new RepoImportModalView { DataContext = modal }; modal.CloseAction = () => dlg.Close(); await dlg.ShowDialog(this); }; } } private void OnWindowKeyDown(object? sender, KeyEventArgs e) { if (e.Key == Key.Space && FocusManager?.GetFocusedElement() is not TextBox && DataContext is IslandsShellViewModel vm) { e.Handled = true; _ = vm.ToggleSelectedDoneAsync(); } } private void OnTitleBarPressed(object? sender, PointerPressedEventArgs e) { if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) BeginMoveDrag(e); } private void OnMinimize(object? s, Avalonia.Interactivity.RoutedEventArgs e) => WindowState = WindowState.Minimized; private void OnToggleMax(object? s, Avalonia.Interactivity.RoutedEventArgs e) => WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized; private void OnClose(object? s, Avalonia.Interactivity.RoutedEventArgs e) => Close(); protected override void OnSizeChanged(SizeChangedEventArgs e) { base.OnSizeChanged(e); if (DataContext is IslandsShellViewModel vm) vm.WindowWidth = Bounds.Width; } private static System.Threading.Tasks.Task JumpToTaskAsync(IslandsShellViewModel s, string listId, string taskId) => JumpToTaskHelper.SelectAsync(s, listId, taskId); private async System.Threading.Tasks.Task ShowConfirmAsync(string message) { var tcs = new TaskCompletionSource(); var cancel = new Button { Content = "Cancel", MinWidth = 90 }; var confirm = new Button { Content = "Confirm", MinWidth = 90, Classes = { "danger" } }; var dialog = new Window { Title = "Confirm", Width = 380, SizeToContent = SizeToContent.Height, CanResize = false, WindowStartupLocation = WindowStartupLocation.CenterOwner, ShowInTaskbar = false, Background = this.FindResource("SurfaceBrush") as IBrush, Content = new StackPanel { Margin = new Thickness(20), Spacing = 16, Children = { new TextBlock { Text = message, TextWrapping = TextWrapping.Wrap }, new StackPanel { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Right, Spacing = 8, Children = { cancel, confirm }, }, }, }, }; cancel.Click += (_, _) => { tcs.TrySetResult(false); dialog.Close(); }; confirm.Click += (_, _) => { tcs.TrySetResult(true); dialog.Close(); }; dialog.Closed += (_, _) => tcs.TrySetResult(false); _ = dialog.ShowDialog(this); return await tcs.Task; } }