From 5bacce50afc30f21e0c6cc74c1cde375d8a8137f Mon Sep 17 00:00:00 2001 From: lml Date: Tue, 17 Mar 2026 21:54:56 +0800 Subject: [PATCH] feat: Add share_plus and url_launcher support for file sharing and launching URLs --- ios/Podfile.lock | 6 ++ lib/ui/home_page.dart | 71 +++++++++++++------ linux/flutter/generated_plugin_registrant.cc | 4 ++ linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 48 +++++++++++++ pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 6 ++ windows/flutter/generated_plugins.cmake | 2 + 9 files changed, 120 insertions(+), 21 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index c06115c..fa00fee 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -42,6 +42,8 @@ PODS: - SDWebImage (5.21.3): - SDWebImage/Core (= 5.21.3) - SDWebImage/Core (5.21.3) + - share_plus (0.0.1): + - Flutter - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS @@ -53,6 +55,7 @@ DEPENDENCIES: - ffmpeg_kit_flutter_new_min (from `.symlinks/plugins/ffmpeg_kit_flutter_new_min/ios`) - file_picker (from `.symlinks/plugins/file_picker/ios`) - Flutter (from `Flutter`) + - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - whisper_ggml_plus (from `.symlinks/plugins/whisper_ggml_plus/ios`) @@ -70,6 +73,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/file_picker/ios" Flutter: :path: Flutter + share_plus: + :path: ".symlinks/plugins/share_plus/ios" shared_preferences_foundation: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" whisper_ggml_plus: @@ -82,6 +87,7 @@ SPEC CHECKSUMS: file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a + share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 whisper_ggml_plus: 03dbc05ca07acd625beec982db80b41dae2fe005 diff --git a/lib/ui/home_page.dart b/lib/ui/home_page.dart index 132ccc5..e8d9976 100644 --- a/lib/ui/home_page.dart +++ b/lib/ui/home_page.dart @@ -3,6 +3,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:file_picker/file_picker.dart'; import 'package:path/path.dart' as p; +import 'package:path_provider/path_provider.dart'; +import 'package:share_plus/share_plus.dart'; import '../services/settings_service.dart'; import '../services/translation/translation_service.dart'; import '../blocs/transcription/transcription_bloc.dart'; @@ -536,33 +538,60 @@ class _HomePageState extends State { bool bilingual, ) async { final l10n = AppLocalizations.of(context)!; - final srtContent = SrtParser.generate( - segments.cast(), - useTranslation: translatedOnly, - bilingual: bilingual, - ); + try { + final srtContent = SrtParser.generate( + segments.cast(), + useTranslation: translatedOnly, + bilingual: bilingual, + ); - final transcriptionState = context.read().state; - final selectedFileName = _getFileName(transcriptionState); - final baseName = (selectedFileName != null && selectedFileName.isNotEmpty) - ? p.basenameWithoutExtension(selectedFileName) - : 'subtitles'; - final exportFileName = '$baseName.srt'; + final transcriptionState = context.read().state; + final selectedFileName = _getFileName(transcriptionState); + final baseName = (selectedFileName != null && selectedFileName.isNotEmpty) + ? p.basenameWithoutExtension(selectedFileName) + : 'subtitles'; + final exportFileName = '$baseName.srt'; - final outputPath = await FilePicker.platform.saveFile( - dialogTitle: l10n.exportSrt, - fileName: exportFileName, - type: FileType.custom, - allowedExtensions: ['srt'], - ); + // `saveFile` is desktop-friendly; mobile should use system share sheet. + if (Platform.isAndroid || Platform.isIOS) { + final tempDir = await getTemporaryDirectory(); + final outputPath = p.join(tempDir.path, exportFileName); + await File(outputPath).writeAsString(srtContent); - if (outputPath != null) { - await File(outputPath).writeAsString(srtContent); + await SharePlus.instance.share( + ShareParams( + files: [XFile(outputPath, mimeType: 'application/x-subrip')], + subject: exportFileName, + text: exportFileName, + ), + ); + return; + } + + final outputPath = await FilePicker.platform.saveFile( + dialogTitle: l10n.exportSrt, + fileName: exportFileName, + type: FileType.custom, + allowedExtensions: ['srt'], + ); + + if (outputPath != null) { + await File(outputPath).writeAsString(srtContent); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(l10n.exportedTo(outputPath)), + backgroundColor: Colors.green.shade700, + ), + ); + } + } + } catch (e) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text(l10n.exportedTo(outputPath)), - backgroundColor: Colors.green.shade700, + content: Text('Export failed: $e'), + backgroundColor: Colors.red.shade700, ), ); } diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 1859a62..5ccf7d4 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,9 +7,13 @@ #include "generated_plugin_registrant.h" #include +#include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) ffmpeg_kit_extended_flutter_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FfmpegKitExtendedFlutterPlugin"); ffmpeg_kit_extended_flutter_plugin_register_with_registrar(ffmpeg_kit_extended_flutter_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 68d484c..85589cc 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ffmpeg_kit_extended_flutter + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 3da136e..33479bf 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,10 +7,12 @@ import Foundation import ffmpeg_kit_flutter_new_min import file_picker +import share_plus import shared_preferences_foundation func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FFmpegKitFlutterPlugin.register(with: registry.registrar(forPlugin: "FFmpegKitFlutterPlugin")) FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) + SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index ad5168e..2796827 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -614,6 +614,22 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.2.1" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: "14c8860d4de93d3a7e53af51bff479598c4e999605290756bbbe45cf65b37840" + url: "https://pub.flutter-io.cn" + source: hosted + version: "12.0.1" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a" + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.1.0" shared_preferences: dependency: "direct main" description: @@ -811,6 +827,38 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.3.1" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.2.2" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.4.2" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.5" uuid: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 395368f..c9c46d3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,6 +31,7 @@ dependencies: file_picker: ^8.0.3 path_provider: ^2.1.3 path: ^1.9.0 + share_plus: ^12.0.1 http: ^1.2.1 # Networking & Storage diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 4055549..61594ae 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,8 +7,14 @@ #include "generated_plugin_registrant.h" #include +#include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { FfmpegKitExtendedFlutterPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FfmpegKitExtendedFlutterPlugin")); + SharePlusWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index ec1064b..53ff5ff 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,8 @@ list(APPEND FLUTTER_PLUGIN_LIST ffmpeg_kit_extended_flutter + share_plus + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST