Skip to content

Commit ffbc2a5

Browse files
sharpninjaCopilot
andcommitted
Improve status bar scroll and long-press copy
Wrap status text in scroll viewers and add Android long-press clipboard copy while preserving short-tap status dialog behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 4a83b5c commit ffbc2a5

6 files changed

Lines changed: 141 additions & 30 deletions

File tree

src/McpServerManager.Android/Views/PhoneMainView.axaml

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,20 @@
7979
VerticalAlignment="Center"
8080
FontSize="19"
8181
Padding="8,4"/>
82-
<SelectableTextBlock x:Name="StatusMessageText"
83-
Grid.Row="1" Grid.Column="0"
84-
Grid.ColumnSpan="2"
85-
Text="{Binding StatusViewModel.Status}"
86-
FontWeight="Bold"
87-
FontSize="19"
88-
VerticalAlignment="Center"
89-
TextTrimming="CharacterEllipsis"
90-
PointerPressed="StatusMessageText_OnPointerPressed"/>
82+
<ScrollViewer Grid.Row="1"
83+
Grid.Column="0"
84+
Grid.ColumnSpan="2"
85+
HorizontalScrollBarVisibility="Auto"
86+
VerticalScrollBarVisibility="Disabled">
87+
<SelectableTextBlock x:Name="StatusMessageText"
88+
Text="{Binding StatusViewModel.Status}"
89+
FontWeight="Bold"
90+
FontSize="19"
91+
VerticalAlignment="Center"
92+
PointerPressed="StatusMessageText_OnPointerPressed"
93+
PointerReleased="StatusMessageText_OnPointerReleased"
94+
PointerCaptureLost="StatusMessageText_OnPointerCaptureLost"/>
95+
</ScrollViewer>
9196
<Ellipse Grid.Row="1"
9297
Grid.Column="2"
9398
Width="10"

src/McpServerManager.Android/Views/PhoneMainView.axaml.cs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System;
2+
using System.Threading.Tasks;
13
using Avalonia.Controls;
24
using Avalonia.Input;
35
using Avalonia.Interactivity;
@@ -7,6 +9,9 @@ namespace McpServerManager.Android.Views;
79

