Forge
csharpdeeb25a2
1using Avalonia.Threading;
2using CascadeIDE.ViewModels;
3using CommunityToolkit.Mvvm.ComponentModel;
4
5namespace CascadeIDE.Features.Build;
6
7/// <summary>
8/// Вкладка «Сборка · вывод» нижней панели: текст вывода сборки и связанных операций.
9/// <see cref="Append"/> коалесит обновления привязки через один <see cref="IUiScheduler.Post"/> на серию вызовов (фаза 5).
10/// </summary>
11public partial class BuildOutputPanelViewModel : ViewModelBase
12{
13 /// <summary>
14 /// Максимальный размер накопленного вывода (чтобы не ловить OOM на больших логах).
15 /// </summary>
16 public const int MaxChars = 250_000;
17
18 private readonly object _batchLock = new();
19 private OutputAccumulator _acc = new(MaxChars);
20 private int _contentVersion;
21 private bool _flushPosted;
22
23 [ObservableProperty]
24 private string _buildOutput = "";
25
26 public void Clear()
27 {
28 lock (_batchLock)
29 {
30 _contentVersion++;
31 _acc = new OutputAccumulator(MaxChars);
32 _flushPosted = false;
33 BuildOutput = "";
34 }
35 }
36
37 public void Set(string text)
38 {
39 lock (_batchLock)
40 {
41 _contentVersion++;
42 _acc = new OutputAccumulator(MaxChars);
43 _acc.Append((text ?? "").AsSpan());
44 _flushPosted = false;
45 BuildOutput = _acc.ToStringAndTrim();
46 }
47 }
48
49 public void Append(string text)
50 {
51 if (string.IsNullOrEmpty(text))
52 return;
53
54 int ver;
55 lock (_batchLock)
56 {
57 _acc.Append(text.AsSpan());
58 if (_flushPosted)
59 return;
60 _flushPosted = true;
61 ver = _contentVersion;
62 }
63
64 UiScheduler.Default.Post(() => FlushToUi(ver), DispatcherPriority.Background);
65 }
66
67 private void FlushToUi(int scheduledVersion)
68 {
69 lock (_batchLock)
70 {
71 if (scheduledVersion != _contentVersion)
72 {
73 _flushPosted = false;
74 return;
75 }
76
77 BuildOutput = _acc.ToStringAndTrim();
78 _flushPosted = false;
79 }
80 }
81
82 /// <summary>
83 /// Синхронно выставляет <see cref="BuildOutput"/> из накопителя и отменяет отложенный flush
84 /// (после серии <see cref="Append"/>, чтобы MCP/пользователь не читали устаревший текст).
85 /// </summary>
86 public void FlushPending()
87 {
88 lock (_batchLock)
89 {
90 _contentVersion++;
91 BuildOutput = _acc.ToStringAndTrim();
92 _flushPosted = false;
93 }
94 }
95}
96
View only · write via MCP/CIDE