feat(ui): keyboard shortcuts (/ Ctrl+N Space Esc)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,8 @@ public sealed partial class ListsIslandViewModel : ViewModelBase
|
|||||||
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;
|
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;
|
||||||
|
|
||||||
public event EventHandler? SelectionChanged;
|
public event EventHandler? SelectionChanged;
|
||||||
|
public event EventHandler? FocusSearchRequested;
|
||||||
|
public void RequestFocusSearch() => FocusSearchRequested?.Invoke(this, EventArgs.Empty);
|
||||||
|
|
||||||
public ObservableCollection<ListNavItemViewModel> Items { get; } = new();
|
public ObservableCollection<ListNavItemViewModel> Items { get; } = new();
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ public sealed partial class TasksIslandViewModel : ViewModelBase
|
|||||||
private ListNavItemViewModel? _currentList;
|
private ListNavItemViewModel? _currentList;
|
||||||
|
|
||||||
public event EventHandler? SelectionChanged;
|
public event EventHandler? SelectionChanged;
|
||||||
|
public event EventHandler? FocusAddTaskRequested;
|
||||||
|
public void RequestFocusAddTask() => FocusAddTaskRequested?.Invoke(this, EventArgs.Empty);
|
||||||
|
|
||||||
public ObservableCollection<TaskRowViewModel> Items { get; } = new();
|
public ObservableCollection<TaskRowViewModel> Items { get; } = new();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using ClaudeDo.Ui.ViewModels.Islands;
|
using ClaudeDo.Ui.ViewModels.Islands;
|
||||||
|
|
||||||
namespace ClaudeDo.Ui.ViewModels;
|
namespace ClaudeDo.Ui.ViewModels;
|
||||||
@@ -15,6 +16,18 @@ public sealed partial class IslandsShellViewModel : ViewModelBase
|
|||||||
public bool ShowDetails => WindowWidth >= 1100;
|
public bool ShowDetails => WindowWidth >= 1100;
|
||||||
public bool ShowLists => WindowWidth >= 780;
|
public bool ShowLists => WindowWidth >= 780;
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void FocusSearch() => Lists.RequestFocusSearch();
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void FocusAddTask() => Tasks.RequestFocusAddTask();
|
||||||
|
|
||||||
|
public async Task ToggleSelectedDoneAsync()
|
||||||
|
{
|
||||||
|
if (Tasks.SelectedTask is { } row)
|
||||||
|
await Tasks.ToggleDoneCommand.ExecuteAsync(row);
|
||||||
|
}
|
||||||
|
|
||||||
partial void OnWindowWidthChanged(double value)
|
partial void OnWindowWidthChanged(double value)
|
||||||
{
|
{
|
||||||
OnPropertyChanged(nameof(ShowDetails));
|
OnPropertyChanged(nameof(ShowDetails));
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<TextBlock FontFamily="{DynamicResource SansFamily}" FontSize="18"
|
<TextBlock FontFamily="{DynamicResource SansFamily}" FontSize="18"
|
||||||
FontWeight="SemiBold" Foreground="{DynamicResource TextBrush}"
|
FontWeight="SemiBold" Foreground="{DynamicResource TextBrush}"
|
||||||
Text="Lists"/>
|
Text="Lists"/>
|
||||||
<TextBox Classes="search" Margin="0,8,0,0" PlaceholderText="Search…"
|
<TextBox x:Name="SearchBox" Classes="search" Margin="0,8,0,0" PlaceholderText="Search…"
|
||||||
Text="{Binding SearchText, Mode=TwoWay}"/>
|
Text="{Binding SearchText, Mode=TwoWay}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
@@ -6,7 +6,15 @@ namespace ClaudeDo.Ui.Views.Islands;
|
|||||||
|
|
||||||
public partial class ListsIslandView : UserControl
|
public partial class ListsIslandView : UserControl
|
||||||
{
|
{
|
||||||
public ListsIslandView() { InitializeComponent(); }
|
public ListsIslandView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
DataContextChanged += (_, _) =>
|
||||||
|
{
|
||||||
|
if (DataContext is ListsIslandViewModel vm)
|
||||||
|
vm.FocusSearchRequested += (_, _) => SearchBox.Focus();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private void OnItemTapped(object? sender, RoutedEventArgs e)
|
private void OnItemTapped(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
<!-- Add-task row -->
|
<!-- Add-task row -->
|
||||||
<Border DockPanel.Dock="Top" Margin="18,8,18,4">
|
<Border DockPanel.Dock="Top" Margin="18,8,18,4">
|
||||||
<TextBox Watermark="Add a task…" Text="{Binding NewTaskTitle, Mode=TwoWay}">
|
<TextBox x:Name="AddTaskBox" Watermark="Add a task…" Text="{Binding NewTaskTitle, Mode=TwoWay}">
|
||||||
<TextBox.KeyBindings>
|
<TextBox.KeyBindings>
|
||||||
<KeyBinding Gesture="Enter" Command="{Binding AddCommand}"/>
|
<KeyBinding Gesture="Enter" Command="{Binding AddCommand}"/>
|
||||||
</TextBox.KeyBindings>
|
</TextBox.KeyBindings>
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using ClaudeDo.Ui.ViewModels.Islands;
|
||||||
|
|
||||||
namespace ClaudeDo.Ui.Views.Islands;
|
namespace ClaudeDo.Ui.Views.Islands;
|
||||||
|
|
||||||
public partial class TasksIslandView : UserControl
|
public partial class TasksIslandView : UserControl
|
||||||
{
|
{
|
||||||
public TasksIslandView() { InitializeComponent(); }
|
public TasksIslandView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
DataContextChanged += (_, _) =>
|
||||||
|
{
|
||||||
|
if (DataContext is TasksIslandViewModel vm)
|
||||||
|
vm.FocusAddTaskRequested += (_, _) => AddTaskBox.Focus();
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,11 @@
|
|||||||
SystemDecorations="None"
|
SystemDecorations="None"
|
||||||
ExtendClientAreaToDecorationsHint="True"
|
ExtendClientAreaToDecorationsHint="True"
|
||||||
ExtendClientAreaTitleBarHeightHint="-1">
|
ExtendClientAreaTitleBarHeightHint="-1">
|
||||||
|
<Window.KeyBindings>
|
||||||
|
<KeyBinding Gesture="OemQuestion" Command="{Binding FocusSearchCommand}"/>
|
||||||
|
<KeyBinding Gesture="Shift+OemQuestion" Command="{Binding FocusSearchCommand}"/>
|
||||||
|
<KeyBinding Gesture="Ctrl+N" Command="{Binding FocusAddTaskCommand}"/>
|
||||||
|
</Window.KeyBindings>
|
||||||
<Grid RowDefinitions="36,*">
|
<Grid RowDefinitions="36,*">
|
||||||
<!-- Custom title bar -->
|
<!-- Custom title bar -->
|
||||||
<Border Grid.Row="0" Background="{DynamicResource DeepBrush}" PointerPressed="OnTitleBarPressed">
|
<Border Grid.Row="0" Background="{DynamicResource DeepBrush}" PointerPressed="OnTitleBarPressed">
|
||||||
|
|||||||
@@ -6,7 +6,22 @@ namespace ClaudeDo.Ui.Views;
|
|||||||
|
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
public MainWindow() { InitializeComponent(); }
|
public MainWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
KeyDown += OnWindowKeyDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
private void OnTitleBarPressed(object? sender, PointerPressedEventArgs e)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user