PraxaLing / mobile /lib /widgets /furi_text.dart
Reubencf's picture
Deploy PraxaLing: component refactor, bug fixes, unified neo-brutal design, Qwen3.5 everywhere
2992997
Raw
History Blame Contribute Delete
2.53 kB
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../theme/app_theme.dart';
class FuriSegment {
const FuriSegment({required this.text, this.reading});
final String text;
final String? reading;
factory FuriSegment.fromJson(Map<String, dynamic> json) => FuriSegment(
text: (json['text'] ?? '').toString(),
reading: (json['reading'] is String && (json['reading'] as String).isNotEmpty)
? json['reading'] as String
: null,
);
}
List<FuriSegment>? parseFuriSegments(dynamic raw) {
if (raw is! List) return null;
final segments = <FuriSegment>[];
for (final item in raw) {
if (item is Map) {
final seg = FuriSegment.fromJson(Map<String, dynamic>.from(item));
if (seg.text.isNotEmpty) segments.add(seg);
}
}
return segments.isEmpty ? null : segments;
}
class FuriText extends StatelessWidget {
const FuriText({
super.key,
required this.text,
this.segments,
required this.fontSize,
this.color = kBrutalBlack,
this.fontWeight = FontWeight.w900,
this.readingColor = kBrutalMuted,
});
final String text;
final List<FuriSegment>? segments;
final double fontSize;
final Color color;
final FontWeight fontWeight;
final Color readingColor;
@override
Widget build(BuildContext context) {
final segs = segments;
final mainStyle = GoogleFonts.almarai(
fontSize: fontSize,
fontWeight: fontWeight,
color: color,
height: 1.0,
);
if (segs == null || segs.isEmpty) {
return Text(text, style: mainStyle);
}
final readingSize = (fontSize * 0.45).clamp(9.0, 18.0);
final readingStyle = GoogleFonts.almarai(
fontSize: readingSize,
fontWeight: FontWeight.w800,
color: readingColor,
height: 1.0,
);
final readingSlotHeight = readingSize + 2;
return Wrap(
crossAxisAlignment: WrapCrossAlignment.end,
children: segs
.map(
(seg) => Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: readingSlotHeight,
child: seg.reading != null
? Center(child: Text(seg.reading!, style: readingStyle))
: null,
),
Text(seg.text, style: mainStyle),
],
),
)
.toList(),
);
}
}