From 316ad3a65d76bb11e993ec263afa83317cc14949 Mon Sep 17 00:00:00 2001 From: Terence ZAFINDRATAFA Date: Mon, 6 May 2024 22:39:47 +0200 Subject: [PATCH] TW-1699: picture copy paste fixed --- lib/pages/chat/chat_view.dart | 201 ++++++++++-------- .../mixins/handle_clipboard_action_mixin.dart | 18 +- .../mixins/paste_image_mixin.dart | 4 +- lib/utils/shortcuts.dart | 4 + 4 files changed, 130 insertions(+), 97 deletions(-) diff --git a/lib/pages/chat/chat_view.dart b/lib/pages/chat/chat_view.dart index d2b0b17b91..d21cd91f53 100644 --- a/lib/pages/chat/chat_view.dart +++ b/lib/pages/chat/chat_view.dart @@ -6,10 +6,12 @@ import 'package:fluffychat/pages/chat/chat_view_body.dart'; import 'package:fluffychat/pages/chat/chat_view_style.dart'; import 'package:fluffychat/pages/chat/events/message_content_mixin.dart'; import 'package:fluffychat/resource/image_paths.dart'; +import 'package:fluffychat/utils/shortcuts.dart'; import 'package:fluffychat/utils/stream_extension.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/twake_components/twake_icon_button.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:linagora_design_flutter/colors/linagora_state_layer.dart'; import 'package:linagora_design_flutter/colors/linagora_sys_colors.dart'; @@ -103,105 +105,120 @@ class ChatView extends StatelessWidget with MessageContentMixin { return Focus( focusNode: controller.chatFocusNode, - child: GestureDetector( - onTapDown: (_) => controller.setReadMarker(), - behavior: HitTestBehavior.opaque, - child: StreamBuilder( - stream: controller.room!.onUpdate.stream - .rateLimit(const Duration(seconds: 1)), - builder: (context, snapshot) => FutureBuilder( - future: controller.loadTimelineFuture, - builder: (BuildContext context, snapshot) { - return Scaffold( - backgroundColor: LinagoraSysColors.material().onPrimary, - appBar: AppBar( - backgroundColor: LinagoraSysColors.material().onPrimary, - automaticallyImplyLeading: false, - toolbarHeight: AppConfig.toolbarHeight(context), - title: Padding( - padding: ChatViewStyle.paddingLeading(context), - child: Row( - children: [ - _buildLeading(context), - Expanded( - child: ChatAppBarTitle( - selectedEvents: controller.selectedEvents, - room: controller.room, - isArchived: controller.isArchived, - sendController: controller.sendController, - connectivityResultStream: controller - .networkConnectionService - .connectivity - .onConnectivityChanged, - actions: _appBarActions(context), - onPushDetails: controller.onPushDetails, - roomName: controller.roomName, - ), - ), - ], - ), - ), - actions: [ - if (!controller.selectMode) - Padding( - padding: ChatViewStyle.paddingTrailing(context), + child: Shortcuts( + shortcuts: { + LogicalKeySet( + LogicalKeyboardKey.control, + LogicalKeyboardKey.keyV, + ): const PasteIntent(), + }, + child: Actions( + actions: >{ + PasteIntent: CallbackAction( + onInvoke: (intent) => controller.paste(), + ), + }, + child: GestureDetector( + onTapDown: (_) => controller.setReadMarker(), + behavior: HitTestBehavior.opaque, + child: StreamBuilder( + stream: controller.room!.onUpdate.stream + .rateLimit(const Duration(seconds: 1)), + builder: (context, snapshot) => FutureBuilder( + future: controller.loadTimelineFuture, + builder: (BuildContext context, snapshot) { + return Scaffold( + backgroundColor: LinagoraSysColors.material().onPrimary, + appBar: AppBar( + backgroundColor: LinagoraSysColors.material().onPrimary, + automaticallyImplyLeading: false, + toolbarHeight: AppConfig.toolbarHeight(context), + title: Padding( + padding: ChatViewStyle.paddingLeading(context), child: Row( children: [ - IconButton( - hoverColor: Colors.transparent, - splashColor: Colors.transparent, - highlightColor: Colors.transparent, - onPressed: controller.toggleSearch, - icon: const Icon(Icons.search), - ), - if (!controller.room!.isDirectChat) - Builder( - builder: (context) => TwakeIconButton( - icon: Icons.more_vert, - tooltip: L10n.of(context)!.more, - onTapDown: (tapDownDetails) => - controller.handleAppbarMenuAction( - context, - tapDownDetails, - ), - preferBelow: false, - ), + _buildLeading(context), + Expanded( + child: ChatAppBarTitle( + selectedEvents: controller.selectedEvents, + room: controller.room, + isArchived: controller.isArchived, + sendController: controller.sendController, + connectivityResultStream: controller + .networkConnectionService + .connectivity + .onConnectivityChanged, + actions: _appBarActions(context), + onPushDetails: controller.onPushDetails, + roomName: controller.roomName, ), + ), ], ), ), - ], - bottom: PreferredSize( - preferredSize: const Size(double.infinity, 1), - child: Container( - color: LinagoraStateLayer( - LinagoraSysColors.material().surfaceTint, - ).opacityLayer1, - height: 1, - ), - ), - ), - floatingActionButton: ValueListenableBuilder( - valueListenable: controller.showScrollDownButtonNotifier, - builder: (context, showScrollDownButton, _) { - if (showScrollDownButton && - controller.selectedEvents.isEmpty && - controller.replyEventNotifier.value == null) { - return Padding( - padding: const EdgeInsets.only(bottom: 56.0), - child: FloatingActionButton( - onPressed: controller.scrollDown, - mini: true, - child: const Icon(Icons.arrow_downward_outlined), + actions: [ + if (!controller.selectMode) + Padding( + padding: ChatViewStyle.paddingTrailing(context), + child: Row( + children: [ + IconButton( + hoverColor: Colors.transparent, + splashColor: Colors.transparent, + highlightColor: Colors.transparent, + onPressed: controller.toggleSearch, + icon: const Icon(Icons.search), + ), + if (!controller.room!.isDirectChat) + Builder( + builder: (context) => TwakeIconButton( + icon: Icons.more_vert, + tooltip: L10n.of(context)!.more, + onTapDown: (tapDownDetails) => + controller.handleAppbarMenuAction( + context, + tapDownDetails, + ), + preferBelow: false, + ), + ), + ], + ), + ), + ], + bottom: PreferredSize( + preferredSize: const Size(double.infinity, 1), + child: Container( + color: LinagoraStateLayer( + LinagoraSysColors.material().surfaceTint, + ).opacityLayer1, + height: 1, ), - ); - } - return const SizedBox(); - }, - ), - body: _buildBody(), - ); - }, + ), + ), + floatingActionButton: ValueListenableBuilder( + valueListenable: controller.showScrollDownButtonNotifier, + builder: (context, showScrollDownButton, _) { + if (showScrollDownButton && + controller.selectedEvents.isEmpty && + controller.replyEventNotifier.value == null) { + return Padding( + padding: const EdgeInsets.only(bottom: 56.0), + child: FloatingActionButton( + onPressed: controller.scrollDown, + mini: true, + child: const Icon(Icons.arrow_downward_outlined), + ), + ); + } + return const SizedBox(); + }, + ), + body: _buildBody(), + ); + }, + ), + ), ), ), ), diff --git a/lib/presentation/mixins/handle_clipboard_action_mixin.dart b/lib/presentation/mixins/handle_clipboard_action_mixin.dart index 636cb20304..5b7b4f9a34 100644 --- a/lib/presentation/mixins/handle_clipboard_action_mixin.dart +++ b/lib/presentation/mixins/handle_clipboard_action_mixin.dart @@ -29,17 +29,29 @@ mixin HandleClipboardActionMixin on PasteImageMixin { ); } + Future paste() async { + final clipboard = SystemClipboard.instance; + if (clipboard != null) { + final reader = await clipboard.read(); + _paste(reader); + } + } + void _onPasteEvent(ClipboardReadEvent event) async { if (chatFocusNode.hasFocus != true) { return; } final clipboardReader = await event.getClipboardReader(); + _paste(clipboardReader); + } + + void _paste(ClipboardReader reader) async { if (await TwakeClipboard.instance - .isReadableImageFormat(clipboardReader: clipboardReader) && + .isReadableImageFormat(clipboardReader: reader) && room != null) { - await pasteImage(context, room!, clipboardReader: clipboardReader); + await pasteImage(context, room!, clipboardReader: reader); } else { - sendController.pasteText(clipboardReader: clipboardReader); + sendController.pasteText(clipboardReader: reader); } } } diff --git a/lib/presentation/mixins/paste_image_mixin.dart b/lib/presentation/mixins/paste_image_mixin.dart index 7dff5f4421..b18abc9f0d 100644 --- a/lib/presentation/mixins/paste_image_mixin.dart +++ b/lib/presentation/mixins/paste_image_mixin.dart @@ -20,7 +20,7 @@ mixin PasteImageMixin { return; } List? matrixFiles; - if (PlatformInfos.isWeb) { + if (PlatformInfos.isWebOrDesktop) { matrixFiles = await TwakeClipboard.instance .pasteImagesUsingBytes(reader: clipboardReader); } @@ -43,7 +43,7 @@ mixin PasteImageMixin { .toList(); await showDialog( context: context, - useRootNavigator: PlatformInfos.isWeb, + useRootNavigator: PlatformInfos.isWebOrDesktop, builder: (context) { return SendFileDialog( room: room, diff --git a/lib/utils/shortcuts.dart b/lib/utils/shortcuts.dart index ffa994eac8..739f123078 100644 --- a/lib/utils/shortcuts.dart +++ b/lib/utils/shortcuts.dart @@ -7,3 +7,7 @@ class OnEmojiActionIntent extends Intent { class SelectAllIntent extends Intent { const SelectAllIntent(); } + +class PasteIntent extends Intent { + const PasteIntent(); +}