mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: highlight code block (#5540)
This commit is contained in:
parent
1d23e28eaf
commit
ce1a6e4fca
@ -67,7 +67,19 @@ class ChatBloc extends Bloc<ChatEvent, ChatState> {
|
||||
chatId: state.view.id,
|
||||
limit: Int64(10),
|
||||
);
|
||||
ChatEventLoadNextMessage(payload).send();
|
||||
ChatEventLoadNextMessage(payload).send().then(
|
||||
(result) {
|
||||
result.fold((list) {
|
||||
if (!isClosed) {
|
||||
final messages =
|
||||
list.messages.map(_createTextMessage).toList();
|
||||
add(ChatEvent.didLoadLatestMessages(messages));
|
||||
}
|
||||
}, (err) {
|
||||
Log.error("Failed to load messages: $err");
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
startLoadingPrevMessage: () async {
|
||||
Int64? beforeMessageId;
|
||||
|
@ -2,6 +2,7 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/ai_chat/application/chat_ai_message_bloc.dart';
|
||||
import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart';
|
||||
import 'package:appflowy/plugins/ai_chat/presentation/chat_loading.dart';
|
||||
import 'package:appflowy/util/theme_extension.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
@ -13,6 +14,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_chat_types/flutter_chat_types.dart';
|
||||
import 'package:markdown_widget/markdown_widget.dart';
|
||||
|
||||
import 'selectable_highlight.dart';
|
||||
|
||||
class ChatAITextMessageWidget extends StatelessWidget {
|
||||
const ChatAITextMessageWidget({
|
||||
super.key,
|
||||
@ -132,16 +135,28 @@ class ChatAITextMessageWidget extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
PreConfig(
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.surfaceContainerHighest
|
||||
.withOpacity(0.6),
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(8.0),
|
||||
),
|
||||
),
|
||||
builder: (code, language) {
|
||||
return ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 800,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6.0)),
|
||||
child: SelectableHighlightView(
|
||||
code,
|
||||
language: language,
|
||||
theme: getHightlineTheme(context),
|
||||
padding: const EdgeInsets.all(14),
|
||||
textStyle: TextStyle(
|
||||
color: AFThemeExtension.of(context).textColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
PConfig(
|
||||
textStyle: TextStyle(
|
||||
@ -168,6 +183,51 @@ class ChatAITextMessageWidget extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, TextStyle> getHightlineTheme(BuildContext context) {
|
||||
return {
|
||||
'root': TextStyle(
|
||||
color: const Color(0xffabb2bf),
|
||||
backgroundColor:
|
||||
Theme.of(context).isLightMode ? Colors.white : Colors.black38,
|
||||
),
|
||||
'comment':
|
||||
const TextStyle(color: Color(0xff5c6370), fontStyle: FontStyle.italic),
|
||||
'quote':
|
||||
const TextStyle(color: Color(0xff5c6370), fontStyle: FontStyle.italic),
|
||||
'doctag': const TextStyle(color: Color(0xffc678dd)),
|
||||
'keyword': const TextStyle(color: Color(0xffc678dd)),
|
||||
'formula': const TextStyle(color: Color(0xffc678dd)),
|
||||
'section': const TextStyle(color: Color(0xffe06c75)),
|
||||
'name': const TextStyle(color: Color(0xffe06c75)),
|
||||
'selector-tag': const TextStyle(color: Color(0xffe06c75)),
|
||||
'deletion': const TextStyle(color: Color(0xffe06c75)),
|
||||
'subst': const TextStyle(color: Color(0xffe06c75)),
|
||||
'literal': const TextStyle(color: Color(0xff56b6c2)),
|
||||
'string': const TextStyle(color: Color(0xff98c379)),
|
||||
'regexp': const TextStyle(color: Color(0xff98c379)),
|
||||
'addition': const TextStyle(color: Color(0xff98c379)),
|
||||
'attribute': const TextStyle(color: Color(0xff98c379)),
|
||||
'meta-string': const TextStyle(color: Color(0xff98c379)),
|
||||
'built_in': const TextStyle(color: Color(0xffe6c07b)),
|
||||
'attr': const TextStyle(color: Color(0xffd19a66)),
|
||||
'variable': const TextStyle(color: Color(0xffd19a66)),
|
||||
'template-variable': const TextStyle(color: Color(0xffd19a66)),
|
||||
'type': const TextStyle(color: Color(0xffd19a66)),
|
||||
'selector-class': const TextStyle(color: Color(0xffd19a66)),
|
||||
'selector-attr': const TextStyle(color: Color(0xffd19a66)),
|
||||
'selector-pseudo': const TextStyle(color: Color(0xffd19a66)),
|
||||
'number': const TextStyle(color: Color(0xffd19a66)),
|
||||
'symbol': const TextStyle(color: Color(0xff61aeee)),
|
||||
'bullet': const TextStyle(color: Color(0xff61aeee)),
|
||||
'link': const TextStyle(color: Color(0xff61aeee)),
|
||||
'meta': const TextStyle(color: Color(0xff61aeee)),
|
||||
'selector-id': const TextStyle(color: Color(0xff61aeee)),
|
||||
'title': const TextStyle(color: Color(0xff61aeee)),
|
||||
'emphasis': const TextStyle(fontStyle: FontStyle.italic),
|
||||
'strong': const TextStyle(fontWeight: FontWeight.bold),
|
||||
};
|
||||
}
|
||||
|
||||
class ChatH1Config extends HeadingConfig {
|
||||
const ChatH1Config({
|
||||
this.style = const TextStyle(
|
||||
|
@ -0,0 +1,92 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:highlight/highlight.dart';
|
||||
|
||||
/// Highlight Flutter Widget
|
||||
class SelectableHighlightView extends StatelessWidget {
|
||||
SelectableHighlightView(
|
||||
String input, {
|
||||
super.key,
|
||||
this.language,
|
||||
this.theme = const {},
|
||||
this.padding,
|
||||
this.textStyle,
|
||||
int tabSize = 8,
|
||||
}) : source = input.replaceAll('\t', ' ' * tabSize);
|
||||
|
||||
/// The original code to be highlighted
|
||||
final String source;
|
||||
|
||||
/// Highlight language
|
||||
///
|
||||
/// It is recommended to give it a value for performance
|
||||
///
|
||||
/// [All available languages](https://github.com/pd4d10/highlight/tree/master/highlight/lib/languages)
|
||||
final String? language;
|
||||
|
||||
/// Highlight theme
|
||||
///
|
||||
/// [All available themes](https://github.com/pd4d10/highlight/blob/master/flutter_highlight/lib/themes)
|
||||
final Map<String, TextStyle> theme;
|
||||
|
||||
/// Padding
|
||||
final EdgeInsetsGeometry? padding;
|
||||
|
||||
/// Text styles
|
||||
///
|
||||
/// Specify text styles such as font family and font size
|
||||
final TextStyle? textStyle;
|
||||
|
||||
List<TextSpan> _convert(List<Node> nodes) {
|
||||
final List<TextSpan> spans = [];
|
||||
var currentSpans = spans;
|
||||
final List<List<TextSpan>> stack = [];
|
||||
|
||||
// ignore: always_declare_return_types
|
||||
traverse(Node node) {
|
||||
if (node.value != null) {
|
||||
currentSpans.add(
|
||||
node.className == null
|
||||
? TextSpan(text: node.value)
|
||||
: TextSpan(text: node.value, style: theme[node.className!]),
|
||||
);
|
||||
} else if (node.children != null) {
|
||||
final List<TextSpan> tmp = [];
|
||||
currentSpans
|
||||
.add(TextSpan(children: tmp, style: theme[node.className!]));
|
||||
stack.add(currentSpans);
|
||||
currentSpans = tmp;
|
||||
|
||||
for (final n in node.children!) {
|
||||
traverse(n);
|
||||
if (n == node.children!.last) {
|
||||
currentSpans = stack.isEmpty ? spans : stack.removeLast();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final node in nodes) {
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
return spans;
|
||||
}
|
||||
|
||||
static const _rootKey = 'root';
|
||||
static const _defaultBackgroundColor = Color(0xffffffff);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: theme[_rootKey]?.backgroundColor ?? _defaultBackgroundColor,
|
||||
padding: padding,
|
||||
child: SelectableText.rich(
|
||||
TextSpan(
|
||||
style: textStyle,
|
||||
children:
|
||||
_convert(highlight.parse(source, language: language).nodes!),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -681,7 +681,7 @@ packages:
|
||||
source: git
|
||||
version: "1.0.2"
|
||||
flutter_highlight:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_highlight
|
||||
sha256: "7b96333867aa07e122e245c033b8ad622e4e3a42a1a2372cbb098a2541d8782c"
|
||||
|
@ -149,6 +149,7 @@ dependencies:
|
||||
|
||||
# BitsDojo Window for Windows
|
||||
bitsdojo_window: ^0.1.6
|
||||
flutter_highlight: ^0.7.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_lints: ^3.0.1
|
||||
|
Loading…
Reference in New Issue
Block a user