feat: Added file previews
This commit is contained in:
@@ -1,18 +1,28 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
||||
import 'package:stream_chat_flutter/src/stream_svg_icon.dart';
|
||||
import 'package:stream_chat_flutter/src/utils.dart';
|
||||
import 'media_utils.dart';
|
||||
|
||||
enum FileAttachmentType { local, online }
|
||||
|
||||
class FileAttachment extends StatelessWidget {
|
||||
final Attachment attachment;
|
||||
final Size size;
|
||||
final Widget trailing;
|
||||
final FileAttachmentType attachmentType;
|
||||
final PlatformFile file;
|
||||
|
||||
const FileAttachment({
|
||||
Key key,
|
||||
@required this.attachment,
|
||||
this.size,
|
||||
this.trailing,
|
||||
this.attachmentType = FileAttachmentType.online,
|
||||
this.file,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -32,7 +42,7 @@ class FileAttachment extends StatelessWidget {
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
child: _getFileTypeImage(attachment.extraData['mime_type']),
|
||||
child: _getFileTypeImage(),
|
||||
height: 40.0,
|
||||
width: 33.33,
|
||||
margin: EdgeInsets.all(8.0),
|
||||
@@ -117,8 +127,38 @@ class FileAttachment extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
StreamSvgIcon _getFileTypeImage(String type) {
|
||||
switch (type) {
|
||||
Widget _getFileTypeImage() {
|
||||
if ((MediaUtils.getMimeType(attachment.title).type == 'image')) {
|
||||
switch (attachmentType) {
|
||||
case FileAttachmentType.local:
|
||||
return Image.memory(
|
||||
file.bytes,
|
||||
fit: BoxFit.cover,
|
||||
);
|
||||
break;
|
||||
case FileAttachmentType.online:
|
||||
return CachedNetworkImage(
|
||||
imageUrl: attachment.imageUrl ??
|
||||
attachment.assetUrl ??
|
||||
attachment.thumbUrl,
|
||||
fit: BoxFit.cover,
|
||||
progressIndicatorBuilder: (context, _, progress) {
|
||||
return Center(
|
||||
child: Container(
|
||||
width: 20.0,
|
||||
height: 20.0,
|
||||
child: CircularProgressIndicator(
|
||||
backgroundColor: StreamChatTheme.of(context).accentColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (attachment.extraData['mime_type']) {
|
||||
case '7z':
|
||||
return StreamSvgIcon.filetype_7z();
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:http_parser/http_parser.dart' as httpParser;
|
||||
import 'package:mime/mime.dart';
|
||||
|
||||
class MediaUtils {
|
||||
static httpParser.MediaType getMimeType(String filename) {
|
||||
httpParser.MediaType mimeType;
|
||||
if (filename != null) {
|
||||
if (filename.toLowerCase().endsWith('heic')) {
|
||||
mimeType = httpParser.MediaType.parse('image/heic');
|
||||
} else {
|
||||
mimeType = httpParser.MediaType.parse(lookupMimeType(filename));
|
||||
}
|
||||
}
|
||||
|
||||
return mimeType;
|
||||
}
|
||||
}
|
||||
@@ -683,10 +683,18 @@ class MessageInputState extends State<MessageInput> {
|
||||
Color _getIconColor(int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return _attachments.isEmpty ? StreamChatTheme.of(context).accentColor : (!_attachmentContainsFile ? StreamChatTheme.of(context).accentColor : Colors.black.withOpacity(0.2));
|
||||
return _attachments.isEmpty
|
||||
? StreamChatTheme.of(context).accentColor
|
||||
: (!_attachmentContainsFile
|
||||
? StreamChatTheme.of(context).accentColor
|
||||
: Colors.black.withOpacity(0.2));
|
||||
break;
|
||||
case 1:
|
||||
return _attachmentContainsFile ? StreamChatTheme.of(context).accentColor : (_attachments.isEmpty ? Colors.black.withOpacity(0.5) : Colors.black.withOpacity(0.2));
|
||||
return _attachmentContainsFile
|
||||
? StreamChatTheme.of(context).accentColor
|
||||
: (_attachments.isEmpty
|
||||
? Colors.black.withOpacity(0.5)
|
||||
: Colors.black.withOpacity(0.2));
|
||||
break;
|
||||
case 2:
|
||||
return _attachmentContainsFile && _attachments.isNotEmpty
|
||||
@@ -1268,6 +1276,8 @@ class MessageInputState extends State<MessageInput> {
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: FileAttachment(
|
||||
attachment: e.attachment,
|
||||
attachmentType: FileAttachmentType.local,
|
||||
file: e.file,
|
||||
size: Size(
|
||||
MediaQuery.of(context).size.width * 0.55,
|
||||
MediaQuery.of(context).size.height * 0.3,
|
||||
@@ -1676,12 +1686,16 @@ class MessageInputState extends State<MessageInput> {
|
||||
|
||||
final mimeType = _getMimeType(file.path.split('/').last);
|
||||
|
||||
if (mimeType.type == 'video' || mimeType.type == 'image') {
|
||||
attachmentType = mimeType.type;
|
||||
}
|
||||
|
||||
Map<String, dynamic> extraDataMap = {};
|
||||
|
||||
if (camera) {
|
||||
if (mimeType.type == 'video' || mimeType.type == 'image') {
|
||||
attachmentType = mimeType.type;
|
||||
}
|
||||
} else {
|
||||
attachmentType = 'file';
|
||||
}
|
||||
|
||||
if (mimeType?.subtype != null) {
|
||||
extraDataMap['mime_type'] = mimeType.subtype.toLowerCase();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user