import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:star_lock/main/lockDetail/realTimePicture/realTimePicture_state.dart'; import 'package:star_lock/talk/call/callTalk.dart'; import '../../../../app_settings/app_colors.dart'; import '../../../../tools/showTFView.dart'; import '../../../app_settings/app_settings.dart'; import 'realTimePicture_logic.dart'; class RealTimePicturePage extends StatefulWidget { const RealTimePicturePage({Key? key}) : super(key: key); @override State createState() => _RealTimePicturePageState(); } class _RealTimePicturePageState extends State with TickerProviderStateMixin { final RealTimePictureLogic logic = Get.put(RealTimePictureLogic()); final RealTimePictureState state = Get.find().state; @override void initState() { super.initState(); //写一个定时器,三十秒后页面自动返回 state.autoBackTimer = Timer(const Duration(seconds: 30), Get.back); state.animationController = AnimationController( vsync: this, // 确保使用的TickerProvider是当前Widget duration: const Duration(seconds: 1), ); ; state.animationController.repeat(); //动画开始、结束、向前移动或向后移动时会调用StatusListener state.animationController.addStatusListener((AnimationStatus status) { // AppLog.log("AnimationStatus:$status"); if (status == AnimationStatus.completed) { state.animationController.reset(); state.animationController.forward(); } else if (status == AnimationStatus.dismissed) { state.animationController.reset(); state.animationController.forward(); } }); initiateUdpMonitorAction(); } //发起监视命令,每隔一秒钟发一次,三十秒无应答则失败 void initiateUdpMonitorAction() { // 每隔一秒调用一次 udpMonitorAction 方法 state.realTimePicTimer = Timer.periodic(const Duration(seconds: 1), (Timer timer) { state.elapsedSeconds++; logic.udpMonitorAction(); // 检查条件,如果达到30秒且未得到应答,则认为失败 if (state.elapsedSeconds >= 30) { state.realTimePicTimer.cancel(); // 取消定时器 _handleFailure(); } }); } @override Widget build(BuildContext context) { return SizedBox( width: 1.sw, height: 1.sh, child: Stack( alignment: Alignment.center, children: [ Obx( () => state.listData.value.isEmpty || state.listData.value.isEmpty ? Image.asset( 'images/main/monitorBg.png', width: ScreenUtil().screenWidth, height: ScreenUtil().screenHeight, fit: BoxFit.cover, ) : Builder( builder: (BuildContext context) { try { return Image.memory( state.listData.value, gaplessPlayback: true, width: 1.sw, height: 1.sh, fit: BoxFit.cover, ); } catch (e, stackTrace) { AppLog.log('Error loading image: $e'); AppLog.log('Stack trace: $stackTrace'); return Container(); } }, ), ), Obx(() => state.listData.value.isEmpty ? Positioned( bottom: 300.h, child: Text( '正在创建安全连接...'.tr, style: TextStyle(color: Colors.black, fontSize: 26.sp), )) : Container()), Positioned( bottom: 10.w, child: Container( width: 1.sw - 30.w * 2, // height: 300.h, margin: EdgeInsets.all(30.w), decoration: BoxDecoration( color: Colors.black.withOpacity(0.2), borderRadius: BorderRadius.circular(20.h)), child: Column( children: [ SizedBox(height: 20.h), bottomTopBtnWidget(), SizedBox(height: 20.h), bottomBottomBtnWidget(), SizedBox(height: 20.h), ], ), )), Obx(() => state.listData.value.isEmpty ? buildRotationTransition() : Container()) ], ), ); } Widget bottomTopBtnWidget() { return Row(mainAxisAlignment: MainAxisAlignment.center, children: [ // 打开关闭声音 GestureDetector( onTap: () { state.isOpenVoice.value = !state.isOpenVoice.value; }, child: Container( width: 50.w, height: 50.w, padding: EdgeInsets.all(5.w), child: Obx(() => Image( width: 40.w, height: 40.w, image: state.isOpenVoice.value ? const AssetImage( 'images/main/icon_lockDetail_monitoringCloseVoice.png') : const AssetImage( 'images/main/icon_lockDetail_monitoringOpenVoice.png'))), ), ), SizedBox(width: 50.w), // 截图 GestureDetector( onTap: () { // Get.toNamed(Routers.monitoringRealTimeScreenPage); }, child: Container( width: 50.w, height: 50.w, padding: EdgeInsets.all(5.w), child: Image( width: 40.w, height: 40.w, image: const AssetImage( 'images/main/icon_lockDetail_monitoringScreenshot.png')), ), ), SizedBox(width: 50.w), // 录制 GestureDetector( onTap: () { // Get.toNamed(Routers.monitoringRealTimeScreenPage); }, child: Container( width: 50.w, height: 50.w, padding: EdgeInsets.all(5.w), child: Image( width: 40.w, height: 40.w, fit: BoxFit.fill, image: const AssetImage( 'images/main/icon_lockDetail_monitoringScreenRecording.png')), ), ), SizedBox(width: 50.w), GestureDetector( onTap: () { logic.showToast('功能暂未开放'.tr); }, child: Image( width: 28.w, height: 28.w, fit: BoxFit.fill, image: const AssetImage('images/main/icon_lockDetail_rectangle.png')) // child: Container( // width: 50.w, // height: 50.w, // padding: EdgeInsets.all(5.w), // child: Image( // width: 40.w, // height: 40.w, // fit: BoxFit.fill, // image: const AssetImage( // "images/main/icon_lockDetail_rectangle.png")), // ), ) ]); } Widget bottomBottomBtnWidget() { return Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ // 接听 Obx(() => bottomBtnItemWidget( getAnswerBtnImg(), getAnswerBtnName(), Colors.white, () async { //监视状态下不能发送录音 logic.showToast('监视状态下不能发送录音'.tr); }, longPress: () async { /* // 开始长按 AppLog.log("onLongPress"); //获取麦克风权限 await logic.getPermissionStatus().then((value) async { if (!value) { return; } // state.isSenderAudioData.value = false; }); state.listAudioData.value = []; if (state.udpStatus.value == 8) { state.udpStatus.value = 9; } // logic.readG711Data(); logic.startProcessing(); */ }, longPressUp: () async { /* // 长按结束 AppLog.log("onLongPressUp"); if (state.udpStatus.value == 9) { state.udpStatus.value = 8; } */ })), bottomBtnItemWidget( 'images/main/icon_lockDetail_hangUp.png', '挂断'.tr, Colors.red, () async { // 挂断 logic.udpHangUpAction(); CallTalk().finishAVData(); Get.back(); }), bottomBtnItemWidget('images/main/icon_lockDetail_monitoringUnlock.png', '开锁', AppColors.mainColor, () { logic.showToast('监视中暂不能开锁'.tr); /* showDeletPasswordAlertDialog(context); */ }) ]); } String getAnswerBtnImg() { switch (state.udpStatus.value) { case 8: return 'images/main/icon_lockDetail_monitoringUnTalkback.png'; case 9: return 'images/main/icon_lockDetail_monitoringTalkback.png'; default: return 'images/main/icon_lockDetail_monitoringUnTalkback.png'; } } String getAnswerBtnName() { switch (state.udpStatus.value) { case 8: return '长按说话'.tr; case 9: return '松开发送'.tr; default: return '长按说话'.tr; } } Widget bottomBtnItemWidget( String iconUrl, String name, Color backgroundColor, Function() onClick, {Function()? longPress, Function()? longPressUp}) { double wh = 80.w; return GestureDetector( onTap: onClick, onLongPress: longPress, onLongPressUp: longPressUp, child: SizedBox( height: 140.h, child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( width: wh, height: wh, decoration: BoxDecoration( color: backgroundColor, borderRadius: BorderRadius.circular((wh + 10.w * 2) / 2)), padding: EdgeInsets.all(20.w), child: Image.asset(iconUrl, fit: BoxFit.fitWidth), ), SizedBox(height: 20.w), Expanded( child: Text(name, style: TextStyle(fontSize: 20.sp, color: Colors.white), textAlign: TextAlign.center)) ], )), ); } void showDeletPasswordAlertDialog(BuildContext context) { showDialog( barrierDismissible: false, context: context, builder: (BuildContext context) { return ShowTFView( title: '请输入六位数字开锁密码'.tr, tipTitle: '', controller: state.passwordTF, inputFormatters: [ LengthLimitingTextInputFormatter(6), //限制长度 FilteringTextInputFormatter.allow(RegExp('[0-9]')), ], sureClick: () async { //发送删除锁请求 if (state.passwordTF.text.isEmpty) { logic.showToast('请输入开锁密码'.tr); return; } // List numbers = state.passwordTF.text.split('').map((char) => int.parse(char)).toList(); // 开锁 // lockID List numbers = []; List lockIDData = utf8.encode(state.passwordTF.text); numbers.addAll(lockIDData); // topBytes = getFixedLengthList(lockIDData, 20 - lockIDData.length); for (int i = 0; i < 6 - lockIDData.length; i++) { numbers.add(0); } logic.udpOpenDoorAction(numbers); }, cancelClick: () { Get.back(); }, ); }, ); } //旋转动画 Widget buildRotationTransition() { return Positioned( left: ScreenUtil().screenWidth / 2 - 220.w / 2, top: ScreenUtil().screenHeight / 2 - 220.w / 2 - 150.h, child: GestureDetector( child: RotationTransition( //设置动画的旋转中心 alignment: Alignment.center, //动画控制器 turns: state.animationController, //将要执行动画的子view child: AnimatedOpacity( opacity: 0.5, duration: const Duration(seconds: 2), child: Image.asset( 'images/main/realTime_connecting.png', width: 220.w, height: 220.w, ), ), ), onTap: () { state.animationController.forward(); initiateUdpMonitorAction(); }, ), ); } void _handleFailure() { // 在这里处理失败的逻辑 CallTalk().finishAVData(); state.realTimePicTimer.cancel(); state.autoBackTimer.cancel(); if (state.animationController != null) { state.animationController.stop(); } } @override void dispose() { state.animationController.dispose(); state.realTimePicTimer.cancel(); state.autoBackTimer.cancel(); CallTalk().finishAVData(); super.dispose(); } }