import 'dart:async'; import 'dart:io'; import 'package:electronic_assistant/base/base_controller.dart'; import 'package:electronic_assistant/data/repositories/task_repository.dart'; import 'package:electronic_assistant/module/talk/summary/view.dart'; import 'package:electronic_assistant/module/talk/todo/view.dart'; import 'package:electronic_assistant/resource/assets.gen.dart'; import 'package:electronic_assistant/resource/colors.gen.dart'; import 'package:electronic_assistant/resource/string.gen.dart'; import 'package:electronic_assistant/utils/error_handler.dart'; import 'package:electronic_assistant/utils/expand.dart'; import 'package:electronic_assistant/utils/mmkv_util.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import '../../data/bean/agenda_list_all_bean.dart'; import '../../data/bean/talks.dart'; import '../../data/repositories/agenda_repository.dart'; import '../../data/repositories/talk_repository.dart'; import '../../dialog/alert_dialog.dart'; import '../../utils/toast_util.dart'; import '../record/controller.dart'; import 'original/view.dart'; import 'package:just_audio/just_audio.dart'; class TalkController extends BaseController { final String uploadNoPrompts = "UPLOAD_NO_PROMPTS"; final Rxn talkBean = Rxn(); final isShowElectricLow = false.obs; bool isAudioLoading = false; final double sliderMax = 1; bool? audioFileIsExist; bool? isUploadedFile; final isAudioPlaying = false.obs; final audioProgressValue = 0.0.obs; final audioDuration = Duration.zero.obs; final agendaAllList = [].obs; final List tabBeans = [ StringName.talkTabSummary.tr, StringName.talkTabMyTask.tr, StringName.talkTabOriginal.tr ]; final _audioPlayer = AudioPlayer(); StreamSubscription? _talkBeanListener; final pages = [const SummaryView(), const TodoView(), const OriginalView()]; @override void onReady() { super.onReady(); _initAudioPlayer(); _initListener(); _getArguments(); } void _initAudioPlayer() { _audioPlayer.playerStateStream.listen((playerState) { if (playerState.processingState == ProcessingState.loading || playerState.processingState == ProcessingState.buffering) { isAudioLoading = true; debugPrint('音频load = true'); } else { debugPrint('音频load = false'); isAudioLoading = false; if (playerState.processingState == ProcessingState.completed) { _audioPlayer.stop(); _audioPlayer.seek(Duration.zero); isAudioPlaying.value = false; debugPrint('音频 播放结束了'); } } isAudioPlaying.value = playerState.playing; }, onError: (Object e, StackTrace stackTrace) { debugPrint('音频加载异常 == $e'); }); _audioPlayer.durationStream.listen((duration) { if (duration != null) { debugPrint('音频总播放时长 == ${duration.inMilliseconds}'); audioDuration.value = duration; } }); _audioPlayer.positionStream.listen((position) { if (audioDuration.value.inMilliseconds > 0) { audioProgressValue.value = (position.inMilliseconds / audioDuration.value.inMilliseconds) .clamp(0.0, sliderMax); } }); } void _initListener() { _talkBeanListener = talkBean.listen((bean) { _dealTalkUpdate(bean); }); } void _dealTalkUpdate(TalkBean? bean) async { String? id = talkBean.value?.id; if (id == null) { return; } try { File file = await RecordController.getRecordFile(id); await _audioPlayer.setAudioSource(AudioSource.uri(file.uri)); audioFileIsExist = true; } catch (e) { audioFileIsExist = false; debugPrint('音频设置异常 == $e'); } } void _getArguments() { if (Get.arguments is TalkBean) { talkBean.value = Get.arguments as TalkBean; } } void updateProgress(double value) { final newPosition = Duration( milliseconds: (value * audioDuration.value.inMilliseconds).toInt()); _audioPlayer.seek(newPosition); } void clickPlayAudio() { if (audioFileIsExist != true) { ToastUtil.showToast(StringName.talkFileNotFind.tr); return; } if (isAudioLoading) { ToastUtil.showToast(StringName.talkAudioLoading.tr); return; } if (_audioPlayer.playing) { _audioPlayer.pause(); isAudioPlaying.value = false; } else { _audioPlayer.play(); isAudioPlaying.value = true; } } void _checkFileSizeAndNet() async { String? id = talkBean.value?.id; if (id == null) { return; } File file = await RecordController.getRecordFile(id); if (!file.existsSync()) { ToastUtil.showToast(StringName.talkUploadFileNotExist.tr); return; } bool isCheckRemind = KVUtil.getBool(uploadNoPrompts, false); if (isCheckRemind) { _requestAnalyze(file); return; } //如果文件大小低于250MB 不弹窗提醒 if (file.lengthSync() < 250 * 1024 * 1024) { _requestAnalyze(file); return; } final List connectivityResult = await (Connectivity().checkConnectivity()); if (connectivityResult.contains(ConnectivityResult.wifi)) { _requestAnalyze(file); } else { _showTrafficRemindDialog(file.lengthSync().toReadableSize(), confirmOnTap: (isCheckRemind) { if (isCheckRemind) { KVUtil.putBool(uploadNoPrompts, true); } _requestAnalyze(file); }); } } void _showTrafficRemindDialog(String holderTxt, {void Function(bool isCheckRemind)? confirmOnTap}) { final remindTrafficConsume = false.obs; Widget getSelectIcon() { return Obx(() { return remindTrafficConsume.value ? Assets.images.iconSelectTrue.image() : Assets.images.iconSelectFalse.image(); }); } Assets.images.iconSelectTrue.image(); EAAlertDialog.show( contentWidget: Column( children: [ Text( StringName.talkTrafficRemindTitle.tr .replacePlaceholders([holderTxt]), style: TextStyle(fontSize: 15.sp, color: ColorName.primaryTextColor), ), SizedBox(height: 8.h), GestureDetector( onTap: () { remindTrafficConsume.value = !remindTrafficConsume.value; }, child: IntrinsicWidth( child: Row( children: [ SizedBox(width: 20.w, height: 20.w, child: getSelectIcon()), SizedBox(width: 5.w), Text( StringName.talkTrafficRemindTips.tr, style: TextStyle( fontSize: 15.sp, color: ColorName.tertiaryTextColor), ) ], ), ), ) ], ), cancelText: StringName.cancel.tr, confirmText: StringName.sure.tr, confirmOnTap: () { confirmOnTap?.call(remindTrafficConsume.value); }); } void checkCanAnalyze() async { String? id = talkBean.value?.id; double? duration = talkBean.value?.duration; if (id == null || duration == null) { return; } talkRepository.checkElectric(duration).then((data) { if (data.enough) { //检查网络以及文件大小 _checkFileSizeAndNet(); } else { ToastUtil.showToast(StringName.talkAnalyseLowToast.tr); isShowElectricLow.value = true; } }).catchError((error) { ToastUtil.showToast(error); }); } void _requestAnalyze(File file) { String? talkId = talkBean.value?.id; double? duration = talkBean.value?.duration; if (talkId == null || duration == null || isUploadedFile == true) { return; } talkRepository.uploadTalkFile(talkId, duration, file).then((taskId) { ToastUtil.showToast('提交成功,小听正在分析谈话,请稍后'); isUploadedFile = true; talkBean.value?.taskId = taskId; talkBean.value?.status = TalkStatus.analysing; taskRepository.addTask(taskId); }).catchError((error) { ErrorHandler.toastError(error); }); } void goElectricStore() { //TODO 跳转至商店页 } void refreshAgendaAllData() { String? id = talkBean.value?.id; if (id == null || agendaAllList.isNotEmpty) { return; } agendaRepository.agendaListAll(id).then((agenda) { if (agenda.list != null) { agendaAllList.value = agenda.list!; } }); } @override void onClose() { super.onClose(); _talkBeanListener?.cancel(); _audioPlayer.dispose(); } }