diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 42dcf1e6e..355f8a609 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -464,6 +464,22 @@ class ChatController extends State { ); } + void sendImageFromClipBoard(Uint8List? image) async { + await showDialog( + context: context, + useRootNavigator: false, + builder: (c) => SendFileDialog( + files: [ + MatrixFile( + bytes: image!, + name: "image from Clipboard", + ).detectFileType, + ], + room: room, + ), + ); + } + void sendImageAction() async { final result = await FilePicker.platform.pickFiles( type: FileType.image, diff --git a/lib/pages/chat/chat_input_row.dart b/lib/pages/chat/chat_input_row.dart index 2c389d52a..30c38ca59 100644 --- a/lib/pages/chat/chat_input_row.dart +++ b/lib/pages/chat/chat_input_row.dart @@ -235,6 +235,7 @@ class ChatInputRow extends StatelessWidget { textInputAction: AppConfig.sendOnEnter ? TextInputAction.send : null, onSubmitted: controller.onInputBarSubmitted, + onSubmitImage: controller.sendImageFromClipBoard, focusNode: controller.inputFocus, controller: controller.sendController, decoration: InputDecoration( diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index de31e7ea0..d6f6794b4 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -5,6 +5,7 @@ import 'package:emojis/emoji.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart'; import 'package:matrix/matrix.dart'; +import 'package:pasteboard/pasteboard.dart'; import 'package:slugify/slugify.dart'; import 'package:fluffychat/config/app_config.dart'; @@ -21,6 +22,7 @@ class InputBar extends StatelessWidget { final TextInputType? keyboardType; final TextInputAction? textInputAction; final ValueChanged? onSubmitted; + final ValueChanged? onSubmitImage; final FocusNode? focusNode; final TextEditingController? controller; final InputDecoration? decoration; @@ -34,6 +36,7 @@ class InputBar extends StatelessWidget { this.maxLines, this.keyboardType, this.onSubmitted, + this.onSubmitImage, this.focusNode, this.controller, this.decoration, @@ -401,6 +404,10 @@ class InputBar extends StatelessWidget { LogicalKeySet(LogicalKeyboardKey.shift, LogicalKeyboardKey.enter): NewLineIntent(), LogicalKeySet(LogicalKeyboardKey.enter): SubmitLineIntent(), + LogicalKeySet( + LogicalKeyboardKey.controlLeft, + LogicalKeyboardKey.keyM, + ): PasteLineIntent() }, child: Actions( actions: !useShortCuts @@ -427,6 +434,16 @@ class InputBar extends StatelessWidget { return null; }, ), + PasteLineIntent: CallbackAction( + onInvoke: (i) async { + final image = await Pasteboard.image; + if (image != null) { + onSubmitImage!(image); + return null; + } + return null; + }, + ) }, child: TypeAheadField>( direction: AxisDirection.up, @@ -476,3 +493,5 @@ class InputBar extends StatelessWidget { class NewLineIntent extends Intent {} class SubmitLineIntent extends Intent {} + +class PasteLineIntent extends Intent {} diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 968d817e7..710031b18 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) handy_window_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "HandyWindowPlugin"); handy_window_plugin_register_with_registrar(handy_window_registrar); + g_autoptr(FlPluginRegistrar) pasteboard_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "PasteboardPlugin"); + pasteboard_plugin_register_with_registrar(pasteboard_registrar); g_autoptr(FlPluginRegistrar) record_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "RecordLinuxPlugin"); record_linux_plugin_register_with_registrar(record_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 0a4dbb69c..88981ef6f 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST flutter_secure_storage_linux flutter_webrtc handy_window + pasteboard record_linux url_launcher_linux window_to_front diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 586f80759..f6375bfec 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -23,6 +23,7 @@ import just_audio import macos_ui import macos_window_utils import package_info_plus +import pasteboard import path_provider_foundation import record_macos import share_plus @@ -53,6 +54,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { MacOSUiPlugin.register(with: registry.registrar(forPlugin: "MacOSUiPlugin")) MacOSWindowUtilsPlugin.register(with: registry.registrar(forPlugin: "MacOSWindowUtilsPlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) + PasteboardPlugin.register(with: registry.registrar(forPlugin: "PasteboardPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) RecordMacosPlugin.register(with: registry.registrar(forPlugin: "RecordMacosPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 2dbffd201..63249360f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1261,6 +1261,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + pasteboard: + dependency: "direct main" + description: + name: pasteboard + sha256: "1c8b6a8b3f1d12e55d4e9404433cda1b4abe66db6b17bc2d2fb5965772c04674" + url: "https://pub.dev" + source: hosted + version: "0.2.0" path: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2b08a0948..174542d4b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -66,6 +66,7 @@ dependencies: matrix_homeserver_recommendations: ^0.3.0 native_imaging: ^0.1.0 package_info_plus: ^4.0.0 + pasteboard: ^0.2.0 path_provider: ^2.0.9 permission_handler: ^10.0.0 pin_code_text_field: ^1.8.0 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 69b12dde8..9a0f2d89a 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); FlutterWebRTCPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterWebRTCPlugin")); + PasteboardPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PasteboardPlugin")); PermissionHandlerWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); RecordWindowsPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 39f5851da..2d6a562c7 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST file_selector_windows flutter_secure_storage_windows flutter_webrtc + pasteboard permission_handler_windows record_windows share_plus