94 lines
2.9 KiB
Dart
94 lines
2.9 KiB
Dart
import "package:flutter/material.dart" as material hide Card;
|
|
import "package:flutter_markdown/flutter_markdown.dart";
|
|
import "package:shadcn_flutter/shadcn_flutter.dart";
|
|
|
|
import "../../src/session/session_types.dart";
|
|
|
|
class MessageBubble extends StatelessWidget {
|
|
const MessageBubble({required this.message});
|
|
|
|
final Message message;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final isUser = message.role == "user";
|
|
final isTool = message.role == "tool";
|
|
final isAssistant = message.role == "assistant";
|
|
final accentColor = isTool
|
|
? const Color(0xFF64748B)
|
|
: const Color(0xFF94A3B8);
|
|
|
|
return Align(
|
|
alignment: isUser ? Alignment.centerRight : Alignment.centerLeft,
|
|
child: Container(
|
|
constraints: BoxConstraints(
|
|
maxWidth: material.MediaQuery.of(context).size.width * 0.7,
|
|
),
|
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
child: Card(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(12),
|
|
child: material.Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
message.role,
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w600,
|
|
color: accentColor,
|
|
),
|
|
),
|
|
const SizedBox(height: 4),
|
|
if (isAssistant || isTool)
|
|
MarkdownBody(
|
|
data: isTool
|
|
? _buildToolMarkdown(message.content)
|
|
: message.content,
|
|
selectable: true,
|
|
shrinkWrap: true,
|
|
styleSheet: isTool
|
|
? _toolMarkdownStyleSheet(context)
|
|
: null,
|
|
)
|
|
else
|
|
Text(message.content),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
String _buildToolMarkdown(String content) {
|
|
final lines = content.split("\n");
|
|
if (lines.isEmpty) {
|
|
return "```text\n\n```";
|
|
}
|
|
|
|
final title = lines.first.trim();
|
|
final body = lines.skip(1).join("\n").trimRight();
|
|
if (body.isEmpty) {
|
|
return title;
|
|
}
|
|
|
|
return "$title\n\n```text\n$body\n```";
|
|
}
|
|
|
|
MarkdownStyleSheet _toolMarkdownStyleSheet(BuildContext context) {
|
|
final theme = Theme.of(context);
|
|
return MarkdownStyleSheet.fromTheme(material.Theme.of(context)).copyWith(
|
|
p: theme.typography.base.copyWith(height: 1.35),
|
|
codeblockDecoration: BoxDecoration(
|
|
color: theme.colorScheme.muted.withValues(alpha: 0.35),
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
codeblockPadding: const EdgeInsets.all(12),
|
|
code: theme.typography.base.copyWith(
|
|
fontFamily: "monospace",
|
|
height: 1.35,
|
|
),
|
|
);
|
|
}
|
|
}
|