import 'dart:async'; import 'dart:ui'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:dating_touchme_app/generated/assets.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import '../../controller/message/call_manager.dart'; import '../../controller/message/conversation_controller.dart'; import '../../model/home/marriage_data.dart'; /// 视频通话页面 class VideoCallPage extends StatefulWidget { final String targetUserId; final MarriageData? userData; final bool isInitiator; // 是否是发起方 const VideoCallPage({ super.key, required this.targetUserId, this.userData, this.isInitiator = true, }); @override State createState() => _VideoCallPageState(); } class _VideoCallPageState extends State { final CallManager _callManager = CallManager.instance; bool _isMicMuted = false; bool _isSpeakerOn = false; Duration _callDuration = Duration.zero; Timer? _durationTimer; String? _targetUserName; String? _targetAvatarUrl; // 通话是否已接通 bool _isCallConnected = false; @override void initState() { super.initState(); _initializeCall(); _loadUserInfo(); _initCallStatus(); _startDurationTimer(); // 设置系统UI样式 SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, ]); } /// 初始化通话状态 void _initCallStatus() { // 检查当前通话状态 final callSession = _callManager.currentCall.value; if (callSession != null && _callManager.callDurationSeconds.value > 0) { // 如果通话已存在且已经开始计时,说明已接通 _isCallConnected = true; _callDuration = Duration(seconds: _callManager.callDurationSeconds.value); } else { // 否则是未接通状态 _isCallConnected = false; } } /// 加载用户信息 Future _loadUserInfo() async { // 优先使用传入的 userData if (widget.userData != null) { setState(() { _targetUserName = widget.userData!.nickName.isNotEmpty ? widget.userData!.nickName : widget.targetUserId; _targetAvatarUrl = widget.userData!.profilePhoto; }); return; } // 如果没有传入 userData,尝试从 ConversationController 获取 try { if (Get.isRegistered()) { final conversationController = Get.find(); // 先从缓存中获取 final cachedUserInfo = conversationController.getCachedUserInfo(widget.targetUserId); if (cachedUserInfo != null && (cachedUserInfo.nickName != null || cachedUserInfo.avatarUrl != null)) { setState(() { _targetUserName = cachedUserInfo.nickName ?? widget.targetUserId; _targetAvatarUrl = cachedUserInfo.avatarUrl; }); return; } // 如果缓存中没有,尝试从 IM 加载 final userInfo = await conversationController.loadContact(widget.targetUserId); if (userInfo != null && (userInfo.nickName != null || userInfo.avatarUrl != null)) { setState(() { _targetUserName = userInfo.nickName ?? widget.targetUserId; _targetAvatarUrl = userInfo.avatarUrl; }); return; } } } catch (e) { print('⚠️ [VideoCallPage] 加载用户信息失败: $e'); } // 如果都获取不到,使用默认值 setState(() { _targetUserName = widget.targetUserId; _targetAvatarUrl = null; }); } @override void dispose() { _durationTimer?.cancel(); SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values); SystemChrome.setPreferredOrientations(DeviceOrientation.values); super.dispose(); } /// 初始化通话 Future _initializeCall() async { try { // TODO: 初始化RTC Engine并加入频道 // await _rtcManager.initialize(appId: 'your_app_id'); // await _rtcManager.joinChannel(token: 'token', channelId: 'channel_id', uid: uid); } catch (e) { print('初始化通话失败: $e'); } } /// 开始通话时长计时器 void _startDurationTimer() { // 监听 CallManager 的通话状态变化 _callManager.currentCall.listen((callSession) { if (mounted) { final wasConnected = _isCallConnected; // 如果通话存在且已经开始计时,说明已接通 if (callSession != null && _callManager.callDurationSeconds.value > 0) { _isCallConnected = true; if (!wasConnected) { // 刚接通,同步时长 _callDuration = Duration(seconds: _callManager.callDurationSeconds.value); } } else if (callSession == null) { _isCallConnected = false; } setState(() {}); } }); // 监听通话时长变化(已接通时更新) _callManager.callDurationSeconds.listen((seconds) { if (mounted && _isCallConnected) { setState(() { _callDuration = Duration(seconds: seconds); }); } else if (mounted && !_isCallConnected && seconds > 0) { // 如果时长开始增加,说明刚接通 setState(() { _isCallConnected = true; _callDuration = Duration(seconds: seconds); }); } }); // 如果未接通,使用本地计时器检查状态变化 if (!_isCallConnected) { _durationTimer = Timer.periodic(Duration(seconds: 1), (timer) { if (mounted) { final callSession = _callManager.currentCall.value; final duration = _callManager.callDurationSeconds.value; // 检查是否已接通(通话存在且时长大于0) if (callSession != null && duration > 0) { _isCallConnected = true; _callDuration = Duration(seconds: duration); timer.cancel(); setState(() {}); } } }); } } /// 格式化通话时长 String _formatDuration(Duration duration) { String twoDigits(int n) => n.toString().padLeft(2, '0'); final minutes = twoDigits(duration.inMinutes.remainder(60)); final seconds = twoDigits(duration.inSeconds.remainder(60)); return '$minutes:$seconds'; } /// 切换麦克风状态 void _toggleMic() { setState(() { _isMicMuted = !_isMicMuted; }); // TODO: 调用RTC Manager切换麦克风 // _rtcManager.enableAudio(!_isMicMuted); } /// 切换扬声器状态 void _toggleSpeaker() { setState(() { _isSpeakerOn = !_isSpeakerOn; }); // TODO: 调用RTC Manager切换扬声器 // _rtcManager.setEnableSpeakerphone(_isSpeakerOn); } /// 挂断通话 void _hangUp() async { try { // TODO: 离开RTC频道 // await _rtcManager.leaveChannel(); // 结束通话(传递通话时长) await _callManager.endCall(callDuration: _callDuration.inSeconds); // 返回上一页 Get.back(); } catch (e) { print('挂断通话失败: $e'); Get.back(); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, body: Stack( children: [ // 背景视频/头像(模糊) _buildBackground(), // 最小化按钮(左上角) _buildMinimizeButton(), // 用户信息 _buildUserInfo(), // 通话时长 _buildCallDuration(), // 底部控制按钮 _buildControlButtons(), ], ), ); } /// 构建最小化按钮 Widget _buildMinimizeButton() { return Positioned( top: 26.w, left: 26.w, child: GestureDetector( onTap: _minimizeCall, child: Image.asset(Assets.imagesCloseArrow, width: 20.w, height: 20.w), ), ); } /// 最小化通话 void _minimizeCall() { // TODO: 实现最小化逻辑 // 可以返回上一页,或者显示一个小窗口 Get.back(); } /// 构建背景 Widget _buildBackground() { return SizedBox( width: double.infinity, height: 1.sh, child: _targetAvatarUrl != null && _targetAvatarUrl!.isNotEmpty ? ImageFiltered( imageFilter: ImageFilter.blur(sigmaX: 15, sigmaY: 15), child: CachedNetworkImage( imageUrl: _targetAvatarUrl!, fit: BoxFit.cover, width: double.infinity, height: double.infinity, errorWidget: (context, url, error) => _buildDefaultBackground(), ), ) : _buildDefaultBackground(), ); } /// 构建默认背景 Widget _buildDefaultBackground() { return Container( color: Colors.black, ); } /// 构建用户信息 Widget _buildUserInfo() { return Positioned( top: MediaQuery.of(context).size.height * 0.15, left: 0, right: 0, child: Column( children: [ // 头像 ClipOval( child: _targetAvatarUrl != null && _targetAvatarUrl!.isNotEmpty ? CachedNetworkImage( imageUrl: _targetAvatarUrl!, width: 120.w, height: 120.w, fit: BoxFit.cover, errorWidget: (context, url, error) => Image.asset( Assets.imagesUserAvatar, width: 120.w, height: 120.w, fit: BoxFit.cover, ), ) : Image.asset( Assets.imagesUserAvatar, width: 120.w, height: 120.w, fit: BoxFit.cover, ), ), SizedBox(height: 16.h), // 用户名 Text( _targetUserName ?? widget.targetUserId, style: TextStyle( color: Colors.white, fontSize: 24.sp, fontWeight: FontWeight.w600, ), ), ], ), ); } /// 构建通话时长 Widget _buildCallDuration() { return Positioned( bottom: MediaQuery.of(context).size.height * 0.25, left: 0, right: 0, child: Center( child: Text( _isCallConnected ? _formatDuration(_callDuration) : '正在呼叫中', style: TextStyle( color: Colors.white, fontSize: 16.sp, fontWeight: FontWeight.w500, ), ), ), ); } /// 构建控制按钮 Widget _buildControlButtons() { return Positioned( bottom: 40.h, left: 0, right: 0, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ // 免提按钮 _buildControlButton( icon: Icons.volume_up, label: '免提', isActive: _isSpeakerOn, onTap: _toggleSpeaker, ), // 麦克风按钮 _buildControlButton( icon: Icons.mic, label: '麦克风', isActive: !_isMicMuted, onTap: _toggleMic, ), // 挂断按钮 _buildControlButton( icon: Icons.call_end, label: '挂断', isActive: true, onTap: _hangUp, isHangUp: true, ), ], ), ); } /// 构建控制按钮 Widget _buildControlButton({ required IconData icon, required String label, required bool isActive, required VoidCallback onTap, bool isHangUp = false, }) { return GestureDetector( onTap: onTap, child: Column( children: [ Container( width: 56.w, height: 56.w, decoration: BoxDecoration( color: isHangUp ? Color(0xFFFF3B30) : (isActive ? Colors.white.withOpacity(0.3) : Colors.white.withOpacity(0.2)), shape: BoxShape.circle, ), child: Icon( icon, color: Colors.white, size: 28.w, ), ), SizedBox(height: 8.h), Text( label, style: TextStyle( color: Colors.white, fontSize: 12.sp, ), ), ], ), ); } }