diff --git a/lib/src/views/chats/chat_messages.view.dart b/lib/src/views/chats/chat_messages.view.dart index 928796a..562c3ee 100644 --- a/lib/src/views/chats/chat_messages.view.dart +++ b/lib/src/views/chats/chat_messages.view.dart @@ -20,7 +20,7 @@ import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_dat import 'package:twonly/src/views/chats/chat_messages_components/message_input.dart'; import 'package:twonly/src/views/chats/chat_messages_components/response_container.dart'; import 'package:twonly/src/views/components/avatar_icon.component.dart'; -import 'package:twonly/src/views/components/blink.component.dart'; +import 'package:twonly/src/views/chats/chat_messages_components/blink.component.dart'; import 'package:twonly/src/views/components/flame.dart'; import 'package:twonly/src/views/components/verified_shield.dart'; diff --git a/lib/src/views/components/blink.component.dart b/lib/src/views/chats/chat_messages_components/blink.component.dart similarity index 100% rename from lib/src/views/components/blink.component.dart rename to lib/src/views/chats/chat_messages_components/blink.component.dart diff --git a/lib/src/views/chats/chat_messages_components/chat_list_entry.dart b/lib/src/views/chats/chat_messages_components/chat_list_entry.dart index 93c623e..9b48759 100644 --- a/lib/src/views/chats/chat_messages_components/chat_list_entry.dart +++ b/lib/src/views/chats/chat_messages_components/chat_list_entry.dart @@ -19,7 +19,7 @@ import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_med import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_text_entry.dart'; import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_unkown.entry.dart'; import 'package:twonly/src/views/chats/chat_messages_components/entries/common.dart'; -import 'package:twonly/src/views/chats/chat_messages_components/message_actions.dart'; +import 'package:twonly/src/views/chats/chat_messages_components/message_reply_drag.dart'; import 'package:twonly/src/views/chats/chat_messages_components/message_context_menu.dart'; import 'package:twonly/src/views/chats/chat_messages_components/response_container.dart'; import 'package:twonly/src/views/components/avatar_icon.component.dart'; @@ -74,8 +74,9 @@ class _ChatListEntryState extends State { Future initAsync() async { if (widget.message.mediaId != null) { - final mediaFileStream = - twonlyDB.mediaFilesDao.watchMedia(widget.message.mediaId!); + final mediaFileStream = twonlyDB.mediaFilesDao.watchMedia( + widget.message.mediaId!, + ); mediaFileSub = mediaFileStream.listen((mediaFiles) { if (mediaFiles != null) { mediaService = MediaFileService(mediaFiles); @@ -87,8 +88,9 @@ class _ChatListEntryState extends State { } }); } - final stream = - twonlyDB.reactionsDao.watchReactions(widget.message.messageId); + final stream = twonlyDB.reactionsDao.watchReactions( + widget.message.messageId, + ); reactionsSub = stream.listen((update) { setState(() { @@ -159,8 +161,10 @@ class _ChatListEntryState extends State { ); final seen = {}; - var reactionsForWidth = - reactions.where((t) => seen.add(t.emoji)).toList().length; + var reactionsForWidth = reactions + .where((t) => seen.add(t.emoji)) + .toList() + .length; if (reactionsForWidth > 4) reactionsForWidth = 4; Widget child = Stack( @@ -205,7 +209,7 @@ class _ChatListEntryState extends State { ); if (widget.onResponseTriggered != null) { - child = MessageActions( + child = MessageReplyDrag( message: widget.message, onResponseTriggered: widget.onResponseTriggered!, child: child, @@ -228,8 +232,9 @@ class _ChatListEntryState extends State { child: Padding( padding: padding, child: Row( - mainAxisAlignment: - right ? MainAxisAlignment.end : MainAxisAlignment.start, + mainAxisAlignment: right + ? MainAxisAlignment.end + : MainAxisAlignment.start, children: [ if (!right && !widget.group.isDirectChat) hideContactAvatar @@ -306,6 +311,6 @@ class _ChatListEntryState extends State { bottomRight: Radius.circular(bottomRight), bottomLeft: Radius.circular(bottomLeft), ), - hideContactAvatar + hideContactAvatar, ); } diff --git a/lib/src/views/chats/chat_messages_components/message_actions.dart b/lib/src/views/chats/chat_messages_components/message_reply_drag.dart similarity index 50% rename from lib/src/views/chats/chat_messages_components/message_actions.dart rename to lib/src/views/chats/chat_messages_components/message_reply_drag.dart index e691a92..4241f82 100644 --- a/lib/src/views/chats/chat_messages_components/message_actions.dart +++ b/lib/src/views/chats/chat_messages_components/message_reply_drag.dart @@ -5,8 +5,8 @@ import 'package:flutter/services.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:twonly/src/database/twonly.db.dart'; -class MessageActions extends StatefulWidget { - const MessageActions({ +class MessageReplyDrag extends StatefulWidget { + const MessageReplyDrag({ required this.child, required this.message, required this.onResponseTriggered, @@ -17,27 +17,49 @@ class MessageActions extends StatefulWidget { final VoidCallback onResponseTriggered; @override - State createState() => _SlidingResponseWidgetState(); + State createState() => _SlidingResponseWidgetState(); } -class _SlidingResponseWidgetState extends State { +class _SlidingResponseWidgetState extends State { double _offsetX = 0; bool gotFeedback = false; + double _dragProgress = 0; + double _animatedScale = 1; + + Future _triggerPopAnimation() async { + setState(() { + _animatedScale = 1.3; + }); + + await Future.delayed(Duration(milliseconds: 50)); + + if (mounted) { + setState(() { + _animatedScale = 1.0; + }); + } + } void _onHorizontalDragUpdate(DragUpdateDetails details) { setState(() { _offsetX += details.delta.dx; + if (_offsetX <= 0) _offsetX = 0; if (_offsetX > 40) { - _offsetX = 40; if (!gotFeedback) { unawaited(HapticFeedback.heavyImpact()); gotFeedback = true; + unawaited(_triggerPopAnimation()); } + _dragProgress = 1; + } else { + _dragProgress = _offsetX / 40; } if (_offsetX < 30) { gotFeedback = false; } - if (_offsetX <= 0) _offsetX = 0; + if (_offsetX > 50) { + _offsetX = 50; + } }); } @@ -47,6 +69,7 @@ class _SlidingResponseWidgetState extends State { } setState(() { _offsetX = 0.0; + _dragProgress = 0; }); } @@ -54,6 +77,32 @@ class _SlidingResponseWidgetState extends State { Widget build(BuildContext context) { return Stack( children: [ + if (_dragProgress > 0.2) + Positioned( + left: _dragProgress * 10, + top: 0, + bottom: 0, + child: Transform.scale( + scale: 1 * _dragProgress, + child: AnimatedScale( + duration: const Duration(milliseconds: 50), + scale: _animatedScale, + curve: Curves.easeInOut, + child: Opacity( + opacity: 1 * _dragProgress, + child: const Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FaIcon( + FontAwesomeIcons.reply, + size: 14, + ), + ], + ), + ), + ), + ), + ), Transform.translate( offset: Offset(_offsetX, 0), child: GestureDetector( @@ -62,22 +111,6 @@ class _SlidingResponseWidgetState extends State { child: widget.child, ), ), - if (_offsetX >= 40) - const Positioned( - left: 20, - top: 0, - bottom: 0, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - FaIcon( - FontAwesomeIcons.reply, - size: 14, - // color: Colors.green, - ), - ], - ), - ), ], ); }