415 lines
13 KiB
Dart
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 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/talk/call/callTalk.dart';
import 'package:star_lock/talk/startChart/constant/talk_status.dart';
import 'package:star_lock/talk/startChart/views/talkView/talk_view_logic.dart';
import 'package:star_lock/talk/startChart/views/talkView/talk_view_state.dart';
import '../../../../app_settings/app_colors.dart';
import '../../../../tools/showTFView.dart';
class TalkViewPage extends StatefulWidget {
const TalkViewPage({Key? key}) : super(key: key);
@override
State<TalkViewPage> createState() => _TalkViewPageState();
}
class _TalkViewPageState extends State<TalkViewPage>
with TickerProviderStateMixin {
final TalkViewLogic logic = Get.put(TalkViewLogic());
final TalkViewState state = Get.find<TalkViewLogic>().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) {
if (status == AnimationStatus.completed) {
state.animationController.reset();
state.animationController.forward();
} else if (status == AnimationStatus.dismissed) {
state.animationController.reset();
state.animationController.forward();
}
});
}
@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
? Image.asset(
'images/main/monitorBg.png',
width: ScreenUtil().screenWidth,
height: ScreenUtil().screenHeight,
fit: BoxFit.cover,
)
: Container(
decoration: state.isRecordingScreen.value
? BoxDecoration(
border: Border.all(color: Colors.red, width: 1))
: BoxDecoration(),
child: PopScope(
canPop: false,
child: RepaintBoundary(
key: state.globalKey,
child: RotatedBox(
quarterTurns: 1, // 顺时针旋转 90 度1 个四分之一圈)
child: Image.memory(
state.listData.value,
gaplessPlayback: true,
width: 1.sw,
height: 1.sh,
fit: BoxFit.cover,
filterQuality: FilterQuality.high,
errorBuilder: (
BuildContext context,
Object error,
StackTrace? stackTrace,
) {
return Container(color: Colors.transparent);
},
),
),
),
),
),
),
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),
],
),
),
),
// Positioned(
// top: 100.h,
// left: 10.w,
// child: Obx(
// () => Text(
// 'FPS:${state.fps.value}',
// style: TextStyle(
// fontSize: 30.sp,
// color: Colors.orange,
// fontWeight: FontWeight.bold),
// ),
// ),
// ),
Obx(() => state.listData.value.isEmpty
? buildRotationTransition()
: Container())
],
),
);
}
Widget bottomTopBtnWidget() {
return Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
// 打开关闭声音
GestureDetector(
onTap: () {
if (state.talkStatus.value == TalkStatus.answeredSuccessfully) {
// 打开关闭声音
logic.updateTalkExpect();
}
},
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_monitoringOpenVoice.png')
: const AssetImage(
'images/main/icon_lockDetail_monitoringCloseVoice.png'))),
),
),
SizedBox(width: 50.w),
// 截图
GestureDetector(
onTap: () async {
if (state.talkStatus.value == TalkStatus.answeredSuccessfully) {
await logic.captureAndSavePng();
}
},
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: () async {
if (state.talkStatus.value == TalkStatus.answeredSuccessfully) {
if (state.isRecordingScreen.value) {
await logic.stopRecording();
print('停止录屏');
} else {
await logic.startRecording();
print('开始录屏');
}
}
},
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'),
),
),
]);
}
Widget bottomBottomBtnWidget() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
// 接听
Obx(
() => bottomBtnItemWidget(
getAnswerBtnImg(),
getAnswerBtnName(),
Colors.white,
longPress: () async {
if (state.talkStatus.value == TalkStatus.answeredSuccessfully) {
print('开始录音');
logic.startProcessingAudio();
}
},
longPressUp: () async {
print('停止录音');
logic.stopProcessingAudio();
},
onClick: () async {
if (state.talkStatus.value == TalkStatus.waitingAnswer) {
// 接听
logic.initiateAnswerCommand();
}
},
),
),
bottomBtnItemWidget(
'images/main/icon_lockDetail_hangUp.png', '挂断'.tr, Colors.red,
onClick: () {
// 挂断
logic.udpHangUpAction();
}),
bottomBtnItemWidget(
'images/main/icon_lockDetail_monitoringUnlock.png',
'开锁',
AppColors.mainColor,
onClick: () {},
)
]);
}
String getAnswerBtnImg() {
switch (state.talkStatus.value) {
case TalkStatus.waitingAnswer:
return 'images/main/icon_lockDetail_monitoringAnswerCalls.png';
case TalkStatus.answeredSuccessfully:
return 'images/main/icon_lockDetail_monitoringUnTalkback.png';
default:
return 'images/main/icon_lockDetail_monitoringAnswerCalls.png';
}
}
String getAnswerBtnName() {
switch (state.talkStatus.value) {
case TalkStatus.waitingAnswer:
return '接听'.tr;
case TalkStatus.answeredSuccessfully:
return '长按说话'.tr;
default:
return '接听'.tr;
}
}
Widget bottomBtnItemWidget(String iconUrl, String name, Color backgroundColor,
{required 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);
// }
},
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();
},
),
);
}
@override
void dispose() {
state.animationController.dispose();
state.realTimePicTimer.cancel();
state.autoBackTimer.cancel();
CallTalk().finishAVData();
super.dispose();
}
}