import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:onufitness/constants/api_enum_constant.dart'; import 'package:onufitness/constants/color_constant.dart'; import 'package:onufitness/screens/chat/controllers/chat_controller.dart'; import 'package:onufitness/screens/chat/widgets/show_media_bottom_sheet.dart'; class ChatInputAreaWithVoice extends StatelessWidget { final ChatController chatCtrl; final TextEditingController textController; final String targetUserId; final bool isGroupMessage; final String targetUserName; const ChatInputAreaWithVoice({ super.key, required this.chatCtrl, required this.textController, required this.targetUserId, this.isGroupMessage = false, required this.targetUserName, }); @override Widget build(BuildContext context) { return PopScope( canPop: true, onPopInvokedWithResult: (didPop, result) { // Stop recording when navigating back if (chatCtrl.isRecording.value) { chatCtrl.cancelRecording(); } }, child: Obx(() { // Show recording interface when recording if (chatCtrl.isRecording.value) { return recordingInterface(context); } // Show normal input interface return messageInputInterface(context); }), ); } // Normal chat input interface Widget messageInputInterface(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 10.h), decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.05), offset: const Offset(0, -1), blurRadius: 3, ), ], ), child: Row( children: [ // Attachment button IconButton( icon: Icon( Icons.add_circle_outline, color: Colors.grey.shade600, size: 26.sp, ), onPressed: () => showMediaOptions( context, targetUserId, isGroup: isGroupMessage, ), ), // Text input Expanded( child: Container( decoration: BoxDecoration( color: Colors.grey.shade100, borderRadius: BorderRadius.circular(22), ), child: TextField( controller: textController, decoration: InputDecoration( hintText: "Message", hintStyle: TextStyle( color: Colors.grey.shade500, fontSize: 14.sp, ), border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 16.w, vertical: 10.h, ), ), maxLines: null, ), ), ), SizedBox(width: 8.w), // Mic or Send button ValueListenableBuilder( valueListenable: textController, builder: (context, value, child) { final hasText = value.text.trim().isNotEmpty; return GestureDetector( onTap: hasText ? _sendMessage : null, onLongPress: !hasText ? () => _startRecording() : null, child: Container( width: 40.w, height: 40.h, decoration: BoxDecoration( color: Color(primaryColor), shape: BoxShape.circle, ), child: Icon( hasText ? Icons.send_rounded : Icons.mic, color: Colors.black, size: 20.sp, ), ), ); }, ), ], ), ), // Bottom padding Container( color: Colors.white, height: MediaQuery.of(context).padding.bottom, ), ], ); } // Compact professional voice recording interface with pause button Widget recordingInterface(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h), decoration: BoxDecoration( color: Colors.white, border: Border( top: BorderSide(color: Colors.red.shade100, width: 2), ), boxShadow: [ BoxShadow( color: Colors.red.withValues(alpha: 0.08), offset: Offset(0, -2), blurRadius: 8, ), ], ), child: Row( children: [ // Animated recording indicator (only shows when not paused) Obx(() { final isPaused = chatCtrl.isRecordingPaused.value; return TweenAnimationBuilder( key: ValueKey(isPaused), tween: Tween(begin: 0.7, end: 1.0), duration: const Duration(milliseconds: 600), curve: Curves.easeInOut, onEnd: () { // This will restart via widget rebuild }, builder: (context, double value, child) { return Transform.scale( scale: isPaused ? 1.0 : value, child: Container( width: 10.w, height: 10.h, decoration: BoxDecoration( color: isPaused ? Colors.orange : Colors.red, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: (isPaused ? Colors.orange : Colors.red) .withValues(alpha: 0.4), blurRadius: 6, spreadRadius: 1, ), ], ), ), ); }, ); }), SizedBox(width: 12.w), // Recording waveform animation (only animates when not paused) Obx(() { final isPaused = chatCtrl.isRecordingPaused.value; return Row( children: List.generate(15, (index) { return Padding( padding: EdgeInsets.only(right: 3.w), child: TweenAnimationBuilder( key: ValueKey('$isPaused-$index'), tween: Tween( begin: 8.0, end: isPaused ? 8.0 : [12.0, 18.0, 14.0, 20.0, 16.0][index % 5], ), duration: Duration(milliseconds: 300 + (index * 50)), curve: Curves.easeInOut, onEnd: () {}, builder: (context, double height, child) { return Container( width: 2.5.w, height: height.h, decoration: BoxDecoration( color: isPaused ? Colors.orange.shade300 : Colors.red.shade400, borderRadius: BorderRadius.circular(2), ), ); }, ), ); }), ); }), const Spacer(), // Duration display Obx(() { final isPaused = chatCtrl.isRecordingPaused.value; return Container( padding: EdgeInsets.symmetric( horizontal: 12.w, vertical: 6.h, ), decoration: BoxDecoration( color: isPaused ? Colors.orange.shade50 : Colors.red.shade50, borderRadius: BorderRadius.circular(16), ), child: Text( chatCtrl.formatVoiceDuration( chatCtrl.recordingDuration.value, ), style: TextStyle( fontSize: 13.sp, color: isPaused ? Colors.orange.shade700 : Colors.red.shade700, fontWeight: FontWeight.w600, letterSpacing: 0.5, ), ), ); }), SizedBox(width: 12.w), // Pause/Resume button Obx(() { final isPaused = chatCtrl.isRecordingPaused.value; return GestureDetector( onTap: () => chatCtrl.togglePauseRecording(), child: Container( width: 38.w, height: 38.h, decoration: BoxDecoration( color: isPaused ? Colors.orange.shade100 : Colors.grey.shade100, shape: BoxShape.circle, ), child: Icon( isPaused ? Icons.play_arrow_rounded : Icons.pause_rounded, color: isPaused ? Colors.orange.shade700 : Colors.grey.shade700, size: 20.sp, ), ), ); }), SizedBox(width: 8.w), // Delete button GestureDetector( onTap: () => chatCtrl.cancelRecording(), child: Container( width: 38.w, height: 38.h, decoration: BoxDecoration( color: Colors.grey.shade100, shape: BoxShape.circle, ), child: Icon( Icons.delete_outline_rounded, color: Colors.grey.shade700, size: 20.sp, ), ), ), SizedBox(width: 8.w), // Send button GestureDetector( onTap: () async { chatCtrl.stopAndSendRecording( targetUserId, isGroup: isGroupMessage, ); chatCtrl.isRecordingPaused.value = false; if (isGroupMessage) { await chatCtrl.sendGroupChatNotification( notificationMessage: "Voice message", notificationTitle: "", notificationType: ApiEnum.ChatNotification, tribeId: targetUserId, ); } else { await chatCtrl.sendChatNotification( notificationMessage: "Voice message", notificationTitle: "", notificationType: ApiEnum.ChatNotification, receiverId: targetUserId, ); } }, child: Container( width: 38.w, height: 38.h, decoration: BoxDecoration( color: Colors.red, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.red.withValues(alpha: 0.3), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Icon( Icons.send_rounded, color: Colors.white, size: 18.sp, ), ), ), ], ), ), // Bottom padding Container( color: Colors.white, height: MediaQuery.of(context).padding.bottom, ), ], ); } void _sendMessage() { final text = textController.text.trim(); if (text.isNotEmpty) { chatCtrl.sendTextMessage(targetUserId, text, isGroup: isGroupMessage); textController.clear(); if (isGroupMessage) { chatCtrl.sendGroupChatNotification( notificationMessage: text, notificationTitle: "", notificationType: ApiEnum.ChatNotification, tribeId: targetUserId, ); } else { chatCtrl.sendChatNotification( notificationMessage: text, notificationTitle: "", notificationType: ApiEnum.ChatNotification, receiverId: targetUserId, ); } } } void _startRecording() { chatCtrl.startRecording(targetUserId); } }