810
public partial class PhoneMainView : UserControl
911
{
12+
private const int StatusLongPressThresholdMilliseconds = 600;
13+
private DateTimeOffset? _statusPointerPressedAt;
14+
1015
public PhoneMainView()
1116
{
1217
InitializeComponent();
@@ -36,11 +41,54 @@ private void StatusMessageText_OnPointerPressed(object? sender, PointerPressedEv
3641
if (DataContext is not MainWindowViewModel vm || string.IsNullOrWhiteSpace(vm.StatusMessage))
3742
return;
3843

39-
StatusDialogText.Text = vm.StatusMessage;
40-
StatusDialogOverlay.IsVisible = true;
44+
_statusPointerPressedAt = DateTimeOffset.UtcNow;
4145
e.Handled = true;
4246
}
4347

48+
private async void StatusMessageText_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
49+
{
50+
if (DataContext is not MainWindowViewModel vm || string.IsNullOrWhiteSpace(vm.StatusMessage))
51+
{
52+
_statusPointerPressedAt = null;
53+
return;
54+
}
55+
56+
var pressedAt = _statusPointerPressedAt;
57+
_statusPointerPressedAt = null;
58+
if (pressedAt is null)
59+
return;
60+
61+
if ((DateTimeOffset.UtcNow - pressedAt.Value).TotalMilliseconds >= StatusLongPressThresholdMilliseconds)
62+
{
63+
await CopyStatusToClipboardAsync(vm.StatusMessage);
64+
e.Handled = true;
65+
return;
66+
}
67+
68+
ShowStatusDialog(vm.StatusMessage);
69+
e.Handled = true;
70+
}
71+
72+
private void StatusMessageText_OnPointerCaptureLost(object? sender, PointerCaptureLostEventArgs e)
73+
{
74+
_statusPointerPressedAt = null;
75+
}
76+
77+
private async Task CopyStatusToClipboardAsync(string statusText)
78+
{
79+
var topLevel = TopLevel.GetTopLevel(this);
80+
if (topLevel?.Clipboard is null)
81+
return;
82+
83+
await topLevel.Clipboard.SetTextAsync(statusText);
84+
}
85+
86+
private void ShowStatusDialog(string statusText)
87+
{
88+
StatusDialogText.Text = statusText;
89+
StatusDialogOverlay.IsVisible = true;
90+
}
91+
4492
private void CloseStatusDialog_OnClick(object? sender, RoutedEventArgs e)
4593
{
4694
StatusDialogOverlay.IsVisible = false;

src/McpServerManager.Android/Views/TabletMainView.axaml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,17 @@
3232
<!-- Status Bar -->
3333
<views:AnimatedStatusBar Grid.Row="1" Margin="6,0,6,6" IsBusy="{Binding IsBusy}" IdleBrush="{DynamicResource StatusBarBrush}">
3434
<Grid ColumnDefinitions="*,Auto,Auto,Auto,Auto" ColumnSpacing="8">
35-
<SelectableTextBlock x:Name="StatusMessageText"
36-
Grid.Column="0"
37-
Text="{Binding StatusViewModel.Status}"
38-
FontWeight="Bold"
39-
VerticalAlignment="Center"
40-
TextTrimming="CharacterEllipsis"
41-
PointerPressed="StatusMessageText_OnPointerPressed"/>
35+
<ScrollViewer Grid.Column="0"
36+
HorizontalScrollBarVisibility="Auto"
37+
VerticalScrollBarVisibility="Disabled">
38+
<SelectableTextBlock x:Name="StatusMessageText"
39+
Text="{Binding StatusViewModel.Status}"
40+
FontWeight="Bold"
41+
VerticalAlignment="Center"
42+
PointerPressed="StatusMessageText_OnPointerPressed"
43+
PointerReleased="StatusMessageText_OnPointerReleased"
44+
PointerCaptureLost="StatusMessageText_OnPointerCaptureLost"/>
45+
</ScrollViewer>
4246
<ComboBox Grid.Column="1"
4347
MinWidth="220"
4448
MaxWidth="340"

src/McpServerManager.Android/Views/TabletMainView.axaml.cs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System;
2+
using System.Threading.Tasks;
13
using Avalonia.Controls;
24
using Avalonia.Input;
35
using Avalonia.Interactivity;
@@ -7,6 +9,9 @@ namespace McpServerManager.Android.Views;
79

810
public partial class TabletMainView : UserControl
911
{
12+
private const int StatusLongPressThresholdMilliseconds = 600;
13+
private DateTimeOffset? _statusPointerPressedAt;
14+
1015
public TabletMainView()
1116
{
1217
InitializeComponent();
@@ -17,11 +22,54 @@ private void StatusMessageText_OnPointerPressed(object? sender, PointerPressedEv
1722
if (DataContext is not MainWindowViewModel vm || string.IsNullOrWhiteSpace(vm.StatusMessage))
1823
return;
1924

20-
StatusDialogText.Text = vm.StatusMessage;
21-
StatusDialogOverlay.IsVisible = true;
25+
_statusPointerPressedAt = DateTimeOffset.UtcNow;
26+
e.Handled = true;
27+
}
28+
29+
private async void StatusMessageText_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
30+
{
31+
if (DataContext is not MainWindowViewModel vm || string.IsNullOrWhiteSpace(vm.StatusMessage))
32+
{
33+
_statusPointerPressedAt = null;
34+
return;
35+
}
36+
37+
var pressedAt = _statusPointerPressedAt;
38+
_statusPointerPressedAt = null;
39+
if (pressedAt is null)
40+
return;
41+
42+
if ((DateTimeOffset.UtcNow - pressedAt.Value).TotalMilliseconds >= StatusLongPressThresholdMilliseconds)
43+
{
44+
await CopyStatusToClipboardAsync(vm.StatusMessage);
45+
e.Handled = true;
46+
return;
47+
}
48+
49+
ShowStatusDialog(vm.StatusMessage);
2250
e.Handled = true;
2351
}
2452

53+
private void StatusMessageText_OnPointerCaptureLost(object? sender, PointerCaptureLostEventArgs e)
54+
{
55+
_statusPointerPressedAt = null;
56+
}
57+
58+
private async Task CopyStatusToClipboardAsync(string statusText)
59+
{
60+
var topLevel = TopLevel.GetTopLevel(this);
61+
if (topLevel?.Clipboard is null)
62+
return;
63+
64+
await topLevel.Clipboard.SetTextAsync(statusText);
65+
}
66+
67+
private void ShowStatusDialog(string statusText)
68+
{
69+
StatusDialogText.Text = statusText;
70+
StatusDialogOverlay.IsVisible = true;
71+
}
72+
2573
private void CloseStatusDialog_OnClick(object? sender, RoutedEventArgs e)
2674
{
2775
StatusDialogOverlay.IsVisible = false;

src/McpServerManager.Desktop/Views/MainWindow.axaml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,14 @@
4242
<!-- Status Bar -->
4343
<Border Grid.Row="1" Margin="8,0,8,8" Padding="8,6" Classes="phone-toolbar-card">
4444
<Grid ColumnDefinitions="*,Auto,Auto,Auto,Auto" ColumnSpacing="8">
45-
<SelectableTextBlock Grid.Column="0"
46-
Text="{Binding StatusViewModel.Status}"
47-
FontWeight="Bold"
48-
VerticalAlignment="Center"
49-
HorizontalAlignment="Left"/>
45+
<ScrollViewer Grid.Column="0"
46+
HorizontalScrollBarVisibility="Auto"
47+
VerticalScrollBarVisibility="Disabled">
48+
<SelectableTextBlock Text="{Binding StatusViewModel.Status}"
49+
FontWeight="Bold"
50+
VerticalAlignment="Center"
51+
HorizontalAlignment="Left"/>
52+
</ScrollViewer>
5053
<ComboBox Grid.Column="1"
5154
MinWidth="260"
5255
MaxWidth="420"

src/McpServerManager/Views/MainWindow.axaml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -301,11 +301,14 @@
301301
<!-- Status Bar. Bottom of window for both orientations; row/column set in code-behind -->
302302
<Border x:Name="StatusBarBorder" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3" Padding="8,6">
303303
<Grid ColumnDefinitions="*,Auto">
304-
<SelectableTextBlock Grid.Column="0"
305-
Text="{Binding StatusMessage}"
306-
FontWeight="Bold"
307-
VerticalAlignment="Center"
308-
HorizontalAlignment="Left"/>
304+
<ScrollViewer Grid.Column="0"
305+
HorizontalScrollBarVisibility="Auto"
306+
VerticalScrollBarVisibility="Disabled">
307+
<SelectableTextBlock Text="{Binding StatusMessage}"
308+
FontWeight="Bold"
309+
VerticalAlignment="Center"
310+
HorizontalAlignment="Left"/>
311+
</ScrollViewer>
309312
<SelectableTextBlock Grid.Column="1"
310313
Text="{Binding AppVersionDisplay}"
311314
VerticalAlignment="Center"

0 commit comments

Comments
 (0)