Forge
csharpdeeb25a2
1using System.Collections.ObjectModel;
2using Avalonia.Threading;
3using CascadeIDE.Models;
4using CascadeIDE.Services;
5using CascadeIDE.ViewModels;
6using CommunityToolkit.Mvvm.ComponentModel;
7using CommunityToolkit.Mvvm.Input;
8
9namespace CascadeIDE.Features.Debug;
10
11/// <summary>Вкладка «Гипотезы»: список из <see cref="DebugHypothesesStorage"/>.</summary>
12public sealed partial class HypothesesPanelViewModel : ViewModelBase
13{
14 private readonly Func<string> _getWorkspaceRoot;
15 private DispatcherTimer? _persistDebounce;
16
17 public HypothesesPanelViewModel(Func<string> getWorkspaceRoot)
18 {
19 _getWorkspaceRoot = getWorkspaceRoot;
20 }
21
22 /// <summary>Отложенная запись после правки текста (не на каждый символ).</summary>
23 public void RequestPersistSoon()
24 {
25 if (_persistDebounce is null)
26 {
27 _persistDebounce = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(450) };
28 _persistDebounce.Tick += OnPersistDebounceTick;
29 }
30
31 _persistDebounce.Stop();
32 _persistDebounce.Start();
33 }
34
35 private void OnPersistDebounceTick(object? sender, EventArgs e)
36 {
37 _persistDebounce?.Stop();
38 Persist();
39 }
40
41 public ObservableCollection<HypothesisRowViewModel> Items { get; } = [];
42
43 /// <summary>Перезагрузить с диска при смене workspace.</summary>
44 public void LoadFromWorkspace()
45 {
46 Items.Clear();
47 var root = _getWorkspaceRoot();
48 if (string.IsNullOrEmpty(root))
49 return;
50
51 var data = DebugHypothesesStorage.Load(root);
52 foreach (var r in data.Hypotheses)
53 {
54 if (string.IsNullOrWhiteSpace(r.Id))
55 continue;
56 Items.Add(new HypothesisRowViewModel(this, r));
57 }
58 }
59
60 internal void Persist()
61 {
62 var ws = _getWorkspaceRoot();
63 if (string.IsNullOrEmpty(ws))
64 return;
65
66 var root = new DebugHypothesesFileRoot
67 {
68 Version = 1,
69 Hypotheses = Items.Select(h => h.ToRecord()).Where(r => !string.IsNullOrWhiteSpace(r.Id)).ToList(),
70 };
71 DebugHypothesesStorage.Save(ws, root);
72 }
73
74 [RelayCommand]
75 private void AddHypothesis()
76 {
77 Items.Add(new HypothesisRowViewModel(this, new DebugHypothesisRecord
78 {
79 Id = Guid.NewGuid().ToString("N"),
80 Text = "",
81 Status = DebugHypothesisStatus.Open,
82 }));
83 Persist();
84 }
85
86 internal void RemoveRow(HypothesisRowViewModel row)
87 {
88 Items.Remove(row);
89 Persist();
90 }
91}
92
93/// <summary>Строка списка гипотез.</summary>
94public sealed partial class HypothesisRowViewModel : ViewModelBase
95{
96 private readonly HypothesesPanelViewModel _owner;
97
98 public HypothesisRowViewModel(HypothesesPanelViewModel owner, DebugHypothesisRecord record)
99 {
100 _owner = owner;
101 _id = record.Id;
102 _text = record.Text ?? "";
103 _status = record.Status;
104 }
105
106 [ObservableProperty]
107 private string _id;
108
109 [ObservableProperty]
110 private string _text;
111
112 [ObservableProperty]
113 private DebugHypothesisStatus _status;
114
115 partial void OnTextChanged(string value) => _owner.RequestPersistSoon();
116
117 partial void OnStatusChanged(DebugHypothesisStatus value) => _owner.Persist();
118
119 public DebugHypothesisRecord ToRecord() => new()
120 {
121 Id = Id,
122 Text = Text ?? "",
123 Status = Status,
124 };
125
126 [RelayCommand]
127 private void Remove() => _owner.RemoveRow(this);
128
129 [RelayCommand]
130 private void SetOpen() => Status = DebugHypothesisStatus.Open;
131
132 [RelayCommand]
133 private void SetRejected() => Status = DebugHypothesisStatus.Rejected;
134
135 [RelayCommand]
136 private void SetConfirmed() => Status = DebugHypothesisStatus.Confirmed;
137}
138
View only · write via MCP/CIDE