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

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

@ -13,13 +13,11 @@ class MeetingRecordView extends GetView<MeetingRecordController> {
Widget build(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return PopScope(
onPopInvokedWithResult: (didPop, result) async {
if (didPop) {
// 在返回时执行保存操作
//controller.saveTitleChange();
//await controller.saveRecording();
}
return WillPopScope(
onWillPop: () async {
await controller.saveTitleChange();
await controller.saveRecording();
return true;
},
child: Scaffold(
appBar: AppBar(
@ -29,12 +27,7 @@ class MeetingRecordView extends GetView<MeetingRecordController> {
color: isDarkMode ? Colors.white : Colors.black,
size: 20.sp,
),
onPressed: () async {
// 在返回按钮点击时执行保存操作
controller.saveTitleChange();
await controller.saveRecording();
Get.back();
},
onPressed: () => Navigator.of(context).maybePop(),
),
title: Obx(() {
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(
Container(
padding: EdgeInsets.only(

Loading…
Cancel
Save