import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../constant/colors.dart'; import '../../constant/style.dart'; import '../../controller/voice_call_controller.dart'; class VoiceCallBottomSheet extends StatelessWidget { const VoiceCallBottomSheet({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final controller = Get.find(); final double screenHeight = MediaQuery.of(context).size.height; final bool isDark = Theme.of(context).brightness == Brightness.dark; // Harmonious curated colors final Color bgColor = isDark ? const Color(0xFF121212) : Colors.white; final Color cardColor = isDark ? const Color(0xFF1E1E1E) : const Color(0xFFF5F5F7); final Color textColor = isDark ? Colors.white : const Color(0xFF1C1C1E); final Color subTextColor = isDark ? Colors.white70 : Colors.black54; return WillPopScope( onWillPop: () async => false, child: Container( height: screenHeight * 0.9, decoration: BoxDecoration( color: bgColor, borderRadius: const BorderRadius.vertical(top: Radius.circular(32)), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 20, offset: const Offset(0, -5), ) ], ), child: Obx(() { final state = controller.state.value; final seconds = controller.elapsedSeconds.value; final remoteName = controller.remoteName.value; final isMuted = controller.isMuted.value; final isSpeakerOn = controller.isSpeakerOn.value; final errorMsg = controller.errorMessage.value; // Progress ring logic final double progress = seconds / 60.0; final Color ringColor = (errorMsg.isNotEmpty || seconds <= 10) ? const Color(0xFFE74C3C) : const Color(0xFF2ECC71); // Status text translations String statusText = ""; if (errorMsg.isNotEmpty) { statusText = errorMsg; } else { switch (state) { case VoiceCallState.dialing: statusText = "${'Calling'.tr} $remoteName..."; break; case VoiceCallState.ringing: statusText = "${'Incoming Call...'.tr}"; break; case VoiceCallState.connecting: statusText = "Connecting...".tr; break; case VoiceCallState.active: statusText = "Call Connected".tr; break; case VoiceCallState.ended: statusText = "Call Ended".tr; break; case VoiceCallState.idle: statusText = ""; break; } } return Column( children: [ // Top Drag Handle Indicator Center( child: Container( margin: const EdgeInsets.only(top: 12, bottom: 24), width: 44, height: 5, decoration: BoxDecoration( color: isDark ? Colors.white24 : Colors.black12, borderRadius: BorderRadius.circular(10), ), ), ), Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ // Header Info Column( children: [ Text( "Free Call".tr, style: TextStyle( color: ringColor, fontWeight: FontWeight.w800, fontSize: 14, letterSpacing: 1.2, ), ), const SizedBox(height: 8), Text( remoteName, style: TextStyle( color: textColor, fontWeight: FontWeight.w900, fontSize: 26, ), textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( statusText, style: TextStyle( color: errorMsg.isNotEmpty ? const Color(0xFFE74C3C) : subTextColor, fontWeight: FontWeight.w600, fontSize: 16, ), textAlign: TextAlign.center, ), ], ), // Avatar & Animated Progress Ring Stack( alignment: Alignment.center, children: [ // Progress ring around avatar (Active state only) if (state == VoiceCallState.active) SizedBox( width: 172, height: 172, child: CircularProgressIndicator( value: progress, strokeWidth: 5, backgroundColor: isDark ? Colors.white10 : Colors.black12, valueColor: AlwaysStoppedAnimation(ringColor), ), ), // Main Avatar Card Container( width: 150, height: 150, decoration: BoxDecoration( shape: BoxShape.circle, color: cardColor, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), blurRadius: 15, offset: const Offset(0, 8), ) ], ), child: Center( child: remoteName.isNotEmpty ? Text( remoteName[0].toUpperCase(), style: TextStyle( color: textColor, fontWeight: FontWeight.bold, fontSize: 54, ), ) : Icon( Icons.person, color: textColor.withOpacity(0.6), size: 64, ), ), ), ], ), // Timer Counter Display if (state == VoiceCallState.active) Text( "0:${seconds.toString().padLeft(2, '0')}", style: TextStyle( color: seconds > 10 ? textColor : const Color(0xFFE74C3C), fontWeight: FontWeight.bold, fontSize: 22, fontFamily: 'monospace', ), ) else const SizedBox(height: 24), // Action Controls Block if (state == VoiceCallState.ringing) // Incoming Ringing Controls: Accept / Decline Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildCircleActionButton( icon: Icons.call_end_rounded, color: Colors.white, bgColor: const Color(0xFFE74C3C), onTap: () => controller.declineCall(), label: "Decline".tr, ), _buildCircleActionButton( icon: Icons.call_rounded, color: Colors.white, bgColor: const Color(0xFF2ECC71), onTap: () => controller.acceptCall(), label: "Accept".tr, ), ], ) else // Dialing or Connected Controls: Speaker / Mute / Hangup Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ // Speakerphone toggle _buildCircleActionButton( icon: isSpeakerOn ? Icons.volume_up_rounded : Icons.volume_down_rounded, color: isSpeakerOn ? Colors.white : textColor, bgColor: isSpeakerOn ? const Color(0xFF2ECC71) : cardColor, onTap: () => controller.toggleSpeaker(), label: "Speaker".tr, ), // Hangup Call _buildCircleActionButton( icon: Icons.call_end_rounded, color: Colors.white, bgColor: const Color(0xFFE74C3C), onTap: () => controller.hangup(), label: "End".tr, ), // Mute Microphone _buildCircleActionButton( icon: isMuted ? Icons.mic_off_rounded : Icons.mic_rounded, color: isMuted ? Colors.white : textColor, bgColor: isMuted ? const Color(0xFFE74C3C) : cardColor, onTap: () => controller.toggleMute(), label: "Mute".tr, ), ], ), ], ), ), ), ], ); }), ), ); } Widget _buildCircleActionButton({ required IconData icon, required Color color, required Color bgColor, required VoidCallback onTap, required String label, }) { return Column( mainAxisSize: MainAxisSize.min, children: [ ElevatedButton( onPressed: onTap, style: ElevatedButton.styleFrom( shape: const CircleBorder(), padding: const EdgeInsets.all(18), backgroundColor: bgColor, foregroundColor: color, elevation: 2, ), child: Icon(icon, size: 28), ), const SizedBox(height: 8), Text( label, style: const TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.grey, ), ), ], ); } }