import 'package:flutter/material.dart'; import 'dart:ui'; import '../../widgets/chat_box.dart'; import 'package:provider/provider.dart'; import '../../services/message_service.dart'; import '../../widgets/gradient_background.dart'; import '../../utils/assets_util.dart'; import '../../pages/full_screen.dart'; class ChatWindowContent extends StatefulWidget { final AnimationController? animationController; final double? minHeight; final double? maxHeight; final double? chatWidth; final VoidCallback? onCloseWindow; const ChatWindowContent({ super.key, this.onCloseWindow, this.animationController, this.minHeight, this.maxHeight, this.chatWidth, }); @override State createState() => _ChatWindowContentState(); } class _ChatWindowContentState extends State { final ScrollController _scrollController = ScrollController(); int _lastMessageCount = 0; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { final messageService = Provider.of(context, listen: false); messageService.removeNonListeningMessages(); }); } @override void dispose() { _scrollController.dispose(); super.dispose(); } void _scrollToBottom() { if (_scrollController.hasClients) { _scrollController.animateTo( 0.0, duration: const Duration(milliseconds: 200), curve: Curves.easeOut, ); } } void _openFullScreen() async { if (widget.onCloseWindow != null) { widget.onCloseWindow!(); } final messageService = context.read(); Navigator.of(context).push( MaterialPageRoute( builder: (context) => ChangeNotifierProvider.value( value: messageService, // 传递同一个单例实例 child: const FullScreenPage(), ), ), ); } @override Widget build(BuildContext context) { final minHeight = widget.minHeight ?? 0; final maxHeight = widget.maxHeight ?? double.infinity; final chatWidth = widget.chatWidth ?? double.infinity; final animationController = widget.animationController; return Consumer( builder: (context, messageService, child) { final messageCount = messageService.messages.length; if (messageCount > _lastMessageCount) { WidgetsBinding.instance.addPostFrameCallback((_) { _scrollToBottom(); }); } _lastMessageCount = messageCount; var chatContent = _buildChatContent(messageService); // 包裹弹窗动画 if (animationController != null) { Widget content = FadeTransition( opacity: animationController, child: SlideTransition( position: Tween( begin: const Offset(0, 0.3), end: Offset.zero, ).animate(CurvedAnimation( parent: animationController, curve: Curves.easeOutQuart, )), child: TweenAnimationBuilder( tween: Tween(begin: 0.8, end: 1.0), duration: const Duration(milliseconds: 200), curve: Curves.easeOutBack, builder: (context, scale, child) { return Transform.scale( scale: scale, child: Container( width: chatWidth, constraints: BoxConstraints( minHeight: minHeight, maxHeight: maxHeight, ), child: child, ), ); }, child: chatContent, ), ), ); } Widget content = Container( width: chatWidth, constraints: BoxConstraints( minHeight: minHeight, maxHeight: maxHeight, ), child: chatContent, ); return content; }, ); } Widget _buildChatContent(MessageService messageService) { Widget content = ClipRRect( borderRadius: BorderRadius.circular(24), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 12, sigmaY: 12), child: GradientBackground( colors: const [ Color(0XBF3B0A3F), Color(0xBF0E0E24), Color(0xBF0C0B33), ], borderRadius: BorderRadius.circular(6), child: Stack( children: [ Padding( padding: const EdgeInsets.only(top: 50, left: 6, right: 6, bottom: 30), child: LayoutBuilder( builder: (context, boxConstraints) { return ChatBox( scrollController: _scrollController, messages: messageService.messages, ); }, ), ), Positioned( top: 6, right: 6, child: IconButton( icon: AssetsUtil.getImageWidget( 'open_in_full.png', width: 24, height: 24, ), onPressed: _openFullScreen, padding: EdgeInsets.zero, ), ), ], ), ), ), ); return content; } }