From a6b17f2c053cce1c965fc2e1b94b02135274658a Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Mon, 14 Oct 2024 13:26:30 +0800 Subject: [PATCH] :sparkles: Multi-platform support share as image --- assets/locales/en_us.json | 2 +- assets/locales/zh_cn.json | 2 +- ios/Podfile.lock | 6 ++ lib/widgets/posts/post_action.dart | 55 ++++++++++++------- linux/flutter/generated_plugin_registrant.cc | 4 ++ linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + macos/Runner/DebugProfile.entitlements | 2 + macos/Runner/Info.plist | 4 ++ macos/Runner/Release.entitlements | 2 + pubspec.lock | 8 +++ pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 14 files changed, 70 insertions(+), 23 deletions(-) diff --git a/assets/locales/en_us.json b/assets/locales/en_us.json index 54e865d..3735921 100644 --- a/assets/locales/en_us.json +++ b/assets/locales/en_us.json @@ -367,7 +367,7 @@ "bsRegisteringPushNotify": "Enabling Push Notifications", "bsDismissibleErrorHint": "Click anywhere to ignore this error", "postShareContent": "@content\n\n@username on the Solar Network\nCheck it out: @link", - "postShareSubject": "@username posted a post on the Solar Network", + "postShareSubject": "@title by @username on Solar Network", "themeColor": "Global Theme Color", "themeColorRed": "Modern Red", "themeColorBlue": "Classic Blue", diff --git a/assets/locales/zh_cn.json b/assets/locales/zh_cn.json index 4d0f5b4..5083ef5 100644 --- a/assets/locales/zh_cn.json +++ b/assets/locales/zh_cn.json @@ -363,7 +363,7 @@ "bsRegisteringPushNotify": "正在启用推送通知", "bsDismissibleErrorHint": "点击任意地方忽略此错误", "postShareContent": "@content\n\n@username 在 Solar Network\n原帖地址:@link", - "postShareSubject": "@username 在 Solar Network 上发布了一篇帖子", + "postShareSubject": "@username 在 Solar Network 发表的 @title", "themeColor": "全局主题色", "themeColorRed": "现代红", "themeColorBlue": "经典蓝", diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 5061490..aa157a1 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -38,6 +38,8 @@ PODS: - file_picker (0.0.1): - DKImagePickerController/PhotoGallery - Flutter + - file_saver (0.0.1): + - Flutter - Firebase/Analytics (11.2.0): - Firebase/Core - Firebase/Core (11.2.0): @@ -308,6 +310,7 @@ DEPENDENCIES: - connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - file_picker (from `.symlinks/plugins/file_picker/ios`) + - file_saver (from `.symlinks/plugins/file_saver/ios`) - firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`) @@ -383,6 +386,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/device_info_plus/ios" file_picker: :path: ".symlinks/plugins/file_picker/ios" + file_saver: + :path: ".symlinks/plugins/file_saver/ios" firebase_analytics: :path: ".symlinks/plugins/firebase_analytics/ios" firebase_core: @@ -462,6 +467,7 @@ SPEC CHECKSUMS: DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655 + file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808 Firebase: 98e6bf5278170668a7983e12971a66b2cd57fc8c firebase_analytics: fbc57838bdb94eef1e0ff504f127d974ff2981ad firebase_core: 2bedc3136ec7c7b8561c6123ed0239387b53f2af diff --git a/lib/widgets/posts/post_action.dart b/lib/widgets/posts/post_action.dart index ad3e545..473bde9 100644 --- a/lib/widgets/posts/post_action.dart +++ b/lib/widgets/posts/post_action.dart @@ -1,11 +1,14 @@ import 'dart:io'; import 'dart:math'; +import 'package:file_saver/file_saver.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; +import 'package:intl/intl.dart'; +import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; import 'package:screenshot/screenshot.dart'; import 'package:share_plus/share_plus.dart'; @@ -73,7 +76,8 @@ class _PostActionState extends State { 'link': 'https://solsynth.dev/posts/$id', }), subject: 'postShareSubject'.trParams({ - 'username': widget.item.author.nick, + 'username': '@${widget.item.author.name}', + 'title': widget.item.body['title'] ?? '#${widget.item.id}', }), sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, ); @@ -104,27 +108,37 @@ class _PostActionState extends State { pixelRatio: 2, constraints: BoxConstraints( minWidth: 480, - maxWidth: hasMultipleAttachment ? 480 : 640, + maxWidth: hasMultipleAttachment ? 640 : 480, minHeight: 640, maxHeight: double.infinity, ), ); final directory = await getApplicationDocumentsDirectory(); final imageFile = await File( - '${directory.path}/temporary_share_image.png', + '${directory.path}/share_image_${DateFormat('yyyy-MM-dd-HH-mm-ss').format(DateTime.now())}.png', ).create(); await imageFile.writeAsBytes(image); - final box = context.findRenderObject() as RenderBox?; + if (PlatformInfo.isAndroid || PlatformInfo.isIOS) { + final box = context.findRenderObject() as RenderBox?; - final file = XFile(imageFile.path); - await Share.shareXFiles( - [file], - subject: 'postShareSubject'.trParams({ - 'username': widget.item.author.nick, - }), - sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, - ); + final file = XFile(imageFile.path); + await Share.shareXFiles( + [file], + subject: 'postShareSubject'.trParams({ + 'username': '@${widget.item.author.name}', + 'title': widget.item.body['title'] ?? '#${widget.item.id}', + }), + sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, + ); + } else { + await FileSaver.instance.saveAs( + name: path.basename(imageFile.path), + ext: path.extension(imageFile.path), + mimeType: MimeType.png, + file: imageFile, + ); + } await imageFile.delete(); } @@ -192,15 +206,14 @@ class _PostActionState extends State { Navigator.pop(context); }, ), - if (PlatformInfo.isIOS || PlatformInfo.isAndroid) - IconButton( - icon: const Icon(Icons.image), - tooltip: 'shareImage'.tr, - onPressed: () async { - await _shareImage(); - Navigator.pop(context); - }, - ), + IconButton( + icon: const Icon(Icons.image), + tooltip: 'shareImage'.tr, + onPressed: () async { + await _shareImage(); + Navigator.pop(context); + }, + ), ], ), onTap: () async { diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index d986dc0..995c4b3 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,6 +7,7 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include @@ -22,6 +23,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) desktop_drop_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin"); desktop_drop_plugin_register_with_registrar(desktop_drop_registrar); + g_autoptr(FlPluginRegistrar) file_saver_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSaverPlugin"); + file_saver_plugin_register_with_registrar(file_saver_registrar); g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); file_selector_plugin_register_with_registrar(file_selector_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 044f50f..cf8c728 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_drop + file_saver file_selector_linux flutter_acrylic flutter_secure_storage_linux diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index b83c970..8b8f8c6 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,6 +8,7 @@ import Foundation import connectivity_plus import desktop_drop import device_info_plus +import file_saver import file_selector_macos import firebase_analytics import firebase_core @@ -39,6 +40,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + FileSaverPlugin.register(with: registry.registrar(forPlugin: "FileSaverPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements index da39c2f..02fcc46 100644 --- a/macos/Runner/DebugProfile.entitlements +++ b/macos/Runner/DebugProfile.entitlements @@ -14,6 +14,8 @@ com.apple.security.device.camera + com.apple.security.files.downloads.read-write + com.apple.security.files.user-selected.read-only com.apple.security.network.client diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist index bc53a67..67a7fcc 100644 --- a/macos/Runner/Info.plist +++ b/macos/Runner/Info.plist @@ -62,5 +62,9 @@ Allow you record audio for your message or post NSPhotoLibraryUsageDescription Allow you add photo to your message or post + UIFileSharingEnabled + + LSSupportsOpeningDocumentsInPlace + diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements index 4235e02..9ca9e76 100644 --- a/macos/Runner/Release.entitlements +++ b/macos/Runner/Release.entitlements @@ -12,6 +12,8 @@ com.apple.security.device.camera + com.apple.security.files.downloads.read-write + com.apple.security.files.user-selected.read-only com.apple.security.network.client diff --git a/pubspec.lock b/pubspec.lock index ac45a9b..37276f8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -454,6 +454,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.1.2" + file_saver: + dependency: "direct main" + description: + name: file_saver + sha256: "017a127de686af2d2fbbd64afea97052d95f2a0f87d19d25b87e097407bf9c1e" + url: "https://pub.dev" + source: hosted + version: "0.2.14" file_selector_linux: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index b1021bd..a050e0b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -88,6 +88,7 @@ dependencies: screenshot: ^3.0.0 qr_flutter: ^4.1.0 flutter_resizable_container: ^3.0.0 + file_saver: ^0.2.14 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index e3b8ac0..0a3a2f0 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -31,6 +32,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); DesktopDropPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("DesktopDropPlugin")); + FileSaverPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSaverPlugin")); FileSelectorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSelectorWindows")); FirebaseCorePluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index c5936fd..365985c 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST connectivity_plus desktop_drop + file_saver file_selector_windows firebase_core flutter_acrylic