96 lines
2.7 KiB
Dart
96 lines
2.7 KiB
Dart
import 'dart:ui';
|
|
|
|
import 'package:extended_text/extended_text.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/gestures.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:yumi/ui_kit/theme/socialchat_theme.dart';
|
|
import 'package:yumi/shared/tools/sc_string_utils.dart';
|
|
|
|
class AtTextSpanBuilder extends SpecialTextSpanBuilder {
|
|
final Function(String userId)? onTapCall;
|
|
|
|
AtTextSpanBuilder({this.onTapCall});
|
|
|
|
@override
|
|
SpecialText? createSpecialText(
|
|
String flag, {
|
|
TextStyle? textStyle,
|
|
SpecialTextGestureTapCallback? onTap,
|
|
required int index,
|
|
}) {
|
|
if (isStart(flag, AtText.flag)) {
|
|
return AtText(
|
|
textStyle: textStyle!,
|
|
start: index - (AtText.flag.length - 1),
|
|
onTap: (userId) {
|
|
onTapCall?.call(userId);
|
|
},
|
|
);
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
class AtText extends SpecialText {
|
|
static const String flag = '<user id="';
|
|
static const String endFlag2 = '</user>';
|
|
final int start;
|
|
final SpecialTextGestureTapCallback? onTap;
|
|
|
|
AtText({
|
|
required TextStyle textStyle,
|
|
required this.start,
|
|
required this.onTap,
|
|
}) : super(flag, endFlag2, textStyle, onTap: onTap);
|
|
|
|
@override
|
|
InlineSpan finishText() {
|
|
final String atContent = toString();
|
|
final TextStyle style =
|
|
textStyle?.copyWith(color: SocialChatTheme.primaryLight, fontWeight: FontWeight.w600) ??
|
|
const TextStyle();
|
|
String userName = _extractUserName(toString());
|
|
return SpecialTextSpan(
|
|
start: start,
|
|
actualText: atContent,
|
|
deleteAll: true,
|
|
style: style,
|
|
text:
|
|
SCStringUtils.containsArabicCharacters(userName) ? "${userName}@" : "@${userName}",
|
|
recognizer:
|
|
TapGestureRecognizer()
|
|
..onTap = () {
|
|
onTap?.call(_extractUserId(atContent));
|
|
},
|
|
);
|
|
}
|
|
|
|
/// 提取用户ID
|
|
String _extractUserId(String atContent) {
|
|
// 匹配 id="xxx"
|
|
final RegExp exp = RegExp(r'id\s*=\s*"([^"]*)"');
|
|
final RegExpMatch? match = exp.firstMatch(atContent);
|
|
return match?.group(1)?.trim() ?? '';
|
|
}
|
|
|
|
/// 提取用户名
|
|
String _extractUserName(String atContent) {
|
|
// 匹配 >用户名<
|
|
final RegExp exp = RegExp(r'>([^<]+)<');
|
|
final RegExpMatch? match = exp.firstMatch(atContent);
|
|
return match?.group(1)?.trim() ?? '';
|
|
}
|
|
|
|
@override
|
|
bool operator ==(Object other) {
|
|
if (identical(this, other)) return true;
|
|
return other is AtText &&
|
|
other.start == start &&
|
|
other.toString() == toString();
|
|
}
|
|
|
|
@override
|
|
int get hashCode => start.hashCode ^ toString().hashCode;
|
|
}
|