app-starlock/lib/main/lockDetail/realTimePicture/realTimePicture_page.dart

420 lines
13 KiB
Dart
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<RealTimePicturePage> createState() => _RealTimePicturePageState();
}
class _RealTimePicturePageState extends State<RealTimePicturePage> with TickerProviderStateMixin {
final RealTimePictureLogic logic = Get.put(RealTimePictureLogic());
final RealTimePictureState state = Get.find<RealTimePictureLogic>().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: <Widget>[
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: <Widget>[
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: <Widget>[
// 打开关闭声音
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: <Widget>[
// 接听
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 = <int>[];
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: <Widget>[
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: <TextInputFormatter>[
LengthLimitingTextInputFormatter(6), //限制长度
FilteringTextInputFormatter.allow(RegExp('[0-9]')),
],
sureClick: () async {
//发送删除锁请求
if (state.passwordTF.text.isEmpty) {
logic.showToast('请输入开锁密码'.tr);
return;
}
// List<int> numbers = state.passwordTF.text.split('').map((char) => int.parse(char)).toList();
// 开锁
// lockID
List<int> numbers = <int>[];
List<int> 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();
}
}