Files
FlClash/lib/ui/text.dart
T
chen08209 7c9627fffb feat(ui): add Liquid Glass and slide-to-pick popup menus
Changelog: Optional two-tier Liquid Glass and slide-to-pick menus
2026-10-17 17:21:43 +08:00

109 lines
2.6 KiB
Dart

import 'package:emoji_regex/emoji_regex.dart';
import 'package:fl_clash/ui/measure.dart';
import 'package:fl_clash/ui/text_style.dart';
import 'package:material_ui/material_ui.dart';
class TooltipText extends StatelessWidget {
final Text text;
const TooltipText({super.key, required this.text});
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final maxWidth = constraints.maxWidth;
final isOverflow = MeasureScope.of(
context,
).computeTextIsOverflow(text, maxWidth: maxWidth);
if (isOverflow) {
return Tooltip(
triggerMode: TooltipTriggerMode.longPress,
preferBelow: false,
message: text.data,
child: text,
);
}
return text;
},
);
}
}
class TooltipLabel extends StatelessWidget {
final String text;
final TextStyle? style;
final int maxLines;
const TooltipLabel(this.text, {super.key, this.style, this.maxLines = 2});
@override
Widget build(BuildContext context) {
return TooltipText(
text: Text(
text,
maxLines: maxLines,
overflow: TextOverflow.ellipsis,
style: DefaultTextStyle.of(context).style.merge(style),
),
);
}
}
class EmojiText extends StatelessWidget {
final String text;
final TextStyle? style;
final int? maxLines;
final TextOverflow? overflow;
const EmojiText(
this.text, {
super.key,
this.maxLines,
this.overflow,
this.style,
});
/// The spans [EmojiText] lays [text] out in, emoji in their own font.
static TextSpan spanOf(String text, TextStyle? style) {
final List<TextSpan> spans = [];
final matches = emojiRegex().allMatches(text);
int lastMatchEnd = 0;
for (final match in matches) {
if (match.start > lastMatchEnd) {
spans.add(
TextSpan(
text: text.substring(lastMatchEnd, match.start),
style: style,
),
);
}
spans.add(
TextSpan(
text: match.group(0),
style: (style ?? const TextStyle()).copyWith(
fontFamily: FontFamily.twEmoji.value,
),
),
);
lastMatchEnd = match.end;
}
if (lastMatchEnd < text.length) {
spans.add(TextSpan(text: text.substring(lastMatchEnd), style: style));
}
return TextSpan(children: spans);
}
@override
Widget build(BuildContext context) {
return Text.rich(
spanOf(text, style),
style: style,
maxLines: maxLines,
overflow: overflow ?? TextOverflow.clip,
);
}
}