From b75c461d02de9bdde372a2b3339ece84d2cdf050 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Fri, 23 May 2025 14:37:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=92=AD=E6=94=BE=E5=8A=A8?= =?UTF-8?q?=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/lottie/sound_effect.json | 1 + .../meeting_details_controller.dart | 17 ++++- .../meeting/views/meeting_details_view.dart | 69 +++++++++---------- .../views/speaker_all_bottom_sheet.dart | 16 +++++ lib/modules/meeting/views/speech_tab.dart | 52 +++++++++++++- 5 files changed, 114 insertions(+), 41 deletions(-) create mode 100644 assets/lottie/sound_effect.json diff --git a/assets/lottie/sound_effect.json b/assets/lottie/sound_effect.json new file mode 100644 index 000000000..44c2522c1 --- /dev/null +++ b/assets/lottie/sound_effect.json @@ -0,0 +1 @@ +{"nm":"3line_soundwave","ddd":0,"h":200,"w":80,"meta":{"g":"@lottiefiles/toolkit-js 0.33.2"},"layers":[{"ty":4,"nm":"3 Outlines","sr":1,"st":0,"op":24,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[16.036,58.68,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[64.215,101.592,0],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[0],"t":8},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[100],"t":12},{"s":[1],"t":16}],"ix":11}},"ef":[],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Group 1","ix":1,"cix":2,"np":4,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[1.527,-0.046],[1.003,-1.094],[-0.16,-1.436],[-1.184,-1.231],[-3.258,-8.386],[0,-9.388],[3.259,-8.385],[6.107,-6.426],[0.159,-1.435],[-0.957,-1.094],[-1.527,-0.022],[-1.184,1.276],[-3.896,9.684],[0,10.892],[3.897,9.684],[7.11,7.428]],"o":[[-1.527,0.046],[-0.957,1.094],[0.159,1.436],[6.107,6.426],[3.259,8.385],[0,9.388],[-3.258,8.386],[-1.184,1.231],[-0.16,1.436],[1.003,1.14],[1.527,0.023],[7.11,-7.429],[3.897,-9.685],[0,-10.892],[-3.896,-9.685],[-1.184,-1.276]],"v":[[-10.635,-58.385],[-14.429,-56.675],[-15.625,-52.882],[-13.609,-48.882],[0.439,-26.666],[5.327,-0.006],[0.439,26.654],[-13.609,48.871],[-15.625,52.87],[-14.429,56.665],[-10.635,58.408],[-6.568,56.529],[9.941,30.859],[15.786,-0.006],[9.941,-30.87],[-6.568,-56.538]]},"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.9569,0.2627,0.2118],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[16.035,58.68],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":1},{"ty":4,"nm":"2 Outlines","sr":1,"st":0,"op":24,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[12.743,42.89,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[44.128,101.592,0],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.667,"y":1},"s":[0],"t":4},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[100],"t":8},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[100],"t":16},{"s":[0],"t":20}],"ix":11}},"ef":[],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Group 1","ix":1,"cix":2,"np":2,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[1.572,0.046],[1.002,-1.23],[-0.205,-1.413],[-1.185,-1.276],[-2.119,-5.628],[0,-6.289],[2.119,-5.651],[3.965,-4.421],[0.205,-1.39],[-1.049,-1.139],[-1.572,0.023],[-1.23,1.368],[-2.666,6.973],[0,7.748],[2.666,6.973],[4.967,5.377]],"o":[[-1.572,-0.046],[-1.049,1.094],[0.205,1.413],[3.965,4.466],[2.119,5.628],[0,6.289],[-2.119,5.652],[-1.185,1.322],[-0.205,1.39],[1.002,1.185],[1.572,-0.022],[4.967,-5.332],[2.666,-6.972],[0,-7.702],[-2.666,-6.972],[-1.23,-1.322]],"v":[[-7.161,-42.594],[-11.023,-40.816],[-12.288,-37.057],[-10.202,-33.023],[-1.077,-17.882],[2.102,-0.006],[-1.077,17.904],[-10.202,33.012],[-12.288,37.079],[-11.023,40.874],[-7.161,42.617],[-2.956,40.531],[8.493,22.074],[12.493,-0.006],[8.493,-22.018],[-2.956,-40.542]]},"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.9569,0.2627,0.2118],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[12.742,42.89],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":2},{"ty":4,"nm":"1 Outlines","sr":1,"st":0,"op":24,"ip":-5,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[9.137,25.999,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[24.355,101.586,0],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11}},"ef":[],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Group 1","ix":1,"cix":2,"np":2,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[1.641,0.046],[1.048,-1.23],[-0.274,-1.344],[-1.003,-1.413],[0,-6.243],[3.463,-4.466],[0.273,-1.345],[-1.048,-1.139],[-1.641,0.046],[-1.139,1.458],[-1.413,4.011],[0,4.375],[1.412,4.01],[2.598,3.236]],"o":[[-1.641,-0.046],[-1.048,1.14],[0.273,1.344],[3.463,4.466],[0,6.244],[-1.003,1.413],[-0.274,1.344],[1.048,1.231],[1.641,-0.045],[2.598,-3.236],[1.412,-4.01],[0,-4.375],[-1.413,-4.01],[-1.139,-1.458]],"v":[[-3.418,-25.703],[-7.451,-23.926],[-8.613,-20.2],[-6.699,-16.064],[-1.504,0],[-6.699,16.065],[-8.613,20.201],[-7.451,23.926],[-3.418,25.703],[0.752,23.448],[6.768,12.578],[8.887,0],[6.768,-12.578],[0.752,-23.447]]},"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.9569,0.2627,0.2118],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[9.137,25.999],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":3}],"v":"5.7.4","fr":12,"op":24,"ip":0,"assets":[]} \ No newline at end of file diff --git a/lib/modules/meeting/controllers/meeting_details_controller.dart b/lib/modules/meeting/controllers/meeting_details_controller.dart index 6a65612e2..dbf05cccf 100644 --- a/lib/modules/meeting/controllers/meeting_details_controller.dart +++ b/lib/modules/meeting/controllers/meeting_details_controller.dart @@ -18,15 +18,18 @@ import '../model/meeting_details_model.dart'; import '../model/meeting_model.dart'; class MeetingDetailsController extends GetxController - with GetSingleTickerProviderStateMixin { + with GetTickerProviderStateMixin { late TabController tabController; final RxInt currentIndex = 0.obs; + late AnimationController lottieController; + final PlayerController playerController = PlayerController(); RxBool isTop = false.obs; RxInt durationMax = 0.obs; RxDouble dragOffset = 210.w.obs; + RxBool isPlay = false.obs; RxInt currentDuration = 0.obs; RxInt speakerAllStarttime = (-1).obs; @@ -65,6 +68,8 @@ class MeetingDetailsController extends GetxController } currentIndex.value = tabController.index; }); + lottieController = AnimationController(vsync: this) + ..duration = const Duration(seconds: 2); final Map args = Get.arguments ?? {}; id = args['id']; _headers = { @@ -80,6 +85,7 @@ class MeetingDetailsController extends GetxController tabController.dispose(); playerController.dispose(); _isDisposed = true; + lottieController.dispose(); super.onClose(); } @@ -114,6 +120,15 @@ class MeetingDetailsController extends GetxController } } }); + playerController.onPlayerStateChanged.listen((PlayerState playerState) { + isPlay.value = playerState.isPlaying; + if (_isDisposed) return; + if (playerState.isPlaying) { + lottieController.repeat(); + } else { + lottieController.stop(); + } + }); if (meetingDetails.value.tasktype == 1) { List speakerList = await SqfliteApi.getMeetingSpeaker(id); textList.value = List.from(speakerList); diff --git a/lib/modules/meeting/views/meeting_details_view.dart b/lib/modules/meeting/views/meeting_details_view.dart index f6bbd6984..fa8bb5621 100644 --- a/lib/modules/meeting/views/meeting_details_view.dart +++ b/lib/modules/meeting/views/meeting_details_view.dart @@ -71,25 +71,23 @@ class MeetingDetailsView extends GetView { ), child: Row( children: [ - StreamBuilder( - stream: controller.playerController.onPlayerStateChanged, - builder: (context, snapshot) { - bool isPlay = snapshot.data?.isPlaying ?? false; - return GestureDetector( - onTap: () { - if (isPlay) { - controller.playerController.pausePlayer(); - } else { - controller.playerController.startPlayer(); - } - }, - child: Icon( - isPlay ? Icons.pause_circle : Icons.play_circle, - color: Colors.black, - size: 30.w, - ), - ); + GestureDetector( + onTap: () { + if (controller.isPlay.value) { + controller.playerController.pausePlayer(); + } else { + controller.playerController.startPlayer(); + } }, + child: Obx( + () => Icon( + controller.isPlay.value + ? Icons.pause_circle + : Icons.play_circle, + color: Colors.black, + size: 30.w, + ), + ), ), 4.horizontalSpace, GestureDetector( @@ -352,26 +350,23 @@ class MeetingDetailsView extends GetView { size: 30.w, ), ), - StreamBuilder( - stream: - controller.playerController.onPlayerStateChanged, - builder: (context, snapshot) { - bool isPlay = snapshot.data?.isPlaying ?? false; - return GestureDetector( - onTap: () { - if (isPlay) { - controller.playerController.pausePlayer(); - } else { - controller.playerController.startPlayer(); - } - }, - child: Icon( - isPlay ? Icons.pause_circle : Icons.play_circle, - color: Colors.black, - size: 48.w, - ), - ); + GestureDetector( + onTap: () { + if (controller.isPlay.value) { + controller.playerController.pausePlayer(); + } else { + controller.playerController.startPlayer(); + } }, + child: Obx( + () => Icon( + controller.isPlay.value + ? Icons.pause_circle + : Icons.play_circle, + color: Colors.black, + size: 48.w, + ), + ), ), GestureDetector( onTap: () { diff --git a/lib/modules/meeting/views/speaker_all_bottom_sheet.dart b/lib/modules/meeting/views/speaker_all_bottom_sheet.dart index ecf12291e..c73e1575d 100644 --- a/lib/modules/meeting/views/speaker_all_bottom_sheet.dart +++ b/lib/modules/meeting/views/speaker_all_bottom_sheet.dart @@ -4,6 +4,7 @@ import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; +import 'package:lottie/lottie.dart'; import '../../../data/services/db/sqflite_api.dart'; import '../controllers/meeting_details_controller.dart'; @@ -361,6 +362,21 @@ class _SpeakerAllBottomSheetState extends State { fontSize: 12.sp, ), ), + if (isActive) + Container( + width: 16.w, + height: 16.w, + margin: EdgeInsets.only(left: 5.w), + alignment: Alignment.center, + clipBehavior: Clip.hardEdge, + decoration: const BoxDecoration(), + child: Transform.scale( + scale: 1.6, + child: Lottie.asset( + 'assets/lottie/sound_effect.json', + ), + ), + ), ], ), Padding( diff --git a/lib/modules/meeting/views/speech_tab.dart b/lib/modules/meeting/views/speech_tab.dart index 1d742a493..1d14f57ef 100644 --- a/lib/modules/meeting/views/speech_tab.dart +++ b/lib/modules/meeting/views/speech_tab.dart @@ -2,6 +2,7 @@ import 'package:common_utils/common_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:lottie/lottie.dart'; import '../controllers/meeting_details_controller.dart'; import 'speaker_all_bottom_sheet.dart'; @@ -87,6 +88,43 @@ class SpeechTab extends GetView { fontSize: 13.sp, ), ), + Obx(() { + bool isActive = false; + int starttime = item['starttime']; + int endtime = 0; + if (index == controller.textList.length - 1) { + endtime = controller.durationMax.value; + } else { + endtime = + controller.textList[index + 1]['starttime']; + } + if (controller.currentDuration.value != 0) { + if (controller.currentDuration.value >= starttime && + controller.currentDuration.value < endtime) { + isActive = true; + } + } + return isActive + ? Container( + width: 16.w, + height: 16.w, + margin: EdgeInsets.only(left: 5.w), + alignment: Alignment.center, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + color: Colors.red[100], + borderRadius: BorderRadius.circular(4.r), + ), + child: Transform.scale( + scale: 1.6, + child: Lottie.asset( + 'assets/lottie/sound_effect.json', + controller: controller.lottieController, + ), + ), + ) + : const SizedBox(); + }), ], ), ), @@ -169,9 +207,17 @@ class SpeechTab extends GetView { return GestureDetector( behavior: HitTestBehavior.translucent, onTap: () { - controller.playerController - .seekTo(item['starttime']); - controller.playerController.startPlayer(); + if (isActive) { + if (controller.isPlay.value) { + controller.playerController.pausePlayer(); + } else { + controller.playerController.startPlayer(); + } + } else { + controller.playerController + .seekTo(item['starttime']); + controller.playerController.startPlayer(); + } }, child: Container( width: double.infinity,