diff --git a/lib/core/utils/synchrodata.dart b/lib/core/utils/synchrodata.dart index b25638663..6571862c5 100644 --- a/lib/core/utils/synchrodata.dart +++ b/lib/core/utils/synchrodata.dart @@ -128,7 +128,6 @@ class Synchrodata { 'title': element['title'] ?? '', 'type': element['rtype'] ?? '', 'seconds': element['seconds'] ?? 0, - 'filepath': '', 'audiourl': element['audiourl'] ?? '', 'tasktype': element['tasktype'] ?? 0, 'creationtime': element['creationtime'] ?? 0, @@ -157,7 +156,10 @@ class Synchrodata { whereArgs: [element['number']], ); } else { - await txn.insert('meeting', meetingData); + await txn.insert('meeting', { + ...meetingData, + 'filepath': '', + }); await txn.insert('meetingdetails', meetingDetailsData); } if (element['original'].isNotEmpty) { diff --git a/lib/modules/meeting/controllers/meeting_details_controller.dart b/lib/modules/meeting/controllers/meeting_details_controller.dart index 8ac33d0fd..c97e7ed53 100644 --- a/lib/modules/meeting/controllers/meeting_details_controller.dart +++ b/lib/modules/meeting/controllers/meeting_details_controller.dart @@ -1,7 +1,9 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:io'; import 'package:audio_waveforms/audio_waveforms.dart'; +import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart' show rootBundle; import 'package:flutter_easyloading/flutter_easyloading.dart'; @@ -9,6 +11,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:http/http.dart' as http; +import 'package:path_provider/path_provider.dart'; import '../../../core/utils/logger.dart'; import '../../../core/utils/synchrodata.dart'; @@ -58,6 +61,9 @@ class MeetingDetailsController extends GetxController String markmapToolbarJs = ''; String saveSvgAsPngJs = ''; + RxBool isDownload = false.obs; + RxDouble downloadProgress = 0.0.obs; + String _systemPrompt = ''; String _userId = ''; @@ -205,6 +211,30 @@ class MeetingDetailsController extends GetxController await rootBundle.loadString('assets/js/saveSvgAsPng.min.js'); } + void downloadAudio() async { + if (isDownload.value) return; + isDownload.value = true; + final directory = await getApplicationDocumentsDirectory(); + final directoryDir = Directory('${directory.path}/DownloadAudio'); + if (!await directoryDir.exists()) { + await directoryDir.create(recursive: true); + } + final fileName = meetingData.value.audiourl.split('/').last; + final String filePath = '${directory.path}/DownloadAudio/$fileName'; + await Dio().download( + meetingData.value.audiourl, + filePath, + onReceiveProgress: (int received, int total) { + downloadProgress.value = total > 0 ? received / total : 0.0; + }, + ); + meetingData.value.filepath = filePath; + meetingData.refresh(); + _loadPlayerController(); + SqfliteApi.editMeetingTitle(id, {'filePath': filePath}); + isDownload.value = false; + } + void editSpeakerText() async { if (editSpeakerTextId.value != 0 && editSpeakerTextChange.isNotEmpty) { Map? foundElement = editSpeakerTextList.firstWhere( diff --git a/lib/modules/meeting/views/meeting_details_view.dart b/lib/modules/meeting/views/meeting_details_view.dart index 1217d09d2..79640b2a6 100644 --- a/lib/modules/meeting/views/meeting_details_view.dart +++ b/lib/modules/meeting/views/meeting_details_view.dart @@ -81,20 +81,50 @@ class MeetingDetailsView extends GetView { children: [ GestureDetector( onTap: () { - if (controller.isPlay.value) { - controller.playerController.pausePlayer(); + if (controller.meetingData.value.filepath.isEmpty) { + controller.downloadAudio(); } else { - controller.playerController.startPlayer(); + 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, - ), + () => !controller.isLoading.value && + controller.meetingData.value.filepath.isEmpty + ? Obx( + () => Stack( + alignment: Alignment.center, + children: [ + if (controller.isDownload.value) + SizedBox( + width: 26.w, + height: 26.w, + child: CircularProgressIndicator( + value: controller.downloadProgress.value, + valueColor: + const AlwaysStoppedAnimation( + Colors.red), + strokeWidth: 2.w, + ), + ), + Icon( + Icons.download_for_offline, + color: Colors.black, + size: 30.w, + ), + ], + ), + ) + : Icon( + controller.isPlay.value + ? Icons.pause_circle + : Icons.play_circle, + color: Colors.black, + size: 30.w, + ), ), ), 4.horizontalSpace, @@ -446,20 +476,52 @@ class MeetingDetailsView extends GetView { ), GestureDetector( onTap: () { - if (controller.isPlay.value) { - controller.playerController.pausePlayer(); + if (controller.meetingData.value.filepath.isEmpty) { + controller.downloadAudio(); } else { - controller.playerController.startPlayer(); + 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, - ), + () => !controller.isLoading.value && + controller + .meetingData.value.filepath.isEmpty + ? Obx( + () => Stack( + alignment: Alignment.center, + children: [ + if (controller.isDownload.value) + SizedBox( + width: 42.w, + height: 42.w, + child: CircularProgressIndicator( + value: controller + .downloadProgress.value, + valueColor: + const AlwaysStoppedAnimation< + Color>(Colors.red), + strokeWidth: 3.w, + ), + ), + Icon( + Icons.download_for_offline, + color: Colors.black, + size: 48.w, + ), + ], + ), + ) + : Icon( + controller.isPlay.value + ? Icons.pause_circle + : Icons.play_circle, + color: Colors.black, + size: 48.w, + ), ), ), GestureDetector(