feat(ui): My Day actions, orphan-aware grouping, menu restructure
Pending UI work: - My Day add/remove context actions on task rows (parent removal cascades to children) - orphan-aware grouping: a child whose parent isn't in view renders as a top-level row, not an indented draft - shell menu restructure (Worker / Repositories submenus); 'Finalize plan' action, drop 'Queue subtasks sequentially' - notes editor refinements - subtask-row hover tweak (Surface3, no transition) - bump Avalonia 12.0.0 -> 12.0.4
This commit is contained in:
@@ -29,7 +29,9 @@ public partial class DescriptionStepsCard : UserControl
|
||||
|
||||
private void OnSubtaskEditLostFocus(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is TextBox { DataContext: SubtaskRowViewModel row })
|
||||
row.IsEditing = false;
|
||||
if (sender is TextBox { DataContext: SubtaskRowViewModel row }
|
||||
&& DataContext is DetailsIslandViewModel vm
|
||||
&& vm.CommitSubtaskEditCommand.CanExecute(row))
|
||||
vm.CommitSubtaskEditCommand.Execute(row);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,13 @@ public partial class DetailsIslandView : UserControl
|
||||
if (h <= 0) return;
|
||||
DetailBodyGrid.RowDefinitions[0].MaxHeight = h * 2.0 / 3.0;
|
||||
DetailBodyGrid.RowDefinitions[1].MinHeight = h / 3.0;
|
||||
// The description sits in an Auto row, which measures its cell with
|
||||
// infinite height — so the card's inner ScrollViewer thinks everything
|
||||
// fits and never scrolls. Bounding the card itself gives that
|
||||
// ScrollViewer a finite measure constraint so it engages once the
|
||||
// content exceeds 2/3 of the island. (RowDefinition.MaxHeight above only
|
||||
// clamps the drag and the final row height, not the measure constraint.)
|
||||
DescriptionCard.MaxHeight = h * 2.0 / 3.0;
|
||||
}
|
||||
|
||||
private void OnDataContextChanged(object? sender, EventArgs e)
|
||||
|
||||
@@ -28,11 +28,8 @@
|
||||
<ItemsControl ItemsSource="{Binding Bullets}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:NoteBulletViewModel">
|
||||
<Grid ColumnDefinitions="*,Auto,Auto" Margin="0,2" ColumnSpacing="6">
|
||||
<TextBox Grid.Column="0" Text="{Binding Text}"/>
|
||||
<Button Grid.Column="1" Classes="btn" Content="{loc:Tr notes.save}" Command="{Binding SaveCommand}"/>
|
||||
<Button Grid.Column="2" Classes="btn" Content="{loc:Tr notes.delete}" Command="{Binding DeleteCommand}"/>
|
||||
</Grid>
|
||||
<TextBox Text="{Binding Text}" Margin="0,2"
|
||||
LostFocus="OnBulletLostFocus"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using ClaudeDo.Ui.ViewModels.Islands;
|
||||
|
||||
namespace ClaudeDo.Ui.Views.Islands;
|
||||
|
||||
public partial class NotesEditorView : UserControl
|
||||
{
|
||||
public NotesEditorView() => InitializeComponent();
|
||||
|
||||
private void OnBulletLostFocus(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is TextBox { DataContext: NoteBulletViewModel bullet }
|
||||
&& DataContext is NotesEditorViewModel vm
|
||||
&& vm.CommitBulletCommand.CanExecute(bullet))
|
||||
vm.CommitBulletCommand.Execute(bullet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
<!-- Indent wrapper: col 0 = 24px child indent track, col 1 = content -->
|
||||
<Grid Grid.Row="1" ColumnDefinitions="Auto,*">
|
||||
|
||||
<!-- Indent track (only visible for child tasks) -->
|
||||
<Border Grid.Column="0" Width="24" IsVisible="{Binding IsChild}" VerticalAlignment="Stretch">
|
||||
<!-- Indent track (only while the parent shares this view; orphaned children render flat) -->
|
||||
<Border Grid.Column="0" Width="24" IsVisible="{Binding ShowAsChild}" VerticalAlignment="Stretch">
|
||||
<Rectangle Width="1" Fill="{DynamicResource LineBrush}"
|
||||
HorizontalAlignment="Right" Margin="0,4"/>
|
||||
</Border>
|
||||
@@ -56,17 +56,23 @@
|
||||
<MenuItem Header="{loc:Tr tasks.ctxResumePlanningSession}"
|
||||
Click="OnResumePlanningSessionClick"
|
||||
IsVisible="{Binding CanResumeOrDiscardPlanning}"/>
|
||||
<MenuItem Header="{loc:Tr tasks.ctxFinalizePlanningSession}"
|
||||
Click="OnFinalizePlanningSessionClick"
|
||||
IsVisible="{Binding CanFinalizePlanning}"/>
|
||||
<MenuItem Header="{loc:Tr tasks.ctxDiscardPlanningSession}"
|
||||
Click="OnDiscardPlanningSessionClick"
|
||||
IsVisible="{Binding CanResumeOrDiscardPlanning}"/>
|
||||
<MenuItem Header="{loc:Tr tasks.ctxQueueSubtasks}"
|
||||
Click="OnQueuePlanningSubtasksClick"
|
||||
IsVisible="{Binding CanQueuePlan}"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="{loc:Tr tasks.ctxScheduleFor}" Click="OnScheduleForClick"/>
|
||||
<MenuItem Header="{loc:Tr tasks.ctxClearSchedule}"
|
||||
IsVisible="{Binding HasSchedule}"
|
||||
Click="OnClearScheduleClick"/>
|
||||
<MenuItem Header="{loc:Tr tasks.ctxAddToMyDay}"
|
||||
IsVisible="{Binding CanAddToMyDay}"
|
||||
Click="OnAddToMyDayClick"/>
|
||||
<MenuItem Header="{loc:Tr tasks.ctxRemoveFromMyDay}"
|
||||
IsVisible="{Binding IsMyDay}"
|
||||
Click="OnRemoveFromMyDayClick"/>
|
||||
</ContextMenu>
|
||||
</Border.ContextMenu>
|
||||
<Grid ColumnDefinitions="0,18,32,*,Auto,Auto,32" Margin="6,8,10,8">
|
||||
|
||||
@@ -48,6 +48,18 @@ public partial class TaskRowView : UserControl
|
||||
await vm.ClearScheduleCommand.ExecuteAsync(row);
|
||||
}
|
||||
|
||||
private async void OnAddToMyDayClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is TaskRowViewModel row && FindTasksVm() is { } vm)
|
||||
await vm.AddToMyDayCommand.ExecuteAsync(row);
|
||||
}
|
||||
|
||||
private async void OnRemoveFromMyDayClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is TaskRowViewModel row && FindTasksVm() is { } vm)
|
||||
await vm.RemoveFromMyDayCommand.ExecuteAsync(row);
|
||||
}
|
||||
|
||||
private async void OnOpenPlanningSessionClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is TaskRowViewModel row && FindTasksVm() is { } vm)
|
||||
@@ -72,10 +84,10 @@ public partial class TaskRowView : UserControl
|
||||
await vm.DiscardPlanningSessionCommand.ExecuteAsync(row);
|
||||
}
|
||||
|
||||
private async void OnQueuePlanningSubtasksClick(object? sender, RoutedEventArgs e)
|
||||
private async void OnFinalizePlanningSessionClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is TaskRowViewModel row && FindTasksVm() is { } vm)
|
||||
await vm.QueuePlanningSubtasksCommand.ExecuteAsync(row);
|
||||
await vm.FinalizePlanningSessionCommand.ExecuteAsync(row);
|
||||
}
|
||||
|
||||
private async void OnSetStatusClick(object? sender, RoutedEventArgs e)
|
||||
|
||||
@@ -57,18 +57,26 @@
|
||||
<Menu Margin="12,0,0,0"
|
||||
Background="Transparent"
|
||||
VerticalAlignment="Center">
|
||||
<MenuItem Header="{loc:Tr shell.menu.worker}"
|
||||
FontSize="{StaticResource FontSizeMono}"
|
||||
Foreground="{DynamicResource TextDimBrush}">
|
||||
<MenuItem Header="{loc:Tr shell.menu.restartWorker}"
|
||||
Command="{Binding RestartWorkerCommand}"/>
|
||||
<MenuItem Header="{loc:Tr shell.menu.checkForUpdates}"
|
||||
Command="{Binding CheckForUpdatesCommand}"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="{loc:Tr shell.menu.repositories}"
|
||||
FontSize="{StaticResource FontSizeMono}"
|
||||
Foreground="{DynamicResource TextDimBrush}">
|
||||
<MenuItem Header="{loc:Tr shell.menu.addRepos}" Command="{Binding OpenRepoImportCommand}"/>
|
||||
<MenuItem Header="{loc:Tr shell.menu.worktrees}"
|
||||
Command="{Binding OpenWorktreesOverviewGlobalCommand}"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="{loc:Tr shell.menu.help}"
|
||||
FontSize="{StaticResource FontSizeMono}"
|
||||
Foreground="{DynamicResource TextDimBrush}">
|
||||
<MenuItem Header="{loc:Tr shell.menu.checkForUpdates}"
|
||||
Command="{Binding CheckForUpdatesCommand}"/>
|
||||
<MenuItem Header="{loc:Tr shell.menu.restartWorker}"
|
||||
Command="{Binding RestartWorkerCommand}"/>
|
||||
<MenuItem Header="{loc:Tr shell.menu.worktrees}"
|
||||
Command="{Binding OpenWorktreesOverviewGlobalCommand}"/>
|
||||
<MenuItem Header="{loc:Tr shell.menu.weeklyReport}" Command="{Binding OpenWeeklyReportCommand}"/>
|
||||
<MenuItem Header="{loc:Tr shell.menu.about}" Command="{Binding OpenAboutCommand}"/>
|
||||
<MenuItem Header="{loc:Tr shell.menu.addRepos}" Command="{Binding OpenRepoImportCommand}"/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</StackPanel>
|
||||
|
||||
Reference in New Issue
Block a user