import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import '../chat_provider.dart'; import '../model/call_session.dart'; import 'audio_call_page.dart'; import 'video_call_page.dart'; /// Native-style full-screen incoming call dialog matching audio call page design class IncomingCallDialog extends StatefulWidget { final CallSession call; const IncomingCallDialog({ Key? key, required this.call, }) : super(key: key); static void show(BuildContext context, CallSession call) { Navigator.of(context).push( MaterialPageRoute( fullscreenDialog: true, builder: (context) => IncomingCallDialog(call: call), ), ); } @override State createState() => _IncomingCallDialogState(); } class _IncomingCallDialogState extends State { @override void initState() { super.initState(); // Listen for call status changes WidgetsBinding.instance.addPostFrameCallback((_) { final chatProvider = context.read(); chatProvider.addListener(_checkCallStatus); }); } void _checkCallStatus() { if (!mounted) return; // Early exit if widget is unmounted final chatProvider = context.read(); // If call status is idle (call cancelled/ended), automatically dismiss dialog if (chatProvider.callStatus == CallStatus.idle) { // Remove listener before popping chatProvider.removeListener(_checkCallStatus); Navigator.of(context).pop(); } } @override void dispose() { // Clean up listener try { context.read().removeListener(_checkCallStatus); } catch (e) { // Provider might already be disposed } super.dispose(); } @override Widget build(BuildContext context) { final chatProvider = context.read(); return PopScope( canPop: false, // Prevent dismissing by back button child: Scaffold( backgroundColor: AppColor.backgroundTabBarDark, body: Column( children: [ const Spacer(flex: 2), _buildContactInfo(context, widget.call), 8.height, _buildIncomingCallStatus(context), const Spacer(flex: 4), _buildActions(context, chatProvider, widget.call), 32.height, ], ), ), ); } Widget _buildContactInfo(BuildContext context, CallSession session) { return Column( children: [ Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( shape: BoxShape.circle, color: AppColor.whiteF8d, border: Border.all(color: AppColor.white10.withOpacity(0.2), width: 1), ), child: ClipOval( child: session.peerAvatar != null ? CachedNetworkImage( imageUrl: session.peerAvatar!, fit: BoxFit.cover, placeholder: (context, url) => Center( child: CircularProgressIndicator( color: Colors.white.withOpacity(0.5), ), ), errorWidget: (context, url, error) => 'call_user_avatar'.toSvgAsset(height: 48, width: 48), ) : 'call_user_avatar'.toSvgAsset(height: 48, width: 48), ), ), 24.height, Text( session.peerName, style: AppTextStyles.heading2.copyWith( color: Colors.white, fontWeight: FontWeight.w600, ), textAlign: TextAlign.center, ), ], ); } Widget _buildIncomingCallStatus(BuildContext context) { return Column( children: [ Text( widget.call.type == CallType.video ? 'Atoms Video Call' : 'Atoms Audio Call', style: AppTextStyles.heading5.copyWith( color: AppColor.neutral100, fontWeight: FontWeight.w400, ), ), 8.height, Text( 'Incoming call...', style: AppTextStyles.heading5.copyWith( color: AppColor.neutral100, fontWeight: FontWeight.w400, ), ), ], ); } Widget _buildActions(BuildContext context, ChatProvider chatProvider, CallSession session) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ // Decline button _buildActionButton( icon: 'end_call', label: 'Decline', onPressed: () async { Navigator.of(context).pop(); await chatProvider.declineCall('declined'); }, ), // Accept button _buildActionButton( icon: 'calling_icon', label: 'Accept', onPressed: () async { // Just dismiss the dialog - acceptCall() will handle navigation Navigator.of(context).pop(); await chatProvider.acceptCall(); }, ), ], ); } Widget _buildActionButton({ required String icon, required String label, required VoidCallback onPressed, }) { return Column( children: [ Container( padding: const EdgeInsets.all(18), decoration: BoxDecoration( color: icon == 'end_call' ? AppColor.red30 : Colors.green, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 4), ), ], ), alignment: Alignment.center, child: icon.toSvgAsset(height: 32, width: 32, color: AppColor.white10), ).onPress(onPressed), 8.height, Text( label, style: AppTextStyles.heading5.copyWith( color: AppColor.neutral100, fontWeight: FontWeight.w400, ), ), ], ); } }