feat(notes): notes get their own list, a day log and an Enter chain

The editor was reachable from one button that only appeared in My Day,
which is how it got forgotten. It is now a permanent sidebar entry next
to My Day and Planned, and it fills the tasks island rather than the
details pane, because a note list is content.

Inside, the date picker is gone: today sits at the top with the capture
box, older days follow as dated groups. Enter in a note saves it and
opens the next one, Shift+Enter breaks the line so notes can be several,
Backspace on an empty note deletes it and steps back up. Deleting also
has a visible hover button instead of only "clear the text and hope".
Agent-written notes carry a marker.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
CubeGameLP
2026-08-28 21:19:37 +02:00
co-authored by Claude Opus 5
parent ae0c7d3771
commit 0f04b796f4
34 changed files with 533 additions and 192 deletions
@@ -1,38 +1,110 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Islands"
xmlns:ctl="using:ClaudeDo.Ui.Views.Controls"
xmlns:loc="using:ClaudeDo.Ui.Localization"
x:Class="ClaudeDo.Ui.Views.Islands.NotesEditorView"
x:DataType="vm:NotesEditorViewModel">
<DockPanel Margin="16">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="8">
<Button Classes="btn" Content="&#x2039;" Command="{Binding PrevDayCommand}"/>
<ctl:ThemedDatePicker SelectedDate="{Binding CurrentDate, Mode=TwoWay}"/>
<Button Classes="btn" Content="&#x203A;" Command="{Binding NextDayCommand}"/>
<Button Classes="btn" Content="{loc:Tr notes.today}" Command="{Binding TodayCommand}"/>
<TextBlock Classes="meta" VerticalAlignment="Center" Text="{Binding CurrentDayLabel}"/>
</StackPanel>
<DockPanel DockPanel.Dock="Top" Margin="0,12,0,8">
<Button DockPanel.Dock="Right" Classes="btn" Content="{loc:Tr notes.add}" Margin="8,0,0,0"
Command="{Binding AddBulletCommand}"/>
<TextBox PlaceholderText="{loc:Tr notes.newNotePlaceholder}" Text="{Binding NewBulletText}">
<TextBox.KeyBindings>
<KeyBinding Gesture="Enter" Command="{Binding AddBulletCommand}"/>
</TextBox.KeyBindings>
</TextBox>
</DockPanel>
<UserControl.Styles>
<!-- A note reads as text, not as a form field: the box only shows itself under the pointer
and while it has focus. -->
<Style Selector="TextBox.note">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="4,3"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="AcceptsReturn" Value="True"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
<Style Selector="TextBox.note /template/ Border#PART_BorderElement">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Bullets}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:NoteBulletViewModel">
<TextBox Text="{Binding Text}" Margin="0,2"
LostFocus="OnBulletLostFocus"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<Style Selector="Border.note-row">
<Setter Property="CornerRadius" Value="6"/>
<Setter Property="Padding" Value="10,1,6,1"/>
<Setter Property="Margin" Value="4,1"/>
</Style>
<Style Selector="Border.note-row:pointerover">
<Setter Property="Background" Value="{DynamicResource PeatSoftBrush}"/>
</Style>
<!-- Row actions stay out of the way until the row is hovered. -->
<Style Selector="Border.note-row Button.note-del">
<Setter Property="Opacity" Value="0"/>
</Style>
<Style Selector="Border.note-row:pointerover Button.note-del">
<Setter Property="Opacity" Value="1"/>
</Style>
</UserControl.Styles>
<DockPanel LastChildFill="True">
<!-- Today's capture box: Enter files the note and leaves the caret here for the next one. -->
<Border DockPanel.Dock="Top" Classes="add-task" Margin="16,14,16,10">
<Grid ColumnDefinitions="Auto,*,Auto">
<Border Grid.Column="0" Classes="add-task-plus" VerticalAlignment="Center">
<PathIcon Width="12" Height="12" Data="{StaticResource Icon.Plus}"
Foreground="{DynamicResource TextFaintBrush}"/>
</Border>
<TextBox Grid.Column="1" x:Name="NewNoteBox" Classes="add-task-input"
PlaceholderText="{loc:Tr notes.newNotePlaceholder}"
Text="{Binding NewBulletText, Mode=TwoWay}"
VerticalAlignment="Center" Margin="12,0,0,0">
<TextBox.KeyBindings>
<KeyBinding Gesture="Enter" Command="{Binding AddBulletCommand}"/>
</TextBox.KeyBindings>
</TextBox>
<Border Grid.Column="2" Classes="kbd kbd-enter" VerticalAlignment="Center"
IsVisible="{Binding #NewNoteBox.IsFocused}">
<TextBlock Text="{loc:Tr tasks.enterKey}"/>
</Border>
</Grid>
</Border>
<Panel>
<ScrollViewer>
<ItemsControl x:Name="RowsHost" ItemsSource="{Binding Rows}" Margin="10,0,10,12">
<ItemsControl.DataTemplates>
<DataTemplate DataType="vm:NoteDayHeaderViewModel">
<TextBlock Classes="eyebrow section-label" Margin="14,12,14,4" Text="{Binding Label}"/>
</DataTemplate>
<DataTemplate DataType="vm:NoteBulletViewModel">
<Border Classes="note-row">
<Grid ColumnDefinitions="Auto,*,Auto,Auto">
<Ellipse Grid.Column="0" Width="4" Height="4" Margin="0,0,10,0"
VerticalAlignment="Center"
Fill="{DynamicResource TextFaintBrush}"/>
<TextBox Grid.Column="1" Classes="note" Text="{Binding Text, Mode=TwoWay}"
LostFocus="OnBulletLostFocus" KeyDown="OnBulletKeyDown"/>
<PathIcon Grid.Column="2" Width="12" Height="12" Margin="6,0"
VerticalAlignment="Center"
IsVisible="{Binding FromAgent}"
ToolTip.Tip="{loc:Tr notes.fromAgentTip}"
Data="{StaticResource Icon.AgentSuggested}"
Foreground="{DynamicResource TextFaintBrush}"/>
<Button Grid.Column="3" Classes="icon-btn note-del"
VerticalAlignment="Center"
ToolTip.Tip="{loc:Tr notes.deleteTip}"
Click="OnDeleteBulletClick">
<PathIcon Classes="danger" Data="{StaticResource Icon.Trash}" Width="12" Height="12"/>
</Button>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.DataTemplates>
</ItemsControl>
</ScrollViewer>
<TextBlock IsVisible="{Binding IsEmpty}"
Text="{loc:Tr notes.emptyHint}"
Foreground="{DynamicResource TextMuteBrush}"
MaxWidth="260" TextAlignment="Center" TextWrapping="Wrap"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
</Panel>
</DockPanel>
</UserControl>