add file upload

This commit is contained in:
Salvatore Giordano
2020-02-28 17:02:10 +01:00
parent 1fea1fd19b
commit b6f0b6f2c1
4 changed files with 144 additions and 29 deletions
+4
View File
@@ -48,6 +48,10 @@
</array> </array>
<key>NSAppleMusicUsageDescription</key> <key>NSAppleMusicUsageDescription</key>
<string>Used to send message attachments</string> <string>Used to send message attachments</string>
<key>NSCameraUsageDescription</key>
<string>Used to send message attachments</string>
<key>NSMicrophoneUsageDescription</key>
<string>Used to send message attachments</string>
<key>NSPhotoLibraryUsageDescription</key> <key>NSPhotoLibraryUsageDescription</key>
<string>Used to send message attachments</string> <string>Used to send message attachments</string>
</dict> </dict>
+136 -25
View File
@@ -3,6 +3,7 @@ import 'dart:io';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.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_chat_theme.dart';
@@ -136,7 +137,7 @@ class _MessageInputState extends State<MessageInput> {
Container( Container(
height: 50, height: 50,
width: 50, width: 50,
child: Image.file(attachment.file), child: _buildAttachment(attachment),
), ),
Positioned( Positioned(
height: 16, height: 16,
@@ -176,6 +177,25 @@ class _MessageInputState extends State<MessageInput> {
); );
} }
Widget _buildAttachment(_SendingAttachment attachment) {
switch (attachment.type) {
case FileType.IMAGE:
return Image.file(attachment.file);
break;
case FileType.VIDEO:
return Container(
child: Icon(Icons.videocam),
color: Colors.black26,
);
break;
default:
return Container(
child: Icon(Icons.insert_drive_file),
color: Colors.black26,
);
}
}
Material _buildAttachmentButton() { Material _buildAttachmentButton() {
return Material( return Material(
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
@@ -184,25 +204,72 @@ class _MessageInputState extends State<MessageInput> {
), ),
color: Colors.transparent, color: Colors.transparent,
child: IconButton( child: IconButton(
onPressed: () async { onPressed: () {
final file = await FilePicker.getFile(type: FileType.IMAGE); showModalBottomSheet(
print(file.path); clipBehavior: Clip.hardEdge,
shape: RoundedRectangleBorder(
final channel = StreamChannel.of(context).channel; borderRadius: BorderRadius.only(
topLeft: Radius.circular(32),
final bytes = await file.readAsBytes(); topRight: Radius.circular(32),
final res = await channel.sendFile(MultipartFile.fromBytes( ),
bytes, ),
filename: file.path.split('/').last, context: context,
)); builder: (_) {
return Column(
setState(() { mainAxisSize: MainAxisSize.min,
_attachments.add(_SendingAttachment( children: <Widget>[
url: res.file, ListTile(
extension: file.path.split('.').last, title: Text(
file: file, 'Add a file',
)); style: TextStyle(
}); fontWeight: FontWeight.bold,
),
),
),
ListTile(
leading: Icon(Icons.image),
title: Text('Upload a photo'),
onTap: () {
_pickFile(FileType.IMAGE, false);
Navigator.pop(context);
},
),
ListTile(
leading: Icon(Icons.video_library),
title: Text('Upload a video'),
onTap: () {
_pickFile(FileType.VIDEO, false);
Navigator.pop(context);
},
),
ListTile(
leading: Icon(Icons.camera_alt),
title: Text('Photo from camera'),
onTap: () {
ImagePicker.pickImage(source: ImageSource.camera);
_pickFile(FileType.IMAGE, true);
Navigator.pop(context);
},
),
ListTile(
leading: Icon(Icons.videocam),
title: Text('Video from camera'),
onTap: () {
_pickFile(FileType.VIDEO, true);
Navigator.pop(context);
},
),
ListTile(
leading: Icon(Icons.insert_drive_file),
title: Text('Upload a file'),
onTap: () {
_pickFile(FileType.ANY, false);
Navigator.pop(context);
},
),
],
);
});
}, },
icon: Icon( icon: Icon(
Icons.add_circle_outline, Icons.add_circle_outline,
@@ -211,6 +278,38 @@ class _MessageInputState extends State<MessageInput> {
); );
} }
void _pickFile(FileType type, bool camera) async {
File file;
if (camera) {
if (type == FileType.IMAGE) {
file = await ImagePicker.pickImage(source: ImageSource.camera);
} else if (type == FileType.VIDEO) {
file = await ImagePicker.pickVideo(source: ImageSource.camera);
}
} else {
file = await FilePicker.getFile(type: type);
}
final channel = StreamChannel.of(context).channel;
final bytes = await file.readAsBytes();
final res = await channel.sendFile(
MultipartFile.fromBytes(
bytes,
filename: file.path.split('/').last,
),
);
setState(() {
_attachments.add(_SendingAttachment(
url: res.file,
file: file,
type: type,
));
});
}
Widget _buildSendButton(BuildContext context) { Widget _buildSendButton(BuildContext context) {
return IconTheme( return IconTheme(
data: data:
@@ -239,7 +338,7 @@ class _MessageInputState extends State<MessageInput> {
return; return;
} }
final attachments = List.from(_attachments); final attachments = List<_SendingAttachment>.from(_attachments);
_textController.clear(); _textController.clear();
_attachments.clear(); _attachments.clear();
@@ -257,10 +356,22 @@ class _MessageInputState extends State<MessageInput> {
parentId: widget.parentMessage?.id, parentId: widget.parentMessage?.id,
text: text, text: text,
attachments: attachments.map((attachment) { attachments: attachments.map((attachment) {
String type;
switch (attachment.type) {
case FileType.IMAGE:
type = 'image';
break;
case FileType.VIDEO:
type = 'video';
break;
default:
type = 'file';
}
return Attachment( return Attachment(
imageUrl: attachment.url, imageUrl:
attachment.type == FileType.IMAGE ? attachment.url : null,
assetUrl: attachment.url, assetUrl: attachment.url,
type: 'image', type: type,
); );
}).toList(), }).toList(),
), ),
@@ -275,12 +386,12 @@ class _MessageInputState extends State<MessageInput> {
class _SendingAttachment { class _SendingAttachment {
final String url; final String url;
final String extension;
final File file; final File file;
final FileType type;
_SendingAttachment({ _SendingAttachment({
this.url, this.url,
this.extension,
this.file, this.file,
this.type,
}); });
} }
+2 -2
View File
@@ -211,7 +211,7 @@ class _MessageWidgetState extends State<MessageWidget>
borderRadius: boxDecoration.borderRadius, borderRadius: boxDecoration.borderRadius,
child: Container( child: Container(
decoration: boxDecoration, decoration: boxDecoration,
constraints: BoxConstraints.loose(Size(300, 500)), constraints: BoxConstraints.loose(Size.fromWidth(300)),
child: Stack( child: Stack(
children: <Widget>[ children: <Widget>[
Column( Column(
@@ -256,7 +256,7 @@ class _MessageWidgetState extends State<MessageWidget>
), ),
color: Color(0xffebebeb), color: Color(0xffebebeb),
) )
: Container(), : SizedBox(),
], ],
), ),
attachment.type == 'image' && attachment.titleLink != null attachment.type == 'image' && attachment.titleLink != null
+2 -2
View File
@@ -19,8 +19,8 @@ dependencies:
video_player: ^0.10.7 video_player: ^0.10.7
chewie: ^0.9.8+1 chewie: ^0.9.8+1
file_picker: ^1.4.3+2 file_picker: ^1.4.3+2
stream_chat: image_picker: ^0.6.3+4
path: ../stream_chat_dart stream_chat: ^0.1.12
dev_dependencies: dev_dependencies:
pedantic: ^1.8.0+1 pedantic: ^1.8.0+1