Forge
csharpdeeb25a2
1#nullable enable
2
3namespace CascadeIDE.Features.Chat;
4
5/// <summary>Строка состояния Intercom в Skia-toolbar (compact / Forward), вместо «хвоста» в ленте.</summary>
6public static class ChatIntercomChromeStatusPresentation
7{
8 public const int MaxTopicChars = 28;
9 public const int MaxLineChars = 24;
10
11 public static string? FormatSubtitle(
12 ChatSurfaceSnapshot snapshot,
13 bool overviewMode,
14 Guid detailThreadId,
15 bool showTopicTabBar = false)
16 {
17 if (!overviewMode && showTopicTabBar)
18 {
19 var messageCount = ResolveMessageCount(snapshot, detailThreadId);
20 return $"сообщений: {messageCount}";
21 }
22
23 if (overviewMode)
24 {
25 var count = snapshot.Layout.Overview.Count;
26 return count == 0
27 ? null
28 : $"тем: {count} · {ChatThreadOverviewPresentation.CatalogFooter}";
29 }
30
31 var topic = ResolveTopicLabel(snapshot, detailThreadId);
32 var line = snapshot.ProductSpine.HasContent
33 ? ChatProductSpinePresentation.ResolveLineTitle(snapshot.ProductSpine)
34 : null;
35 var messages = ResolveMessageCount(snapshot, detailThreadId);
36
37 var parts = new List<string>(3)
38 {
39 "тема: " + Truncate(topic, MaxTopicChars),
40 };
41 if (!string.IsNullOrWhiteSpace(line))
42 parts.Add("линия: " + Truncate(line.Trim(), MaxLineChars));
43 parts.Add($"сообщений: {messages}");
44 return string.Join(" · ", parts);
45 }
46
47 private static string ResolveTopicLabel(ChatSurfaceSnapshot snapshot, Guid detailThreadId)
48 {
49 var fromOverview = snapshot.Layout.Overview.FirstOrDefault(t => t.ThreadId == detailThreadId)
50 ?? snapshot.Layout.Overview.FirstOrDefault(t => t.IsActive)
51 ?? snapshot.Layout.Overview.FirstOrDefault();
52 if (fromOverview is not null)
53 return fromOverview.Title;
54
55 var fromLane = snapshot.Layout.Lanes.FirstOrDefault(l => l.Thread.ThreadId == detailThreadId)
56 ?? snapshot.Layout.Lanes.FirstOrDefault(l => l.Thread.ThreadId == snapshot.State.ActiveThreadId)
57 ?? snapshot.Layout.Lanes.FirstOrDefault();
58 return fromLane?.Thread.Title ?? snapshot.State.ActiveThreadLabel;
59 }
60
61 private static int ResolveMessageCount(ChatSurfaceSnapshot snapshot, Guid detailThreadId)
62 {
63 var lane = snapshot.Layout.Lanes.FirstOrDefault(l => l.Thread.ThreadId == detailThreadId)
64 ?? snapshot.Layout.Lanes.FirstOrDefault(l => l.Thread.ThreadId == snapshot.State.ActiveThreadId);
65 if (lane is not null)
66 {
67 return lane.Entries.Count(e => e.Kind == ChatSurfaceEntryKind.Message);
68 }
69
70 var item = snapshot.Layout.Overview.FirstOrDefault(t => t.ThreadId == detailThreadId);
71 return item?.ItemCount ?? 0;
72 }
73
74 private static string Truncate(string text, int maxChars) =>
75 text.Length <= maxChars ? text : text[..maxChars] + "…";
76}
77
View only · write via MCP/CIDE