|
|
|
@ -1,18 +1,11 @@ |
|
|
|
import 'dart:convert'; |
|
|
|
import 'dart:io'; |
|
|
|
|
|
|
|
import 'package:file_picker/file_picker.dart'; |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:audio_waveforms/audio_waveforms.dart'; |
|
|
|
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
|
|
|
import 'package:get/get.dart'; |
|
|
|
import 'package:http/http.dart' as http; |
|
|
|
import 'package:just_audio/just_audio.dart'; |
|
|
|
import 'package:path_provider/path_provider.dart'; |
|
|
|
import 'package:permission_handler/permission_handler.dart'; |
|
|
|
|
|
|
|
import '../../../core/utils/logger.dart'; |
|
|
|
import '../../../core/utils/upload_oss.dart'; |
|
|
|
import '../../../data/services/db/sqflite_api.dart'; |
|
|
|
import '../../../core/utils/permission_util.dart'; |
|
|
|
|
|
|
|
import 'package:share_plus/share_plus.dart'; |
|
|
|
@ -28,14 +21,21 @@ class TranslationListController extends GetxController { |
|
|
|
final appDocDir = getApplicationDocumentsDirectory(); |
|
|
|
// final directory = Directory( |
|
|
|
// '/storage/emulated/0/Android/data/com.yunqiinnovation.deepsound/files'); |
|
|
|
List<FileSystemEntity> files = []; |
|
|
|
TextEditingController titleController = TextEditingController(); // 录音标题 |
|
|
|
final RxList<FileSystemEntity> files = <FileSystemEntity>[].obs; |
|
|
|
|
|
|
|
RxList dataList = [].obs; |
|
|
|
|
|
|
|
List dataListTask = []; |
|
|
|
bool isDisposed = false; |
|
|
|
|
|
|
|
// 添加音频播放器 |
|
|
|
// 添加音频时长缓存 |
|
|
|
final Map<String, Duration> audioDurations = {}; |
|
|
|
// 播放状态 |
|
|
|
final RxBool isPlaying = false.obs; |
|
|
|
// 当前播放的文件路径 |
|
|
|
final RxString currentPlayingPath = ''.obs; |
|
|
|
final AudioPlayer audioPlayer = AudioPlayer(); |
|
|
|
final PlayerController playerController = PlayerController(); |
|
|
|
@override |
|
|
|
void onInit() { |
|
|
|
super.onInit(); |
|
|
|
@ -49,16 +49,47 @@ class TranslationListController extends GetxController { |
|
|
|
// _getDataList(); |
|
|
|
// addMeetingAudio(); |
|
|
|
loadTranslatAudio(); |
|
|
|
// 监听播放状态变化 |
|
|
|
audioPlayer.playerStateStream.listen((playerState) { |
|
|
|
isPlaying.value = playerState.playing; |
|
|
|
if (playerState.processingState == ProcessingState.completed) { |
|
|
|
// 播放完成后重置状态 |
|
|
|
currentPlayingPath.value = ''; |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
void onClose() { |
|
|
|
titleController.dispose(); |
|
|
|
|
|
|
|
isDisposed = true; |
|
|
|
audioPlayer.dispose(); // 释放播放器资源 |
|
|
|
super.onClose(); |
|
|
|
} |
|
|
|
|
|
|
|
// 播放/暂停音频 |
|
|
|
void togglePlay(FileSystemEntity file) async { |
|
|
|
final filePath = file.path; |
|
|
|
|
|
|
|
if (currentPlayingPath.value == filePath) { |
|
|
|
// 同一个文件:切换播放/暂停 |
|
|
|
if (isPlaying.value) { |
|
|
|
await audioPlayer.pause(); |
|
|
|
} else { |
|
|
|
await audioPlayer.play(); |
|
|
|
} |
|
|
|
} else { |
|
|
|
// 新文件:停止当前播放,开始新文件 |
|
|
|
currentPlayingPath.value = filePath; |
|
|
|
try { |
|
|
|
await audioPlayer.stop(); |
|
|
|
await audioPlayer.setFilePath(filePath); |
|
|
|
await audioPlayer.play(); |
|
|
|
} catch (e) { |
|
|
|
print("播放失败: $e"); |
|
|
|
currentPlayingPath.value = ''; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 请求存储权限 |
|
|
|
void _requestStoragePermission() async { |
|
|
|
// final BuildContext context = Get.overlayContext!; |
|
|
|
@ -81,16 +112,22 @@ class TranslationListController extends GetxController { |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
void loadTranslatopus() async { |
|
|
|
final appDir = await appDocDir; // 先 await 获取目录 |
|
|
|
final dir = Directory("${appDir.path}/OpusAudio"); |
|
|
|
|
|
|
|
print("appDocDir=${dir?.path}"); |
|
|
|
// 添加方法:获取音频时长 |
|
|
|
Future<Duration> getAudioDuration(String filePath) async { |
|
|
|
if (audioDurations.containsKey(filePath)) { |
|
|
|
return audioDurations[filePath]!; |
|
|
|
} |
|
|
|
|
|
|
|
files = dir |
|
|
|
.listSync() |
|
|
|
.where((f) => f is File && (f.path.endsWith('.opus'))) |
|
|
|
.toList(); |
|
|
|
try { |
|
|
|
final audioPlayer = AudioPlayer(); |
|
|
|
await audioPlayer.setFilePath(filePath); |
|
|
|
final duration = await audioPlayer.duration ?? Duration.zero; |
|
|
|
audioDurations[filePath] = duration; |
|
|
|
return duration; |
|
|
|
} catch (e) { |
|
|
|
print("获取音频时长失败: $e"); |
|
|
|
return Duration.zero; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void loadTranslatAudio() async { |
|
|
|
@ -102,12 +139,12 @@ class TranslationListController extends GetxController { |
|
|
|
// Create directory if it doesn't exist |
|
|
|
if (!await dir.exists()) { |
|
|
|
await dir.create(recursive: true); // Create directory tree if needed |
|
|
|
files = []; // No files exist in new directory |
|
|
|
files.value = []; // No files exist in new directory |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Directory exis |
|
|
|
files = dir |
|
|
|
files.value = dir |
|
|
|
.listSync() |
|
|
|
.where((f) => |
|
|
|
f is File && |
|
|
|
@ -120,7 +157,7 @@ class TranslationListController extends GetxController { |
|
|
|
.toList(); |
|
|
|
} catch (e) { |
|
|
|
print("Error loading files: $e"); |
|
|
|
files = []; // Return empty list on error |
|
|
|
files.value = []; // Return empty list on error |
|
|
|
} |
|
|
|
} |
|
|
|
// 导入音频文件 |
|
|
|
@ -144,48 +181,4 @@ class TranslationListController extends GetxController { |
|
|
|
EasyLoading.showToast('分享失败: ${e.toString()}'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Future<String> _saveFile(PlatformFile file) async { |
|
|
|
final directory = await getApplicationDocumentsDirectory(); |
|
|
|
final directoryDir = Directory('${directory.path}/ExternalAudio'); |
|
|
|
if (!await directoryDir.exists()) { |
|
|
|
await directoryDir.create(recursive: true); |
|
|
|
} |
|
|
|
final String filePath = '${directory.path}/ExternalAudio/${file.name}'; |
|
|
|
final File localFile = File(filePath); |
|
|
|
await localFile.writeAsBytes(file.bytes!); |
|
|
|
return filePath; |
|
|
|
} |
|
|
|
|
|
|
|
// 修改标题 |
|
|
|
void editMeetingTitle(int id, String title) async { |
|
|
|
if (title.isNotEmpty) { |
|
|
|
SqfliteApi.editMeetingTitle(id, {'title': title}); |
|
|
|
int index = dataList.indexWhere((item) => item['id'] == id); |
|
|
|
if (index != -1) { |
|
|
|
final dataMap = Map<String, dynamic>.from(dataList[index]); |
|
|
|
dataMap['title'] = title; |
|
|
|
dataList[index] = dataMap; |
|
|
|
} |
|
|
|
} |
|
|
|
Get.back(); |
|
|
|
} |
|
|
|
|
|
|
|
// 删除数据 |
|
|
|
void deleteMeeting(int id, String filepath) async { |
|
|
|
dataList.removeWhere((item) => item['id'] == id); |
|
|
|
// 删除数据库中的记录 |
|
|
|
SqfliteApi.deleteMeeting(id); |
|
|
|
_deleteFile(filepath); |
|
|
|
addQuantity--; |
|
|
|
} |
|
|
|
|
|
|
|
// 删除文件 |
|
|
|
Future<void> _deleteFile(String filepath) async { |
|
|
|
File file = File(filepath); |
|
|
|
bool fileExists = await file.exists(); |
|
|
|
if (fileExists) { |
|
|
|
await file.delete(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|