From 895497290c74ccdb97c1e5a9735d1151c6e9ed0b Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Tue, 1 Dec 2020 15:26:54 +0530 Subject: [PATCH 01/16] feat: Added file icons, added new file attachment and bg --- lib/src/file_attachment.dart | 96 +++++++++++++- lib/src/message_input.dart | 12 ++ lib/src/message_widget.dart | 55 ++++++-- lib/src/stream_svg_icon.dart | 240 +++++++++++++++++++++++++++++++++++ 4 files changed, 387 insertions(+), 16 deletions(-) diff --git a/lib/src/file_attachment.dart b/lib/src/file_attachment.dart index 05318862..ebbf57f6 100644 --- a/lib/src/file_attachment.dart +++ b/lib/src/file_attachment.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_flutter/src/stream_svg_icon.dart'; import 'package:stream_chat_flutter/src/utils.dart'; class FileAttachment extends StatelessWidget { @@ -17,16 +18,103 @@ class FileAttachment extends StatelessWidget { return Material( child: InkWell( onTap: () { - launchURL(context, attachment.assetUrl); + //launchURL(context, attachment.assetUrl); }, child: Container( width: size?.width ?? 100, - height: size?.height ?? 100, - child: Center( - child: Icon(Icons.attach_file), + decoration: BoxDecoration( + color: Colors.white, + ), + child: ListTile( + dense: true, + leading: Container( + child: _getFileTypeImage(attachment.extraData['mime_type']), + height: 40.0, + width: 33.33, + ), + title: Text( + attachment?.title ?? 'File', + style: TextStyle( + fontWeight: FontWeight.bold, + ), + maxLines: 3, + ), + subtitle: Text( + '${attachment.extraData['file_size'] ?? 'N/A'} bytes', + style: TextStyle( + color: Colors.black.withOpacity(0.5), + ), + ), + trailing: IconButton( + icon: StreamSvgIcon.cloud_download( + color: Colors.black, + ), + onPressed: () { + launchURL(context, attachment.assetUrl); + }, + ), ), ), ), ); } + + StreamSvgIcon _getFileTypeImage(String type) { + switch (type) { + case '7z': + return StreamSvgIcon.filetype_7z(); + break; + case 'csv': + return StreamSvgIcon.filetype_csv(); + break; + case 'doc': + return StreamSvgIcon.filetype_doc(); + break; + case 'docx': + return StreamSvgIcon.filetype_docx(); + break; + case 'html': + return StreamSvgIcon.filetype_html(); + break; + case 'md': + return StreamSvgIcon.filetype_md(); + break; + case 'odt': + return StreamSvgIcon.filetype_odt(); + break; + case 'pdf': + return StreamSvgIcon.filetype_pdf(); + break; + case 'ppt': + return StreamSvgIcon.filetype_ppt(); + break; + case 'pptx': + return StreamSvgIcon.filetype_pptx(); + break; + case 'rar': + return StreamSvgIcon.filetype_rar(); + break; + case 'rtf': + return StreamSvgIcon.filetype_rtf(); + break; + case 'tar': + return StreamSvgIcon.filetype_tar(); + break; + case 'txt': + return StreamSvgIcon.filetype_txt(); + break; + case 'xls': + return StreamSvgIcon.filetype_xls(); + break; + case 'xlsx': + return StreamSvgIcon.filetype_xlsx(); + break; + case 'zip': + return StreamSvgIcon.filetype_zip(); + break; + default: + return StreamSvgIcon.filetype_Generic(); + break; + } + } } diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 1dbc45df..c2d3d7e6 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -1562,12 +1562,24 @@ class MessageInputState extends State { attachmentType = mimeType.type; } + Map extraDataMap = {}; + + if (mimeType?.subtype != null) { + extraDataMap['mime_type'] = mimeType.subtype.toLowerCase(); + } + + if (file.size != null) { + extraDataMap['file_size'] = file.size; + } + final channel = StreamChannel.of(context).channel; final attachment = _SendingAttachment( file: file, attachment: Attachment( localUri: file.path != null ? Uri.parse(file.path) : null, type: attachmentType, + extraData: extraDataMap.isNotEmpty ? extraDataMap : null, + title: file.name ?? 'File', ), ); diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index 64dab4ac..3e83ac0d 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -223,6 +223,8 @@ class _MessageWidgetState extends State { widget.message.attachments?.any((element) => element.type == 'giphy') == true; + var user = StreamChat.of(context).user; + return Portal( child: Padding( padding: widget.padding ?? EdgeInsets.all(8), @@ -295,18 +297,47 @@ class _MessageWidgetState extends State { messageTheme: widget.messageTheme, ), ) - : Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - ..._parseAttachments(context), - if (widget.message.text - .trim() - .isNotEmpty && - !isGiphy) - _buildTextBubble(context), - ], + : Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(8.0), + topRight: Radius.circular(8.0), + bottomRight: Radius.circular(8.0), + ), + border: Border.fromBorderSide( + BorderSide( + color: Color(0xFFE6E6E6), + )), + color: widget.message.attachments + .where((element) => + element.type == 'file') + .isEmpty + ? Colors.transparent + : (user.id == + widget.message.user.id + ? Color(0xFFE6E6E6) + : Colors.white), + ), + padding: EdgeInsets.all(widget + .message.attachments + .where((element) => + element.type == 'file') + .isEmpty + ? 0.0 + : 2.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + ..._parseAttachments(context), + if (widget.message.text + .trim() + .isNotEmpty && + !isGiphy) + _buildTextBubble(context), + ], + ), ), ), if (widget.showReactionPickerIndicator) diff --git a/lib/src/stream_svg_icon.dart b/lib/src/stream_svg_icon.dart index e5ef7ec9..42fed46e 100644 --- a/lib/src/stream_svg_icon.dart +++ b/lib/src/stream_svg_icon.dart @@ -338,6 +338,30 @@ class StreamSvgIcon extends StatelessWidget { ); } + factory StreamSvgIcon.download({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'Icon_download.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.cloud_download({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'Icon_cloud_download.svg', + color: color, + width: size, + height: size, + ); + } + factory StreamSvgIcon.copy({ double size, Color color, @@ -481,4 +505,220 @@ class StreamSvgIcon extends StatelessWidget { height: size, ); } + + factory StreamSvgIcon.filetype_7z({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_7z.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_csv({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_CSV.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_doc({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_DOC.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_docx({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_DOCX.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_Generic({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_Generic.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_html({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_html.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_md({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_MD.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_odt({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_ODT.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_pdf({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_PDF.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_ppt({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_PPT.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_pptx({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_PPTX.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_rar({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_RAR.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_rtf({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_RTF.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_tar({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_TAR.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_txt({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_TXT.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_xls({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_XLS.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_xlsx({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_XLSX.svg', + color: color, + width: size, + height: size, + ); + } + + factory StreamSvgIcon.filetype_zip({ + double size, + Color color, + }) { + return StreamSvgIcon( + assetName: 'filetype_ZIP.svg', + color: color, + width: size, + height: size, + ); + } } From 922208224d6f571f861f9e78fcec82d3a0e1860a Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Tue, 1 Dec 2020 16:19:02 +0530 Subject: [PATCH 02/16] feat: Added file attachment to pick attachment section --- lib/src/file_attachment.dart | 24 ++++++--- lib/src/message_input.dart | 94 +++++++++++++++++++++++------------- lib/src/message_widget.dart | 56 ++++++++++++--------- 3 files changed, 109 insertions(+), 65 deletions(-) diff --git a/lib/src/file_attachment.dart b/lib/src/file_attachment.dart index ebbf57f6..fd6f152a 100644 --- a/lib/src/file_attachment.dart +++ b/lib/src/file_attachment.dart @@ -6,11 +6,13 @@ import 'package:stream_chat_flutter/src/utils.dart'; class FileAttachment extends StatelessWidget { final Attachment attachment; final Size size; + final Widget trailing; const FileAttachment({ Key key, @required this.attachment, this.size, + this.trailing, }) : super(key: key); @override @@ -22,8 +24,13 @@ class FileAttachment extends StatelessWidget { }, child: Container( width: size?.width ?? 100, + margin: trailing != null ? EdgeInsets.only(top: 4.0) : null, decoration: BoxDecoration( color: Colors.white, + borderRadius: trailing != null ? BorderRadius.circular(16.0) : null, + border: trailing != null + ? Border.fromBorderSide(BorderSide(color: Color(0xFFE6E6E6))) + : null, ), child: ListTile( dense: true, @@ -45,14 +52,15 @@ class FileAttachment extends StatelessWidget { color: Colors.black.withOpacity(0.5), ), ), - trailing: IconButton( - icon: StreamSvgIcon.cloud_download( - color: Colors.black, - ), - onPressed: () { - launchURL(context, attachment.assetUrl); - }, - ), + trailing: trailing ?? + IconButton( + icon: StreamSvgIcon.cloud_download( + color: Colors.black, + ), + onPressed: () { + launchURL(context, attachment.assetUrl); + }, + ), ), ), ), diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index c2d3d7e6..4119be7d 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -1201,44 +1201,72 @@ class MessageInputState extends State { Widget _buildAttachments() { return _attachments.isEmpty ? Container() - : LimitedBox( - maxHeight: 104.0, - child: ListView( - scrollDirection: Axis.horizontal, - children: _attachments + : Column( + children: [ + ..._attachments + .where((e) => e.attachment.type == 'file') .map( - (attachment) => Padding( - padding: const EdgeInsets.all(8.0), - child: ClipRRect( - borderRadius: BorderRadius.circular(10), - child: Stack( - children: [ - AspectRatio( - aspectRatio: 1.0, - child: Container( - height: 104, - width: 104, - child: _buildAttachment(attachment), - ), - ), - _buildRemoveButton(attachment), - attachment.uploaded - ? SizedBox() - : Positioned.fill( - child: Center( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: CircularProgressIndicator(), - ), - ), - ), - ], - ), + (e) => FileAttachment( + attachment: e.attachment, + size: Size( + MediaQuery.of(context).size.width * 0.6, + MediaQuery.of(context).size.height * 0.3, + ), + trailing: IconButton( + icon: StreamSvgIcon.close_small(), + onPressed: () { + setState(() { + _attachments.remove(e); + }); + }, ), ), ) .toList(), - ), + if (_attachments.any((e) => e.attachment.type != 'file')) + LimitedBox( + maxHeight: 104.0, + child: ListView( + scrollDirection: Axis.horizontal, + children: _attachments + .where((e) => e.attachment.type != 'file') + .map( + (attachment) => Padding( + padding: const EdgeInsets.all(8.0), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Stack( + children: [ + AspectRatio( + aspectRatio: 1.0, + child: Container( + height: 104, + width: 104, + child: _buildAttachment(attachment), + ), + ), + _buildRemoveButton(attachment), + attachment.uploaded + ? SizedBox() + : Positioned.fill( + child: Center( + child: Padding( + padding: + const EdgeInsets.all(16.0), + child: + CircularProgressIndicator(), + ), + ), + ), + ], + ), + ), + ), + ) + .toList(), + ), + ), + ], ); } diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index 3e83ac0d..6a35648d 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -225,6 +225,9 @@ class _MessageWidgetState extends State { var user = StreamChat.of(context).user; + bool hasFiles = + widget.message.attachments.any((element) => element.type == 'file'); + return Portal( child: Padding( padding: widget.padding ?? EdgeInsets.all(8), @@ -298,33 +301,38 @@ class _MessageWidgetState extends State { ), ) : Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(8.0), - topRight: Radius.circular(8.0), - bottomRight: Radius.circular(8.0), - ), - border: Border.fromBorderSide( - BorderSide( - color: Color(0xFFE6E6E6), - )), - color: widget.message.attachments - .where((element) => - element.type == 'file') - .isEmpty - ? Colors.transparent - : (user.id == - widget.message.user.id - ? Color(0xFFE6E6E6) - : Colors.white), - ), - padding: EdgeInsets.all(widget - .message.attachments + decoration: widget.message.attachments .where((element) => element.type == 'file') .isEmpty - ? 0.0 - : 2.0), + ? null + : BoxDecoration( + borderRadius: + BorderRadius.only( + topLeft: + Radius.circular(8.0), + topRight: + Radius.circular(8.0), + bottomRight: + Radius.circular(8.0), + ), + border: hasFiles + ? Border.fromBorderSide( + BorderSide( + color: + Color(0xFFE6E6E6), + )) + : null, + color: hasFiles + ? (user.id == + widget.message + .user.id + ? Color(0xFFE6E6E6) + : Colors.white) + : Colors.transparent, + ), + padding: EdgeInsets.all( + hasFiles ? 2.0 : 0.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, From a846048ef171457a5b3e2b7250b18e18feb12aea Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Tue, 1 Dec 2020 20:41:11 +0530 Subject: [PATCH 03/16] fix: Fixed multiple file upload --- lib/src/message_input.dart | 49 ++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 4119be7d..489ba558 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -1203,26 +1203,35 @@ class MessageInputState extends State { ? Container() : Column( children: [ - ..._attachments - .where((e) => e.attachment.type == 'file') - .map( - (e) => FileAttachment( - attachment: e.attachment, - size: Size( - MediaQuery.of(context).size.width * 0.6, - MediaQuery.of(context).size.height * 0.3, - ), - trailing: IconButton( - icon: StreamSvgIcon.close_small(), - onPressed: () { - setState(() { - _attachments.remove(e); - }); - }, - ), - ), - ) - .toList(), + LimitedBox( + maxHeight: 73.0, + child: ListView( + scrollDirection: Axis.horizontal, + children: _attachments + .where((e) => e.attachment.type == 'file') + .map( + (e) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 4.0), + child: FileAttachment( + attachment: e.attachment, + size: Size( + MediaQuery.of(context).size.width * 0.55, + MediaQuery.of(context).size.height * 0.3, + ), + trailing: IconButton( + icon: StreamSvgIcon.close_small(), + onPressed: () { + setState(() { + _attachments.remove(e); + }); + }, + ), + ), + ), + ) + .toList(), + ), + ), if (_attachments.any((e) => e.attachment.type != 'file')) LimitedBox( maxHeight: 104.0, From 9918a4bfde4ddb27079a5ce70323a6a0c480ad6c Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Wed, 2 Dec 2020 16:37:08 +0530 Subject: [PATCH 04/16] fix: Added boolean for picking one thing at a time -_- --- lib/src/message_input.dart | 84 +++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 33 deletions(-) diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 489ba558..bb9c8ec4 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -108,6 +108,7 @@ class MessageInput extends StatefulWidget { this.actionsLocation = ActionsLocation.left, this.attachmentThumbnailBuilders, this.focusNode, + this.enableFileAndImageAttachment = false, }) : super(key: key); /// Message to edit @@ -156,6 +157,9 @@ class MessageInput extends StatefulWidget { /// The focus node associated to the TextField final FocusNode focusNode; + /// Enables adding both file+images at the same time + final bool enableFileAndImageAttachment; + @override MessageInputState createState() => MessageInputState(); @@ -787,7 +791,14 @@ class MessageInputState extends State { onSelect: (media) async { if (!_attachments .any((element) => element.id == media.id)) { - _addAttachment(media); + if (widget.enableFileAndImageAttachment) { + _addAttachment(media); + } else { + if (!_attachments.any( + (element) => element.attachment?.type == 'file')) { + _addAttachment(media); + } + } } else { setState(() { _attachments @@ -850,7 +861,7 @@ class MessageInputState extends State { ); if (file.size > _kMaxAttachmentSize) { - if (medium.type == AssetType.video) { + if (medium?.type == AssetType.video) { final mediaInfo = await CompressVideoService.compressVideo(file.path); if (mediaInfo.filesize / (1024 * 1024) > _kMaxAttachmentSize) { @@ -1203,42 +1214,44 @@ class MessageInputState extends State { ? Container() : Column( children: [ - LimitedBox( - maxHeight: 73.0, - child: ListView( - scrollDirection: Axis.horizontal, - children: _attachments - .where((e) => e.attachment.type == 'file') - .map( - (e) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 4.0), - child: FileAttachment( - attachment: e.attachment, - size: Size( - MediaQuery.of(context).size.width * 0.55, - MediaQuery.of(context).size.height * 0.3, - ), - trailing: IconButton( - icon: StreamSvgIcon.close_small(), - onPressed: () { - setState(() { - _attachments.remove(e); - }); - }, + if (_attachments.any((e) => e.attachment?.type == 'file')) + LimitedBox( + maxHeight: 73.0, + child: ListView( + scrollDirection: Axis.horizontal, + children: _attachments + .where((e) => e.attachment?.type == 'file') + .map( + (e) => Padding( + padding: + const EdgeInsets.symmetric(horizontal: 4.0), + child: FileAttachment( + attachment: e.attachment, + size: Size( + MediaQuery.of(context).size.width * 0.55, + MediaQuery.of(context).size.height * 0.3, + ), + trailing: IconButton( + icon: StreamSvgIcon.close_small(), + onPressed: () { + setState(() { + _attachments.remove(e); + }); + }, + ), ), ), - ), - ) - .toList(), + ) + .toList(), + ), ), - ), - if (_attachments.any((e) => e.attachment.type != 'file')) + if (_attachments.any((e) => e.attachment?.type != 'file')) LimitedBox( maxHeight: 104.0, child: ListView( scrollDirection: Axis.horizontal, children: _attachments - .where((e) => e.attachment.type != 'file') + .where((e) => e.attachment?.type != 'file') .map( (attachment) => Padding( padding: const EdgeInsets.all(8.0), @@ -1312,9 +1325,9 @@ class MessageInputState extends State { Widget _buildAttachment(_SendingAttachment attachment) { if (widget.attachmentThumbnailBuilders - ?.containsKey(attachment.attachment.type) == + ?.containsKey(attachment.attachment?.type) == true) { - return widget.attachmentThumbnailBuilders[attachment.attachment.type]( + return widget.attachmentThumbnailBuilders[attachment.attachment?.type]( context, attachment, ); @@ -1324,7 +1337,7 @@ class MessageInputState extends State { return SizedBox(); } - switch (attachment.attachment.type) { + switch (attachment.attachment?.type) { case 'image': case 'giphy': return attachment.file != null @@ -1568,6 +1581,11 @@ class MessageInputState extends State { bytes: bytes, ); } else { + if (_attachments.any((element) => element.attachment.type != 'file') && + !widget.enableFileAndImageAttachment) { + return; + } + FileType type; if (fileType == DefaultAttachmentTypes.image) { type = FileType.image; From 3d92d5fc32403eb01d300ac940a25b8f5da59ec6 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 2 Dec 2020 15:11:04 +0100 Subject: [PATCH 05/16] ui fix --- lib/src/file_attachment.dart | 75 +++++++++++++++++------------------- lib/src/message_widget.dart | 62 ++++++++++++++--------------- 2 files changed, 63 insertions(+), 74 deletions(-) diff --git a/lib/src/file_attachment.dart b/lib/src/file_attachment.dart index fd6f152a..168e7989 100644 --- a/lib/src/file_attachment.dart +++ b/lib/src/file_attachment.dart @@ -18,50 +18,45 @@ class FileAttachment extends StatelessWidget { @override Widget build(BuildContext context) { return Material( - child: InkWell( - onTap: () { - //launchURL(context, attachment.assetUrl); - }, - child: Container( - width: size?.width ?? 100, - margin: trailing != null ? EdgeInsets.only(top: 4.0) : null, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: trailing != null ? BorderRadius.circular(16.0) : null, - border: trailing != null - ? Border.fromBorderSide(BorderSide(color: Color(0xFFE6E6E6))) - : null, + child: Container( + width: size?.width ?? 100, + margin: trailing != null ? EdgeInsets.only(top: 4.0) : null, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: trailing != null ? BorderRadius.circular(16.0) : null, + border: trailing != null + ? Border.fromBorderSide(BorderSide(color: Color(0xFFE6E6E6))) + : null, + ), + child: ListTile( + dense: true, + leading: Container( + child: _getFileTypeImage(attachment.extraData['mime_type']), + height: 40.0, + width: 33.33, ), - child: ListTile( - dense: true, - leading: Container( - child: _getFileTypeImage(attachment.extraData['mime_type']), - height: 40.0, - width: 33.33, + title: Text( + attachment?.title ?? 'File', + style: TextStyle( + fontWeight: FontWeight.bold, ), - title: Text( - attachment?.title ?? 'File', - style: TextStyle( - fontWeight: FontWeight.bold, - ), - maxLines: 3, + maxLines: 3, + ), + subtitle: Text( + '${attachment.extraData['file_size'] ?? 'N/A'} bytes', + style: TextStyle( + color: Colors.black.withOpacity(0.5), ), - subtitle: Text( - '${attachment.extraData['file_size'] ?? 'N/A'} bytes', - style: TextStyle( - color: Colors.black.withOpacity(0.5), - ), - ), - trailing: trailing ?? - IconButton( - icon: StreamSvgIcon.cloud_download( - color: Colors.black, - ), - onPressed: () { - launchURL(context, attachment.assetUrl); - }, + ), + trailing: trailing ?? + IconButton( + icon: StreamSvgIcon.cloud_download( + color: Colors.black, ), - ), + onPressed: () { + launchURL(context, attachment.assetUrl); + }, + ), ), ), ); diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index 6a35648d..7c007735 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -668,46 +668,40 @@ class _MessageWidgetState extends State { []; } - Padding wrapAttachmentWidget( + Widget wrapAttachmentWidget( BuildContext context, Widget attachmentWidget, { Attachment attachment, }) { final attachmentShape = widget.attachmentShape ?? widget.shape ?? _getDefaultShape(context); - return Padding( - padding: EdgeInsets.only( - bottom: 4, - ), - child: GestureDetector( - onTap: () => retryMessage(context), - onLongPress: () => onLongPress(context), - child: Material( - color: attachment?.type == 'giphy' - ? Colors.white - : _getBackgroundColor(), - clipBehavior: Clip.hardEdge, - shape: attachmentShape, - child: Padding( - padding: widget.attachmentPadding, - child: Material( - clipBehavior: Clip.hardEdge, - shape: attachmentShape, - type: MaterialType.transparency, - child: Transform( - transform: Matrix4.rotationY(widget.reverse ? pi : 0), - alignment: Alignment.center, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - getFailedMessageWidget( - context, - padding: const EdgeInsets.all(8.0), - ), - attachmentWidget, - ], - ), + return GestureDetector( + onTap: () => retryMessage(context), + onLongPress: () => onLongPress(context), + child: Material( + color: + attachment?.type == 'giphy' ? Colors.white : _getBackgroundColor(), + clipBehavior: Clip.hardEdge, + shape: attachmentShape, + child: Padding( + padding: widget.attachmentPadding, + child: Material( + clipBehavior: Clip.hardEdge, + shape: attachmentShape, + type: MaterialType.transparency, + child: Transform( + transform: Matrix4.rotationY(widget.reverse ? pi : 0), + alignment: Alignment.center, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + getFailedMessageWidget( + context, + padding: const EdgeInsets.all(8.0), + ), + attachmentWidget, + ], ), ), ), From d26833aa72c374f2e9adf184a0d80cadf76ccf72 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 2 Dec 2020 15:25:33 +0100 Subject: [PATCH 06/16] fi borderradius --- lib/src/message_widget.dart | 113 ++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 45 deletions(-) diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index 7c007735..e1644c84 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -300,51 +300,74 @@ class _MessageWidgetState extends State { messageTheme: widget.messageTheme, ), ) - : Container( - decoration: widget.message.attachments - .where((element) => - element.type == 'file') - .isEmpty - ? null - : BoxDecoration( - borderRadius: - BorderRadius.only( - topLeft: - Radius.circular(8.0), - topRight: - Radius.circular(8.0), - bottomRight: - Radius.circular(8.0), - ), - border: hasFiles - ? Border.fromBorderSide( - BorderSide( - color: - Color(0xFFE6E6E6), - )) - : null, - color: hasFiles - ? (user.id == - widget.message - .user.id - ? Color(0xFFE6E6E6) - : Colors.white) - : Colors.transparent, - ), - padding: EdgeInsets.all( - hasFiles ? 2.0 : 0.0), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - ..._parseAttachments(context), - if (widget.message.text - .trim() - .isNotEmpty && - !isGiphy) - _buildTextBubble(context), - ], + : Material( + shape: widget.shape ?? + RoundedRectangleBorder( + side: !hasFiles + ? BorderSide.none + : widget.borderSide ?? + BorderSide( + color: Theme.of(context) + .brightness == + Brightness + .dark + ? Colors.white + .withAlpha(24) + : Colors.black + .withAlpha( + 24), + ), + borderRadius: widget + .borderRadiusGeometry ?? + BorderRadius.zero, + ), + color: _getBackgroundColor(), + // decoration: widget.message.attachments + // .where((element) => + // element.type == 'file') + // .isEmpty + // ? null + // : BoxDecoration( + // borderRadius: + // BorderRadius.only( + // topLeft: + // Radius.circular(8.0), + // topRight: + // Radius.circular(8.0), + // bottomRight: + // Radius.circular(8.0), + // ), + // border: hasFiles + // ? Border.fromBorderSide( + // BorderSide( + // color: + // Color(0xFFE6E6E6), + // )) + // : null, + // color: hasFiles + // ? (user.id == + // widget.message + // .user.id + // ? Color(0xFFE6E6E6) + // : Colors.white) + // : Colors.transparent, + // ), + child: Padding( + padding: EdgeInsets.all( + hasFiles ? 2.0 : 0.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + ..._parseAttachments(context), + if (widget.message.text + .trim() + .isNotEmpty && + !isGiphy) + _buildTextBubble(context), + ], + ), ), ), ), From aff59fd603398edb5e5eef7e9a0a1d5229862a50 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 2 Dec 2020 15:29:13 +0100 Subject: [PATCH 07/16] fix message text align --- lib/src/message_widget.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index e1644c84..a510da28 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -357,7 +357,7 @@ class _MessageWidgetState extends State { hasFiles ? 2.0 : 0.0), child: Column( crossAxisAlignment: - CrossAxisAlignment.start, + CrossAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: [ ..._parseAttachments(context), From e1c1e053b364b8d654e6ba652d5199be125d4904 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Wed, 2 Dec 2020 15:42:16 +0100 Subject: [PATCH 08/16] remove comment --- lib/src/message_widget.dart | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index a510da28..deeaa921 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -322,36 +322,6 @@ class _MessageWidgetState extends State { BorderRadius.zero, ), color: _getBackgroundColor(), - // decoration: widget.message.attachments - // .where((element) => - // element.type == 'file') - // .isEmpty - // ? null - // : BoxDecoration( - // borderRadius: - // BorderRadius.only( - // topLeft: - // Radius.circular(8.0), - // topRight: - // Radius.circular(8.0), - // bottomRight: - // Radius.circular(8.0), - // ), - // border: hasFiles - // ? Border.fromBorderSide( - // BorderSide( - // color: - // Color(0xFFE6E6E6), - // )) - // : null, - // color: hasFiles - // ? (user.id == - // widget.message - // .user.id - // ? Color(0xFFE6E6E6) - // : Colors.white) - // : Colors.transparent, - // ), child: Padding( padding: EdgeInsets.all( hasFiles ? 2.0 : 0.0), From c4c0f97f3416487386206f888aedffdbc3d39f05 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Thu, 3 Dec 2020 14:12:39 +0530 Subject: [PATCH 09/16] feat: Icons are now disabled according to file type chosen --- lib/src/message_input.dart | 122 +++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 52 deletions(-) diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index bb9c8ec4..04c9b3d1 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -108,7 +108,6 @@ class MessageInput extends StatefulWidget { this.actionsLocation = ActionsLocation.left, this.attachmentThumbnailBuilders, this.focusNode, - this.enableFileAndImageAttachment = false, }) : super(key: key); /// Message to edit @@ -157,9 +156,6 @@ class MessageInput extends StatefulWidget { /// The focus node associated to the TextField final FocusNode focusNode; - /// Enables adding both file+images at the same time - final bool enableFileAndImageAttachment; - @override MessageInputState createState() => MessageInputState(); @@ -662,6 +658,34 @@ class MessageInputState extends State { } Widget _buildFilePickerSection() { + var _attachmentContainsFile = + _attachments.any((element) => element.attachment.type == 'file'); + + Color _getIconColor(int index) { + switch (index) { + case 0: + return _attachmentContainsFile && _attachments.isNotEmpty + ? Colors.black.withOpacity(0.2) + : Colors.black.withOpacity(0.5); + break; + case 1: + return !_attachmentContainsFile && _attachments.isNotEmpty + ? Colors.black.withOpacity(0.2) + : Colors.black.withOpacity(0.5); + break; + case 2: + return _attachmentContainsFile && _attachments.isNotEmpty + ? Colors.black.withOpacity(0.2) + : Colors.black.withOpacity(0.5); + break; + case 3: + return _attachmentContainsFile && _attachments.isNotEmpty + ? Colors.black.withOpacity(0.2) + : Colors.black.withOpacity(0.5); + break; + } + } + return AnimatedContainer( duration: _animateContainer ? Duration(milliseconds: 300) : Duration.zero, height: _openFilePickerSection ? _filePickerSize : 0, @@ -675,49 +699,49 @@ class MessageInputState extends State { IconButton( iconSize: 24, icon: StreamSvgIcon.pictures( - color: _filePickerIndex == 0 - ? StreamChatTheme.of(context).accentColor - : Colors.black.withOpacity(0.5), + color: _getIconColor(0), ), - onPressed: () { - setState(() { - _filePickerIndex = 0; - }); - }, + onPressed: _attachmentContainsFile && _attachments.isNotEmpty + ? null + : () { + setState(() { + _filePickerIndex = 0; + }); + }, ), IconButton( iconSize: 32, icon: StreamSvgIcon.files( - color: _filePickerIndex == 1 - ? StreamChatTheme.of(context).accentColor - : Colors.black.withOpacity(0.5), + color: _getIconColor(1), ), - onPressed: () { - pickFile(DefaultAttachmentTypes.file, false); - }, + onPressed: !_attachmentContainsFile && _attachments.isNotEmpty + ? null + : () { + pickFile(DefaultAttachmentTypes.file, false); + }, ), IconButton( iconSize: 24, icon: StreamSvgIcon.camera( - color: _filePickerIndex == 2 - ? StreamChatTheme.of(context).accentColor - : Colors.black.withOpacity(0.5), + color: _getIconColor(2), ), - onPressed: () { - pickFile(DefaultAttachmentTypes.image, true); - }, + onPressed: _attachmentContainsFile && _attachments.isNotEmpty + ? null + : () { + pickFile(DefaultAttachmentTypes.image, true); + }, ), IconButton( padding: const EdgeInsets.all(0), iconSize: 24, icon: StreamSvgIcon.record( - color: _filePickerIndex == 3 - ? StreamChatTheme.of(context).accentColor - : Colors.black.withOpacity(0.5), + color: _getIconColor(3), ), - onPressed: () { - pickFile(DefaultAttachmentTypes.video, true); - }, + onPressed: _attachmentContainsFile && _attachments.isNotEmpty + ? null + : () { + pickFile(DefaultAttachmentTypes.video, true); + }, ), ], ), @@ -774,6 +798,9 @@ class MessageInputState extends State { } Widget _buildPickerSection() { + var _attachmentContainsFile = + _attachments.any((element) => element.attachment.type == 'file'); + switch (_filePickerIndex) { case 0: return FutureBuilder( @@ -786,26 +813,22 @@ class MessageInputState extends State { } if (snapshot.data) { - return MediaListView( - selectedIds: _attachments.map((e) => e.id).toList(), - onSelect: (media) async { - if (!_attachments - .any((element) => element.id == media.id)) { - if (widget.enableFileAndImageAttachment) { + return IgnorePointer( + ignoring: _attachmentContainsFile, + child: MediaListView( + selectedIds: _attachments.map((e) => e.id).toList(), + onSelect: (media) async { + if (!_attachments + .any((element) => element.id == media.id)) { _addAttachment(media); } else { - if (!_attachments.any( - (element) => element.attachment?.type == 'file')) { - _addAttachment(media); - } + setState(() { + _attachments + .removeWhere((element) => element.id == media.id); + }); } - } else { - setState(() { - _attachments - .removeWhere((element) => element.id == media.id); - }); - } - }, + }, + ), ); } @@ -1581,11 +1604,6 @@ class MessageInputState extends State { bytes: bytes, ); } else { - if (_attachments.any((element) => element.attachment.type != 'file') && - !widget.enableFileAndImageAttachment) { - return; - } - FileType type; if (fileType == DefaultAttachmentTypes.image) { type = FileType.image; From dffad3d6bca6b94454f5af37083d9c32e5b383f4 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Thu, 3 Dec 2020 14:54:58 +0530 Subject: [PATCH 10/16] fix: fixed sizes of file attachment --- lib/src/file_attachment.dart | 107 ++++++++++++++++++++++++++--------- lib/src/message_input.dart | 24 +++++--- 2 files changed, 98 insertions(+), 33 deletions(-) diff --git a/lib/src/file_attachment.dart b/lib/src/file_attachment.dart index 168e7989..fff13bbe 100644 --- a/lib/src/file_attachment.dart +++ b/lib/src/file_attachment.dart @@ -20,6 +20,7 @@ class FileAttachment extends StatelessWidget { return Material( child: Container( width: size?.width ?? 100, + height: 56.0, margin: trailing != null ? EdgeInsets.only(top: 4.0) : null, decoration: BoxDecoration( color: Colors.white, @@ -28,36 +29,90 @@ class FileAttachment extends StatelessWidget { ? Border.fromBorderSide(BorderSide(color: Color(0xFFE6E6E6))) : null, ), - child: ListTile( - dense: true, - leading: Container( - child: _getFileTypeImage(attachment.extraData['mime_type']), - height: 40.0, - width: 33.33, - ), - title: Text( - attachment?.title ?? 'File', - style: TextStyle( - fontWeight: FontWeight.bold, + child: Row( + children: [ + Container( + child: _getFileTypeImage(attachment.extraData['mime_type']), + height: 40.0, + width: 33.33, + margin: EdgeInsets.all(8.0), ), - maxLines: 3, - ), - subtitle: Text( - '${attachment.extraData['file_size'] ?? 'N/A'} bytes', - style: TextStyle( - color: Colors.black.withOpacity(0.5), + SizedBox( + width: 6.0, ), - ), - trailing: trailing ?? - IconButton( - icon: StreamSvgIcon.cloud_download( - color: Colors.black, - ), - onPressed: () { - launchURL(context, attachment.assetUrl); - }, + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + attachment?.title ?? 'File', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14.0, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + SizedBox( + height: 3.0, + ), + Text( + '${attachment.extraData['file_size'] ?? 'N/A'} bytes', + style: TextStyle( + color: Colors.black.withOpacity(0.5), + fontSize: 14.0, + ), + ), + ], ), + ), + Column( + children: [ + trailing ?? + IconButton( + icon: StreamSvgIcon.cloud_download( + color: Colors.black, + ), + onPressed: () { + launchURL(context, attachment.assetUrl); + }, + ), + ], + ), + ], ), + + // ListTile( + // dense: true, + // leading: Container( + // child: _getFileTypeImage(attachment.extraData['mime_type']), + // height: 40.0, + // width: 33.33, + // ), + // title: Text( + // attachment?.title ?? 'File', + // style: TextStyle( + // fontWeight: FontWeight.bold, + // ), + // maxLines: 3, + // ), + // subtitle: Text( + // '${attachment.extraData['file_size'] ?? 'N/A'} bytes', + // style: TextStyle( + // color: Colors.black.withOpacity(0.5), + // ), + // ), + // trailing: trailing ?? + // IconButton( + // icon: StreamSvgIcon.cloud_download( + // color: Colors.black, + // ), + // onPressed: () { + // launchURL(context, attachment.assetUrl); + // }, + // ), + // ), ), ); } diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 04c9b3d1..3ebcef21 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -1254,13 +1254,23 @@ class MessageInputState extends State { MediaQuery.of(context).size.width * 0.55, MediaQuery.of(context).size.height * 0.3, ), - trailing: IconButton( - icon: StreamSvgIcon.close_small(), - onPressed: () { - setState(() { - _attachments.remove(e); - }); - }, + trailing: Padding( + padding: const EdgeInsets.all(8.0), + child: InkWell( + child: CircleAvatar( + backgroundColor: + Colors.black.withOpacity(0.2), + maxRadius: 12.0, + child: StreamSvgIcon.close( + color: Colors.white, + ), + ), + onTap: () { + setState(() { + _attachments.remove(e); + }); + }, + ), ), ), ), From 38687f59efedf88a6dca225ad85594636dd6871f Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 3 Dec 2020 11:32:59 +0100 Subject: [PATCH 11/16] add cliprrect to file section of messageinput --- lib/src/message_input.dart | 46 +++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 3ebcef21..1469e574 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -1247,29 +1247,33 @@ class MessageInputState extends State { .map( (e) => Padding( padding: - const EdgeInsets.symmetric(horizontal: 4.0), - child: FileAttachment( - attachment: e.attachment, - size: Size( - MediaQuery.of(context).size.width * 0.55, - MediaQuery.of(context).size.height * 0.3, - ), - trailing: Padding( - padding: const EdgeInsets.all(8.0), - child: InkWell( - child: CircleAvatar( - backgroundColor: - Colors.black.withOpacity(0.2), - maxRadius: 12.0, - child: StreamSvgIcon.close( - color: Colors.white, + const EdgeInsets.symmetric(horizontal: 8.0), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + clipBehavior: Clip.antiAlias, + child: FileAttachment( + attachment: e.attachment, + size: Size( + MediaQuery.of(context).size.width * 0.55, + MediaQuery.of(context).size.height * 0.3, + ), + trailing: Padding( + padding: const EdgeInsets.all(8.0), + child: InkWell( + child: CircleAvatar( + backgroundColor: + Colors.black.withOpacity(0.2), + maxRadius: 12.0, + child: StreamSvgIcon.close( + color: Colors.white, + ), ), + onTap: () { + setState(() { + _attachments.remove(e); + }); + }, ), - onTap: () { - setState(() { - _attachments.remove(e); - }); - }, ), ), ), From e1c02de32039262116779d43d1dcc32dce913d28 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 3 Dec 2020 11:37:40 +0100 Subject: [PATCH 12/16] fix mention debounce --- lib/src/message_input.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 1469e574..580a4f17 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -1087,7 +1087,7 @@ class MessageInputState extends State { offset: rejoin.length, ), ); - + _debounce.cancel(); _mentionsOverlay?.remove(); _mentionsOverlay = null; }, @@ -1294,6 +1294,7 @@ class MessageInputState extends State { padding: const EdgeInsets.all(8.0), child: ClipRRect( borderRadius: BorderRadius.circular(10), + clipBehavior: Clip.antiAlias, child: Stack( children: [ AspectRatio( From d81d6804201b98aad232841eb656e125c465123e Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 3 Dec 2020 11:55:14 +0100 Subject: [PATCH 13/16] fix borderradius --- lib/src/message_list_view.dart | 7 +++++- lib/src/message_widget.dart | 39 ++++++++++++---------------------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/lib/src/message_list_view.dart b/lib/src/message_list_view.dart index 3feda8ce..430e0b85 100644 --- a/lib/src/message_list_view.dart +++ b/lib/src/message_list_view.dart @@ -617,7 +617,12 @@ class _MessageListViewState extends State { showDeleteMessage: isMyMessage, borderSide: isMyMessage ? BorderSide.none : null, onThreadTap: _onThreadTap, - attachmentBorderRadiusGeometry: BorderRadius.circular(16), + attachmentBorderRadiusGeometry: BorderRadius.only( + topLeft: Radius.circular(16), + bottomLeft: Radius.circular(!isNextUser ? 0 : 16), + topRight: Radius.circular(16), + bottomRight: Radius.circular(16), + ), attachmentPadding: const EdgeInsets.all(2), borderRadiusGeometry: BorderRadius.only( topLeft: Radius.circular(16), diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index deeaa921..1ba4db87 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -301,22 +301,19 @@ class _MessageWidgetState extends State { ), ) : Material( + clipBehavior: Clip.antiAlias, shape: widget.shape ?? RoundedRectangleBorder( - side: !hasFiles - ? BorderSide.none - : widget.borderSide ?? - BorderSide( - color: Theme.of(context) - .brightness == - Brightness - .dark - ? Colors.white - .withAlpha(24) - : Colors.black - .withAlpha( - 24), - ), + side: widget.borderSide ?? + BorderSide( + color: Theme.of(context) + .brightness == + Brightness.dark + ? Colors.white + .withAlpha(24) + : Colors.black + .withAlpha(24), + ), borderRadius: widget .borderRadiusGeometry ?? BorderRadius.zero, @@ -327,7 +324,7 @@ class _MessageWidgetState extends State { hasFiles ? 2.0 : 0.0), child: Column( crossAxisAlignment: - CrossAxisAlignment.end, + CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ ..._parseAttachments(context), @@ -828,17 +825,7 @@ class _MessageWidgetState extends State { BuildContext context, Widget child, }) { - return Material( - shape: widget.shape ?? - RoundedRectangleBorder( - side: widget.borderSide ?? - BorderSide( - color: Theme.of(context).brightness == Brightness.dark - ? Colors.white.withAlpha(24) - : Colors.black.withAlpha(24), - ), - borderRadius: widget.borderRadiusGeometry ?? BorderRadius.zero, - ), + return Container( color: _getBackgroundColor(), child: child, ); From a551ab445b36a582a4c3e004e93b4b90fc25ac37 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 3 Dec 2020 12:08:20 +0100 Subject: [PATCH 14/16] fix emoji only messages --- lib/src/message_widget.dart | 52 ++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index 1ba4db87..94d9afd3 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -223,9 +223,10 @@ class _MessageWidgetState extends State { widget.message.attachments?.any((element) => element.type == 'giphy') == true; - var user = StreamChat.of(context).user; + final isOnlyEmoji = + widget.message.text.characters.every((c) => Emoji.byChar(c) != null); - bool hasFiles = + final hasFiles = widget.message.attachments.any((element) => element.type == 'file'); return Portal( @@ -304,16 +305,20 @@ class _MessageWidgetState extends State { clipBehavior: Clip.antiAlias, shape: widget.shape ?? RoundedRectangleBorder( - side: widget.borderSide ?? - BorderSide( - color: Theme.of(context) - .brightness == - Brightness.dark - ? Colors.white - .withAlpha(24) - : Colors.black - .withAlpha(24), - ), + side: isOnlyEmoji + ? BorderSide.none + : widget.borderSide ?? + BorderSide( + color: Theme.of(context) + .brightness == + Brightness + .dark + ? Colors.white + .withAlpha(24) + : Colors.black + .withAlpha( + 24), + ), borderRadius: widget .borderRadiusGeometry ?? BorderRadius.zero, @@ -821,16 +826,6 @@ class _MessageWidgetState extends State { return SizedBox(); } - Widget _wrapTextInBubble({ - BuildContext context, - Widget child, - }) { - return Container( - color: _getBackgroundColor(), - child: child, - ); - } - Widget _buildTextBubble(BuildContext context) { final isOnlyEmoji = widget.message.text.characters.every((c) => Emoji.byChar(c) != null); @@ -871,13 +866,6 @@ class _MessageWidgetState extends State { ], ), ); - - if (!isOnlyEmoji) { - child = _wrapTextInBubble( - context: context, - child: child, - ); - } return GestureDetector( onTap: () => retryMessage(context), onLongPress: () => onLongPress(context), @@ -886,6 +874,9 @@ class _MessageWidgetState extends State { } Color _getBackgroundColor() { + final isOnlyEmoji = + widget.message.text.characters.every((c) => Emoji.byChar(c) != null); + if ((widget.message.status == MessageSendingStatus.FAILED || widget.message.status == MessageSendingStatus.FAILED_UPDATE || widget.message.status == MessageSendingStatus.FAILED_DELETE)) { @@ -898,6 +889,9 @@ class _MessageWidgetState extends State { return Color(0xFFE9F2FF); } + if (isOnlyEmoji) { + return Colors.transparent; + } return widget.messageTheme.messageBackgroundColor; } From 71b494c977af8fa56804f9f5144b7fd9b1441654 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 3 Dec 2020 12:14:35 +0100 Subject: [PATCH 15/16] fix messageinput exception --- lib/src/message_input.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 580a4f17..4e30afe1 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -659,7 +659,7 @@ class MessageInputState extends State { Widget _buildFilePickerSection() { var _attachmentContainsFile = - _attachments.any((element) => element.attachment.type == 'file'); + _attachments.any((element) => element?.attachment?.type == 'file'); Color _getIconColor(int index) { switch (index) { @@ -924,7 +924,7 @@ class MessageInputState extends State { ..file = file ..attachment = Attachment( localUri: file.path != null ? Uri.parse(file.path) : null, - type: medium.type == AssetType.image ? 'image' : 'video', + type: medium?.type == AssetType.image ? 'image' : 'video', ); }); From f052ac96ac3fdec2049464bc6c07c76fbf089e2a Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 3 Dec 2020 12:36:43 +0100 Subject: [PATCH 16/16] fix tests --- lib/src/message_widget.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index 94d9afd3..e5fe146f 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -227,7 +227,8 @@ class _MessageWidgetState extends State { widget.message.text.characters.every((c) => Emoji.byChar(c) != null); final hasFiles = - widget.message.attachments.any((element) => element.type == 'file'); + widget.message.attachments?.any((element) => element.type == 'file') == + true; return Portal( child: Padding(