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, + ); + } }