import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:lucide_icons/lucide_icons.dart'; import 'package:go_router/go_router.dart'; import '../../models/character.dart'; import '../../models/message.dart'; import '../../data/mock_data.dart'; import 'voice_mode_overlay.dart'; class InteractionScreen extends StatefulWidget { final String characterId; const InteractionScreen({super.key, required this.characterId}); @override State createState() => _InteractionScreenState(); } class _InteractionScreenState extends State { late Character _character; final List _messages = List.from(mockMessages); final TextEditingController _controller = TextEditingController(); bool _isVoiceMode = false; @override void initState() { super.initState(); _character = mockCharacters.firstWhere( (c) => c.id == widget.characterId, orElse: () => mockCharacters.first, ); } void _sendMessage() { if (_controller.text.trim().isEmpty) return; final newUserMsg = Message( id: DateTime.now().toString(), text: _controller.text, sender: MessageSender.user, type: MessageType.text, timestamp: DateTime.now() ); setState(() { _messages.add(newUserMsg); _controller.clear(); }); // Mock AI Reply Future.delayed(const Duration(seconds: 2), () { if (!mounted) return; final newAiMsg = Message( id: DateTime.now().toString(), text: '我收到了你的信号: "${newUserMsg.text}"。这让我感觉很好...', sender: MessageSender.ai, type: MessageType.text, timestamp: DateTime.now() ); setState(() { _messages.add(newAiMsg); }); }); } @override Widget build(BuildContext context) { return Stack( children: [ Scaffold( extendBodyBehindAppBar: true, appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, flexibleSpace: ClipRRect( child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), child: Container(color: Colors.black.withOpacity(0.5)), ), ), leading: IconButton( icon: const Icon(LucideIcons.arrowLeft, color: Colors.white), onPressed: () => context.pop(), ), title: Row( children: [ CircleAvatar( backgroundImage: NetworkImage(_character.avatar), radius: 16, ), const SizedBox(width: 10), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(_character.name, style: const TextStyle(fontSize: 16, color: Colors.white)), Row( children: [ Container(width: 6, height: 6, decoration: const BoxDecoration(color: Color(0xFF10B981), shape: BoxShape.circle)), const SizedBox(width: 4), Text('Online', style: TextStyle(fontSize: 10, color: Colors.white.withOpacity(0.7))), ], ) ], ) ], ), actions: [ IconButton(icon: const Icon(LucideIcons.moreVertical, color: Colors.white), onPressed: () {}), ], ), body: Container( decoration: const BoxDecoration( color: Color(0xFF2E1065), gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Color(0xFF2E1065), Color(0xFF0F172A)], ) ), child: Column( children: [ Expanded( child: ListView.separated( padding: const EdgeInsets.only(top: 120, bottom: 20, left: 16, right: 16), itemCount: _messages.length, separatorBuilder: (_, __) => const SizedBox(height: 16), itemBuilder: (context, index) { final msg = _messages[index]; final isMe = msg.sender == MessageSender.user; return Align( alignment: isMe ? Alignment.centerRight : Alignment.centerLeft, child: Container( constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.75), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: isMe ? const Color(0xFFA855F7) : Colors.white.withOpacity(0.1), borderRadius: BorderRadius.only( topLeft: const Radius.circular(16), topRight: const Radius.circular(16), bottomLeft: isMe ? const Radius.circular(16) : const Radius.circular(2), bottomRight: isMe ? const Radius.circular(2) : const Radius.circular(16), ), border: Border.all(color: Colors.white.withOpacity(0.1)), ), child: Text( msg.text, style: const TextStyle(color: Colors.white, fontSize: 14, height: 1.4), ), ), ); }, ), ), // Input Area ClipRRect( child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20), child: Container( padding: EdgeInsets.only( bottom: MediaQuery.of(context).padding.bottom + 10, top: 10, left: 16, right: 16 ), color: Colors.black.withOpacity(0.4), child: Row( children: [ GestureDetector( onTap: () => setState(() => _isVoiceMode = true), child: Container( width: 44, height: 44, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withOpacity(0.1), border: Border.all(color: Colors.white.withOpacity(0.1)) ), child: const Icon(LucideIcons.phone, color: Colors.white, size: 20), ), ), const SizedBox(width: 8), Expanded( child: TextField( controller: _controller, style: const TextStyle(color: Colors.white), decoration: InputDecoration( filled: true, fillColor: Colors.white.withOpacity(0.05), hintText: 'Type a message...', hintStyle: TextStyle(color: Colors.white.withOpacity(0.3)), border: OutlineInputBorder( borderRadius: BorderRadius.circular(24), borderSide: BorderSide.none, ), contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), ), ), ), const SizedBox(width: 8), GestureDetector( onTap: _sendMessage, child: Container( width: 44, height: 44, decoration: const BoxDecoration( shape: BoxShape.circle, gradient: LinearGradient(colors: [Color(0xFFA855F7), Color(0xFFEC4899)]) ), child: const Icon(LucideIcons.send, color: Colors.white, size: 20), ), ) ], ), ), ), ) ], ), // Column ), // Container ), // Scaffold if (_isVoiceMode) VoiceModeOverlay( character: _character, onClose: () => setState(() => _isVoiceMode = false), ), ], ); } }