Merge pull request #446 from GetStream/feat/maxAttachmentSize

feat: max attachment size
This commit is contained in:
Salvatore Giordano
2021-05-21 10:23:29 +02:00
committed by GitHub
4 changed files with 71 additions and 76 deletions
@@ -159,6 +159,7 @@ class FileAttachment extends AttachmentWidget {
shape: _getDefaultShape(context), shape: _getDefaultShape(context),
child: source.when( child: source.when(
local: () => VideoThumbnailImage( local: () => VideoThumbnailImage(
fit: BoxFit.cover,
video: attachment.file!.path!, video: attachment.file!.path!,
placeholderBuilder: (_) => const Center( placeholderBuilder: (_) => const Center(
child: SizedBox( child: SizedBox(
@@ -169,6 +170,7 @@ class FileAttachment extends AttachmentWidget {
), ),
), ),
network: () => VideoThumbnailImage( network: () => VideoThumbnailImage(
fit: BoxFit.cover,
video: attachment.assetUrl!, video: attachment.assetUrl!,
placeholderBuilder: (_) => const Center( placeholderBuilder: (_) => const Center(
child: SizedBox( child: SizedBox(
@@ -212,50 +214,42 @@ class FileAttachment extends AttachmentWidget {
final attachmentId = attachment.id; final attachmentId = attachment.id;
var trailingWidget = trailing; var trailingWidget = trailing;
trailingWidget ??= attachment.uploadState.when( trailingWidget ??= attachment.uploadState.when(
preparing: () => Padding( preparing: () => Padding(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
child: _buildButton( child: _buildButton(
icon: StreamSvgIcon.close(color: theme.colorTheme.white), icon: StreamSvgIcon.close(color: theme.colorTheme.white),
fillColor: theme.colorTheme.overlayDark, fillColor: theme.colorTheme.overlayDark,
onPressed: () => channel.cancelAttachmentUpload(attachmentId), onPressed: () => channel.cancelAttachmentUpload(attachmentId),
), ),
),
inProgress: (_, __) => Padding(
padding: const EdgeInsets.all(8),
child: _buildButton(
icon: StreamSvgIcon.close(color: theme.colorTheme.white),
fillColor: theme.colorTheme.overlayDark,
onPressed: () => channel.cancelAttachmentUpload(attachmentId),
),
),
success: () => Padding(
padding: const EdgeInsets.all(8),
child: CircleAvatar(
backgroundColor: theme.colorTheme.accentBlue,
maxRadius: 12,
child: StreamSvgIcon.check(color: theme.colorTheme.white),
),
),
failed: (_) => Padding(
padding: const EdgeInsets.all(8),
child: _buildButton(
icon: StreamSvgIcon.retry(color: theme.colorTheme.white),
fillColor: theme.colorTheme.overlayDark,
onPressed: () => channel.retryAttachmentUpload(
message.id,
attachmentId,
), ),
inProgress: (_, __) => Padding( ),
padding: const EdgeInsets.all(8), ),
child: _buildButton( );
icon: StreamSvgIcon.close(color: theme.colorTheme.white),
fillColor: theme.colorTheme.overlayDark,
onPressed: () => channel.cancelAttachmentUpload(attachmentId),
),
),
success: () => Padding(
padding: const EdgeInsets.all(8),
child: CircleAvatar(
backgroundColor: theme.colorTheme.accentBlue,
maxRadius: 12,
child: StreamSvgIcon.check(color: theme.colorTheme.white),
),
),
failed: (_) => Padding(
padding: const EdgeInsets.all(8),
child: _buildButton(
icon: StreamSvgIcon.retry(color: theme.colorTheme.white),
fillColor: theme.colorTheme.overlayDark,
onPressed: () => channel.retryAttachmentUpload(
message.id,
attachmentId,
),
),
),
) ??
IconButton(
icon: StreamSvgIcon.cloudDownload(color: theme.colorTheme.black),
visualDensity: VisualDensity.compact,
splashRadius: 16,
onPressed: () {
launchURL(context, attachment.assetUrl);
},
);
if (message.status == MessageSendingStatus.sent) { if (message.status == MessageSendingStatus.sent) {
trailingWidget = IconButton( trailingWidget = IconButton(
@@ -281,25 +275,17 @@ class FileAttachment extends AttachmentWidget {
color: theme.colorTheme.grey, color: theme.colorTheme.grey,
); );
return attachment.uploadState.when( return attachment.uploadState.when(
preparing: () => UploadProgressIndicator( preparing: () => Text(fileSize(size), style: textStyle),
uploaded: 0, inProgress: (sent, total) => UploadProgressIndicator(
total: double.maxFinite.toInt(), uploaded: sent,
showBackground: false, total: total,
padding: EdgeInsets.zero, showBackground: false,
textStyle: textStyle, padding: EdgeInsets.zero,
progressIndicatorColor: theme.colorTheme.accentBlue, textStyle: textStyle,
), progressIndicatorColor: theme.colorTheme.accentBlue,
inProgress: (sent, total) => UploadProgressIndicator( ),
uploaded: sent, success: () => Text(fileSize(size), style: textStyle),
total: total, failed: (_) => Text('UPLOAD ERROR', style: textStyle),
showBackground: false, );
padding: EdgeInsets.zero,
textStyle: textStyle,
progressIndicatorColor: theme.colorTheme.accentBlue,
),
success: () => Text(fileSize(size), style: textStyle),
failed: (_) => Text('UPLOAD ERROR', style: textStyle),
) ??
Text(fileSize(size), style: textStyle);
} }
} }
@@ -76,7 +76,7 @@ class _ImageFooterState extends State<ImageFooter> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final showShareButton = !kIsWeb; const showShareButton = !kIsWeb;
final mediaQueryData = MediaQuery.of(context); final mediaQueryData = MediaQuery.of(context);
final chatThemeData = StreamChatTheme.of(context); final chatThemeData = StreamChatTheme.of(context);
return SizedBox.fromSize( return SizedBox.fromSize(
@@ -76,7 +76,7 @@ enum SendButtonLocation {
const _kMinMediaPickerSize = 360.0; const _kMinMediaPickerSize = 360.0;
const _kMaxAttachmentSize = 20971520; // 20MB in Bytes const _kDefaultMaxAttachmentSize = 20971520; // 20MB in Bytes
/// Inactive state /// Inactive state
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_input.png) /// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_input.png)
@@ -148,11 +148,17 @@ class MessageInput extends StatefulWidget {
this.activeSendButton, this.activeSendButton,
this.showCommandsButton = true, this.showCommandsButton = true,
this.mentionsTileBuilder, this.mentionsTileBuilder,
this.maxAttachmentSize = _kDefaultMaxAttachmentSize,
}) : super(key: key); }) : super(key: key);
/// Message to edit /// Message to edit
final Message? editMessage; final Message? editMessage;
/// Max attachment size in bytes
/// Defaults to 20 MB
/// do not set it if you're using our default CDN
final int maxAttachmentSize;
/// Message to start with /// Message to start with
final Message? initialMessage; final Message? initialMessage;
@@ -1108,12 +1114,12 @@ class MessageInputState extends State<MessageInput> {
bytes: mediaFile.readAsBytesSync(), bytes: mediaFile.readAsBytesSync(),
); );
if (file.size! > _kMaxAttachmentSize) { if (file.size! > widget.maxAttachmentSize) {
if (medium.type == AssetType.video) { if (medium.type == AssetType.video && file.path != null) {
final mediaInfo = await (VideoService.compressVideo(file.path) final mediaInfo = await (VideoService.compressVideo(file.path!)
as FutureOr<MediaInfo>); as FutureOr<MediaInfo>);
if (mediaInfo.filesize! > _kMaxAttachmentSize) { if (mediaInfo.filesize! > widget.maxAttachmentSize) {
_showErrorAlert( _showErrorAlert(
// ignore: lines_longer_than_80_chars // ignore: lines_longer_than_80_chars
'The file is too large to upload. The file size limit is 20MB. We tried compressing it, but it was not enough.', 'The file is too large to upload. The file size limit is 20MB. We tried compressing it, but it was not enough.',
@@ -1505,7 +1511,9 @@ class MessageInputState extends State<MessageInput> {
(e) => ClipRRect( (e) => ClipRRect(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
child: FileAttachment( child: FileAttachment(
message: Message(), // dummy message message: Message(
status: MessageSendingStatus.sending,
), // dummy message
attachment: e, attachment: e,
size: Size( size: Size(
MediaQuery.of(context).size.width * 0.65, MediaQuery.of(context).size.width * 0.65,
@@ -1893,15 +1901,16 @@ class MessageInputState extends State<MessageInput> {
final attachment = Attachment( final attachment = Attachment(
file: file, file: file,
type: attachmentType, type: attachmentType,
uploadState: const UploadState.preparing(),
extraData: extraDataMap, extraData: extraDataMap,
); );
if (file.size! > _kMaxAttachmentSize) { if (file.size! > widget.maxAttachmentSize) {
if (attachmentType == 'Video') { if (attachmentType == 'video' && file.path != null) {
final mediaInfo = await (VideoService.compressVideo(file.path) final mediaInfo = await (VideoService.compressVideo(file.path!)
as FutureOr<MediaInfo>); as FutureOr<MediaInfo>);
if (mediaInfo.filesize! > _kMaxAttachmentSize) { if (mediaInfo.filesize! > widget.maxAttachmentSize) {
_showErrorAlert( _showErrorAlert(
// ignore: lines_longer_than_80_chars // ignore: lines_longer_than_80_chars
'The file is too large to upload. The file size limit is 20MB. We tried compressing it, but it was not enough.', 'The file is too large to upload. The file size limit is 20MB. We tried compressing it, but it was not enough.',
@@ -28,9 +28,9 @@ class IVideoService {
/// ); /// );
/// debugPrint(info.toJson()); /// debugPrint(info.toJson());
/// ``` /// ```
Future<MediaInfo?> compressVideo(String? path) async => _lock.synchronized( Future<MediaInfo?> compressVideo(String path) async => _lock.synchronized(
() => VideoCompress.compressVideo( () => VideoCompress.compressVideo(
path!, path,
), ),
); );