import 'dart:ui'; import 'package:flutter/material.dart'; class ChatScreen extends StatefulWidget { const ChatScreen({super.key}); @override State createState() => _ChatScreenState(); } class ChatMessage { final String text; final bool isAssistant; ChatMessage({required this.text, this.isAssistant = false}); } class _ChatScreenState extends State with TickerProviderStateMixin { final List _messages = []; final TextEditingController _textController = TextEditingController(); final ScrollController _scrollController = ScrollController(); bool _isTyping = false; void _handleSubmitted(String text) { if (text.trim().isEmpty) return; _textController.clear(); setState(() { _messages.insert(0, ChatMessage(text: text)); _isTyping = true; }); // Simulate EPVChat! typing delay Future.delayed(const Duration(milliseconds: 1500), () { if (mounted) { setState(() { _isTyping = false; _messages.insert(0, ChatMessage( text: "This is a simulated modern response to: \"$text\"", isAssistant: true, )); }); } }); } Widget _buildMessage(ChatMessage message) { bool isAssistant = message.isAssistant; return Padding( padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0), child: Row( mainAxisAlignment: isAssistant ? MainAxisAlignment.start : MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end, children: [ if (isAssistant) Container( margin: const EdgeInsets.only(right: 12), decoration: BoxDecoration( shape: BoxShape.circle, gradient: const LinearGradient( colors: [Color(0xFF8ad5c9), Color(0xFF57a7ed)], // Mint & Blue begin: Alignment.topLeft, end: Alignment.bottomRight, ), boxShadow: [ BoxShadow( color: const Color(0xFF8ad5c9).withOpacity(0.4), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: const CircleAvatar( backgroundColor: Colors.transparent, radius: 16, child: Icon(Icons.auto_awesome, color: Colors.white, size: 18), ), ), Flexible( child: Container( padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 14.0), decoration: BoxDecoration( gradient: isAssistant ? const LinearGradient( colors: [Color(0xFFF1F5F9), Color(0xFFE2E8F0)], // Light bubbles begin: Alignment.topLeft, end: Alignment.bottomRight, ) : const LinearGradient( colors: [Color(0xFF8ad5c9), Color(0xFF57a7ed)], // Mint & Blue bubbles begin: Alignment.centerLeft, end: Alignment.centerRight, ), borderRadius: BorderRadius.only( topLeft: const Radius.circular(20), topRight: const Radius.circular(20), bottomLeft: Radius.circular(isAssistant ? 4 : 20), bottomRight: Radius.circular(isAssistant ? 20 : 4), ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 10, offset: const Offset(0, 4), ), ], border: Border.all( color: isAssistant ? Colors.black.withOpacity(0.05) : Colors.transparent, width: 1, ) ), child: Text( message.text, style: TextStyle( color: isAssistant ? Colors.black87 : Colors.white, fontSize: 15, height: 1.4, ), ), ), ), if (!isAssistant) Container( margin: const EdgeInsets.only(left: 12), decoration: BoxDecoration( shape: BoxShape.circle, gradient: const LinearGradient( colors: [Color(0xFF57a7ed), Color(0xFF3A8BD1)], // User avatar gradient begin: Alignment.topLeft, end: Alignment.bottomRight, ), boxShadow: [ BoxShadow( color: const Color(0xFF57a7ed).withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: const CircleAvatar( backgroundColor: Colors.transparent, radius: 16, child: Icon(Icons.person, color: Colors.white, size: 18), ), ), ], ), ); } Widget _buildTypingIndicator() { return Padding( padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Container( margin: const EdgeInsets.only(right: 12), decoration: const BoxDecoration( shape: BoxShape.circle, gradient: LinearGradient( colors: [Color(0xFF8ad5c9), Color(0xFF57a7ed)], // Mint & Blue begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), child: const CircleAvatar( backgroundColor: Colors.transparent, radius: 16, child: Icon(Icons.auto_awesome, color: Colors.white, size: 18), ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0), decoration: BoxDecoration( color: const Color(0xFFF1F5F9), // Typing bubble matching assistant light bubble borderRadius: const BorderRadius.only( topLeft: Radius.circular(20), topRight: Radius.circular(20), bottomLeft: Radius.circular(4), bottomRight: Radius.circular(20), ), border: Border.all(color: Colors.black.withOpacity(0.05)), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ _buildDot(0), const SizedBox(width: 4), _buildDot(1), const SizedBox(width: 4), _buildDot(2), ], ), ), ], ), ); } Widget _buildDot(int index) { return TweenAnimationBuilder( tween: Tween(begin: 0, end: 1), duration: const Duration(milliseconds: 600), builder: (context, double value, child) { return Opacity( opacity: (value + (index * 0.3)) % 1.0, child: Container( width: 6, height: 6, decoration: const BoxDecoration( color: Colors.black54, shape: BoxShape.circle, ), ), ); }, ); } Widget _buildTextComposer() { return ClipRRect( child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), child: Container( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0), decoration: BoxDecoration( color: Colors.white.withOpacity(0.8), // Light backdrop border: Border( top: BorderSide( color: Colors.black.withOpacity(0.05), width: 0.5, ), ), ), child: SafeArea( child: Row( children: [ Expanded( child: Container( decoration: BoxDecoration( color: const Color(0xFFF1F5F9), // Light input box background borderRadius: BorderRadius.circular(30.0), border: Border.all(color: Colors.black.withOpacity(0.05)), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: TextField( controller: _textController, onSubmitted: _handleSubmitted, style: const TextStyle(color: Colors.black87), decoration: InputDecoration( hintText: "Message EPVChat!...", hintStyle: TextStyle(color: Colors.black.withOpacity(0.4)), border: InputBorder.none, contentPadding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 14.0), ), ), ), ), const SizedBox(width: 12), Container( decoration: BoxDecoration( gradient: const LinearGradient( colors: [Color(0xFF8ad5c9), Color(0xFF57a7ed)], // Mint & Blue send button begin: Alignment.topLeft, end: Alignment.bottomRight, ), shape: BoxShape.circle, boxShadow: [ BoxShadow( color: const Color(0xFF8ad5c9).withOpacity(0.4), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: IconButton( icon: const Icon(Icons.send_rounded, color: Colors.white, size: 20), onPressed: () => _handleSubmitted(_textController.text), ), ), ], ), ), ), ), ); } @override Widget build(BuildContext context) { return Scaffold( extendBodyBehindAppBar: true, appBar: PreferredSize( preferredSize: const Size.fromHeight(kToolbarHeight), child: ClipRRect( child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), child: AppBar( title: ShaderMask( shaderCallback: (bounds) => const LinearGradient( colors: [Color(0xFF8ad5c9), Color(0xFF57a7ed)], // Text gradient header begin: Alignment.topLeft, end: Alignment.bottomRight, ).createShader(bounds), child: const Text( 'EPVChat!', style: TextStyle( fontWeight: FontWeight.w800, fontSize: 22, letterSpacing: -0.5, ), ), ), backgroundColor: Colors.white.withOpacity(0.7), // Light Header backgrop elevation: 0, centerTitle: true, bottom: PreferredSize( preferredSize: const Size.fromHeight(1.0), child: Container( color: Colors.black.withOpacity(0.05), height: 1.0, ), ), ), ), ), ), body: Container( decoration: const BoxDecoration( gradient: RadialGradient( center: Alignment.topCenter, radius: 1.5, colors: [ Colors.white, Color(0xFFF8FAFC), // Slate 50 ], ) ), child: SafeArea( bottom: false, child: Column( children: [ Expanded( child: ListView.builder( controller: _scrollController, padding: const EdgeInsets.symmetric(vertical: 20.0), reverse: true, itemCount: _messages.length + (_isTyping ? 1 : 0), itemBuilder: (_, int index) { if (_isTyping && index == 0) { return _buildTypingIndicator(); } int messageIndex = _isTyping ? index - 1 : index; return _buildMessage(_messages[messageIndex]); }, ), ), _buildTextComposer(), ], ), ), ), ); } }