import 'package:awesome_snackbar_content/awesome_snackbar_content.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:onufitness/constants/asset_constants.dart'; import 'package:onufitness/constants/color_constant.dart'; import 'package:onufitness/constants/text_constant.dart'; import 'package:onufitness/routes/route_constant.dart'; import 'package:onufitness/screens/chat/controllers/chat_controller.dart'; import 'package:onufitness/services/agora/call_services.dart'; import 'package:onufitness/widgets/others/new_custom_sneakbar.dart'; Widget chatAppBar({ required BuildContext context, required ChatController chatCtrl, required String userId, required String receiverName, String? targetUserAvatarUrl, bool showOnlineDot = false, bool isGroupChat = false, }) { final agoraCallService = AgoraCallService.instance; // Function to check if call can be made.............................................................................. void checkAndMakeCall(CallType callType) { if (agoraCallService.callState.value != CallState.idle) { AwesomeCustomSnackbar.show( context: context, title: 'Call In Progress', message: 'You are already in a call. Please end the current call first.', contentType: ContentType.warning, ); return; } if (receiverName.isEmpty && userId.isEmpty) { AwesomeCustomSnackbar.show( context: context, title: 'Invalid User', message: 'Cannot initiate call. User information is not available.', contentType: ContentType.warning, ); return; } try { agoraCallService.makeCall( context: context, targetUserId: userId, targatedUserName: receiverName, targatedUserProfilePic: targetUserAvatarUrl, callType: callType, ); } catch (e) { AwesomeCustomSnackbar.show( context: context, title: 'Call Failed', message: 'Unable to initiate call. Please try again later.', contentType: ContentType.warning, ); } } return Column( children: [ // Call Indicator - Above the AppBar Obx(() { if (agoraCallService.callState.value == CallState.connected || agoraCallService.callState.value == CallState.calling || agoraCallService.callState.value == CallState.ringing) { return Container( width: double.infinity, decoration: BoxDecoration( gradient: LinearGradient( colors: _getCallGradientColors( agoraCallService.callState.value, ), begin: Alignment.centerLeft, end: Alignment.centerRight, ), boxShadow: [ BoxShadow( color: _getCallStatusColor( agoraCallService.callState.value, ).withValues(alpha: 0.3), blurRadius: 8, offset: Offset(0, 2), ), ], ), child: Material( color: Colors.transparent, child: InkWell( onTap: () => _navigateToCallScreen(agoraCallService), child: Padding( padding: EdgeInsets.symmetric( horizontal: 15.w, vertical: 12.h, ), child: Row( children: [ // Call Icon Container( padding: EdgeInsets.all(6.sp), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.2), shape: BoxShape.circle, ), child: Icon( agoraCallService.currentCallType.value == CallType.video ? Icons.videocam : Icons.call, color: Colors.white, size: 15.sp, ), ), SizedBox(width: 12.w), // Call Status and Details Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( _getCallStatusText(agoraCallService), style: TextStyle( color: Colors.white, fontSize: smallSizeText, fontWeight: FontWeight.w600, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), if (agoraCallService.callState.value == CallState.connected) Obx( () => Text( _formatDuration( agoraCallService.callDuration.value, ), style: TextStyle( color: Colors.white.withValues(alpha: 0.9), fontSize: verySmallSizeText, fontWeight: FontWeight.w400, ), ), ), ], ), ), // Action Buttons Row( mainAxisSize: MainAxisSize.min, children: [ // Return to Call Button _buildActionButton( icon: Icons.open_in_full, onTap: () => _navigateToCallScreen(agoraCallService), tooltip: 'Return to call', ), SizedBox(width: 8), // End Call Button (only show for connected calls) if (agoraCallService.callState.value == CallState.connected) _buildActionButton( icon: Icons.call_end, onTap: () => agoraCallService.endCall(), tooltip: 'End call', isDestructive: true, ), ], ), ], ), ), ), ), ); } return SizedBox.shrink(); }), // Main AppBar content Container( padding: EdgeInsets.only(top: 15.h, bottom: 10.h), decoration: BoxDecoration( color: Color(primaryColor), image: DecorationImage( image: AssetImage(AssetConstants.chatAppBarBackgroundImage), fit: BoxFit.cover, opacity: 0.5, ), ), child: Row( children: [ IconButton( icon: Icon(Icons.arrow_back_ios, color: Colors.black), onPressed: () async { Get.back(); chatCtrl.selectedUserId.value = ""; await chatCtrl.markAllMessagesAsRead(userId); await chatCtrl.unsuscribePresence(userId); }, ), // User Avatar with Online Indicator Stack( children: [ CircleAvatar( radius: 20.r, backgroundColor: Colors.grey.shade300, backgroundImage: (targetUserAvatarUrl != null && targetUserAvatarUrl.isNotEmpty) ? NetworkImage(targetUserAvatarUrl) : null, child: (targetUserAvatarUrl == null || targetUserAvatarUrl.isEmpty) ? Text( receiverName.isNotEmpty ? receiverName[0].toUpperCase() : 'U', style: const TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.w600, ), ) : null, ), // if (showOnlineDot && !isGroupChat) // Positioned( // right: 2, // bottom: 2, // child: Container( // width: 12, // height: 12, // decoration: BoxDecoration( // color: Colors.green, // shape: BoxShape.circle, // border: Border.all(color: Colors.white, width: 2), // ), // ), // ), ], ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( receiverName.isNotEmpty ? receiverName : "Unknown User", style: TextStyle( color: Colors.black, fontWeight: FontWeight.w600, fontSize: smallSizeText, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), if (!isGroupChat) Text( showOnlineDot ? "Online" : "Last seen recently", style: TextStyle( fontSize: verySmallSizeText, color: showOnlineDot ? Colors.green : Colors.grey, fontWeight: FontWeight.w400, ), ), ], ), ), // Action Buttons Obx(() { bool isCallActive = agoraCallService.callState.value != CallState.idle; return Padding( padding: EdgeInsets.only(right: 15.sp), child: Row( children: [ if (!isGroupChat && chatCtrl.isMyFriend.value) AppBarAction( icon: Icons.call, onPressed: () => checkAndMakeCall(CallType.voice), isEnabled: showOnlineDot && !isCallActive, ), if (!isGroupChat && chatCtrl.isMyFriend.value) AppBarAction( icon: Icons.videocam, onPressed: () => checkAndMakeCall(CallType.video), isEnabled: showOnlineDot && !isCallActive, ), ], ), ); }), ], ), ), ], ); } // Helper function to navigate to appropriate call screen void _navigateToCallScreen(AgoraCallService agoraCallService) { final callState = agoraCallService.callState.value; if (callState == CallState.connected) { Get.toNamed(RouteConstant.activeCallScreen); } else if (callState == CallState.calling) { Get.toNamed(RouteConstant.outgoingCallScreen); } else if (callState == CallState.ringing) { Get.toNamed(RouteConstant.incomingCallScreen); } } // Helper function to get call gradient colors List _getCallGradientColors(CallState callState) { switch (callState) { case CallState.connected: return [Color(0xFF4CAF50), Color(0xFF66BB6A)]; case CallState.calling: return [Color(0xFFFF9800), Color(0xFFFFB74D)]; case CallState.ringing: return [Color(0xFF2196F3), Color(0xFF64B5F6)]; default: return [Colors.grey, Colors.grey.shade400]; } } // Helper function to get call status color Color _getCallStatusColor(CallState callState) { switch (callState) { case CallState.connected: return Color(0xFF4CAF50); case CallState.calling: return Color(0xFFFF9800); case CallState.ringing: return Color(0xFF2196F3); default: return Colors.grey; } } // Helper function to build action buttons Widget _buildActionButton({ required IconData icon, required VoidCallback onTap, required String tooltip, bool isDestructive = false, }) { return Tooltip( message: tooltip, child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(20), child: Container( padding: EdgeInsets.all(8), decoration: BoxDecoration( color: isDestructive ? Colors.red.withValues(alpha: 0.2) : Colors.white.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(20), ), child: Icon( icon, color: isDestructive ? Colors.red.shade100 : Colors.white, size: 15.sp, ), ), ), ); } // Helper function to get call status text String _getCallStatusText(AgoraCallService agoraCallService) { switch (agoraCallService.callState.value) { case CallState.calling: return 'Calling ${agoraCallService.callerName.value}...'; case CallState.ringing: return 'Incoming call from ${agoraCallService.callerName.value}'; case CallState.connected: return 'On call with ${agoraCallService.callerName.value}'; default: return ''; } } // Helper function to format call duration String _formatDuration(int seconds) { int hours = seconds ~/ 3600; int minutes = (seconds % 3600) ~/ 60; int remainingSeconds = seconds % 60; if (hours > 0) { return '${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${remainingSeconds.toString().padLeft(2, '0')}'; } return '${minutes.toString().padLeft(2, '0')}:${remainingSeconds.toString().padLeft(2, '0')}'; } // App Bar Action Widget class AppBarAction extends StatelessWidget { final IconData icon; final VoidCallback onPressed; final bool isEnabled; const AppBarAction({ super.key, required this.icon, required this.onPressed, this.isEnabled = true, }); @override Widget build(BuildContext context) { return IconButton( // icon: Icon(icon, color: isEnabled ? Colors.black : Colors.grey.shade500), icon: Icon(icon, color: Colors.black), onPressed: onPressed, ); } } //............................................................................................................................