fluffychat merge

This commit is contained in:
ggurdin 2026-02-05 11:40:05 -05:00
commit b0cf567bf1
No known key found for this signature in database
GPG key ID: A01CB41737CBB478
5 changed files with 97 additions and 41 deletions

View file

@ -2,9 +2,8 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:collection/collection.dart';
import 'package:flutter_highlighter/flutter_highlighter.dart';
import 'package:flutter_highlighter/themes/shades-of-purple.dart';
import 'package:flutter_linkify/flutter_linkify.dart';
import 'package:highlight/highlight.dart' show highlight;
import 'package:html/dom.dart' as dom;
import 'package:html/parser.dart' as parser;
import 'package:matrix/matrix.dart';
@ -23,6 +22,7 @@ import 'package:fluffychat/pangea/toolbar/reading_assistance/token_emoji_button.
import 'package:fluffychat/pangea/toolbar/reading_assistance/token_rendering_util.dart';
import 'package:fluffychat/pangea/toolbar/reading_assistance/tokens_util.dart';
import 'package:fluffychat/pangea/toolbar/reading_assistance/underline_text_widget.dart';
import 'package:fluffychat/utils/code_highlight_theme.dart';
import 'package:fluffychat/utils/event_checkbox_extension.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/future_loading_dialog.dart';
@ -368,6 +368,19 @@ class HtmlMessage extends StatelessWidget {
];
}
InlineSpan _renderCodeBlockNode(dom.Node node) {
if (node is! dom.Element) {
return TextSpan(text: node.text);
}
final style = atomOneDarkTheme[node.className.split('-').last] ??
atomOneDarkTheme['root'];
return TextSpan(
children: node.nodes.map(_renderCodeBlockNode).toList(),
style: style,
);
}
/// Transforms a Node to an InlineSpan.
InlineSpan _renderHtml(
dom.Node node,
@ -775,31 +788,40 @@ class HtmlMessage extends StatelessWidget {
);
case 'code':
final isInline = node.parent?.localName != 'pre';
final lang = node.className
.split(' ')
.singleWhereOrNull(
(className) => className.startsWith('language-'),
)
?.split('language-')
.last ??
'md';
final highlightedHtml =
highlight.parse(node.text, language: lang).toHtml();
final element = parser.parse(highlightedHtml).body;
if (element == null) {
return const TextSpan(text: 'Unable to render code block!');
}
return WidgetSpan(
child: Material(
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(4),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: HighlightView(
node.text,
language: node.className
.split(' ')
.singleWhereOrNull(
(className) => className.startsWith('language-'),
)
?.split('language-')
.last ??
'md',
theme: shadesOfPurpleTheme,
padding: EdgeInsets.symmetric(
horizontal: 8,
vertical: isInline ? 0 : 8,
),
textStyle: TextStyle(
fontSize: fontSize,
fontFamily: 'RobotoMono',
color: atomOneBackgroundColor,
shape: RoundedRectangleBorder(
side: const BorderSide(color: hightlightTextColor),
borderRadius: BorderRadius.circular(4),
),
child: Padding(
padding: isInline
? const EdgeInsets.symmetric(horizontal: 4.0)
: const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 4.0,
),
child: Text.rich(
TextSpan(
children: [_renderCodeBlockNode(element)],
),
selectionColor: hightlightTextColor.withAlpha(128),
),
),
),

View file

@ -0,0 +1,40 @@
import 'package:flutter/widgets.dart';
const hightlightTextColor = Color(0xffabb2bf);
const atomOneBackgroundColor = Color(0xff282c34);
const atomOneDarkTheme = {
'root': TextStyle(color: hightlightTextColor),
'comment': TextStyle(color: Color(0xff5c6370), fontStyle: FontStyle.italic),
'quote': TextStyle(color: Color(0xff5c6370), fontStyle: FontStyle.italic),
'doctag': TextStyle(color: Color(0xffc678dd)),
'keyword': TextStyle(color: Color(0xffc678dd)),
'formula': TextStyle(color: Color(0xffc678dd)),
'section': TextStyle(color: Color(0xffe06c75)),
'name': TextStyle(color: Color(0xffe06c75)),
'selector-tag': TextStyle(color: Color(0xffe06c75)),
'deletion': TextStyle(color: Color(0xffe06c75)),
'subst': TextStyle(color: Color(0xffe06c75)),
'literal': TextStyle(color: Color(0xff56b6c2)),
'string': TextStyle(color: Color(0xff98c379)),
'regexp': TextStyle(color: Color(0xff98c379)),
'addition': TextStyle(color: Color(0xff98c379)),
'attribute': TextStyle(color: Color(0xff98c379)),
'meta-string': TextStyle(color: Color(0xff98c379)),
'built_in': TextStyle(color: Color(0xffe6c07b)),
'attr': TextStyle(color: Color(0xffd19a66)),
'variable': TextStyle(color: Color(0xffd19a66)),
'template-variable': TextStyle(color: Color(0xffd19a66)),
'type': TextStyle(color: Color(0xffd19a66)),
'selector-class': TextStyle(color: Color(0xffd19a66)),
'selector-attr': TextStyle(color: Color(0xffd19a66)),
'selector-pseudo': TextStyle(color: Color(0xffd19a66)),
'number': TextStyle(color: Color(0xffd19a66)),
'symbol': TextStyle(color: Color(0xff61aeee)),
'bullet': TextStyle(color: Color(0xff61aeee)),
'link': TextStyle(color: Color(0xff61aeee)),
'meta': TextStyle(color: Color(0xff61aeee)),
'selector-id': TextStyle(color: Color(0xff61aeee)),
'title': TextStyle(color: Color(0xff61aeee)),
'emphasis': TextStyle(fontStyle: FontStyle.italic),
'strong': TextStyle(fontWeight: FontWeight.bold),
};

View file

@ -62,10 +62,12 @@ class ErrorReporter {
// height: 256,
// width: 256,
// child: SingleChildScrollView(
// child: HighlightView(
// child: Text(
// text,
// language: 'sh',
// theme: shadesOfPurpleTheme,
// style: const TextStyle(
// fontSize: 14,
// fontFamily: 'RobotoMono',
// ),
// ),
// ),
// ),

View file

@ -740,14 +740,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "9.1.0"
flutter_highlighter:
dependency: "direct main"
description:
name: flutter_highlighter
sha256: "93173afd47a9ada53f3176371755e7ea4a1065362763976d06d6adfb4d946e10"
url: "https://pub.dev"
source: hosted
version: "0.1.1"
flutter_html:
dependency: "direct main"
description:
@ -1120,14 +1112,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.4.0"
highlighter:
dependency: transitive
highlight:
dependency: "direct main"
description:
name: highlighter
sha256: "92180c72b9da8758e1acf39a45aa305a97dcfe2fdc8f3d1d2947c23f2772bfbc"
name: highlight
sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21"
url: "https://pub.dev"
source: hosted
version: "0.1.1"
version: "0.7.0"
html:
dependency: "direct main"
description:

View file

@ -36,7 +36,6 @@ dependencies:
flutter:
sdk: flutter
flutter_foreground_task: ^9.1.0
flutter_highlighter: ^0.1.1
flutter_linkify: ^6.0.0
flutter_local_notifications: ^19.5.0
flutter_localizations:
@ -51,6 +50,7 @@ dependencies:
geolocator: ^14.0.2
go_router: ^17.0.0
handy_window: ^0.4.0
highlight: ^0.7.0
html: ^0.15.4
http: ^1.6.0
image: ^4.1.7