|
|
|
@ -51,6 +51,28 @@ class _ShareBottomSheetState extends State<ShareBottomSheet> { |
|
|
|
/// 包含会议数据、转写列表、总结内容等核心数据 |
|
|
|
final _controller = Get.find<MeetingDetailsController>(); |
|
|
|
|
|
|
|
/// 获取分享弹出位置(iOS iPad需要) |
|
|
|
/// 多层兜底策略:控件真实位置 → 屏幕中心小矩形 |
|
|
|
Rect _getSharePositionOrigin() { |
|
|
|
// 检查 mounted 状态,避免 context 已释放导致崩溃 |
|
|
|
if (mounted) { |
|
|
|
try { |
|
|
|
final box = context.findRenderObject() as RenderBox?; |
|
|
|
if (box != null && box.hasSize) { |
|
|
|
return box.localToGlobal(Offset.zero) & box.size; |
|
|
|
} |
|
|
|
} catch (_) { |
|
|
|
// context 可能已失效,使用兜底方案 |
|
|
|
} |
|
|
|
} |
|
|
|
// 兜底:屏幕中心小矩形,符合iOS交互规范 |
|
|
|
return Rect.fromCenter( |
|
|
|
center: Offset(Get.width / 2, Get.height / 2), |
|
|
|
width: 1, |
|
|
|
height: 1, |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
/// ========================================================================== |
|
|
|
/// 构建UI界面 |
|
|
|
/// ========================================================================== |
|
|
|
@ -141,34 +163,37 @@ class _ShareBottomSheetState extends State<ShareBottomSheet> { |
|
|
|
// 5. 调用SharePlus分享链接 |
|
|
|
// 6. 分享成功后显示提示 |
|
|
|
onTap: () async { |
|
|
|
// 在关闭弹窗前捕获分享位置(iPad需要) |
|
|
|
final origin = _getSharePositionOrigin(); |
|
|
|
Get.back(); |
|
|
|
final GetStorage storage = GetStorage(); |
|
|
|
String token = storage.read("logintoken") ?? ''; |
|
|
|
int id = _controller.meetingData.value.id; |
|
|
|
|
|
|
|
// final thumbnail = await getAssetThumbnailFile( |
|
|
|
// 'assets/images/mine-background.png', |
|
|
|
// 'share_thumb.png', |
|
|
|
// ); |
|
|
|
|
|
|
|
// 获取动态服务器地址 |
|
|
|
final serverUrl = DioManager().baseUrl; |
|
|
|
final serverHost = serverUrl |
|
|
|
.replaceFirst('https://', '') |
|
|
|
.replaceFirst('http://', ''); |
|
|
|
|
|
|
|
final result = |
|
|
|
await SharePlus.instance.share(ShareParams( |
|
|
|
title: _controller.meetingData.value.title, |
|
|
|
subject: |
|
|
|
'Voitrans WEB,由DeepSound.Ai提供支持-实时记录会议纪要,多语言翻译。', |
|
|
|
uri: Uri.parse( |
|
|
|
'https://share.deepechomeet.com/share/$serverHost/voitrans.net/$id/$token', |
|
|
|
), |
|
|
|
//previewThumbnail: thumbnail, |
|
|
|
)); |
|
|
|
if (result.status == ShareResultStatus.success) { |
|
|
|
EasyLoading.showToast('shareSuccess'.tr); // 对应中文:分享完成 |
|
|
|
try { |
|
|
|
final GetStorage storage = GetStorage(); |
|
|
|
String token = storage.read("logintoken") ?? ''; |
|
|
|
int id = _controller.meetingData.value.id; |
|
|
|
|
|
|
|
// 获取动态服务器地址 |
|
|
|
final serverUrl = DioManager().baseUrl; |
|
|
|
final serverHost = serverUrl |
|
|
|
.replaceFirst('https://', '') |
|
|
|
.replaceFirst('http://', ''); |
|
|
|
|
|
|
|
final result = |
|
|
|
await SharePlus.instance.share(ShareParams( |
|
|
|
title: _controller.meetingData.value.title, |
|
|
|
subject: |
|
|
|
'Voitrans WEB,由DeepSound.Ai提供支持-实时记录会议纪要,多语言翻译。', |
|
|
|
uri: Uri.parse( |
|
|
|
'https://share.deepechomeet.com/share/$serverHost/voitrans.net/$id/$token', |
|
|
|
), |
|
|
|
sharePositionOrigin: origin, |
|
|
|
)); |
|
|
|
if (result.status == ShareResultStatus.success) { |
|
|
|
EasyLoading.showToast( |
|
|
|
'shareSuccess'.tr); // 对应中文:分享完成 |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
EasyLoading.showToast('shareFailed'.tr.replaceAll( |
|
|
|
'{error}', e.toString())); // 对应中文:分享失败 |
|
|
|
} |
|
|
|
}, |
|
|
|
), |
|
|
|
@ -525,12 +550,18 @@ class _ShareBottomSheetState extends State<ShareBottomSheet> { |
|
|
|
/// |
|
|
|
/// 返回值:Future<void> - 异步操作 |
|
|
|
Future<void> _share(String filepath, String title) async { |
|
|
|
final result = await SharePlus.instance.share(ShareParams( |
|
|
|
text: title, |
|
|
|
files: [XFile(filepath)], |
|
|
|
)); |
|
|
|
if (result.status == ShareResultStatus.success) { |
|
|
|
EasyLoading.showToast('shareSuccess'.tr); // 对应中文:分享完成! |
|
|
|
try { |
|
|
|
final result = await SharePlus.instance.share(ShareParams( |
|
|
|
text: title, |
|
|
|
files: [XFile(filepath)], |
|
|
|
sharePositionOrigin: _getSharePositionOrigin(), |
|
|
|
)); |
|
|
|
if (result.status == ShareResultStatus.success) { |
|
|
|
EasyLoading.showToast('shareSuccess'.tr); // 对应中文:分享完成! |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
EasyLoading.showToast( |
|
|
|
'shareFailed'.tr.replaceAll('{error}', e.toString())); // 对应中文:分享失败 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -724,23 +755,29 @@ class _ShareBottomSheetState extends State<ShareBottomSheet> { |
|
|
|
/// 返回值:Future<void> - 异步操作 |
|
|
|
Future<void> _exportMarkdownPdf() async { |
|
|
|
EasyLoading.show(status: 'exportingPDF'.tr); // 对应中文:正在导出PDF... |
|
|
|
final tempDir = await getTemporaryDirectory(); |
|
|
|
final file = File( |
|
|
|
'${tempDir.path}/${_controller.meetingData.value.title}_summary.pdf'); |
|
|
|
final List<pdf.Widget> markdownWidgets = |
|
|
|
await pdf.HTMLToPdf().convertMarkdown( |
|
|
|
_controller.meetingDetails.value.summary, |
|
|
|
fontFallback: [ |
|
|
|
pdf.Font.ttf( |
|
|
|
await rootBundle.load('assets/fonts/NotoSansSC-Regular.ttf')), |
|
|
|
], |
|
|
|
); |
|
|
|
final markdownPdf = pdf.Document(); |
|
|
|
markdownPdf.addPage(pdf.MultiPage( |
|
|
|
build: (context) => markdownWidgets, |
|
|
|
)); |
|
|
|
await file.writeAsBytes(await markdownPdf.save()); |
|
|
|
await _share(file.path, 'exportSummary'.tr); // 对应中文:分享会议总结 |
|
|
|
EasyLoading.dismiss(); |
|
|
|
try { |
|
|
|
final tempDir = await getTemporaryDirectory(); |
|
|
|
final file = File( |
|
|
|
'${tempDir.path}/${_controller.meetingData.value.title}_summary.pdf'); |
|
|
|
final List<pdf.Widget> markdownWidgets = |
|
|
|
await pdf.HTMLToPdf().convertMarkdown( |
|
|
|
_controller.meetingDetails.value.summary, |
|
|
|
fontFallback: [ |
|
|
|
pdf.Font.ttf( |
|
|
|
await rootBundle.load('assets/fonts/NotoSansSC-Regular.ttf')), |
|
|
|
], |
|
|
|
); |
|
|
|
final markdownPdf = pdf.Document(); |
|
|
|
markdownPdf.addPage(pdf.MultiPage( |
|
|
|
build: (context) => markdownWidgets, |
|
|
|
)); |
|
|
|
await file.writeAsBytes(await markdownPdf.save()); |
|
|
|
await _share(file.path, 'exportSummary'.tr); // 对应中文:分享会议总结 |
|
|
|
} catch (e) { |
|
|
|
EasyLoading.showToast( |
|
|
|
'shareFailed'.tr.replaceAll('{error}', e.toString())); // 对应中文:分享失败 |
|
|
|
} finally { |
|
|
|
EasyLoading.dismiss(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|