|
|
|
@ -9,6 +9,7 @@ import 'package:path_provider/path_provider.dart'; |
|
|
|
import 'package:just_audio/just_audio.dart'; |
|
|
|
import 'package:jl_opus/jl_opus.dart'; |
|
|
|
import 'package:permission_handler/permission_handler.dart'; |
|
|
|
import 'package:share_plus/share_plus.dart'; // 添加分享插件导入 |
|
|
|
|
|
|
|
class OpusTestController extends GetxController { |
|
|
|
// 选中的文件 |
|
|
|
@ -346,6 +347,166 @@ class OpusTestController extends GetxController { |
|
|
|
// 数据大小 |
|
|
|
data.setUint32(40, pcmLength, Endian.little); |
|
|
|
} |
|
|
|
|
|
|
|
/// 删除外部文件 |
|
|
|
Future<void> deleteExternalFile(PlatformFile file) async { |
|
|
|
try { |
|
|
|
final fileToDelete = File(file.path!); |
|
|
|
if (await fileToDelete.exists()) { |
|
|
|
await fileToDelete.delete(); |
|
|
|
externalFiles.removeWhere((f) => f.path == file.path); |
|
|
|
|
|
|
|
// 如果删除的是当前选中的文件,清空选择 |
|
|
|
if (selectedFiles.isNotEmpty && selectedFiles.first.path == file.path) { |
|
|
|
selectedFiles.clear(); |
|
|
|
} |
|
|
|
|
|
|
|
statusMessage.value = '文件已删除: ${file.name}'; |
|
|
|
} else { |
|
|
|
statusMessage.value = '文件不存在: ${file.name}'; |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
statusMessage.value = '删除文件失败: $e'; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 分享外部文件 |
|
|
|
Future<void> shareExternalFile(PlatformFile file) async { |
|
|
|
try { |
|
|
|
if (file.path != null) { |
|
|
|
final fileToShare = File(file.path!); |
|
|
|
if (await fileToShare.exists()) { |
|
|
|
await Share.shareXFiles( |
|
|
|
[XFile(file.path!)], |
|
|
|
text: '分享Opus音频文件: ${file.name}', |
|
|
|
); |
|
|
|
statusMessage.value = '正在分享文件: ${file.name}'; |
|
|
|
} else { |
|
|
|
statusMessage.value = '文件不存在: ${file.name}'; |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
statusMessage.value = '分享文件失败: $e'; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 显示文件操作底部弹窗 |
|
|
|
void showFileActionSheet(BuildContext context, PlatformFile file) { |
|
|
|
showModalBottomSheet( |
|
|
|
context: context, |
|
|
|
backgroundColor: Get.isDarkMode ? Colors.grey[900] : Colors.white, |
|
|
|
shape: const RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(16)), |
|
|
|
), |
|
|
|
builder: (context) => Container( |
|
|
|
padding: const EdgeInsets.symmetric(vertical: 20), |
|
|
|
child: Column( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: [ |
|
|
|
// 文件信息 |
|
|
|
Padding( |
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
Icon( |
|
|
|
Icons.audiotrack, |
|
|
|
color: Get.isDarkMode ? Colors.white70 : Colors.black87, |
|
|
|
), |
|
|
|
const SizedBox(width: 12), |
|
|
|
Expanded( |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
file.name, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: Get.isDarkMode ? Colors.white : Colors.black, |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
Text( |
|
|
|
'${(file.size / 1024).toStringAsFixed(2)} KB', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 14, |
|
|
|
color: Get.isDarkMode |
|
|
|
? Colors.white60 |
|
|
|
: Colors.black54, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
const Divider(), |
|
|
|
// 分享选项 |
|
|
|
ListTile( |
|
|
|
leading: const Icon(Icons.share, color: Colors.blue), |
|
|
|
title: const Text('分享文件'), |
|
|
|
onTap: () { |
|
|
|
Navigator.pop(context); |
|
|
|
shareExternalFile(file); |
|
|
|
}, |
|
|
|
), |
|
|
|
// 删除选项 |
|
|
|
ListTile( |
|
|
|
leading: const Icon(Icons.delete, color: Colors.red), |
|
|
|
title: const Text('删除文件', style: TextStyle(color: Colors.red)), |
|
|
|
onTap: () { |
|
|
|
Navigator.pop(context); |
|
|
|
_showDeleteConfirmDialog(context, file); |
|
|
|
}, |
|
|
|
), |
|
|
|
// 取消选项 |
|
|
|
ListTile( |
|
|
|
leading: const Icon(Icons.cancel), |
|
|
|
title: const Text('取消'), |
|
|
|
onTap: () => Navigator.pop(context), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
/// 显示删除确认对话框 |
|
|
|
void _showDeleteConfirmDialog(BuildContext context, PlatformFile file) { |
|
|
|
showDialog( |
|
|
|
context: context, |
|
|
|
builder: (context) => AlertDialog( |
|
|
|
backgroundColor: Get.isDarkMode ? Colors.grey[900] : Colors.white, |
|
|
|
title: Text( |
|
|
|
'确认删除', |
|
|
|
style: TextStyle( |
|
|
|
color: Get.isDarkMode ? Colors.white : Colors.black, |
|
|
|
), |
|
|
|
), |
|
|
|
content: Text( |
|
|
|
'确定要删除文件 "${file.name}" 吗?\n此操作不可撤销。', |
|
|
|
style: TextStyle( |
|
|
|
color: Get.isDarkMode ? Colors.white70 : Colors.black87, |
|
|
|
), |
|
|
|
), |
|
|
|
actions: [ |
|
|
|
TextButton( |
|
|
|
onPressed: () => Navigator.pop(context), |
|
|
|
child: const Text('取消'), |
|
|
|
), |
|
|
|
TextButton( |
|
|
|
onPressed: () { |
|
|
|
Navigator.pop(context); |
|
|
|
deleteExternalFile(file); |
|
|
|
}, |
|
|
|
style: TextButton.styleFrom(foregroundColor: Colors.red), |
|
|
|
child: const Text('删除'), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// PCM音频源 |
|
|
|
|