diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index 9f8078c4..59463470 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -1,3 +1,15 @@ +## Upcoming + +🐞 Fixed + +- [[#668]](https://github.com/GetStream/stream-chat-flutter/issues/668): Fix `MessageInput` rendering errors in case + there are no actions available to show. +- [[#349]](https://github.com/GetStream/stream-chat-flutter/issues/349): Fix `MessageInput` attachment render overflow error. + +🔄 Changed + +- Animation curves changed from default `Curves.linear` to `Curves.easeOut` and `Curves.easeIn` for attachment controls. + ## 2.2.1 ⚠️ Deprecated diff --git a/packages/stream_chat_flutter/lib/src/message_input.dart b/packages/stream_chat_flutter/lib/src/message_input.dart index f5f51b46..cee653d2 100644 --- a/packages/stream_chat_flutter/lib/src/message_input.dart +++ b/packages/stream_chat_flutter/lib/src/message_input.dart @@ -578,6 +578,8 @@ class MessageInputState extends State { crossFadeState: _actionsShrunk ? CrossFadeState.showFirst : CrossFadeState.showSecond, + firstCurve: Curves.easeOut, + secondCurve: Curves.easeIn, firstChild: IconButton( onPressed: () { if (_actionsShrunk) { @@ -604,20 +606,17 @@ class MessageInputState extends State { !widget.showCommandsButton && widget.actions?.isNotEmpty != true ? const Offstage() - : FittedBox( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - if (!widget.disableAttachments) - _buildAttachmentButton(context), - if (widget.showCommandsButton && - widget.editMessage == null && - channel.state != null && - channel.config?.commands.isNotEmpty == true) - _buildCommandButton(context), - ...widget.actions ?? [], - ].insertBetween(const SizedBox(width: 8)), - ), + : Wrap( + children: [ + if (!widget.disableAttachments) + _buildAttachmentButton(context), + if (widget.showCommandsButton && + widget.editMessage == null && + channel.state != null && + channel.config?.commands.isNotEmpty == true) + _buildCommandButton(context), + ...widget.actions ?? [], + ].insertBetween(const SizedBox(width: 8)), ), duration: const Duration(milliseconds: 300), alignment: Alignment.center, @@ -1089,108 +1088,120 @@ class MessageInputState extends State { return AnimatedContainer( duration: const Duration(milliseconds: 300), + curve: Curves.easeOut, height: _openFilePickerSection ? _kMinMediaPickerSize : 0, - child: Material( - color: _streamChatTheme.colorTheme.inputBg, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( + child: SingleChildScrollView( + child: SizedBox( + height: _kMinMediaPickerSize, + child: Material( + color: _streamChatTheme.colorTheme.inputBg, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - IconButton( - icon: StreamSvgIcon.pictures( - color: _getIconColor(0), + Row( + children: [ + IconButton( + icon: StreamSvgIcon.pictures( + color: _getIconColor(0), + ), + onPressed: + _attachmentContainsFile && _attachments.isNotEmpty + ? null + : () { + setState(() { + _filePickerIndex = 0; + }); + }, + ), + IconButton( + iconSize: 32, + icon: StreamSvgIcon.files( + color: _getIconColor(1), + ), + onPressed: + !_attachmentContainsFile && _attachments.isNotEmpty + ? null + : () { + pickFile(DefaultAttachmentTypes.file); + }, + ), + IconButton( + icon: StreamSvgIcon.camera( + color: _getIconColor(2), + ), + onPressed: attachmentLimitCrossed || + (_attachmentContainsFile && + _attachments.isNotEmpty) + ? null + : () { + pickFile(DefaultAttachmentTypes.image, + camera: true); + }, + ), + IconButton( + padding: const EdgeInsets.all(0), + icon: StreamSvgIcon.record( + color: _getIconColor(3), + ), + onPressed: attachmentLimitCrossed || + (_attachmentContainsFile && + _attachments.isNotEmpty) + ? null + : () { + pickFile(DefaultAttachmentTypes.video, + camera: true); + }, + ), + ], + ), + DecoratedBox( + decoration: BoxDecoration( + color: _streamChatTheme.colorTheme.barsBg, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + ), ), - onPressed: _attachmentContainsFile && _attachments.isNotEmpty - ? null - : () { - setState(() { - _filePickerIndex = 0; - }); - }, - ), - IconButton( - iconSize: 32, - icon: StreamSvgIcon.files( - color: _getIconColor(1), - ), - onPressed: !_attachmentContainsFile && _attachments.isNotEmpty - ? null - : () { - pickFile(DefaultAttachmentTypes.file); - }, - ), - IconButton( - icon: StreamSvgIcon.camera( - color: _getIconColor(2), - ), - onPressed: attachmentLimitCrossed || - (_attachmentContainsFile && _attachments.isNotEmpty) - ? null - : () { - pickFile(DefaultAttachmentTypes.image, camera: true); - }, - ), - IconButton( - padding: const EdgeInsets.all(0), - icon: StreamSvgIcon.record( - color: _getIconColor(3), - ), - onPressed: attachmentLimitCrossed || - (_attachmentContainsFile && _attachments.isNotEmpty) - ? null - : () { - pickFile(DefaultAttachmentTypes.video, camera: true); - }, - ), - ], - ), - DecoratedBox( - decoration: BoxDecoration( - color: _streamChatTheme.colorTheme.barsBg, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16), - ), - ), - child: Center( - child: Padding( - padding: const EdgeInsets.all(8), - child: Container( - width: 40, - height: 4, - decoration: BoxDecoration( - color: _streamChatTheme.colorTheme.inputBg, - borderRadius: BorderRadius.circular(4), + child: Center( + child: Padding( + padding: const EdgeInsets.all(8), + child: Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: _streamChatTheme.colorTheme.inputBg, + borderRadius: BorderRadius.circular(4), + ), + ), ), ), ), - ), + if (_openFilePickerSection) + Expanded( + child: DecoratedBox( + decoration: BoxDecoration( + color: _streamChatTheme.colorTheme.barsBg, + borderRadius: BorderRadius.circular(8), + ), + child: _PickerWidget( + filePickerIndex: _filePickerIndex, + streamChatTheme: _streamChatTheme, + containsFile: _attachmentContainsFile, + selectedMedias: _attachments.keys.toList(), + onAddMoreFilesClick: pickFile, + onMediaSelected: (media) { + if (_attachments.containsKey(media.id)) { + setState(() => _attachments.remove(media.id)); + } else { + _addAssetAttachment(media); + } + }, + ), + ), + ), + ], ), - if (_openFilePickerSection) - Expanded( - child: DecoratedBox( - decoration: BoxDecoration( - color: _streamChatTheme.colorTheme.barsBg, - borderRadius: BorderRadius.circular(8), - ), - child: _PickerWidget( - filePickerIndex: _filePickerIndex, - streamChatTheme: _streamChatTheme, - containsFile: _attachmentContainsFile, - selectedMedias: _attachments.keys.toList(), - onAddMoreFilesClick: pickFile, - onMediaSelected: (media) { - if (_attachments.containsKey(media.id)) { - setState(() => _attachments.remove(media.id)); - } else { - _addAssetAttachment(media); - } - }, - ), - ), - ), - ], + ), ), ), ); @@ -2315,7 +2326,7 @@ class _PickerWidgetState extends State<_PickerWidget> { future: requestPermission, builder: (context, snapshot) { if (!snapshot.hasData) { - return const Center(child: CircularProgressIndicator()); + return const Offstage(); } if (snapshot.data!) {