Browse Source

fix(meeting): 修复返回操作时未保存录音和标题的问题

修改返回逻辑,确保在返回前保存录音和标题变更
修复底部弹窗显示时未暂停录音的问题
weicu
lxm 9 months ago
parent
commit
05a19d18e3
  1. 48
      lib/modules/meeting/controllers/meeting_record_controller.dart
  2. 26
      lib/modules/meeting/views/meeting_record_view.dart

48
lib/modules/meeting/controllers/meeting_record_controller.dart

@ -25,7 +25,7 @@ enum TimerStatus {
/// 负责会议记录的状态管理、音频处理、语音识别和UI交互 /// 负责会议记录的状态管理、音频处理、语音识别和UI交互
class MeetingRecordController extends GetxController class MeetingRecordController extends GetxController
with GetTickerProviderStateMixin { with GetTickerProviderStateMixin {
// Services // 服务
final AsrService _asrService = Get.find<AsrService>(); final AsrService _asrService = Get.find<AsrService>();
final BleManager _bleManager = Get.find<BleManager>(); final BleManager _bleManager = Get.find<BleManager>();
@ -45,7 +45,7 @@ class MeetingRecordController extends GetxController
final RecorderController waveformController = RecorderController(); final RecorderController waveformController = RecorderController();
// Transcription content // 转写内容
final RxString intermediateContent = ''.obs; final RxString intermediateContent = ''.obs;
final RxString finalContent = ''.obs; final RxString finalContent = ''.obs;
@ -57,7 +57,7 @@ class MeetingRecordController extends GetxController
late FocusNode titleFocusNode; late FocusNode titleFocusNode;
final Future<Directory> appDocDir = getApplicationDocumentsDirectory(); final Future<Directory> appDocDir = getApplicationDocumentsDirectory();
// Timing variables // 计时变量
Timer? _timer; Timer? _timer;
int _elapsedMilliseconds = 0; int _elapsedMilliseconds = 0;
int? _lastStartTime; int? _lastStartTime;
@ -107,19 +107,19 @@ class MeetingRecordController extends GetxController
} }
} }
/// Initializes UI controllers and focus nodes /// 初始化 UI 控制器和焦点节点
void _initializeComponents() { void _initializeComponents() {
titleEditingController = TextEditingController(text: fileName.value); titleEditingController = TextEditingController(text: fileName.value);
titleFocusNode = FocusNode(); titleFocusNode = FocusNode();
titleFocusNode.addListener(_handleTitleFocusChange); titleFocusNode.addListener(_handleTitleFocusChange);
} }
/// Sets up initial state from navigation arguments /// 根据路由参数设置初始状态
void _setupFromArguments() { void _setupFromArguments() {
final Map<String, dynamic> args = Get.arguments ?? {}; final Map<String, dynamic> args = Get.arguments ?? {};
audioType.value = args['audioTypes'] ?? 0; audioType.value = args['audioTypes'] ?? 0;
// Set default filename based on audio type // 根据音频类型设置默认文件名
switch (audioType.value) { switch (audioType.value) {
case 0: case 0:
fileName.value = "liveRecording".tr; //对应中文:现场录音 fileName.value = "liveRecording".tr; //对应中文:现场录音
@ -134,7 +134,7 @@ class MeetingRecordController extends GetxController
newName.value = fileName.value; newName.value = fileName.value;
} }
/// Cleans up resources when controller is disposed /// 控制器销毁时清理资源
void _cleanupResources() { void _cleanupResources() {
_timer?.cancel(); _timer?.cancel();
_stopWaveformTimer(); _stopWaveformTimer();
@ -156,14 +156,14 @@ class MeetingRecordController extends GetxController
waveformController.dispose(); waveformController.dispose();
} }
/// Handles focus changes in title text field /// 处理标题输入框焦点变化
void _handleTitleFocusChange() { void _handleTitleFocusChange() {
if (!titleFocusNode.hasFocus && isEditingTitle.value) { if (!titleFocusNode.hasFocus && isEditingTitle.value) {
saveTitleChange(); saveTitleChange();
} }
} }
/// Starts title editing mode /// 开始标题编辑模式
void startTitleEditing() { void startTitleEditing() {
isEditingTitle.value = true; isEditingTitle.value = true;
titleEditingController.text = fileName.value; titleEditingController.text = fileName.value;
@ -173,7 +173,7 @@ class MeetingRecordController extends GetxController
}); });
} }
/// Saves new title and exits editing mode /// 保存新标题后退出编辑状态
Future<void> saveTitleChange() async { Future<void> saveTitleChange() async {
isEditingTitle.value = true; isEditingTitle.value = true;
if (isEditingTitle.value) { if (isEditingTitle.value) {
@ -183,12 +183,12 @@ class MeetingRecordController extends GetxController
} }
} }
/// Toggles visibility of transcribed text content /// 切换转写文本内容的显示状态
Future<void> toggleTextDisplay() async { Future<void> toggleTextDisplay() async {
showTextContent.toggle(); showTextContent.toggle();
} }
/// Toggles important mark status /// 切换重要标记状态
void toggleMarked() => isMarked.toggle(); void toggleMarked() => isMarked.toggle();
/// 格式化时间为 MM:SS.S 显示格式 /// 格式化时间为 MM:SS.S 显示格式
@ -204,7 +204,7 @@ class MeetingRecordController extends GetxController
'.${centiseconds.toString()}'; '.${centiseconds.toString()}';
} }
/// Starts/resumes recording based on current state /// 根据当前状态开始或恢复录音
Future<void> toggleRecording() async { Future<void> toggleRecording() async {
// 等待权限请求完成并获取结果 // 等待权限请求完成并获取结果
final bool granted = await _requestRecordPermission(); final bool granted = await _requestRecordPermission();
@ -229,7 +229,7 @@ class MeetingRecordController extends GetxController
} }
} }
/// Starts recording session /// 开始录音会话
Future<void> _startRecording() async { Future<void> _startRecording() async {
// Prepare storage directory // Prepare storage directory
final appDir = await appDocDir; final appDir = await appDocDir;
@ -260,7 +260,7 @@ class MeetingRecordController extends GetxController
}); });
isRecording.value = true; isRecording.value = true;
// Update state // 更新录音状态
fileName.value = fullFileName; fileName.value = fullFileName;
newName.value = fullFileName; newName.value = fullFileName;
titleEditingController.text = fullFileName; titleEditingController.text = fullFileName;
@ -272,7 +272,7 @@ class MeetingRecordController extends GetxController
startTimer(); startTimer();
} }
/// Activates appropriate hardware service based on audio type /// 根据音频类型启动对应的硬件服务
void _startHardwareServices() { void _startHardwareServices() {
switch (audioType.value) { switch (audioType.value) {
case 0: case 0:
@ -289,7 +289,7 @@ class MeetingRecordController extends GetxController
} }
} }
/// Pauses current recording session /// 暂停当前录音会话
Future<void> _pauseRecording() async { Future<void> _pauseRecording() async {
await _asrService.pauseRecord(); await _asrService.pauseRecord();
_stopWaveformTimer(); _stopWaveformTimer();
@ -297,7 +297,7 @@ class MeetingRecordController extends GetxController
pauseTimer(); pauseTimer();
} }
/// Resumes paused recording session /// 恢复已暂停的录音会话
Future<void> _resumeRecording() async { Future<void> _resumeRecording() async {
await _asrService.resumeRecord(); await _asrService.resumeRecord();
_startWaveformTimer(); _startWaveformTimer();
@ -370,7 +370,7 @@ class MeetingRecordController extends GetxController
return (rms / 32768.0).clamp(0.0, 1.0); return (rms / 32768.0).clamp(0.0, 1.0);
} }
/// Saves recording and cleans up resources /// 保存录音并清理相关资源
Future<void> saveRecording() async { Future<void> saveRecording() async {
resetTimer(); resetTimer();
_stopWaveformTimer(); _stopWaveformTimer();
@ -380,7 +380,7 @@ class MeetingRecordController extends GetxController
if (!isRecording.value) return; if (!isRecording.value) return;
await _asrService.stopRecord(true); await _asrService.stopRecord(true);
// Rename file if title was edited // 如果标题被修改则重命名文件
if (fileName.value != newName.value) { if (fileName.value != newName.value) {
final appDir = await appDocDir; final appDir = await appDocDir;
final dir = Directory("${appDir.path}/MeetingAudio/"); final dir = Directory("${appDir.path}/MeetingAudio/");
@ -408,7 +408,7 @@ class MeetingRecordController extends GetxController
_resetWaveform(); _resetWaveform();
} }
/// Resets controller to initial state /// 将控制器重置到初始状态
void _resetToDefaultState() { void _resetToDefaultState() {
switch (audioType.value) { switch (audioType.value) {
case 0: case 0:
@ -427,7 +427,7 @@ class MeetingRecordController extends GetxController
isMarked.value = false; isMarked.value = false;
} }
/// TIMER CONTROL SECTION /// /// 计时器控制部分 ///
/// 启动定时器 /// 启动定时器
void startTimer() { void startTimer() {
@ -449,7 +449,7 @@ class MeetingRecordController extends GetxController
} }
} }
/// Pauses active timer /// 暂停当前计时器
void pauseTimer() { void pauseTimer() {
if (timerStatus.value == TimerStatus.running) { if (timerStatus.value == TimerStatus.running) {
timerStatus.value = TimerStatus.paused; timerStatus.value = TimerStatus.paused;
@ -462,7 +462,7 @@ class MeetingRecordController extends GetxController
} }
} }
/// Resets timer to initial state /// 将计时器重置到初始状态
void resetTimer() { void resetTimer() {
_timer?.cancel(); _timer?.cancel();
_timer = null; _timer = null;

26
lib/modules/meeting/views/meeting_record_view.dart

@ -13,13 +13,11 @@ class MeetingRecordView extends GetView<MeetingRecordController> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark; final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return PopScope( return WillPopScope(
onPopInvokedWithResult: (didPop, result) async { onWillPop: () async {
if (didPop) { await controller.saveTitleChange();
// 在返回时执行保存操作 await controller.saveRecording();
//controller.saveTitleChange(); return true;
//await controller.saveRecording();
}
}, },
child: Scaffold( child: Scaffold(
appBar: AppBar( appBar: AppBar(
@ -29,12 +27,7 @@ class MeetingRecordView extends GetView<MeetingRecordController> {
color: isDarkMode ? Colors.white : Colors.black, color: isDarkMode ? Colors.white : Colors.black,
size: 20.sp, size: 20.sp,
), ),
onPressed: () async { onPressed: () => Navigator.of(context).maybePop(),
// 在返回按钮点击时执行保存操作
controller.saveTitleChange();
await controller.saveRecording();
Get.back();
},
), ),
title: Obx(() { title: Obx(() {
if (controller.isEditingTitle.value) { if (controller.isEditingTitle.value) {
@ -411,7 +404,12 @@ class MeetingRecordView extends GetView<MeetingRecordController> {
} }
// 底部编辑弹窗 // 底部编辑弹窗
void _bottomSheet(BuildContext context, bool isDarkMode) { void _bottomSheet(BuildContext context, bool isDarkMode) async {
//如果当前计时器在运行,先暂停录音,避免编辑时继续录音
if (controller.timerStatus.value == TimerStatus.running) {
await controller.toggleRecording();
}
Get.bottomSheet( Get.bottomSheet(
Container( Container(
padding: EdgeInsets.only( padding: EdgeInsets.only(

Loading…
Cancel
Save