Skip to content

Commit 63cb201

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

File tree

2 files changed

+19
-16
lines changed

2 files changed

+19
-16
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ class UserMessage extends StatelessWidget {
2929
),
3030
child: MentionTextField(
3131
controller: MentionTextEditingController(text: message.content),
32+
style: Theme.of(context).textTheme.bodyMedium,
3233
readOnly: true,
34+
selectionColor: Theme.of(context).colorScheme.primaryContainer,
3335
),
3436
),
3537
),

client/lib/widgets/mention_text.dart

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import 'package:flutter/material.dart';
55
import 'package:flutter/services.dart';
66
import 'package:hugeicons/hugeicons.dart';
77

8+
/// 统一的 marker 字符:
9+
/// - encodedString 中用于标记 mention 结束(@label + marker)
10+
/// - driverString 中用于 TextField 驱动的 placeholder(mention 视为一个字符)
11+
const String _marker = '\uE000';
12+
813
sealed class Segment {
914
int get driverLength => switch (this) {
1015
TextSegment(:final value) => value.length,
@@ -42,11 +47,6 @@ typedef MentionItemBuilder = Widget Function(
4247
String query,
4348
);
4449

45-
/// 统一的 marker 字符:
46-
/// - encodedString 中用于标记 mention 结束(@label + marker)
47-
/// - driverString 中用于 TextField 驱动的 placeholder(mention 视为一个字符)
48-
const String _marker = '\uE000';
49-
5050
class MentionSegmentSerializer {
5151
static String encode(List<Segment> segments) {
5252
return segments
@@ -117,14 +117,19 @@ class MentionTextController extends TextEditingController {
117117
MentionTextController({String? text})
118118
: _segments = text != null ? MentionSegmentSerializer.decode(text) : <Segment>[],
119119
super(text: '') {
120-
final initialDriver = _segmentsToDriverString(_segments);
120+
final initialDriver = _segmentsToDriverString();
121121
super.value = TextEditingValue(
122122
text: initialDriver,
123123
selection: TextSelection.collapsed(offset: initialDriver.length),
124124
);
125125
_updateMentionState();
126126
}
127127

128+
/// 将 segment 转化成 value 给 TextEditingController 使用
129+
String _segmentsToDriverString() {
130+
return _segments.map((s) => s.toDriverString(_marker)).join();
131+
}
132+
128133
List<Segment> get segments => List.unmodifiable(_segments);
129134

130135
String get displayText => MentionSegmentSerializer.encode(_segments);
@@ -150,7 +155,7 @@ class MentionTextController extends TextEditingController {
150155
if (index < 0) return false;
151156

152157
_segments.removeAt(index);
153-
final driver = _segmentsToDriverString(_segments);
158+
final driver = _segmentsToDriverString();
154159
super.value = TextEditingValue(
155160
text: driver,
156161
selection: TextSelection.collapsed(offset: driverOffset.clamp(0, driver.length)),
@@ -162,7 +167,7 @@ class MentionTextController extends TextEditingController {
162167

163168
void loadFromEncodedString(String encodedString) {
164169
_segments = MentionSegmentSerializer.decode(encodedString);
165-
final driver = _segmentsToDriverString(_segments);
170+
final driver = _segmentsToDriverString();
166171
super.value = TextEditingValue(
167172
text: driver,
168173
selection: TextSelection.collapsed(offset: driver.length),
@@ -179,7 +184,7 @@ class MentionTextController extends TextEditingController {
179184
final end = selection.extentOffset.clamp(start, driverText.length);
180185
_replaceRangeInSegments(start, end, [MentionSegment(label: label)]);
181186
mentionState.value = null;
182-
final newDriver = _segmentsToDriverString(_segments);
187+
final newDriver = _segmentsToDriverString();
183188
super.value = TextEditingValue(
184189
text: newDriver,
185190
selection: TextSelection.collapsed(offset: (start + 1).clamp(0, newDriver.length)),
@@ -206,7 +211,7 @@ class MentionTextController extends TextEditingController {
206211
final start = math.min(sel.start, sel.end);
207212
final end = math.max(sel.start, sel.end);
208213
_replaceRangeInSegments(start, end, const []);
209-
final driver = _segmentsToDriverString(_segments);
214+
final driver = _segmentsToDriverString();
210215
super.value = TextEditingValue(
211216
text: driver,
212217
selection: TextSelection.collapsed(offset: start.clamp(0, driver.length)),
@@ -226,7 +231,7 @@ class MentionTextController extends TextEditingController {
226231
final start = sel.isValid ? math.min(sel.start, sel.end) : text.length;
227232
final end = sel.isValid ? math.max(sel.start, sel.end) : text.length;
228233
_replaceRangeInSegments(start, end, inserted);
229-
final driver = _segmentsToDriverString(_segments);
234+
final driver = _segmentsToDriverString();
230235
final caret = (start + inserted.fold<int>(0, (a, s) => a + s.driverLength)).clamp(0, driver.length);
231236
super.value = TextEditingValue(
232237
text: driver,
@@ -260,7 +265,7 @@ class MentionTextController extends TextEditingController {
260265

261266
_replaceRangeInSegments(delStart, delEnd, inserted.isEmpty ? [] : [TextSegment(inserted)]);
262267

263-
final driver = _segmentsToDriverString(_segments);
268+
final driver = _segmentsToDriverString();
264269
final clampedSelection = _clampSelection(
265270
newValue.selection,
266271
driver.length,
@@ -355,10 +360,6 @@ class MentionTextController extends TextEditingController {
355360
return TextSpan(children: spans, style: baseStyle);
356361
}
357362

358-
static String _segmentsToDriverString(List<Segment> segments) {
359-
return segments.map((s) => s.toDriverString(_marker)).join();
360-
}
361-
362363
List<Segment> _sliceSegments(int start, int end) {
363364
final out = <Segment>[];
364365
int currentOffset = 0;

0 commit comments

Comments
 (0)