Forge
csharpdeeb25a2
1using CascadeIDE.Cockpit.DataBus;
2using CascadeIDE.Features.HybridIndex.Application;
3using CascadeIDE.Models;
4using CommunityToolkit.Mvvm.ComponentModel;
5using CommunityToolkit.Mvvm.Input;
6
7namespace CascadeIDE.ViewModels;
8
9/// <summary>
10/// Hybrid Codebase Index (HCI): status projection and UI commands for the HIS (MFD) page.
11/// </summary>
12public partial class MainWindowViewModel
13{
14 private IDisposable? _hybridIndexStateSubscription;
15
16 /// <summary>
17 /// Имена свойств HIS, которые завязаны на <see cref="HybridIndexLast"/> или должны пересчитываться без нового <c>HybridIndexStateChanged</c> (UTC/открытие вкладки).
18 /// При добавлении свойства расширяй массив и список в <c>[NotifyPropertyChangedFor(...)]</c> над полем снимка индекса.
19 /// </summary>
20 private static readonly string[] HybridIndexDependentPresentationNames =
21 [
22 nameof(HybridIndexLampText),
23 nameof(HybridIndexStateShort),
24 nameof(HybridIndexDocumentCountText),
25 nameof(HybridIndexDocsValue),
26 nameof(HybridIndexDocsGauge01),
27 nameof(HybridIndexIndexedAtText),
28 nameof(HybridIndexFreshnessText),
29 nameof(HybridIndexFreshnessMinutes),
30 nameof(HybridIndexFreshnessMinutesText),
31 nameof(HybridIndexFreshnessEcamText),
32 nameof(HybridIndexLastErrorText),
33 nameof(HybridIndexWorkspaceRootText),
34 nameof(HybridIndexSolutionPathText),
35 nameof(HybridIndexDatabasePathText),
36 nameof(HybridIndexWorkspaceShortText),
37 nameof(HybridIndexSolutionShortText),
38 nameof(HybridIndexDatabaseShortText),
39 nameof(HybridIndexLampItem),
40 nameof(HybridIndexMsgLine1),
41 nameof(HybridIndexMsgLine2),
42 nameof(ShowPfdBackgroundStatusBar),
43 ];
44
45 [ObservableProperty]
46 [NotifyPropertyChangedFor(
47 nameof(HybridIndexLampText),
48 nameof(HybridIndexStateShort),
49 nameof(HybridIndexDocumentCountText),
50 nameof(HybridIndexDocsValue),
51 nameof(HybridIndexDocsGauge01),
52 nameof(HybridIndexIndexedAtText),
53 nameof(HybridIndexFreshnessText),
54 nameof(HybridIndexFreshnessMinutes),
55 nameof(HybridIndexFreshnessMinutesText),
56 nameof(HybridIndexFreshnessEcamText),
57 nameof(HybridIndexLastErrorText),
58 nameof(HybridIndexWorkspaceRootText),
59 nameof(HybridIndexSolutionPathText),
60 nameof(HybridIndexDatabasePathText),
61 nameof(HybridIndexWorkspaceShortText),
62 nameof(HybridIndexSolutionShortText),
63 nameof(HybridIndexDatabaseShortText),
64 nameof(HybridIndexLampItem),
65 nameof(HybridIndexMsgLine1),
66 nameof(HybridIndexMsgLine2),
67 nameof(ShowPfdBackgroundStatusBar))]
68 private HybridIndexStateChanged? _hybridIndexLast;
69
70 public string HybridIndexLampText => HybridIndexHisPresentationProjection.LampText(HybridIndexLast);
71
72 public string HybridIndexStateShort =>
73 HybridIndexHisPresentationProjection.StateShort(HybridIndexLast);
74
75 public string HybridIndexDocumentCountText =>
76 HybridIndexLast is null ? "—" : HybridIndexLast.DocumentCount.ToString(System.Globalization.CultureInfo.InvariantCulture);
77
78 public double HybridIndexDocsValue => (double)(HybridIndexLast?.DocumentCount ?? 0);
79
80 public double HybridIndexDocsGauge01 =>
81 HybridIndexHisPresentationProjection.DocsGauge01(HybridIndexLast?.DocumentCount ?? 0);
82
83 public double HybridIndexFreshnessMinutes =>
84 HybridIndexHisPresentationProjection.FreshnessTotalMinutes(
85 HybridIndexLast?.IndexedAtIso,
86 DateTimeOffset.UtcNow);
87
88 public string HybridIndexFreshnessMinutesText =>
89 HybridIndexHisPresentationProjection.FreshnessMinutesRoundedText(HybridIndexFreshnessMinutes);
90
91 public string HybridIndexFreshnessEcamText =>
92 HybridIndexHisPresentationProjection.FreshnessEcamText(HybridIndexFreshnessMinutes);
93
94 public string HybridIndexIndexedAtText =>
95 HybridIndexHisPresentationProjection.IndexedAtOrDash(HybridIndexLast?.IndexedAtIso);
96
97 public string HybridIndexFreshnessText =>
98 HybridIndexHisPresentationProjection.FreshnessColonLine(
99 HybridIndexLast?.IndexedAtIso,
100 DateTimeOffset.UtcNow);
101
102 public string HybridIndexLastErrorText =>
103 HybridIndexHisPresentationProjection.LastErrorOrDash(HybridIndexLast?.LastError);
104
105 public string HybridIndexWorkspaceRootText =>
106 HybridIndexHisPresentationProjection.OptionalFieldOrDash(HybridIndexLast?.WorkspaceRoot);
107
108 public string HybridIndexSolutionPathText =>
109 HybridIndexHisPresentationProjection.OptionalFieldOrDash(HybridIndexLast?.SolutionPath);
110
111 public string HybridIndexDatabasePathText =>
112 HybridIndexHisPresentationProjection.OptionalFieldOrDash(HybridIndexLast?.DatabasePath);
113
114 public string HybridIndexWorkspaceShortText => HybridIndexHisPathDisplayShortener.ShortenLikeEcam(HybridIndexWorkspaceRootText);
115 public string HybridIndexSolutionShortText => HybridIndexHisPathDisplayShortener.ShortenLikeEcam(HybridIndexSolutionPathText);
116 public string HybridIndexDatabaseShortText => HybridIndexHisPathDisplayShortener.ShortenLikeEcam(HybridIndexDatabasePathText);
117
118 public AnnunciatorLampItem HybridIndexLampItem =>
119 HybridIndexHisPresentationProjection.LampItem(HybridIndexLast);
120
121 public string HybridIndexMsgLine1 =>
122 $"HCI {HybridIndexLampText} DOCS {HybridIndexDocumentCountText} FRESH {HybridIndexFreshnessEcamText}";
123
124 public string HybridIndexMsgLine2 =>
125 $"{SolutionWarmupStatusText} | {HybridIndexHisPresentationProjection.SecondMessageLine(HybridIndexLastErrorText)}";
126
127 [RelayCommand]
128 private void HybridIndexReindexNow()
129 {
130 var sln = Workspace.SolutionPath;
131 var ws = WorkspaceDirectoryFromSolutionPath.Resolve(sln);
132 if (string.IsNullOrWhiteSpace(ws))
133 return;
134
135 _ = HybridIndexOrchestrationPolicy.TriggerReindexNowAsync(
136 _hybridIndex,
137 _settings.HybridIndex,
138 ChatMcpOnly,
139 ws,
140 sln,
141 CancellationToken.None);
142
143 RaiseHybridIndexPresentationProperties();
144 }
145
146 [RelayCommand]
147 private void HybridIndexOpenIndexDir()
148 {
149 var sln = Workspace.SolutionPath;
150 var ws = WorkspaceDirectoryFromSolutionPath.Resolve(sln);
151 if (string.IsNullOrWhiteSpace(ws))
152 return;
153 var dir = Path.Combine(ws, HybridIndexIndexDirectoryRelative.ResolveOrDefault(_settings.HybridIndex.IndexDir));
154 _osShell.TryOpenDirectory(dir);
155 }
156
157
158 private void EnsureHybridIndexSubscription()
159 {
160 if (_hybridIndexStateSubscription is not null)
161 return;
162 _hybridIndexStateSubscription = HybridIndexHisStateBusSubscription.Subscribe(
163 _ideDataBus,
164 UiScheduler.Default,
165 evt => HybridIndexLast = evt);
166 }
167
168 /// <summary>Перерисовать вычисляемые поля HIS без смены последнего события DataBus (свежесть от часов, открытие вкладки).</summary>
169 private void RaiseHybridIndexPresentationProperties()
170 {
171 foreach (var name in HybridIndexDependentPresentationNames)
172 OnPropertyChanged(name);
173 }
174
175}
176
177
View only · write via MCP/CIDE