Merge branch 'develop' into perf
This commit is contained in:
@@ -159,6 +159,7 @@ class FileAttachment extends AttachmentWidget {
|
||||
shape: _getDefaultShape(context),
|
||||
child: source.when(
|
||||
local: () => VideoThumbnailImage(
|
||||
fit: BoxFit.cover,
|
||||
video: attachment.file!.path!,
|
||||
placeholderBuilder: (_) => const Center(
|
||||
child: SizedBox(
|
||||
@@ -169,6 +170,7 @@ class FileAttachment extends AttachmentWidget {
|
||||
),
|
||||
),
|
||||
network: () => VideoThumbnailImage(
|
||||
fit: BoxFit.cover,
|
||||
video: attachment.assetUrl!,
|
||||
placeholderBuilder: (_) => const Center(
|
||||
child: SizedBox(
|
||||
@@ -212,50 +214,42 @@ class FileAttachment extends AttachmentWidget {
|
||||
final attachmentId = attachment.id;
|
||||
var trailingWidget = trailing;
|
||||
trailingWidget ??= attachment.uploadState.when(
|
||||
preparing: () => Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: _buildButton(
|
||||
icon: StreamSvgIcon.close(color: theme.colorTheme.white),
|
||||
fillColor: theme.colorTheme.overlayDark,
|
||||
onPressed: () => channel.cancelAttachmentUpload(attachmentId),
|
||||
),
|
||||
preparing: () => Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: _buildButton(
|
||||
icon: StreamSvgIcon.close(color: theme.colorTheme.white),
|
||||
fillColor: theme.colorTheme.overlayDark,
|
||||
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) {
|
||||
trailingWidget = IconButton(
|
||||
@@ -281,25 +275,17 @@ class FileAttachment extends AttachmentWidget {
|
||||
color: theme.colorTheme.grey,
|
||||
);
|
||||
return attachment.uploadState.when(
|
||||
preparing: () => UploadProgressIndicator(
|
||||
uploaded: 0,
|
||||
total: double.maxFinite.toInt(),
|
||||
showBackground: false,
|
||||
padding: EdgeInsets.zero,
|
||||
textStyle: textStyle,
|
||||
progressIndicatorColor: theme.colorTheme.accentBlue,
|
||||
),
|
||||
inProgress: (sent, total) => UploadProgressIndicator(
|
||||
uploaded: sent,
|
||||
total: total,
|
||||
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);
|
||||
preparing: () => Text(fileSize(size), style: textStyle),
|
||||
inProgress: (sent, total) => UploadProgressIndicator(
|
||||
uploaded: sent,
|
||||
total: total,
|
||||
showBackground: false,
|
||||
padding: EdgeInsets.zero,
|
||||
textStyle: textStyle,
|
||||
progressIndicatorColor: theme.colorTheme.accentBlue,
|
||||
),
|
||||
success: () => Text(fileSize(size), style: textStyle),
|
||||
failed: (_) => Text('UPLOAD ERROR', style: textStyle),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ class _ImageFooterState extends State<ImageFooter> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final showShareButton = !kIsWeb;
|
||||
const showShareButton = !kIsWeb;
|
||||
final mediaQueryData = MediaQuery.of(context);
|
||||
final chatThemeData = StreamChatTheme.of(context);
|
||||
return SizedBox.fromSize(
|
||||
|
||||
@@ -76,7 +76,7 @@ enum SendButtonLocation {
|
||||
|
||||
const _kMinMediaPickerSize = 360.0;
|
||||
|
||||
const _kMaxAttachmentSize = 20971520; // 20MB in Bytes
|
||||
const _kDefaultMaxAttachmentSize = 20971520; // 20MB in Bytes
|
||||
|
||||
/// Inactive state
|
||||
/// 
|
||||
@@ -148,11 +148,17 @@ class MessageInput extends StatefulWidget {
|
||||
this.activeSendButton,
|
||||
this.showCommandsButton = true,
|
||||
this.mentionsTileBuilder,
|
||||
this.maxAttachmentSize = _kDefaultMaxAttachmentSize,
|
||||
}) : super(key: key);
|
||||
|
||||
/// Message to edit
|
||||
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
|
||||
final Message? initialMessage;
|
||||
|
||||
@@ -1108,12 +1114,12 @@ class MessageInputState extends State<MessageInput> {
|
||||
bytes: mediaFile.readAsBytesSync(),
|
||||
);
|
||||
|
||||
if (file.size! > _kMaxAttachmentSize) {
|
||||
if (medium.type == AssetType.video) {
|
||||
final mediaInfo = await (VideoService.compressVideo(file.path)
|
||||
if (file.size! > widget.maxAttachmentSize) {
|
||||
if (medium.type == AssetType.video && file.path != null) {
|
||||
final mediaInfo = await (VideoService.compressVideo(file.path!)
|
||||
as FutureOr<MediaInfo>);
|
||||
|
||||
if (mediaInfo.filesize! > _kMaxAttachmentSize) {
|
||||
if (mediaInfo.filesize! > widget.maxAttachmentSize) {
|
||||
_showErrorAlert(
|
||||
// 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.',
|
||||
@@ -1473,16 +1479,12 @@ class MessageInputState extends State<MessageInput> {
|
||||
final containsUrl = widget.quotedMessage!.attachments
|
||||
.any((element) => element.ogScrapeUrl != null) ==
|
||||
true;
|
||||
return Transform(
|
||||
transform: Matrix4.rotationY(pi),
|
||||
alignment: Alignment.center,
|
||||
child: QuotedMessageWidget(
|
||||
reverse: true,
|
||||
showBorder: !containsUrl,
|
||||
message: widget.quotedMessage!,
|
||||
messageTheme: StreamChatTheme.of(context).otherMessageTheme,
|
||||
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0),
|
||||
),
|
||||
return QuotedMessageWidget(
|
||||
reverse: true,
|
||||
showBorder: !containsUrl,
|
||||
message: widget.quotedMessage!,
|
||||
messageTheme: StreamChatTheme.of(context).otherMessageTheme,
|
||||
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1509,7 +1511,9 @@ class MessageInputState extends State<MessageInput> {
|
||||
(e) => ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: FileAttachment(
|
||||
message: Message(), // dummy message
|
||||
message: Message(
|
||||
status: MessageSendingStatus.sending,
|
||||
), // dummy message
|
||||
attachment: e,
|
||||
size: Size(
|
||||
MediaQuery.of(context).size.width * 0.65,
|
||||
@@ -1897,15 +1901,16 @@ class MessageInputState extends State<MessageInput> {
|
||||
final attachment = Attachment(
|
||||
file: file,
|
||||
type: attachmentType,
|
||||
uploadState: const UploadState.preparing(),
|
||||
extraData: extraDataMap,
|
||||
);
|
||||
|
||||
if (file.size! > _kMaxAttachmentSize) {
|
||||
if (attachmentType == 'Video') {
|
||||
final mediaInfo = await (VideoService.compressVideo(file.path)
|
||||
if (file.size! > widget.maxAttachmentSize) {
|
||||
if (attachmentType == 'video' && file.path != null) {
|
||||
final mediaInfo = await (VideoService.compressVideo(file.path!)
|
||||
as FutureOr<MediaInfo>);
|
||||
|
||||
if (mediaInfo.filesize! > _kMaxAttachmentSize) {
|
||||
if (mediaInfo.filesize! > widget.maxAttachmentSize) {
|
||||
_showErrorAlert(
|
||||
// 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.',
|
||||
|
||||
@@ -815,11 +815,13 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
padding: const EdgeInsets.all(8),
|
||||
showSendingIndicator: false,
|
||||
onThreadTap: _onThreadTap,
|
||||
borderRadiusGeometry: const BorderRadius.only(
|
||||
topLeft: Radius.circular(16),
|
||||
bottomLeft: Radius.circular(2),
|
||||
topRight: Radius.circular(16),
|
||||
bottomRight: Radius.circular(16),
|
||||
borderRadiusGeometry: BorderRadius.only(
|
||||
topLeft: const Radius.circular(16),
|
||||
bottomLeft:
|
||||
isMyMessage ? const Radius.circular(16) : const Radius.circular(2),
|
||||
topRight: const Radius.circular(16),
|
||||
bottomRight:
|
||||
isMyMessage ? const Radius.circular(2) : const Radius.circular(16),
|
||||
),
|
||||
textPadding: EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
|
||||
@@ -102,21 +102,24 @@ class QuotedMessageWidget extends StatelessWidget {
|
||||
bool get _containsText => message.text?.isNotEmpty == true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Padding(
|
||||
padding: padding,
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Flexible(child: _buildMessage(context)),
|
||||
const SizedBox(width: 8),
|
||||
if (message.user != null) _buildUserAvatar(),
|
||||
],
|
||||
),
|
||||
Widget build(BuildContext context) {
|
||||
final children = [
|
||||
Flexible(child: _buildMessage(context)),
|
||||
const SizedBox(width: 8),
|
||||
if (message.user != null) _buildUserAvatar(),
|
||||
];
|
||||
return Padding(
|
||||
padding: padding,
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: reverse ? children.reversed.toList() : children,
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMessage(BuildContext context) {
|
||||
final isOnlyEmoji = message.text!.isOnlyEmoji;
|
||||
@@ -154,10 +157,11 @@ class QuotedMessageWidget extends StatelessWidget {
|
||||
color: StreamChatTheme.of(context).colorTheme.greyGainsboro,
|
||||
)
|
||||
: null,
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(12),
|
||||
topLeft: Radius.circular(12),
|
||||
bottomLeft: Radius.circular(12),
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: const Radius.circular(12),
|
||||
topLeft: const Radius.circular(12),
|
||||
bottomRight: reverse ? const Radius.circular(12) : Radius.zero,
|
||||
bottomLeft: reverse ? Radius.zero : const Radius.circular(12),
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.all(8),
|
||||
|
||||
@@ -28,9 +28,9 @@ class IVideoService {
|
||||
/// );
|
||||
/// debugPrint(info.toJson());
|
||||
/// ```
|
||||
Future<MediaInfo?> compressVideo(String? path) async => _lock.synchronized(
|
||||
Future<MediaInfo?> compressVideo(String path) async => _lock.synchronized(
|
||||
() => VideoCompress.compressVideo(
|
||||
path!,
|
||||
path,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user