Skip to content

Commit 75d0182

Browse files
authored
Improves the operation output views in the Avalonia UI (#4743)
1 parent 941b1dc commit 75d0182

5 files changed

Lines changed: 55 additions & 45 deletions

File tree

src/UniGetUI.Avalonia/ViewModels/DialogPages/OperationViewModel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,12 +328,12 @@ private void ShowDetails()
328328
if (Operation.Status is OperationStatus.Failed)
329329
{
330330
var win = new OperationFailedDialog(Operation);
331-
_ = win.ShowDialog(mainWindow);
331+
win.Show(mainWindow);
332332
}
333333
else
334334
{
335335
var win = new OperationOutputWindow(Operation);
336-
_ = win.ShowDialog(mainWindow);
336+
win.Show(mainWindow);
337337
}
338338
}
339339

src/UniGetUI.Avalonia/Views/DialogPages/OperationFailedDialog.axaml

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
<Window xmlns="https://github.com/avaloniaui"
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
33
xmlns:automation="clr-namespace:Avalonia.Automation;assembly=Avalonia.Controls"
4-
xmlns:local="using:UniGetUI.Avalonia.Views.DialogPages"
54
x:Class="UniGetUI.Avalonia.Views.DialogPages.OperationFailedDialog"
65
Width="800" MinWidth="500"
76
Height="550" MinHeight="300"
8-
MaxWidth="800"
97
CanResize="True"
108
ShowInTaskbar="False"
119
Background="{DynamicResource AppDialogBackground}"
@@ -28,19 +26,12 @@
2826
VerticalScrollBarVisibility="Auto"
2927
Background="{DynamicResource AppDialogDarkBackground}"
3028
CornerRadius="6">
31-
<ItemsControl x:Name="OutputLines"
32-
Padding="8"
33-
automation:AutomationProperties.AccessibilityView="Raw">
34-
<ItemsControl.ItemTemplate>
35-
<DataTemplate x:DataType="local:OutputLineVm">
36-
<TextBlock Text="{Binding Text}"
37-
Foreground="{Binding Foreground}"
38-
FontFamily="Cascadia Mono,Consolas,Menlo,monospace"
39-
FontSize="12"
40-
TextWrapping="Wrap"/>
41-
</DataTemplate>
42-
</ItemsControl.ItemTemplate>
43-
</ItemsControl>
29+
<SelectableTextBlock x:Name="OutputText"
30+
Padding="8"
31+
FontFamily="Cascadia Mono,Consolas,Menlo,monospace"
32+
FontSize="12"
33+
TextWrapping="Wrap"
34+
automation:AutomationProperties.AccessibilityView="Raw"/>
4435
</ScrollViewer>
4536

4637
<!-- ── Footer buttons ── -->

src/UniGetUI.Avalonia/Views/DialogPages/OperationFailedDialog.axaml.cs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Avalonia;
22
using Avalonia.Controls;
3+
using Avalonia.Controls.Documents;
34
using Avalonia.Layout;
45
using Avalonia.Media;
56
using Avalonia.Threading;
@@ -28,7 +29,8 @@ public OperationFailedDialog(AbstractOperation operation)
2829
var normalBrush = Application.Current?.FindResource("SystemControlForegroundBaseHighBrush") as IBrush
2930
?? Brushes.White;
3031

31-
var lines = new List<OutputLineVm>();
32+
var inlines = OutputText.Inlines ??= new InlineCollection();
33+
bool first = true;
3234
foreach (var (text, type) in operation.GetOutput())
3335
{
3436
IBrush brush = type switch
@@ -37,9 +39,10 @@ public OperationFailedDialog(AbstractOperation operation)
3739
AbstractOperation.LineType.VerboseDetails => debugBrush,
3840
_ => normalBrush,
3941
};
40-
lines.Add(new OutputLineVm(text, brush));
42+
if (!first) inlines.Add(new LineBreak());
43+
inlines.Add(new Run(text) { Foreground = brush });
44+
first = false;
4145
}
42-
OutputLines.ItemsSource = lines;
4346

4447
var closeButton = new Button
4548
{
@@ -132,10 +135,3 @@ private static MenuItem MenuItem(string header, Action action)
132135
return item;
133136
}
134137
}
135-
136-
/// <summary>View model for a single colored output line in OperationFailedDialog.</summary>
137-
public sealed class OutputLineVm(string text, IBrush foreground)
138-
{
139-
public string Text { get; } = text;
140-
public IBrush Foreground { get; } = foreground;
141-
}

