madari-oss/lib/features/chat/container/chat_bubble.dart
Madari Developers 16fe4a653f Project import generated by Copybara.
GitOrigin-RevId: 829626e92d5dba6a4586d1e7c4bd1615ec396e88
2025-01-02 18:46:26 +00:00

158 lines
6 KiB
Dart

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
class ChatBubble extends StatelessWidget {
final String message;
final bool isUser;
final bool isComplete;
final VoidCallback? onCancel;
final bool isStreaming = false;
final int length;
const ChatBubble({
super.key,
required this.message,
required this.isUser,
this.isComplete = true,
this.onCancel,
this.length = 0,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 4.0),
child: Column(
crossAxisAlignment:
isUser ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment:
isUser ? MainAxisAlignment.end : MainAxisAlignment.start,
children: [
const SizedBox(width: 8),
Flexible(
child: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 5,
offset: const Offset(0, 2),
),
],
),
child: GestureDetector(
onTap: () {
showDialog(
context: context,
builder: (context) => BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: AlertDialog(
contentPadding: const EdgeInsets.only(
bottom: 12,
),
insetPadding: const EdgeInsets.all(10),
title: const Text("Message"),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Close'),
),
TextButton.icon(
onPressed: () {
Clipboard.setData(
ClipboardData(text: message),
);
},
label: const Text('Copy'),
icon: const Icon(Icons.copy),
),
],
content: Container(
constraints: BoxConstraints(
maxHeight:
MediaQuery.of(context).size.height - 220,
),
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 20),
MarkdownBody(
data: message,
selectable: true,
),
],
),
),
),
),
),
),
);
},
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: isUser
? Theme.of(context).primaryColor.withOpacity(0.9)
: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(20),
border: !isUser
? Border.all(color: Colors.grey.withOpacity(0.2))
: null,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
message.trim().isEmpty && isUser
? Column(
children: [
const Icon(Icons.file_present),
Text("Files Attached $length"),
],
)
: MarkdownBody(
data: message,
styleSheet: MarkdownStyleSheet(
p: TextStyle(
color: isUser
? Colors.white
: Theme.of(context)
.textTheme
.bodyLarge
?.color,
fontSize: 16,
),
),
),
],
),
),
),
),
),
if (isUser) _buildAvatar(true),
],
),
],
),
);
}
Widget _buildAvatar(bool isUser) {
return CircleAvatar(
backgroundColor: isUser ? Colors.blue.shade700 : Colors.grey.shade900,
child: Icon(
isUser ? Icons.person : Icons.auto_awesome,
color: Colors.white,
),
);
}
}