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:flutter/material.dart';
|
||||||
import 'package:stream_chat/stream_chat.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/stream_svg_icon.dart';
|
||||||
import 'package:stream_chat_flutter/src/utils.dart';
|
import 'package:stream_chat_flutter/src/utils.dart';
|
||||||
|
import 'media_utils.dart';
|
||||||
|
|
||||||
|
enum FileAttachmentType { local, online }
|
||||||
|
|
||||||
class FileAttachment extends StatelessWidget {
|
class FileAttachment extends StatelessWidget {
|
||||||
final Attachment attachment;
|
final Attachment attachment;
|
||||||
final Size size;
|
final Size size;
|
||||||
final Widget trailing;
|
final Widget trailing;
|
||||||
|
final FileAttachmentType attachmentType;
|
||||||
|
final PlatformFile file;
|
||||||
|
|
||||||
const FileAttachment({
|
const FileAttachment({
|
||||||
Key key,
|
Key key,
|
||||||
@required this.attachment,
|
@required this.attachment,
|
||||||
this.size,
|
this.size,
|
||||||
this.trailing,
|
this.trailing,
|
||||||
|
this.attachmentType = FileAttachmentType.online,
|
||||||
|
this.file,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -32,7 +42,7 @@ class FileAttachment extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
child: _getFileTypeImage(attachment.extraData['mime_type']),
|
child: _getFileTypeImage(),
|
||||||
height: 40.0,
|
height: 40.0,
|
||||||
width: 33.33,
|
width: 33.33,
|
||||||
margin: EdgeInsets.all(8.0),
|
margin: EdgeInsets.all(8.0),
|
||||||
@@ -117,8 +127,38 @@ class FileAttachment extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamSvgIcon _getFileTypeImage(String type) {
|
Widget _getFileTypeImage() {
|
||||||
switch (type) {
|
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':
|
case '7z':
|
||||||
return StreamSvgIcon.filetype_7z();
|
return StreamSvgIcon.filetype_7z();
|
||||||
break;
|
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) {
|
Color _getIconColor(int index) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
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;
|
break;
|
||||||
case 1:
|
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;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
return _attachmentContainsFile && _attachments.isNotEmpty
|
return _attachmentContainsFile && _attachments.isNotEmpty
|
||||||
@@ -1268,6 +1276,8 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
child: FileAttachment(
|
child: FileAttachment(
|
||||||
attachment: e.attachment,
|
attachment: e.attachment,
|
||||||
|
attachmentType: FileAttachmentType.local,
|
||||||
|
file: e.file,
|
||||||
size: Size(
|
size: Size(
|
||||||
MediaQuery.of(context).size.width * 0.55,
|
MediaQuery.of(context).size.width * 0.55,
|
||||||
MediaQuery.of(context).size.height * 0.3,
|
MediaQuery.of(context).size.height * 0.3,
|
||||||
@@ -1676,12 +1686,16 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
|
|
||||||
final mimeType = _getMimeType(file.path.split('/').last);
|
final mimeType = _getMimeType(file.path.split('/').last);
|
||||||
|
|
||||||
if (mimeType.type == 'video' || mimeType.type == 'image') {
|
|
||||||
attachmentType = mimeType.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, dynamic> extraDataMap = {};
|
Map<String, dynamic> extraDataMap = {};
|
||||||
|
|
||||||
|
if (camera) {
|
||||||
|
if (mimeType.type == 'video' || mimeType.type == 'image') {
|
||||||
|
attachmentType = mimeType.type;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
attachmentType = 'file';
|
||||||
|
}
|
||||||
|
|
||||||
if (mimeType?.subtype != null) {
|
if (mimeType?.subtype != null) {
|
||||||
extraDataMap['mime_type'] = mimeType.subtype.toLowerCase();
|
extraDataMap['mime_type'] = mimeType.subtype.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user