src/UniGetUI.Avalonia/Views/DialogPages/OperationOutputWindow.axaml

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
33
xmlns:automation="clr-namespace:Avalonia.Automation;assembly=Avalonia.Controls"
44
xmlns:vm="using:UniGetUI.Avalonia.ViewModels.DialogPages"
5-
xmlns:logVm="using:UniGetUI.Avalonia.ViewModels.Pages.LogPages"
65
x:Class="UniGetUI.Avalonia.Views.DialogPages.OperationOutputWindow"
76
x:DataType="vm:OperationOutputViewModel"
87
Width="700" MinWidth="400"
@@ -19,20 +18,13 @@
1918
VerticalScrollBarVisibility="Auto"
2019
Background="{DynamicResource AppDialogDarkBackground}"
2120
CornerRadius="6">
22-
<ItemsControl ItemsSource="{Binding OutputLines}"
23-
Padding="8"
24-
automation:AutomationProperties.Name="{Binding Title}"
25-
automation:AutomationProperties.AccessibilityView="Raw">
26-
<ItemsControl.ItemTemplate>
27-
<DataTemplate x:DataType="logVm:LogLineItem">
28-
<TextBlock Text="{Binding Text}"
29-
Foreground="{Binding Foreground}"
30-
FontFamily="Cascadia Mono,Consolas,Menlo,monospace"
31-
FontSize="12"
32-
TextWrapping="Wrap"/>
33-
</DataTemplate>
34-
</ItemsControl.ItemTemplate>
35-
</ItemsControl>
21+
<SelectableTextBlock x:Name="OutputText"
22+
Padding="8"
23+
FontFamily="Cascadia Mono,Consolas,Menlo,monospace"
24+
FontSize="12"
25+
TextWrapping="Wrap"
26+
automation:AutomationProperties.Name="{Binding Title}"
27+
automation:AutomationProperties.AccessibilityView="Raw"/>
3628
</ScrollViewer>
3729

3830
</Window>

src/UniGetUI.Avalonia/Views/DialogPages/OperationOutputWindow.axaml.cs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
using System.Collections.Specialized;
12
using Avalonia.Controls;
3+
using Avalonia.Controls.Documents;
24
using Avalonia.Threading;
35
using UniGetUI.Avalonia.ViewModels.DialogPages;
6+
using UniGetUI.Avalonia.ViewModels.Pages.LogPages;
47
using UniGetUI.PackageOperations;
58

69
namespace UniGetUI.Avalonia.Views.DialogPages;
@@ -9,11 +12,39 @@ public partial class OperationOutputWindow : Window
912
{
1013
public OperationOutputWindow(AbstractOperation operation)
1114
{
12-
DataContext = new OperationOutputViewModel(operation);
15+
var vm = new OperationOutputViewModel(operation);
16+
DataContext = vm;
1317
InitializeComponent();
1418

15-
((OperationOutputViewModel)DataContext).OutputLines.CollectionChanged +=
16-
(_, _) => Dispatcher.UIThread.Post(OutputScroll.ScrollToEnd, DispatcherPriority.Background);
19+
foreach (var line in vm.OutputLines)
20+
AppendLine(line);
21+
22+
vm.OutputLines.CollectionChanged += OnOutputLinesChanged;
23+
}
24+
25+
private void OnOutputLinesChanged(object? sender, NotifyCollectionChangedEventArgs e)
26+
{
27+
Dispatcher.UIThread.Post(() =>
28+
{
29+
if (e.Action == NotifyCollectionChangedAction.Reset)
30+
{
31+
OutputText.Inlines?.Clear();
32+
}
33+
else if (e.NewItems is not null)
34+
{
35+
foreach (LogLineItem item in e.NewItems)
36+
AppendLine(item);
37+
}
38+
OutputScroll.ScrollToEnd();
39+
}, DispatcherPriority.Background);
40+
}
41+
42+
private void AppendLine(LogLineItem line)
43+
{
44+
var inlines = OutputText.Inlines ??= new InlineCollection();
45+
if (inlines.Count > 0)
46+
inlines.Add(new LineBreak());
47+
inlines.Add(new Run(line.Text) { Foreground = line.Foreground });
1748
}
1849

1950
protected override void OnOpened(EventArgs e)

0 commit comments

Comments
 (0)