diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index e4693244..72c754e0 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -730,12 +730,18 @@ class MessageInputState extends State { void _addAttachment(Media medium) async { final mediaFile = await medium.getFile(); + final thumbBytes = await medium.getThumbnail(); final file = PlatformFile( path: mediaFile.path, bytes: mediaFile.readAsBytesSync(), ); + final thumbFile = PlatformFile( + bytes: thumbBytes, + name: '${file.name ?? file.path?.split('/')?.last}_thumbnail.jpeg', + ); + setState(() { _inputEnabled = true; }); @@ -747,6 +753,7 @@ class MessageInputState extends State { final channel = StreamChannel.of(context).channel; final attachment = _SendingAttachment( file: file, + thumbFile: thumbFile, attachment: Attachment( localUri: file.path != null ? Uri.parse(file.path) : null, type: medium.mediaType == MediaType.image ? 'image' : 'video', @@ -758,6 +765,11 @@ class MessageInputState extends State { _attachments.add(attachment); }); + final thumbUrl = await _uploadImage( + thumbFile, + channel, + ); + final url = await _uploadAttachment( file, medium.mediaType == MediaType.image @@ -772,10 +784,12 @@ class MessageInputState extends State { if (fileType == DefaultAttachmentTypes.image) { attachment.attachment = attachment.attachment.copyWith( imageUrl: url, + thumbUrl: thumbUrl, ); } else { attachment.attachment = attachment.attachment.copyWith( assetUrl: url, + thumbUrl: thumbUrl, ); } @@ -1041,7 +1055,7 @@ class MessageInputState extends State { return _attachments.isEmpty ? Container() : LimitedBox( - maxHeight: 76.0, + maxHeight: 104.0, child: ListView( scrollDirection: Axis.horizontal, children: _attachments @@ -1055,8 +1069,8 @@ class MessageInputState extends State { AspectRatio( aspectRatio: 1.0, child: Container( - height: 50, - width: 50, + height: 104, + width: 104, child: _buildAttachment(attachment), ), ), @@ -1138,9 +1152,26 @@ class MessageInputState extends State { ); break; case 'video': - return Container( - child: Icon(Icons.videocam), - color: Colors.black26, + return Stack( + children: [ + Container( + child: attachment.thumbFile != null + ? Image.memory( + attachment.thumbFile.bytes, + fit: BoxFit.cover, + ) + : Icon(Icons.videocam), + color: Colors.black26, + ), + Positioned( + left: 8, + bottom: 10, + child: SvgPicture.asset( + 'svgs/video_call_icon.svg', + package: 'stream_chat_flutter', + ), + ), + ], ); break; default: @@ -1426,7 +1457,9 @@ class MessageInputState extends State { MultipartFile.fromBytes( bytes, filename: filename, - contentType: httpParser.MediaType.parse(lookupMimeType(filename)), + contentType: filename != null + ? httpParser.MediaType.parse(lookupMimeType(filename)) + : null, ), ); return res.file; @@ -1657,12 +1690,14 @@ class MessageInputState extends State { class _SendingAttachment { PlatformFile file; + PlatformFile thumbFile; Attachment attachment; bool uploaded; String id; _SendingAttachment({ this.file, + this.thumbFile, this.attachment, this.uploaded = false, this.id, diff --git a/lib/src/user_avatar.dart b/lib/src/user_avatar.dart index 86bf7abd..d1dd2e41 100644 --- a/lib/src/user_avatar.dart +++ b/lib/src/user_avatar.dart @@ -38,25 +38,23 @@ class UserAvatar extends StatelessWidget { : null, child: Stack( children: [ - ClipRRect( - borderRadius: borderRadius ?? - streamChatTheme.ownMessageTheme.avatarTheme.borderRadius, - child: Container( - constraints: constraints ?? - streamChatTheme.ownMessageTheme.avatarTheme.constraints, - decoration: BoxDecoration( - color: streamChatTheme.accentColor, - ), - child: hasImage - ? CachedNetworkImage( - imageUrl: user.extraData['image'], - errorWidget: (_, __, ___) { - return streamChatTheme.defaultUserImage(context, user); - }, - fit: BoxFit.cover, - ) - : streamChatTheme.defaultUserImage(context, user), + Container( + constraints: constraints ?? + streamChatTheme.ownMessageTheme.avatarTheme.constraints, + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration( + borderRadius: borderRadius ?? + streamChatTheme.ownMessageTheme.avatarTheme.borderRadius, + color: streamChatTheme.accentColor, ), + child: hasImage + ? CachedNetworkImage( + imageUrl: user.extraData['image'], + errorWidget: (_, __, ___) { + return streamChatTheme.defaultUserImage(context, user); + }, + ) + : streamChatTheme.defaultUserImage(context, user), ), if (showOnlineStatus && user.online == true) Positioned(