Skip to content

Commit d635eeb

Browse files
committed
text field 重构,简化ai写的代码逻辑
1 parent 801a5ad commit d635eeb

File tree

5 files changed

+146
-410
lines changed

5 files changed

+146
-410
lines changed

client/lib/screens/sessions/ai_chat/input_user.dart

Lines changed: 5 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,6 @@ class SessionChatInputCard extends ConsumerStatefulWidget {
3030
}
3131

3232
class _SessionChatInputCardState extends ConsumerState<SessionChatInputCard> {
33-
Set<String> _extractMentionedTables(String encoded) {
34-
final segments = MentionSegmentSerializer.decode(encoded);
35-
final tableNames = <String>{};
36-
37-
// 只取“真正的 mention token”
38-
for (final s in segments) {
39-
if (s is MentionSegment) {
40-
tableNames.add(s.label);
41-
}
42-
}
43-
44-
return tableNames;
45-
}
46-
4733
MetaDataNode? _findSchemaNode(SessionAIChatModel chatModel) {
4834
if (chatModel.metadata == null || chatModel.currentSchema == null) return null;
4935
final root = MetaDataNode(MetaType.instance, "", items: chatModel.metadata!.metadata);
@@ -87,13 +73,11 @@ class _SessionChatInputCardState extends ConsumerState<SessionChatInputCard> {
8773

8874
Future<void> _sendMessage(AIChatId chatId, SessionAIChatModel chatModel) async {
8975
final chatInputController = SessionController.sessionController(chatModel.sessionId).chatInputController;
90-
final encoded = chatInputController.text.trim();
91-
final segments = MentionSegmentSerializer.decode(encoded);
92-
final text = segments.map((s) => s.toDisplayText()).join().trim();
76+
final text = chatInputController.displayText;
9377
chatInputController.clear();
9478

9579
// 如果用户通过 @ 提及了表,则把表结构信息放到 ref 里
96-
final mentionedTables = _extractMentionedTables(encoded);
80+
final mentionedTables = chatInputController.segments.whereType<MentionSegment>().map((s) => s.label).toList();
9781
final refText = _buildTableRef(chatModel, mentionedTables);
9882

9983
// 调用AIChatService的chat方法
@@ -325,112 +309,6 @@ class ChatInputFieldWidget extends ConsumerStatefulWidget {
325309
}
326310

327311
class _ChatInputFieldWidgetState extends ConsumerState<ChatInputFieldWidget> {
328-
late final MentionTextEditingController _controller;
329-
late final SessionController _sessionController;
330-
late final VoidCallback _syncFromMention;
331-
late final VoidCallback _syncFromSession;
332-
bool _syncing = false;
333-
334-
@override
335-
void initState() {
336-
super.initState();
337-
_sessionController = SessionController.sessionController(widget.model.sessionId);
338-
final stored = _sessionController.chatInputController.text;
339-
final looksEncoded = stored.contains(MentionSegmentSerializer.mentionEndChar);
340-
_controller = MentionTextEditingController(
341-
text: looksEncoded ? null : stored,
342-
encodedString: looksEncoded ? stored : null,
343-
mentionBuilderV2: _buildMentionWidget,
344-
);
345-
346-
_syncFromMention = () {
347-
if (_syncing) return;
348-
_syncing = true;
349-
_sessionController.chatInputController.text = _controller.toEncodedString();
350-
_syncing = false;
351-
};
352-
_syncFromSession = () {
353-
if (_syncing) return;
354-
_syncing = true;
355-
final encoded = _sessionController.chatInputController.text;
356-
if (encoded != _controller.toEncodedString()) {
357-
_controller.loadFromEncodedString(encoded);
358-
}
359-
_syncing = false;
360-
};
361-
362-
_controller.addListener(_syncFromMention);
363-
_sessionController.chatInputController.addListener(_syncFromSession);
364-
365-
// 初始化时确保 session 保存的是 encodedString
366-
_syncFromMention();
367-
}
368-
369-
@override
370-
void dispose() {
371-
_controller.removeListener(_syncFromMention);
372-
_sessionController.chatInputController.removeListener(_syncFromSession);
373-
_controller.dispose();
374-
super.dispose();
375-
}
376-
377-
Widget _buildMentionWidget(
378-
BuildContext context,
379-
MentionSegment segment,
380-
TextStyle baseStyle,
381-
bool hovering,
382-
VoidCallback onDelete,
383-
) {
384-
final colorScheme = Theme.of(context).colorScheme;
385-
final cardBg = colorScheme.primaryContainer;
386-
final cardFg = colorScheme.onSurface;
387-
final fontSize = baseStyle.fontSize ?? 14;
388-
// 让 token 的高度尽量贴近 TextField 的行高(selection 背景高度也会更一致)。
389-
final heightFactor = baseStyle.height ?? 1.0;
390-
final tokenHeight = fontSize * heightFactor;
391-
final labelStyle = baseStyle.copyWith(color: cardFg, height: heightFactor);
392-
return Container(
393-
key: ValueKey('table_mention_${segment.label}'),
394-
padding: const EdgeInsets.symmetric(horizontal: 6),
395-
decoration: BoxDecoration(
396-
color: cardBg,
397-
borderRadius: BorderRadius.circular(5),
398-
),
399-
child: SizedBox(
400-
height: tokenHeight,
401-
child: Row(
402-
mainAxisSize: MainAxisSize.min,
403-
crossAxisAlignment: CrossAxisAlignment.center,
404-
children: [
405-
if (hovering)
406-
GestureDetector(
407-
behavior: HitTestBehavior.opaque,
408-
onTap: onDelete,
409-
child: Icon(
410-
Icons.close_rounded,
411-
size: fontSize,
412-
color: cardFg,
413-
),
414-
)
415-
else
416-
HugeIcon(
417-
icon: HugeIcons.strokeRoundedTable,
418-
size: fontSize,
419-
color: cardFg,
420-
),
421-
const SizedBox(width: 4),
422-
Center(
423-
child: Text(
424-
segment.label,
425-
style: labelStyle,
426-
),
427-
),
428-
],
429-
),
430-
),
431-
);
432-
}
433-
434312
List<String> _getTableNames() {
435313
if (widget.model.metadata == null || widget.model.currentSchema == null) {
436314
return [];
@@ -525,9 +403,10 @@ class _ChatInputFieldWidgetState extends ConsumerState<ChatInputFieldWidget> {
525403

526404
@override
527405
Widget build(BuildContext context) {
406+
final controller = SessionController.sessionController(widget.model.sessionId).chatInputController;
528407
final tokenBg = Theme.of(context).colorScheme.primaryContainer;
529408
return MentionTextField(
530-
controller: _controller,
409+
controller: controller,
531410
style: Theme.of(context).textTheme.bodyMedium,
532411
textAlignVertical: TextAlignVertical.center,
533412
minLines: 1,
@@ -545,7 +424,7 @@ class _ChatInputFieldWidgetState extends ConsumerState<ChatInputFieldWidget> {
545424
mentionItemBuilder: _mentionItemBuilder,
546425
onSubmitted: (_) {
547426
widget.onSubmitted?.call();
548-
_controller.loadFromEncodedString('');
427+
controller.clear();
549428
},
550429
);
551430
}

client/lib/screens/sessions/ai_chat/message_user.dart

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:client/models/ai.dart';
22
import 'package:client/widgets/const.dart';
3+
import 'package:client/widgets/mention_text.dart';
34
import 'package:flutter/material.dart';
45

56
class UserMessage extends StatelessWidget {
@@ -26,11 +27,9 @@ class UserMessage extends StatelessWidget {
2627
width: 0.5,
2728
),
2829
),
29-
child: Text(
30-
message.content,
31-
style: TextStyle(
32-
color: Theme.of(context).colorScheme.onSurface,
33-
),
30+
child: MentionTextField(
31+
controller: MentionTextEditingController(text: message.content),
32+
readOnly: true,
3433
),
3534
),
3635
),

client/lib/services/sessions/session_controller.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:client/widgets/split_view.dart';
66
import 'package:flutter/material.dart';
77
import 'package:client/widgets/scroll.dart';
88
import 'package:sql_editor/re_editor.dart';
9+
import 'package:client/widgets/mention_text.dart';
910

1011
class SessionController {
1112
// split
@@ -16,7 +17,7 @@ class SessionController {
1617
final CodeScrollController sqlEditorScrollController;
1718

1819
// ai chat
19-
final TextEditingController chatInputController;
20+
final MentionTextEditingController chatInputController;
2021
final TextEditingController aiChatSearchTextController;
2122
final TextEditingController aiChatModelSearchTextController;
2223
final KeepOffestScrollController aiChatScrollController;
@@ -52,7 +53,7 @@ class SessionController {
5253
// ai chat
5354
aiChatSearchTextController: TextEditingController(),
5455
aiChatModelSearchTextController: TextEditingController(),
55-
chatInputController: TextEditingController(),
56+
chatInputController: MentionTextEditingController(),
5657
aiChatScrollController: KeepOffestScrollController(),
5758

5859
// drawer

0 commit comments

Comments
 (0)