Forge
csharpdeeb25a2
1#nullable enable
2
3using Avalonia.Input;
4
5namespace CascadeIDE.Features.Chat;
6
7public partial class ChatPanelViewModel
8{
9 /// <summary>Обработка клавиш slash-composer / CCL; view синхронизирует surface по флагам результата.</summary>
10 public IntercomComposerKeyHandleResult TryHandleSlashComposerKey(
11 IntercomComposerKeyKind kind,
12 KeyEventArgs? keyEvent = null)
13 {
14 switch (kind)
15 {
16 case IntercomComposerKeyKind.Tab:
17 return handleTabCommitSuggestion();
18 case IntercomComposerKeyKind.SlashUp:
19 MoveComposerAutocompleteSelection(-1);
20 return new(true, false, false, false, false);
21 case IntercomComposerKeyKind.SlashDown:
22 MoveComposerAutocompleteSelection(1);
23 return new(true, false, false, false, false);
24 case IntercomComposerKeyKind.Escape:
25 if (IsCockpitCommandLineOpen)
26 {
27 CloseCockpitCommandLine();
28 return new(true, true, false, false, false);
29 }
30
31 DismissChatSlashAutocomplete();
32 DismissChatBracketAutocomplete();
33 return new(true, false, false, false, false);
34 case IntercomComposerKeyKind.Enter:
35 if (keyEvent is { } enterKey && IsChatLoading)
36 PrepareDeliveryModeForComposerKey(kind, enterKey);
37 return handleEnter(keyEvent);
38 case IntercomComposerKeyKind.CommitSlashSuggestion:
39 return handleTabCommitSuggestion();
40 default:
41 return default;
42 }
43 }
44
45 private IntercomComposerKeyHandleResult handleTabCommitSuggestion()
46 {
47 if (!TryCommitSelectedComposerSuggestion(out var autoExecute))
48 return default;
49
50 if (IsCockpitCommandLineOpen)
51 return new(true, true, false, autoExecute, false);
52
53 return new(true, false, true, false, autoExecute);
54 }
55
56 private IntercomComposerKeyHandleResult handleEnter(KeyEventArgs? keyEvent)
57 {
58 if (IsCockpitCommandLineOpen)
59 {
60 if (trySendRunnableSlashLine(keyEvent, CockpitCommandLineText, CockpitCommandLineCaretIndex, out var cclSend))
61 return new(true, true, false, cclSend, false);
62
63 if (IsComposerAutocompleteVisible
64 && TryCommitSelectedComposerSuggestion(out var cclAutoExecute))
65 {
66 return new(true, true, false, cclAutoExecute, false);
67 }
68
69 return new(true, true, false, true, false);
70 }
71
72 if (trySendRunnableSlashLine(keyEvent, ChatInput, ChatComposerCaretIndex, out var sendSlash))
73 return new(true, false, true, false, true);
74
75 if (IsComposerAutocompleteVisible
76 && TryCommitSelectedComposerSuggestion(out var autoExecute))
77 {
78 if (!autoExecute
79 && trySendRunnableSlashLine(keyEvent, ChatInput, ChatComposerCaretIndex, out _))
80 return new(true, false, true, false, true);
81
82 return new(true, false, true, false, autoExecute);
83 }
84
85 if (keyEvent is { } enterKey && ChatSendKeyMatcher.Matches(enterKey, GetSendMessageKey()))
86 return new(true, false, false, false, true);
87
88 return default;
89 }
90
91 private bool trySendRunnableSlashLine(KeyEventArgs? keyEvent, string text, int caret, out bool runCockpitCommit)
92 {
93 runCockpitCommit = false;
94 if (keyEvent is not { } enterKey)
95 return false;
96
97 if (!ChatSlashAutocomplete.IsRunnableSlashLineAtCaret(text, caret))
98 return false;
99
100 if (!ChatSendKeyMatcher.Matches(enterKey, GetSendMessageKey())
101 && !ChatSendKeyMatcher.IsBareEnterForSlashCommit(enterKey))
102 return false;
103
104 if (IsComposerAutocompleteVisible)
105 {
106 DismissChatSlashAutocomplete();
107 DismissChatBracketAutocomplete();
108 }
109
110 runCockpitCommit = IsCockpitCommandLineOpen;
111 return true;
112 }
113
114 /// <summary>Composer Enter без send: вставка новой строки (view обновляет текст/caret).</summary>
115 public bool TryInsertComposerNewLineAtCaret(string currentText, int caretIndex, out string newText, out int newCaret)
116 {
117 if (IsCockpitCommandLineOpen)
118 {
119 newText = currentText;
120 newCaret = caretIndex;
121 return false;
122 }
123
124 var caret = Math.Clamp(caretIndex, 0, currentText.Length);
125 newText = currentText.Insert(caret, "\n");
126 newCaret = caret + 1;
127 ChatInput = newText;
128 ChatComposerCaretIndex = newCaret;
129 return true;
130 }
131
132 [Obsolete("Use TryHandleSlashComposerKey.")]
133 public IntercomComposerKeyHandleResult TryHandleIntercomComposerKey(
134 IntercomComposerKeyKind kind,
135 KeyEventArgs? keyEvent = null) =>
136 TryHandleSlashComposerKey(kind, keyEvent);
137}
138
View only · write via MCP/CIDE