fix(notes): let Shift+Enter break the line, and clear the leftovers around the editor

Shift+Enter did nothing because AcceptsReturn was only set from a style
setter and never reached the box. Setting it on the element is half the
fix: TextBox.OnKeyDown consumes Enter regardless of modifiers and runs
before any bubbling handler, so the split chain would have died in its
place. Enter is now taken in the tunnel phase and Shift+Enter is left to
the box.

Alongside, the notes list stops borrowing furniture it has no use for:
no "0 open tasks" subtitle, no show-completed and list-settings buttons,
and no details pane beside it — the editor spans that column instead of
leaving it empty.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
CubeGameLP
2026-08-28 21:36:28 +02:00
co-authored by Claude Opus 5
parent 0f04b796f4
commit b90c5855f4
6 changed files with 38 additions and 9 deletions
@@ -13,8 +13,6 @@
<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"/>
@@ -77,8 +75,13 @@
<Ellipse Grid.Column="0" Width="4" Height="4" Margin="0,0,10,0"
VerticalAlignment="Center"
Fill="{DynamicResource TextFaintBrush}"/>
<!-- AcceptsReturn/TextWrapping are set here, not in the style above: TextBox
reads AcceptsReturn in its own OnKeyDown, which runs before any handler a
style or the XAML could attach. Enter is intercepted in the tunnel phase
(see code-behind) so the split still wins over the newline. -->
<TextBox Grid.Column="1" Classes="note" Text="{Binding Text, Mode=TwoWay}"
LostFocus="OnBulletLostFocus" KeyDown="OnBulletKeyDown"/>
AcceptsReturn="True" TextWrapping="Wrap"
LostFocus="OnBulletLostFocus"/>
<PathIcon Grid.Column="2" Width="12" Height="12" Margin="6,0"
VerticalAlignment="Center"
IsVisible="{Binding FromAgent}"
@@ -15,6 +15,10 @@ public partial class NotesEditorView : UserControl
{
InitializeComponent();
DataContextChanged += OnDataContextChanged;
// Tunnel, not bubble: with AcceptsReturn on, TextBox.OnKeyDown consumes Enter (any
// modifier) before a bubbling handler ever sees it. Taking Enter in the tunnel phase
// keeps the split chain, and letting Shift+Enter through leaves the newline to the box.
AddHandler(KeyDownEvent, OnBulletKeyDown, RoutingStrategies.Tunnel);
}
private void OnDataContextChanged(object? sender, EventArgs e)
@@ -33,7 +37,9 @@ public partial class NotesEditorView : UserControl
private void OnBulletKeyDown(object? sender, KeyEventArgs e)
{
if (sender is not TextBox { DataContext: NoteBulletViewModel bullet } box
// Source, not sender: the tunnel handler is attached to the whole view, so this also sees
// keys from the capture box at the top — which has no bullet behind it and is skipped.
if (e.Source is not TextBox { DataContext: NoteBulletViewModel bullet } box
|| DataContext is not NotesEditorViewModel vm) return;
// Shift+Enter falls through to the TextBox and breaks the line — a note can be several.
@@ -31,6 +31,7 @@
<TextBlock Text="{Binding StatusPill}"/>
</Border>
<Button Classes="icon-btn" Classes.active="{Binding IsShowingCompleted}"
IsVisible="{Binding !IsNotesList}"
Command="{Binding ToggleShowCompletedCommand}"
ToolTip.Tip="{loc:Tr tasks.showCompletedTip}">
<PathIcon Width="15" Height="15" Data="{StaticResource Icon.Eye}"/>
@@ -60,7 +61,8 @@
<Path Classes="icon-stroke" Data="{StaticResource Icon.PlanDay}"/>
</Viewbox>
</Button>
<Button Classes="icon-btn" Command="{Binding OpenListSettingsCommand}" ToolTip.Tip="{loc:Tr tasks.listSettingsTip}">
<Button Classes="icon-btn" IsVisible="{Binding !IsNotesList}"
Command="{Binding OpenListSettingsCommand}" ToolTip.Tip="{loc:Tr tasks.listSettingsTip}">
<PathIcon Width="15" Height="15" Data="{StaticResource Icon.Settings}"/>
</Button>
</StackPanel>
+1 -1
View File
@@ -144,7 +144,7 @@
ResizeDirection="Columns"
ResizeBehavior="PreviousAndNext"/>
<Border Grid.Column="2" Classes="island" Margin="3">
<Border Grid.Column="2" Grid.ColumnSpan="{Binding TasksColumnSpan}" Classes="island" Margin="3">
<islands:TasksIslandView DataContext="{Binding Tasks}"/>
</Border>