flexible bubble

This commit is contained in:
Chen Li
2025-08-22 09:28:15 +08:00
parent 2f0e82fd69
commit f5116fb2ac
2 changed files with 42 additions and 72 deletions

View File

@@ -72,7 +72,7 @@ class _PartScreenState extends State<PartScreen> {
context.watch<MessageService>().messages.length; context.watch<MessageService>().messages.length;
double chatHeight; double chatHeight;
if (messageCount <= 1) { if (messageCount <= 1) {
chatHeight = minHeight; chatHeight = minHeight + 70;
} else { } else {
final height = minHeight + (messageCount * 78); final height = minHeight + (messageCount * 78);
chatHeight = height < maxHeight ? height : maxHeight; chatHeight = height < maxHeight ? height : maxHeight;

View File

@@ -28,56 +28,20 @@ class _ChatBubbleState extends State<ChatBubble> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isThinking = message.status == MessageStatus.thinking; final isThinking = message.status == MessageStatus.thinking;
return Align( final content = Container(
alignment: message.isUser ? Alignment.centerRight : Alignment.centerLeft, constraints: const BoxConstraints(minWidth: 50),
child: Column( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
crossAxisAlignment:
message.isUser ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: [
Container(
constraints: const BoxConstraints(
minWidth: 50,
),
width: isThinking ? double.infinity : null,
child: isThinking
? Container(
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 12),
decoration: BoxDecoration(
color: message.isUser
? CommonUtil.commonColor
: Colors.white.withValues(alpha: 0.12),
borderRadius: message.isUser
? BorderRadius.only(
topLeft: Radius.circular(12),
bottomLeft: Radius.circular(12),
bottomRight: Radius.circular(12),
)
: BorderRadius.only(
topRight: Radius.circular(12),
bottomLeft: Radius.circular(12),
bottomRight: Radius.circular(12),
),
),
child: _buildAssistantContent(isThinking),
)
: Container(
constraints: const BoxConstraints(
minWidth: 50,
),
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: message.isUser color: message.isUser
? CommonUtil.commonColor ? CommonUtil.commonColor
: Colors.white.withOpacity(0.12), : Colors.white.withOpacity(0.12),
borderRadius: message.isUser borderRadius: message.isUser
? BorderRadius.only( ? const BorderRadius.only(
topLeft: Radius.circular(12), topLeft: Radius.circular(12),
bottomLeft: Radius.circular(12), bottomLeft: Radius.circular(12),
bottomRight: Radius.circular(12), bottomRight: Radius.circular(12),
) )
: BorderRadius.only( : const BorderRadius.only(
topRight: Radius.circular(12), topRight: Radius.circular(12),
bottomLeft: Radius.circular(12), bottomLeft: Radius.circular(12),
bottomRight: Radius.circular(12), bottomRight: Radius.circular(12),
@@ -86,9 +50,24 @@ class _ChatBubbleState extends State<ChatBubble> {
child: message.isUser child: message.isUser
? _buildUserContent() ? _buildUserContent()
: _buildAssistantContent(isThinking), : _buildAssistantContent(isThinking),
);
// 用户气泡做宽度自适应处理
final wrappedContent = message.isUser
? ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: double.infinity,
), ),
), child: IntrinsicWidth(child: content),
], )
: content;
return Align(
alignment: message.isUser ? Alignment.centerRight : Alignment.centerLeft,
child: Column(
crossAxisAlignment:
message.isUser ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: [wrappedContent],
), ),
); );
} }
@@ -129,9 +108,7 @@ class _ChatBubbleState extends State<ChatBubble> {
case MessageStatus.listening: case MessageStatus.listening:
case MessageStatus.recognizing: case MessageStatus.recognizing:
case MessageStatus.thinking: case MessageStatus.thinking:
icon = RotatingImage( icon = RotatingImage(imagePath: 'assets/images/thinking_circle.png');
imagePath: 'assets/images/thinking_circle.png'
);
color = Colors.white; color = Colors.white;
break; break;
case MessageStatus.executing: case MessageStatus.executing:
@@ -146,11 +123,7 @@ class _ChatBubbleState extends State<ChatBubble> {
break; break;
case MessageStatus.completed: case MessageStatus.completed:
case MessageStatus.success: case MessageStatus.success:
icon = Image.asset( icon = Image.asset('assets/images/checked.png', width: 20, height: 20);
'assets/images/checked.png',
width: 20,
height: 20
);
color = Colors.white; color = Colors.white;
break; break;
case MessageStatus.failure: case MessageStatus.failure:
@@ -274,8 +247,8 @@ class _ChatBubbleState extends State<ChatBubble> {
child: Divider(color: Colors.white, height: 1), child: Divider(color: Colors.white, height: 1),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
SizedBox( ConstrainedBox(
height: 24, constraints: const BoxConstraints(minHeight: 24),
child: isThinking child: isThinking
? Row( ? Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
@@ -328,11 +301,8 @@ class _ChatBubbleState extends State<ChatBubble> {
}, },
child: Padding( child: Padding(
padding: const EdgeInsets.only(left: 12), padding: const EdgeInsets.only(left: 12),
child: Image.asset( child: Image.asset('assets/images/copy.png',
'assets/images/copy.png', width: 22, height: 22),
width: 22,
height: 22
),
), ),
), ),
InkWell( InkWell(