Tasks with subtasks show a chevron for inline expand/collapse. Subtask checkboxes toggle completion state directly. Also sets Windows AppUserModelID for proper taskbar identity. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
129 lines
4.0 KiB
C#
129 lines
4.0 KiB
C#
using System.Collections.ObjectModel;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Input;
|
|
using Avalonia.Interactivity;
|
|
using Avalonia.VisualTree;
|
|
using ClaudeDo.Ui.ViewModels;
|
|
|
|
namespace ClaudeDo.Ui.Views;
|
|
|
|
public partial class TaskListView : UserControl
|
|
{
|
|
public TaskListView()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
private void OnInlineAddKeyDown(object? sender, KeyEventArgs e)
|
|
{
|
|
if (DataContext is not TaskListViewModel vm) return;
|
|
|
|
if (e.Key == Key.Enter)
|
|
{
|
|
vm.InlineAddCommand.Execute(null);
|
|
e.Handled = true;
|
|
}
|
|
else if (e.Key == Key.Escape)
|
|
{
|
|
vm.InlineAddTitle = "";
|
|
this.FindControl<ListBox>("TaskListBox")?.Focus();
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void OnInlineAddGotFocus(object? sender, FocusChangedEventArgs e)
|
|
{
|
|
if (sender is TextBox tb)
|
|
tb.BorderBrush = Avalonia.Application.Current?.FindResource("AccentBrush") as Avalonia.Media.IBrush;
|
|
}
|
|
|
|
private void OnInlineAddLostFocus(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (sender is TextBox tb)
|
|
tb.BorderBrush = Avalonia.Application.Current?.FindResource("BorderSubtleBrush") as Avalonia.Media.IBrush;
|
|
}
|
|
|
|
private void OnTaskListKeyDown(object? sender, KeyEventArgs e)
|
|
{
|
|
if (DataContext is not TaskListViewModel vm || vm.SelectedTask is null) return;
|
|
|
|
switch (e.Key)
|
|
{
|
|
case Key.Delete:
|
|
vm.DeleteTaskCommand.Execute(null);
|
|
e.Handled = true;
|
|
break;
|
|
case Key.Space:
|
|
if (vm.SelectedTask.CanToggleDone)
|
|
{
|
|
vm.SelectedTask.ToggleDoneCommand.Execute(null);
|
|
e.Handled = true;
|
|
}
|
|
break;
|
|
case Key.Enter:
|
|
case Key.F2:
|
|
var detailView = this.GetVisualAncestors().OfType<Window>().FirstOrDefault()
|
|
?.GetVisualDescendants().OfType<TaskDetailView>().FirstOrDefault();
|
|
detailView?.FocusTitle();
|
|
e.Handled = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void OnCheckboxPressed(object? sender, PointerPressedEventArgs e)
|
|
{
|
|
if (sender is not Border { DataContext: TaskItemViewModel task }) return;
|
|
if (task.CanToggleDone)
|
|
{
|
|
task.ToggleDoneCommand.Execute(null);
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void OnTaskItemDoubleTapped(object? sender, TappedEventArgs e)
|
|
{
|
|
if (DataContext is TaskListViewModel vm)
|
|
vm.EditTaskCommand.Execute(null);
|
|
}
|
|
|
|
private void OnTaskItemPointerPressed(object? sender, PointerPressedEventArgs e)
|
|
{
|
|
var props = e.GetCurrentPoint(this).Properties;
|
|
if (!props.IsRightButtonPressed) return;
|
|
|
|
if (sender is Grid { DataContext: TaskItemViewModel item }
|
|
&& DataContext is TaskListViewModel vm)
|
|
{
|
|
vm.SelectedTask = item;
|
|
}
|
|
}
|
|
|
|
private void OnSubtaskPointerPressed(object? sender, PointerPressedEventArgs e)
|
|
{
|
|
if (e.GetCurrentPoint(null).Properties.IsRightButtonPressed
|
|
&& sender is Control { DataContext: SubtaskItemViewModel subtask }
|
|
&& DataContext is TaskListViewModel vm)
|
|
{
|
|
var parent = vm.Tasks.FirstOrDefault(t => t.Subtasks.Contains(subtask));
|
|
if (parent is not null)
|
|
vm.SelectedTask = parent;
|
|
}
|
|
}
|
|
|
|
private async void OnSubtaskCheckboxClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (sender is CheckBox { DataContext: SubtaskItemViewModel subtask }
|
|
&& DataContext is TaskListViewModel vm)
|
|
{
|
|
var parent = vm.Tasks.FirstOrDefault(t => t.Subtasks.Contains(subtask));
|
|
if (parent is not null)
|
|
await parent.ToggleSubtaskDoneCommand.ExecuteAsync(subtask.Id);
|
|
}
|
|
}
|
|
|
|
public void FocusInlineAdd()
|
|
{
|
|
this.FindControl<TextBox>("InlineAddBox")?.Focus();
|
|
}
|
|
}
|